### 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: + *

+     * <servlet-mapping>
+     *   <servlet-name>Repository</servlet-name>
+     *   <url-pattern>/repository/*</url-pattern>
+     * </servlet-mapping>
+     * 
+ *

+ * 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. + *

+ * A typical way to use this class would be: + *

+ * public class MyServlet extends HttpServlet {
+ *
+ *     private final Repository repository = new ServletRepository(this);
+ *
+ *     protected void doGet(
+ *             HttpServletRequest request, HttpServletResponse response)
+ *             throws ServletException, IOException {
+ *          try {
+ *              Session session = repository.login();
+ *              try {
+ *                  ...;
+ *              } finally {
+ *                  session.logout();
+ *              }
+ *          } catch (RepositoryException e) {
+ *              throw new ServletException(e);
+ *          }
+ *      }
+ *
+ * }
+ * 
+ *

+ * Starting with version 1.6 this class can also be used by a servlet filter: + *

+ * public class MyFilter implements Filter {
+ *
+ *     private Repository repository;
+ *
+ *     public void init(FilterConfig config) {
+ *         repository = new ServletRepository(config);
+ *     }
+ *
+ *     // ...
+ *
+ * }
+ * 
+ + * + * @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". + *
+ *
org.apache.jackrabbit.rmi.server.RemoteAdapterFactory
+ *
+ * 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". + *
+ *
org.apache.jackrabbit.rmi.client.LocalAdapterFactory
+ *
+ * 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". + *
+ *
org.apache.jackrabbit.rmi.server.RemoteAdapterFactory
+ *
+ * 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". + *
+ *
org.apache.jackrabbit.rmi.client.LocalAdapterFactory
+ *
+ * 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". + *
+ *
org.apache.jackrabbit.rmi.server.RemoteAdapterFactory
+ *
+ * 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". + *
+ *
org.apache.jackrabbit.rmi.client.LocalAdapterFactory
+ *
+ * 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". + *
+ *
org.apache.jackrabbit.rmi.server.RemoteAdapterFactory
+ *
+ * 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". + *
+ *
org.apache.jackrabbit.rmi.client.LocalAdapterFactory
+ *
+ * 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 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: + *

+ *

+ * 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:
+ *

+ */ + public DefaultHandler() { + this(null); + } + + /** + * Creates a new DefaultHandler with default nodetype definitions:
+ * + * + * @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 importProperties(PropertyImportContext importContext, boolean isCollection) throws RepositoryException { + if (!canImport(importContext, isCollection)) { + throw new RepositoryException("PropertyHandler " + getName() + " failed import properties"); + } + + // loop over List and remember all properties and propertyNames + // that failed to be imported (set or remove). + Map failures = new HashMap(); + List changeList = importContext.getChangeList(); + + // for collections the import-root is the target node where properties + // are altered. in contrast 'non-collections' are with the handler + // represented by 'file' nodes, that must have a jcr:content child + // node, which holds all properties except jcr:created. + // -> see canImport for the corresponding assertions + Node cn = (Node) importContext.getImportRoot(); + if (!isCollection && cn.hasNode(JcrConstants.JCR_CONTENT)) { + cn = cn.getNode(JcrConstants.JCR_CONTENT); + } + + if (changeList != null) { + 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 + *

+ */ + 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(""); + writer.print(Text.encodeIllegalHTMLCharacters(repName)); + writer.print(" "); + writer.print(Text.encodeIllegalHTMLCharacters(repVersion)); + writer.print(" "); + writer.print(Text.encodeIllegalHTMLCharacters(item.getPath())); + writer.print(""); + writer.print("

"); + writer.print(Text.encodeIllegalHTMLCharacters(item.getPath())); + 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#exportContent(ExportContext, DavResource) + */ + public boolean exportContent(ExportContext context, DavResource resource) throws IOException { + if (!canExport(context, resource)) { + 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(""); + writer.print(Text.encodeIllegalHTMLCharacters(repName)); + writer.print(" "); + writer.print(Text.encodeIllegalHTMLCharacters(repVersion)); + writer.print(" "); + writer.print(Text.encodeIllegalHTMLCharacters(resource.getResourcePath())); + writer.print(""); + writer.print("

"); + writer.print(Text.encodeIllegalHTMLCharacters(resource.getResourcePath())); + 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 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 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 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 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 alterProperties(PropertyImportContext context, boolean isCollection) throws RepositoryException { + Map 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 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 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 referenceToSessionMap; + + /** + * Create a new session cache with the {@link #CONCURRENCY_LEVEL_DEFAULT default concurrency level}. + */ + private SessionCache() { + this(CONCURRENCY_LEVEL_DEFAULT); + } + + /** + * Create a new session cache with the specified the level of concurrency + * for this server. + * + * @param cacheConcurrencyLevel A positive int value specifying the + * concurrency level of the server. + */ + private SessionCache(int cacheConcurrencyLevel) { + sessionMap = new ConcurrentHashMap>(INITIAL_CAPACITY, .75f, cacheConcurrencyLevel); + referenceToSessionMap = new ConcurrentHashMap(INITIAL_CAPACITY_REF_TO_SESSION, .75f, cacheConcurrencyLevel); + } + + /** + * Try to retrieve DavSession if a TransactionId or + * SubscriptionId is present in the request header. If no cached session + * was found null is returned. + * + * @param request + * @return a cached DavSession or null. + * @throws DavException + */ + private DavSession get(WebdavRequest request) + throws DavException { + String txId = request.getTransactionId(); + String subscriptionId = request.getSubscriptionId(); + String lockToken = request.getLockToken(); + + DavSession session = null; + // try to retrieve a cached session + if (lockToken != null && containsReference(lockToken)) { + session = getSessionByReference(lockToken); + } else if (txId != null && containsReference(txId)) { + session = getSessionByReference(txId); + } else if (subscriptionId != null && containsReference(subscriptionId)) { + session = getSessionByReference(subscriptionId); + } + + if (session == null) { + // try tokens present in the if-header + IfHeader ifHeader = new IfHeader(request); + for (Iterator it = ifHeader.getAllTokens(); it.hasNext();) { + String token = it.next(); + if (containsReference(token)) { + session = getSessionByReference(token); + break; + } + } + } + + // no cached session present -> create new one. + if (session == null) { + Session repSession = getRepositorySession(request); + session = new DavSessionImpl(repSession); + + // TODO: review again if using ConcurrentMap#putIfAbsent() was more appropriate. + sessionMap.put(session, new HashSet()); + log.debug("login: User '" + repSession.getUserID() + "' logged in."); + } else { + log.debug("login: Retrieved cached session for user '" + getUserID(session) + "'"); + } + addReference(session, request); + return session; + } + + /** + * Add a references to the specified DavSession. + * + * @param session + * @param reference + */ + private void addReference(DavSession session, Object reference) { + Set referenceSet = sessionMap.get(session); + if (referenceSet != null) { + referenceSet.add(reference); + referenceToSessionMap.put(reference, session); + } else { + log.error("Failed to add reference to session. No entry in cache found."); + } + } + + /** + * Remove the given reference from the specified DavSession. + * + * @param session + * @param reference + */ + private void removeReference(DavSession session, Object reference) { + Set referenceSet = sessionMap.get(session); + if (referenceSet != null) { + if (referenceSet.remove(reference)) { + log.debug("Removed reference " + reference + " to session " + session); + referenceToSessionMap.remove(reference); + } else { + log.warn("Failed to remove reference " + reference + " to session " + session); + } + if (referenceSet.isEmpty()) { + log.debug("No more references present on webdav session -> clean up."); + sessionMap.remove(session); + try { + Session repSession = DavSessionImpl.getRepositorySession(session); + String usr = getUserID(session) ; + sessionProvider.releaseSession(repSession); + log.debug("Login: User '" + usr + "' logged out"); + } catch (DavException e) { + // should not occur, since we originally built a + // DavSessionImpl that wraps a repository session. + log.error("Unexpected error: " + e.getMessage(), e.getCause()); + } + } else { + log.debug(referenceSet.size() + " references remaining on webdav session " + session); + } + } else { + log.error("Failed to remove reference from session. No entry in cache found."); + } + } + + /** + * Returns true, if there exists a DavSession in the cache + * that is referenced by the specified object. + * + * @param reference + * @return true if a DavSession is referenced by the given + * object. + */ + private boolean containsReference(Object reference) { + return referenceToSessionMap.containsKey(reference); + } + + /** + * Returns the DavSession that is referenced by the + * specified reference object. + * + * @param reference + * @return DavSession that is referenced by this reference + * object. + * @see #containsReference(Object) + */ + private DavSession getSessionByReference(Object reference) { + return referenceToSessionMap.get(reference); + } + + /** + * Retrieve the {@link Session} object for the given request. + * + * @param request + * @return JCR session object used to build the DavSession + * @throws DavException + * @throws DavException in case a {@link javax.jcr.LoginException} or {@link javax.jcr.RepositoryException} occurs. + */ + private Session getRepositorySession(WebdavRequest request) throws DavException { + try { + String workspaceName = null; + if (DavMethods.DAV_MKWORKSPACE != DavMethods.getMethodCode(request.getMethod())) { + workspaceName = request.getRequestLocator().getWorkspaceName(); + } + + Session session = sessionProvider.getSession( + request, repository, workspaceName); + + // extract information from Link header fields + LinkHeaderFieldParser lhfp = + new LinkHeaderFieldParser(request.getHeaders("Link")); + setJcrUserData(session, lhfp); + setSessionIdentifier(session, lhfp); + + return session; + } catch (LoginException e) { + // LoginException results in UNAUTHORIZED, + throw new JcrDavException(e); + } catch (RepositoryException e) { + // RepositoryException results in FORBIDDEN + throw new JcrDavException(e); + } catch (ServletException e) { + throw new DavException(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); + } + } + + /** + * Find first link relation for JCR user data and set it as + * the user data of the observation manager of the given session. + */ + private void setJcrUserData( + Session session, LinkHeaderFieldParser lhfp) + throws RepositoryException { + String data = null; + + // extract User Data string from RFC 2397 "data" URI + // only supports the simple case of "data:,..." for now + String target = lhfp.getFirstTargetForRelation( + JcrRemotingConstants.RELATION_USER_DATA); + if (target != null) { + try { + URI uri = new URI(target); + // Poor Man's data: URI parsing + if ("data".equalsIgnoreCase(uri.getScheme())) { + String sspart = uri.getRawSchemeSpecificPart(); + if (sspart.startsWith(",")) { + data = Text.unescape(sspart.substring(1)); + } + } + } catch (URISyntaxException ex) { + // not a URI, skip + } + } + + try { + session.getWorkspace().getObservationManager().setUserData(data); + } catch (UnsupportedRepositoryOperationException ignore) { + } + } + + /** + * Find first link relation for remote session identifier and set + * it as an attribute of the given session. + */ + private void setSessionIdentifier( + Session session, LinkHeaderFieldParser lhfp) { + if (session instanceof SessionExtensions) { + String name = JcrRemotingConstants.RELATION_REMOTE_SESSION_ID; + String id = lhfp.getFirstTargetForRelation(name); + ((SessionExtensions) session).setAttribute(name, id); + } + } + + private String getUserID(DavSession session) { + try { + Session s = DavSessionImpl.getRepositorySession(session); + if (s != null) { + return s.getUserID(); + } + } catch (DavException e) { + log.error(e.toString()); + } + // fallback + return session.toString(); + } + } +} Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/jcr/JCRWebdavServer.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/package-info.java =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/package-info.java (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/package-info.java (working copy) @@ -0,0 +1,18 @@ +/* + * 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. + */ +@org.osgi.annotation.versioning.Version("1.0") +package org.apache.jackrabbit.server; Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/package-info.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/remoting/davex/AclRemoveHandler.java =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/remoting/davex/AclRemoveHandler.java (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/remoting/davex/AclRemoveHandler.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.remoting.davex; + +import javax.jcr.Item; +import javax.jcr.Node; +import javax.jcr.RepositoryException; +import javax.jcr.Session; +import javax.jcr.security.AccessControlManager; +import javax.jcr.security.AccessControlPolicy; + +import org.apache.jackrabbit.util.Text; + +public class AclRemoveHandler implements ProtectedItemRemoveHandler { + + private static final String NT_REP_ACL = "rep:ACL"; + + @Override + public boolean remove(Session session, String itemPath) throws RepositoryException { + if (canHandle(session, itemPath)) { + String controlledPath = Text.getRelativeParent(itemPath, 1); + AccessControlManager acMgr = session.getAccessControlManager(); + AccessControlPolicy[] policies = acMgr.getPolicies(controlledPath); + for (AccessControlPolicy policy : policies) { + acMgr.removePolicy(controlledPath, policy); + } + return true; + } + return false; + } + + // -----------------------------------------------------------< private >--- + private boolean canHandle(Session session, String itemPath) throws RepositoryException { + Item aclItem = session.getItem(itemPath); + if (aclItem.isNode() && itemPath.startsWith("/")) { + if (isJackrabbitAclNodeType((Node) aclItem)) { + return true; + } + } + return false; + } + + private boolean isJackrabbitAclNodeType(Node aclNode) throws RepositoryException { + String ntName = aclNode.getPrimaryNodeType().getName(); + return ntName.equals(NT_REP_ACL); + } +} Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/remoting/davex/AclRemoveHandler.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/remoting/davex/BatchReadConfig.java =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/remoting/davex/BatchReadConfig.java (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/remoting/davex/BatchReadConfig.java (working copy) @@ -0,0 +1,170 @@ +/* + * 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.remoting.davex; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.jcr.Node; +import javax.jcr.RepositoryException; +import java.util.Map; +import java.util.HashMap; +import java.util.Properties; +import java.util.Enumeration; +import java.io.InputStream; +import java.io.IOException; + +/** + * BatchReadConfig defines if and how deep child item + * information should be retrieved, when accessing a Node. + * The configuration is based on node type names. + */ +class BatchReadConfig { + + private static Logger log = LoggerFactory.getLogger(BatchReadConfig.class); + + private static final String NAME_DEFAULT = "default"; + public static final int DEPTH_DEFAULT = 0; + public static final int DEPTH_INFINITE = -1; + + private int defaultDepth = DEPTH_DEFAULT; + private final Map depthMap = new HashMap(); + + /** + * Create an empty batch-read config. + */ + BatchReadConfig() {} + + /** + * Load the batch read configuration. + * + * @param in An input stream. + * @throws IOException If an error occurs. + */ + public void load(InputStream in) throws IOException { + Properties props = new Properties(); + props.load(in); + add(props); + } + + /** + * Add the configuration entries present in the given properties. + * + * @param props + */ + public void add(Properties props) { + for (Enumeration en = props.propertyNames(); en.hasMoreElements();) { + String name = en.nextElement().toString(); + String depthStr = props.getProperty(name); + try { + int depth = Integer.parseInt(depthStr); + if (depth < DEPTH_INFINITE) { + log.warn("invalid depth " + depthStr + " -> ignoring."); + continue; + } + if (NAME_DEFAULT.equals(name)) { + setDefaultDepth(depth); + } else { + setDepth(name, depth); + } + } catch (NumberFormatException e) { + // invalid entry in the properties file -> ignore + log.warn("Invalid depth value for name " + name + ". " + depthStr + " cannot be parsed into an integer."); + } + } + } + + /** + * Return the depth for the given node type name. If the name is + * not defined in this configuration, the {@link #DEPTH_DEFAULT default value} + * is returned. + * + * @param ntName The jcr name of the node type. + * @return {@link #DEPTH_INFINITE -1} If all child infos should be return or + * any value greater than {@link #DEPTH_DEFAULT 0} if only parts of the + * subtree should be returned. If the given nodetype name is not defined + * in this configuration, the default depth {@link #DEPTH_DEFAULT 0} will + * be returned. + */ + public int getDepth(String ntName) { + if (depthMap.containsKey(ntName)) { + return depthMap.get(ntName); + } else { + return defaultDepth; + } + } + + /** + * Return the depth for the given node or the default depth if the config + * does not provide an specific entry for the given node. + * + * @param node The node for with depth information should be retrieved. + * @return {@link #DEPTH_INFINITE -1} If all child infos should be return or + * any value greater than {@link #DEPTH_DEFAULT 0} if only parts of the + * subtree should be returned. + */ + public int getDepth(Node node) { + int depth = defaultDepth; + try { + String ntName = node.getPrimaryNodeType().getName(); + if (depthMap.containsKey(ntName)) { + depth = depthMap.get(ntName); + } + } catch (RepositoryException e) { + // ignore and return default. + } + return depth; + } + + /** + * Define the batch-read depth for the given node type name. + * + * @param ntName jcr name of the node type for which depth is defined. + * @param depth Depth for the specified node type name. + * @throws IllegalArgumentException if ntName is null + * or depth is lower than {@link #DEPTH_INFINITE}. + */ + public void setDepth(String ntName, int depth) { + if (ntName == null || depth < DEPTH_INFINITE) { + throw new IllegalArgumentException(); + } + depthMap.put(ntName, depth); + } + + /** + * Returns the default depth. + * + * @return the default depth. + */ + public int getDefaultDepth() { + return defaultDepth; + } + + /** + * Set the default depth. + * + * @param depth The default depth. + * @throws IllegalArgumentException if depth is lower than + * {@link #DEPTH_INFINITE}. + */ + public void setDefaultDepth(int depth) { + if (depth < -1) { + throw new IllegalArgumentException(); + } + defaultDepth = depth; + } +} Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/remoting/davex/BatchReadConfig.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/remoting/davex/DavexServletService.java =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/remoting/davex/DavexServletService.java (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/remoting/davex/DavexServletService.java (working copy) @@ -0,0 +1,190 @@ +/* + * 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.remoting.davex; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.Set; + +import javax.jcr.LoginException; +import javax.jcr.Repository; +import javax.jcr.RepositoryException; +import javax.jcr.Session; +import javax.servlet.Servlet; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; + +import org.apache.felix.scr.annotations.Activate; +import org.apache.felix.scr.annotations.Component; +import org.apache.felix.scr.annotations.Properties; +import org.apache.felix.scr.annotations.Property; +import org.apache.felix.scr.annotations.Reference; +import org.apache.felix.scr.annotations.ReferenceCardinality; +import org.apache.felix.scr.annotations.ReferencePolicy; +import org.apache.felix.scr.annotations.Service; +import org.apache.jackrabbit.server.SessionProvider; +import org.apache.jackrabbit.webdav.server.AbstractWebdavServlet; +import org.apache.jackrabbit.webdav.util.CSRFUtil; + +@Component(metatype = true, label = "%dav.name", description = "%dav.description") +@Service(Servlet.class) +@Properties({ + @Property(name = "service.description", value = "Apache Jackrabbit JcrRemoting Servlet"), + @Property(name = JcrRemotingServlet.INIT_PARAM_AUTHENTICATE_HEADER, value = AbstractWebdavServlet.DEFAULT_AUTHENTICATE_HEADER), + @Property(name = JcrRemotingServlet.INIT_PARAM_CSRF_PROTECTION, value = CSRFUtil.DISABLED), + @Property(name = JcrRemotingServlet.INIT_PARAM_MISSING_AUTH_MAPPING, value = ""), + @Property(name = "contextId", value = "") }) +@Reference( + name = "providers", referenceInterface = SessionProvider.class, + policy = ReferencePolicy.DYNAMIC, + cardinality = ReferenceCardinality.OPTIONAL_MULTIPLE, + bind = "addSessionProvider", unbind = "removeSessionProvider") +public class DavexServletService extends JcrRemotingServlet + implements SessionProvider { + + /** Serial version UID */ + private static final long serialVersionUID = -901601294536148635L; + + private static final String DEFAULT_ALIAS = "/server"; + + @Property(value = DEFAULT_ALIAS) + private static final String PARAM_ALIAS = "alias"; + + @Reference + private Repository repository; + + private String alias; + + /** + * Currently available custom session providers. They're used + * first before the default provider gets consulted. The associated + * set of sessions is used to forcibly release all sessions acquired + * from a provider when that provider is being removed. + */ + private final Map> providers = + new LinkedHashMap>(); + + /** + * Currently active sessions. Used to link a session to the correct + * provider in the {@link #releaseSession(Session)} method. + */ + private final Map sessions = + new HashMap(); + + @Override + protected Repository getRepository() { + return repository; + } + + @Override + protected String getResourcePathPrefix() { + return alias; + } + + @Activate + public void activate(Map config) { + Object object = config.get(PARAM_ALIAS); + String string = ""; + if (object != null) { + string = object.toString(); + } + if (string.length() > 0) { + this.alias = string; + } else { + this.alias = DEFAULT_ALIAS; + } + } + + @Override + protected SessionProvider getSessionProvider() { + return this; + } + + /** + * Adds a custom session provider service. + * + * @param provider session provider + */ + public synchronized void addSessionProvider(SessionProvider provider) { + providers.put(provider, new HashSet()); + } + + /** + * Removes a custom session provider service. All active sessions + * acquired from that provider are forcibly released. + * + * @param provider session provider + */ + public synchronized void removeSessionProvider(SessionProvider provider) { + Set sessions = providers.remove(provider); + if (sessions != null) { + for (Session session : sessions) { + releaseSession(session); + } + } + } + + //-----------------------------------------------------< SessionProvider > + + /** + * Asks each available session provider in order for a session and + * returns the first session given. The default provider is used + * if no custom provider service is available or can provide a requested + * session. + */ + public synchronized Session getSession( + HttpServletRequest request, Repository repository, String workspace) + throws LoginException, ServletException, RepositoryException { + SessionProvider provider = null; + Session session = null; + + for (Map.Entry> entry : providers.entrySet()) { + provider = entry.getKey(); + session = provider.getSession(request, repository, workspace); + if (session != null) { + entry.getValue().add(session); + break; + } + } + + if (session == null) { + provider = super.getSessionProvider(); + session = provider.getSession(request, repository, workspace); + } + + if (session != null) { + sessions.put(session, provider); + } + + return session; + } + + /** + * Releases the given session using the provider from which it was acquired. + */ + public synchronized void releaseSession(Session session) { + SessionProvider provider = sessions.remove(session); + if (provider != null) { + provider.releaseSession(session); + } + } + +} Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/remoting/davex/DavexServletService.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/remoting/davex/DiffException.java =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/remoting/davex/DiffException.java (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/remoting/davex/DiffException.java (working copy) @@ -0,0 +1,41 @@ +/* + * 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.remoting.davex; + +import java.io.IOException; + +/** + * DiffException... + */ +class DiffException extends IOException { + + private Throwable cause; + + public DiffException(String message) { + super(message); + } + + public DiffException(String message, Throwable cause) { + super(message); + this.cause = cause; + } + + @Override + public Throwable getCause() { + return cause; + } +} Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/remoting/davex/DiffException.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/remoting/davex/DiffHandler.java =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/remoting/davex/DiffHandler.java (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/remoting/davex/DiffHandler.java (working copy) @@ -0,0 +1,31 @@ +/* + * 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.remoting.davex; + +/** + * DiffHandler... + */ +interface DiffHandler { + + void addNode(String targetPath, String diffValue) throws DiffException; + + void setProperty(String targetPath, String diffValue) throws DiffException; + + void remove(String targetPath, String diffValue) throws DiffException; + + void move(String targetPath, String diffValue) throws DiffException; +} Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/remoting/davex/DiffHandler.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/remoting/davex/DiffParser.java =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/remoting/davex/DiffParser.java (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/remoting/davex/DiffParser.java (working copy) @@ -0,0 +1,218 @@ +/* + * 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.remoting.davex; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.Reader; +import java.io.StringReader; +import java.io.InputStream; +import java.io.InputStreamReader; + +/** DiffParser... */ +class DiffParser { + + // TODO: review again: currently all line-sep. chars before an diff-char are + // TODO: ignored unless they are escaped in way the handler understands (e.g. + // TODO: JSON does: \\r for \r). + // TODO: in contrast line sep. at the end of the string are treated as value. + // TODO: ... similar: line sep. following by non-diff symbol. + + private final DiffHandler handler; + + private static final int EOF = -1; + + private static final char SYMBOL_ADD_NODE = '+'; + private static final char SYMBOL_MOVE = '>'; + private static final char SYMBOL_REMOVE = '-'; + private static final char SYMBOL_SET_PROPERTY = '^'; + + private static final int STATE_START_LINE = 0; + private static final int STATE_START_TARGET = 1; + private static final int STATE_TARGET = 2; + private static final int STATE_START_VALUE = 3; + private static final int STATE_VALUE = 4; + + /** + * + * @param handler + */ + public DiffParser(DiffHandler handler) { + this.handler = handler; + } + + public void parse(String str) throws IOException, DiffException { + parse(new BufferedReader(new StringReader(str))); + } + + public void parse(InputStream input, String charSetName) throws IOException, DiffException { + parse(new BufferedReader(new InputStreamReader(input, charSetName))); + } + + public void parse(Reader reader) throws IOException, DiffException { + int action = -1; + String path = null; + + StringBuffer lineSeparator = null; + StringBuffer bf = null; + + int state = STATE_START_LINE; + int next = reader.read(); + + while (next != EOF) { + switch (state) { + case STATE_START_LINE: + if (isSymbol(next)) { + // notify the last action read + if (action > -1) { + informAction(action, path, bf); + } + // ... and start recording the next action + action = next; + bf = null; + lineSeparator = null; + state = STATE_START_TARGET; + } else if (isLineSeparator(next)) { + // still line-separator -> append c to the lineSeparator + // buffer and keep state set to STATE_START_LINE + if (lineSeparator == null) { + throw new DiffException("Invalid start of new line."); + } else { + lineSeparator.append((char) next); + } + } else if (lineSeparator != null && bf != null) { + // append the collected return/linefeed chars as part + // of the value read and continued reading value. + bf.append(lineSeparator); + bf.append((char) next); + lineSeparator = null; + state = STATE_VALUE; + } else { + throw new DiffException("Invalid start of new line."); + } + break; + + case STATE_START_TARGET: + if (Character.isWhitespace((char) next) || next == ':') { + throw new DiffException("Invalid start of target path '" + next + "'"); + } + bf = new StringBuffer(); + bf.append((char) next); + state = STATE_TARGET; + break; + + case STATE_TARGET: + if (Character.isWhitespace((char) next) && endsWithDelim(bf)) { + // a sequence of 'wsp:wsp' indicates the delimiter between + // the target path and the diff value. + path = bf.substring(0, bf.lastIndexOf(":")).trim(); + state = STATE_START_VALUE; + // reset buffer + bf = null; + } else { + // continue reading the path into the buffer. + bf.append((char) next); + } + break; + + case STATE_START_VALUE: + if (isLineSeparator(next)) { + lineSeparator = new StringBuffer(); + lineSeparator.append((char) next); + bf = new StringBuffer(); + state = STATE_START_LINE; + } else { + bf = new StringBuffer(); + bf.append((char) next); + state = STATE_VALUE; + } + break; + + case STATE_VALUE: + if (isLineSeparator(next)) { + lineSeparator = new StringBuffer(); + lineSeparator.append((char) next); + state = STATE_START_LINE; + } else { + bf.append((char) next); + // keep state set to STATE_VALUE + } + break; + + } + // read the next character. + next = reader.read(); + } + + // a diff ending after a command or within the target is invalid. + if (state == STATE_START_TARGET || state == STATE_TARGET) { + throw new DiffException("Invalid end of DIFF string: missing separator and value."); + } + if (state == STATE_START_VALUE ) { + // line separator AND buffer must be null + if (!(lineSeparator == null && bf == null)) { + throw new DiffException("Invalid end of DIFF string."); + } + } + + // append eventual remaining line-separators to the value + if (lineSeparator != null) { + bf.append(lineSeparator); + } + // notify the last action read + informAction(action, path, bf); + } + + private void informAction(int action, String path, StringBuffer diffVal) throws DiffException { + if (path == null) { + throw new DiffException("Missing path for action " + action + "(diffValue = '"+ diffVal +"')"); + } + String value = (diffVal == null) ? null : diffVal.toString(); + switch (action) { + case SYMBOL_ADD_NODE: + handler.addNode(path, value); + break; + case SYMBOL_SET_PROPERTY: + handler.setProperty(path, value); + break; + case SYMBOL_MOVE: + handler.move(path, value); + break; + case SYMBOL_REMOVE: + handler.remove(path, value); + break; + default: + throw new DiffException("Invalid action " + action); + } + } + + private static boolean isSymbol(int c) { + return c == SYMBOL_ADD_NODE || c == SYMBOL_SET_PROPERTY || c == SYMBOL_MOVE || c == SYMBOL_REMOVE; + } + + private static boolean isLineSeparator(int c) { + return c == '\n' || c == '\r'; + + } + private static boolean endsWithDelim(StringBuffer bf) { + if (bf.length() < 2) { + return false; + } else { + return ':' == bf.charAt(bf.length()-1) && Character.isWhitespace(bf.charAt(bf.length()-2)); + } + } +} Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/remoting/davex/DiffParser.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/remoting/davex/JcrRemotingServlet.java =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/remoting/davex/JcrRemotingServlet.java (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/remoting/davex/JcrRemotingServlet.java (working copy) @@ -0,0 +1,812 @@ +/* + * 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.remoting.davex; + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashSet; +import java.util.Iterator; +import java.util.Locale; +import java.util.Set; + +import javax.jcr.Item; +import javax.jcr.ItemNotFoundException; +import javax.jcr.Node; +import javax.jcr.NodeIterator; +import javax.jcr.PathNotFoundException; +import javax.jcr.RepositoryException; +import javax.jcr.Session; +import javax.jcr.Workspace; +import javax.jcr.nodetype.NodeType; +import javax.servlet.ServletConfig; +import javax.servlet.ServletContext; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletResponse; + +import org.apache.jackrabbit.JcrConstants; +import org.apache.jackrabbit.server.util.RequestData; +import org.apache.jackrabbit.util.Text; +import org.apache.jackrabbit.webdav.DavException; +import org.apache.jackrabbit.webdav.DavLocatorFactory; +import org.apache.jackrabbit.webdav.DavMethods; +import org.apache.jackrabbit.webdav.DavResource; +import org.apache.jackrabbit.webdav.DavResourceFactory; +import org.apache.jackrabbit.webdav.DavResourceLocator; +import org.apache.jackrabbit.webdav.DavServletResponse; +import org.apache.jackrabbit.webdav.DavSession; +import org.apache.jackrabbit.webdav.WebdavRequest; +import org.apache.jackrabbit.webdav.WebdavResponse; +import org.apache.jackrabbit.webdav.jcr.JCRWebdavServerServlet; +import org.apache.jackrabbit.webdav.jcr.JcrDavException; +import org.apache.jackrabbit.webdav.jcr.JcrDavSession; +import org.apache.jackrabbit.webdav.jcr.transaction.TxLockManagerImpl; +import org.apache.jackrabbit.webdav.observation.SubscriptionManager; +import org.apache.jackrabbit.webdav.version.DeltaVConstants; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * JcrRemotingServlet is an extended version of the + * {@link org.apache.jackrabbit.webdav.jcr.JCRWebdavServerServlet JCR Remoting Servlet} + * that provides improved + * + * functionality and supports cross workspace copy and cloning. + * + *

Batch Read

+ * + * Upon RepositoryService.getItemInfos a JSON object is composed containing + * the information for the requested node and its child items up to a + * specified or configuration determined depth. + *

+ * Batch read is triggered by adding a '.json' extension to the resource href. + * Optionally the client may explicitly specify the desired batch read depth + * by appending '.depth.json' extension. If no json extension is present the + * GET request is processed by the base servlet. + *

+ * The JSON writer applies the following rules: + * + *

+ * - Nodes are represented as JSON objects.
+ *
+ * - Each Node has its properties included as JSON key/value pairs.
+ *
+ * - Single valued Properties are simple key/value pairs.
+ *
+ * - Multi valued Properties are represented as JSON array.
+ *
+ * - Each Node has its child nodes included as long a maximal depths is not reached.
+ * 
+ * - Nodes without any child nodes get a special JSON member named
+ *   ::NodeIteratorSize, whose value is zero.
+ *
+ * - If the maximal depth is reached only name, index and unique id of the
+ *   direct child are included (incomplete node info). In order to obtain
+ *   the complete information the client sends another GET with .json extension.
+ * 
+ * + * Same name sibling nodes and properties whose type cannot be unambiguously be + * extracted from the JSON on the client side need some special handling: + * + *
+ * - Node with index > 1, get a JSON key consisting of
+ *   Node.getName() + "[" + Node.getIndex() + "]" 
+ *
+ * - Binary Property
+ *   JSON value = length of the JCR value.
+ *   The JCR value must be retrieved separately.
+ *
+ * - Name, Path, Reference and Date Property
+ *   The JSON member representing the Property (name, value) is preceded by a
+ *   special member consisting of
+ *   JSON key = ":" + Property.getName()
+ *   JSON value = PropertyType.nameFromValue(Property.getType())
+ *
+ * - Multi valued properties with Property.getValues().length == 0 will be
+ *   treated as special property types above (extra property indicating the
+ *   type of the property).
+ *
+ * - Double Property
+ *   JSON value must not have any trailing ".0" removed.
+ * 
+ * + *

Multi Read

+ *

+ * Since Jackrabbit 2.3.6 it is also possible to request multiple subtrees + * in a single request. This is done by adding one or more ":include" + * parameters to a batch read request describe above. These extra parameters + * specify the (relative) paths of all the nodes to be included in the + * response. The response is a JSON object whose "nodes" property contains + * all the selected nodes keyed by path. Missing nodes are not included in + * the response. Each included node is serialized as defined above for + * batch read. + *

+ * Example: + *

+ * $ curl 'http://.../parent.json?:path=child1&:path=child2'
+ * {"nodes":{"/parent/child1":{...},"/parent/child2":{...}}}
+ * 
+ * + *

Batch Write

+ * + * The complete SPI Batch is sent to the server in a single request, currently a + * POST request containing a custom ":diff" parameter. + *
+ * NOTE that this is targeted to be replaced by a PATCH request. + * + *

Diff format

+ * + * The diff parameter currently consists of JSON-like key-value pairs with the + * following special requirements: + * + *
+ *   diff       ::= members
+ *   members    ::= pair | pairs
+ *   pair       ::= key " : " value
+ *   pairs      ::= pair line-end pair | pair line-end pairs
+ *   line-end   ::= "\r\n" | "\n" | "\r"
+ *   key        ::= diffchar path
+ *   diffchar   ::= "+" | "^" | "-" | ">"
+ *   path       ::= abspath | relpath
+ *   abspath    ::= * absolute path to an item *
+ *   relpath    ::= * relpath from item at request URI to an item *
+ *   value      ::= value+ | value- | value^ | value>
+ *   value+     ::= * a JSON object *
+ *   value-     ::= ""
+ *   value^     ::= * any JSON value except JSON object *
+ *   value>     ::= path | path "#before" | path "#after" | "#first" | "#last"
+ * 
+ * + * In other words: + *
    + *
  • diff consists of one or more key-value pair(s)
  • + *
  • key must start with a diffchar followed by a rel. or abs. item path
  • + *
  • diffchar being any of "+", "^", "-" or ">" representing the transient + * item modifications as follows + *
    + *   "+" addNode
    + *   "^" setProperty / setValue / removeProperty
    + *   "-" remove Item
    + *   ">" move / reorder Nodes
    + * 
    + *
  • + *
  • key must be separated from the value by a ":" surrounded by whitespace.
  • + *
  • two pairs must be separated by a line end
  • + *
  • the format of the value depends on the diffchar
  • + *
  • for moving around node the value must consist of a abs. or rel. path. + * in contrast reordering of existing nodes is achieved by appending a trailing + * order position hint (#first, #last, #before or #after)
  • + *
+ * + * NOTE the following special handling of JCR properties of type + * Binary, Name, Path, Date and Reference: + *
    + *
  • the JSON value must be missing
  • + *
  • the POST request is expected to contain extra multipart(s) or request + * parameter(s) for the property value(s)
  • + *
  • the content type of the extra parts/params must reflect the property + * type:"jcr-value/" + PropertyType.nameFromValue(Property.getType).toLowerCase()
  • + *
+ * + * @see www.json.org for the definition of + * JSON object and JSON value. + */ +public abstract class JcrRemotingServlet extends JCRWebdavServerServlet { + + private static Logger log = LoggerFactory.getLogger(JcrRemotingServlet.class); + + /** + * the home init parameter. other relative filesystem paths are + * relative to this location. + */ + public static final String INIT_PARAM_HOME = "home"; + + /** + * the 'temp-directory' init parameter + */ + public static final String INIT_PARAM_TMP_DIRECTORY = "temp-directory"; + /** + * temp-dir attribute to be set to the servlet-context + */ + public static final String ATTR_TMP_DIRECTORY = "remoting-servlet.tmpdir"; + + /** + * the 'temp-directory' init parameter + */ + public static final String INIT_PARAM_BATCHREAD_CONFIG = "batchread-config"; + + /** + * the 'protectedhandlers-config' init paramter. this parameter contains the XML + * configuration file for protected item remove handlers. + */ + public static final String INIT_PARAM_PROTECTED_HANDLERS_CONFIG = "protectedhandlers-config"; + + private static final String PARAM_DIFF = ":diff"; + private static final String PARAM_COPY = ":copy"; + private static final String PARAM_CLONE = ":clone"; + private static final String PARAM_INCLUDE = ":include"; + + private static final String CONTENT_TYPE_APPLICATION_JSON = "application/json"; + + private BatchReadConfig brConfig; + private ProtectedRemoveManager protectedRemoveManager; + + @Override + public void init() throws ServletException { + super.init(); + + brConfig = new BatchReadConfig(); + String brConfigParam = getServletConfig().getInitParameter(INIT_PARAM_BATCHREAD_CONFIG); + if (brConfigParam == null) { + // TODO: define default values. + log.debug("batchread-config missing -> initialize defaults."); + brConfig.setDepth("nt:file", BatchReadConfig.DEPTH_INFINITE); + brConfig.setDefaultDepth(5); + } else { + try { + InputStream in = getServletContext().getResourceAsStream(brConfigParam); + if (in != null) { + brConfig.load(in); + } + } catch (IOException e) { + log.debug("Unable to build BatchReadConfig from " + brConfigParam + "."); + } + } + + String protectedHandlerConfig = getServletConfig().getInitParameter(INIT_PARAM_PROTECTED_HANDLERS_CONFIG); + InputStream in = null; + try { + in = getServletContext().getResourceAsStream(protectedHandlerConfig); + if (in != null){ + protectedRemoveManager = new ProtectedRemoveManager(); + protectedRemoveManager.load(in); + } else { + //Config might be direct class implementation + protectedRemoveManager = new ProtectedRemoveManager(protectedHandlerConfig); + } + } catch (IOException e) { + log.debug("Unable to create ProtectedRemoveManager from " + protectedHandlerConfig , e); + } finally{ + if (in != null){ + try { + in.close(); + } catch (IOException ignore) { + } + } + } + + // Determine the configured location for temporary files used when + // processing file uploads. Since JCR-3029 the default is the + // standard java.io.tmpdir location, but the presence of explicit + // configuration parameters restores the original behavior. + File tmp = null; + ServletConfig config = getServletConfig(); + String paramHome = config.getInitParameter(INIT_PARAM_HOME); + String paramTemp = config.getInitParameter(INIT_PARAM_TMP_DIRECTORY); + if (paramHome != null || paramTemp != null) { + if (paramHome == null) { + log.debug("Missing init-param " + INIT_PARAM_HOME + + ". Using default: 'jackrabbit'"); + paramHome = "jackrabbit"; + } else if (paramTemp == null) { + log.debug("Missing init-param " + INIT_PARAM_TMP_DIRECTORY + + ". Using default: 'tmp'"); + paramTemp = "tmp"; + } + + tmp = new File(paramHome, paramTemp); + try { + tmp = tmp.getCanonicalFile(); + tmp.mkdirs(); + log.debug(" temp-directory = " + tmp.getPath()); + } catch (IOException e) { + log.warn("Invalid temporary directory " + tmp.getPath() + + ", using system default instead", e); + tmp = null; + } + } + getServletContext().setAttribute(ATTR_TMP_DIRECTORY, tmp); + + // force usage of custom locator factory. + super.setLocatorFactory(new DavLocatorFactoryImpl(getResourcePathPrefix())); + } + + protected String getResourcePathPrefix() { + return getInitParameter(INIT_PARAM_RESOURCE_PATH_PREFIX); + } + + @Override + public DavResourceFactory getResourceFactory() { + return new ResourceFactoryImpl(txMgr, subscriptionMgr); + } + + @Override + protected void doGet(WebdavRequest webdavRequest, + WebdavResponse webdavResponse, + DavResource davResource) throws IOException, DavException { + if (canHandle(DavMethods.DAV_GET, webdavRequest, davResource)) { + // return json representation of the requested resource + DavResourceLocator locator = davResource.getLocator(); + String path = locator.getRepositoryPath(); + + Session session = getRepositorySession(webdavRequest); + try { + Node node = session.getNode(path); + int depth = ((WrappingLocator) locator).getDepth(); + + webdavResponse.setContentType(CONTENT_TYPE_APPLICATION_JSON); + webdavResponse.setCharacterEncoding(StandardCharsets.UTF_8.name()); + webdavResponse.setStatus(DavServletResponse.SC_OK); + JsonWriter writer = new JsonWriter(webdavResponse.getWriter()); + + String[] includes = webdavRequest.getParameterValues(PARAM_INCLUDE); + if (includes == null) { + if (depth < BatchReadConfig.DEPTH_INFINITE) { + NodeType type = node.getPrimaryNodeType(); + depth = brConfig.getDepth(type.getName()); + } + writer.write(node, depth); + } else { + writeMultiple(writer, node, includes, depth); + } + } catch (PathNotFoundException e) { + // properties cannot be requested as json object. + throw new JcrDavException( + new ItemNotFoundException("No node at " + path), + DavServletResponse.SC_NOT_FOUND); + } catch (RepositoryException e) { + // should only get here if the item does not exist. + log.debug(e.getMessage()); + throw new JcrDavException(e); + } + } else { + super.doGet(webdavRequest, webdavResponse, davResource); + } + } + + private void writeMultiple( + JsonWriter writer, Node node, String[] includes, int depth) + throws RepositoryException, IOException { + Collection nodes = new ArrayList(); + Set alreadyAdded = new HashSet(); + for (String include : includes) { + try { + Node n; + if (include.startsWith("/")) { + n = node.getSession().getNode(include); + } else { + n = node.getNode(include); + } + String np = n.getPath(); + if (!alreadyAdded.contains(np)) { + nodes.add(n); + alreadyAdded.add(np); + } + } catch (PathNotFoundException e) { + // skip missing node + } + } + writer.write(nodes, depth); + } + + @Override + protected void doPost(WebdavRequest webdavRequest, WebdavResponse webdavResponse, DavResource davResource) + throws IOException, DavException { + if (canHandle(DavMethods.DAV_POST, webdavRequest, davResource)) { + // special remoting request: the defined parameters are exclusive + // and cannot be combined. + Session session = getRepositorySession(webdavRequest); + RequestData data = new RequestData(webdavRequest, getTempDirectory(getServletContext())); + String loc = null; + try { + String[] pValues; + String[] includes = null; // multi-read over POST + if ((pValues = data.getParameterValues(PARAM_CLONE)) != null) { + loc = clone(session, pValues, davResource.getLocator()); + } else if ((pValues = data.getParameterValues(PARAM_COPY)) != null) { + loc = copy(session, pValues, davResource.getLocator()); + } else if (data.getParameterValues(PARAM_DIFF) != null) { + String targetPath = davResource.getLocator().getRepositoryPath(); + processDiff(session, targetPath, data, protectedRemoveManager); + } else if ((pValues = data.getParameterValues(PARAM_INCLUDE)) != null + && canHandle(DavMethods.DAV_GET, webdavRequest, davResource)) { + includes = pValues; + } else { + String targetPath = davResource.getLocator().getRepositoryPath(); + loc = modifyContent(session, targetPath, data, protectedRemoveManager); + } + + // TODO: append entity + if (loc == null) { + webdavResponse.setStatus(HttpServletResponse.SC_OK); + if (includes != null) { + webdavResponse.setContentType(CONTENT_TYPE_APPLICATION_JSON); + webdavResponse.setCharacterEncoding(StandardCharsets.UTF_8.name()); + JsonWriter writer = new JsonWriter(webdavResponse.getWriter()); + + DavResourceLocator locator = davResource.getLocator(); + String path = locator.getRepositoryPath(); + + Node node = session.getNode(path); + int depth = ((WrappingLocator) locator).getDepth(); + + writeMultiple(writer, node, includes, depth); + } + } else { + webdavResponse.setHeader(DeltaVConstants.HEADER_LOCATION, loc); + webdavResponse.setStatus(HttpServletResponse.SC_CREATED); + } + } catch (RepositoryException e) { + log.warn(e.getMessage(), e); + throw new JcrDavException(e); + } catch (DiffException e) { + log.warn(e.getMessage()); + Throwable cause = e.getCause(); + if (cause instanceof RepositoryException) { + throw new JcrDavException((RepositoryException) cause); + } else { + throw new DavException(DavServletResponse.SC_BAD_REQUEST, "Invalid diff format."); + } + } finally { + data.dispose(); + } + } else { + super.doPost(webdavRequest, webdavResponse, davResource); + } + } + + private boolean canHandle(int methodCode, WebdavRequest request, DavResource davResource) { + DavResourceLocator locator = davResource.getLocator(); + switch (methodCode) { + case DavMethods.DAV_GET: + return davResource.exists() && (locator instanceof WrappingLocator) + && ((WrappingLocator) locator).isJsonRequest; + case DavMethods.DAV_POST: + String ct = request.getContentType(); + if (ct == null) { + return false; + } else { + int semicolon = ct.indexOf(';'); + if (semicolon >= 0) { + ct = ct.substring(0, semicolon); + } + ct = ct.trim().toLowerCase(Locale.ENGLISH); + return "multipart/form-data".equals(ct) || "application/x-www-form-urlencoded".equals(ct); + } + default: + return false; + } + } + + private static String clone(Session session, String[] cloneArgs, DavResourceLocator reqLocator) throws RepositoryException { + Workspace wsp = session.getWorkspace(); + String destPath = null; + for (String cloneArg : cloneArgs) { + String[] args = cloneArg.split(","); + if (args.length == 4) { + wsp.clone(args[0], args[1], args[2], Boolean.valueOf(args[3])); + destPath = args[2]; + } else { + throw new RepositoryException(":clone parameter must have a value consisting of the 4 args needed for a Workspace.clone() call."); + } + } + return buildLocationHref(session, destPath, reqLocator); + } + + private static String copy(Session session, String[] copyArgs, DavResourceLocator reqLocator) throws RepositoryException { + Workspace wsp = session.getWorkspace(); + String destPath = null; + for (String copyArg : copyArgs) { + String[] args = copyArg.split(","); + switch (args.length) { + case 2: + wsp.copy(args[0], args[1]); + destPath = args[1]; + break; + case 3: + wsp.copy(args[0], args[1], args[2]); + destPath = args[2]; + break; + default: + throw new RepositoryException(":copy parameter must have a value consisting of 2 jcr paths or workspaceName plus 2 jcr paths separated by ','."); + } + } + return buildLocationHref(session, destPath, reqLocator); + } + + private static String buildLocationHref(Session s, String destPath, DavResourceLocator reqLocator) throws RepositoryException { + if (destPath != null) { + NodeIterator it = s.getRootNode().getNodes(destPath.substring(1)); + Node n = null; + while (it.hasNext()) { + n = it.nextNode(); + } + if (n != null) { + DavResourceLocator loc = reqLocator.getFactory().createResourceLocator(reqLocator.getPrefix(), reqLocator.getWorkspacePath(), n.getPath(), false); + return loc.getHref(true); + } + } + + // unable to determine -> no location header sent back. + return null; + } + + private static void processDiff(Session session, String targetPath, RequestData data, ProtectedRemoveManager protectedRemoveManager) + throws RepositoryException, DiffException, IOException { + + String[] diffs = data.getParameterValues(PARAM_DIFF); + DiffHandler handler = new JsonDiffHandler(session, targetPath, data, protectedRemoveManager); + DiffParser parser = new DiffParser(handler); + + for (String diff : diffs) { + boolean success = false; + try { + parser.parse(diff); + + session.save(); + success = true; + } finally { + if (!success) { + session.refresh(false); + } + } + } + } + + /** + * TODO: doesn't work properly with intermediate SNS-nodes + * TODO: doesn't respect jcr:uuid properties. + */ + private static String modifyContent(Session session, String targetPath, RequestData data, ProtectedRemoveManager protectedRemoveManager) + throws RepositoryException, DiffException { + + JsonDiffHandler dh = new JsonDiffHandler(session, targetPath, data, protectedRemoveManager); + boolean success = false; + try { + for (Iterator pNames = data.getParameterNames(); pNames.hasNext();) { + String paramName = pNames.next(); + String propPath = dh.getItemPath(paramName); + String parentPath = Text.getRelativeParent(propPath, 1); + + if (!session.itemExists(parentPath) || !session.getItem(parentPath).isNode()) { + createNode(session, parentPath, data); + } + + if (JcrConstants.JCR_PRIMARYTYPE.equals(Text.getName(propPath))) { + // already handled by createNode above -> ignore + continue; + } + // none of the special properties -> let the diffhandler take care + // of the property creation/modification. + dh.setProperty(paramName, null); + } + + // save the complete set of modifications + session.save(); + success = true; + } finally { + if (!success) { + session.refresh(false); + } + } + return null; // TODO build loc-href if items were created. + } + + private static void createNode(Session session, String nodePath, RequestData data) throws RepositoryException { + Node parent = session.getRootNode(); + String[] smgts = Text.explode(nodePath, '/'); + + for (String nodeName : smgts) { + if (parent.hasNode(nodeName)) { + parent = parent.getNode(nodeName); + } else { + // need to create the node + // TODO: won't work for SNS + String nPath = parent.getPath() + "/" + nodeName; + String ntName = data.getParameter(nPath + "/" + JcrConstants.JCR_PRIMARYTYPE); + if (ntName == null) { + parent = parent.addNode(nodeName); + } else { + parent = parent.addNode(nodeName, ntName); + } + } + } + } + + private static Session getRepositorySession(WebdavRequest request) throws DavException { + DavSession ds = request.getDavSession(); + return JcrDavSession.getRepositorySession(ds); + } + + /** + * Returns the temp directory + * + * @return the temp directory + */ + private static File getTempDirectory(ServletContext servletCtx) { + return (File) servletCtx.getAttribute(ATTR_TMP_DIRECTORY); + } + + //-------------------------------------------------------------------------- + /** + * Locator factory that specially deals with hrefs having a .json extension. + */ + private static class DavLocatorFactoryImpl extends org.apache.jackrabbit.webdav.jcr.DavLocatorFactoryImpl { + + public DavLocatorFactoryImpl(String s) { + super(s); + } + + @Override + public DavResourceLocator createResourceLocator(String prefix, String href) { + return createResourceLocator(prefix, href, false); + } + + @Override + public DavResourceLocator createResourceLocator(String prefix, String href, boolean forDestination) { + DavResourceLocator loc = super.createResourceLocator(prefix, href); + if (!forDestination && endsWithJson(href)) { + loc = new WrappingLocator(super.createResourceLocator(prefix, href)); + } + return loc; + } + + @Override + public DavResourceLocator createResourceLocator(String prefix, String workspacePath, String path, boolean isResourcePath) { + DavResourceLocator loc = super.createResourceLocator(prefix, workspacePath, path, isResourcePath); + if (isResourcePath && endsWithJson(path)) { + loc = new WrappingLocator(loc); + } + return loc; + } + + private static boolean endsWithJson(String s) { + return s.endsWith(".json"); + } + } + + /** + * Resource locator that removes trailing .json extensions and depth + * selector that do not form part of the repository path. + * As the locator and it's factory do not have access to a JCR session + * the extraJson flag may be reset later on. + * + * @see ResourceFactoryImpl#getItem(org.apache.jackrabbit.webdav.jcr.JcrDavSession, org.apache.jackrabbit.webdav.DavResourceLocator) + */ + private static class WrappingLocator implements DavResourceLocator { + + private final DavResourceLocator loc; + private boolean isJsonRequest = true; + private int depth = Integer.MIN_VALUE; + private String repositoryPath; + + private WrappingLocator(DavResourceLocator loc) { + this.loc = loc; + } + + private void extract() { + String rp = loc.getRepositoryPath(); + rp = rp.substring(0, rp.lastIndexOf('.')); + int pos = rp.lastIndexOf('.'); + if (pos > -1) { + String depthStr = rp.substring(pos + 1); + try { + depth = Integer.parseInt(depthStr); + rp = rp.substring(0, pos); + } catch (NumberFormatException e) { + // apparently no depth-info -> ignore + } + } + repositoryPath = rp; + } + + private int getDepth() { + if (isJsonRequest) { + if (repositoryPath == null) { + extract(); + } + return depth; + } else { + return Integer.MIN_VALUE; + } + } + + public String getPrefix() { + return loc.getPrefix(); + } + public String getResourcePath() { + return loc.getResourcePath(); + } + public String getWorkspacePath() { + return loc.getWorkspacePath(); + } + public String getWorkspaceName() { + return loc.getWorkspaceName(); + } + public boolean isSameWorkspace(DavResourceLocator davResourceLocator) { + return loc.isSameWorkspace(davResourceLocator); + } + public boolean isSameWorkspace(String string) { + return loc.isSameWorkspace(string); + } + public String getHref(boolean b) { + return loc.getHref(b); + } + public boolean isRootLocation() { + return loc.isRootLocation(); + } + public DavLocatorFactory getFactory() { + return loc.getFactory(); + } + public String getRepositoryPath() { + if (isJsonRequest) { + if (repositoryPath == null) { + extract(); + } + return repositoryPath; + } else { + return loc.getRepositoryPath(); + } + } + } + + /** + * Resource factory used to make sure that the .json extension was properly + * interpreted. + */ + private static class ResourceFactoryImpl extends org.apache.jackrabbit.webdav.jcr.DavResourceFactoryImpl { + + /** + * Create a new DavResourceFactoryImpl. + * + * @param txMgr + * @param subsMgr + */ + public ResourceFactoryImpl(TxLockManagerImpl txMgr, SubscriptionManager subsMgr) { + super(txMgr, subsMgr); + } + + @Override + protected Item getItem(JcrDavSession sessionImpl, DavResourceLocator locator) throws PathNotFoundException, RepositoryException { + if (locator instanceof WrappingLocator && ((WrappingLocator)locator).isJsonRequest) { + // check if the .json extension has been correctly interpreted. + Session s = sessionImpl.getRepositorySession(); + try { + if (s.itemExists(((WrappingLocator)locator).loc.getRepositoryPath())) { + // an item exists with the original calculated repo-path + // -> assume that the repository item path ends with .json + // or .depth.json. i.e. .json wasn't an extra extension + // appended to request the json-serialization of the node. + // -> change the flag in the WrappingLocator correspondingly. + ((WrappingLocator) locator).isJsonRequest = false; + } + } catch (RepositoryException e) { + // if the unmodified repository path isn't valid (e.g. /a/b[2].5.json) + // -> ignore. + } + } + return super.getItem(sessionImpl, locator); + } + } +} Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/remoting/davex/JcrRemotingServlet.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/remoting/davex/JsonDiffHandler.java =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/remoting/davex/JsonDiffHandler.java (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/remoting/davex/JsonDiffHandler.java (working copy) @@ -0,0 +1,1022 @@ +/* + * 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.remoting.davex; + +import org.apache.jackrabbit.JcrConstants; +import org.apache.jackrabbit.commons.webdav.JcrValueType; +import org.apache.jackrabbit.server.util.RequestData; +import org.apache.jackrabbit.spi.Name; +import org.apache.jackrabbit.commons.json.JsonHandler; +import org.apache.jackrabbit.commons.json.JsonParser; +import org.apache.jackrabbit.util.Text; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.xml.sax.ContentHandler; +import org.xml.sax.SAXException; +import org.xml.sax.helpers.AttributesImpl; + +import javax.jcr.ImportUUIDBehavior; +import javax.jcr.Item; +import javax.jcr.ItemNotFoundException; +import javax.jcr.Node; +import javax.jcr.NodeIterator; +import javax.jcr.Property; +import javax.jcr.PropertyType; +import javax.jcr.RepositoryException; +import javax.jcr.Session; +import javax.jcr.Value; +import javax.jcr.ValueFactory; +import javax.jcr.ValueFormatException; +import javax.jcr.nodetype.ConstraintViolationException; +import javax.jcr.nodetype.ItemDefinition; +import javax.jcr.nodetype.NodeDefinition; +import javax.jcr.nodetype.NodeType; +import javax.jcr.nodetype.NodeTypeManager; +import javax.jcr.nodetype.PropertyDefinition; +import java.io.IOException; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Stack; +import java.util.LinkedList; + +/** JsonDiffHandler... */ +class JsonDiffHandler implements DiffHandler { + + private static final Logger log = LoggerFactory.getLogger(JsonDiffHandler.class); + + private static final String ORDER_POSITION_AFTER = "#after"; + private static final String ORDER_POSITION_BEFORE = "#before"; + private static final String ORDER_POSITION_FIRST = "#first"; + private static final String ORDER_POSITION_LAST = "#last"; + + private final Session session; + private final ValueFactory vf; + private final String requestItemPath; + private final RequestData data; + private final ProtectedRemoveManager protectedRemoveManager; + + private NodeTypeManager ntManager; + + JsonDiffHandler(Session session, String requestItemPath, RequestData data) throws RepositoryException { + this(session, requestItemPath, data, null); + } + + JsonDiffHandler(Session session, String requestItemPath, RequestData data, ProtectedRemoveManager protectedRemoveManager) throws RepositoryException { + this.session = session; + this.requestItemPath = requestItemPath; + this.data = data; + vf = session.getValueFactory(); + this.protectedRemoveManager = protectedRemoveManager; + } + + //--------------------------------------------------------< DiffHandler >--- + /** + * @see DiffHandler#addNode(String, String) + */ + @Override + public void addNode(String targetPath, String diffValue) throws DiffException { + if (diffValue == null || !(diffValue.startsWith("{") && diffValue.endsWith("}"))) { + throw new DiffException("Invalid 'addNode' value '" + diffValue + "'"); + } + + try { + String itemPath = getItemPath(targetPath); + String parentPath = Text.getRelativeParent(itemPath, 1); + String nodeName = Text.getName(itemPath); + + addNode(parentPath, nodeName, diffValue); + + } catch (RepositoryException e) { + throw new DiffException(e.getMessage(), e); + } + } + + /** + * @see DiffHandler#setProperty(String, String) + */ + @Override + public void setProperty(String targetPath, String diffValue) throws DiffException { + try { + String itemPath = getItemPath(targetPath); + Item item = session.getItem(Text.getRelativeParent(itemPath, 1)); + if (!item.isNode()) { + throw new DiffException("No such node " + itemPath, new ItemNotFoundException(itemPath)); + } + + Node parent = (Node) item; + String propName = Text.getName(itemPath); + + if (JcrConstants.JCR_MIXINTYPES.equals(propName)) { + setMixins(parent, extractValuesFromRequest(targetPath)); + } else if (JcrConstants.JCR_PRIMARYTYPE.equals(propName)) { + setPrimaryType(parent, extractValuesFromRequest(targetPath)); + } else { + if (diffValue == null || diffValue.length() == 0) { + // single valued property with value present in multipart. + Value[] vs = extractValuesFromRequest(targetPath); + if (vs.length == 0) { + if (parent.hasProperty(propName)) { + // avoid problems with single vs. multi valued props. + parent.getProperty(propName).remove(); + } else { + // property does not exist -> stick to rule that missing + // [] indicates single valued. + parent.setProperty(propName, (Value) null); + } + } else if (vs.length == 1) { + parent.setProperty(propName, vs[0]); + } else { + throw new DiffException("Unexpected number of values in multipart. Was " + vs.length + " but expected 1."); + } + } else if (diffValue.startsWith("[") && diffValue.endsWith("]")) { + // multivalued property + if (diffValue.length() == 2) { + // empty array OR values in multipart + Value[] vs = extractValuesFromRequest(targetPath); + parent.setProperty(propName, vs); + } else { + // json array + Value[] vs = extractValues(diffValue); + parent.setProperty(propName, vs); + } + } else { + // single prop value included in the diff + Value v = extractValue(diffValue); + parent.setProperty(propName, v); + } + } + } catch (RepositoryException e) { + throw new DiffException(e.getMessage(), e); + } catch (IOException e) { + if (e instanceof DiffException) { + throw (DiffException) e; + } else { + throw new DiffException(e.getMessage(), e); + } + } + } + + /** + * @see DiffHandler#remove(String, String) + */ + @Override + public void remove(String targetPath, String diffValue) throws DiffException { + if (!(diffValue == null || diffValue.trim().length() == 0)) { + throw new DiffException("'remove' may not have a diffValue."); + } + try { + String itemPath = getItemPath(targetPath); + Item item = session.getItem(itemPath); + + ItemDefinition def = (item.isNode()) ? ((Node) item).getDefinition() : ((Property) item).getDefinition(); + if (def.isProtected()) { + // delegate to the manager. + if (protectedRemoveManager == null || !protectedRemoveManager.remove(session, itemPath)) { + throw new ConstraintViolationException("Cannot remove protected node: no suitable handler configured."); + } + } else { + item.remove(); + } + } catch (RepositoryException e) { + throw new DiffException(e.getMessage(), e); + } + } + + /** + * @see DiffHandler#move(String, String) + */ + @Override + public void move(String targetPath, String diffValue) throws DiffException { + if (diffValue == null || diffValue.length() == 0) { + throw new DiffException("Invalid 'move' value '" + diffValue + "'"); + } + try { + String srcPath = getItemPath(targetPath); + String orderPosition = getOrderPosition(diffValue); + if (orderPosition == null) { + // simple move + String destPath = getItemPath(diffValue); + session.move(srcPath, destPath); + } else { + String srcName = Text.getName(srcPath); + int pos = diffValue.lastIndexOf('#'); + String destName = (pos == 0) ? null : Text.getName(diffValue.substring(0, pos)); + + Item item = session.getItem(Text.getRelativeParent(srcPath, 1)); + if (!item.isNode()) { + throw new ItemNotFoundException(srcPath); + } + Node parent = (Node) item; + + if (ORDER_POSITION_FIRST.equals(orderPosition)) { + if (destName != null) { + throw new DiffException(ORDER_POSITION_FIRST + " may not have a leading destination."); + } + destName = Text.getName(parent.getNodes().nextNode().getPath()); + parent.orderBefore(srcName, destName); + } else if (ORDER_POSITION_LAST.equals(orderPosition)) { + if (destName != null) { + throw new DiffException(ORDER_POSITION_LAST + " may not have a leading destination."); + } + parent.orderBefore(srcName, null); + } else if (ORDER_POSITION_AFTER.equals(orderPosition)) { + if (destName == null) { + throw new DiffException(ORDER_POSITION_AFTER + " must have a leading destination."); + } + for (NodeIterator it = parent.getNodes(); it.hasNext();) { + Node child = it.nextNode(); + if (destName.equals(child.getName())) { + if (it.hasNext()) { + destName = Text.getName(it.nextNode().getName()); + } else { + destName = null; + } + break; + } + } + // reorder... if no child node matches the original destName + // the reorder will fail. no extra check. + parent.orderBefore(srcName, destName); + } else { + // standard jcr reorder (before) + parent.orderBefore(srcName, destName); + } + } + + } catch (RepositoryException e) { + throw new DiffException(e.getMessage(), e); + } + } + + //-------------------------------------------------------------------------- + /** + * + * @param diffPath + * @return + * @throws RepositoryException + */ + String getItemPath(String diffPath) throws RepositoryException { + StringBuffer itemPath; + if (!diffPath.startsWith("/")) { + // diff path is relative to the item path retrieved from the + // request URI -> calculate item path. + itemPath = new StringBuffer(requestItemPath); + if (!requestItemPath.endsWith("/")) { + itemPath.append('/'); + } + itemPath.append(diffPath); + } else { + itemPath = new StringBuffer(diffPath); + } + return normalize(itemPath.toString()); + } + + private void addNode(String parentPath, String nodeName, String diffValue) + throws DiffException, RepositoryException { + Item item = session.getItem(parentPath); + if (!item.isNode()) { + throw new ItemNotFoundException(parentPath); + } + + Node parent = (Node) item; + try { + NodeHandler hndlr = new NodeHandler(parent, nodeName); + new JsonParser(hndlr).parse(diffValue); + } catch (IOException e) { + if (e instanceof DiffException) { + throw (DiffException) e; + } else { + throw new DiffException(e.getMessage(), e); + } + } + } + + private NodeTypeManager getNodeTypeManager() throws RepositoryException { + if (ntManager == null) { + ntManager = session.getWorkspace().getNodeTypeManager(); + } + return ntManager; + } + + private static String normalize(String path) { + if (path.indexOf('.') == -1) { + return path; + } + String[] elems = Text.explode(path, '/', false); + LinkedList queue = new LinkedList(); + String last = ".."; + for (String segm : elems) { + if ("..".equals(segm) && !"..".equals(last)) { + queue.removeLast(); + if (queue.isEmpty()) { + last = ".."; + } else { + last = queue.getLast(); + } + } else if (!".".equals(segm)) { + last = segm; + queue.add(last); + } + } + return "/" + Text.implode(queue.toArray(new String[queue.size()]), "/"); + } + + private static ContentHandler createContentHandler(Node parent) throws RepositoryException { + return parent.getSession().getImportContentHandler(parent.getPath(), ImportUUIDBehavior.IMPORT_UUID_COLLISION_THROW); + } + + private static Node importNode(Node parent, String nodeName, String ntName, + String uuid) throws RepositoryException { + + String uri = "http://www.jcp.org/jcr/sv/1.0"; + String prefix = "sv:"; + + ContentHandler ch = createContentHandler(parent); + try { + ch.startDocument(); + + String nN = "node"; + AttributesImpl attrs = new AttributesImpl(); + attrs.addAttribute(uri, "name", prefix + "name", "CDATA", nodeName); + ch.startElement(uri, nN, prefix + nN, attrs); + + // primary node type + String pN = "property"; + attrs = new AttributesImpl(); + attrs.addAttribute(uri, "name", prefix + "name", "CDATA", JcrConstants.JCR_PRIMARYTYPE); + attrs.addAttribute(uri, "type", prefix + "type", "CDATA", PropertyType.nameFromValue(PropertyType.NAME)); + ch.startElement(uri, pN, prefix + pN, attrs); + ch.startElement(uri, "value", prefix + "value", new AttributesImpl()); + char[] val = ntName.toCharArray(); + ch.characters(val, 0, val.length); + ch.endElement(uri, "value", prefix + "value"); + ch.endElement(uri, pN, prefix + pN); + + // uuid + attrs = new AttributesImpl(); + attrs.addAttribute(uri, "name", prefix + "name", "CDATA", JcrConstants.JCR_UUID); + attrs.addAttribute(uri, "type", prefix + "type", "CDATA", PropertyType.nameFromValue(PropertyType.STRING)); + ch.startElement(uri, pN, prefix + pN, attrs); + ch.startElement(uri, "value", prefix + "value", new AttributesImpl()); + val = uuid.toCharArray(); + ch.characters(val, 0, val.length); + ch.endElement(uri, "value", prefix + "value"); + ch.endElement(uri, pN, prefix + pN); + + ch.endElement(uri, nN, prefix + nN); + ch.endDocument(); + + } catch (SAXException e) { + throw new RepositoryException(e); + } + + Node n = null; + NodeIterator it = parent.getNodes(nodeName); + while (it.hasNext()) { + n = it.nextNode(); + } + if (n == null) { + throw new RepositoryException("Internal error: No child node added."); + } + return n; + } + + private static void setPrimaryType(Node n, Value[] values) throws RepositoryException, DiffException { + if (values.length == 1) { + String ntName = values[0].getString(); + if (!ntName.equals(n.getPrimaryNodeType().getName())) { + n.setPrimaryType(ntName); + } // else: same primaryType as before -> nothing to do. + } else { + throw new DiffException("Invalid diff: jcr:primarytype cannot have multiple values, nor can it's value be removed."); + } + } + + private static void setMixins(Node n, Value[] values) throws RepositoryException { + if (values.length == 0) { + // remove all mixins + NodeType[] mixins = n.getMixinNodeTypes(); + for (NodeType mixin : mixins) { + String mixinName = mixin.getName(); + n.removeMixin(mixinName); + } + } else { + List newMixins = new ArrayList(values.length); + for (Value value : values) { + newMixins.add(value.getString()); + } + NodeType[] mixins = n.getMixinNodeTypes(); + for (NodeType mixin : mixins) { + String mixinName = mixin.getName(); + if (!newMixins.remove(mixinName)) { + n.removeMixin(mixinName); + } + } + for (String newMixinName : newMixins) { + n.addMixin(newMixinName); + } + } + } + + private static String getOrderPosition(String diffValue) { + String position = null; + if (diffValue.indexOf('#') > -1) { + if (diffValue.endsWith(ORDER_POSITION_FIRST) || + diffValue.endsWith(ORDER_POSITION_LAST) || + diffValue.endsWith(ORDER_POSITION_BEFORE) || + diffValue.endsWith(ORDER_POSITION_AFTER)) { + position = diffValue.substring(diffValue.lastIndexOf('#')); + } // else: apparently # is part of the move path. + } + return position; + } + + private Value[] extractValuesFromRequest(String paramName) throws RepositoryException, IOException { + ValueFactory vf = session.getValueFactory(); + Value[] vs; + InputStream[] ins = data.getFileParameters(paramName); + if (ins != null) { + vs = new Value[ins.length]; + for (int i = 0; i < ins.length; i++) { + vs[i] = vf.createValue(ins[i]); + } + } else { + String[] strs = data.getParameterValues(paramName); + if (strs == null) { + vs = new Value[0]; + } else { + List valList = new ArrayList(strs.length); + for (int i = 0; i < strs.length; i++) { + if (strs[i] != null) { + String[] types = data.getParameterTypes(paramName); + int type = (types == null || types.length <= i) ? PropertyType.UNDEFINED : JcrValueType.typeFromContentType(types[i]); + if (type == PropertyType.UNDEFINED) { + valList.add(vf.createValue(strs[i])); + } else { + valList.add(vf.createValue(strs[i], type)); + } + } + } + vs = valList.toArray(new Value[valList.size()]); + } + } + return vs; + } + + private Value extractValue(String diffValue) throws RepositoryException, DiffException, IOException { + ValueHandler hndlr = new ValueHandler(); + // surround diff value { key : } to make it parsable + new JsonParser(hndlr).parse("{\"a\":"+diffValue+"}"); + + return hndlr.getValue(); + } + + private Value[] extractValues(String diffValue) throws RepositoryException, DiffException, IOException { + ValuesHandler hndlr = new ValuesHandler(); + // surround diff value { key : } to make it parsable + new JsonParser(hndlr).parse("{\"a\":" + diffValue + "}"); + + return hndlr.getValues(); + } + + //-------------------------------------------------------------------------- + /** + * Inner class used to parse a single value + */ + private final class ValueHandler implements JsonHandler { + private Value v; + + @Override + public void object() throws IOException { + // ignore + } + @Override + public void endObject() throws IOException { + // ignore + } + @Override + public void array() throws IOException { + // ignore + } + @Override + public void endArray() throws IOException { + // ignore + } + @Override + public void key(String key) throws IOException { + // ignore + } + + @Override + public void value(String value) throws IOException { + v = (value == null) ? null : vf.createValue(value); + } + @Override + public void value(boolean value) throws IOException { + v = vf.createValue(value); + } + @Override + public void value(long value) throws IOException { + v = vf.createValue(value); + } + @Override + public void value(double value) throws IOException { + v = vf.createValue(value); + } + + private Value getValue() { + return v; + } + } + + /** + * Inner class used to parse the values from a simple json array + */ + private final class ValuesHandler implements JsonHandler { + private List values = new ArrayList(); + + @Override + public void object() throws IOException { + // ignore + } + @Override + public void endObject() throws IOException { + // ignore + } + @Override + public void array() throws IOException { + // ignore + } + @Override + public void endArray() throws IOException { + // ignore + } + @Override + public void key(String key) throws IOException { + // ignore + } + + @Override + public void value(String value) throws IOException { + if (value != null) { + values.add(vf.createValue(value)); + } else { + log.warn("Null element for a multivalued property -> Ignore."); + } + } + @Override + public void value(boolean value) throws IOException { + values.add(vf.createValue(value)); + } + @Override + public void value(long value) throws IOException { + values.add(vf.createValue(value)); + } + @Override + public void value(double value) throws IOException { + values.add(vf.createValue(value)); + } + + private Value[] getValues() { + return values.toArray(new Value[values.size()]); + } + } + + /** + * Inner class for parsing a simple json object defining a node and its + * child nodes and/or child properties + */ + private final class NodeHandler implements JsonHandler { + private Node parent; + private String key; + + private Stack st = new Stack(); + + private NodeHandler(Node parent, String nodeName) throws IOException { + this.parent = parent; + key = nodeName; + } + + @Override + public void object() throws IOException { + ImportNode n; + if (st.isEmpty()) { + try { + n = new ImportNode(parent.getPath(), key); + } catch (RepositoryException e) { + throw new DiffException(e.getMessage(), e); + } + + } else { + ImportItem obj = st.peek(); + n = new ImportNode(obj.getPath(), key); + if (obj instanceof ImportNode) { + ((ImportNode) obj).addNode(n); + } else { + throw new DiffException("Invalid DIFF format: The JSONArray may only contain simple values."); + } + } + st.push(n); + } + + @Override + public void endObject() throws IOException { + // element on stack must be ImportMvProp since array may only + // contain simple values, no arrays/objects are allowed. + ImportItem obj = st.pop(); + if (!((obj instanceof ImportNode))) { + throw new DiffException("Invalid DIFF format."); + } + if (st.isEmpty()) { + // everything parsed -> start adding all nodes and properties + try { + if (obj.mandatesImport(parent)) { + obj.importItem(createContentHandler(parent)); + } else { + obj.createItem(parent); + } + } catch (IOException e) { + log.error(e.getMessage()); + throw new DiffException(e.getMessage(), e); + } catch (RepositoryException e) { + log.error(e.getMessage()); + throw new DiffException(e.getMessage(), e); + } + } + } + + @Override + public void array() throws IOException { + ImportItem obj = st.peek(); + ImportMvProp prop = new ImportMvProp(obj.getPath(), key); + if (obj instanceof ImportNode) { + ((ImportNode)obj).addProp(prop); + } else { + throw new DiffException("Invalid DIFF format: The JSONArray may only contain simple values."); + } + st.push(prop); + } + + @Override + public void endArray() throws IOException { + // element on stack must be ImportMvProp since array may only + // contain simple values, no arrays/objects are allowed. + ImportItem obj = st.pop(); + if (!((obj instanceof ImportMvProp))) { + throw new DiffException("Invalid DIFF format: The JSONArray may only contain simple values."); + } + } + + @Override + public void key(String key) throws IOException { + this.key = key; + } + + @Override + public void value(String value) throws IOException { + Value v = (value == null) ? null : vf.createValue(value); + value(v); + } + + @Override + public void value(boolean value) throws IOException { + value(vf.createValue(value)); + } + + @Override + public void value(long value) throws IOException { + Value v = vf.createValue(value); + value(v); + } + + @Override + public void value(double value) throws IOException { + value(vf.createValue(value)); + } + + private void value(Value v) throws IOException { + ImportItem obj = st.peek(); + if (obj instanceof ImportMvProp) { + ((ImportMvProp) obj).values.add(v); + } else { + ((ImportNode) obj).addProp(new ImportProp(obj.getPath(), key, v)); + } + } + } + + private abstract class ImportItem { + + static final String TYPE_CDATA = "CDATA"; + + final String parentPath; + final String name; + final String path; + + private ImportItem(String parentPath, String name) throws IOException { + if (name == null) { + throw new DiffException("Invalid DIFF format: NULL key."); + } + this.name = name; + this.parentPath = parentPath; + this.path = parentPath+"/"+name; + } + + void setNameAttribute(AttributesImpl attr) { + attr.addAttribute(Name.NS_SV_URI, "name", Name.NS_SV_PREFIX +":name", TYPE_CDATA, name); + } + + String getPath() { + return path; + } + + abstract boolean mandatesImport(Node parent); + + abstract void createItem(Node parent) throws RepositoryException, IOException; + + abstract void importItem(ContentHandler contentHandler) throws IOException; + } + + private final class ImportNode extends ImportItem { + + private static final String LOCAL_NAME = "node"; + + private ImportProp ntName; + private ImportProp uuid; + + private List childN = new ArrayList(); + private List childP = new ArrayList(); + + private ImportNode(String parentPath, String name) throws IOException { + super(parentPath, name); + } + + private String getUUID() { + if (uuid != null && uuid.value != null) { + try { + return uuid.value.getString(); + } catch (RepositoryException e) { + log.error(e.getMessage()); + } + } + return null; + } + + private String getPrimaryType() { + if (ntName != null && ntName.value != null) { + try { + return ntName.value.getString(); + } catch (RepositoryException e) { + log.error(e.getMessage()); + } + } + return null; + } + + @Override + boolean mandatesImport(Node parent) { + String primaryType = getPrimaryType(); + // Very simplistic and simplified test for protection that doesn't + // take mixin types into account and ignores all JCR primary types + if (!primaryType.startsWith(Name.NS_NT_PREFIX)) { + try { + NodeType nt = getNodeTypeManager().getNodeType(primaryType); + for (NodeDefinition nd : nt.getChildNodeDefinitions()) { + if (nd.isProtected()) { + return true; + } + } + for (PropertyDefinition pd : nt.getPropertyDefinitions()) { + if (!pd.getName().startsWith(Name.NS_JCR_PREFIX) && pd.isProtected()) { + return true; + } + } + } catch (RepositoryException e) { + log.warn(e.getMessage(), e); + } + } + return false; + } + + void addProp(ImportProp prop) { + if (prop.name.equals(JcrConstants.JCR_PRIMARYTYPE)) { + ntName = prop; + } else if (prop.name.equals(JcrConstants.JCR_UUID)) { + uuid = prop; + } else { + // regular property + childP.add(prop); + } + } + + void addProp(ImportMvProp prop) { + childP.add(prop); + } + + void addNode(ImportNode node) { + childN.add(node); + } + + @Override + void importItem(ContentHandler contentHandler) throws IOException { + try { + AttributesImpl attr = new AttributesImpl(); + setNameAttribute(attr); + contentHandler.startElement(Name.NS_SV_URI, LOCAL_NAME, Name.NS_SV_PREFIX+":"+LOCAL_NAME, attr); + + if (ntName != null && ntName.value != null) { + ntName.importItem(contentHandler); + } + if (uuid != null && uuid.value != null) { + uuid.importItem(contentHandler); + } + + for(ImportProperty prop : childP) { + prop.importItem(contentHandler); + } + + for(ImportNode node : childN) { + node.importItem(contentHandler); + } + contentHandler.endElement(Name.NS_SV_URI, LOCAL_NAME, Name.NS_SV_PREFIX+":"+LOCAL_NAME); + } catch(SAXException e) { + throw new DiffException(e.getMessage(), e); + } + } + + @Override + void createItem(Node parent) throws RepositoryException, IOException { + if (mandatesImport(parent)) { + ContentHandler ch = createContentHandler(parent); + try { + ch.startDocument(); + importItem(ch); + ch.endDocument(); + } catch (SAXException e) { + throw new DiffException(e.getMessage(), e); + } + } else { + Node n; + String uuidValue = getUUID(); + String primaryType = getPrimaryType(); + if (uuidValue == null) { + n = (primaryType == null) ? parent.addNode(name) : parent.addNode(name, primaryType); + } else { + n = importNode(parent, name, primaryType, uuidValue); + } + // create all properties + for (ImportItem obj : childP) { + obj.createItem(n); + } + // recursively create all child nodes + for (ImportItem obj : childN) { + obj.createItem(n); + } + } + } + } + + private abstract class ImportProperty extends ImportItem { + + static final String VALUE = "value"; + static final String TYPE = "type"; + static final String LOCAL_NAME = "property"; + + private ImportProperty(String parentPath, String name) throws IOException { + super(parentPath, name); + } + + @Override + boolean mandatesImport(Node parent) { + // TODO: verify again if a protected property (except for jcr:primaryType and jcr:mixinTypes) will ever change outside the scope of importing the whole tree. + return false; + } + + @Override + void importItem(ContentHandler contentHandler) throws IOException { + try { + AttributesImpl propAtts = new AttributesImpl(); + setNameAttribute(propAtts); + setTypeAttribute(propAtts); + contentHandler.startElement(Name.NS_SV_URI, LOCAL_NAME, Name.NS_SV_PREFIX+":"+LOCAL_NAME, propAtts); + startValueElement(contentHandler); + contentHandler.endElement(Name.NS_SV_URI, LOCAL_NAME, Name.NS_SV_PREFIX+":"+LOCAL_NAME); + } catch(SAXException e) { + throw new DiffException(e.getMessage(), e); + } + } + + void setTypeAttribute(AttributesImpl attr) { + String type = null; + if (name.equals(JcrConstants.JCR_PRIMARYTYPE)) { + type = PropertyType.nameFromValue(PropertyType.NAME); + } else if (name.equals(JcrConstants.JCR_MIXINTYPES)) { + type = PropertyType.nameFromValue(PropertyType.NAME); + } else if (name.equals(JcrConstants.JCR_UUID)) { + type = PropertyType.nameFromValue(PropertyType.STRING); + } else { + type = PropertyType.nameFromValue(PropertyType.UNDEFINED); + } + attr.addAttribute(Name.NS_SV_URI, TYPE, Name.NS_SV_PREFIX+":"+TYPE, TYPE_CDATA, type); + } + + abstract void startValueElement(ContentHandler contentHandler) throws IOException; + } + + private final class ImportProp extends ImportProperty { + + private final Value value; + + private ImportProp(String parentPath, String name, Value value) throws IOException { + super(parentPath, name); + try { + if (value == null) { + this.value = extractValuesFromRequest(getPath())[0]; + } else { + this.value = value; + } + } catch (RepositoryException e) { + throw new DiffException(e.getMessage(), e); + } + } + + @Override + void createItem(Node parent) throws RepositoryException { + parent.setProperty(name, value); + } + + @Override + void startValueElement(ContentHandler contentHandler) throws IOException { + try { + String str = value.getString(); + contentHandler.startElement(Name.NS_SV_URI, VALUE, Name.NS_SV_PREFIX + ":" + VALUE, new AttributesImpl()); + contentHandler.characters(str.toCharArray(), 0, str.length()); + contentHandler.endElement(Name.NS_SV_URI, VALUE, Name.NS_SV_PREFIX + ":" + VALUE); + } catch (SAXException e) { + throw new DiffException(e.getMessage()); + } catch (ValueFormatException e) { + throw new DiffException(e.getMessage()); + } catch (RepositoryException e) { + throw new DiffException(e.getMessage()); + } + } + } + + private final class ImportMvProp extends ImportProperty { + + private List values = new ArrayList(); + + private ImportMvProp(String parentPath, String name) throws IOException { + super(parentPath, name); + } + + @Override + void createItem(Node parent) throws RepositoryException { + Value[] vls = values.toArray(new Value[values.size()]); + if (JcrConstants.JCR_MIXINTYPES.equals(name)) { + setMixins(parent, vls); + } else { + parent.setProperty(name, vls); + } + } + + @Override + void startValueElement(ContentHandler contentHandler) throws IOException { + try { + // Multi-valued property with values present in the request + // multi-part + if (values.size() == 0) { + values = Arrays.asList(extractValuesFromRequest(getPath())); + } + + for (Value v : values) { + String str = v.getString(); + contentHandler.startElement(Name.NS_SV_URI, VALUE, Name.NS_SV_PREFIX + ":" + VALUE, new AttributesImpl()); + contentHandler.characters(str.toCharArray(), 0, str.length()); + contentHandler.endElement(Name.NS_SV_URI, VALUE, Name.NS_SV_PREFIX + ":" + VALUE); + } + } catch (SAXException e) { + throw new DiffException(e.getMessage()); + } catch (ValueFormatException e) { + throw new DiffException(e.getMessage()); + } catch (RepositoryException e) { + throw new DiffException(e.getMessage()); + } + } + } +} Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/remoting/davex/JsonDiffHandler.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/remoting/davex/JsonWriter.java =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/remoting/davex/JsonWriter.java (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/remoting/davex/JsonWriter.java (working copy) @@ -0,0 +1,292 @@ +/* + * 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.remoting.davex; + +import java.io.IOException; +import java.io.Writer; +import java.util.Collection; +import javax.jcr.Node; +import javax.jcr.NodeIterator; +import javax.jcr.Property; +import javax.jcr.PropertyIterator; +import javax.jcr.PropertyType; +import javax.jcr.RepositoryException; +import javax.jcr.Value; + +import org.apache.jackrabbit.JcrConstants; +import org.apache.jackrabbit.commons.json.JsonUtil; + +/** + * JsonWriter traverses a tree of JCR items and writes a JSON object + * exposing nodes as JSON object members and properties as JSON pairs. + *

+ * Note: Using JSON.org library is deliberately avoided for the + * following reasons. + *

    + *
  • JSONObject does not preserve the order of members added, which is required + * for JCR remoting.
  • + *
  • JSONObject#numberToString: + * Double numbers get their trailing '.0' stripped away, which removes + * the ability to distinguish between JCR values of type {@link PropertyType#DOUBLE} + * and {@link PropertyType#LONG}.
  • + *
+ */ +class JsonWriter { + + private final Writer writer; + + /** + * Create a new JsonItemWriter + * + * @param writer Writer to which the generated JSON string is written. + */ + JsonWriter(Writer writer) { + this.writer = writer; + } + + void write(Node node, int maxLevels) throws RepositoryException, IOException { + write(node, 0, maxLevels); + } + + void write(Collection nodes, int maxLevels) + throws RepositoryException, IOException { + writer.write('{'); + writeKey("nodes"); + writer.write('{'); + boolean first = true; + for (Node node : nodes) { + if (first) { + first = false; + } else { + writer.write(','); + } + writeKey(node.getPath()); + write(node, maxLevels); + } + writer.write('}'); + writer.write('}'); + } + + private void write(Node node, int currentLevel, int maxLevels) + throws RepositoryException, IOException { + // start of node info + writer.write('{'); + + // append the jcr properties as JSON pairs. + PropertyIterator props = node.getProperties(); + while (props.hasNext()) { + Property prop = props.nextProperty(); + writeProperty(prop); + // add separator: next json pair/member is either a property or + // a childnode or the special no-children-present pair. + writer.write(','); + } + + // for jcr child nodes include member unless the max-depths is reached. + // in case there are no children at all, append a special pair. + final NodeIterator children = node.getNodes(); + if (!children.hasNext()) { + // no child present at all -> add special property. + writeKeyValue("::NodeIteratorSize", 0); + } else { + // the child nodes + while (children.hasNext()) { + final Node n = children.nextNode(); + String name = n.getName(); + int index = n.getIndex(); + if (index > 1) { + writeKey(name + "[" + index + "]"); + } else { + writeKey(name); + } + if (maxLevels < 0 || currentLevel < maxLevels) { + write(n, currentLevel + 1, maxLevels); + } else { + /** + * In order to be able to compute the set of child-node entries + * upon Node creation -> add incomplete "node info" JSON + * object for the child node omitting properties and child + * information except for the jcr:uuid property (if present + * at all). + * the latter is required in order to build the correct SPI + * ChildInfo for Node n. + */ + writeChildInfo(n); + } + if (children.hasNext()) { + writer.write(','); + } + } + } + + // end of node info + writer.write('}'); + } + + /** + * Write child info without including the complete node info. + * + * @param n + * @throws RepositoryException + * @throws IOException + */ + private void writeChildInfo(Node n) throws RepositoryException, IOException { + // start child info + writer.write('{'); + + // make sure the SPI childInfo can be built correctly on the + // client side -> pass uuid if present. + if (n.isNodeType(JcrConstants.MIX_REFERENCEABLE) && + n.hasProperty(JcrConstants.JCR_UUID)) { + writeProperty(n.getProperty(JcrConstants.JCR_UUID)); + } + + // end child info + writer.write('}'); + } + + /** + * Write a single property + * + * @param p + * @throws javax.jcr.RepositoryException + * @throws java.io.IOException + */ + private void writeProperty(Property p) throws RepositoryException, IOException { + // special handling for binaries: we dump the length and not the length + int type = p.getType(); + if (type == PropertyType.BINARY) { + // mark binary properties with a leading ':' + // the value(s) reflect the jcr-values length instead of the binary data. + String key = ":" + p.getName(); + if (p.isMultiple()) { + long[] binLengths = p.getLengths(); + writeKeyArray(key, binLengths); + } else { + writeKeyValue(key, p.getLength()); + } + } else { + boolean isMultiple = p.isMultiple(); + if (requiresTypeInfo(p) || (isMultiple && p.getValues().length == 0)) { + /* special property types that have no correspondence in JSON + are transported as String. the type is transported with an + extra key-value pair, the key having a leading ':' the value + reflects the type. + the same applies for multivalued properties consisting of an + empty array -> property type guessing would not be possible. + */ + writeKeyValue(":" + p.getName(), PropertyType.nameFromValue(type), true); + } + /* append key-value pair containing the jcr value(s). + for String, Boolean, Double, Long -> types in json available */ + if (isMultiple) { + writeKeyArray(p.getName(), p.getValues()); + } else { + writeKeyValue(p.getName(), p.getValue()); + } + } + } + + private static boolean requiresTypeInfo(Property p) throws RepositoryException { + switch (p.getType()) { + case PropertyType.NAME: + case PropertyType.PATH: + case PropertyType.REFERENCE: + case PropertyType.DATE: + case PropertyType.WEAKREFERENCE: + case PropertyType.URI: + case PropertyType.DECIMAL: + case PropertyType.DOUBLE: + return true; + default: + // any other property type + return false; + } + } + + private void writeKeyValue(String key, String value, boolean hasNext) throws IOException { + writeKey(key); + writer.write(JsonUtil.getJsonString(value)); + if (hasNext) { + writer.write(','); + } + } + + private void writeKeyValue(String key, Value value) throws RepositoryException, IOException { + writeKey(key); + writeJsonValue(value); + } + + private void writeKeyArray(String key, Value[] values) throws RepositoryException, IOException { + writeKey(key); + writer.write('['); + for (int i = 0; i < values.length; i++) { + if (i > 0) { + writer.write(','); + } + writeJsonValue(values[i]); + } + writer.write(']'); + } + + private void writeKeyValue(String key, long binLength) throws IOException { + writeKey(key); + writer.write(String.valueOf(binLength)); + } + + private void writeKeyArray(String key, long[] binLengths) throws RepositoryException, IOException { + writeKey(key); + writer.write('['); + for (int i = 0; i < binLengths.length; i++) { + if (i > 0) { + writer.write(','); + } + writer.write(String.valueOf(binLengths[i])); + } + writer.write(']'); + } + + private void writeKey(String key) throws IOException { + writer.write(JsonUtil.getJsonString(key)); + writer.write(':'); + } + + private void writeJsonValue(Value v) throws RepositoryException, IOException { + + switch (v.getType()) { + case PropertyType.BINARY: + // should never get here + throw new IllegalArgumentException(); + + case PropertyType.BOOLEAN: + case PropertyType.LONG: + writer.write(v.getString()); + break; + case PropertyType.DOUBLE: + double d = v.getDouble(); + String str = v.getString(); + if (Double.isNaN(d) || Double.isInfinite(d)) { + str = JsonUtil.getJsonString(str); + } + writer.write(str); + break; + + default: + writer.write(JsonUtil.getJsonString(v.getString())); + } + } +} Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/remoting/davex/JsonWriter.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/remoting/davex/ProtectedItemRemoveHandler.java =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/remoting/davex/ProtectedItemRemoveHandler.java (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/remoting/davex/ProtectedItemRemoveHandler.java (working copy) @@ -0,0 +1,28 @@ +/* + * 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.remoting.davex; + +import javax.jcr.RepositoryException; +import javax.jcr.Session; + +/** + * ProtectedItemRemoveHandler... TODO + */ +public interface ProtectedItemRemoveHandler { + + public boolean remove(Session session, String itemPath) throws RepositoryException; +} Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/remoting/davex/ProtectedItemRemoveHandler.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/remoting/davex/ProtectedRemoveConfig.java =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/remoting/davex/ProtectedRemoveConfig.java (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/remoting/davex/ProtectedRemoveConfig.java (working copy) @@ -0,0 +1,83 @@ +/* + * 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.remoting.davex; + +import java.io.IOException; +import java.io.InputStream; + +import javax.xml.parsers.ParserConfigurationException; + +import org.apache.jackrabbit.webdav.xml.DomUtil; +import org.apache.jackrabbit.webdav.xml.ElementIterator; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.w3c.dom.Element; +import org.xml.sax.SAXException; + +/** + * A configuration of ProtectedItemRemoveHandler(s). + * + * ProtectedRemoveConfig + */ +class ProtectedRemoveConfig { + + private static final Logger log = LoggerFactory.getLogger(ProtectedRemoveConfig.class); + + private static final String ELEMENT_HANDLER = "protecteditemremovehandler"; + private static final String ELEMENT_CLASS = "class"; + private static final String ATTRIBUTE_NAME = "name"; + + private final ProtectedRemoveManager manager; + + ProtectedRemoveConfig(ProtectedRemoveManager manager) { + this.manager = manager; + } + + void parse(InputStream inputStream) throws IOException { + Element config; + ProtectedItemRemoveHandler instance = null; + try { + config = DomUtil.parseDocument(inputStream).getDocumentElement(); + if (config == null) { + log.warn("Missing mandatory config element"); + return; + } + ElementIterator handlers = DomUtil.getChildren(config, ELEMENT_HANDLER, null); + while (handlers.hasNext()) { + Element handler = handlers.nextElement(); + instance = createHandler(handler); + manager.addHandler(instance); + } + } catch (ParserConfigurationException e) { + log.error(e.getMessage(), e); + } catch (SAXException e) { + log.error(e.getMessage(), e); + } + } + + private ProtectedItemRemoveHandler createHandler(Element parent) { + ProtectedItemRemoveHandler instance = null; + Element classElem = DomUtil.getChildElement(parent, ELEMENT_CLASS, null); + if (classElem != null) { + String className = DomUtil.getAttribute(classElem, ATTRIBUTE_NAME, null); + if (className != null) { + instance = manager.createHandler(className); + } + } + return instance; + } +} Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/remoting/davex/ProtectedRemoveConfig.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/remoting/davex/ProtectedRemoveManager.java =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/remoting/davex/ProtectedRemoveManager.java (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/remoting/davex/ProtectedRemoveManager.java (working copy) @@ -0,0 +1,112 @@ +/* + * 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.remoting.davex; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.List; + +import javax.jcr.RepositoryException; +import javax.jcr.Session; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +class ProtectedRemoveManager { + + private static final Logger log = LoggerFactory.getLogger(ProtectedRemoveManager.class); + + private List handlers = new ArrayList(); + + ProtectedRemoveManager(){ + + } + + ProtectedRemoveManager(String config) throws IOException { + + if (config == null) { + log.warn("protectedhandlers-config is missing -> DIFF processing can fail for the Remove operation if the content to" + + "remove is protected!"); + } else { + File file = new File(config); + if (file.exists()) { + try { + InputStream fis = new FileInputStream(file); + load(fis); + } catch (FileNotFoundException e) { + throw new IOException(e.getMessage(), e); + } + } else { // config is an Impl class + if (!config.isEmpty()) { + ProtectedItemRemoveHandler handler = createHandler(config); + addHandler(handler); + } else { + log.debug("Fail to locate the protected-item-remove-handler properties file."); + } + } + } + } + + void load(InputStream fis) throws IOException { + ProtectedRemoveConfig prConfig = new ProtectedRemoveConfig(this); + prConfig.parse(fis); + } + + boolean remove(Session session, String itemPath) throws RepositoryException { + for (ProtectedItemRemoveHandler handler : handlers) { + if (handler.remove(session, itemPath)) { + return true; + } + } + return false; + } + + /** + * Instantiates and returns a concrete ProtectedItemRemoveHandler implementation. + * @param className + * @return + * @throws RepositoryException + */ + ProtectedItemRemoveHandler createHandler(String className) { + ProtectedItemRemoveHandler irHandler = null; + try { + if (!className.isEmpty()) { + Class irHandlerClass = Class.forName(className); + if (ProtectedItemRemoveHandler.class.isAssignableFrom(irHandlerClass)) { + irHandler = (ProtectedItemRemoveHandler) irHandlerClass.newInstance(); + } + } + } catch (ClassNotFoundException e) { + log.error(e.getMessage(), e); + } catch (InstantiationException e) { + log.error(e.getMessage(), e); + } catch (IllegalAccessException e) { + log.error(e.getMessage(), e); + } + return irHandler; + } + + void addHandler(ProtectedItemRemoveHandler instance) { + if (instance != null) { + handlers.add(instance); + } + } +} Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/remoting/davex/ProtectedRemoveManager.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/util/HttpMultipartPost.java =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/util/HttpMultipartPost.java (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/util/HttpMultipartPost.java (working copy) @@ -0,0 +1,286 @@ +/* + * 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.util; + +import org.apache.commons.fileupload.FileItem; +import org.apache.commons.fileupload.FileItemFactory; +import org.apache.commons.fileupload.FileUploadException; +import org.apache.commons.fileupload.disk.DiskFileItemFactory; +import org.apache.commons.fileupload.servlet.ServletFileUpload; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.servlet.http.HttpServletRequest; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; + +/** + * HttpMultipartPost... + */ +class HttpMultipartPost { + + private static final Logger log = LoggerFactory.getLogger(HttpMultipartPost.class); + + private final Map> nameToItems = new LinkedHashMap>(); + private final Set fileParamNames = new HashSet(); + + private boolean initialized; + + HttpMultipartPost(HttpServletRequest request, File tmpDir) throws IOException { + extractMultipart(request, tmpDir); + initialized = true; + } + + private static FileItemFactory getFileItemFactory(File tmpDir) { + DiskFileItemFactory fiFactory = new DiskFileItemFactory(DiskFileItemFactory.DEFAULT_SIZE_THRESHOLD, tmpDir); + return fiFactory; + } + + private void extractMultipart(HttpServletRequest request, File tmpDir) + throws IOException { + if (!ServletFileUpload.isMultipartContent(request)) { + log.debug("Request does not contain multipart content -> ignoring."); + return; + } + + ServletFileUpload upload = new ServletFileUpload(getFileItemFactory(tmpDir)); + // make sure the content disposition headers are read with the charset + // specified in the request content type (or UTF-8 if no charset is specified). + // see JCR + if (request.getCharacterEncoding() == null) { + upload.setHeaderEncoding("UTF-8"); + } + try { + @SuppressWarnings("unchecked") + List fileItems = upload.parseRequest(request); + for (FileItem fileItem : fileItems) { + addItem(fileItem); + } + } catch (FileUploadException e) { + log.error("Error while processing multipart.", e); + throw new IOException(e.toString()); + } + } + + /** + * Add the given file item to the list defined for its name and make the + * list is present in the map. If the item does not represent a simple + * form field its name is also added to the fileParamNames set. + * + * @param item The {@link FileItem} to add. + */ + private void addItem(FileItem item) { + String name = item.getFieldName(); + List l = nameToItems.get(item.getFieldName()); + if (l == null) { + l = new ArrayList(); + nameToItems.put(name, l); + } + l.add(item); + + // if file parameter, add name to the set of file parameters in order to + // be able to extract the file parameter values later on without iterating + // over all keys. + if (!item.isFormField()) { + fileParamNames.add(name); + } + } + + private void checkInitialized() { + if (!initialized) { + throw new IllegalStateException("HttpMultipartPost not initialized (or already disposed)."); + } + } + + /** + * Release all file items hold with the name-to-items map. Especially those + * having a temporary file associated with. + * + * @see FileItem#delete() + */ + synchronized void dispose() { + checkInitialized(); + + for (List fileItems : nameToItems.values()) { + for (FileItem fileItem : fileItems) { + fileItem.delete(); + } + } + + nameToItems.clear(); + fileParamNames.clear(); + initialized = false; + } + + /** + * Returns an iterator over all file item names. + * + * @return a set of strings. + */ + Set getParameterNames() { + checkInitialized(); + return nameToItems.keySet(); + } + + + /** + * Returns the content types of the parameters with the given name. If + * the parameter does not exist null is returned. If the content + * type of any of the parameter values is not known, the corresponding entry + * in the array returned is null. + *

+ * The content type of a parameter is only known here if the information + * has been sent by the client browser. This is generally only the case + * for file upload fields of HTML forms which have been posted using the + * HTTP POST with multipart/form-data encoding. + *

+ * Example : For the form + *

+         
+
+
+ +
+ *
+ * this method will return an array of two entries when called for the + * Upload parameter. The first entry will contain the content + * type (if transmitted by the client) of the file uploaded. The second + * entry will be null because the content type of the text + * input field will generally not be sent by the client. + * + * @param name The name of the parameter whose content type is to be + * returned. + * @return The content types of the file items with the specified name. + */ + String[] getParameterTypes(String name) { + checkInitialized(); + String[] cts = null; + List l = nameToItems.get(name); + if (l != null && !l.isEmpty()) { + cts = new String[l.size()]; + for (int i = 0; i < cts.length; i++) { + cts[i] = l.get(i).getContentType(); + } + } + return cts; + } + + /** + * Returns the first value of the file items with the given name. + * The byte to string conversion is done using either the content type of + * the file items or the formEncoding. + *

+ * Please note that if the addressed parameter is an uploaded file rather + * than a simple form entry, the name of the original file is returned + * instead of the content. + * + * @param name the name of the parameter + * @return the string of the first value or null if the + * parameter does not exist + */ + String getParameter(String name) { + checkInitialized(); + List l = nameToItems.get(name); + if (l == null || l.isEmpty()) { + return null; + } else { + FileItem item = l.get(0); + if (item.isFormField()) { + return item.getString(); + } else { + return item.getName(); + } + } + } + + /** + * Returns an array of Strings with all values of the parameter addressed + * by name. the byte to string conversion is done using either + * the content type of the multipart body or the formEncoding. + *

+ * Please note that if the addressed parameter is an uploaded file rather + * than a simple form entry, the name of the original file is returned + * instead of the content. + * + * @param name the name of the parameter + * @return a string array of values or null if no entry with the + * given name exists. + */ + String[] getParameterValues(String name) { + checkInitialized(); + List l = nameToItems.get(name); + if (l == null || l.isEmpty()) { + return null; + } else { + String[] values = new String[l.size()]; + for (int i = 0; i < values.length; i++) { + FileItem item = l.get(i); + if (item.isFormField()) { + values[i] = item.getString(); + } else { + values[i] = item.getName(); + } + } + return values; + } + } + + /** + * Returns a set of the file parameter names. An empty set if + * no file parameters were present in the request. + * + * @return an set of file item names representing the file + * parameters available with the request. + */ + Set getFileParameterNames() { + checkInitialized(); + return fileParamNames; + } + + /** + * Returns an array of input streams for uploaded file parameters. + * + * @param name the name of the file parameter(s) + * @return an array of input streams or null if no file params + * with the given name exist. + * @throws IOException if an I/O error occurs + */ + InputStream[] getFileParameterValues(String name) throws IOException { + checkInitialized(); + InputStream[] values = null; + if (fileParamNames.contains(name)) { + List l = nameToItems.get(name); + if (l != null && !l.isEmpty()) { + List ins = new ArrayList(l.size()); + for (FileItem item : l) { + if (!item.isFormField()) { + ins.add(item.getInputStream()); + } + } + values = ins.toArray(new InputStream[ins.size()]); + } + } + return values; + } +} Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/util/HttpMultipartPost.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/util/RequestData.java =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/util/RequestData.java (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/util/RequestData.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.util; + +import javax.servlet.http.HttpServletRequest; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.util.HashSet; +import java.util.Iterator; + +/** + * RequestData... + */ +public class RequestData { + + private final HttpServletRequest request; + private final HttpMultipartPost mpReq; + + public RequestData(HttpServletRequest request, File tmpDir) throws IOException { + this.request = request; + this.mpReq = new HttpMultipartPost(request, tmpDir); + } + + /** + * Dispose resources used. + */ + public void dispose() { + mpReq.dispose(); + } + + /** + * Returns an iterator over all parameter names. + * + * @return an iterator over strings. + */ + public Iterator getParameterNames() { + @SuppressWarnings("unchecked") + HashSet names = new HashSet(request.getParameterMap().keySet()); + names.addAll(mpReq.getParameterNames()); + + return names.iterator(); + } + + /** + * Returns the first value of the parameter with the given name. + * The byte to string conversion is done using either the content type of + * the parameter or the formEncoding. + *

+ * Please note that if the addressed parameter is a file parameter, the + * name of the original file is returned, and not its content. + * + * @param name the name of the parameter + * @return the string of the first value or null if the + * parameter does not exist + */ + public String getParameter(String name) { + String ret = mpReq.getParameter(name); + return (ret == null) ? request.getParameter(name) : ret; + } + + /** + * Returns the content types retrieved for parameters with the specified + * name from the multipart or null if the multipart does not + * contain parameter(s) with the given name. + * + * @param name parameter name + * @return the parameter types retrieved for the specified parameter + * name from the multipart or null. + */ + public String[] getParameterTypes(String name) { + String[] types = mpReq.getParameterTypes(name); + return types == null ? null : types; + } + + /** + * Returns an array of Strings with all values of the parameter addressed + * by name. the byte to string conversion is done using either + * the content type of the multipart body or the formEncoding. + *

+ * Please note that if the addressed parameter is a file parameter, the + * name of the original file is returned, and not its content. + * + * @param name the name of the parameter + * @return a string array of values or null if the parameter + * does not exist. + */ + public String[] getParameterValues(String name) { + String[] ret = mpReq.getParameterValues(name); + return ret == null ? request.getParameterValues(name) : ret; + } + + /** + * Returns an array of input streams for uploaded file parameters. + * + * @param name the name of the file parameter(s) + * @return an array of input streams or an empty array if no file params + * with the given name exist. + * @throws IOException if an I/O error occurs + */ + public InputStream[] getFileParameters(String name) throws IOException { + return mpReq.getFileParameterValues(name); + } +} Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/util/RequestData.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/webdav/jcr/AbstractItemResource.java =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/AbstractItemResource.java (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/AbstractItemResource.java (working copy) @@ -0,0 +1,482 @@ +/* + * 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.webdav.jcr; + +import org.apache.jackrabbit.util.Text; +import org.apache.jackrabbit.webdav.DavCompliance; +import org.apache.jackrabbit.webdav.DavException; +import org.apache.jackrabbit.webdav.DavResource; +import org.apache.jackrabbit.webdav.DavResourceFactory; +import org.apache.jackrabbit.webdav.DavResourceLocator; +import org.apache.jackrabbit.webdav.DavServletResponse; +import org.apache.jackrabbit.webdav.io.OutputContext; +import org.apache.jackrabbit.webdav.jcr.nodetype.ItemDefinitionImpl; +import org.apache.jackrabbit.webdav.jcr.nodetype.NodeDefinitionImpl; +import org.apache.jackrabbit.webdav.jcr.nodetype.PropertyDefinitionImpl; +import org.apache.jackrabbit.webdav.jcr.property.JcrDavPropertyNameSet; +import org.apache.jackrabbit.webdav.observation.EventDiscovery; +import org.apache.jackrabbit.webdav.observation.ObservationConstants; +import org.apache.jackrabbit.webdav.observation.ObservationResource; +import org.apache.jackrabbit.webdav.observation.Subscription; +import org.apache.jackrabbit.webdav.observation.SubscriptionInfo; +import org.apache.jackrabbit.webdav.observation.SubscriptionManager; +import org.apache.jackrabbit.webdav.property.DavProperty; +import org.apache.jackrabbit.webdav.property.DavPropertyName; +import org.apache.jackrabbit.webdav.property.DefaultDavProperty; +import org.apache.jackrabbit.webdav.property.HrefProperty; +import org.apache.jackrabbit.webdav.transaction.TxLockEntry; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.jcr.Item; +import javax.jcr.Node; +import javax.jcr.PathNotFoundException; +import javax.jcr.Property; +import javax.jcr.RepositoryException; +import javax.jcr.Workspace; +import java.io.IOException; + +/** + * AbstractItemResource covers common functionality for the various + * resources, that represent a repository item. + */ +abstract class AbstractItemResource extends AbstractResource implements + ObservationResource, ItemResourceConstants { + + private static Logger log = LoggerFactory.getLogger(AbstractItemResource.class); + + private SubscriptionManager subsMgr; + protected final Item item; + + /** + * Create a new AbstractItemResource. + * + * @param locator + * @param session + * @param factory + * @param item + */ + AbstractItemResource(DavResourceLocator locator, JcrDavSession session, + DavResourceFactory factory, Item item) { + super(locator, session, factory); + this.item = item; + + // initialize the supported locks and reports + initLockSupport(); + initSupportedReports(); + } + + //----------------------------------------------< DavResource interface >--- + /** + * @see org.apache.jackrabbit.webdav.DavResource#getComplianceClass() + */ + @Override + public String getComplianceClass() { + return DavCompliance.concatComplianceClasses( + new String[] { + super.getComplianceClass(), + DavCompliance.OBSERVATION, + } + ); + } + + @Override + public DavProperty getProperty(DavPropertyName name) { + DavProperty prop = super.getProperty(name); + if (prop == null) { + if (JCR_DEFINITION.equals(name)) { + if (exists()) { + try { + + // protected 'definition' property revealing the item definition + ItemDefinitionImpl val; + if (item.isNode()) { + val = NodeDefinitionImpl.create(((Node)item).getDefinition()); + } else { + val = PropertyDefinitionImpl.create(((Property)item).getDefinition()); + } + prop = new DefaultDavProperty(JCR_DEFINITION, val, true); + } catch (RepositoryException e) { + // should not get here + log.error("Error while accessing item definition: " + e.getMessage()); + } + } + } else if (JCR_ISNEW.equals(name)) { + // transaction resource additional protected properties + if (exists() && item.isNew()) { + prop = new DefaultDavProperty(JCR_ISNEW, null, true); + } + } else if (JCR_ISMODIFIED.equals(name)) { + // transaction resource additional protected properties + if (exists() && item.isModified()) { + prop = new DefaultDavProperty(JCR_ISMODIFIED, null, true); + } + } else if (ObservationConstants.SUBSCRIPTIONDISCOVERY.equals(name)) { + // observation resource + prop = subsMgr.getSubscriptionDiscovery(this); + } + } + + return prop; + } + + /** + * @see org.apache.jackrabbit.webdav.DavResource#getSupportedMethods() + */ + @Override + public String getSupportedMethods() { + return ItemResourceConstants.METHODS; + } + + /** + * Returns true if there exists a {@link Item repository item} with the given + * resource path, false otherwise. + * + * @see org.apache.jackrabbit.webdav.DavResource#exists() + */ + @Override + public boolean exists() { + return item != null; + } + + /** + * Retrieves the last segment of the item path (or the resource path if + * this resource does not exist). An item path is in addition first translated + * to the corresponding resource path.
+ * NOTE: the display name is not equivalent to {@link Item#getName() item name} + * which is exposed with the {@link ItemResourceConstants#JCR_NAME + * {http://www.day.com/jcr/webdav/1.0}name} property. + * + * @see org.apache.jackrabbit.webdav.DavResource#getDisplayName() + */ + @Override + public String getDisplayName() { + String resPath = getResourcePath(); + return (resPath != null) ? Text.getName(resPath) : resPath; + } + + /** + * Spools the properties of this resource to the context. Note that subclasses + * are in charge of spooling the data to the output stream provided by the + * context. + * + * @see DavResource#spool(OutputContext) + */ + @Override + public void spool(OutputContext outputContext) throws IOException { + if (!initedProps) { + initProperties(); + } + // export properties + outputContext.setModificationTime(getModificationTime()); + DavProperty etag = getProperty(DavPropertyName.GETETAG); + if (etag != null) { + outputContext.setETag(String.valueOf(etag.getValue())); + } + DavProperty contentType = getProperty(DavPropertyName.GETCONTENTTYPE); + if (contentType != null) { + outputContext.setContentType(String.valueOf(contentType.getValue())); + } + DavProperty contentLength = getProperty(DavPropertyName.GETCONTENTLENGTH); + if (contentLength != null) { + try { + long length = Long.parseLong(contentLength.getValue() + ""); + if (length > 0) { + outputContext.setContentLength(length); + } + } catch (NumberFormatException e) { + log.error("Could not build content length from property value '" + contentLength.getValue() + "'"); + } + } + DavProperty contentLanguage = getProperty(DavPropertyName.GETCONTENTLANGUAGE); + if (contentLanguage != null) { + outputContext.setContentLanguage(contentLanguage.getValue().toString()); + } + } + + /** + * Returns the resource representing the parent item of the repository item + * represented by this resource. If this resoure represents the root item + * a {@link RootCollection} is returned. + * + * @return the collection this resource is internal member of. Except for the + * repository root, the returned collection always represent the parent + * repository node. + * @see org.apache.jackrabbit.webdav.DavResource#getCollection() + */ + @Override + public DavResource getCollection() { + DavResource collection = null; + + String parentPath = Text.getRelativeParent(getResourcePath(), 1); + DavResourceLocator parentLoc = getLocator().getFactory().createResourceLocator(getLocator().getPrefix(), getLocator().getWorkspacePath(), parentPath); + try { + collection = createResourceFromLocator(parentLoc); + } catch (DavException e) { + log.error("Unexpected error while retrieving collection: " + e.getMessage()); + } + + return collection; + } + + /** + * Moves the underlying repository item to the indicated destination. + * + * @param destination + * @throws DavException + * @see DavResource#move(DavResource) + * @see javax.jcr.Session#move(String, String) + */ + @Override + public void move(DavResource destination) throws DavException { + if (!exists()) { + throw new DavException(DavServletResponse.SC_NOT_FOUND); + } + DavResourceLocator destLocator = destination.getLocator(); + if (!getLocator().isSameWorkspace(destLocator)) { + throw new DavException(DavServletResponse.SC_FORBIDDEN); + } + + try { + String itemPath = getLocator().getRepositoryPath(); + String destItemPath = destination.getLocator().getRepositoryPath(); + if (getTransactionId() == null) { + // if not part of a transaction directly import on workspace + getRepositorySession().getWorkspace().move(itemPath, destItemPath); + } else { + // changes will not be persisted unless the tx is completed. + getRepositorySession().move(itemPath, destItemPath); + } + // no use in calling 'complete' that would fail for a moved item anyway. + } catch (PathNotFoundException e) { + // according to rfc 2518 + throw new DavException(DavServletResponse.SC_CONFLICT, e.getMessage()); + } catch (RepositoryException e) { + throw new JcrDavException(e); + } + } + + /** + * Copies the underlying repository item to the indicated destination. If + * the locator of the specified destination resource indicates a different + * workspace, {@link Workspace#copy(String, String, String)} is used to perform + * the copy operation, {@link Workspace#copy(String, String)} otherwise. + *

+ * Note, that this implementation does not support shallow copy. + * + * @param destination + * @param shallow + * @throws DavException + * @see DavResource#copy(DavResource, boolean) + * @see Workspace#copy(String, String) + * @see Workspace#copy(String, String, String) + */ + @Override + public void copy(DavResource destination, boolean shallow) throws DavException { + if (!exists()) { + throw new DavException(DavServletResponse.SC_NOT_FOUND); + } + // TODO: support shallow and deep copy is required by RFC 2518 + if (shallow) { + throw new DavException(DavServletResponse.SC_FORBIDDEN, "Unable to perform shallow copy."); + } + + try { + String itemPath = getLocator().getRepositoryPath(); + String destItemPath = destination.getLocator().getRepositoryPath(); + Workspace workspace = getRepositorySession().getWorkspace(); + if (getLocator().isSameWorkspace(destination.getLocator())) { + workspace.copy(itemPath, destItemPath); + } else { + log.error("Copy between workspaces is not yet implemented (src: '" + getHref() + "', dest: '" + destination.getHref() + "')"); + throw new DavException(DavServletResponse.SC_NOT_IMPLEMENTED); + } + } catch (PathNotFoundException e) { + // according to RFC 2518, should not occur + throw new DavException(DavServletResponse.SC_NOT_FOUND, e.getMessage()); + } catch (RepositoryException e) { + throw new JcrDavException(e); + } + } + + //--------------------------------------< ObservationResource interface >--- + /** + * @see ObservationResource#init(SubscriptionManager) + */ + @Override + public void init(SubscriptionManager subsMgr) { + this.subsMgr = subsMgr; + } + + /** + * @see ObservationResource#subscribe(org.apache.jackrabbit.webdav.observation.SubscriptionInfo, String) + * @see SubscriptionManager#subscribe(org.apache.jackrabbit.webdav.observation.SubscriptionInfo, String, org.apache.jackrabbit.webdav.observation.ObservationResource) + */ + @Override + public Subscription subscribe(SubscriptionInfo info, String subscriptionId) + throws DavException { + return subsMgr.subscribe(info, subscriptionId, this); + } + + /** + * @see ObservationResource#unsubscribe(String) + * @see SubscriptionManager#unsubscribe(String, org.apache.jackrabbit.webdav.observation.ObservationResource) + */ + @Override + public void unsubscribe(String subscriptionId) throws DavException { + subsMgr.unsubscribe(subscriptionId, this); + } + + /** + * @see ObservationResource#poll(String, long) + * @see SubscriptionManager#poll(String, long, org.apache.jackrabbit.webdav.observation.ObservationResource) + */ + @Override + public EventDiscovery poll(String subscriptionId, long timeout) throws DavException { + return subsMgr.poll(subscriptionId, timeout, this); + } + + //-------------------------------------------------------------------------- + /** + * Initialize the {@link org.apache.jackrabbit.webdav.lock.SupportedLock} property + * with entries that are valid for any type item resources. + * + * @see org.apache.jackrabbit.webdav.lock.SupportedLock + * @see org.apache.jackrabbit.webdav.transaction.TxLockEntry + * @see AbstractResource#initLockSupport() + */ + @Override + protected void initLockSupport() { + if (exists()) { + // add supported lock entries for local and eventually for global + // transaction locks + supportedLock.addEntry(new TxLockEntry(true)); + supportedLock.addEntry(new TxLockEntry(false)); + } + } + + @Override + protected void initPropertyNames() { + super.initPropertyNames(); + if (exists()) { + names.addAll(JcrDavPropertyNameSet.EXISTING_ITEM_BASE_SET); + try { + if (item.getDepth() > 0) { + names.add(JCR_PARENT); + } + } catch (RepositoryException e) { + log.warn("Error while accessing node depth: " + e.getMessage()); + } + if (item.isNew()) { + names.add(JCR_ISNEW); + } else if (item.isModified()) { + names.add(JCR_ISMODIFIED); + } + } else { + names.addAll(JcrDavPropertyNameSet.ITEM_BASE_SET); + } + } + + /** + * Fill the property set for this resource. + */ + @Override + protected void initProperties() { + super.initProperties(); + if (exists()) { + try { + properties.add(new DefaultDavProperty(JCR_NAME, item.getName())); + properties.add(new DefaultDavProperty(JCR_PATH, item.getPath())); + int depth = item.getDepth(); + properties.add(new DefaultDavProperty(JCR_DEPTH, String.valueOf(depth))); + // add href-property for the items parent unless its the root item + if (depth > 0) { + String parentHref = getLocatorFromItem(item.getParent()).getHref(true); + properties.add(new HrefProperty(JCR_PARENT, parentHref, false)); + } + } catch (RepositoryException e) { + // should not get here + log.error("Error while accessing jcr properties: " + e.getMessage()); + } + } + } + + /** + * @return href of the workspace or null if this resource + * does not represent a repository item. + * + * @see AbstractResource#getWorkspaceHref() + */ + @Override + protected String getWorkspaceHref() { + String workspaceHref = null; + DavResourceLocator locator = getLocator(); + if (locator != null && locator.getWorkspacePath() != null) { + String wspPath = locator.getWorkspacePath(); + DavResourceLocator wspLocator = locator.getFactory().createResourceLocator(locator.getPrefix(), wspPath, wspPath); + workspaceHref = wspLocator.getHref(true); + } + log.debug(workspaceHref); + return workspaceHref; + } + + /** + * If this resource exists but does not contain a transaction id, complete + * will try to persist any modifications present on the underlying + * repository item. + * + * @throws DavException if calling {@link Item#save()} fails + */ + void complete() throws DavException { + if (exists() && getTransactionId() == null) { + try { + if (item.isModified()) { + item.save(); + } + } catch (RepositoryException e) { + // this includes LockException, ConstraintViolationException etc. not detected before + log.error("Error while completing request: " + e.getMessage() +" -> reverting changes."); + try { + item.refresh(false); + } catch (RepositoryException re) { + log.error("Error while reverting changes: " + re.getMessage()); + } + throw new JcrDavException(e); + } + } + } + + /** + * Retrieves the last segment of the given path and removes the index if + * present. + * + * @param itemPath + * @return valid jcr item name + */ + protected static String getItemName(String itemPath) { + if (itemPath == null) { + throw new IllegalArgumentException("Cannot retrieve name from a 'null' item path."); + } + // retrieve the last part of the path + String name = Text.getName(itemPath); + // remove index + if (name.endsWith("]")) { + name = name.substring(0, name.lastIndexOf('[')); + } + return name; + } +} Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/AbstractItemResource.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/webdav/jcr/AbstractResource.java =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/AbstractResource.java (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/AbstractResource.java (working copy) @@ -0,0 +1,861 @@ +/* + * 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.webdav.jcr; + +import org.apache.jackrabbit.server.io.IOUtil; +import org.apache.jackrabbit.webdav.DavException; +import org.apache.jackrabbit.webdav.DavLocatorFactory; +import org.apache.jackrabbit.webdav.DavResource; +import org.apache.jackrabbit.webdav.DavResourceFactory; +import org.apache.jackrabbit.webdav.DavResourceLocator; +import org.apache.jackrabbit.webdav.DavServletResponse; +import org.apache.jackrabbit.webdav.DavSession; +import org.apache.jackrabbit.webdav.MultiStatus; +import org.apache.jackrabbit.webdav.MultiStatusResponse; +import org.apache.jackrabbit.webdav.WebdavRequest; +import org.apache.jackrabbit.webdav.WebdavRequestContext; +import org.apache.jackrabbit.webdav.DavCompliance; +import org.apache.jackrabbit.webdav.jcr.property.JcrDavPropertyNameSet; +import org.apache.jackrabbit.webdav.util.HttpDateFormat; +import org.apache.jackrabbit.webdav.jcr.search.SearchResourceImpl; +import org.apache.jackrabbit.webdav.jcr.transaction.TxLockManagerImpl; +import org.apache.jackrabbit.webdav.jcr.version.report.NodeTypesReport; +import org.apache.jackrabbit.webdav.jcr.version.report.LocateByUuidReport; +import org.apache.jackrabbit.webdav.jcr.version.report.RegisteredNamespacesReport; +import org.apache.jackrabbit.webdav.jcr.version.report.RepositoryDescriptorsReport; +import org.apache.jackrabbit.webdav.lock.ActiveLock; +import org.apache.jackrabbit.webdav.lock.LockDiscovery; +import org.apache.jackrabbit.webdav.lock.LockInfo; +import org.apache.jackrabbit.webdav.lock.LockManager; +import org.apache.jackrabbit.webdav.lock.Scope; +import org.apache.jackrabbit.webdav.lock.SupportedLock; +import org.apache.jackrabbit.webdav.lock.Type; +import org.apache.jackrabbit.webdav.property.DavProperty; +import org.apache.jackrabbit.webdav.property.DavPropertyName; +import org.apache.jackrabbit.webdav.property.DavPropertyNameSet; +import org.apache.jackrabbit.webdav.property.DavPropertySet; +import org.apache.jackrabbit.webdav.property.DefaultDavProperty; +import org.apache.jackrabbit.webdav.property.HrefProperty; +import org.apache.jackrabbit.webdav.property.ResourceType; +import org.apache.jackrabbit.webdav.property.PropEntry; +import org.apache.jackrabbit.webdav.search.QueryGrammerSet; +import org.apache.jackrabbit.webdav.search.SearchInfo; +import org.apache.jackrabbit.webdav.search.SearchResource; +import org.apache.jackrabbit.webdav.server.WebdavRequestContextHolder; +import org.apache.jackrabbit.webdav.transaction.TransactionConstants; +import org.apache.jackrabbit.webdav.transaction.TransactionInfo; +import org.apache.jackrabbit.webdav.transaction.TransactionResource; +import org.apache.jackrabbit.webdav.transaction.TxLockManager; +import org.apache.jackrabbit.webdav.version.DeltaVConstants; +import org.apache.jackrabbit.webdav.version.DeltaVResource; +import org.apache.jackrabbit.webdav.version.OptionsInfo; +import org.apache.jackrabbit.webdav.version.OptionsResponse; +import org.apache.jackrabbit.webdav.version.SupportedMethodSetProperty; +import org.apache.jackrabbit.webdav.version.report.Report; +import org.apache.jackrabbit.webdav.version.report.ReportInfo; +import org.apache.jackrabbit.webdav.version.report.ReportType; +import org.apache.jackrabbit.webdav.version.report.SupportedReportSetProperty; +import org.apache.jackrabbit.webdav.xml.DomUtil; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.w3c.dom.Element; + +import javax.jcr.Item; +import javax.jcr.RepositoryException; +import javax.jcr.Session; +import javax.jcr.observation.EventListener; +import javax.jcr.observation.Event; +import javax.jcr.observation.EventIterator; +import javax.xml.parsers.ParserConfigurationException; + +import java.util.ArrayList; +import java.util.Date; +import java.util.Iterator; +import java.util.List; + +/** + * AbstractResource provides functionality common to all + * resources. + */ +abstract class AbstractResource implements DavResource, TransactionResource, + DeltaVResource, SearchResource { + + private static Logger log = LoggerFactory.getLogger(AbstractResource.class); + + private static final String COMPLIANCE_CLASSES = + DavCompliance.concatComplianceClasses(new String[] { + DavCompliance._1_, + DavCompliance._2_, + DavCompliance._3_, + DavCompliance.VERSION_CONTROL, + DavCompliance.VERSION_HISTORY, + DavCompliance.CHECKOUT_IN_PLACE, + DavCompliance.LABEL, + DavCompliance.MERGE, + DavCompliance.UPDATE, + DavCompliance.WORKSPACE + }); + + private final DavResourceLocator locator; + private final JcrDavSession session; + private final DavResourceFactory factory; + + private TxLockManagerImpl txMgr; + private String transactionId; + + protected boolean initedProps; + protected DavPropertySet properties = new DavPropertySet(); + protected DavPropertyNameSet names; + protected SupportedLock supportedLock = new SupportedLock(); + protected SupportedReportSetProperty supportedReports = new SupportedReportSetProperty(); + + /** + * Create a new AbstractResource + * + * @param locator + * @param session + * @param factory + */ + AbstractResource(DavResourceLocator locator, JcrDavSession session, + DavResourceFactory factory) { + if (session == null) { + throw new IllegalArgumentException("Creating AbstractItemResource: DavSession must not be null and must provide a JCR session."); + } + this.locator = locator; + this.session = session; + this.factory = factory; + } + + /** + * Returns a string listing the compliance classes for this resource as it + * is required for the DAV response header. This includes DAV 1, 2 which + * is supported by all derived classes as well as a subset of the + * classes defined by DeltaV: version-control, version-history, checkout-in-place, + * label, merge, update and workspace.
+ * Those compliance classes are added as required by RFC3253 since all + * all resources in the jcr-server support at least the reporting and some + * basic versioning functionality. + * + * @return string listing the compliance classes. + * @see org.apache.jackrabbit.webdav.DavResource#getComplianceClass() + */ + @Override + public String getComplianceClass() { + return COMPLIANCE_CLASSES; + } + + /** + * @see org.apache.jackrabbit.webdav.DavResource#getLocator() + */ + @Override + public DavResourceLocator getLocator() { + return locator; + } + + /** + * Returns the path of the underlying repository item or the item to + * be created (PUT/MKCOL). If the resource exists but does not represent + * a repository item null is returned. + * + * @return path of the underlying repository item. + * @see DavResource#getResourcePath() + * @see org.apache.jackrabbit.webdav.DavResourceLocator#getResourcePath() + */ + @Override + public String getResourcePath() { + return locator.getResourcePath(); + } + + /** + * @see DavResource#getHref() + * @see DavResourceLocator#getHref(boolean) + */ + @Override + public String getHref() { + return locator.getHref(isCollection()); + } + + /** + * @see org.apache.jackrabbit.webdav.DavResource#getPropertyNames() + */ + @Override + public DavPropertyName[] getPropertyNames() { + initPropertyNames(); + return names.getContent().toArray(new DavPropertyName[names.getContentSize()]); + } + + /** + * @see org.apache.jackrabbit.webdav.DavResource#getProperty(org.apache.jackrabbit.webdav.property.DavPropertyName) + */ + @Override + public DavProperty getProperty(DavPropertyName name) { + DavProperty prop = getProperties().get(name); + if (prop == null) { + if (DeltaVConstants.SUPPORTED_METHOD_SET.equals(name)) { + prop = new SupportedMethodSetProperty(getSupportedMethods().split(",\\s")); + } else if (DeltaVConstants.SUPPORTED_REPORT_SET.equals(name)) { + prop = supportedReports; + } else if (DeltaVConstants.CREATOR_DISPLAYNAME.equals(name)) { + // DAV:creator-displayname default value : not available + prop = new DefaultDavProperty(DeltaVConstants.CREATOR_DISPLAYNAME, getCreatorDisplayName(), true); + } else if (DeltaVConstants.COMMENT.equals(name)) { + // DAV:comment not value available from jcr + prop = new DefaultDavProperty(DeltaVConstants.COMMENT, null, true); + } else if (DeltaVConstants.WORKSPACE.equals(name)) { + // 'workspace' property as defined by RFC 3253 + String workspaceHref = getWorkspaceHref(); + if (workspaceHref != null) { + prop = new HrefProperty(DeltaVConstants.WORKSPACE, workspaceHref, true); + } + } + } + + // TODO: required supported-live-property-set + return prop; + } + + /** + * @see org.apache.jackrabbit.webdav.DavResource#getProperties() + */ + @Override + public DavPropertySet getProperties() { + if (!initedProps) { + initProperties(); + } + return properties; + } + + /** + * Throws {@link DavServletResponse#SC_METHOD_NOT_ALLOWED} + * + * @param property + * @throws DavException Always throws {@link DavServletResponse#SC_METHOD_NOT_ALLOWED} + * @see org.apache.jackrabbit.webdav.DavResource#setProperty(org.apache.jackrabbit.webdav.property.DavProperty) + */ + @Override + public void setProperty(DavProperty property) throws DavException { + throw new DavException(DavServletResponse.SC_METHOD_NOT_ALLOWED); + } + + /** + * Throws {@link DavServletResponse#SC_METHOD_NOT_ALLOWED} + * + * @param propertyName + * @throws DavException Always throws {@link DavServletResponse#SC_METHOD_NOT_ALLOWED} + * @see org.apache.jackrabbit.webdav.DavResource#removeProperty(org.apache.jackrabbit.webdav.property.DavPropertyName) + */ + @Override + public void removeProperty(DavPropertyName propertyName) throws DavException { + throw new DavException(DavServletResponse.SC_METHOD_NOT_ALLOWED); + } + + /** + * Throws {@link DavServletResponse#SC_METHOD_NOT_ALLOWED} + * + * @see DavResource#alterProperties(List) + */ + @Override + public MultiStatusResponse alterProperties(List changeList) throws DavException { + throw new DavException(DavServletResponse.SC_METHOD_NOT_ALLOWED); + } + + /** + * Throws {@link DavServletResponse#SC_METHOD_NOT_ALLOWED} + * + * @param destination + * @throws DavException Always throws {@link DavServletResponse#SC_METHOD_NOT_ALLOWED} + * @see DavResource#move(org.apache.jackrabbit.webdav.DavResource) + */ + @Override + public void move(DavResource destination) throws DavException { + throw new DavException(DavServletResponse.SC_METHOD_NOT_ALLOWED); + } + + /** + * Throws {@link DavServletResponse#SC_METHOD_NOT_ALLOWED} + * + * @param destination + * @param shallow + * @throws DavException Always throws {@link DavServletResponse#SC_METHOD_NOT_ALLOWED} + * @see DavResource#copy(org.apache.jackrabbit.webdav.DavResource, boolean) + */ + @Override + public void copy(DavResource destination, boolean shallow) throws DavException { + throw new DavException(DavServletResponse.SC_METHOD_NOT_ALLOWED); + } + + + /** + * Returns true, if the {@link SupportedLock} property contains an entry + * with the given type and scope. By default resources allow for {@link org.apache.jackrabbit.webdav.transaction.TransactionConstants#XML_TRANSACTION + * transaction} lock only. + * + * @param type + * @param scope + * @return true if this resource may be locked by the given type and scope. + * @see DavResource#isLockable(org.apache.jackrabbit.webdav.lock.Type, org.apache.jackrabbit.webdav.lock.Scope) + */ + @Override + public boolean isLockable(Type type, Scope scope) { + return supportedLock.isSupportedLock(type, scope); + } + + /** + * Returns true if this resource has a lock applied with the given type and scope. + * + * @param type + * @param scope + * @return true if this resource has a lock applied with the given type and scope. + * @see DavResource#hasLock(Type, Scope) + */ + @Override + public boolean hasLock(Type type, Scope scope) { + return getLock(type, scope) != null; + } + + /** + * @see DavResource#getLock(Type, Scope) + */ + @Override + public ActiveLock getLock(Type type, Scope scope) { + ActiveLock lock = null; + if (TransactionConstants.TRANSACTION.equals(type)) { + lock = txMgr.getLock(type, scope, this); + } + return lock; + } + + /** + * @see DavResource#getLocks() + * todo improve.... + */ + @Override + public ActiveLock[] getLocks() { + List locks = new ArrayList(); + // tx locks + ActiveLock l = getLock(TransactionConstants.TRANSACTION, TransactionConstants.LOCAL); + if (l != null) { + locks.add(l); + } + l = getLock(TransactionConstants.TRANSACTION, TransactionConstants.GLOBAL); + if (l != null) { + locks.add(l); + } + // write lock (either exclusive or session-scoped). + l = getLock(Type.WRITE, Scope.EXCLUSIVE); + if (l != null) { + locks.add(l); + } else { + l = getLock(Type.WRITE, ItemResourceConstants.EXCLUSIVE_SESSION); + if (l != null) { + locks.add(l); + } + } + return locks.toArray(new ActiveLock[locks.size()]); + } + + /** + * @see DavResource#lock(org.apache.jackrabbit.webdav.lock.LockInfo) + */ + @Override + public ActiveLock lock(LockInfo reqLockInfo) throws DavException { + if (isLockable(reqLockInfo.getType(), reqLockInfo.getScope())) { + return txMgr.createLock(reqLockInfo, this); + } else { + throw new DavException(DavServletResponse.SC_PRECONDITION_FAILED); + } + } + + /** + * Only transaction lock may be available on this resource. + * + * @param info + * @param lockToken + * @throws DavException + * @see DavResource#refreshLock(org.apache.jackrabbit.webdav.lock.LockInfo, String) + */ + @Override + public ActiveLock refreshLock(LockInfo info, String lockToken) throws DavException { + return txMgr.refreshLock(info, lockToken, this); + } + + /** + * Throws {@link DavServletResponse#SC_METHOD_NOT_ALLOWED} since only transaction + * locks may be present on this resource, that need to be released by calling + * {@link TransactionResource#unlock(String, org.apache.jackrabbit.webdav.transaction.TransactionInfo)}. + * + * @param lockToken + * @throws DavException Always throws {@link DavServletResponse#SC_METHOD_NOT_ALLOWED} + */ + @Override + public void unlock(String lockToken) throws DavException { + throw new DavException(DavServletResponse.SC_PRECONDITION_FAILED); + } + + /** + * @see DavResource#addLockManager(org.apache.jackrabbit.webdav.lock.LockManager) + */ + @Override + public void addLockManager(LockManager lockMgr) { + if (lockMgr instanceof TxLockManagerImpl) { + txMgr = (TxLockManagerImpl) lockMgr; + } + } + + /** + * @see org.apache.jackrabbit.webdav.DavResource#getFactory() + */ + @Override + public DavResourceFactory getFactory() { + return factory; + } + + //-------------------------------------------------------------------------- + /** + * @see org.apache.jackrabbit.webdav.transaction.TransactionResource#getSession() + * @see org.apache.jackrabbit.webdav.observation.ObservationResource#getSession() + */ + @Override + public DavSession getSession() { + return session; + } + + //--------------------------------------< TransactionResource interface >--- + /** + * @see TransactionResource#init(TxLockManager, String) + */ + @Override + public void init(TxLockManager txMgr, String transactionId) { + this.txMgr = (TxLockManagerImpl) txMgr; + this.transactionId = transactionId; + } + + /** + * @see TransactionResource#unlock(String, org.apache.jackrabbit.webdav.transaction.TransactionInfo) + */ + @Override + public void unlock(String lockToken, TransactionInfo tInfo) throws DavException { + txMgr.releaseLock(tInfo, lockToken, this); + } + + /** + * @see TransactionResource#getTransactionId() + */ + @Override + public String getTransactionId() { + return transactionId; + } + + //-------------------------------------------< DeltaVResource interface >--- + /** + * @param optionsInfo + * @return object to be used in the OPTIONS response body or null + * @see DeltaVResource#getOptionResponse(org.apache.jackrabbit.webdav.version.OptionsInfo) + */ + @Override + public OptionsResponse getOptionResponse(OptionsInfo optionsInfo) { + OptionsResponse oR = null; + if (optionsInfo != null) { + oR = new OptionsResponse(); + // currently only DAV:version-history-collection-set and + // DAV:workspace-collection-set is supported. + if (optionsInfo.containsElement(DeltaVConstants.XML_VH_COLLECTION_SET, DeltaVConstants.NAMESPACE)) { + String[] hrefs = new String[] { + getLocatorFromItemPath(ItemResourceConstants.VERSIONSTORAGE_PATH).getHref(true) + }; + oR.addEntry(DeltaVConstants.XML_VH_COLLECTION_SET, DeltaVConstants.NAMESPACE, hrefs); + } + if (optionsInfo.containsElement(DeltaVConstants.XML_WSP_COLLECTION_SET, DeltaVConstants.NAMESPACE)) { + // workspaces cannot be created anywhere. + oR.addEntry(DeltaVConstants.XML_WSP_COLLECTION_SET, DeltaVConstants.NAMESPACE, new String[0]); + } + } + return oR; + } + + /** + * @param reportInfo + * @return the requested report + * @throws DavException + * @see DeltaVResource#getReport(org.apache.jackrabbit.webdav.version.report.ReportInfo) + */ + @Override + public Report getReport(ReportInfo reportInfo) throws DavException { + if (reportInfo == null) { + throw new DavException(DavServletResponse.SC_BAD_REQUEST, "A REPORT request must provide a valid XML request body."); + } + if (!exists()) { + throw new DavException(DavServletResponse.SC_NOT_FOUND); + } + + if (!supportedReports.isSupportedReport(reportInfo)) { + Element condition = null; + try { + condition = DomUtil.createDocument().createElementNS("DAV:", "supported-report"); + } catch (ParserConfigurationException ex) { + // we don't care THAT much + } + throw new DavException(DavServletResponse.SC_CONFLICT, + "Unknown report '" + reportInfo.getReportName() + "' requested.", null, condition); + } + + return ReportType.getType(reportInfo).createReport(this, reportInfo); + } + + /** + * The JCR api does not provide methods to create new workspaces. Calling + * addWorkspace on this resource will always fail. + * + * @param workspace + * @throws DavException Always throws. + * @see DeltaVResource#addWorkspace(org.apache.jackrabbit.webdav.DavResource) + */ + @Override + public void addWorkspace(DavResource workspace) throws DavException { + throw new DavException(DavServletResponse.SC_FORBIDDEN); + } + + /** + * Return an array of DavResource objects that are referenced + * by the property with the specified name. + * + * @param hrefPropertyName + * @return array of DavResources + * @throws DavException + * @see DeltaVResource#getReferenceResources(org.apache.jackrabbit.webdav.property.DavPropertyName) + */ + @Override + public DavResource[] getReferenceResources(DavPropertyName hrefPropertyName) throws DavException { + DavProperty prop = getProperty(hrefPropertyName); + if (prop == null || !(prop instanceof HrefProperty)) { + throw new DavException(DavServletResponse.SC_CONFLICT, "Unknown Href-Property '" + hrefPropertyName + "' on resource " + getResourcePath()); + } + + List hrefs = ((HrefProperty)prop).getHrefs(); + DavResource[] refResources = new DavResource[hrefs.size()]; + Iterator hrefIter = hrefs.iterator(); + int i = 0; + while (hrefIter.hasNext()) { + refResources[i] = getResourceFromHref(hrefIter.next()); + i++; + } + return refResources; + } + + /** + * Retrieve the DavResource object that is represented by + * the given href String. + * + * @param href + * @return DavResource object + */ + private DavResource getResourceFromHref(String href) throws DavException { + // build a new locator: remove trailing prefix + DavResourceLocator locator = getLocator(); + String prefix = locator.getPrefix(); + DavResourceLocator loc = locator.getFactory().createResourceLocator(prefix, href); + + // create a new resource object + try { + DavResource res; + if (getRepositorySession().itemExists(loc.getRepositoryPath())) { + res = createResourceFromLocator(loc); + } else { + throw new DavException(DavServletResponse.SC_NOT_FOUND); + } + return res; + } catch (RepositoryException e) { + throw new JcrDavException(e); + } + } + + //-------------------------------------------< SearchResource interface >--- + /** + * @return + * @see org.apache.jackrabbit.webdav.search.SearchResource#getQueryGrammerSet() + */ + @Override + public QueryGrammerSet getQueryGrammerSet() { + return new SearchResourceImpl(getLocator(), session).getQueryGrammerSet(); + } + + /** + * @param sInfo + * @return + * @throws DavException + * @see SearchResource#search(org.apache.jackrabbit.webdav.search.SearchInfo) + */ + @Override + public MultiStatus search(SearchInfo sInfo) throws DavException { + return new SearchResourceImpl(getLocator(), session).search(sInfo); + } + + //-------------------------------------------------------------------------- + /** + * Property names common to all resources. + */ + protected void initPropertyNames() { + names = new DavPropertyNameSet(JcrDavPropertyNameSet.BASE_SET); + } + + /** + * Fill the set of default properties + */ + protected void initProperties() { + if (getDisplayName() != null) { + properties.add(new DefaultDavProperty(DavPropertyName.DISPLAYNAME, getDisplayName())); + } + if (isCollection()) { + properties.add(new ResourceType(ResourceType.COLLECTION)); + // Windows XP support + properties.add(new DefaultDavProperty(DavPropertyName.ISCOLLECTION, "1")); + } else { + properties.add(new ResourceType(ResourceType.DEFAULT_RESOURCE)); + // Windows XP support + properties.add(new DefaultDavProperty(DavPropertyName.ISCOLLECTION, "0")); + } + // todo: add etag + + // default last modified + String lastModified = IOUtil.getLastModified(getModificationTime()); + properties.add(new DefaultDavProperty(DavPropertyName.GETLASTMODIFIED, lastModified)); + + // default creation time + properties.add(new DefaultDavProperty(DavPropertyName.CREATIONDATE, getCreationDate())); + + // supported lock property + properties.add(supportedLock); + + // set current lock information. If no lock is applied to this resource, + // an empty xlockdiscovery will be returned in the response. + properties.add(new LockDiscovery(getLocks())); + + // name of the jcr workspace + properties.add(new DefaultDavProperty(ItemResourceConstants.JCR_WORKSPACE_NAME, + getRepositorySession().getWorkspace().getName())); + } + + /** + * Create a new DavResource from the given locator. + * @param loc + * @return new DavResource + * @throws org.apache.jackrabbit.webdav.DavException + */ + protected DavResource createResourceFromLocator(DavResourceLocator loc) + throws DavException { + DavResource res = factory.createResource(loc, session); + if (res instanceof AbstractResource) { + ((AbstractResource)res).transactionId = this.transactionId; + } + return res; + } + + /** + * Build a DavResourceLocator from the given itemPath path. + * + * @param itemPath + * @return a new DavResourceLocator + * @see DavLocatorFactory#createResourceLocator(String, String, String) + */ + protected DavResourceLocator getLocatorFromItemPath(String itemPath) { + DavResourceLocator loc = locator.getFactory().createResourceLocator(locator.getPrefix(), locator.getWorkspacePath(), itemPath, false); + return loc; + } + + /** + * Build a new {@link DavResourceLocator} from the given repository item. + * + * @param repositoryItem + * @return a new locator for the specified item. + * @see #getLocatorFromItemPath(String) + */ + protected DavResourceLocator getLocatorFromItem(Item repositoryItem) { + String itemPath = null; + try { + if (repositoryItem != null) { + itemPath = repositoryItem.getPath(); + } + } catch (RepositoryException e) { + // ignore: should not occur + log.warn(e.getMessage()); + } + return getLocatorFromItemPath(itemPath); + } + + /** + * Shortcut for getSession().getRepositorySession() + * + * @return repository session present in the {@link AbstractResource#session}. + */ + protected Session getRepositorySession() { + return session.getRepositorySession(); + } + + /** + * Define the set of locks supported by this resource. + * + * @see org.apache.jackrabbit.webdav.lock.SupportedLock + */ + abstract protected void initLockSupport(); + + /** + * Define the set of reports supported by this resource. + * + * @see org.apache.jackrabbit.webdav.version.report.SupportedReportSetProperty + */ + /** + * Define the set of reports supported by this resource. + * + * @see org.apache.jackrabbit.webdav.version.report.SupportedReportSetProperty + * @see AbstractResource#initSupportedReports() + */ + protected void initSupportedReports() { + if (exists()) { + supportedReports = new SupportedReportSetProperty(new ReportType[] { + ReportType.EXPAND_PROPERTY, + NodeTypesReport.NODETYPES_REPORT, + LocateByUuidReport.LOCATE_BY_UUID_REPORT, + RegisteredNamespacesReport.REGISTERED_NAMESPACES_REPORT, + RepositoryDescriptorsReport.REPOSITORY_DESCRIPTORS_REPORT + }); + } + } + + /** + * Retrieve the href of the workspace the current session belongs to. + * + * @return href of the workspace + */ + abstract protected String getWorkspaceHref(); + + /** + * Returns the display name of the creator which is used for the protected + * {@link DeltaVConstants#CREATOR_DISPLAYNAME} property. + * + * @return always null; subclasses may provide a regular value. + */ + protected String getCreatorDisplayName() { + return null; + } + + /** + * Returns the creation date which is used for the + * {@link DavPropertyName#CREATIONDATE} property. + * + * @return a dummy date; subclasses may provide a reasonable value. + */ + protected String getCreationDate() { + return HttpDateFormat.creationDateFormat().format(new Date(0)); + } + + /** + * Normalize the resource {@code href}. For example, remove contextPath prefix if found. + * @param href resource href + * @return normalized resource {@code href} + */ + protected String normalizeResourceHref(final String href) { + if (href == null) { + return href; + } + + final WebdavRequestContext requestContext = WebdavRequestContextHolder.getContext(); + final WebdavRequest request = (requestContext != null) ? requestContext.getRequest() : null; + + if (request == null) { + log.error("WebdavRequest is unavailable in the current execution context."); + return href; + } + + final String contextPath = request.getContextPath(); + + if (!contextPath.isEmpty() && href.startsWith(contextPath)) { + return href.substring(contextPath.length()); + } + + return href; + } + + //-------------------------------------------------------------------------- + /** + * Register the specified event listener with the observation manager present + * the repository session. + * + * @param listener + * @param nodePath + * @throws javax.jcr.RepositoryException + */ + void registerEventListener(EventListener listener, String nodePath) throws RepositoryException { + getRepositorySession().getWorkspace().getObservationManager().addEventListener(listener, EListener.ALL_EVENTS, nodePath, true, null, null, false); + } + + /** + * Unregister the specified event listener with the observation manager present + * the repository session. + * + * @param listener + * @throws javax.jcr.RepositoryException + */ + void unregisterEventListener(EventListener listener) throws RepositoryException { + getRepositorySession().getWorkspace().getObservationManager().removeEventListener(listener); + } + + //------------------------------------------------------< inner classes >--- + /** + * Simple EventListener that creates a new {@link org.apache.jackrabbit.webdav.MultiStatusResponse} object + * for each event and adds it to the specified {@link org.apache.jackrabbit.webdav.MultiStatus}. + */ + class EListener implements EventListener { + + private static final int ALL_EVENTS = Event.NODE_ADDED + | Event.NODE_REMOVED + | Event.PROPERTY_ADDED + | Event.PROPERTY_CHANGED + | Event.PROPERTY_REMOVED + | Event.NODE_MOVED + | Event.PERSIST; + + private final DavPropertyNameSet propNameSet; + private MultiStatus ms; + + EListener(DavPropertyNameSet propNameSet, MultiStatus ms) { + this.propNameSet = propNameSet; + this.ms = ms; + } + + /** + * @see EventListener#onEvent(javax.jcr.observation.EventIterator) + */ + @Override + public void onEvent(EventIterator events) { + while (events.hasNext()) { + try { + Event e = events.nextEvent(); + DavResourceLocator loc = getLocatorFromItemPath(e.getPath()); + DavResource res = createResourceFromLocator(loc); + ms.addResponse(new MultiStatusResponse(res, propNameSet)); + + } catch (DavException e) { + // should not occur + log.error("Error while building MultiStatusResponse from Event: " + e.getMessage()); + } catch (RepositoryException e) { + // should not occur + log.error("Error while building MultiStatusResponse from Event: " + e.getMessage()); + } + } + } + } +} Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/AbstractResource.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/webdav/jcr/DavLocatorFactoryImpl.java =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/DavLocatorFactoryImpl.java (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/DavLocatorFactoryImpl.java (working copy) @@ -0,0 +1,94 @@ +/* + * 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.webdav.jcr; + +import org.apache.jackrabbit.webdav.AbstractLocatorFactory; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * DavLocatorFactoryImpl... + */ +public class DavLocatorFactoryImpl extends AbstractLocatorFactory { + + private static Logger log = LoggerFactory.getLogger(DavLocatorFactoryImpl.class); + + /** + * Create a new factory + * + * @param pathPrefix Prefix, that needs to be removed in order to retrieve + * the repository path from a given href. + */ + public DavLocatorFactoryImpl(String pathPrefix) { + super(pathPrefix); + } + + //---------------------------------------------------------------------- + /** + * + * @param resourcePath + * @param wspPath + * @return + * @see AbstractLocatorFactory#getRepositoryPath(String, String) + */ + @Override + protected String getRepositoryPath(String resourcePath, String wspPath) { + if (resourcePath == null) { + return null; + } + if (resourcePath.equals(wspPath)) { + // workspace + log.debug("Resource path represents workspace path -> repository path is null."); + return null; + } else { + // a repository item -> remove wspPath + /jcr:root + String pfx = wspPath + ItemResourceConstants.ROOT_ITEM_RESOURCEPATH; + if (resourcePath.startsWith(pfx)) { + String repositoryPath = resourcePath.substring(pfx.length()); + return (repositoryPath.length() == 0) ? ItemResourceConstants.ROOT_ITEM_PATH : repositoryPath; + } else { + log.error("Unexpected format of resource path."); + throw new IllegalArgumentException("Unexpected format of resource path: " + resourcePath + " (workspace: " + wspPath + ")"); + } + } + } + + /** + * + * @param repositoryPath + * @param wspPath + * @return + * @see AbstractLocatorFactory#getResourcePath(String, String) + */ + @Override + protected String getResourcePath(String repositoryPath, String wspPath) { + if (wspPath != null) { + StringBuffer b = new StringBuffer(wspPath); + if (repositoryPath != null) { + b.append(ItemResourceConstants.ROOT_ITEM_RESOURCEPATH); + if (!ItemResourceConstants.ROOT_ITEM_PATH.equals(repositoryPath)) { + b.append(repositoryPath); + } + } + return b.toString(); + } else { + log.debug("Workspace path is 'null' -> 'null' resource path"); + return null; + } + } +} + Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/DavLocatorFactoryImpl.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/webdav/jcr/DavResourceFactoryImpl.java =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/DavResourceFactoryImpl.java (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/DavResourceFactoryImpl.java (working copy) @@ -0,0 +1,251 @@ +/* + * 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.webdav.jcr; + +import javax.jcr.AccessDeniedException; +import javax.jcr.Item; +import javax.jcr.Node; +import javax.jcr.PathNotFoundException; +import javax.jcr.RepositoryException; +import javax.jcr.observation.EventJournal; +import javax.jcr.version.Version; +import javax.jcr.version.VersionHistory; +import javax.servlet.http.HttpServletResponse; + +import org.apache.jackrabbit.JcrConstants; +import org.apache.jackrabbit.util.Text; +import org.apache.jackrabbit.webdav.DavException; +import org.apache.jackrabbit.webdav.DavMethods; +import org.apache.jackrabbit.webdav.DavResource; +import org.apache.jackrabbit.webdav.DavResourceFactory; +import org.apache.jackrabbit.webdav.DavResourceLocator; +import org.apache.jackrabbit.webdav.DavServletRequest; +import org.apache.jackrabbit.webdav.DavServletResponse; +import org.apache.jackrabbit.webdav.DavSession; +import org.apache.jackrabbit.webdav.jcr.transaction.TxLockManagerImpl; +import org.apache.jackrabbit.webdav.jcr.version.VersionHistoryItemCollection; +import org.apache.jackrabbit.webdav.jcr.version.VersionItemCollection; +import org.apache.jackrabbit.webdav.observation.ObservationResource; +import org.apache.jackrabbit.webdav.observation.SubscriptionManager; +import org.apache.jackrabbit.webdav.transaction.TransactionDavServletRequest; +import org.apache.jackrabbit.webdav.transaction.TransactionResource; +import org.apache.jackrabbit.webdav.version.DeltaVServletRequest; +import org.apache.jackrabbit.webdav.version.VersionControlledResource; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * DavResourceFactoryImpl... + */ +public class DavResourceFactoryImpl implements DavResourceFactory { + + private static Logger log = LoggerFactory.getLogger(DavResourceFactoryImpl.class); + + private final TxLockManagerImpl txMgr; + private final SubscriptionManager subsMgr; + + /** + * Create a new DavResourceFactoryImpl. + * + * @param txMgr + * @param subsMgr + */ + public DavResourceFactoryImpl(TxLockManagerImpl txMgr, SubscriptionManager subsMgr) { + this.txMgr = txMgr; + this.subsMgr = subsMgr; + } + + /** + * Create a new DavResource from the specified locator and request + * objects. Note, that in contrast to + * {@link #createResource(DavResourceLocator, DavSession)} the locator may + * point to a non-existing resource. + *

+ * If the request contains a {@link org.apache.jackrabbit.webdav.version.DeltaVServletRequest#getLabel() + * Label header}, the resource is build from the indicated + * {@link org.apache.jackrabbit.webdav.version.VersionResource version} instead. + * + * @param locator + * @param request + * @param response + * @return + * @see DavResourceFactory#createResource(org.apache.jackrabbit.webdav.DavResourceLocator, org.apache.jackrabbit.webdav.DavServletRequest, org.apache.jackrabbit.webdav.DavServletResponse) + */ + public DavResource createResource(DavResourceLocator locator, + DavServletRequest request, + DavServletResponse response) throws DavException { + JcrDavSession.checkImplementation(request.getDavSession()); + JcrDavSession session = (JcrDavSession)request.getDavSession(); + + DavResource resource; + String type = request.getParameter("type"); + + if (locator.isRootLocation()) { + // root + resource = new RootCollection(locator, session, this); + } else if ("journal".equals(type) && locator.getResourcePath().equals(locator.getWorkspacePath())) { + // feed/event journal resource + try { + EventJournal ej = session.getRepositorySession().getWorkspace().getObservationManager() + .getEventJournal(); + if (ej == null) { + throw new DavException(HttpServletResponse.SC_NOT_IMPLEMENTED, "event journal not supported"); + } + resource = new EventJournalResourceImpl(ej, locator, session, request, this); + } catch (AccessDeniedException ex) { + // EventJournal only allowed for admin? + throw new DavException(HttpServletResponse.SC_UNAUTHORIZED, ex); + } catch (RepositoryException ex) { + throw new DavException(HttpServletResponse.SC_BAD_REQUEST, ex); + } + } else if (locator.getResourcePath().equals(locator.getWorkspacePath())) { + // workspace resource + resource = new WorkspaceResourceImpl(locator, session, this); + } else { + // resource corresponds to a repository item + try { + resource = createResourceForItem(locator, session); + + Item item = getItem(session, locator); + boolean versionable = item.isNode() && ((Node) item).isNodeType(JcrConstants.MIX_VERSIONABLE); + + /* if the created resource is version-controlled and the request + contains a Label header, the corresponding Version must be used + instead.*/ + if (request instanceof DeltaVServletRequest && versionable) { + String labelHeader = ((DeltaVServletRequest)request).getLabel(); + if (labelHeader != null && DavMethods.isMethodAffectedByLabel(request) && isVersionControlled(resource)) { + Version v = ((Node)item).getVersionHistory().getVersionByLabel(labelHeader); + DavResourceLocator vloc = locator.getFactory().createResourceLocator(locator.getPrefix(), locator.getWorkspacePath(), v.getPath(), false); + resource = new VersionItemCollection(vloc, session, this, v); + } + } + } catch (PathNotFoundException e) { + /* item does not exist yet: create the default resources + Note: MKCOL request forces a collection-resource even if there already + exists a repository-property with the given path. the MKCOL will + in that particular case fail with a 405 (method not allowed).*/ + if (DavMethods.getMethodCode(request.getMethod()) == DavMethods.DAV_MKCOL) { + resource = new VersionControlledItemCollection(locator, session, this, null); + } else { + resource = new DefaultItemResource(locator, session, this, null); + } + } catch (RepositoryException e) { + log.error("Failed to build resource from item '"+ locator.getRepositoryPath() + "'"); + throw new JcrDavException(e); + } + } + + if (request instanceof TransactionDavServletRequest && resource instanceof TransactionResource) { + ((TransactionResource)resource).init(txMgr, ((TransactionDavServletRequest)request).getTransactionId()); + } + if (resource instanceof ObservationResource) { + ((ObservationResource)resource).init(subsMgr); + } + return resource; + } + + /** + * Create a new DavResource from the given locator and session. + * + * @param locator + * @param session + * @return DavResource representing either a repository item or the {@link RootCollection}. + * @throws DavException if the given locator does neither refer to a repository item + * nor does represent the {@link org.apache.jackrabbit.webdav.DavResourceLocator#isRootLocation() + * root location}. + */ + public DavResource createResource(DavResourceLocator locator, DavSession session) throws DavException { + JcrDavSession.checkImplementation(session); + JcrDavSession sessionImpl = (JcrDavSession)session; + + DavResource resource; + if (locator.isRootLocation()) { + resource = new RootCollection(locator, sessionImpl, this); + } else if (locator.getResourcePath().equals(locator.getWorkspacePath())) { + resource = new WorkspaceResourceImpl(locator, sessionImpl, this); + } else { + try { + resource = createResourceForItem(locator, sessionImpl); + } catch (RepositoryException e) { + log.debug("Creating resource for non-existing repository item: " + locator.getRepositoryPath()); + // todo: is this correct? + resource = new VersionControlledItemCollection(locator, sessionImpl, this, null); + } + } + + // todo: currently transactionId is set manually after creation > to be improved. + resource.addLockManager(txMgr); + if (resource instanceof ObservationResource) { + ((ObservationResource)resource).init(subsMgr); + } + return resource; + } + + /** + * Tries to retrieve the repository item defined by the locator's resource + * path and build the corresponding WebDAV resource. The following distinction + * is made between items: Version nodes, VersionHistory nodes, root node, + * unspecified nodes and finally property items. + * + * @param locator + * @param sessionImpl + * @return DavResource representing a repository item. + * @throws RepositoryException if {@link javax.jcr.Session#getItem(String)} fails. + */ + private DavResource createResourceForItem(DavResourceLocator locator, JcrDavSession sessionImpl) throws RepositoryException, DavException { + DavResource resource; + Item item = getItem(sessionImpl, locator); + if (item.isNode()) { + // create special resources for Version and VersionHistory + if (item instanceof Version) { + resource = new VersionItemCollection(locator, sessionImpl, this, item); + } else if (item instanceof VersionHistory) { + resource = new VersionHistoryItemCollection(locator, sessionImpl, this, item); + } else{ + resource = new VersionControlledItemCollection(locator, sessionImpl, this, item); + } + } else { + resource = new DefaultItemResource(locator, sessionImpl, this, item); + } + return resource; + } + + protected Item getItem(JcrDavSession sessionImpl, DavResourceLocator locator) + throws PathNotFoundException, RepositoryException { + return sessionImpl.getRepositorySession().getItem(locator.getRepositoryPath()); + } + + /** + * Returns true, if the specified resource is a {@link VersionControlledResource} + * and has a version history. + * + * @param resource + * @return true if the specified resource is version-controlled. + */ + private boolean isVersionControlled(DavResource resource) { + boolean vc = false; + if (resource instanceof VersionControlledResource) { + try { + vc = ((VersionControlledResource)resource).getVersionHistory() != null; + } catch (DavException e) { + log.debug("Resource '" + resource.getHref() + "' is not version-controlled."); + } + } + return vc; + } +} Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/DavResourceFactoryImpl.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/webdav/jcr/DefaultItemCollection.java =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/DefaultItemCollection.java (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/DefaultItemCollection.java (working copy) @@ -0,0 +1,1168 @@ +/* + * 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.webdav.jcr; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.OutputStream; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; +import java.util.Set; + +import javax.jcr.AccessDeniedException; +import javax.jcr.ImportUUIDBehavior; +import javax.jcr.Item; +import javax.jcr.ItemExistsException; +import javax.jcr.ItemNotFoundException; +import javax.jcr.Node; +import javax.jcr.NodeIterator; +import javax.jcr.PathNotFoundException; +import javax.jcr.Property; +import javax.jcr.PropertyIterator; +import javax.jcr.PropertyType; +import javax.jcr.RepositoryException; +import javax.jcr.Session; +import javax.jcr.UnsupportedRepositoryOperationException; +import javax.jcr.version.VersionIterator; +import javax.jcr.version.Version; +import javax.jcr.lock.Lock; +import javax.jcr.nodetype.NodeType; +import javax.xml.parsers.ParserConfigurationException; + +import org.apache.jackrabbit.JcrConstants; +import org.apache.jackrabbit.commons.webdav.JcrValueType; +import org.apache.jackrabbit.server.io.IOUtil; +import org.apache.jackrabbit.util.Text; +import org.apache.jackrabbit.webdav.DavCompliance; +import org.apache.jackrabbit.webdav.DavException; +import org.apache.jackrabbit.webdav.DavResource; +import org.apache.jackrabbit.webdav.DavResourceFactory; +import org.apache.jackrabbit.webdav.DavResourceIterator; +import org.apache.jackrabbit.webdav.DavResourceIteratorImpl; +import org.apache.jackrabbit.webdav.DavResourceLocator; +import org.apache.jackrabbit.webdav.DavServletResponse; +import org.apache.jackrabbit.webdav.MultiStatusResponse; +import org.apache.jackrabbit.webdav.jcr.property.JcrDavPropertyNameSet; +import org.apache.jackrabbit.webdav.jcr.security.JcrUserPrivilegesProperty; +import org.apache.jackrabbit.webdav.jcr.security.JcrSupportedPrivilegesProperty; +import org.apache.jackrabbit.webdav.jcr.security.SecurityUtils; +import org.apache.jackrabbit.webdav.security.SecurityConstants; +import org.apache.jackrabbit.webdav.util.HttpDateFormat; +import org.apache.jackrabbit.webdav.io.InputContext; +import org.apache.jackrabbit.webdav.io.OutputContext; +import org.apache.jackrabbit.webdav.jcr.lock.JcrActiveLock; +import org.apache.jackrabbit.webdav.jcr.lock.SessionScopedLockEntry; +import org.apache.jackrabbit.webdav.jcr.nodetype.NodeTypeProperty; +import org.apache.jackrabbit.webdav.jcr.property.ValuesProperty; +import org.apache.jackrabbit.webdav.jcr.version.report.ExportViewReport; +import org.apache.jackrabbit.webdav.jcr.version.report.LocateCorrespondingNodeReport; +import org.apache.jackrabbit.webdav.lock.ActiveLock; +import org.apache.jackrabbit.webdav.lock.LockInfo; +import org.apache.jackrabbit.webdav.lock.Scope; +import org.apache.jackrabbit.webdav.lock.Type; +import org.apache.jackrabbit.webdav.ordering.OrderPatch; +import org.apache.jackrabbit.webdav.ordering.OrderingConstants; +import org.apache.jackrabbit.webdav.ordering.OrderingResource; +import org.apache.jackrabbit.webdav.ordering.OrderingType; +import org.apache.jackrabbit.webdav.ordering.Position; +import org.apache.jackrabbit.webdav.property.DavProperty; +import org.apache.jackrabbit.webdav.property.DavPropertyName; +import org.apache.jackrabbit.webdav.property.DefaultDavProperty; +import org.apache.jackrabbit.webdav.property.HrefProperty; +import org.apache.jackrabbit.webdav.property.PropEntry; +import org.apache.jackrabbit.webdav.xml.DomUtil; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.w3c.dom.Document; +import org.xml.sax.SAXException; + +/** + * DefaultItemCollection represents a JCR node item. + */ +public class DefaultItemCollection extends AbstractItemResource + implements OrderingResource { + + private static Logger log = LoggerFactory.getLogger(DefaultItemCollection.class); + private static final String TMP_PREFIX = "_tmp_"; + + /** + * Create a new DefaultItemCollection. + * + * @param locator + * @param session + * @param factory + * @param item + */ + protected DefaultItemCollection(DavResourceLocator locator, + JcrDavSession session, + DavResourceFactory factory, Item item) { + super(locator, session, factory, item); + if (exists() && !(item instanceof Node)) { + throw new IllegalArgumentException("A collection resource can not be constructed from a Property item."); + } + } + + //----------------------------------------------< DavResource interface >--- + /** + * @see org.apache.jackrabbit.webdav.DavResource#getComplianceClass() + */ + @Override + public String getComplianceClass() { + String cc = super.getComplianceClass(); + if (isOrderable()) { + return DavCompliance.concatComplianceClasses( + new String[] { + cc, + DavCompliance.ORDERED_COLLECTIONS, + } + ); + } else { + return cc; + } + } + + @Override + public long getModificationTime() { + // retrieve mod-time from jcr:lastmodified property if existing + if (exists()) { + try { + if (((Node)item).hasProperty(JcrConstants.JCR_LASTMODIFIED)) { + return ((Node)item).getProperty(JcrConstants.JCR_LASTMODIFIED).getLong(); + } + } catch (RepositoryException e) { + log.warn("Error while accessing jcr:lastModified property"); + } + } + // fallback: return 'now' + return new Date().getTime(); + } + + /** + * @see org.apache.jackrabbit.webdav.DavResource#getSupportedMethods() + */ + @Override + public String getSupportedMethods() { + String ms = super.getSupportedMethods(); + if (isOrderable()) { + StringBuffer sb = new StringBuffer(ms); + sb.append(", ").append(OrderingResource.METHODS); + return sb.toString(); + } else { + return ms; + } + } + + /** + * Always returns true + * + * @return true + * @see org.apache.jackrabbit.webdav.DavResource#isCollection() + */ + @Override + public boolean isCollection() { + return true; + } + + /** + * If this resource represents an existing Node the system + * view is spooled as resource content. + * + * @param outputContext + * @throws IOException + * @see Session#exportSystemView(String, OutputStream, boolean, boolean) + */ + @Override + public void spool(OutputContext outputContext) throws IOException { + // spool properties + super.spool(outputContext); + // spool data + try { + OutputStream out = outputContext.getOutputStream(); + if (out != null && exists()) { + getRepositorySession().exportSystemView(item.getPath(), out, false, true); + } + } catch (PathNotFoundException e) { + log.error("Error while spooling resource content: " + e.getMessage()); + } catch (RepositoryException e) { + log.error("Error while spooling resource content: " + e.getMessage()); + } + } + + @Override + public DavProperty getProperty(DavPropertyName name) { + DavProperty prop = super.getProperty(name); + + if (prop == null && exists()) { + Node n = (Node) item; + + // add node-specific resource properties + try { + if (JCR_INDEX.equals(name)) { + prop = new DefaultDavProperty(JCR_INDEX, n.getIndex(), true); + } else if (JCR_REFERENCES.equals(name)) { + prop = getHrefProperty(JCR_REFERENCES, n.getReferences(), true); + } else if (JCR_WEAK_REFERENCES.equals(name)) { + prop = getHrefProperty(JCR_WEAK_REFERENCES, n.getWeakReferences(), true); + } else if (JCR_UUID.equals(name)) { + if (isReferenceable()) { + prop = new DefaultDavProperty(JCR_UUID, n.getUUID(), true); + } + } else if (JCR_PRIMARYITEM.equals(name)) { + if (hasPrimaryItem()) { + Item primaryItem = n.getPrimaryItem(); + prop = getHrefProperty(JCR_PRIMARYITEM, new Item[] {primaryItem}, true); + } + } else if (OrderingConstants.ORDERING_TYPE.equals(name) && isOrderable()) { + // property defined by RFC 3648: this resource always has custom ordering! + prop = new OrderingType(OrderingConstants.ORDERING_TYPE_CUSTOM); + } else if (SecurityConstants.SUPPORTED_PRIVILEGE_SET.equals(name)) { + prop = new JcrSupportedPrivilegesProperty(getRepositorySession(), n.getPath()).asDavProperty(); + } else if (SecurityConstants.CURRENT_USER_PRIVILEGE_SET.equals(name)) { + prop = new JcrUserPrivilegesProperty(getRepositorySession(), n.getPath()).asDavProperty(); + } + } catch (RepositoryException e) { + log.error("Failed to retrieve node-specific property: " + e); + } + } + + return prop; + } + + /** + * This implementation of the DavResource does only allow + * to set the mixinnodetypes property. Please note that the existing list of + * mixin nodetypes will be completely replaced.
+ * In order to add / set any other repository property on the underlying + * {@link javax.jcr.Node} use addMember(DavResource) or + * addMember(DavResource, InputStream) or modify the value + * of the corresponding resource. + * + * @param property + * @throws org.apache.jackrabbit.webdav.DavException + * @see org.apache.jackrabbit.webdav.DavResource#setProperty(org.apache.jackrabbit.webdav.property.DavProperty) + * @see #JCR_MIXINNODETYPES + */ + @Override + public void setProperty(DavProperty property) throws DavException { + internalSetProperty(property); + complete(); + } + + /** + * Internal method used to set or add the given property + * + * @param property + * @throws DavException + * @see #setProperty(DavProperty) + */ + private void internalSetProperty(DavProperty property) throws DavException { + if (!exists()) { + throw new DavException(DavServletResponse.SC_NOT_FOUND); + } + DavPropertyName propName = property.getName(); + if (JCR_MIXINNODETYPES.equals(propName)) { + Node n = (Node) item; + try { + NodeTypeProperty mix = new NodeTypeProperty(property); + Set mixins = mix.getNodeTypeNames(); + + for (NodeType existingMixin : n.getMixinNodeTypes()) { + String name = existingMixin.getName(); + if (mixins.contains(name)){ + // do not add existing mixins + mixins.remove(name); + } else { + // remove mixin that are not contained in the new list + n.removeMixin(name); + } + } + + // add the remaining mixing types that are not yet set + for (String mixin : mixins) { + n.addMixin(mixin); + } + } catch (RepositoryException e) { + throw new JcrDavException(e); + } + } else if (JCR_PRIMARYNODETYPE.equals(propName)) { + Node n = (Node) item; + try { + NodeTypeProperty ntProp = new NodeTypeProperty(property); + Set names = ntProp.getNodeTypeNames(); + if (names.size() == 1) { + String ntName = names.iterator().next(); + n.setPrimaryType(ntName); + } else { + // only a single node type can be primary node type. + throw new DavException(DavServletResponse.SC_BAD_REQUEST); + } + } catch (RepositoryException e) { + throw new JcrDavException(e); + } + } else { + // all props except for mixin node types and primaryType are read-only + throw new DavException(DavServletResponse.SC_CONFLICT); + } + } + + /** + * This implementation of the DavResource does only allow + * to remove the mixinnodetypes property. + * + * @param propertyName + * @throws org.apache.jackrabbit.webdav.DavException + * @see org.apache.jackrabbit.webdav.DavResource#removeProperty(org.apache.jackrabbit.webdav.property.DavPropertyName) + * @see #JCR_MIXINNODETYPES + */ + @Override + public void removeProperty(DavPropertyName propertyName) throws DavException { + internalRemoveProperty(propertyName); + complete(); + } + + /** + * Internal method used to remove the property with the given name. + * + * @param propertyName + * @throws DavException + * @see #removeProperty(DavPropertyName) + */ + private void internalRemoveProperty(DavPropertyName propertyName) throws DavException { + if (!exists()) { + throw new DavException(DavServletResponse.SC_NOT_FOUND); + } + if (JCR_MIXINNODETYPES.equals(propertyName)) { + // remove all mixin nodetypes + try { + Node n = (Node)item; + for (NodeType mixin : n.getMixinNodeTypes()) { + n.removeMixin(mixin.getName()); + } + } catch (RepositoryException e) { + // NoSuchNodeTypeException, ConstraintViolationException should never occur... + throw new JcrDavException(e); + } + } else { + // all props except for mixin node types are read-only + throw new DavException(DavServletResponse.SC_CONFLICT); + } + } + + /** + * Loops over the given Lists and alters the properties accordingly. + * Changes are persisted at the end according to the rules defined with + * the {@link AbstractItemResource#complete()} method.

+ * Please note: since there is only a single property + * ({@link ItemResourceConstants#JCR_MIXINNODETYPES} + * that can be set or removed with PROPPATCH, this method either succeeds + * or throws an exception, even if this violates RFC 2518. Thus no property + * specific multistatus will be created in case of an error. + * + * @param changeList + * @return + * @throws DavException + */ + @Override + public MultiStatusResponse alterProperties(List changeList) throws DavException { + for (PropEntry propEntry : changeList) { + if (propEntry instanceof DavPropertyName) { + // use the internal remove method in order to prevent premature 'save' + DavPropertyName propName = (DavPropertyName) propEntry; + internalRemoveProperty(propName); + } else if (propEntry instanceof DavProperty) { + // use the internal set method in order to prevent premature 'save' + DavProperty prop = (DavProperty) propEntry; + internalSetProperty(prop); + } else { + throw new IllegalArgumentException("unknown object in change list: " + propEntry.getClass().getName()); + } + } + // TODO: missing undo of successful set/remove if subsequent operation fails + // NOTE, that this is relevant with transactions only. + + // success: save all changes together if no error occurred + complete(); + return new MultiStatusResponse(getHref(), DavServletResponse.SC_OK); + } + + /** + * If the specified resource represents a collection, a new node is {@link Node#addNode(String) + * added} to the item represented by this resource. If an input stream is specified + * together with a collection resource {@link Session#importXML(String, java.io.InputStream, int)} + * is called instead and this resource path is used as parentAbsPath argument. + *

+ * However, if the specified resource is not of resource type collection a + * new {@link Property} is set or an existing one is changed by modifying its + * value.
+ * NOTE: with the current implementation it is not possible to create or + * modify multivalue JCR properties.
+ * NOTE: if the JCR property represented by the specified resource has an + * {@link PropertyType#UNDEFINED undefined} resource type, its value will be + * changed/set to type {@link PropertyType#BINARY binary}. + * + * @param resource + * @param inputContext + * @throws org.apache.jackrabbit.webdav.DavException + * @see org.apache.jackrabbit.webdav.DavResource#addMember(org.apache.jackrabbit.webdav.DavResource, InputContext) + * @see Node#addNode(String) + * @see Node#setProperty(String, java.io.InputStream) + */ + @Override + public void addMember(DavResource resource, InputContext inputContext) + throws DavException { + + /* RFC 2815 states that all 'parents' must exist in order all addition of members */ + if (!exists()) { + throw new DavException(DavServletResponse.SC_CONFLICT); + } + + File tmpFile = null; + try { + Node n = (Node) item; + InputStream in = (inputContext != null) ? inputContext.getInputStream() : null; + String itemPath = getLocator().getRepositoryPath(); + String memberName = getItemName(resource.getLocator().getRepositoryPath()); + if (resource.isCollection()) { + if (in == null) { + // MKCOL without a request body, try if a default-primary-type is defined. + n.addNode(memberName); + } else { + // MKCOL, which is not allowed for existing resources + int uuidBehavior = ImportUUIDBehavior.IMPORT_UUID_CREATE_NEW; + String str = inputContext.getProperty(IMPORT_UUID_BEHAVIOR); + if (str != null) { + try { + uuidBehavior = Integer.parseInt(str); + } catch (NumberFormatException e) { + throw new DavException(DavServletResponse.SC_BAD_REQUEST); + } + } + if (getTransactionId() == null) { + // if not part of a transaction directly import on workspace + // since changes would be explicitly saved in the + // complete-call. + getRepositorySession().getWorkspace().importXML(itemPath, in, uuidBehavior); + } else { + // changes will not be persisted unless the tx is completed. + getRepositorySession().importXML(itemPath, in, uuidBehavior); + } + } + } else { + if (in == null) { + // PUT: not possible without request body + throw new DavException(DavServletResponse.SC_BAD_REQUEST, "Cannot create a new non-collection resource without request body."); + } + // PUT : create new or overwrite existing property. + String ct = inputContext.getContentType(); + int type = JcrValueType.typeFromContentType(ct); + if (type != PropertyType.UNDEFINED) { + // no need to create value/values property. instead + // prop-value can be retrieved directly: + int pos = ct.indexOf(';'); + String charSet = (pos > -1) ? ct.substring(pos) : "UTF-8"; + if (type == PropertyType.BINARY) { + n.setProperty(memberName, inputContext.getInputStream()); + } else { + BufferedReader r = new BufferedReader(new InputStreamReader(inputContext.getInputStream(), charSet)); + String line; + StringBuffer value = new StringBuffer(); + while ((line = r.readLine()) != null) { + value.append(line); + } + n.setProperty(memberName, value.toString(), type); + } + } else { + // try to parse the request body into a 'values' property. + tmpFile = File.createTempFile(TMP_PREFIX + Text.escape(memberName), null, null); + FileOutputStream out = new FileOutputStream(tmpFile); + IOUtil.spool(in, out); + out.close(); + // try to parse the request body into a 'values' property. + ValuesProperty vp = buildValuesProperty(new FileInputStream(tmpFile)); + if (vp != null) { + if (JCR_VALUE.equals(vp.getName())) { + n.setProperty(memberName, vp.getJcrValue()); + } else { + n.setProperty(memberName, vp.getJcrValues()); + } + } else { + // request body cannot be parsed into a 'values' property. + // fallback: try to import as single value from stream. + n.setProperty(memberName, new FileInputStream(tmpFile)); + } + } + } + if (resource.exists() && resource instanceof AbstractItemResource) { + // PUT may modify value of existing jcr property. thus, this + // node is not modified by the 'addMember' call. + ((AbstractItemResource)resource).complete(); + } else { + complete(); + } + } catch (ItemExistsException e) { + // according to RFC 2518: MKCOL only possible on non-existing/deleted resource + throw new JcrDavException(e, DavServletResponse.SC_METHOD_NOT_ALLOWED); + } catch (RepositoryException e) { + throw new JcrDavException(e); + } catch (IOException e) { + throw new DavException(DavServletResponse.SC_UNPROCESSABLE_ENTITY, e.getMessage()); + } finally { + if (tmpFile != null) { + tmpFile.delete(); + } + } + } + + /** + * @see org.apache.jackrabbit.webdav.DavResource#getMembers() + */ + @Override + public DavResourceIterator getMembers() { + ArrayList memberList = new ArrayList(); + if (exists()) { + try { + Node n = (Node)item; + // add all node members + NodeIterator it = n.getNodes(); + while (it.hasNext()) { + Node node = it.nextNode(); + DavResourceLocator loc = getLocatorFromItem(node); + memberList.add(createResourceFromLocator(loc)); + } + // add all property members + PropertyIterator propIt = n.getProperties(); + while (propIt.hasNext()) { + Property prop = propIt.nextProperty(); + DavResourceLocator loc = getLocatorFromItem(prop); + memberList.add(createResourceFromLocator(loc)); + } + } catch (RepositoryException e) { + // ignore + log.error(e.getMessage()); + } catch (DavException e) { + // should never occur. + log.error(e.getMessage()); + } + } + return new DavResourceIteratorImpl(memberList); + } + + /** + * Removes the repository item represented by the specified member + * resource. + * + * @throws DavException if this resource does not exist or if an error occurs + * while deleting the underlying item. + * @see DavResource#removeMember(DavResource) + * @see javax.jcr.Item#remove() + */ + @Override + public void removeMember(DavResource member) throws DavException { + Session session = getRepositorySession(); + try { + String itemPath = member.getLocator().getRepositoryPath(); + if (!exists() || !session.itemExists(itemPath)) { + throw new DavException(DavServletResponse.SC_NOT_FOUND); + } + if (!getResourcePath().equals(Text.getRelativeParent(member.getResourcePath(), 1))) { + throw new DavException(DavServletResponse.SC_CONFLICT, member.getResourcePath() + "is not member of this resource (" + getResourcePath() + ")"); + } + getRepositorySession().getItem(itemPath).remove(); + complete(); + } catch (RepositoryException e) { + log.error("Unexpected error: " + e.getMessage()); + throw new JcrDavException(e); + } + } + + /** + * @param type + * @param scope + * @return true if a lock with the specified type and scope is present on + * this resource, false otherwise. If retrieving the corresponding information + * fails, false is returned. + * @see org.apache.jackrabbit.webdav.DavResource#hasLock(org.apache.jackrabbit.webdav.lock.Type, org.apache.jackrabbit.webdav.lock.Scope) + */ + @Override + public boolean hasLock(Type type, Scope scope) { + if (isLockable(type, scope)) { + if (Type.WRITE.equals(type)) { + try { + return ((Node) item).isLocked(); + } catch (RepositoryException e) { + log.error(e.getMessage()); + } + } else { + return super.hasLock(type, scope); + } + } + return false; + } + + /** + * Retrieve the lock with the specified type and scope. + * + * @param type + * @param scope + * @return lock with the specified type and scope is present on this + * resource or null. NOTE: If retrieving the write lock present + * on the underlying repository item fails, null is return. + * @see org.apache.jackrabbit.webdav.DavResource#getLock(org.apache.jackrabbit.webdav.lock.Type, org.apache.jackrabbit.webdav.lock.Scope) + * @see javax.jcr.Node#getLock() for the write locks. + */ + @Override + public ActiveLock getLock(Type type, Scope scope) { + ActiveLock lock = null; + if (Type.WRITE.equals(type)) { + try { + if (!exists()) { + log.warn("Unable to retrieve lock: no item found at '" + getResourcePath() + "'"); + } else if (((Node) item).isLocked()) { + Lock jcrLock = ((Node) item).getLock(); + lock = new JcrActiveLock(jcrLock); + DavResourceLocator locator = super.getLocator(); + String lockroot = locator + .getFactory() + .createResourceLocator(locator.getPrefix(), locator.getWorkspacePath(), jcrLock.getNode().getPath(), + false).getHref(false); + lock.setLockroot(lockroot); + } + } catch (AccessDeniedException e) { + log.error("Error while accessing resource lock: "+e.getMessage()); + } catch (UnsupportedRepositoryOperationException e) { + log.error("Error while accessing resource lock: "+e.getMessage()); + } catch (RepositoryException e) { + log.error("Error while accessing resource lock: "+e.getMessage()); + } + } else { + lock = super.getLock(type, scope); + } + return lock; + } + + /** + * Creates a lock on this resource by locking the underlying + * {@link javax.jcr.Node node}. Except for the {@link org.apache.jackrabbit.webdav.lock.LockInfo#isDeep()} } + * all information included in the LockInfo object is ignored. + * Lock timeout is defined by JCR implementation. + * + * @param reqLockInfo + * @return lock object representing the lock created on this resource. + * @throws org.apache.jackrabbit.webdav.DavException + * @see org.apache.jackrabbit.webdav.DavResource#lock(org.apache.jackrabbit.webdav.lock.LockInfo) + * @see Node#lock(boolean, boolean) + */ + @Override + public ActiveLock lock(LockInfo reqLockInfo) throws DavException { + + if (!isLockable(reqLockInfo.getType(), reqLockInfo.getScope())) { + throw new DavException(DavServletResponse.SC_PRECONDITION_FAILED); + } + + if (Type.WRITE.equals(reqLockInfo.getType())) { + if (!exists()) { + log.warn("Cannot create a write lock for non-existing JCR node (" + getResourcePath() + ")"); + throw new DavException(DavServletResponse.SC_NOT_FOUND); + } + try { + boolean sessionScoped = EXCLUSIVE_SESSION.equals(reqLockInfo.getScope()); + long timeout = reqLockInfo.getTimeout(); + if (timeout == LockInfo.INFINITE_TIMEOUT) { + timeout = Long.MAX_VALUE; + } else { + timeout = timeout/1000; + } + javax.jcr.lock.LockManager lockMgr = getRepositorySession().getWorkspace().getLockManager(); + Lock jcrLock = lockMgr.lock((item).getPath(), reqLockInfo.isDeep(), + sessionScoped, timeout, reqLockInfo.getOwner()); + ActiveLock lock = new JcrActiveLock(jcrLock); + // add reference to DAVSession for this lock + getSession().addReference(lock.getToken()); + return lock; + } catch (RepositoryException e) { + // UnsupportedRepositoryOperationException should not occur... + throw new JcrDavException(e); + } + } else { + return super.lock(reqLockInfo); + } + } + + /** + * Refreshes the lock on this resource. With this implementation the + * {@link javax.jcr.lock lock} present on the underlying {@link javax.jcr.Node node} + * is refreshed. The timeout indicated by the LockInfo + * object is ignored. + * + * @param reqLockInfo LockInfo as build from the request. + * @param lockToken + * @return the updated lock info object. + * @throws org.apache.jackrabbit.webdav.DavException in case the lock could not be refreshed. + * @see org.apache.jackrabbit.webdav.DavResource#refreshLock(org.apache.jackrabbit.webdav.lock.LockInfo, String) + * @see javax.jcr.lock.Lock#refresh() + */ + @Override + public ActiveLock refreshLock(LockInfo reqLockInfo, String lockToken) + throws DavException { + + if (lockToken == null) { + throw new DavException(DavServletResponse.SC_PRECONDITION_FAILED); + } + + ActiveLock lock = getLock(reqLockInfo.getType(), reqLockInfo.getScope()); + if (lock == null) { + throw new DavException(DavServletResponse.SC_PRECONDITION_FAILED, "No lock with the given scope/type present on this resource."); + } + + if (Type.WRITE.equals(lock.getType())) { + try { + Lock jcrLock = ((Node) item).getLock(); + jcrLock.refresh(); + return new JcrActiveLock(jcrLock); + } catch (RepositoryException e) { + /* + NOTE: LockException is only thrown by Lock.refresh() + the lock exception thrown by Node.getLock() was circumvented + by the init test if there is a lock applied... + NOTE: UnsupportedRepositoryOperationException should not occur + */ + throw new JcrDavException(e); + } + } else { + return super.refreshLock(reqLockInfo, lockToken); + } + } + + /** + * Remove the write lock from this resource by unlocking the underlying + * {@link javax.jcr.Node node}. + * + * @param lockToken + * @throws org.apache.jackrabbit.webdav.DavException + * @see org.apache.jackrabbit.webdav.DavResource#unlock(String) + * @see javax.jcr.Node#unlock() + */ + @Override + public void unlock(String lockToken) throws DavException { + ActiveLock lock = getWriteLock(); + if (lock != null && lockToken.equals(lock.getToken())) { + try { + ((Node) item).unlock(); + getSession().removeReference(lock.getToken()); + } catch (RepositoryException e) { + throw new JcrDavException(e); + } + } else { + super.unlock(lockToken); + } + } + + /** + * Returns the write lock present on this resource or null if + * no write lock exists. NOTE: that the scope of a write lock may either + * be {@link org.apache.jackrabbit.webdav.lock.Scope#EXCLUSIVE} or + * {@link ItemResourceConstants#EXCLUSIVE_SESSION}. + * + * @return write lock or null + * @throws DavException if this resource does not represent a repository item. + */ + private ActiveLock getWriteLock() throws DavException { + if (!exists()) { + throw new DavException(DavServletResponse.SC_NOT_FOUND, "Unable to retrieve write lock for non existing repository item (" + getResourcePath() + ")"); + } + ActiveLock writeLock = getLock(Type.WRITE, Scope.EXCLUSIVE); + if (writeLock == null) { + writeLock = getLock(Type.WRITE, EXCLUSIVE_SESSION); + } + return writeLock; + } + + //-----------------------------------------< OrderingResource interface >--- + /** + * Returns true if this resource exists and the nodetype defining the + * underlying repository node allow to reorder this nodes children. + * + * @return true if {@link DefaultItemCollection#orderMembers(OrderPatch)} + * can be called on this resource. + * @see org.apache.jackrabbit.webdav.ordering.OrderingResource#isOrderable() + * @see javax.jcr.nodetype.NodeType#hasOrderableChildNodes() + */ + @Override + public boolean isOrderable() { + boolean orderable = false; + if (exists()) { + try { + orderable = ((Node) item).getPrimaryNodeType().hasOrderableChildNodes(); + } catch (RepositoryException e) { + log.warn(e.getMessage()); + } + } + return orderable; + } + + /** + * Reorder the child nodes of the repository item represented by this + * resource as indicated by the specified {@link OrderPatch} object. + * + * @param orderPatch + * @throws org.apache.jackrabbit.webdav.DavException + * @see org.apache.jackrabbit.webdav.ordering.OrderingResource#orderMembers(org.apache.jackrabbit.webdav.ordering.OrderPatch) + * @see Node#orderBefore(String, String) + */ + @Override + public void orderMembers(OrderPatch orderPatch) throws DavException { + if (!isOrderable()) { + throw new DavException(DavServletResponse.SC_METHOD_NOT_ALLOWED); + } + // only custom ordering is allowed + if (!OrderingConstants.ORDERING_TYPE_CUSTOM.equalsIgnoreCase(orderPatch.getOrderingType())) { + throw new DavException(DavServletResponse.SC_UNPROCESSABLE_ENTITY, "Only DAV:custom ordering type supported."); + } + + Node n = (Node)item; + try { + for (OrderPatch.Member instruction : orderPatch.getOrderInstructions()) { + String srcRelPath = Text.unescape(instruction.getMemberHandle()); + Position pos = instruction.getPosition(); + String destRelPath = getRelDestinationPath(pos, n.getNodes()); + // preform the reordering + n.orderBefore(srcRelPath, destRelPath); + } + complete(); + } catch (RepositoryException e) { + // UnsupportedRepositoryException should not occur + throw new JcrDavException(e); + } + } + + /** + * Retrieve the relative path of the child node that acts as destination. + * A null destination path is used to place the child node indicated + * by the source path at the end of the list. + * + * @param position + * @param childNodes + * @return the relative path of the child node used as destination or null + * if the source node should be placed at the last position. + * @throws javax.jcr.RepositoryException + */ + private String getRelDestinationPath(Position position, NodeIterator childNodes) + throws RepositoryException { + + String destRelPath = null; + if (OrderingConstants.XML_FIRST.equals(position.getType())) { + if (childNodes.hasNext()) { + Node firstChild = childNodes.nextNode(); + // use last segment of node-path instead of name. + destRelPath = Text.getName(firstChild.getPath()); + } + // no child nodes available > reordering to 'first' position fails. + if (destRelPath == null) { + throw new ItemNotFoundException("No 'first' item found for reordering."); + } + } else if (OrderingConstants.XML_AFTER.equals(position.getType())) { + String afterRelPath = position.getSegment(); + boolean found = false; + // jcr only knows order-before > retrieve the node that follows the + // one indicated by the 'afterRelPath'. + while (childNodes.hasNext() && destRelPath == null) { + // compare to last segment of node-path instead of name. + String childRelPath = Text.getName(childNodes.nextNode().getPath()); + if (found) { + destRelPath = childRelPath; + } else { + found = afterRelPath.equals(childRelPath); + } + } + } else { + // before or last. in the latter case the segment is 'null' + destRelPath = position.getSegment(); + } + if (destRelPath != null) { + destRelPath = Text.unescape(destRelPath); + } + return destRelPath; + } + + //-------------------------------------------------------------------------- + /** + * Extend the general {@link AbstractResource#supportedLock} field by + * lock entries specific for this resource: write locks (exclusive or + * exclusive session-scoped) in case the underlying node has the node + * type mix:lockable. + * + * @see org.apache.jackrabbit.JcrConstants#MIX_LOCKABLE + */ + @Override + protected void initLockSupport() { + super.initLockSupport(); + // add exclusive write lock if allowed for the given node + try { + if (exists() && ((Node)item).isNodeType(JcrConstants.MIX_LOCKABLE)) { + supportedLock.addEntry(Type.WRITE, Scope.EXCLUSIVE); + supportedLock.addEntry(new SessionScopedLockEntry()); + } + } catch (RepositoryException e) { + log.warn(e.getMessage()); + } + } + + /** + * Defines the additional reports supported by this resource (reports + * specific for resources representing a repository {@link Node node}): + *

    + *
  • {@link ExportViewReport export view report}
  • + *
  • {@link LocateCorrespondingNodeReport locate corresponding node report}
  • + *
+ * + * @see org.apache.jackrabbit.webdav.version.report.SupportedReportSetProperty + */ + @Override + protected void initSupportedReports() { + super.initSupportedReports(); + if (exists()) { + supportedReports.addReportType(ExportViewReport.EXPORTVIEW_REPORT); + supportedReports.addReportType(LocateCorrespondingNodeReport.LOCATE_CORRESPONDING_NODE_REPORT); + } + } + + @Override + protected void initPropertyNames() { + super.initPropertyNames(); + + if (exists()) { + names.addAll(JcrDavPropertyNameSet.NODE_SET); + + if (isReferenceable()) { + names.add(JCR_UUID); + } + if (hasPrimaryItem()) { + names.add(JCR_PRIMARYITEM); + } + if (isOrderable()) { + names.add(OrderingConstants.ORDERING_TYPE); + } + if (SecurityUtils.supportsAccessControl(getRepositorySession())) { + names.add(SecurityConstants.SUPPORTED_PRIVILEGE_SET); + names.add(SecurityConstants.CURRENT_USER_PRIVILEGE_SET); + } + } + } + + /** + * Fill the property set for this resource. + */ + @Override + protected void initProperties() { + super.initProperties(); + if (exists()) { + // resource is serialized as system-view (xml) + properties.add(new DefaultDavProperty(DavPropertyName.GETCONTENTTYPE, "text/xml")); + Node n = (Node)item; + + // add node-specific resource properties + try { + properties.add(new NodeTypeProperty(JCR_PRIMARYNODETYPE, n.getPrimaryNodeType(), false)); + properties.add(new NodeTypeProperty(JCR_MIXINNODETYPES, n.getMixinNodeTypes(), false)); + } catch (RepositoryException e) { + log.error("Failed to retrieve node-specific property: " + e); + } + } + } + + @Override + protected String getCreatorDisplayName() { + // overwrite the default creation date and creator-displayname if possible + try { + // DAV:creator-displayname -> use jcr:createBy if present. + if (exists() && ((Node) item).hasProperty(Property.JCR_CREATED_BY)) { + return ((Node) item).getProperty(Property.JCR_CREATED_BY).getString(); + } + } catch (RepositoryException e) { + log.warn("Error while accessing jcr:createdBy property"); + } + + // fallback + return super.getCreatorDisplayName(); + } + + @Override + protected String getCreationDate() { + // overwrite the default creation date and creator-displayname if possible + try { + if (exists() && ((Node) item).hasProperty(JcrConstants.JCR_CREATED)) { + long creationTime = ((Node) item).getProperty(JcrConstants.JCR_CREATED).getValue().getLong(); + return HttpDateFormat.creationDateFormat().format(new Date(creationTime)); + } + } catch (RepositoryException e) { + log.warn("Error while accessing jcr:created property"); + } + + // fallback + return super.getCreationDate(); + } + + /** + * Creates a new HrefProperty with the specified name using the given + * array of items as value. + * + * @param name + * @param values + * @param isProtected + * @return + */ + protected HrefProperty getHrefProperty(DavPropertyName name, Item[] values, boolean isProtected) { + String[] pHref = new String[values.length]; + for (int i = 0; i < values.length; i++) { + pHref[i] = getLocatorFromItem(values[i]).getHref(true); + } + return new HrefProperty(name, pHref, isProtected); + } + + /** + * Add a {@link org.apache.jackrabbit.webdav.property.HrefProperty} with the + * specified property name and values. Each item present in the specified + * values array is referenced in the resulting property. + * + * @param name + * @param values + * @param isProtected + */ + protected void addHrefProperty(DavPropertyName name, Item[] values, boolean isProtected) { + properties.add(getHrefProperty(name, values, isProtected)); + } + + /** + * Creates a new {@link HrefProperty href property} to the property set, where + * all properties present in the specified iterator are referenced in the + * resulting property. + * + * @param name + * @param itemIterator + * @param isProtected + * @return + */ + protected HrefProperty getHrefProperty(DavPropertyName name, PropertyIterator itemIterator, + boolean isProtected) { + ArrayList l = new ArrayList(); + while (itemIterator.hasNext()) { + l.add(itemIterator.nextProperty()); + } + return getHrefProperty(name, l.toArray(new Property[l.size()]), isProtected); + } + + /** + * Add a new {@link HrefProperty href property} to the property set, where + * all properties present in the specified iterator are referenced in the + * resulting property. + * + * @param name + * @param itemIterator + * @param isProtected + * @see #addHrefProperty(DavPropertyName, Item[], boolean) + */ + protected void addHrefProperty(DavPropertyName name, PropertyIterator itemIterator, + boolean isProtected) { + properties.add(getHrefProperty(name, itemIterator, isProtected)); + } + + /** + * Add a new {@link HrefProperty href property} to the property set, where + * all versions present in the specified iterator are referenced in the + * resulting property. + * + * @param name + * @param itemIterator + * @param isProtected + */ + protected HrefProperty getHrefProperty(DavPropertyName name, VersionIterator itemIterator, + boolean isProtected) { + ArrayList l = new ArrayList(); + while (itemIterator.hasNext()) { + l.add(itemIterator.nextVersion()); + } + return getHrefProperty(name, l.toArray(new Version[l.size()]), isProtected); + } + + /** + * Add a new {@link HrefProperty href property} to the property set, where + * all versions present in the specified iterator are referenced in the + * resulting property. + * + * @param name + * @param itemIterator + * @param isProtected + */ + protected void addHrefProperty(DavPropertyName name, VersionIterator itemIterator, + boolean isProtected) { + properties.add(getHrefProperty(name, itemIterator, isProtected)); + } + + /** + * Tries to parse the given input stream as xml document and build a + * {@link ValuesProperty} out of it. + * + * @param in + * @return values property or 'null' if the given stream cannot be parsed + * into an XML document or if build the property fails. + */ + private ValuesProperty buildValuesProperty(InputStream in) { + String errorMsg = "Cannot parse stream into a 'ValuesProperty'."; + try { + Document reqBody = DomUtil.parseDocument(in); + DavProperty defaultProp = DefaultDavProperty.createFromXml(reqBody.getDocumentElement()); + ValuesProperty vp = new ValuesProperty(defaultProp, PropertyType.STRING, getRepositorySession().getValueFactory()); + return vp; + } catch (IOException e) { + log.debug(errorMsg, e); + } catch (ParserConfigurationException e) { + log.debug(errorMsg, e); + } catch (SAXException e) { + log.debug(errorMsg, e); + } catch (DavException e) { + log.debug(errorMsg, e); + } catch (RepositoryException e) { + log.debug(errorMsg, e); + } + // cannot parse request body into a 'values' property + return null; + } + + private boolean hasPrimaryItem() { + try { + return exists() && ((Node) item).getPrimaryNodeType().getPrimaryItemName() != null; + } catch (RepositoryException e) { + log.warn(e.getMessage()); + } + return false; + } + + private boolean isReferenceable() { + try { + return exists() && ((Node) item).isNodeType(JcrConstants.MIX_REFERENCEABLE); + } catch (RepositoryException e) { + log.warn(e.getMessage()); + } + return false; + } +} Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/DefaultItemCollection.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/webdav/jcr/DefaultItemResource.java =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/DefaultItemResource.java (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/DefaultItemResource.java (working copy) @@ -0,0 +1,421 @@ +/* + * 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.webdav.jcr; + +import org.apache.jackrabbit.commons.webdav.JcrValueType; +import org.apache.jackrabbit.commons.xml.SerializingContentHandler; +import org.apache.jackrabbit.server.io.IOUtil; +import org.apache.jackrabbit.webdav.DavException; +import org.apache.jackrabbit.webdav.DavResource; +import org.apache.jackrabbit.webdav.DavResourceFactory; +import org.apache.jackrabbit.webdav.DavResourceIterator; +import org.apache.jackrabbit.webdav.DavResourceIteratorImpl; +import org.apache.jackrabbit.webdav.DavResourceLocator; +import org.apache.jackrabbit.webdav.DavServletResponse; +import org.apache.jackrabbit.webdav.MultiStatusResponse; +import org.apache.jackrabbit.webdav.io.InputContext; +import org.apache.jackrabbit.webdav.io.OutputContext; +import org.apache.jackrabbit.webdav.jcr.property.JcrDavPropertyNameSet; +import org.apache.jackrabbit.webdav.jcr.property.LengthsProperty; +import org.apache.jackrabbit.webdav.jcr.property.ValuesProperty; +import org.apache.jackrabbit.webdav.lock.ActiveLock; +import org.apache.jackrabbit.webdav.lock.Scope; +import org.apache.jackrabbit.webdav.lock.Type; +import org.apache.jackrabbit.webdav.property.DavProperty; +import org.apache.jackrabbit.webdav.property.DavPropertyName; +import org.apache.jackrabbit.webdav.property.DavPropertyNameSet; +import org.apache.jackrabbit.webdav.property.DefaultDavProperty; +import org.apache.jackrabbit.webdav.property.PropEntry; +import org.apache.jackrabbit.webdav.xml.DomUtil; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.w3c.dom.Document; +import org.xml.sax.ContentHandler; +import org.xml.sax.SAXException; + +import javax.jcr.Binary; +import javax.jcr.Item; +import javax.jcr.Property; +import javax.jcr.PropertyType; +import javax.jcr.RepositoryException; +import javax.jcr.Value; +import javax.jcr.ValueFactory; +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.transform.Transformer; +import javax.xml.transform.TransformerConfigurationException; +import javax.xml.transform.TransformerException; +import javax.xml.transform.TransformerFactory; +import javax.xml.transform.dom.DOMSource; +import javax.xml.transform.sax.SAXResult; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.util.Collections; +import java.util.Date; +import java.util.List; + +/** + * DefaultItemResource represents JCR property item. + * + * @see Property + */ +public class DefaultItemResource extends AbstractItemResource { + + private static Logger log = LoggerFactory.getLogger(DefaultItemResource.class); + + /** + * Create a new DefaultItemResource. + * + * @param locator + * @param session + */ + public DefaultItemResource(DavResourceLocator locator, JcrDavSession session, + DavResourceFactory factory, Item item) { + super(locator, session, factory, item); + } + + //----------------------------------------------< DavResource interface >--- + /** + * Returns false. + * + * @return false + * @see DavResource#isCollection() + */ + @Override + public boolean isCollection() { + return false; + } + + /** + * Always returns 'now' + * + * @return + * @see DavResource#getModificationTime() + */ + @Override + public long getModificationTime() { + return new Date().getTime(); + } + + /** + * In case an underlying repository {@link Property property} exists the following + * logic is applied to spool the property content: + *
    + *
  • Property is not multi valued: Return the {@link javax.jcr.Value#getStream() + * stream representation} of the property value.
  • + *
  • Property is multivalue: Return the xml representation of the values.
  • + *
+ * + * @param outputContext + * @see DavResource#spool(OutputContext) + */ + @Override + public void spool(OutputContext outputContext) throws IOException { + // write properties + super.spool(outputContext); + // spool content + OutputStream out = outputContext.getOutputStream(); + if (out != null && exists()) { + if (isMultiple()) { + spoolMultiValued(out); + } else { + spoolSingleValued(out); + } + } + } + + private void spoolMultiValued(OutputStream out) { + try { + Document doc = DomUtil.createDocument(); + doc.appendChild(getProperty(JCR_VALUES).toXml(doc)); + + ContentHandler handler = + SerializingContentHandler.getSerializer(out); + + Transformer transformer = + TransformerFactory.newInstance().newTransformer(); + transformer.transform( + new DOMSource(doc), new SAXResult(handler)); + } catch (SAXException e) { + log.error("Failed to set up XML serializer for " + item, e); + } catch (TransformerConfigurationException e) { + log.error("Failed to set up XML transformer for " + item, e); + } catch (ParserConfigurationException e) { + log.error("Failed to set up XML document for " + item, e); + } catch (TransformerException e) { + log.error("Failed to serialize the values of " + item, e); + } + } + + private void spoolSingleValued(OutputStream out) throws IOException { + try { + Binary binary = ((Property) item).getBinary(); + try { + InputStream in = binary.getStream(); + try { + IOUtil.spool(in, out); + } finally { + in.close(); + } + } finally { + binary.dispose(); + } + } catch (RepositoryException e) { + log.error("Cannot obtain stream from " + item, e); + } + } + + @Override + public DavProperty getProperty(DavPropertyName name) { + DavProperty prop = super.getProperty(name); + + if (prop == null && exists()) { + try { + Property p = (Property) item; + if (isMultiple()) { + if (JCR_LENGTHS.equals(name)) { + prop = new LengthsProperty(p.getLengths()); + } + } else { + if (JCR_LENGTH.equals(name)) { + long length = p.getLength(); + prop = new DefaultDavProperty(JCR_LENGTH, String.valueOf(length), true); + } else if (JCR_GET_STRING.equals(name) && p.getType() != PropertyType.BINARY) { + // getstring property is only created for single value + // non-binary jcr properties + prop = new DefaultDavProperty(JCR_GET_STRING, p.getString(), true); + } + } + } catch (RepositoryException e) { + log.error("Failed to retrieve resource properties: "+e.getMessage()); + } + } + + return prop; + } + + /** + * Sets the given property. Note, that {@link #JCR_VALUE} and {@link #JCR_VALUES} + * are the only resource properties that are allowed to be modified. Any other + * property is read-only and will throw an exception ('Conflict'). + * + * @param property + * @throws DavException + * @see DavResource#setProperty(org.apache.jackrabbit.webdav.property.DavProperty) + */ + @Override + public void setProperty(DavProperty property) throws DavException { + internalSetProperty(property); + complete(); + } + + /** + * Internal method that performs the setting or adding of properties + * + * @param property + * @throws DavException + * @see #setProperty(DavProperty) + * @see #alterProperties(List) + */ + private void internalSetProperty(DavProperty property) throws DavException { + if (!exists()) { + throw new DavException(DavServletResponse.SC_NOT_FOUND); + } + try { + Property prop = (Property) item; + int defaultType = prop.getType(); + ValueFactory vfact = getRepositorySession().getValueFactory(); + ValuesProperty vp = new ValuesProperty(property, defaultType, vfact); + if (property.getName().equals(JCR_VALUE)) { + prop.setValue(vp.getJcrValue(vp.getValueType(), vfact)); + } else if (property.getName().equals(JCR_VALUES)) { + prop.setValue(vp.getJcrValues()); + } else { + throw new DavException(DavServletResponse.SC_CONFLICT); + } + } catch (RepositoryException e) { + throw new JcrDavException(e); + } + } + + /** + * Removing properties is not allowed, for a single-value JCR-property without + * a value does not exist. For multivalue properties an empty {@link Value values array} + * may be specified with by setting the {@link #JCR_VALUES 'values' webdav property}. + * + * @param propertyName + * @throws DavException + * @see org.apache.jackrabbit.webdav.DavResource#removeProperty(org.apache.jackrabbit.webdav.property.DavPropertyName) + */ + @Override + public void removeProperty(DavPropertyName propertyName) throws DavException { + if (!exists()) { + throw new DavException(DavServletResponse.SC_NOT_FOUND); + } + throw new DavException(DavServletResponse.SC_FORBIDDEN); + } + + /** + * Loops over the given List and alters the properties accordingly. + * Changes are persisted at the end only according to the rules defined with + * the {@link #complete()} method.

+ * Please note: since there is only a single property than can be set + * from a client (i.e. jcr:value OR jcr:values) this method either succeeds + * or throws an exception, even if this violates RFC 2518. + * + * @param changeList + * @throws DavException + * @see DavResource#alterProperties(List) + */ + @Override + public MultiStatusResponse alterProperties(List changeList) throws DavException { + for (PropEntry propEntry : changeList) { + if (propEntry instanceof DavPropertyName) { + // altering any properties fails if an attempt is made to remove + // a property + throw new DavException(DavServletResponse.SC_FORBIDDEN); + } else if (propEntry instanceof DavProperty) { + DavProperty prop = (DavProperty) propEntry; + internalSetProperty(prop); + } else { + throw new IllegalArgumentException("unknown object in change list: " + propEntry.getClass().getName()); + } + } + complete(); + return new MultiStatusResponse(getHref(), DavServletResponse.SC_OK); + } + + /** + * Method is not allowed. + * + * @see org.apache.jackrabbit.webdav.DavResource#addMember(org.apache.jackrabbit.webdav.DavResource, InputContext) + */ + @Override + public void addMember(DavResource resource, InputContext inputContext) throws DavException { + throw new DavException(DavServletResponse.SC_METHOD_NOT_ALLOWED, "Cannot add members to a non-collection resource"); + } + + /** + * Always returns an empty iterator for a non-collection resource might + * not have internal members. + * + * @return an empty iterator + * @see DavResource#getMembers() + */ + @Override + public DavResourceIterator getMembers() { + log.warn("A non-collection resource never has internal members."); + List drl = Collections.emptyList(); + return new DavResourceIteratorImpl(drl); + } + + /** + * Method is not allowed. + * + * @see DavResource#removeMember(DavResource) + */ + @Override + public void removeMember(DavResource member) throws DavException { + throw new DavException(DavServletResponse.SC_METHOD_NOT_ALLOWED, "Cannot remove members from a non-collection resource"); + } + + /** + * {@link javax.jcr.Property JCR properties} are locked if their + * parent node is locked; thus this method will always return the + * {@link ActiveLock lock} object from the collection this resource is + * internal member of. + * + * @param type + * @param scope + * @return lock present on this resource or null if this resource + * has no lock. + * @see DavResource#getLock(Type, Scope) + */ + @Override + public ActiveLock getLock(Type type, Scope scope) { + if (Type.WRITE.equals(type)) { + return getCollection().getLock(type, scope); + } else { + return super.getLock(type, scope); + } + } + + //-------------------------------------------------------------------------- + @Override + protected void initPropertyNames() { + super.initPropertyNames(); + if (exists()) { + DavPropertyNameSet propNames = (isMultiple() ? + JcrDavPropertyNameSet.PROPERTY_MV_SET : + JcrDavPropertyNameSet.PROPERTY_SET); + names.addAll(propNames); + } + } + + /** + * Add resource specific properties. + */ + @Override + protected void initProperties() { + super.initProperties(); + if (exists()) { + try { + Property prop = (Property)item; + int type = prop.getType(); + + // set the content type + String contentType; + if (isMultiple()) { + contentType = IOUtil.buildContentType("text/xml","utf-8"); + } else { + contentType = IOUtil.buildContentType(JcrValueType.contentTypeFromType(type), "utf-8"); + + } + properties.add(new DefaultDavProperty(DavPropertyName.GETCONTENTTYPE, contentType)); + + // add jcr-specific resource properties + properties.add(new DefaultDavProperty(JCR_TYPE, PropertyType.nameFromValue(type))); + if (isMultiple()) { + properties.add(new ValuesProperty(prop.getValues())); + } else { + properties.add(new ValuesProperty(prop.getValue())); + } + } catch (RepositoryException e) { + log.error("Failed to retrieve resource properties: "+e.getMessage()); + } + } + } + + /** + * Returns true if the JCR Property represented by this resource is a multi + * value property. Note: if this resource does not exist or if the definition + * could not be retrieved false is returned. + * + * @return true if the underlying resource is a multi value property. + */ + private boolean isMultiple() { + try { + if (exists() && ((Property)item).isMultiple()) { + return true; + } + } catch (RepositoryException e) { + log.error("Error while retrieving property definition: " + e.getMessage()); + } + return false; + } +} Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/DefaultItemResource.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/webdav/jcr/EventJournalResourceImpl.java =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/EventJournalResourceImpl.java (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/EventJournalResourceImpl.java (working copy) @@ -0,0 +1,483 @@ +/* + * 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.webdav.jcr; + +import java.io.IOException; +import java.io.OutputStream; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Calendar; +import java.util.Collections; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.Set; + +import javax.jcr.RepositoryException; +import javax.jcr.UnsupportedRepositoryOperationException; +import javax.jcr.observation.Event; +import javax.jcr.observation.EventJournal; +import javax.servlet.http.HttpServletRequest; +import javax.xml.transform.OutputKeys; +import javax.xml.transform.Transformer; +import javax.xml.transform.TransformerFactory; +import javax.xml.transform.sax.SAXTransformerFactory; +import javax.xml.transform.sax.TransformerHandler; +import javax.xml.transform.stream.StreamResult; + +import org.apache.jackrabbit.commons.webdav.AtomFeedConstants; +import org.apache.jackrabbit.commons.webdav.EventUtil; +import org.apache.jackrabbit.spi.Name; +import org.apache.jackrabbit.spi.commons.AdditionalEventInfo; +import org.apache.jackrabbit.util.ISO8601; +import org.apache.jackrabbit.webdav.DavConstants; +import org.apache.jackrabbit.webdav.DavException; +import org.apache.jackrabbit.webdav.DavResource; +import org.apache.jackrabbit.webdav.DavResourceFactory; +import org.apache.jackrabbit.webdav.DavResourceIterator; +import org.apache.jackrabbit.webdav.DavResourceIteratorImpl; +import org.apache.jackrabbit.webdav.DavResourceLocator; +import org.apache.jackrabbit.webdav.DavServletResponse; +import org.apache.jackrabbit.webdav.io.InputContext; +import org.apache.jackrabbit.webdav.io.OutputContext; +import org.apache.jackrabbit.webdav.observation.ObservationConstants; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.xml.sax.Attributes; +import org.xml.sax.SAXException; +import org.xml.sax.helpers.AttributesImpl; + +/** + * Implements a JCR {@link EventJournal} in terms of an RFC 4287 Atom feed. + *

+ * Each feed entry represents either a single event, or, if the repository + * supports the {@link Event#PERSIST} event, an event bundle. The actual event + * data is sent in the Atom <content> element and uses the same XML + * serialization as the one used for subscriptions. + *

+ * Skipping is implemented by specifying the desired time offset (represented + * as hexadecimal long in ms since the epoch) disguised as ETag in the HTTP "If-None-Match" + * header field. + *

+ * The generated feed may not be complete; the total number of events is limited in + * order not to overload the client. + *

+ * Furthermore, the number of events is limited by going up to 2000 ms into the future + * (based on the request time). This is supposed to limit the wait time for the client). + */ +public class EventJournalResourceImpl extends AbstractResource { + + public static final String RELURIFROMWORKSPACE = "?type=journal"; + + public static final String EVENTMEDIATYPE = "application/vnd.apache.jackrabbit.event+xml"; + + private static Logger log = LoggerFactory.getLogger(EventJournalResourceImpl.class); + + private final HttpServletRequest request; + private final EventJournal journal; + private final DavResourceLocator locator; + + EventJournalResourceImpl(EventJournal journal, DavResourceLocator locator, JcrDavSession session, + HttpServletRequest request, DavResourceFactory factory) { + super(locator, session, factory); + this.journal = journal; + this.locator = locator; + this.request = request; + } + + @Override + public String getSupportedMethods() { + return "GET, HEAD"; + } + + @Override + public boolean exists() { + try { + List available = Arrays.asList(getRepositorySession().getWorkspace().getAccessibleWorkspaceNames()); + return available.contains(getLocator().getWorkspaceName()); + } catch (RepositoryException e) { + log.warn(e.getMessage()); + return false; + } + } + + @Override + public boolean isCollection() { + return false; + } + + @Override + public String getDisplayName() { + return "event journal for " + getLocator().getWorkspaceName(); + } + + @Override + public long getModificationTime() { + return System.currentTimeMillis(); + } + + private static final String ATOMNS = AtomFeedConstants.NS_URI; + private static final String EVNS = ObservationConstants.NAMESPACE.getURI(); + + private static final String AUTHOR = AtomFeedConstants.XML_AUTHOR; + private static final String CONTENT = AtomFeedConstants.XML_CONTENT; + private static final String ENTRY = AtomFeedConstants.XML_ENTRY; + private static final String FEED = AtomFeedConstants.XML_FEED; + private static final String ID = AtomFeedConstants.XML_ID; + private static final String LINK = AtomFeedConstants.XML_LINK; + private static final String NAME = AtomFeedConstants.XML_NAME; + private static final String TITLE = AtomFeedConstants.XML_TITLE; + private static final String UPDATED = AtomFeedConstants.XML_UPDATED; + + private static final String E_EVENT = ObservationConstants.XML_EVENT; + private static final String E_EVENTDATE = ObservationConstants.XML_EVENTDATE; + private static final String E_EVENTIDENTIFIER = ObservationConstants.XML_EVENTIDENTIFIER; + private static final String E_EVENTINFO = ObservationConstants.XML_EVENTINFO; + private static final String E_EVENTTYPE = ObservationConstants.XML_EVENTTYPE; + private static final String E_EVENTMIXINNODETYPE = ObservationConstants.XML_EVENTMIXINNODETYPE; + private static final String E_EVENTPRIMARNODETYPE = ObservationConstants.XML_EVENTPRIMARNODETYPE; + private static final String E_EVENTUSERDATA = ObservationConstants.XML_EVENTUSERDATA; + + private static final int MAXWAIT = 2000; // maximal wait time + private static final int MAXEV = 10000; // maximal event number + + private static final Attributes NOATTRS = new AttributesImpl(); + + @Override + public void spool(OutputContext outputContext) throws IOException { + + Calendar cal = Calendar.getInstance(Locale.ENGLISH); + + try { + outputContext.setContentType("application/atom+xml; charset=UTF-8"); + outputContext.setProperty("Vary", "If-None-Match"); + // TODO: Content-Encoding: gzip + + // find out where to start + long prevts = -1; + String inm = request.getHeader("If-None-Match"); + if (inm != null) { + // TODO: proper parsing when comma-delimited + inm = inm.trim(); + if (inm.startsWith("\"") && inm.endsWith("\"")) { + String tmp = inm.substring(1, inm.length() - 1); + try { + prevts = Long.parseLong(tmp, 16); + journal.skipTo(prevts); + } catch (NumberFormatException ex) { + // broken etag + } + } + } + + boolean hasPersistEvents = false; + + if (outputContext.hasStream()) { + + long lastts = -1; + long now = System.currentTimeMillis(); + boolean done = false; + + // collect events + List events = new ArrayList(MAXEV); + + while (!done && journal.hasNext()) { + Event e = journal.nextEvent(); + + hasPersistEvents |= e.getType() == Event.PERSIST; + + if (e.getDate() != lastts) { + // consider stopping + if (events.size() > MAXEV) { + done = true; + } + if (e.getDate() > now + MAXWAIT) { + done = true; + } + } + + if (!done && (prevts == -1 || e.getDate() >= prevts)) { + events.add(e); + } + + lastts = e.getDate(); + } + + if (lastts >= 0) { + // construct ETag from newest event + outputContext.setETag("\"" + Long.toHexString(lastts) + "\""); + } + + OutputStream os = outputContext.getOutputStream(); + StreamResult streamResult = new StreamResult(os); + SAXTransformerFactory tf = (SAXTransformerFactory) TransformerFactory.newInstance(); + TransformerHandler th = tf.newTransformerHandler(); + Transformer s = th.getTransformer(); + s.setOutputProperty(OutputKeys.ENCODING, "UTF-8"); + s.setOutputProperty(OutputKeys.INDENT, "yes"); + s.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes"); + + th.setResult(streamResult); + + th.startDocument(); + + th.startElement(ATOMNS, FEED, FEED, NOATTRS); + + writeAtomElement(th, TITLE, "EventJournal for " + getLocator().getWorkspaceName()); + + th.startElement(ATOMNS, AUTHOR, AUTHOR, NOATTRS); + writeAtomElement(th, NAME, "Jackrabbit Event Journal Feed Generator"); + th.endElement(ATOMNS, AUTHOR, AUTHOR); + + String id = getFullUri(request); + writeAtomElement(th, ID, id); + + AttributesImpl linkattrs = new AttributesImpl(); + linkattrs.addAttribute(null, "self", "self", "CDATA", id); + writeAtomElement(th, LINK, linkattrs, null); + + cal.setTimeInMillis(lastts >= 0 ? lastts : now); + String upd = ISO8601.format(cal); + writeAtomElement(th, UPDATED, upd); + + String lastDateString = ""; + long lastTimeStamp = 0; + long index = 0; + + AttributesImpl contentatt = new AttributesImpl(); + contentatt.addAttribute(null, "type", "type", "CDATA", EVENTMEDIATYPE); + + while (!events.isEmpty()) { + + List bundle = null; + String path = null; + String op; + + if (hasPersistEvents) { + bundle = new ArrayList(); + Event e = null; + op = "operations"; + + do { + e = events.remove(0); + bundle.add(e); + + // compute common path + if (path == null) { + path = e.getPath(); + } else { + if (e.getPath() != null && e.getPath().length() < path.length()) { + path = e.getPath(); + } + } + } while (e.getType() != Event.PERSIST && !events.isEmpty()); + } else { + // no persist events + Event e = events.remove(0); + bundle = Collections.singletonList(e); + path = e.getPath(); + op = EventUtil.getEventName(e.getType()); + } + + Event firstEvent = bundle.get(0); + + String entryupd = lastDateString; + if (lastTimeStamp != firstEvent.getDate()) { + cal.setTimeInMillis(firstEvent.getDate()); + entryupd = ISO8601.format(cal); + index = 0; + } else { + index += 1; + } + + th.startElement(ATOMNS, ENTRY, ENTRY, NOATTRS); + + String entrytitle = op + (path != null ? (": " + path) : ""); + writeAtomElement(th, TITLE, entrytitle); + + String entryid = id + "?type=journal&ts=" + Long.toHexString(firstEvent.getDate()) + "-" + index; + writeAtomElement(th, ID, entryid); + + String author = firstEvent.getUserID() == null || firstEvent.getUserID().length() == 0 ? null + : firstEvent.getUserID(); + if (author != null) { + th.startElement(ATOMNS, AUTHOR, AUTHOR, NOATTRS); + writeAtomElement(th, NAME, author); + th.endElement(ATOMNS, AUTHOR, AUTHOR); + } + + writeAtomElement(th, UPDATED, entryupd); + + th.startElement(ATOMNS, CONTENT, CONTENT, contentatt); + + for (Event e : bundle) { + + // serialize the event + th.startElement(EVNS, E_EVENT, E_EVENT, NOATTRS); + + // DAV:href + if (e.getPath() != null) { + boolean isCollection = (e.getType() == Event.NODE_ADDED || e.getType() == Event.NODE_REMOVED); + String href = locator + .getFactory() + .createResourceLocator(locator.getPrefix(), locator.getWorkspacePath(), + e.getPath(), false).getHref(isCollection); + th.startElement(DavConstants.NAMESPACE.getURI(), DavConstants.XML_HREF, + DavConstants.XML_HREF, NOATTRS); + th.characters(href.toCharArray(), 0, href.length()); + th.endElement(DavConstants.NAMESPACE.getURI(), DavConstants.XML_HREF, DavConstants.XML_HREF); + } + + // event type + String evname = EventUtil.getEventName(e.getType()); + th.startElement(EVNS, E_EVENTTYPE, E_EVENTTYPE, NOATTRS); + th.startElement(EVNS, evname, evname, NOATTRS); + th.endElement(EVNS, evname, evname); + th.endElement(EVNS, E_EVENTTYPE, E_EVENTTYPE); + + // date + writeObsElement(th, E_EVENTDATE, Long.toString(e.getDate())); + + // user data + if (e.getUserData() != null && e.getUserData().length() > 0) { + writeObsElement(th, E_EVENTUSERDATA, firstEvent.getUserData()); + } + + // user id: already sent as Atom author/name + + // try to compute nodetype information + if (e instanceof AdditionalEventInfo) { + try { + Name pnt = ((AdditionalEventInfo) e).getPrimaryNodeTypeName(); + if (pnt != null) { + writeObsElement(th, E_EVENTPRIMARNODETYPE, pnt.toString()); + } + + Set mixins = ((AdditionalEventInfo) e).getMixinTypeNames(); + if (mixins != null) { + for (Name mixin : mixins) { + writeObsElement(th, E_EVENTMIXINNODETYPE, mixin.toString()); + } + } + + } catch (UnsupportedRepositoryOperationException ex) { + // optional + } + } + + // identifier + if (e.getIdentifier() != null) { + writeObsElement(th, E_EVENTIDENTIFIER, e.getIdentifier()); + } + + // info + if (!e.getInfo().isEmpty()) { + th.startElement(EVNS, E_EVENTINFO, E_EVENTINFO, NOATTRS); + Map m = e.getInfo(); + for (Map.Entry entry : m.entrySet()) { + String key = entry.getKey().toString(); + Object value = entry.getValue(); + String t = value != null ? value.toString() : null; + writeElement(th, null, key, NOATTRS, t); + } + th.endElement(EVNS, E_EVENTINFO, E_EVENTINFO); + } + + th.endElement(EVNS, E_EVENT, E_EVENT); + + lastTimeStamp = e.getDate(); + lastDateString = entryupd; + } + + th.endElement(ATOMNS, CONTENT, CONTENT); + th.endElement(ATOMNS, ENTRY, ENTRY); + } + + th.endElement(ATOMNS, FEED, FEED); + + th.endDocument(); + + os.flush(); + } + } catch (Exception ex) { + throw new IOException("error generating feed: " + ex.getMessage()); + } + } + + @Override + public DavResource getCollection() { + return null; + } + + @Override + public void addMember(DavResource resource, InputContext inputContext) throws DavException { + throw new DavException(DavServletResponse.SC_FORBIDDEN); + } + + @Override + public DavResourceIterator getMembers() { + return DavResourceIteratorImpl.EMPTY; + } + + @Override + public void removeMember(DavResource member) throws DavException { + throw new DavException(DavServletResponse.SC_FORBIDDEN); + } + + @Override + protected void initLockSupport() { + // lock not allowed + } + + @Override + protected String getWorkspaceHref() { + return getHref(); + } + + private void writeElement(TransformerHandler th, String ns, String name, Attributes attrs, String textContent) + throws SAXException { + th.startElement(ns, name, name, attrs); + if (textContent != null) { + th.characters(textContent.toCharArray(), 0, textContent.length()); + } + th.endElement(ns, name, name); + } + + private void writeAtomElement(TransformerHandler th, String name, Attributes attrs, String textContent) + throws SAXException { + writeElement(th, ATOMNS, name, attrs, textContent); + } + + private void writeAtomElement(TransformerHandler th, String name, String textContent) throws SAXException { + writeAtomElement(th, name, NOATTRS, textContent); + } + + private void writeObsElement(TransformerHandler th, String name, String textContent) throws SAXException { + writeElement(th, EVNS, name, NOATTRS, textContent); + } + + private String getFullUri(HttpServletRequest req) { + + String scheme = req.getScheme(); + int port = req.getServerPort(); + boolean isDefaultPort = (scheme.equals("http") && port == 80) || (scheme.equals("http") && port == 443); + String query = request.getQueryString() != null ? "?" + request.getQueryString() : ""; + + return String.format("%s://%s%s%s%s%s", scheme, req.getServerName(), isDefaultPort ? ":" : "", + isDefaultPort ? Integer.toString(port) : "", req.getRequestURI(), query); + } +} Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/EventJournalResourceImpl.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/webdav/jcr/ItemResourceConstants.java =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/ItemResourceConstants.java (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/ItemResourceConstants.java (working copy) @@ -0,0 +1,125 @@ +/* + * 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.webdav.jcr; + +import javax.jcr.Session; + +import org.apache.jackrabbit.commons.webdav.JcrRemotingConstants; +import org.apache.jackrabbit.webdav.DavResource; +import org.apache.jackrabbit.webdav.lock.Scope; +import org.apache.jackrabbit.webdav.observation.ObservationResource; +import org.apache.jackrabbit.webdav.property.DavPropertyName; +import org.apache.jackrabbit.webdav.search.SearchResource; +import org.apache.jackrabbit.webdav.security.Privilege; +import org.apache.jackrabbit.webdav.version.DeltaVResource; +import org.apache.jackrabbit.webdav.xml.Namespace; + +/** + * ItemResourceConstants provides constants for any resources + * representing repository items. + */ +public interface ItemResourceConstants extends JcrRemotingConstants { + + /** + * Methods common to all item resources. + */ + public static final String METHODS = DavResource.METHODS + ", " + ObservationResource.METHODS + ", " + SearchResource.METHODS + ", " +DeltaVResource.METHODS; + + /** + * The namespace for all jcr specific extensions. + */ + public static final Namespace NAMESPACE = Namespace.getNamespace(NS_PREFIX, NS_URI); + + /** + * Extension to the WebDAV 'exclusive' lock, that allows to distinguish + * the session-scoped and open-scoped locks on a JCR node. + * + * @see javax.jcr.Node#lock(boolean, boolean) + */ + public static final Scope EXCLUSIVE_SESSION = Scope.create(XML_EXCLUSIVE_SESSION_SCOPED, NAMESPACE); + + // name of the workspace for which the repository session has been created. + public static final DavPropertyName JCR_WORKSPACE_NAME = DavPropertyName.create(JCR_WORKSPACE_NAME_LN, NAMESPACE); + + // general property names + public static final DavPropertyName JCR_NAME = DavPropertyName.create(JCR_NAME_LN, NAMESPACE); + public static final DavPropertyName JCR_PATH = DavPropertyName.create(JCR_PATH_LN, NAMESPACE); + public static final DavPropertyName JCR_DEPTH = DavPropertyName.create(JCR_DEPTH_LN, NAMESPACE); + public static final DavPropertyName JCR_PARENT = DavPropertyName.create(JCR_PARENT_LN, NAMESPACE); + public static final DavPropertyName JCR_ISNEW = DavPropertyName.create(JCR_ISNEW_LN, NAMESPACE); + public static final DavPropertyName JCR_ISMODIFIED = DavPropertyName.create(JCR_ISMODIFIED_LN, NAMESPACE); + public static final DavPropertyName JCR_DEFINITION = DavPropertyName.create(JCR_DEFINITION_LN, NAMESPACE); + public static final DavPropertyName JCR_SELECTOR_NAME = DavPropertyName.create(JCR_SELECTOR_NAME_LN, NAMESPACE); + + // property names used for resources representing jcr-nodes + public static final DavPropertyName JCR_PRIMARYNODETYPE = DavPropertyName.create(JCR_PRIMARYNODETYPE_LN, NAMESPACE); + public static final DavPropertyName JCR_MIXINNODETYPES = DavPropertyName.create(JCR_MIXINNODETYPES_LN, NAMESPACE); + public static final DavPropertyName JCR_INDEX = DavPropertyName.create(JCR_INDEX_LN, NAMESPACE); + public static final DavPropertyName JCR_REFERENCES = DavPropertyName.create(JCR_REFERENCES_LN, NAMESPACE); + /** + * @since JCR 2.0 + */ + public static final DavPropertyName JCR_WEAK_REFERENCES = DavPropertyName.create(JCR_WEAK_REFERENCES_LN, NAMESPACE); + public static final DavPropertyName JCR_UUID = DavPropertyName.create(JCR_UUID_LN, NAMESPACE); + public static final DavPropertyName JCR_PRIMARYITEM = DavPropertyName.create(JCR_PRIMARYITEM_LN, NAMESPACE); + + // property names used for resources representing jcr-properties + public static final DavPropertyName JCR_TYPE = DavPropertyName.create(JCR_TYPE_LN, NAMESPACE); + public static final DavPropertyName JCR_VALUE = DavPropertyName.create(JCR_VALUE_LN, NAMESPACE); + public static final DavPropertyName JCR_VALUES = DavPropertyName.create(JCR_VALUES_LN, NAMESPACE); + public static final DavPropertyName JCR_LENGTH = DavPropertyName.create(JCR_LENGTH_LN, NAMESPACE); + public static final DavPropertyName JCR_LENGTHS = DavPropertyName.create(JCR_LENGTHS_LN, NAMESPACE); + public static final DavPropertyName JCR_GET_STRING = DavPropertyName.create(JCR_GET_STRING_LN, NAMESPACE); + + // property names used for resource representing a workspace + public static final DavPropertyName JCR_NAMESPACES = DavPropertyName.create(JCR_NAMESPACES_LN, NAMESPACE); + public static final DavPropertyName JCR_NODETYPES_CND = DavPropertyName.create(JCR_NODETYPES_CND_LN, NAMESPACE); + + // property names used for resource representing a version history + public static final DavPropertyName JCR_VERSIONABLEUUID = DavPropertyName.create(JCR_VERSIONABLEUUID_LN, NAMESPACE); + + //-----------------------------------------< JSR170 specific privileges >--- + /** + * Privilege representing the JSR170 'read' action. + *

Note: the name of this constant is somewhat misleading + * as it corresponds to {@link javax.jcr.Session#ACTION_READ} and not + * to {@link javax.jcr.security.Privilege#JCR_READ}.

+ */ + public static final Privilege PRIVILEGE_JCR_READ = Privilege.getPrivilege(Session.ACTION_READ, NAMESPACE); + /** + * Privilege representing the JSR170 'add_node' action. + *

Note: the name of this constant is somewhat misleading + * as it corresponds to {@link javax.jcr.Session#ACTION_ADD_NODE} and not + * to {@link javax.jcr.security.Privilege#JCR_ADD_CHILD_NODES}.

+ */ + public static final Privilege PRIVILEGE_JCR_ADD_NODE = Privilege.getPrivilege(Session.ACTION_ADD_NODE, NAMESPACE); + /** + * Privilege representing the JSR170 'set_property' action. + *

Note: the name of this constant is somewhat misleading + * as it corresponds to {@link javax.jcr.Session#ACTION_SET_PROPERTY} and not + * to {@link javax.jcr.security.Privilege#JCR_MODIFY_PROPERTIES}.

+ */ + public static final Privilege PRIVILEGE_JCR_SET_PROPERTY = Privilege.getPrivilege(Session.ACTION_SET_PROPERTY, NAMESPACE); + /** + * Privilege representing the JSR170 'remove' action. + *

Note: the name of this constant is somewhat misleading + * as it corresponds to {@link javax.jcr.Session#ACTION_REMOVE} and not + * to {@link javax.jcr.security.Privilege#JCR_REMOVE_NODE} or + * {@link javax.jcr.security.Privilege#JCR_REMOVE_CHILD_NODES}.

+ */ + public static final Privilege PRIVILEGE_JCR_REMOVE = Privilege.getPrivilege(Session.ACTION_REMOVE, NAMESPACE); +} Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/ItemResourceConstants.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/webdav/jcr/JCRWebdavServerServlet.java =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/JCRWebdavServerServlet.java (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/JCRWebdavServerServlet.java (working copy) @@ -0,0 +1,321 @@ +/* + * 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.webdav.jcr; + +import org.apache.jackrabbit.server.BasicCredentialsProvider; +import org.apache.jackrabbit.server.CredentialsProvider; +import org.apache.jackrabbit.server.SessionProvider; +import org.apache.jackrabbit.server.SessionProviderImpl; +import org.apache.jackrabbit.server.jcr.JCRWebdavServer; +import org.apache.jackrabbit.webdav.DavException; +import org.apache.jackrabbit.webdav.DavLocatorFactory; +import org.apache.jackrabbit.webdav.DavMethods; +import org.apache.jackrabbit.webdav.DavResource; +import org.apache.jackrabbit.webdav.DavResourceFactory; +import org.apache.jackrabbit.webdav.DavServletResponse; +import org.apache.jackrabbit.webdav.DavSessionProvider; +import org.apache.jackrabbit.webdav.WebdavRequest; +import org.apache.jackrabbit.webdav.jcr.observation.SubscriptionManagerImpl; +import org.apache.jackrabbit.webdav.jcr.transaction.TxLockManagerImpl; +import org.apache.jackrabbit.webdav.observation.SubscriptionManager; +import org.apache.jackrabbit.webdav.server.AbstractWebdavServlet; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.jcr.Repository; +import javax.jcr.Session; +import javax.servlet.ServletContext; +import javax.servlet.ServletException; + +/** + * JCRWebdavServerServlet provides request/response handling for the + * JCRWebdavServer. + *

+ * Implementations of this abstract class must implement the + * {@link #getRepository()} method to access the repository. + */ +public abstract class JCRWebdavServerServlet extends AbstractWebdavServlet { + + /** + * the default logger + */ + private static Logger log = LoggerFactory.getLogger(JCRWebdavServerServlet.class); + + /** + * Init parameter specifying the prefix used with the resource path. + */ + public static final String INIT_PARAM_RESOURCE_PATH_PREFIX = "resource-path-prefix"; + + /** + * Optional 'concurrency-level' parameter defining the concurrency level + * within the jcr-server. If the parameter is omitted the internal default + * value (50) is used. + */ + public final static String INIT_PARAM_CONCURRENCY_LEVEL = "concurrency-level"; + + /** + * Servlet context attribute used to store the path prefix instead of + * having a static field with this servlet. The latter causes problems + * when running multiple + */ + public static final String CTX_ATTR_RESOURCE_PATH_PREFIX = "jackrabbit.webdav.jcr.resourcepath"; + + private String pathPrefix; + + private JCRWebdavServer server; + private DavResourceFactory resourceFactory; + private DavLocatorFactory locatorFactory; + protected TxLockManagerImpl txMgr; + protected SubscriptionManager subscriptionMgr; + + /** + * Initializes the servlet set reads the following parameter from the + * servlet configuration: + *

    + *
  • resource-path-prefix: optional prefix for all resources.
  • + *
+ * + * @throws ServletException + */ + @Override + public void init() throws ServletException { + super.init(); + + // set resource path prefix + pathPrefix = getInitParameter(INIT_PARAM_RESOURCE_PATH_PREFIX); + getServletContext().setAttribute(CTX_ATTR_RESOURCE_PATH_PREFIX, pathPrefix); + log.debug(INIT_PARAM_RESOURCE_PATH_PREFIX + " = " + pathPrefix); + + txMgr = new TxLockManagerImpl(); + subscriptionMgr = new SubscriptionManagerImpl(); + txMgr.addTransactionListener((SubscriptionManagerImpl) subscriptionMgr); + + // todo: eventually make configurable + resourceFactory = new DavResourceFactoryImpl(txMgr, subscriptionMgr); + locatorFactory = new DavLocatorFactoryImpl(pathPrefix); + } + + /** + * Returns true if the preconditions are met. This includes validation of + * {@link WebdavRequest#matchesIfHeader(DavResource) If header} and validation + * of {@link org.apache.jackrabbit.webdav.transaction.TransactionConstants#HEADER_TRANSACTIONID + * TransactionId header}. This method will also return false if the requested + * resource resides within a different workspace as is assigned to the repository + * session attached to the given request. + * + * @see AbstractWebdavServlet#isPreconditionValid(WebdavRequest, DavResource) + */ + @Override + protected boolean isPreconditionValid(WebdavRequest request, DavResource resource) { + // first check matching If header + if (!request.matchesIfHeader(resource)) { + return false; + } + + // test if the requested path matches to the existing session + // this may occur if the session was retrieved from the cache. + try { + Session repositorySesssion = JcrDavSession.getRepositorySession(request.getDavSession()); + String reqWspName = resource.getLocator().getWorkspaceName(); + String wsName = repositorySesssion.getWorkspace().getName(); + // compare workspace names if the requested resource isn't the + // root-collection and the request not MKWORKSPACE. + if (DavMethods.DAV_MKWORKSPACE != DavMethods.getMethodCode(request.getMethod()) && + reqWspName != null && !reqWspName.equals(wsName)) { + return false; + } + } catch (DavException e) { + log.error("Internal error: " + e.toString()); + return false; + } + + + // make sure, the TransactionId header is valid + String txId = request.getTransactionId(); + return txId == null || txMgr.hasLock(txId, resource); + } + + /** + * Returns the DavSessionProvider + * + * @return server + * @see AbstractWebdavServlet#getDavSessionProvider() + */ + @Override + public DavSessionProvider getDavSessionProvider() { + if (server == null) { + Repository repository = getRepository(); + String cl = getInitParameter(INIT_PARAM_CONCURRENCY_LEVEL); + if (cl != null) { + try { + server = new JCRWebdavServer(repository, getSessionProvider(), Integer.parseInt(cl)); + } catch (NumberFormatException e) { + log.debug("Invalid value '" + cl+ "' for init-param 'concurrency-level'. Using default instead."); + server = new JCRWebdavServer(repository, getSessionProvider()); + } + } else { + server = new JCRWebdavServer(repository, getSessionProvider()); + } + } + return server; + } + + /** + * Throws UnsupportedOperationException. + * + * @see AbstractWebdavServlet#setDavSessionProvider(DavSessionProvider) + */ + @Override + public void setDavSessionProvider(DavSessionProvider davSessionProvider) { + throw new UnsupportedOperationException("Not implemented. DavSession(s) are provided by the 'JCRWebdavServer'"); + } + + /** + * Returns the DavLocatorFactory + * + * @see AbstractWebdavServlet#getLocatorFactory() + */ + @Override + public DavLocatorFactory getLocatorFactory() { + if (locatorFactory == null) { + locatorFactory = new DavLocatorFactoryImpl(pathPrefix); + } + return locatorFactory; + } + + /** + * Sets the DavLocatorFactory + * + * @see AbstractWebdavServlet#setLocatorFactory(DavLocatorFactory) + */ + @Override + public void setLocatorFactory(DavLocatorFactory locatorFactory) { + this.locatorFactory = locatorFactory; + } + + /** + * Returns the DavResourceFactory. + * + * @see AbstractWebdavServlet#getResourceFactory() + */ + @Override + public DavResourceFactory getResourceFactory() { + if (resourceFactory == null) { + resourceFactory = new DavResourceFactoryImpl(txMgr, subscriptionMgr); + } + return resourceFactory; + } + + /** + * Sets the DavResourceFactory. + * + * @see AbstractWebdavServlet#setResourceFactory(org.apache.jackrabbit.webdav.DavResourceFactory) + */ + @Override + public void setResourceFactory(DavResourceFactory resourceFactory) { + this.resourceFactory = resourceFactory; + } + + /** + * Modified variant needed for JCR move and copy that isn't compliant to + * WebDAV. The latter requires both methods to fail if the destination already + * exists and Overwrite is set to F (false); in JCR however this depends on + * the node type characteristics of the parent (SNSiblings allowed or not). + * + * @param destResource destination resource to be validated. + * @param request The webdav request + * @param checkHeader flag indicating if the destination header must be present. + * @return status code indicating whether the destination is valid. + */ + @Override + protected int validateDestination(DavResource destResource, WebdavRequest request, boolean checkHeader) + throws DavException { + + if (checkHeader) { + String destHeader = request.getHeader(HEADER_DESTINATION); + if (destHeader == null || "".equals(destHeader)) { + return DavServletResponse.SC_BAD_REQUEST; + } + } + if (destResource.getLocator().equals(request.getRequestLocator())) { + return DavServletResponse.SC_FORBIDDEN; + } + + int status; + if (destResource.exists()) { + if (request.isOverwrite()) { + // matching if-header required for existing resources + if (!request.matchesIfHeader(destResource)) { + return DavServletResponse.SC_PRECONDITION_FAILED; + } else { + // overwrite existing resource + destResource.getCollection().removeMember(destResource); + status = DavServletResponse.SC_NO_CONTENT; + } + } else { + /* NO overwrite header: + + but, instead of return the 412 Precondition-Failed code required + by the WebDAV specification(s) leave the validation to the + JCR repository. + */ + status = DavServletResponse.SC_CREATED; + } + + } else { + // destination does not exist >> copy/move can be performed + status = DavServletResponse.SC_CREATED; + } + return status; + } + + /** + * Returns the configured path prefix + * + * @param ctx The servlet context. + * @return resourcePathPrefix + * @see #INIT_PARAM_RESOURCE_PATH_PREFIX + */ + public static String getPathPrefix(ServletContext ctx) { + return (String) ctx.getAttribute(CTX_ATTR_RESOURCE_PATH_PREFIX); + } + + /** + * Returns the repository to be used by this servlet. + * + * @return the JCR repository to be used by this servlet + */ + protected abstract Repository getRepository(); + + /** + * Returns a new instanceof BasicCredentialsProvider. + * + * @return a new credentials provider + */ + protected CredentialsProvider getCredentialsProvider() { + return new BasicCredentialsProvider(getInitParameter(INIT_PARAM_MISSING_AUTH_MAPPING)); + } + + /** + * Returns a new instanceof SessionProviderImpl. + * + * @return a new session provider + */ + protected SessionProvider getSessionProvider() { + return new SessionProviderImpl(getCredentialsProvider()); + } +} Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/JCRWebdavServerServlet.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/webdav/jcr/JcrDavException.java =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/JcrDavException.java (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/JcrDavException.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.webdav.jcr; + +import org.apache.jackrabbit.webdav.DavConstants; +import org.apache.jackrabbit.webdav.DavException; +import org.apache.jackrabbit.webdav.DavServletResponse; +import org.apache.jackrabbit.webdav.xml.DomUtil; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +import javax.jcr.AccessDeniedException; +import javax.jcr.InvalidItemStateException; +import javax.jcr.InvalidSerializedDataException; +import javax.jcr.ItemExistsException; +import javax.jcr.ItemNotFoundException; +import javax.jcr.LoginException; +import javax.jcr.MergeException; +import javax.jcr.NamespaceException; +import javax.jcr.NoSuchWorkspaceException; +import javax.jcr.PathNotFoundException; +import javax.jcr.ReferentialIntegrityException; +import javax.jcr.RepositoryException; +import javax.jcr.UnsupportedRepositoryOperationException; +import javax.jcr.ValueFormatException; +import javax.jcr.lock.LockException; +import javax.jcr.nodetype.ConstraintViolationException; +import javax.jcr.nodetype.NoSuchNodeTypeException; +import javax.jcr.query.InvalidQueryException; +import javax.jcr.version.VersionException; +import java.util.Map; +import java.util.LinkedHashMap; + + +/** + * JcrDavException extends the {@link DavException} in order to + * wrap various repository exceptions. + */ +public class JcrDavException extends DavException { + + private static Logger log = LoggerFactory.getLogger(JcrDavException.class); + + // ordered mapping of Jcr exceptions to error codes. + private static Map, Integer> codeMap = new LinkedHashMap, Integer>(20); + static { + codeMap.put(AccessDeniedException.class, DavServletResponse.SC_FORBIDDEN); + codeMap.put(ConstraintViolationException.class, DavServletResponse.SC_CONFLICT); + codeMap.put(InvalidItemStateException.class, DavServletResponse.SC_CONFLICT); + codeMap.put(InvalidSerializedDataException.class, DavServletResponse.SC_BAD_REQUEST); + codeMap.put(InvalidQueryException.class, DavServletResponse.SC_BAD_REQUEST); + codeMap.put(ItemExistsException.class, DavServletResponse.SC_CONFLICT); + codeMap.put(ItemNotFoundException.class, DavServletResponse.SC_FORBIDDEN); + codeMap.put(LockException.class, DavServletResponse.SC_LOCKED); + codeMap.put(MergeException.class, DavServletResponse.SC_CONFLICT); + codeMap.put(NamespaceException.class, DavServletResponse.SC_CONFLICT); + codeMap.put(NoSuchNodeTypeException.class, DavServletResponse.SC_CONFLICT); + codeMap.put(NoSuchWorkspaceException.class, DavServletResponse.SC_CONFLICT); + codeMap.put(PathNotFoundException.class, DavServletResponse.SC_CONFLICT); + codeMap.put(ReferentialIntegrityException.class, DavServletResponse.SC_CONFLICT); + codeMap.put(LoginException.class, DavServletResponse.SC_UNAUTHORIZED); + codeMap.put(UnsupportedRepositoryOperationException.class, DavServletResponse.SC_NOT_IMPLEMENTED); + codeMap.put(ValueFormatException.class, DavServletResponse.SC_CONFLICT); + codeMap.put(VersionException.class, DavServletResponse.SC_CONFLICT); + codeMap.put(RepositoryException.class, DavServletResponse.SC_FORBIDDEN); + } + + private static int lookupErrorCode(Class exceptionClass) { + Integer code = codeMap.get(exceptionClass); + if (code == null) { + for (Class jcrExceptionClass : codeMap.keySet()) { + if (jcrExceptionClass.isAssignableFrom(exceptionClass)) { + code = codeMap.get(jcrExceptionClass); + break; + } + } + if (code == null) { + code = DavServletResponse.SC_FORBIDDEN; // fallback + } + } + return code; + } + + /** + * The exception wrapped by this DavException instance. + */ + private Class exceptionClass; + + /** + * Create a new JcrDavException. + * + * @param cause The original cause of this DavException. Note, that + * in contrast to {@link Throwable#Throwable(Throwable)}, {@link Throwable#Throwable(String, Throwable)} and + * {@link Throwable#initCause(Throwable)} the cause must not be null. + * @param errorCode Status code for the response. + * @throws NullPointerException if the given exception is null. + * @see DavException#DavException(int, String) + * @see DavException#DavException(int) + */ + public JcrDavException(Throwable cause, int errorCode) { + super(errorCode, cause.getMessage(), cause, null); + exceptionClass = cause.getClass(); + if (log.isDebugEnabled()) { + log.debug("Handling exception with error code " + errorCode, cause); + } + } + + /** + * Same as {@link JcrDavException#JcrDavException(Throwable, int)} where the + * error code is retrieved from an internal mapping. + * + * @param cause Cause of this DavException + * @throws NullPointerException if the given exception is null. + * @see JcrDavException#JcrDavException(Throwable, int) + */ + public JcrDavException(RepositoryException cause) { + this(cause, lookupErrorCode(cause.getClass())); + } + + /** + * Always returns true. + * + * @return true + */ + @Override + public boolean hasErrorCondition() { + return true; + } + + /** + * Returns a DAV:error Xml element containing the exceptions class and the + * message as child elements. + * + * @return Xml representation of this exception. + * @see org.apache.jackrabbit.webdav.xml.XmlSerializable#toXml(Document) + * @param document + */ + @Override + public Element toXml(Document document) { + Element error = DomUtil.createElement(document, XML_ERROR, DavConstants.NAMESPACE); + Element excep = DomUtil.createElement(document, "exception", ItemResourceConstants.NAMESPACE); + DomUtil.addChildElement(excep, "class", ItemResourceConstants.NAMESPACE, exceptionClass.getName()); + DomUtil.addChildElement(excep, "message", ItemResourceConstants.NAMESPACE, getMessage()); + error.appendChild(excep); + return error; + } +} Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/JcrDavException.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/webdav/jcr/JcrDavSession.java =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/JcrDavSession.java (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/JcrDavSession.java (working copy) @@ -0,0 +1,140 @@ +/* + * 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.webdav.jcr; + +import org.apache.jackrabbit.webdav.DavException; +import org.apache.jackrabbit.webdav.DavServletResponse; +import org.apache.jackrabbit.webdav.DavSession; +import org.apache.jackrabbit.webdav.jcr.lock.LockTokenMapper; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.jcr.RepositoryException; +import javax.jcr.Session; +import java.util.HashSet; + +/** + * JcrDavSession specific base implementation of the + * DavSession interface, which simply wraps a {@link Session} + * object. This implementation adds a utility method that allows to + * {@link #getRepositorySession() unwrap} the underlying repository session. + *
+ * Note, that in this basic implementation the following methods are simply + * forwarded to the corresponding call on Session: + *
    + *
  • {@link #getLockTokens()} => {@link Session#getLockTokens()}
  • + *
  • {@link #addLockToken(String)} => {@link Session#addLockToken(String)}
  • + *
  • {@link #removeLockToken(String)} => {@link Session#removeLockToken(String)}
  • + *
+ * Subclasses may overwrite or extend this behaviour. + */ +public abstract class JcrDavSession implements DavSession { + + private static Logger log = LoggerFactory.getLogger(JcrDavSession.class); + + /** the underlying jcr session */ + private final Session session; + + /** the lock tokens of this session */ + private final HashSet lockTokens = new HashSet(); + + /** + * + * @param session + */ + protected JcrDavSession(Session session) { + this.session = session; + } + + /** + * + * @param davSession + * @throws DavException + */ + public static void checkImplementation(DavSession davSession) throws DavException { + if (!(davSession instanceof JcrDavSession)) { + throw new DavException(DavServletResponse.SC_INTERNAL_SERVER_ERROR, "JCR specific DavSession expected. Found: " + davSession); + } + } + + /** + * + * @param davSession + * @return + * @throws DavException + */ + public static Session getRepositorySession(DavSession davSession) throws DavException { + checkImplementation(davSession); + return ((JcrDavSession)davSession).getRepositorySession(); + } + + /** + * Unwrap the {@link Session repository session} object. + * + * @return the session object wrapped by this DavSession + */ + public Session getRepositorySession() { + return session; + } + + //---------------------------------------------------------< DavSession >--- + /** + * + * @param token + * @see DavSession#addLockToken(String) + */ + @Override + public void addLockToken(String token) { + if (!LockTokenMapper.isForSessionScopedLock(token)) { + try { + session.getWorkspace().getLockManager().addLockToken(LockTokenMapper.getJcrLockToken(token)); + } + catch (RepositoryException ex) { + log.debug("trying to add lock token " + token + " to session", ex); + } + } + lockTokens.add(token); + } + + /** + * + * @return + * @see DavSession#getLockTokens() + */ + @Override + public String[] getLockTokens() { + return lockTokens.toArray(new String[lockTokens.size()]); + } + + /** + * + * @param token + * @see DavSession#removeLockToken(String) + */ + @Override + public void removeLockToken(String token) { + if (!LockTokenMapper.isForSessionScopedLock(token)) { + try { + session.getWorkspace().getLockManager().removeLockToken(LockTokenMapper.getJcrLockToken(token)); + } + catch (RepositoryException ex) { + log.debug("trying to remove lock token " + token + " to session", ex); + } + } + lockTokens.remove(token); + } +} Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/JcrDavSession.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/webdav/jcr/JcrValueType.java =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/JcrValueType.java (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/JcrValueType.java (working copy) @@ -0,0 +1,25 @@ +/* + * 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.webdav.jcr; + +/** JcrValueType... + * + * @deprecated As of Jackrabbit 2.2. Please Use {@link org.apache.jackrabbit.commons.webdav.JcrValueType} instead. + */ +public final class JcrValueType extends org.apache.jackrabbit.commons.webdav.JcrValueType { + +} \ No newline at end of file Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/JcrValueType.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/webdav/jcr/RootCollection.java =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/RootCollection.java (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/RootCollection.java (working copy) @@ -0,0 +1,310 @@ +/* + * 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.webdav.jcr; + +import java.io.IOException; +import java.io.OutputStreamWriter; +import java.io.PrintWriter; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; +import javax.jcr.Repository; +import javax.jcr.RepositoryException; +import javax.jcr.Session; +import javax.jcr.Workspace; + +import org.apache.jackrabbit.util.Text; +import org.apache.jackrabbit.webdav.DavException; +import org.apache.jackrabbit.webdav.DavResource; +import org.apache.jackrabbit.webdav.DavResourceFactory; +import org.apache.jackrabbit.webdav.DavResourceIterator; +import org.apache.jackrabbit.webdav.DavResourceIteratorImpl; +import org.apache.jackrabbit.webdav.DavResourceLocator; +import org.apache.jackrabbit.webdav.DavServletResponse; +import org.apache.jackrabbit.webdav.io.InputContext; +import org.apache.jackrabbit.webdav.io.OutputContext; +import org.apache.jackrabbit.webdav.jcr.security.JcrSupportedPrivilegesProperty; +import org.apache.jackrabbit.webdav.jcr.security.SecurityUtils; +import org.apache.jackrabbit.webdav.property.DavProperty; +import org.apache.jackrabbit.webdav.property.DavPropertyName; +import org.apache.jackrabbit.webdav.search.SearchResource; +import org.apache.jackrabbit.webdav.security.SecurityConstants; +import org.apache.jackrabbit.webdav.version.DeltaVResource; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * RootCollection represent the WebDAV root resource that does not + * represent any repository item. A call to getMembers() returns a + * DavResourceIterator containing only workspace resources + * resources, thus revealing the names of the accessible JCR workspaces. + */ +public class RootCollection extends AbstractResource { + + private static Logger log = LoggerFactory.getLogger(RootCollection.class); + + /** + * Create a new RootCollection. + * + * @param locator + * @param session + * @param factory + */ + protected RootCollection(DavResourceLocator locator, JcrDavSession session, + DavResourceFactory factory) { + super(locator, session, factory); + + // initialize the supported locks and reports + initLockSupport(); + initSupportedReports(); + } + + //--------------------------------------------------------< DavResource >--- + /** + * Returns a string listing the METHODS for this resource as it + * is required for the "Allow" response header. + * + * @return string listing the METHODS allowed + * @see org.apache.jackrabbit.webdav.DavResource#getSupportedMethods() + */ + @Override + public String getSupportedMethods() { + StringBuilder sb = new StringBuilder(DavResource.METHODS); + sb.append(", "); + sb.append(DeltaVResource.METHODS_INCL_MKWORKSPACE); + sb.append(", "); + sb.append(SearchResource.METHODS); + return sb.toString(); + } + + /** + * Returns true + * + * @return true + * @see org.apache.jackrabbit.webdav.DavResource#exists() + */ + @Override + public boolean exists() { + return true; + } + + @Override + public DavProperty getProperty(DavPropertyName name) { + DavProperty prop = super.getProperty(name); + if (prop == null) { + try { + if (SecurityConstants.SUPPORTED_PRIVILEGE_SET.equals(name)) { + prop = new JcrSupportedPrivilegesProperty(getRepositorySession()).asDavProperty(); + } + } catch (RepositoryException e) { + log.error("Failed to build SupportedPrivilegeSet property: " + e.getMessage()); + } + } + return prop; + } + + /** + * Returns true + * + * @return true + * @see org.apache.jackrabbit.webdav.DavResource#isCollection() + */ + @Override + public boolean isCollection() { + return true; + } + + /** + * Returns an empty string. + * + * @return empty string + * @see org.apache.jackrabbit.webdav.DavResource#getDisplayName() + */ + @Override + public String getDisplayName() { + return ""; + } + + /** + * Always returns 'now' + * + * @return + * @see org.apache.jackrabbit.webdav.DavResource#getModificationTime() + */ + @Override + public long getModificationTime() { + return new Date().getTime(); + } + + /** + * Sets content lengths to '0' and retrieves the modification time. + * + * @param outputContext + * @throws IOException + * @see DavResource#spool(org.apache.jackrabbit.webdav.io.OutputContext) + */ + @Override + public void spool(OutputContext outputContext) throws IOException { + if (outputContext.hasStream()) { + Session session = getRepositorySession(); + Repository rep = session.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); + String repostr = repName + " " + repVersion; + + StringBuilder sb = new StringBuilder(); + sb.append(""); + sb.append(repostr); + sb.append(""); + sb.append("

").append(repostr).append("

"); + sb.append("

Available Workspace Resources:


Powered by ").append(repName); + sb.append(" ").append(repVersion); + sb.append(""); + + outputContext.setContentLength(sb.length()); + outputContext.setModificationTime(getModificationTime()); + PrintWriter writer = new PrintWriter(new OutputStreamWriter(outputContext.getOutputStream(), "utf8")); + writer.print(sb.toString()); + writer.close(); + } else { + outputContext.setContentLength(0); + outputContext.setModificationTime(getModificationTime()); + } + } + + /** + * Always returns null + * + * @return null for the root resource is not internal member + * of any resource. + * @see org.apache.jackrabbit.webdav.DavResource#getCollection() + */ + @Override + public DavResource getCollection() { + return null; + } + + /** + * Throws exception: 403 Forbidden. + * @see DavResource#addMember(DavResource, InputContext) + */ + @Override + public void addMember(DavResource resource, InputContext inputContext) throws DavException { + throw new DavException(DavServletResponse.SC_FORBIDDEN); + } + + /** + * Returns an iterator over the member resources, which are all + * workspace resources available. + * + * @return members of this collection + * @see org.apache.jackrabbit.webdav.DavResource#getMembers() + */ + @Override + public DavResourceIterator getMembers() { + List memberList = new ArrayList(); + try { + String[] wsNames = getRepositorySession().getWorkspace().getAccessibleWorkspaceNames(); + for (String wsName : wsNames) { + String wspPath = "/" + wsName; + DavResourceLocator childLoc = getLocator().getFactory().createResourceLocator(getLocator().getPrefix(), wspPath, wspPath); + memberList.add(createResourceFromLocator(childLoc)); + } + } catch (RepositoryException e) { + log.error(e.getMessage()); + } catch (DavException e) { + // should never occur + log.error(e.getMessage()); + } + return new DavResourceIteratorImpl(memberList); + } + + /** + * Calls {@link Workspace#deleteWorkspace(String)} for the workspace with + * the name as indicated by the specified member. + * + * @see DavResource#removeMember(org.apache.jackrabbit.webdav.DavResource) + */ + @Override + public void removeMember(DavResource member) throws DavException { + Workspace wsp = getRepositorySession().getWorkspace(); + String name = Text.getName(member.getResourcePath()); + try { + wsp.deleteWorkspace(name); + } catch (RepositoryException e) { + throw new JcrDavException(e); + } + } + + //-----------------------------------------------------< DeltaVResource >--- + /** + * @see DeltaVResource#addWorkspace(org.apache.jackrabbit.webdav.DavResource) + */ + @Override + public void addWorkspace(DavResource workspace) throws DavException { + Workspace wsp = getRepositorySession().getWorkspace(); + String name = workspace.getDisplayName(); + try { + wsp.createWorkspace(name); + } catch (RepositoryException e) { + throw new JcrDavException(e); + } + } + + //-------------------------------------------------------------------------- + /** + * @see AbstractResource#initLockSupport() + */ + @Override + protected void initLockSupport() { + // no locking supported + } + + /** + * Since the root resource does not represent a repository item and therefore + * is not member of a workspace resource, this method always returns + * null. + * + * @return null + * @see AbstractResource#getWorkspaceHref() + */ + @Override + protected String getWorkspaceHref() { + return null; + } + + @Override + protected void initPropertyNames() { + super.initPropertyNames(); + if (SecurityUtils.supportsAccessControl(getRepositorySession())) { + names.add(SecurityConstants.SUPPORTED_PRIVILEGE_SET); + } + } +} Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/RootCollection.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/webdav/jcr/VersionControlledItemCollection.java =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/VersionControlledItemCollection.java (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/VersionControlledItemCollection.java (working copy) @@ -0,0 +1,704 @@ +/* + * 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.webdav.jcr; + +import org.apache.jackrabbit.JcrConstants; +import org.apache.jackrabbit.webdav.DavConstants; +import org.apache.jackrabbit.webdav.DavException; +import org.apache.jackrabbit.webdav.DavLocatorFactory; +import org.apache.jackrabbit.webdav.DavResource; +import org.apache.jackrabbit.webdav.DavResourceFactory; +import org.apache.jackrabbit.webdav.DavResourceLocator; +import org.apache.jackrabbit.webdav.DavServletResponse; +import org.apache.jackrabbit.webdav.MultiStatus; +import org.apache.jackrabbit.webdav.MultiStatusResponse; +import org.apache.jackrabbit.webdav.jcr.property.JcrDavPropertyNameSet; +import org.apache.jackrabbit.webdav.property.DavPropertyName; +import org.apache.jackrabbit.webdav.property.DefaultDavProperty; +import org.apache.jackrabbit.webdav.property.HrefProperty; +import org.apache.jackrabbit.webdav.property.DavProperty; +import org.apache.jackrabbit.webdav.property.PropEntry; +import org.apache.jackrabbit.webdav.version.LabelInfo; +import org.apache.jackrabbit.webdav.version.MergeInfo; +import org.apache.jackrabbit.webdav.version.UpdateInfo; +import org.apache.jackrabbit.webdav.version.VersionControlledResource; +import org.apache.jackrabbit.webdav.version.VersionHistoryResource; +import org.apache.jackrabbit.webdav.version.VersionResource; +import org.apache.jackrabbit.webdav.version.VersionableResource; +import org.apache.jackrabbit.webdav.version.report.ReportType; +import org.apache.jackrabbit.webdav.version.report.SupportedReportSetProperty; +import org.apache.jackrabbit.webdav.xml.DomUtil; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.w3c.dom.Element; + +import javax.jcr.Item; +import javax.jcr.Node; +import javax.jcr.NodeIterator; +import javax.jcr.RepositoryException; +import javax.jcr.Session; +import javax.jcr.Value; +import javax.jcr.ValueFormatException; +import javax.jcr.observation.EventListener; +import javax.jcr.version.Version; +import javax.jcr.version.VersionHistory; +import javax.jcr.version.VersionManager; +import java.util.List; +import java.util.Collections; + +/** + * VersionControlledItemCollection represents a JCR node item and + * covers all functionality related to versioning of {@link Node}s. + * + * @see Node + */ +public class VersionControlledItemCollection extends DefaultItemCollection + implements VersionControlledResource { + + private static Logger log = LoggerFactory.getLogger(VersionControlledItemCollection.class); + + /** + * Create a new VersionControlledItemCollection. + * + * @param locator + * @param session + * @param factory + * @param item + */ + public VersionControlledItemCollection(DavResourceLocator locator, + JcrDavSession session, + DavResourceFactory factory, + Item item) { + super(locator, session, factory, item); + if (exists() && !(item instanceof Node)) { + throw new IllegalArgumentException("A collection resource can not be constructed from a Property item."); + } + } + + //----------------------------------------------< DavResource interface >--- + /** + * Return a comma separated string listing the supported method names. + * + * @return the supported method names. + * @see org.apache.jackrabbit.webdav.DavResource#getSupportedMethods() + */ + @Override + public String getSupportedMethods() { + StringBuffer sb = new StringBuffer(super.getSupportedMethods()); + // Versioning support + sb.append(", ").append(VersionableResource.METHODS); + if (isVersionControlled()) { + try { + if (((Node)item).isCheckedOut()) { + sb.append(", ").append(VersionControlledResource.methods_checkedOut); + } else { + sb.append(", ").append(VersionControlledResource.methods_checkedIn); + } + } catch (RepositoryException e) { + // should not occur. + log.error(e.getMessage()); + } + } + return sb.toString(); + } + + @Override + public DavProperty getProperty(DavPropertyName name) { + DavProperty prop = super.getProperty(name); + if (prop == null && isVersionControlled()) { + Node n = (Node) item; + // properties defined by RFC 3253 for version-controlled resources + // workspace property already set in AbstractResource.initProperties() + try { + if (VERSION_HISTORY.equals(name)) { + // DAV:version-history (computed) + String vhHref = getLocatorFromItem(n.getVersionHistory()).getHref(true); + prop = new HrefProperty(VERSION_HISTORY, vhHref, true); + } else if (CHECKED_OUT.equals(name) && n.isCheckedOut()) { + // DAV:checked-out property (protected) + String baseVHref = getLocatorFromItem(n.getBaseVersion()).getHref(true); + prop = new HrefProperty(CHECKED_OUT, baseVHref, true); + } else if (CHECKED_IN.equals(name) && !n.isCheckedOut()) { + // DAV:checked-in property (protected) + String baseVHref = getLocatorFromItem(n.getBaseVersion()).getHref(true); + prop = new HrefProperty(CHECKED_IN, baseVHref, true); + } + } catch (RepositoryException e) { + log.error(e.getMessage()); + } + } + + return prop; + } + + /** + * @param changeList + * @throws DavException + * @see DefaultItemCollection#alterProperties(List) + * for additional description of non-compliant behaviour. + */ + @Override + public MultiStatusResponse alterProperties(List changeList) throws DavException { + /* first resolve merge conflict since they cannot be handled by + setting property values in jcr (and are persisted immediately). + NOTE: this violates RFC 2518 that requires that proppatch + is processed in the order entries are present in the xml and that + required that no changes must be persisted if any set/remove fails. + */ + // TODO: solve violation of RFC 2518 + resolveMergeConflict(changeList); + // alter other properties only if merge-conflicts could be handled + return super.alterProperties(changeList); + } + + /** + * Resolve one or multiple merge conflicts present on this resource. Please + * note that the 'setProperties' or 'removeProperties' set my contain additional + * resource properties, that need to be changed. Those properties are left + * untouched, whereas the {@link #AUTO_MERGE_SET DAV:auto-merge-set}, is + * removed from the list upon successful resolution of a merge conflict.
+ * If the removeProperties or setProperties set do not contain the mentioned + * merge conflict resource properties or if the value of those properties do + * not allow for a resolution of an existing merge conflict, this method + * returns silently. + * + * @param changeList + * @throws org.apache.jackrabbit.webdav.DavException + * @see Node#doneMerge(Version) + * @see Node#cancelMerge(Version) + */ + private void resolveMergeConflict(List changeList) throws DavException { + if (!exists()) { + throw new DavException(DavServletResponse.SC_NOT_FOUND); + } + try { + Node n = (Node) item; + VersionManager vMgr = getVersionManager(); + String path = item.getPath(); + + DavProperty autoMergeSet = null; + DavProperty predecessorSet = null; + /* find DAV:auto-merge-set entries. If none exists no attempt is made + to resolve merge conflict > return silently */ + for (int i = 0; i < changeList.size(); i++) { + PropEntry propEntry = changeList.get(i); + // If DAV:auto-merge-set is DavPropertyName all remaining merge + // conflicts are resolved with 'cancel' + if (propEntry instanceof DavPropertyName && AUTO_MERGE_SET.equals(propEntry)) { + // retrieve the current jcr:mergeFailed property values + if (!n.hasProperty(JcrConstants.JCR_MERGEFAILED)) { + throw new DavException(DavServletResponse.SC_CONFLICT, "Attempt to resolve non-existing merge conflicts."); + } + Value[] mergeFailed = n.getProperty(JcrConstants.JCR_MERGEFAILED).getValues(); + for (Value value : mergeFailed) { + vMgr.cancelMerge(path, (Version) getRepositorySession().getNodeByIdentifier(value.getString())); + } + // remove this entry from the changeList + changeList.remove(propEntry); + } else if (propEntry instanceof DavProperty) { + if (AUTO_MERGE_SET.equals(((DavProperty)propEntry).getName())) { + autoMergeSet = (DavProperty) propEntry; + } else if (PREDECESSOR_SET.equals(((DavProperty)propEntry).getName())) { + predecessorSet = (DavProperty) propEntry; + } + } + } + + // If DAV:auto-merge-set is a DavProperty merge conflicts need to be + // resolved individually according to the DAV:predecessor-set property. + if (autoMergeSet != null) { + // retrieve the current jcr:mergeFailed property values + if (!n.hasProperty(JcrConstants.JCR_MERGEFAILED)) { + throw new DavException(DavServletResponse.SC_CONFLICT, "Attempt to resolve non-existing merge conflicts."); + } + + List mergeset = new HrefProperty(autoMergeSet).getHrefs(); + List predecL; + if (predecessorSet == null) { + predecL = Collections.emptyList(); + } else { + predecL = new HrefProperty(predecessorSet).getHrefs(); + } + + Session session = getRepositorySession(); + // loop over the mergeFailed values (versions) and test whether they are + // removed from the DAV:auto-merge-set thus indicating resolution. + Value[] mergeFailed = n.getProperty(JcrConstants.JCR_MERGEFAILED).getValues(); + for (Value value : mergeFailed) { + // build version-href from each entry in the jcr:mergeFailed property + // in order to be able to compare to the entries in the HrefProperty. + Version version = (Version) session.getNodeByIdentifier(value.getString()); + String href = getLocatorFromItem(version).getHref(true); + + // Test if that version has been removed from the merge-set. + // thus indicating that this merge conflict needs to be resolved. + if (!mergeset.contains(href)) { + // If the conflict value has been moved over from DAV:auto-merge-set + // to the predecessor-set, resolution with 'doneMerge' is + // appropriate. If the value has been removed from the + // merge-set but not added to the predecessors 'cancelMerge' + // must be called. + if (predecL.contains(href)) { + vMgr.doneMerge(path, version); + } else { + vMgr.cancelMerge(path, version); + } + } + } + // after successful resolution of merge-conflicts according to + // DAV:auto-merge-set and DAV:predecessor-set remove these entries + // from the changeList. + changeList.remove(autoMergeSet); + if (predecessorSet != null) { + changeList.remove(predecessorSet); + } + } + } catch (RepositoryException e) { + throw new JcrDavException(e); + } + } + + //--------------------------------------< VersionableResource interface >--- + /** + * Adds version control to this resource. If the resource is already under + * version control, this method has no effect. + * + * @throws org.apache.jackrabbit.webdav.DavException if this resource does not + * exist yet or if an error occurs while making the underlying node versionable. + * @see org.apache.jackrabbit.webdav.version.VersionableResource#addVersionControl() + */ + @Override + public void addVersionControl() throws DavException { + if (!exists()) { + throw new DavException(DavServletResponse.SC_NOT_FOUND); + } + if (!isVersionControlled()) { + try { + ((Node)item).addMixin(JcrConstants.MIX_VERSIONABLE); + item.save(); + } catch (RepositoryException e) { + throw new JcrDavException(e); + } + } // else: is already version controlled -> ignore + } + + //--------------------------------< VersionControlledResource interface >--- + /** + * Calls {@link javax.jcr.Node#checkin()} on the underlying repository node. + * + * @throws org.apache.jackrabbit.webdav.DavException + * @see org.apache.jackrabbit.webdav.version.VersionControlledResource#checkin() + */ + @Override + public String checkin() throws DavException { + if (!exists()) { + throw new DavException(DavServletResponse.SC_NOT_FOUND); + } + if (!isVersionControlled()) { + throw new DavException(DavServletResponse.SC_METHOD_NOT_ALLOWED); + } + try { + Version v = getVersionManager().checkin(item.getPath()); + String versionHref = getLocatorFromItem(v).getHref(true); + return versionHref; + } catch (RepositoryException e) { + // UnsupportedRepositoryException should not occur + throw new JcrDavException(e); + } + } + + /** + * Calls {@link javax.jcr.Node#checkout()} on the underlying repository node. + * + * @throws org.apache.jackrabbit.webdav.DavException + * @see org.apache.jackrabbit.webdav.version.VersionControlledResource#checkout() + */ + @Override + public void checkout() throws DavException { + if (!exists()) { + throw new DavException(DavServletResponse.SC_NOT_FOUND); + } + if (!isVersionControlled()) { + throw new DavException(DavServletResponse.SC_METHOD_NOT_ALLOWED); + } + try { + getVersionManager().checkout(item.getPath()); + } catch (RepositoryException e) { + // UnsupportedRepositoryException should not occur + throw new JcrDavException(e); + } + } + + /** + * Not implemented. Always throws a DavException with error code + * {@link org.apache.jackrabbit.webdav.DavServletResponse#SC_NOT_IMPLEMENTED}. + * + * @throws org.apache.jackrabbit.webdav.DavException + * @see org.apache.jackrabbit.webdav.version.VersionControlledResource#uncheckout() + */ + @Override + public void uncheckout() throws DavException { + throw new DavException(DavServletResponse.SC_NOT_IMPLEMENTED); + } + + /** + * Perform an update on this resource. Depending on the format of the updateInfo + * this is translated to one of the following methods defined by the JCR API: + *
    + *
  • {@link Node#restore(javax.jcr.version.Version, boolean)}
  • + *
  • {@link Node#restore(javax.jcr.version.Version, String, boolean)}
  • + *
  • {@link Node#restoreByLabel(String, boolean)}
  • + *
  • {@link Node#update(String)}
  • + *
+ *

+ * Limitation: note that the MultiStatus returned by this method + * will not list any nodes that have been removed due to an Uuid conflict. + * + * @param updateInfo + * @return + * @throws org.apache.jackrabbit.webdav.DavException + * @see org.apache.jackrabbit.webdav.version.VersionControlledResource#update(org.apache.jackrabbit.webdav.version.UpdateInfo) + */ + //TODO: with jcr the node must not be versionable in order to perform Node.update. + @Override + public MultiStatus update(UpdateInfo updateInfo) throws DavException { + if (updateInfo == null) { + throw new DavException(DavServletResponse.SC_BAD_REQUEST, "Valid update request body required."); + } + if (!exists()) { + throw new DavException(DavServletResponse.SC_NOT_FOUND); + } + + MultiStatus ms = new MultiStatus(); + try { + Node node = (Node)item; + Element udElem = updateInfo.getUpdateElement(); + boolean removeExisting = DomUtil.hasChildElement(udElem, XML_REMOVEEXISTING, NAMESPACE); + + // register eventListener in order to be able to report the modified resources. + EventListener el = new EListener(updateInfo.getPropertyNameSet(), ms); + registerEventListener(el, node.getPath()); + + // perform the update/restore according to the update info + if (updateInfo.getVersionHref() != null) { + String[] hrefs = updateInfo.getVersionHref(); + if (hrefs.length != 1) { + throw new DavException(DavServletResponse.SC_BAD_REQUEST, "Invalid update request body missing version href or containing multiple version hrefs."); + } + + final String href = normalizeResourceHref(hrefs[0]); + String versionPath = getLocatorFromHref(href).getRepositoryPath(); + String versionName = getItemName(versionPath); + + String relPath = DomUtil.getChildText(udElem, XML_RELPATH, NAMESPACE); + if (relPath == null) { + // restore version by name + node.restore(versionName, removeExisting); + } else if (node.hasNode(relPath)) { + Version v = node.getNode(relPath).getVersionHistory().getVersion(versionName); + node.restore(v, relPath, removeExisting); + } else { + Version v = (Version) getRepositorySession().getNode(versionPath); + node.restore(v, relPath, removeExisting); + } + + } else if (updateInfo.getLabelName() != null) { + String[] labels = updateInfo.getLabelName(); + if (labels.length != 1) { + throw new DavException(DavServletResponse.SC_BAD_REQUEST, "Invalid update request body: Multiple labels specified."); + } + node.restoreByLabel(labels[0], removeExisting); + + } else if (updateInfo.getWorkspaceHref() != null) { + String href = normalizeResourceHref(obtainAbsolutePathFromUri(updateInfo.getWorkspaceHref())); + String workspaceName = getLocatorFromHref(href).getWorkspaceName(); + node.update(workspaceName); + } else { + throw new DavException(DavServletResponse.SC_BAD_REQUEST, "Invalid update request body."); + } + + // unregister the event listener again + unregisterEventListener(el); + + } catch (RepositoryException e) { + throw new JcrDavException(e); + } + return ms; + } + + /** + * Merge the repository node represented by this resource according to the + * information present in the given {@link MergeInfo} object. + * + * @param mergeInfo + * @return MultiStatus recording all repository items modified + * by this merge call as well as the resources that a client must modify to + * complete the merge (see RFC 3253) + * @throws org.apache.jackrabbit.webdav.DavException + * @see org.apache.jackrabbit.webdav.version.VersionControlledResource#merge(org.apache.jackrabbit.webdav.version.MergeInfo) + * @see Node#merge(String, boolean) + */ + //TODO: with jcr the node must not be versionable in order to perform Node.merge + @Override + public MultiStatus merge(MergeInfo mergeInfo) throws DavException { + if (mergeInfo == null) { + throw new DavException(DavServletResponse.SC_BAD_REQUEST); + } + if (!exists()) { + throw new DavException(DavServletResponse.SC_NOT_FOUND); + } + + MultiStatus ms = new MultiStatus(); + try { + // NOTE: RFC requires that all modified resources are reported in the + // multistatus response. this doesn't work however with the remoting + // there is no way to distinguish the 'failedId's from any other + // resources that got modified by this merge operation -> omitted. + + // todo: RFC allows multiple href elements inside the DAV:source element + final String href = normalizeResourceHref(mergeInfo.getSourceHrefs()[0]); + String workspaceName = getLocatorFromHref(href).getWorkspaceName(); + + String depth = DomUtil.getChildTextTrim(mergeInfo.getMergeElement(), DavConstants.XML_DEPTH, DavConstants.NAMESPACE); + boolean isShallow = "0".equals(depth); + + NodeIterator failed = getVersionManager().merge(item.getPath(), workspaceName, !mergeInfo.isNoAutoMerge(), isShallow); + + // add resources to the multistatus, that failed to be merged + while (failed.hasNext()) { + Node failedNode = failed.nextNode(); + DavResourceLocator loc = getLocatorFromItem(failedNode); + DavResource res = createResourceFromLocator(loc); + ms.addResponse(new MultiStatusResponse(res, mergeInfo.getPropertyNameSet())); + } + + } catch (RepositoryException e) { + throw new JcrDavException(e); + } + + return ms; + } + + /** + * Modify the labels present with the versions of this resource. + * + * @param labelInfo + * @throws DavException + * @see VersionHistory#addVersionLabel(String, String, boolean) + * @see VersionHistory#removeVersionLabel(String) + */ + @Override + public void label(LabelInfo labelInfo) throws DavException { + if (labelInfo == null) { + throw new DavException(DavServletResponse.SC_BAD_REQUEST, "Valid label request body required."); + } + if (!exists()) { + throw new DavException(DavServletResponse.SC_NOT_FOUND); + } + + try { + if (!isVersionControlled() || ((Node)item).isCheckedOut()) { + throw new DavException(DavServletResponse.SC_PRECONDITION_FAILED, "A LABEL request may only be applied to a version-controlled, checked-in resource."); + } + DavResource[] resArr = this.getReferenceResources(CHECKED_IN); + if (resArr.length == 1 && resArr[0] instanceof VersionResource) { + ((VersionResource)resArr[0]).label(labelInfo); + } else { + throw new DavException(DavServletResponse.SC_INTERNAL_SERVER_ERROR, "DAV:checked-in property on '" + getHref() + "' did not point to a single VersionResource."); + } + } catch (RepositoryException e) { + throw new JcrDavException(e); + } + } + + /** + * Returns the {@link VersionHistory} associated with the repository node. + * If the node is not versionable an exception is thrown. + * + * @return the {@link VersionHistoryResource} associated with this resource. + * @throws org.apache.jackrabbit.webdav.DavException + * @see org.apache.jackrabbit.webdav.version.VersionControlledResource#getVersionHistory() + * @see javax.jcr.Node#getVersionHistory() + */ + @Override + public VersionHistoryResource getVersionHistory() throws DavException { + if (!exists()) { + throw new DavException(DavServletResponse.SC_NOT_FOUND); + } + + try { + VersionHistory vh = ((Node)item).getVersionHistory(); + DavResourceLocator loc = getLocatorFromItem(vh); + return (VersionHistoryResource) createResourceFromLocator(loc); + } catch (RepositoryException e) { + throw new JcrDavException(e); + } + } + + //-------------------------------------------------------------------------- + /** + * Define the set of reports supported by this resource. + * + * @see SupportedReportSetProperty + */ + @Override + protected void initSupportedReports() { + super.initSupportedReports(); + if (exists()) { + supportedReports.addReportType(ReportType.LOCATE_BY_HISTORY); + if (this.isVersionControlled()) { + supportedReports.addReportType(ReportType.VERSION_TREE); + } + } + } + + @Override + protected void initPropertyNames() { + super.initPropertyNames(); + + if (isVersionControlled()) { + names.addAll(JcrDavPropertyNameSet.VERSIONABLE_SET); + + Node n = (Node) item; + try { + if (n.isCheckedOut()) { + names.add(CHECKED_OUT); + if (n.hasProperty(JcrConstants.JCR_PREDECESSORS)) { + names.add(PREDECESSOR_SET); + } + if (n.hasProperty(JcrConstants.JCR_MERGEFAILED)) { + names.add(AUTO_MERGE_SET); + } + // todo: checkout-fork, checkin-fork + } else { + names.add(CHECKED_IN); + } + } catch (RepositoryException e) { + log.warn(e.getMessage()); + } + } + } + + /** + * Fill the property set for this resource. + */ + @Override + protected void initProperties() { + super.initProperties(); + if (isVersionControlled()) { + Node n = (Node)item; + // properties defined by RFC 3253 for version-controlled resources + // workspace property already set in AbstractResource.initProperties() + try { + // DAV:version-history (computed) + String vhHref = getLocatorFromItem(n.getVersionHistory()).getHref(true); + properties.add(new HrefProperty(VERSION_HISTORY, vhHref, true)); + + // DAV:auto-version property: there is no auto version, explicit CHECKOUT is required. + properties.add(new DefaultDavProperty(AUTO_VERSION, null, false)); + + String baseVHref = getLocatorFromItem(n.getBaseVersion()).getHref(true); + if (n.isCheckedOut()) { + // DAV:predecessors property + if (n.hasProperty(JcrConstants.JCR_PREDECESSORS)) { + Value[] predec = n.getProperty(JcrConstants.JCR_PREDECESSORS).getValues(); + addHrefProperty(PREDECESSOR_SET, predec, false); + } + // DAV:auto-merge-set property. NOTE: the DAV:merge-set + // never occurs, because merging without bestEffort flag + // being set results in an exception on failure. + if (n.hasProperty(JcrConstants.JCR_MERGEFAILED)) { + Value[] mergeFailed = n.getProperty(JcrConstants.JCR_MERGEFAILED).getValues(); + addHrefProperty(AUTO_MERGE_SET, mergeFailed, false); + } + // todo: checkout-fork, checkin-fork + } + } catch (RepositoryException e) { + log.error(e.getMessage()); + } + } + } + + /** + * Add a {@link org.apache.jackrabbit.webdav.property.HrefProperty} with the + * specified property name and values. + * + * @param name + * @param values Array of {@link Value}s. + * @param isProtected + * @throws javax.jcr.ValueFormatException + * @throws IllegalStateException + * @throws javax.jcr.RepositoryException + */ + private void addHrefProperty(DavPropertyName name, Value[] values, + boolean isProtected) + throws ValueFormatException, IllegalStateException, RepositoryException { + Node[] nodes = new Node[values.length]; + for (int i = 0; i < values.length; i++) { + nodes[i] = getRepositorySession().getNodeByIdentifier(values[i].getString()); + } + addHrefProperty(name, nodes, isProtected); + } + + /** + * @return true, if this resource represents an existing repository node + * that has the mixin nodetype 'mix:versionable' set. + */ + private boolean isVersionControlled() { + boolean vc = false; + if (exists()) { + try { + vc = ((Node) item).isNodeType(JcrConstants.MIX_VERSIONABLE); + } catch (RepositoryException e) { + log.warn(e.getMessage()); + } + } + return vc; + } + + /** + * Build a new locator for the given href. + * + * @param href + * @return + */ + private DavResourceLocator getLocatorFromHref(String href) { + DavLocatorFactory f = getLocator().getFactory(); + String prefix = getLocator().getPrefix(); + return f.createResourceLocator(prefix, href); + } + + private VersionManager getVersionManager() throws RepositoryException { + return getRepositorySession().getWorkspace().getVersionManager(); + } + + private static String obtainAbsolutePathFromUri(String uri) { + try { + java.net.URI u = new java.net.URI(uri); + StringBuilder sb = new StringBuilder(); + sb.append(u.getRawPath()); + if (u.getRawQuery() != null) { + sb.append("?").append(u.getRawQuery()); + } + return sb.toString(); + } + catch (java.net.URISyntaxException ex) { + log.warn("parsing " + uri, ex); + return uri; + } + } +} Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/VersionControlledItemCollection.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/webdav/jcr/WorkspaceResourceImpl.java =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/WorkspaceResourceImpl.java (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/WorkspaceResourceImpl.java (working copy) @@ -0,0 +1,627 @@ +/* + * 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.webdav.jcr; + +import org.apache.jackrabbit.commons.cnd.CompactNodeTypeDefReader; +import org.apache.jackrabbit.commons.cnd.CompactNodeTypeDefWriter; +import org.apache.jackrabbit.commons.cnd.DefinitionBuilderFactory; +import org.apache.jackrabbit.commons.cnd.ParseException; +import org.apache.jackrabbit.commons.cnd.TemplateBuilderFactory; +import org.apache.jackrabbit.commons.webdav.AtomFeedConstants; +import org.apache.jackrabbit.webdav.DavException; +import org.apache.jackrabbit.webdav.DavMethods; +import org.apache.jackrabbit.webdav.DavResource; +import org.apache.jackrabbit.webdav.DavResourceFactory; +import org.apache.jackrabbit.webdav.DavResourceIterator; +import org.apache.jackrabbit.webdav.DavResourceIteratorImpl; +import org.apache.jackrabbit.webdav.DavResourceLocator; +import org.apache.jackrabbit.webdav.DavServletResponse; +import org.apache.jackrabbit.webdav.MultiStatus; +import org.apache.jackrabbit.webdav.MultiStatusResponse; +import org.apache.jackrabbit.webdav.io.InputContext; +import org.apache.jackrabbit.webdav.io.OutputContext; +import org.apache.jackrabbit.webdav.jcr.property.JcrDavPropertyNameSet; +import org.apache.jackrabbit.webdav.jcr.property.NamespacesProperty; +import org.apache.jackrabbit.webdav.jcr.security.JcrUserPrivilegesProperty; +import org.apache.jackrabbit.webdav.jcr.security.JcrSupportedPrivilegesProperty; +import org.apache.jackrabbit.webdav.jcr.security.SecurityUtils; +import org.apache.jackrabbit.webdav.jcr.version.report.JcrPrivilegeReport; +import org.apache.jackrabbit.webdav.property.DavProperty; +import org.apache.jackrabbit.webdav.property.DavPropertyName; +import org.apache.jackrabbit.webdav.property.DefaultDavProperty; +import org.apache.jackrabbit.webdav.property.PropEntry; +import org.apache.jackrabbit.webdav.search.SearchResource; +import org.apache.jackrabbit.webdav.security.SecurityConstants; +import org.apache.jackrabbit.webdav.version.DeltaVResource; +import org.apache.jackrabbit.webdav.version.LabelInfo; +import org.apache.jackrabbit.webdav.version.MergeInfo; +import org.apache.jackrabbit.webdav.version.UpdateInfo; +import org.apache.jackrabbit.webdav.version.VersionControlledResource; +import org.apache.jackrabbit.webdav.version.VersionHistoryResource; +import org.apache.jackrabbit.webdav.version.WorkspaceResource; +import org.apache.jackrabbit.webdav.xml.DomUtil; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.w3c.dom.Element; + +import javax.jcr.Item; +import javax.jcr.NamespaceRegistry; +import javax.jcr.Repository; +import javax.jcr.RepositoryException; +import javax.jcr.Session; +import javax.jcr.Workspace; +import javax.jcr.nodetype.NodeTypeIterator; +import javax.jcr.nodetype.NodeTypeManager; +import javax.jcr.nodetype.NodeTypeTemplate; +import javax.jcr.observation.EventListener; +import javax.jcr.version.Version; +import java.io.IOException; +import java.io.OutputStreamWriter; +import java.io.PrintWriter; +import java.io.StringReader; +import java.io.StringWriter; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.Date; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * WorkspaceResourceImpl... + */ +public class WorkspaceResourceImpl extends AbstractResource + implements WorkspaceResource, VersionControlledResource { + + private static Logger log = LoggerFactory.getLogger(WorkspaceResourceImpl.class); + + /** + * Create a new WorkspaceResourceImpl + * + * @param locator + * @param session + * @param factory + */ + WorkspaceResourceImpl(DavResourceLocator locator, JcrDavSession session, DavResourceFactory factory) { + super(locator, session, factory); + + // initialize the supported locks and reports + initLockSupport(); + initSupportedReports(); + } + + @Override + public DavProperty getProperty(DavPropertyName name) { + DavProperty prop = super.getProperty(name); + if (prop == null) { + StringWriter writer = null; + try { + if (ItemResourceConstants.JCR_NODETYPES_CND.equals(name)) { + writer = new StringWriter(); + Session s = getRepositorySession(); + + CompactNodeTypeDefWriter cndWriter = new CompactNodeTypeDefWriter(writer, s, true); + NodeTypeIterator ntIterator = s.getWorkspace().getNodeTypeManager().getAllNodeTypes(); + while (ntIterator.hasNext()) { + cndWriter.write(ntIterator.nextNodeType()); + } + cndWriter.close(); + /* + NOTE: avoid having JCR_NODETYPES_CND exposed upon allprop + PROPFIND request since it needs to be calculated. + nevertheless, this property can be altered using + PROPPATCH, which is not consistent with the specification + */ + prop = new DefaultDavProperty(ItemResourceConstants.JCR_NODETYPES_CND, writer.toString(), true); + + } else if (SecurityConstants.SUPPORTED_PRIVILEGE_SET.equals(name)) { + prop = new JcrSupportedPrivilegesProperty(getRepositorySession(), null).asDavProperty(); + } else if (SecurityConstants.CURRENT_USER_PRIVILEGE_SET.equals(name)) { + prop = new JcrUserPrivilegesProperty(getRepositorySession(), null).asDavProperty(); + } + } catch (RepositoryException e) { + log.error("Failed to access NodeTypeManager: " + e.getMessage()); + } catch (IOException e) { + log.error("Failed to write compact node definition: " + e.getMessage()); + } finally { + if (writer != null) { + try { + writer.close(); + } catch (IOException e) { + log.error(e.getMessage()); + } + } + } + } + + // TODO: required property DAV:workspace-checkout-set (computed) + + return prop; + } + + //--------------------------------------------------------< DavResource >--- + + @Override + public String getSupportedMethods() { + StringBuilder sb = new StringBuilder(DavResource.METHODS); + sb.append(", "); + sb.append(DeltaVResource.METHODS_INCL_MKWORKSPACE); + sb.append(", "); + sb.append(SearchResource.METHODS); + // from vc-resource methods only UPDATE is supported + sb.append(", "); + sb.append(DavMethods.METHOD_UPDATE); + return sb.toString(); + } + + /** + * @return true if the workspace name (see {@link #getDisplayName()} is + * present in the list of available workspace names such as exposed by + * the editing JCR session. + */ + @Override + public boolean exists() { + try { + List available = Arrays.asList(getRepositorySession().getWorkspace().getAccessibleWorkspaceNames()); + return available.contains(getDisplayName()); + } catch (RepositoryException e) { + log.warn(e.getMessage()); + return false; + } + } + + /** + * @return true + */ + @Override + public boolean isCollection() { + return true; + } + + /** + * Returns the name of the workspace. + * + * @return The workspace name + * @see org.apache.jackrabbit.webdav.DavResource#getDisplayName() + * @see javax.jcr.Workspace#getName() + */ + @Override + public String getDisplayName() { + return getLocator().getWorkspaceName(); + } + + /** + * Always returns 'now' + * + * @return + */ + @Override + public long getModificationTime() { + return new Date().getTime(); + } + + /** + * @param outputContext + * @throws IOException + */ + @Override + public void spool(OutputContext outputContext) throws IOException { + + outputContext.setProperty("Link", "; title=\"Event Journal\"; rel=alternate; type=\"" + AtomFeedConstants.MEDIATYPE + "\""); + + if (outputContext.hasStream()) { + Session session = getRepositorySession(); + Repository rep = session.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); + String repostr = repName + " " + repVersion; + + StringBuilder sb = new StringBuilder(); + sb.append(""); + sb.append(repostr); + sb.append(""); + sb.append(""); + sb.append(""); + sb.append("

").append(repostr).append("


Powered by ").append(repName); + sb.append(" ").append(repVersion); + sb.append(""); + + outputContext.setContentLength(sb.length()); + outputContext.setModificationTime(getModificationTime()); + PrintWriter writer = new PrintWriter(new OutputStreamWriter(outputContext.getOutputStream(), "utf8")); + writer.print(sb.toString()); + writer.close(); + } else { + outputContext.setContentLength(0); + outputContext.setModificationTime(getModificationTime()); + } + } + + /** + * Retrieve the collection that has all workspace collections + * as internal members. + * + * @see org.apache.jackrabbit.webdav.DavResource#getCollection() + */ + @Override + public DavResource getCollection() { + DavResource collection = null; + // create location with 'null' values for workspace-path and resource-path + DavResourceLocator parentLoc = getLocator().getFactory().createResourceLocator(getLocator().getPrefix(), null, null, false); + try { + collection = createResourceFromLocator(parentLoc); + } catch (DavException e) { + log.error("Unexpected error while retrieving collection: " + e.getMessage()); + } + return collection; + } + + /** + * Throws 403 exception (Forbidden) + * + * @param resource + * @param inputContext + * @throws DavException + */ + @Override + public void addMember(DavResource resource, InputContext inputContext) throws DavException { + log.error("Cannot add a new member to the workspace resource."); + throw new DavException(DavServletResponse.SC_FORBIDDEN); + } + + /** + * Returns the resource representing the JCR root node. + * + * @return + */ + @Override + public DavResourceIterator getMembers() { + try { + DavResourceLocator loc = getLocatorFromItem(getRepositorySession().getRootNode()); + List list = Collections.singletonList(createResourceFromLocator(loc)); + return new DavResourceIteratorImpl(list); + } catch (DavException e) { + log.error("Internal error while building resource for the root node.", e); + return DavResourceIteratorImpl.EMPTY; + } catch (RepositoryException e) { + log.error("Internal error while building resource for the root node.", e); + return DavResourceIteratorImpl.EMPTY; + } + } + + /** + * Throws 403 exception (Forbidden) + * + * @param member + * @throws DavException + */ + @Override + public void removeMember(DavResource member) throws DavException { + log.error("Cannot add a remove the root node."); + throw new DavException(DavServletResponse.SC_FORBIDDEN); + } + + /** + * Allows to alter the registered namespaces ({@link ItemResourceConstants#JCR_NAMESPACES}) + * or register node types {@link ItemResourceConstants#JCR_NODETYPES_CND} + * where the passed value is a cnd string containing the definition + * and forwards any other property to the super class. + *

+ * Note that again no property status is set. Any failure while setting + * a property results in an exception (violating RFC 2518). + * + * @param property + * @throws DavException + * @see DavResource#setProperty(org.apache.jackrabbit.webdav.property.DavProperty) + */ + @Override + public void setProperty(DavProperty property) throws DavException { + if (ItemResourceConstants.JCR_NAMESPACES.equals(property.getName())) { + NamespacesProperty nsp = new NamespacesProperty(property); + try { + Map changes = new HashMap(nsp.getNamespaces()); + NamespaceRegistry nsReg = getRepositorySession().getWorkspace().getNamespaceRegistry(); + for (String prefix : nsReg.getPrefixes()) { + if (!changes.containsKey(prefix)) { + // prefix not present amongst the new values any more > unregister + nsReg.unregisterNamespace(prefix); + } else if (changes.get(prefix).equals(nsReg.getURI(prefix))) { + // present with same uri-value >> no action required + changes.remove(prefix); + } + } + + // try to register any prefix/uri pair that has a changed uri or + // it has not been present before. + for (String prefix : changes.keySet()) { + String uri = changes.get(prefix); + nsReg.registerNamespace(prefix, uri); + } + } catch (RepositoryException e) { + throw new JcrDavException(e); + } + } else if (ItemResourceConstants.JCR_NODETYPES_CND.equals(property.getName())) { + try { + Object value = property.getValue(); + List cmds; + if (value instanceof List) { + cmds = (List) value; + } else if (value instanceof Element) { + cmds = Collections.singletonList(value); + } else { + log.warn("Unexpected structure of dcr:nodetypes-cnd property."); + throw new DavException(DavServletResponse.SC_INTERNAL_SERVER_ERROR); + } + + String registerCnd = null; + boolean allowUpdate = false; + List unregisterNames = new ArrayList(); + + for (Object listEntry : cmds) { + if (listEntry instanceof Element) { + Element e = (Element) listEntry; + String localName = e.getLocalName(); + if (ItemResourceConstants.XML_CND.equals(localName)) { + registerCnd = DomUtil.getText(e); + } else if (ItemResourceConstants.XML_ALLOWUPDATE.equals(localName)) { + String allow = DomUtil.getTextTrim(e); + allowUpdate = Boolean.parseBoolean(allow); + } else if (ItemResourceConstants.XML_NODETYPENAME.equals(localName)) { + unregisterNames.add(DomUtil.getTextTrim(e)); + } + } + } + + // TODO: for simplicity it's currently either registration or unregistration as nt-modifications are immediately persisted. + Session s = getRepositorySession(); + NodeTypeManager ntMgr = s.getWorkspace().getNodeTypeManager(); + if (registerCnd != null) { + StringReader reader = new StringReader(registerCnd); + DefinitionBuilderFactory factory = + new TemplateBuilderFactory(ntMgr, s.getValueFactory(), s.getWorkspace().getNamespaceRegistry()); + + CompactNodeTypeDefReader cndReader = + new CompactNodeTypeDefReader(reader, "davex", factory); + + List ntts = cndReader.getNodeTypeDefinitions(); + ntMgr.registerNodeTypes(ntts.toArray(new NodeTypeTemplate[ntts.size()]), allowUpdate); + } else if (!unregisterNames.isEmpty()) { + ntMgr.unregisterNodeTypes(unregisterNames.toArray(new String[unregisterNames.size()])); + } + + } catch (ParseException e) { + throw new DavException(DavServletResponse.SC_BAD_REQUEST, e); + } + catch (RepositoryException e) { + throw new JcrDavException(e); + } + } else { + // only jcr:namespace or node types can be modified + throw new DavException(DavServletResponse.SC_CONFLICT); + } + } + + /** + * Handles an attempt to set {@link ItemResourceConstants#JCR_NAMESPACES} + * and forwards any other set or remove requests to the super class. + * + * @see #setProperty(DavProperty) + * @see DefaultItemCollection#alterProperties(List) + */ + @Override + public MultiStatusResponse alterProperties(List changeList) throws DavException { + if (changeList.size() == 1) { + PropEntry propEntry = changeList.get(0); + // only modification of prop is allowed. removal is not possible + if (propEntry instanceof DavProperty + && (ItemResourceConstants.JCR_NAMESPACES.equals(((DavProperty)propEntry).getName()) + || ItemResourceConstants.JCR_NODETYPES_CND.equals(((DavProperty)propEntry).getName()))) { + setProperty((DavProperty) propEntry); + } else { + // attempt to remove the namespace property + throw new DavException(DavServletResponse.SC_CONFLICT); + } + } else { + // change list contains more than the jcr:namespaces property + // TODO: build multistatus instead + throw new DavException(DavServletResponse.SC_CONFLICT); + } + return new MultiStatusResponse(getHref(), DavServletResponse.SC_OK); + } + + //------------------------------------------------< VersionableResource >--- + /** + * @throws DavException (403) since workspace is not versionable. implementing + * VersionControlledResource only for 'update'. + */ + @Override + public void addVersionControl() throws DavException { + throw new DavException(DavServletResponse.SC_FORBIDDEN); + } + + //------------------------------------------< VersionControlledResource >--- + /** + * @throws DavException (403) since workspace is not versionable. implementing + * VersionControlledResource only for 'update'. + */ + @Override + public String checkin() throws DavException { + throw new DavException(DavServletResponse.SC_FORBIDDEN); + } + + /** + * @throws DavException (403) since workspace is not versionable. implementing + * VersionControlledResource only for 'update'. + */ + @Override + public void checkout() throws DavException { + throw new DavException(DavServletResponse.SC_FORBIDDEN); + } + + /** + * @throws DavException (403) since workspace is not versionable. implementing + * VersionControlledResource only for 'update'. + */ + @Override + public void uncheckout() throws DavException { + throw new DavException(DavServletResponse.SC_FORBIDDEN); + } + + /** + * While RFC 3253 does not define any version-related operations for the + * workspace resource, this implementation uses {@link VersionControlledResource#update(UpdateInfo)} + * to map {@link Workspace#restore(javax.jcr.version.Version[], boolean)} to + * a WebDAV call. + *

+ * Limitation: note that the MultiStatus returned by this method + * will not list any nodes that have been removed due to an Uuid conflict. + * + * @param updateInfo + * @return + * @throws org.apache.jackrabbit.webdav.DavException + * @see org.apache.jackrabbit.webdav.version.VersionControlledResource#update(org.apache.jackrabbit.webdav.version.UpdateInfo) + */ + @Override + public MultiStatus update(UpdateInfo updateInfo) throws DavException { + if (updateInfo == null) { + throw new DavException(DavServletResponse.SC_BAD_REQUEST, "Valid update request body required."); + } + if (!exists()) { + throw new DavException(DavServletResponse.SC_NOT_FOUND); + } + + Session session = getRepositorySession(); + MultiStatus ms = new MultiStatus(); + try { + Element udElem = updateInfo.getUpdateElement(); + boolean removeExisting = DomUtil.hasChildElement(udElem, ItemResourceConstants.XML_REMOVEEXISTING, ItemResourceConstants.NAMESPACE); + + // register eventListener in order to be able to report the modified resources. + EventListener el = new EListener(updateInfo.getPropertyNameSet(), ms); + registerEventListener(el, session.getRootNode().getPath()); + + String[] hrefs = updateInfo.getVersionHref(); + if (hrefs == null || hrefs.length < 1) { + throw new DavException(DavServletResponse.SC_BAD_REQUEST, "Invalid update request body: at least a single version href must be specified."); + } + // perform the update/restore according to the update info + Version[] versions = new Version[hrefs.length]; + for (int i = 0; i < hrefs.length; i++) { + final String href = normalizeResourceHref(hrefs[i]); + DavResourceLocator vLoc = getLocator().getFactory().createResourceLocator(getLocator().getPrefix(), href); + String versionPath = vLoc.getRepositoryPath(); + Item item = getRepositorySession().getItem(versionPath); + if (item instanceof Version) { + versions[i] = (Version) item; + } else { + throw new DavException(DavServletResponse.SC_BAD_REQUEST, "Invalid update request body: href does not identify a version " + hrefs[i]); + } + } + session.getWorkspace().restore(versions, removeExisting); + + // unregister the event listener again + unregisterEventListener(el); + + } catch (RepositoryException e) { + throw new JcrDavException(e); + } + return ms; + } + + /** + * @throws DavException (403) since workspace is not versionable. implementing + * VersionControlledResource only for 'update'. + */ + @Override + public MultiStatus merge(MergeInfo mergeInfo) throws DavException { + throw new DavException(DavServletResponse.SC_FORBIDDEN); + } + + /** + * @throws DavException (403) since workspace is not versionable. implementing + * VersionControlledResource only for 'update'. + */ + @Override + public void label(LabelInfo labelInfo) throws DavException { + throw new DavException(DavServletResponse.SC_FORBIDDEN); + } + + /** + * @throws DavException (403) since workspace is not versionable. implementing + * VersionControlledResource only for 'update'. + */ + @Override + public VersionHistoryResource getVersionHistory() throws DavException { + throw new DavException(DavServletResponse.SC_FORBIDDEN); + } + + //---------------------------------------------------< AbstractResource >--- + @Override + protected void initLockSupport() { + // lock not allowed + } + + @Override + protected void initSupportedReports() { + super.initSupportedReports(); + supportedReports.addReportType(JcrPrivilegeReport.PRIVILEGES_REPORT); + } + + @Override + protected String getWorkspaceHref() { + return getHref(); + } + + @Override + protected void initPropertyNames() { + super.initPropertyNames(); + names.addAll(JcrDavPropertyNameSet.WORKSPACE_SET); + if (SecurityUtils.supportsAccessControl(getRepositorySession())) { + names.add(SecurityConstants.SUPPORTED_PRIVILEGE_SET); + names.add(SecurityConstants.CURRENT_USER_PRIVILEGE_SET); + } + } + + @Override + protected void initProperties() { + super.initProperties(); + try { + // init workspace specific properties + NamespaceRegistry nsReg = getRepositorySession().getWorkspace().getNamespaceRegistry(); + DavProperty namespacesProp = new NamespacesProperty(nsReg); + properties.add(namespacesProp); + } catch (RepositoryException e) { + log.error("Failed to access NamespaceRegistry: " + e.getMessage()); + } + } +} Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/WorkspaceResourceImpl.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/webdav/jcr/lock/JcrActiveLock.java =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/lock/JcrActiveLock.java (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/lock/JcrActiveLock.java (working copy) @@ -0,0 +1,192 @@ +/* + * 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.webdav.jcr.lock; + +import org.apache.jackrabbit.webdav.DavConstants; +import org.apache.jackrabbit.webdav.jcr.ItemResourceConstants; +import org.apache.jackrabbit.webdav.lock.AbstractActiveLock; +import org.apache.jackrabbit.webdav.lock.ActiveLock; +import org.apache.jackrabbit.webdav.lock.Scope; +import org.apache.jackrabbit.webdav.lock.Type; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.jcr.RepositoryException; +import javax.jcr.lock.Lock; + +/** + * JcrActiveLock wraps a {@link Lock JCR lock} object. + */ +public class JcrActiveLock extends AbstractActiveLock implements ActiveLock, DavConstants { + + private static Logger log = LoggerFactory.getLogger(JcrActiveLock.class); + + private final Lock lock; + + /** + * Create a new ActiveLock object with type '{@link Type#WRITE write}' + * and scope '{@link Scope#EXCLUSIVE exclusive}'. + * + * @param lock + */ + public JcrActiveLock(Lock lock) { + if (lock == null) { + throw new IllegalArgumentException("Can not create a ActiveLock with a 'null' argument."); + } + this.lock = lock; + } + + /** + * Return true if the given lock token equals the token holding that lock. + * + * @param lockToken + * @return true if the given lock token equals this locks token. + * @see org.apache.jackrabbit.webdav.lock.ActiveLock#isLockedByToken(String) + */ + public boolean isLockedByToken(String lockToken) { + if (lockToken != null && lockToken.equals(getToken())) { + return true; + } + return false; + } + + /** + * @see ActiveLock#isExpired() + */ + public boolean isExpired() { + try { + return !lock.isLive(); + } catch (RepositoryException e) { + log.error("Unexpected error: " + e.getMessage()); + return false; + } + } + + /** + * Return the lock token if the {@link javax.jcr.Session} that obtained the lock + * is the lock token holder, null otherwise.
+ * NOTE: currently the token generated by the underlying JCR repository + * is not checked for compliance with RFC 2518 ("OpaqueLockToken-URI = "opaquelocktoken:" + * UUID [Extension] ; The UUID production is the string representation of a + * UUID, as defined in [ISO-11578]. Note that white space (LWS) is not allowed + * between elements of this production."). + *

+ * In case of session-scoped JCR 2.0 locks, the token is never exposed even + * if the current session is lock holder. In order to cope with DAV specific + * requirements and the fulfill the requirement stated above, the node's + * identifier is subsequently exposed as DAV-token. + * + * @see ActiveLock#getToken() + */ + public String getToken() { + try { + return LockTokenMapper.getDavLocktoken(lock); + } catch (RepositoryException e) { + // should never get here + log.warn("Unexpected error while retrieving node identifier for building a DAV specific lock token. {}", + e.getMessage()); + return null; + } + } + + /** + * @see ActiveLock#getOwner() + */ + public String getOwner() { + return lock.getLockOwner(); + } + + /** + * @see ActiveLock#setOwner(String) + */ + public void setOwner(String owner) { + throw new UnsupportedOperationException("setOwner is not implemented"); + } + + /** + * Calculates the milliseconds of the timeout from + * {@link javax.jcr.lock.Lock#getSecondsRemaining()}. If the timeout of + * jcr lock is undefined or infinite {@link #INFINITE_TIMEOUT} is + * returned. + * + * @see ActiveLock#getTimeout() + */ + public long getTimeout() { + try { + long to = lock.getSecondsRemaining(); + long reportAs; + + if (to == Long.MAX_VALUE) { + reportAs = INFINITE_TIMEOUT; + } + else if (to / 1000 <= Long.MAX_VALUE / 1000) { + // expressible as long? + reportAs = to * 1000; + } + else { + reportAs = INFINITE_TIMEOUT; + } + + return reportAs; + } catch (RepositoryException e) { + return INFINITE_TIMEOUT; + } + } + + /** + * Throws UnsupportedOperationException + * + * @see ActiveLock#setTimeout(long) + */ + public void setTimeout(long timeout) { + throw new UnsupportedOperationException("setTimeout is not implemented"); + } + + /** + * @see ActiveLock#isDeep() + */ + public boolean isDeep() { + return lock.isDeep(); + } + + /** + * @see ActiveLock#setIsDeep(boolean) + */ + public void setIsDeep(boolean isDeep) { + throw new UnsupportedOperationException("setIsDeep is not implemented"); + } + + /** + * Always returns {@link Type#WRITE}. + * + * @return {@link Type#WRITE} + * @see ActiveLock#getType() + */ + public Type getType() { + return Type.WRITE; + } + + /** + * @return The scope of this lock, which may either by an {@link Scope#EXCLUSIVE exclusive} + * or {@link ItemResourceConstants#EXCLUSIVE_SESSION exclusive session scoped} + * lock. + * @see ActiveLock#getScope() + */ + public Scope getScope() { + return (lock.isSessionScoped()) ? ItemResourceConstants.EXCLUSIVE_SESSION : Scope.EXCLUSIVE; + } +} Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/lock/JcrActiveLock.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/webdav/jcr/lock/LockTokenMapper.java =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/lock/LockTokenMapper.java (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/lock/LockTokenMapper.java (working copy) @@ -0,0 +1,74 @@ +/* + * 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.webdav.jcr.lock; + +import javax.jcr.RepositoryException; +import javax.jcr.lock.Lock; + +import org.apache.jackrabbit.util.Text; + +/** + * Maps between WebDAV lock tokens and JCR lock tokens. + *

+ * The following notations are used: + * + *

+ * opaquelocktoken:SESSIONSCOPED:NODEIDENTIFIER
+ * opaquelocktoken:OPENSCOPED:JCRLOCKTOKEN
+ * 
+ * + * The first format is used if the JCR lock does not reveal a lock token, such + * as when it is a session-scoped lock (where SESSIONSCOPED is a constant UUID + * defined below, and NODEIDENTIFIER is the suitably escaped JCR Node + * identifier). + *

+ * The second format is used for open-scoped locks (where OPENSCOPED is another + * constant UUID defined below, and JCRLOCKTOKEN is the suitably escaped JCR + * lock token). + */ +public class LockTokenMapper { + + private static final String OL = "opaquelocktoken:"; + + private static final String SESSIONSCOPED = "4403ef44-4124-11e1-b965-00059a3c7a00"; + private static final String OPENSCOPED = "dccce564-412e-11e1-b969-00059a3c7a00"; + + private static final String SESSPREFIX = OL + SESSIONSCOPED + ":"; + private static final String OPENPREFIX = OL + OPENSCOPED + ":"; + + public static String getDavLocktoken(Lock lock) throws RepositoryException { + String jcrLockToken = lock.getLockToken(); + + if (jcrLockToken == null) { + return SESSPREFIX + Text.escape(lock.getNode().getIdentifier()); + } else { + return OPENPREFIX + Text.escape(jcrLockToken); + } + } + + public static String getJcrLockToken(String token) throws RepositoryException { + if (token.startsWith(OPENPREFIX)) { + return Text.unescape(token.substring(OPENPREFIX.length())); + } else { + throw new RepositoryException("not a token for an open-scoped JCR lock: " + token); + } + } + + public static boolean isForSessionScopedLock(String token) { + return token.startsWith(SESSPREFIX); + } +} Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/lock/LockTokenMapper.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/webdav/jcr/lock/SessionScopedLockEntry.java =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/lock/SessionScopedLockEntry.java (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/lock/SessionScopedLockEntry.java (working copy) @@ -0,0 +1,50 @@ +/* + * 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.webdav.jcr.lock; + +import org.apache.jackrabbit.webdav.jcr.ItemResourceConstants; +import org.apache.jackrabbit.webdav.lock.AbstractLockEntry; +import org.apache.jackrabbit.webdav.lock.LockEntry; +import org.apache.jackrabbit.webdav.lock.Scope; +import org.apache.jackrabbit.webdav.lock.Type; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * SessionScopedLockEntry represents the 'session-scoped' write + * lock as defined by JCR. + */ +public class SessionScopedLockEntry extends AbstractLockEntry { + + private static Logger log = LoggerFactory.getLogger(SessionScopedLockEntry.class); + + /** + * @return always returns {@link Type#WRITE write}. + * @see LockEntry#getType() + */ + public Type getType() { + return Type.WRITE; + } + + /** + * @return returns {@link ItemResourceConstants#EXCLUSIVE_SESSION}. + * @see LockEntry#getScope() + */ + public Scope getScope() { + return ItemResourceConstants.EXCLUSIVE_SESSION; + } +} \ No newline at end of file Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/lock/SessionScopedLockEntry.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/webdav/jcr/nodetype/ItemDefinitionImpl.java =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/nodetype/ItemDefinitionImpl.java (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/nodetype/ItemDefinitionImpl.java (working copy) @@ -0,0 +1,126 @@ +/* + * 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.webdav.jcr.nodetype; + +import org.apache.jackrabbit.commons.webdav.NodeTypeConstants; +import org.apache.jackrabbit.webdav.xml.XmlSerializable; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +import javax.jcr.nodetype.ItemDefinition; +import javax.jcr.nodetype.NodeType; +import javax.jcr.version.OnParentVersionAction; + +/** + * ItemDefinitionImpl... + */ +abstract public class ItemDefinitionImpl implements ItemDefinition, NodeTypeConstants, XmlSerializable { + + private static Logger log = LoggerFactory.getLogger(ItemDefinitionImpl.class); + + private final String name; + private NodeType declaringNodeType; + private final boolean isAutoCreated; + private final boolean isMandatory; + private final boolean isProtected; + private final int onParentVersion; + + ItemDefinitionImpl(ItemDefinition definition) { + if (definition == null) { + throw new IllegalArgumentException("PropDef argument can not be null"); + } + name = definition.getName(); + declaringNodeType = definition.getDeclaringNodeType(); + isAutoCreated = definition.isAutoCreated(); + isMandatory = definition.isMandatory(); + isProtected = definition.isProtected(); + onParentVersion = definition.getOnParentVersion(); + } + + /** + * @see ItemDefinition#getDeclaringNodeType() + */ + public NodeType getDeclaringNodeType() { + return declaringNodeType; + } + + /** + * @see ItemDefinition#getName() + */ + public String getName() { + return name; + } + + /** + * @see ItemDefinition#isAutoCreated() + */ + public boolean isAutoCreated() { + return isAutoCreated; + } + + /** + * @see ItemDefinition#isMandatory() + */ + public boolean isMandatory() { + return isMandatory; + } + + /** + * @see ItemDefinition#getOnParentVersion() + */ + public int getOnParentVersion() { + return onParentVersion; + } + + /** + * @see ItemDefinition#isProtected() + */ + public boolean isProtected() { + return isProtected; + } + + //------------------------------------------< XmlSerializable interface >--- + /** + * Returns the Xml representation of a {@link ItemDefinition} object. + * + * @return Xml representation of the specified {@link ItemDefinition def}. + * @param document + */ + public Element toXml(Document document) { + Element elem = document.createElement(getElementName()); + NodeType dnt = getDeclaringNodeType(); + if (dnt != null) { + elem.setAttribute(DECLARINGNODETYPE_ATTRIBUTE, dnt.getName()); + } + elem.setAttribute(NAME_ATTRIBUTE, getName()); + elem.setAttribute(AUTOCREATED_ATTRIBUTE, Boolean.toString(isAutoCreated())); + elem.setAttribute(MANDATORY_ATTRIBUTE, Boolean.toString(isMandatory())); + elem.setAttribute(ONPARENTVERSION_ATTRIBUTE, OnParentVersionAction.nameFromValue(getOnParentVersion())); + elem.setAttribute(PROTECTED_ATTRIBUTE, Boolean.toString(isProtected())); + return elem; + } + + //-------------------------------------< implementation specific method >--- + /** + * Returns the name of the root element + * + * @return the name of the root element + */ + abstract String getElementName(); +} \ No newline at end of file Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/nodetype/ItemDefinitionImpl.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/webdav/jcr/nodetype/NodeDefinitionImpl.java =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/nodetype/NodeDefinitionImpl.java (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/nodetype/NodeDefinitionImpl.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.webdav.jcr.nodetype; + +import org.apache.jackrabbit.webdav.xml.DomUtil; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +import javax.jcr.nodetype.NodeDefinition; +import javax.jcr.nodetype.NodeType; + +/** + * NodeDefinitionImpl... + */ +public final class NodeDefinitionImpl extends ItemDefinitionImpl implements NodeDefinition { + + private static Logger log = LoggerFactory.getLogger(NodeDefinitionImpl.class); + + private final NodeType[] requiredPrimaryTypes; + private final NodeType defaultPrimaryType; + private final boolean allowsSameNameSiblings; + + private NodeDefinitionImpl(NodeDefinition definition) { + super(definition); + + requiredPrimaryTypes = definition.getRequiredPrimaryTypes(); + defaultPrimaryType = definition.getDefaultPrimaryType(); + allowsSameNameSiblings = definition.allowsSameNameSiblings(); + } + + public static NodeDefinitionImpl create(NodeDefinition definition) { + if (definition instanceof NodeDefinitionImpl) { + return (NodeDefinitionImpl) definition; + } else { + return new NodeDefinitionImpl(definition); + } + } + + //-----------------------------------------------------< NodeDefinition >--- + /** + * @see javax.jcr.nodetype.NodeDefinition#getRequiredPrimaryTypes() + */ + public NodeType[] getRequiredPrimaryTypes() { + return requiredPrimaryTypes; + } + + /** + * @see javax.jcr.nodetype.NodeDefinition#getDefaultPrimaryType() + */ + public NodeType getDefaultPrimaryType() { + return defaultPrimaryType; + } + + /** + * @see javax.jcr.nodetype.NodeDefinition#allowsSameNameSiblings() + */ + public boolean allowsSameNameSiblings() { + return allowsSameNameSiblings; + } + + /** + * @see javax.jcr.nodetype.NodeDefinition#getDefaultPrimaryTypeName() + */ + public String getDefaultPrimaryTypeName() { + return defaultPrimaryType.getName(); + } + + /** + * @see javax.jcr.nodetype.NodeDefinition#getRequiredPrimaryTypeNames() + */ + public String[] getRequiredPrimaryTypeNames() { + String[] names = new String[requiredPrimaryTypes.length]; + for (int i = 0; i < requiredPrimaryTypes.length; i++) { + names[i] = requiredPrimaryTypes[i].getName(); + } + return names; + } + + //-------------------------------------< implementation specific method >--- + /** + * Returns xml representation + * + * @return xml representation + * @param document + */ + @Override + public Element toXml(Document document) { + Element elem = super.toXml(document); + elem.setAttribute(SAMENAMESIBLINGS_ATTRIBUTE, Boolean.toString(allowsSameNameSiblings())); + // defaultPrimaryType can be 'null' + NodeType defaultPrimaryType = getDefaultPrimaryType(); + if (defaultPrimaryType != null) { + elem.setAttribute(DEFAULTPRIMARYTYPE_ATTRIBUTE, defaultPrimaryType.getName()); + } + // reqPrimaryTypes: minimal set is nt:base. + Element reqPrimaryTypes = document.createElement(REQUIREDPRIMARYTYPES_ELEMENT); + for (NodeType nt : getRequiredPrimaryTypes()) { + Element rptElem = document.createElement(REQUIREDPRIMARYTYPE_ELEMENT); + DomUtil.setText(rptElem, nt.getName()); + reqPrimaryTypes.appendChild(rptElem); + + } + elem.appendChild(reqPrimaryTypes); + return elem; + } + + /** + * Returns {@link #CHILDNODEDEFINITION_ELEMENT} + * + * @return always returns {@link #CHILDNODEDEFINITION_ELEMENT}. + */ + @Override + String getElementName() { + return CHILDNODEDEFINITION_ELEMENT; + } + +} Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/nodetype/NodeDefinitionImpl.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/webdav/jcr/nodetype/NodeTypeProperty.java =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/nodetype/NodeTypeProperty.java (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/nodetype/NodeTypeProperty.java (working copy) @@ -0,0 +1,105 @@ +/* + * 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.webdav.jcr.nodetype; + +import org.apache.jackrabbit.commons.webdav.NodeTypeConstants; +import org.apache.jackrabbit.commons.webdav.NodeTypeUtil; +import org.apache.jackrabbit.webdav.property.AbstractDavProperty; +import org.apache.jackrabbit.webdav.property.DavProperty; +import org.apache.jackrabbit.webdav.property.DavPropertyName; +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +import javax.jcr.nodetype.NodeType; +import java.util.Collections; +import java.util.HashSet; +import java.util.Set; + +/** + * NodeTypeProperty... + */ +public class NodeTypeProperty extends AbstractDavProperty> implements NodeTypeConstants { + + private final Set nodetypeNames = new HashSet(); + + public NodeTypeProperty(DavPropertyName name, NodeType nodeType, boolean isProtected) { + this(name, new NodeType[]{nodeType}, isProtected); + } + + public NodeTypeProperty(DavPropertyName name, NodeType[] nodeTypes, boolean isProtected) { + super(name, isProtected); + for (NodeType nt : nodeTypes) { + if (nt != null) { + nodetypeNames.add(nt.getName()); + } + } + } + + public NodeTypeProperty(DavPropertyName name, String[] nodeTypeNames, boolean isProtected) { + super(name, isProtected); + for (String nodeTypeName : nodeTypeNames) { + if (nodeTypeName != null) { + nodetypeNames.add(nodeTypeName); + } + } + } + + /** + * Create a new NodeTypeProperty from the specified general + * DavProperty object. + * + * @param property + */ + public NodeTypeProperty(DavProperty property) { + super(property.getName(), property.isInvisibleInAllprop()); + if (property instanceof NodeTypeProperty) { + nodetypeNames.addAll(((NodeTypeProperty) property).nodetypeNames); + } else { + nodetypeNames.addAll(NodeTypeUtil.ntNamesFromXml(property.getValue())); + } + } + + /** + * Return a set of node type names present in this property. + * + * @return set of node type names + */ + public Set getNodeTypeNames() { + return Collections.unmodifiableSet(nodetypeNames); + } + + /** + * Returns the value of this property which is a Set of nodetype names. + * + * @return a Set of nodetype names (String). + */ + public Set getValue() { + return Collections.unmodifiableSet(nodetypeNames); + } + + /** + * @see org.apache.jackrabbit.webdav.xml.XmlSerializable#toXml(Document) + */ + @Override + public Element toXml(Document document) { + Element elem = getName().toXml(document); + for (String name : getNodeTypeNames()) { + elem.appendChild(NodeTypeUtil.ntNameToXml(name, document)); + } + return elem; + } +} Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/nodetype/NodeTypeProperty.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/webdav/jcr/nodetype/PropertyDefinitionImpl.java =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/nodetype/PropertyDefinitionImpl.java (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/nodetype/PropertyDefinitionImpl.java (working copy) @@ -0,0 +1,179 @@ +/* + * 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.webdav.jcr.nodetype; + +import org.apache.jackrabbit.webdav.xml.DomUtil; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +import javax.jcr.PropertyType; +import javax.jcr.RepositoryException; +import javax.jcr.Value; +import javax.jcr.nodetype.PropertyDefinition; + +/** + * PropertyDefinitionImpl... + */ +public final class PropertyDefinitionImpl extends ItemDefinitionImpl implements PropertyDefinition { + + private static Logger log = LoggerFactory.getLogger(PropertyDefinitionImpl.class); + + private final int type; + private final String[] valueConstraints; + private final Value[] defaultValues; + private final boolean isMultiple; + private final String[] availableQueryOperators; + private final boolean isFullTextSearchable; + private final boolean isQueryOrderable; + + private PropertyDefinitionImpl(PropertyDefinition definition) { + super(definition); + + type = definition.getRequiredType(); + valueConstraints = definition.getValueConstraints(); + defaultValues = definition.getDefaultValues(); + isMultiple = definition.isMultiple(); + availableQueryOperators = definition.getAvailableQueryOperators(); + isFullTextSearchable = definition.isFullTextSearchable(); + isQueryOrderable = definition.isQueryOrderable(); + } + + public static PropertyDefinitionImpl create(PropertyDefinition definition) { + if (definition instanceof PropertyDefinitionImpl) { + return (PropertyDefinitionImpl)definition; + } else { + return new PropertyDefinitionImpl(definition); + } + } + + //----------------------------------------< PropertyDefintion interface >--- + /** + * @see PropertyDefinition#getRequiredType() + */ + public int getRequiredType() { + return type; + } + + /** + * @see PropertyDefinition#getValueConstraints() + */ + public String[] getValueConstraints() { + return valueConstraints; + } + + /** + * @see PropertyDefinition#getDefaultValues() + */ + public Value[] getDefaultValues() { + return defaultValues; + } + + /** + * @see PropertyDefinition#isMultiple() + */ + public boolean isMultiple() { + return isMultiple; + } + + /** + * @see PropertyDefinition#getAvailableQueryOperators() + */ + public String[] getAvailableQueryOperators() { + return availableQueryOperators; + } + + /** + * @see PropertyDefinition#isFullTextSearchable() + */ + public boolean isFullTextSearchable() { + return isFullTextSearchable; + } + + /** + * @see PropertyDefinition#isQueryOrderable() + */ + public boolean isQueryOrderable() { + return isQueryOrderable; + } + + //-------------------------------------< implementation specific method >--- + /** + * Return xml representation + * + * @return xml representation + * @param document + */ + @Override + public Element toXml(Document document) { + Element elem = super.toXml(document); + + elem.setAttribute(MULTIPLE_ATTRIBUTE, Boolean.toString(isMultiple())); + elem.setAttribute(REQUIREDTYPE_ATTRIBUTE, PropertyType.nameFromValue(getRequiredType())); + + // JCR 2.0 extensions + elem.setAttribute(FULL_TEXT_SEARCHABLE_ATTRIBUTE, Boolean.toString(isFullTextSearchable())); + elem.setAttribute(QUERY_ORDERABLE_ATTRIBUTE, Boolean.toString(isQueryOrderable())); + + // default values may be 'null' + Value[] values = getDefaultValues(); + if (values != null) { + Element dvElement = document.createElement(DEFAULTVALUES_ELEMENT); + for (Value value : values) { + try { + Element valElem = document.createElement(DEFAULTVALUE_ELEMENT); + DomUtil.setText(valElem, value.getString()); + dvElement.appendChild(valElem); + } catch (RepositoryException e) { + // should not occur + log.error(e.getMessage()); + } + } + elem.appendChild(dvElement); + } + // value constraints array is never null. + Element constrElem = document.createElement(VALUECONSTRAINTS_ELEMENT); + for (String constraint : getValueConstraints()) { + Element vcElem = document.createElement(VALUECONSTRAINT_ELEMENT); + DomUtil.setText(vcElem, constraint); + constrElem.appendChild(vcElem); + } + elem.appendChild(constrElem); + + // JCR 2.0 extension + Element qopElem = document.createElement(AVAILABLE_QUERY_OPERATORS_ELEMENT); + for (String qop : getAvailableQueryOperators()) { + Element opElem = document.createElement(AVAILABLE_QUERY_OPERATOR_ELEMENT); + DomUtil.setText(opElem, qop); + qopElem.appendChild(opElem); + } + elem.appendChild(qopElem); + + return elem; + } + + /** + * Returns {@link #PROPERTYDEFINITION_ELEMENT}. + * + * @return always returns {@link #PROPERTYDEFINITION_ELEMENT} + */ + @Override + String getElementName() { + return PROPERTYDEFINITION_ELEMENT; + } +} Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/nodetype/PropertyDefinitionImpl.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/webdav/jcr/observation/SubscriptionImpl.java =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/observation/SubscriptionImpl.java (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/observation/SubscriptionImpl.java (working copy) @@ -0,0 +1,637 @@ +/* + * 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.webdav.jcr.observation; + +import org.apache.jackrabbit.commons.webdav.EventUtil; +import org.apache.jackrabbit.commons.webdav.JcrRemotingConstants; +import org.apache.jackrabbit.spi.Name; +import org.apache.jackrabbit.spi.commons.AdditionalEventInfo; +import org.apache.jackrabbit.spi.commons.SessionExtensions; +import org.apache.jackrabbit.webdav.DavException; +import org.apache.jackrabbit.webdav.DavResourceLocator; +import org.apache.jackrabbit.webdav.DavServletResponse; +import org.apache.jackrabbit.webdav.transaction.TransactionResource; +import org.apache.jackrabbit.webdav.jcr.transaction.TransactionListener; +import org.apache.jackrabbit.webdav.jcr.JcrDavException; +import org.apache.jackrabbit.webdav.jcr.JcrDavSession; +import org.apache.jackrabbit.webdav.observation.EventBundle; +import org.apache.jackrabbit.webdav.observation.EventDiscovery; +import org.apache.jackrabbit.webdav.observation.EventType; +import org.apache.jackrabbit.webdav.observation.Filter; +import org.apache.jackrabbit.webdav.observation.ObservationConstants; +import org.apache.jackrabbit.webdav.observation.ObservationResource; +import org.apache.jackrabbit.webdav.observation.Subscription; +import org.apache.jackrabbit.webdav.observation.SubscriptionInfo; +import org.apache.jackrabbit.webdav.observation.DefaultEventType; +import org.apache.jackrabbit.webdav.xml.DomUtil; +import org.apache.jackrabbit.webdav.xml.Namespace; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +import javax.jcr.RepositoryException; +import javax.jcr.Session; +import javax.jcr.UnsupportedRepositoryOperationException; +import javax.jcr.observation.Event; +import javax.jcr.observation.EventIterator; +import javax.jcr.observation.EventListener; +import javax.jcr.observation.ObservationManager; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.UUID; + +/** + * The Subscription class encapsulates a single subscription with + * the following responsibilities:

    + *
  • Providing access to the subscription info,
  • + *
  • Recording events this subscription is interested in,
  • + *
  • Providing access to the events.
  • + *
+ */ +public class SubscriptionImpl implements Subscription, ObservationConstants, EventListener { + + private static Logger log = LoggerFactory.getLogger(SubscriptionImpl.class); + private static final long DEFAULT_TIMEOUT = 300000; // 5 minutes + + private SubscriptionInfo info; + private long expirationTime; + + private final DavResourceLocator locator; + private final String subscriptionId = UUID.randomUUID().toString(); + private final List eventBundles = new ArrayList(); + private final ObservationManager obsMgr; + private final Session session; + + /** + * Create a new Subscription with the given {@link SubscriptionInfo} + * and {@link org.apache.jackrabbit.webdav.observation.ObservationResource resource}. + * + * @param info + * @param resource + * @throws DavException if resource is not based on a JCR repository or + * the repository does not support observation. + */ + public SubscriptionImpl(SubscriptionInfo info, ObservationResource resource) + throws DavException { + setInfo(info); + locator = resource.getLocator(); + session = JcrDavSession.getRepositorySession(resource.getSession()); + try { + obsMgr = session.getWorkspace().getObservationManager(); + } catch (RepositoryException e) { + throw new DavException(DavServletResponse.SC_INTERNAL_SERVER_ERROR, e); + } + } + + //-------------------------------------------------------< Subscription >--- + /** + * Returns the id of this subscription. + * + * @return subscriptionId + */ + public String getSubscriptionId() { + return subscriptionId; + } + + public boolean eventsProvideNodeTypeInformation() { + String t = session.getRepository().getDescriptor("org.apache.jackrabbit.spi.commons.AdditionalEventInfo"); + return t == null ? false : Boolean.parseBoolean(t); + } + + public boolean eventsProvideNoLocalFlag() { + return session instanceof SessionExtensions; + } + + //----------------------------------------------------< XmlSerializable >--- + /** + * Return the Xml representation of this Subscription as required + * for the {@link org.apache.jackrabbit.webdav.observation.SubscriptionDiscovery} + * webdav property that in included in the response body of a successful SUBSCRIBE + * request or as part of a PROPFIND response. + * + * @return Xml representation + * @see org.apache.jackrabbit.webdav.xml.XmlSerializable#toXml(Document) + * @param document + */ + public Element toXml(Document document) { + Element subscr = DomUtil.createElement(document, XML_SUBSCRIPTION, NAMESPACE); + + subscr.appendChild(info.toXml(document)); + subscr.appendChild(DomUtil.depthToXml(info.isDeep(), document)); + subscr.appendChild(DomUtil.timeoutToXml(info.getTimeOut(), document)); + + if (getSubscriptionId() != null) { + Element id = DomUtil.addChildElement(subscr, XML_SUBSCRIPTIONID, NAMESPACE); + id.appendChild(DomUtil.hrefToXml(getSubscriptionId(), document)); + } + + DomUtil.addChildElement(subscr, XML_EVENTSWITHTYPES, NAMESPACE, + Boolean.toString(eventsProvideNodeTypeInformation())); + DomUtil.addChildElement(subscr, XML_EVENTSWITHLOCALFLAG, NAMESPACE, + Boolean.toString(eventsProvideNoLocalFlag())); + + return subscr; + } + + //--------------------------------------------< implementation specific >--- + /** + * Modify the {@link SubscriptionInfo} for this subscription. + * + * @param info + */ + void setInfo(SubscriptionInfo info) { + this.info = info; + // validate the timeout and adjust value, if it is invalid or missing + long timeout = info.getTimeOut(); + if (timeout <= 0) { + timeout = DEFAULT_TIMEOUT; + } + expirationTime = System.currentTimeMillis() + timeout; + } + + /** + * @return JCR compliant integer representation of the event types defined + * for this {@link SubscriptionInfo}. + */ + int getJcrEventTypes() throws DavException { + EventType[] eventTypes = info.getEventTypes(); + int events = 0; + for (EventType eventType : eventTypes) { + events |= getJcrEventType(eventType); + } + return events; + } + + /** + * @return a String array with size > 0 or null + */ + String[] getUuidFilters() { + return getFilterValues(XML_UUID); + } + + /** + * @return a String array with size > 0 or null + */ + String[] getNodetypeNameFilters() { + return getFilterValues(XML_NODETYPE_NAME); + } + + private String[] getFilterValues(String filterLocalName) { + List values = new ArrayList(); + for (Filter filter : info.getFilters(filterLocalName, NAMESPACE)) { + String val = filter.getValue(); + if (val != null) { + values.add(val); + } + } + return (values.size() > 0) ? values.toArray(new String[values.size()]) : null; + } + + /** + * + * @return true if a {@link ObservationConstants#XML_NOLOCAL} element + * is present in the {@link SubscriptionInfo}. + */ + boolean isNoLocal() { + return info.isNoLocal(); + } + + /** + * @return true if this subscription is intended to be deep. + */ + boolean isDeep() { + return info.isDeep(); + } + + /** + * @return the locator of the {@link ObservationResource resource} this + * Subscription was requested for. + */ + DavResourceLocator getLocator() { + return locator; + } + + /** + * Returns true if this Subscription matches the given + * resource. + * + * @param resource + * @return true if this Subscription matches the given + * resource. + */ + boolean isSubscribedToResource(ObservationResource resource) { + return locator.getResourcePath().equals(resource.getResourcePath()); + } + + /** + * Returns true if this Subscription is expired and therefore + * stopped recording events. + * + * @return true if this Subscription is expired + */ + boolean isExpired() { + return System.currentTimeMillis() > expirationTime; + } + + /** + * Returns a {@link org.apache.jackrabbit.webdav.observation.EventDiscovery} object listing all events that were + * recorded since the last call to this method and clears the list of event + * bundles. + * + * @param timeout time in milliseconds to wait at most for events if none + * are present currently. + * @return object listing all events that were recorded. + * @see #onEvent(EventIterator) + */ + synchronized EventDiscovery discoverEvents(long timeout) { + EventDiscovery ed = new EventDiscovery(); + if (eventBundles.isEmpty() && timeout > 0) { + try { + wait(timeout); + } catch (InterruptedException e) { + // continue and possibly return empty event discovery + } + } + for (EventBundle eb : eventBundles) { + ed.addEventBundle(eb); + } + // clear list + eventBundles.clear(); + return ed; + } + + /** + * Creates a new transaction listener for the scope of a transaction + * commit (save call). + * @return a transaction listener for this subscription. + */ + TransactionListener createTransactionListener() { + if (info.isNoLocal()) { + // a subscription which is not interested in local changes does + // not need the transaction id + return new TransactionEvent() { + @Override + public void onEvent(EventIterator events) { + // ignore + } + + @Override + public void beforeCommit(TransactionResource resource, String lockToken) { + // ignore + } + + @Override + public void afterCommit(TransactionResource resource, + String lockToken, + boolean success) { + // ignore + } + }; + } else { + return new TransactionEvent(); + } + } + + /** + * Suspend this subscription. This call will remove this subscription as + * event listener from the observation manager. + */ + void suspend() throws DavException { + try { + obsMgr.removeEventListener(this); + } catch (RepositoryException e) { + throw new JcrDavException(e); + } + } + + /** + * Resumes this subscription. This call will register this subscription + * again as event listener to the observation manager. + */ + void resume() throws DavException { + try { + obsMgr.addEventListener(this, getJcrEventTypes(), + getLocator().getRepositoryPath(), isDeep(), getUuidFilters(), + getNodetypeNameFilters(), isNoLocal()); + } catch (RepositoryException e) { + throw new JcrDavException(e); + } + } + + //--------------------------------------------< EventListener interface >--- + /** + * Records the events passed as a new event bundle in order to make them + * available with the next {@link #discoverEvents(long)} request. If this + * subscription is expired it will remove itself as listener from the + * observation manager. + * + * @param events to be recorded. + * @see EventListener#onEvent(EventIterator) + * @see #discoverEvents(long) + */ + public synchronized void onEvent(EventIterator events) { + if (!isExpired()) { + eventBundles.add(new EventBundleImpl(events)); + } else { + // expired -> unsubscribe + try { + obsMgr.removeEventListener(this); + } catch (RepositoryException e) { + log.warn("Exception while unsubscribing: " + e); + } + } + notifyAll(); + } + + //-------------------------------------------------------------------------- + /** + * Static utility method to convert the type defined by a + * {@link javax.jcr.observation.Event JCR event} into an EventType + * object. + * + * @param jcrEventType + * @return EventType representation of the given JCR event type. + * @throws IllegalArgumentException if the given int does not represent a + * valid type constants as defined by {@link Event}.
+ * Valid values are + *
    + *
  • {@link Event#NODE_ADDED}
  • + *
  • {@link Event#NODE_REMOVED}
  • + *
  • {@link Event#PROPERTY_ADDED}
  • + *
  • {@link Event#PROPERTY_REMOVED}
  • + *
  • {@link Event#PROPERTY_CHANGED}
  • + *
  • {@link Event#NODE_MOVED}
  • + *
  • {@link Event#PERSIST}
  • + *
+ */ + public static EventType getEventType(int jcrEventType) { + String localName = EventUtil.getEventName(jcrEventType); + return DefaultEventType.create(localName, NAMESPACE); + } + + /** + * @return The DAV event type representation for all known JCR event types. + */ + public static EventType[] getAllEventTypes() { + EventType[] types = DefaultEventType.create(EventUtil.EVENT_ALL, NAMESPACE); + return types; + } + + /** + * Static utility method to convert an EventType as present in + * the Xml body into the corresponding JCR event constant defined by + * {@link javax.jcr.observation.Event}. + * + * @param eventType + * @return Any of the event types defined by {@link Event}.
+ * Possible values are + *
    + *
  • {@link Event#NODE_ADDED}
  • + *
  • {@link Event#NODE_REMOVED}
  • + *
  • {@link Event#PROPERTY_ADDED}
  • + *
  • {@link Event#PROPERTY_REMOVED}
  • + *
  • {@link Event#PROPERTY_CHANGED}
  • + *
  • {@link Event#NODE_MOVED}
  • + *
  • {@link Event#PERSIST}
  • + *
+ * @throws DavException if the given event type does not define a valid + * JCR event type, such as returned by {@link #getEventType(int)}. + */ + public static int getJcrEventType(EventType eventType) throws DavException { + if (eventType == null || !NAMESPACE.equals(eventType.getNamespace())) { + throw new DavException(DavServletResponse.SC_UNPROCESSABLE_ENTITY, "Invalid JCR event type: "+ eventType + ": Namespace mismatch."); + } + String eventName = eventType.getName(); + if (!EventUtil.isValidEventName(eventName)) { + throw new DavException(DavServletResponse.SC_UNPROCESSABLE_ENTITY, "Invalid event type: "+eventName); + } + return EventUtil.getJcrEventType(eventName); + } + + /** + * Inner class EventBundle encapsulates an event bundle as + * recorded {@link SubscriptionImpl#onEvent(EventIterator) on event} and + * provides the possibility to retrieve the Xml representation of the + * bundle and the events included in order to respond to a POLL request. + * + * @see SubscriptionImpl#discoverEvents(long) + */ + private class EventBundleImpl implements EventBundle { + + private final EventIterator events; + + private final String transactionId; + + private EventBundleImpl(EventIterator events) { + this(events, null); + } + + private EventBundleImpl(EventIterator events, String transactionId) { + this.events = events; + this.transactionId = transactionId; + } + + public Element toXml(Document document) { + Element bundle = DomUtil.createElement(document, XML_EVENTBUNDLE, NAMESPACE); + // TODO: this appears to be unused now + if (transactionId != null) { + DomUtil.setAttribute(bundle, XML_EVENT_TRANSACTION_ID, NAMESPACE, transactionId); + } + + boolean localFlagSet = false; + + while (events.hasNext()) { + Event event = events.nextEvent(); + + if (!localFlagSet) { + // obtain remote session identifier + localFlagSet = true; + String name = JcrRemotingConstants.RELATION_REMOTE_SESSION_ID; + Object forSessionId = session.getAttribute(name); + // calculate "local" flags + if (forSessionId != null + && event instanceof AdditionalEventInfo) { + AdditionalEventInfo aei = (AdditionalEventInfo) event; + try { + boolean isLocal = forSessionId.equals( + aei.getSessionAttribute(name)); + DomUtil.setAttribute( + bundle, XML_EVENT_LOCAL, null, + Boolean.toString(isLocal)); + } catch (UnsupportedRepositoryOperationException ex) { + // optional feature + } + } + } + + Element eventElem = DomUtil.addChildElement(bundle, XML_EVENT, NAMESPACE); + // href + String eHref = ""; + try { + boolean isCollection = (event.getType() == Event.NODE_ADDED || event.getType() == Event.NODE_REMOVED); + eHref = locator.getFactory().createResourceLocator(locator.getPrefix(), locator.getWorkspacePath(), event.getPath(), false).getHref(isCollection); + } catch (RepositoryException e) { + // should not occur.... + log.error(e.getMessage()); + } + eventElem.appendChild(DomUtil.hrefToXml(eHref, document)); + // event type + Element eType = DomUtil.addChildElement(eventElem, XML_EVENTTYPE, NAMESPACE); + eType.appendChild(getEventType(event.getType()).toXml(document)); + // user id + DomUtil.addChildElement(eventElem, XML_EVENTUSERID, NAMESPACE, event.getUserID()); + + // try to compute nodetype information + if (event instanceof AdditionalEventInfo) { + try { + DomUtil.addChildElement(eventElem, + XML_EVENTPRIMARNODETYPE, NAMESPACE, + ((AdditionalEventInfo) event) + .getPrimaryNodeTypeName().toString()); + for (Name mixin : ((AdditionalEventInfo) event) + .getMixinTypeNames()) { + DomUtil.addChildElement(eventElem, + XML_EVENTMIXINNODETYPE, NAMESPACE, + mixin.toString()); + } + } catch (UnsupportedRepositoryOperationException ex) { + // optional + } + } + + // Additional JCR 2.0 event information + // user data + try { + DomUtil.addChildElement(eventElem, XML_EVENTUSERDATA, NAMESPACE, event.getUserData()); + } catch (RepositoryException e) { + log.error("Internal error while retrieving event user data. {}", e.getMessage()); + } + // time stamp + try { + DomUtil.addChildElement(eventElem, XML_EVENTDATE, NAMESPACE, String.valueOf(event.getDate())); + } catch (RepositoryException e) { + log.error("Internal error while retrieving event date. {}", e.getMessage()); + } + // identifier + try { + DomUtil.addChildElement(eventElem, XML_EVENTIDENTIFIER, NAMESPACE, event.getIdentifier()); + } catch (RepositoryException e) { + log.error("Internal error while retrieving event identifier. {}", e.getMessage()); + } + // info + try { + serializeInfoMap(eventElem, session, event.getInfo()); + } catch (RepositoryException e) { + log.error("Internal error while retrieving event info. {}", e.getMessage()); + } + } + return bundle; + } + } + + protected static void serializeInfoMap(Element eventElem, Session session, Map map) { + // info + Element info = DomUtil.addChildElement(eventElem, XML_EVENTINFO, NAMESPACE); + Map m = map; + for (Map.Entry entry : m.entrySet()) { + try { + String key = entry.getKey().toString(); + Namespace ns = Namespace.EMPTY_NAMESPACE; + int colon = key.indexOf(':'); + if (colon >= 0) { + String prefix = key.substring(0, colon); + String localname = key.substring(colon + 1); + ns = Namespace.getNamespace(prefix, session.getNamespaceURI(prefix)); + key = localname; + } + Object value = entry.getValue(); + if (value != null) { + DomUtil.addChildElement(info, key, ns, value.toString()); + } else { + DomUtil.addChildElement(info, key, ns); + } + } catch (RepositoryException nse) { + log.error("Internal error while getting namespaceUri, info map field skipped for {}", entry.getKey()); + } + } + } + + //----------------------------< TransactionEvent >------------------------ + + /** + * Implements a transaction event which listeners for events during a save + * call on the repository. + */ + private class TransactionEvent implements EventListener, TransactionListener { + + private String transactionId; + + /** + * {@inheritDoc} + */ + public void onEvent(EventIterator events) { + String tId = transactionId; + if (tId == null) { + tId = UUID.randomUUID().toString(); + } + synchronized (SubscriptionImpl.this) { + eventBundles.add(new EventBundleImpl(events, tId)); + SubscriptionImpl.this.notifyAll(); + } + } + + //-----------------------------< TransactionListener >------------------ + + /** + * {@inheritDoc} + */ + public void beforeCommit(TransactionResource resource, String lockToken) { + try { + transactionId = lockToken; + obsMgr.addEventListener(this, getJcrEventTypes(), + getLocator().getRepositoryPath(), isDeep(), getUuidFilters(), + getNodetypeNameFilters(), isNoLocal()); + // suspend the subscription + suspend(); + } catch (RepositoryException e) { + log.warn("Unable to register TransactionListener: " + e); + } catch (DavException e) { + log.warn("Unable to register TransactionListener: " + e); + } + } + + /** + * {@inheritDoc} + */ + public void afterCommit(TransactionResource resource, + String lockToken, + boolean success) { + try { + // resume the subscription + resume(); + // remove this transaction event + obsMgr.removeEventListener(this); + } catch (RepositoryException e) { + log.warn("Unable to remove listener: " + e); + } catch (DavException e) { + log.warn("Unable to resume Subscription: " + e); + } + } + } +} Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/observation/SubscriptionImpl.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/webdav/jcr/observation/SubscriptionManagerImpl.java =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/observation/SubscriptionManagerImpl.java (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/observation/SubscriptionManagerImpl.java (working copy) @@ -0,0 +1,358 @@ +/* + * 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.webdav.jcr.observation; + +import org.apache.jackrabbit.webdav.DavException; +import org.apache.jackrabbit.webdav.DavResourceLocator; +import org.apache.jackrabbit.webdav.DavServletResponse; +import org.apache.jackrabbit.webdav.transaction.TransactionResource; +import org.apache.jackrabbit.webdav.jcr.JcrDavException; +import org.apache.jackrabbit.webdav.jcr.JcrDavSession; +import org.apache.jackrabbit.webdav.jcr.transaction.TransactionListener; +import org.apache.jackrabbit.webdav.observation.EventDiscovery; +import org.apache.jackrabbit.webdav.observation.ObservationResource; +import org.apache.jackrabbit.webdav.observation.Subscription; +import org.apache.jackrabbit.webdav.observation.SubscriptionDiscovery; +import org.apache.jackrabbit.webdav.observation.SubscriptionInfo; +import org.apache.jackrabbit.webdav.observation.SubscriptionManager; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.w3c.dom.Element; +import org.w3c.dom.Document; + +import javax.jcr.RepositoryException; +import javax.jcr.Session; +import javax.jcr.observation.ObservationManager; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.Set; +import java.util.Map; +import java.util.List; +import java.util.ArrayList; + +/** + * SubscriptionManager collects all subscriptions requested, handles + * the subscription timeout and provides METHODS to discover subscriptions + * present on a given resource as well as events for an specific subscription. + */ +// todo: make sure all expired subscriptions are removed! +public class SubscriptionManagerImpl implements SubscriptionManager, TransactionListener { + + private static Logger log = LoggerFactory.getLogger(SubscriptionManagerImpl.class); + + /** + * Map containing all {@link org.apache.jackrabbit.webdav.observation.Subscription subscriptions}. + */ + private final SubscriptionMap subscriptions = new SubscriptionMap(); + + private final Map> transactionListenerById = new HashMap>(); + + /** + * Retrieve the {@link org.apache.jackrabbit.webdav.observation.SubscriptionDiscovery} + * object for the given resource. Note, that the discovery object will be empty + * if there are no subscriptions present.
+ * Note that all subscriptions present on the given resource are returned. + * However, the subscription id will not be visible in order to avoid abuse + * by clients not having registered the subscription originally. + * + * @param resource + */ + public SubscriptionDiscovery getSubscriptionDiscovery(ObservationResource resource) { + Subscription[] subsForResource = subscriptions.getByPath(resource.getLocator()); + return new SubscriptionDiscovery(subsForResource); + } + + /** + * Create a new Subscription or update an existing Subscription + * and add it as eventlistener to the {@link javax.jcr.observation.ObservationManager}. + * + * @param info + * @param subscriptionId + * @param resource + * @return Subscription that has been added to the {@link javax.jcr.observation.ObservationManager} + * @throws DavException if the subscription fails + */ + public Subscription subscribe(SubscriptionInfo info, String subscriptionId, + ObservationResource resource) + throws DavException { + + Subscription subscription; + if (subscriptionId == null) { + // new subscription + SubscriptionImpl newSubs = new SubscriptionImpl(info, resource); + registerSubscription(newSubs, resource); + + // adjust references to this subscription + subscriptions.put(newSubs.getSubscriptionId(), newSubs); + resource.getSession().addReference(newSubs.getSubscriptionId()); + subscription = newSubs; + } else { + // refresh/modify existing one + SubscriptionImpl existing = validate(subscriptionId, resource); + existing.setInfo(info); + registerSubscription(existing, resource); + + subscription = new WrappedSubscription(existing); + } + return subscription; + } + + /** + * Register the event listener defined by the given subscription to the + * repository's observation manager. + * + * @param subscription + * @param resource + * @throws DavException + */ + private void registerSubscription(SubscriptionImpl subscription, + ObservationResource resource) throws DavException { + try { + Session session = getRepositorySession(resource); + ObservationManager oMgr = session.getWorkspace().getObservationManager(); + String itemPath = subscription.getLocator().getRepositoryPath(); + oMgr.addEventListener(subscription, subscription.getJcrEventTypes(), + itemPath, subscription.isDeep(), + subscription.getUuidFilters(), + subscription.getNodetypeNameFilters(), + subscription.isNoLocal()); + } catch (RepositoryException e) { + log.error("Unable to register eventlistener: "+e.getMessage()); + throw new JcrDavException(e); + } + } + + /** + * Unsubscribe the Subscription with the given id and remove it + * from the {@link javax.jcr.observation.ObservationManager} as well as + * from the internal map. + * + * @param subscriptionId + * @param resource + * @throws DavException + */ + public void unsubscribe(String subscriptionId, ObservationResource resource) + throws DavException { + + SubscriptionImpl subs = validate(subscriptionId, resource); + unregisterSubscription(subs, resource); + } + + /** + * Remove the event listener defined by the specified subscription from + * the repository's observation manager and clean up the references present + * on the DavSession. + * + * @param subscription + * @param resource + * @throws DavException + */ + private void unregisterSubscription(SubscriptionImpl subscription, + ObservationResource resource) throws DavException { + try { + Session session = getRepositorySession(resource); + session.getWorkspace().getObservationManager().removeEventListener(subscription); + String sId = subscription.getSubscriptionId(); + + // clean up any references + subscriptions.remove(sId); + resource.getSession().removeReference(sId); + + } catch (RepositoryException e) { + log.error("Unable to remove eventlistener: "+e.getMessage()); + throw new JcrDavException(e); + } + } + + /** + * Retrieve all event bundles accumulated since for the subscription specified + * by the given id. + * + * @param subscriptionId + * @param timeout timeout in milliseconds + * @param resource + * @return object encapsulating the events. + */ + public EventDiscovery poll(String subscriptionId, long timeout, ObservationResource resource) + throws DavException { + + SubscriptionImpl subs = validate(subscriptionId, resource); + return subs.discoverEvents(timeout); + } + + /** + * Validate the given subscription id. The validation will fail under the following + * conditions:
    + *
  • The subscription with the given id does not exist,
  • + *
  • DavResource path does not match the subscription id,
  • + *
  • The subscription with the given id is already expired.
  • + *
+ * + * @param subscriptionId + * @param resource + * @return Subscription with the given id. + * @throws DavException if an error occurred while retrieving the Subscription + */ + private SubscriptionImpl validate(String subscriptionId, ObservationResource resource) + throws DavException { + + SubscriptionImpl subs; + if (subscriptions.contains(subscriptionId)) { + subs = subscriptions.get(subscriptionId); + if (!subs.isSubscribedToResource(resource)) { + throw new DavException(DavServletResponse.SC_PRECONDITION_FAILED, "Attempt to operate on subscription with invalid resource path."); + } + if (subs.isExpired()) { + unregisterSubscription(subs, resource); + throw new DavException(DavServletResponse.SC_PRECONDITION_FAILED, "Attempt to operate on expired subscription."); + } + return subs; + } else { + throw new DavException(DavServletResponse.SC_PRECONDITION_FAILED, "Attempt to modify or to poll for non-existing subscription."); + } + } + + /** + * @param resource + * @return JCR session + */ + private static Session getRepositorySession(ObservationResource resource) throws DavException { + return JcrDavSession.getRepositorySession(resource.getSession()); + } + + //---------------------------< TransactionListener >------------------------ + + /** + * {@inheritDoc} + */ + public synchronized void beforeCommit(TransactionResource resource, + String lockToken) { + // suspend regular subscriptions during a commit + List transactionListeners = new ArrayList(); + for (Iterator it = subscriptions.iterator(); it.hasNext(); ) { + SubscriptionImpl sub = it.next(); + TransactionListener tl = sub.createTransactionListener(); + tl.beforeCommit(resource, lockToken); + transactionListeners.add(tl); + } + transactionListenerById.put(lockToken, transactionListeners); + } + + /** + * {@inheritDoc} + */ + public void afterCommit(TransactionResource resource, String lockToken, boolean success) { + List transactionListeners = transactionListenerById.remove(lockToken); + if (transactionListeners != null) { + for (TransactionListener txListener : transactionListeners) { + txListener.afterCommit(resource, lockToken, success); + } + } + } + + //----------------------------------------------< private inner classes >--- + /** + * Private inner class wrapping around an Subscription as + * present in the internal map. This allows to hide the subscription Id + * from other sessions, that did create the subscription. + */ + private static class WrappedSubscription implements Subscription { + + private final Subscription delegatee; + + private WrappedSubscription(Subscription subsc) { + this.delegatee = subsc; + } + + public String getSubscriptionId() { + // always return null, since the subscription id must not be exposed + // but to the client, that created the subscription. + return null; + } + + public Element toXml(Document document) { + return delegatee.toXml(document); + } + + public boolean eventsProvideNodeTypeInformation() { + return delegatee.eventsProvideNodeTypeInformation(); + } + + public boolean eventsProvideNoLocalFlag() { + return delegatee.eventsProvideNoLocalFlag(); + } + } + + /** + * Private inner class SubscriptionMap that allows for quick + * access by resource path as well as by subscription id. + */ + private class SubscriptionMap { + + private HashMap subscriptions = new HashMap(); + private HashMap> ids = new HashMap>(); + + private boolean contains(String subscriptionId) { + return subscriptions.containsKey(subscriptionId); + } + + private SubscriptionImpl get(String subscriptionId) { + return subscriptions.get(subscriptionId); + } + + private Iterator iterator() { + return subscriptions.values().iterator(); + } + + private void put(String subscriptionId, SubscriptionImpl subscription) { + subscriptions.put(subscriptionId, subscription); + DavResourceLocator key = subscription.getLocator(); + Set idSet; + if (ids.containsKey(key)) { + idSet = ids.get(key); + } else { + idSet = new HashSet(); + ids.put(key, idSet); + } + if (!idSet.contains(subscriptionId)) { + idSet.add(subscriptionId); + } + } + + private void remove(String subscriptionId) { + SubscriptionImpl sub = subscriptions.remove(subscriptionId); + ids.get(sub.getLocator()).remove(subscriptionId); + } + + private Subscription[] getByPath(DavResourceLocator locator) { + Set idSet = ids.get(locator); + if (idSet != null && !idSet.isEmpty()) { + Subscription[] subsForResource = new Subscription[idSet.size()]; + int i = 0; + for (String id : idSet) { + SubscriptionImpl s = subscriptions.get(id); + subsForResource[i] = new WrappedSubscription(s); + i++; + } + return subsForResource; + } else { + return new Subscription[0]; + } + } + } +} Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/observation/SubscriptionManagerImpl.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/webdav/jcr/property/JcrDavPropertyNameSet.java =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/property/JcrDavPropertyNameSet.java (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/property/JcrDavPropertyNameSet.java (working copy) @@ -0,0 +1,155 @@ +/* + * 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.webdav.jcr.property; + +import org.apache.jackrabbit.webdav.jcr.ItemResourceConstants; +import org.apache.jackrabbit.webdav.observation.ObservationConstants; +import org.apache.jackrabbit.webdav.property.DavPropertyName; +import org.apache.jackrabbit.webdav.property.DavPropertyNameSet; +import org.apache.jackrabbit.webdav.version.DeltaVConstants; +import org.apache.jackrabbit.webdav.version.VersionControlledResource; +import org.apache.jackrabbit.webdav.version.VersionHistoryResource; +import org.apache.jackrabbit.webdav.version.VersionResource; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * JcrDavPropertyNameSet... + */ +public final class JcrDavPropertyNameSet implements ItemResourceConstants { + + /** + * logger instance + */ + private static final Logger log = LoggerFactory.getLogger(JcrDavPropertyNameSet.class); + + + //------------------------------------------------< property name sets >---- + /** + * Default property names present with all resources. + */ + public static final DavPropertyNameSet BASE_SET = new DavPropertyNameSet(); + static { + BASE_SET.add(DavPropertyName.DISPLAYNAME); + BASE_SET.add(DavPropertyName.RESOURCETYPE); + BASE_SET.add(DavPropertyName.ISCOLLECTION); + BASE_SET.add(DavPropertyName.GETLASTMODIFIED); + BASE_SET.add(DavPropertyName.CREATIONDATE); + BASE_SET.add(DavPropertyName.SUPPORTEDLOCK); + BASE_SET.add(DavPropertyName.LOCKDISCOVERY); + BASE_SET.add(DeltaVConstants.SUPPORTED_METHOD_SET); + BASE_SET.add(DeltaVConstants.SUPPORTED_REPORT_SET); + BASE_SET.add(DeltaVConstants.CREATOR_DISPLAYNAME); + BASE_SET.add(DeltaVConstants.COMMENT); + BASE_SET.add(JCR_WORKSPACE_NAME); + } + + /** + * Property names defined for JCR workspace resources. + */ + public static final DavPropertyNameSet WORKSPACE_SET = new DavPropertyNameSet(); + static { + WORKSPACE_SET.add(DeltaVConstants.WORKSPACE); + WORKSPACE_SET.add(JCR_NAMESPACES); + WORKSPACE_SET.add(JCR_NODETYPES_CND); + } + + /** + * Additional property names defined for existing and non-existing item resources. + */ + public static final DavPropertyNameSet ITEM_BASE_SET = new DavPropertyNameSet(); + static { + ITEM_BASE_SET.add(DavPropertyName.GETCONTENTTYPE); + ITEM_BASE_SET.add(DeltaVConstants.WORKSPACE); + ITEM_BASE_SET.add(ObservationConstants.SUBSCRIPTIONDISCOVERY); + } + + /** + * Additional property names defined for existing item resources. + */ + public static final DavPropertyNameSet EXISTING_ITEM_BASE_SET = new DavPropertyNameSet(ITEM_BASE_SET); + static { + EXISTING_ITEM_BASE_SET.add(JCR_NAME); + EXISTING_ITEM_BASE_SET.add(JCR_PATH); + EXISTING_ITEM_BASE_SET.add(JCR_DEPTH); + EXISTING_ITEM_BASE_SET.add(JCR_DEFINITION); + } + + /** + * Additional property names defined by single value JCR properties. + */ + public static final DavPropertyNameSet PROPERTY_SET = new DavPropertyNameSet(); + static { + PROPERTY_SET.add(JCR_TYPE); + PROPERTY_SET.add(JCR_VALUE); + PROPERTY_SET.add(JCR_LENGTH); + } + + /** + * Additional property names defined by single value JCR properties. + */ + public static final DavPropertyNameSet PROPERTY_MV_SET = new DavPropertyNameSet(); + static { + PROPERTY_MV_SET.add(JCR_TYPE); + PROPERTY_MV_SET.add(JCR_VALUES); + PROPERTY_MV_SET.add(JCR_LENGTHS); + } + + /** + * Additional property names defined by regular JCR nodes. + */ + public static final DavPropertyNameSet NODE_SET = new DavPropertyNameSet(); + static { + NODE_SET.add(JCR_PRIMARYNODETYPE); + NODE_SET.add(JCR_MIXINNODETYPES); + NODE_SET.add(JCR_INDEX); + NODE_SET.add(JCR_REFERENCES); + NODE_SET.add(JCR_WEAK_REFERENCES); + } + + /** + * Additional property names defined by versionable JCR nodes. + */ + public static final DavPropertyNameSet VERSIONABLE_SET = new DavPropertyNameSet(); + static { + VERSIONABLE_SET.add(VersionControlledResource.VERSION_HISTORY); + VERSIONABLE_SET.add(VersionControlledResource.AUTO_VERSION); + } + + /** + * Additional property names defined by JCR version nodes. + */ + public static final DavPropertyNameSet VERSION_SET = new DavPropertyNameSet(); + static { + VERSION_SET.add(VersionResource.VERSION_NAME); + VERSION_SET.add(VersionResource.LABEL_NAME_SET); + VERSION_SET.add(VersionResource.PREDECESSOR_SET); + VERSION_SET.add(VersionResource.SUCCESSOR_SET); + VERSION_SET.add(VersionResource.VERSION_HISTORY); + VERSION_SET.add(VersionResource.CHECKOUT_SET); + } + + /** + * Additional property names defined by JCR version history nodes. + */ + public static final DavPropertyNameSet VERSIONHISTORY_SET = new DavPropertyNameSet(); + static { + VERSIONHISTORY_SET.add(VersionHistoryResource.ROOT_VERSION); + VERSIONHISTORY_SET.add(VersionHistoryResource.VERSION_SET); + VERSIONHISTORY_SET.add(JCR_VERSIONABLEUUID); + } +} \ No newline at end of file Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/property/JcrDavPropertyNameSet.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/webdav/jcr/property/LengthsProperty.java =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/property/LengthsProperty.java (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/property/LengthsProperty.java (working copy) @@ -0,0 +1,67 @@ +/* + * 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.webdav.jcr.property; + +import org.apache.jackrabbit.webdav.jcr.ItemResourceConstants; +import org.apache.jackrabbit.webdav.property.AbstractDavProperty; +import org.apache.jackrabbit.webdav.xml.DomUtil; +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +/** + * LengthsProperty extends {@link org.apache.jackrabbit.webdav.property.DavProperty} providing + * utilities to handle the multiple lengths of the property item represented + * by this resource. + */ +public class LengthsProperty extends AbstractDavProperty implements ItemResourceConstants { + + private final long[] value; + + /** + * Create a new LengthsProperty from the given long array. + * + * @param lengths as retrieved from the JCR property + */ + public LengthsProperty(long[] lengths) { + super(JCR_LENGTHS, true); + this.value = lengths; + } + + /** + * Returns an array of {@link long}s representing the value of this + * property. + * + * @return an array of {@link long}s + */ + public long[] getValue() { + return value; + } + + /** + * @see org.apache.jackrabbit.webdav.xml.XmlSerializable#toXml(Document) + */ + @Override + public Element toXml(Document document) { + Element elem = getName().toXml(document); + for (long length : value) { + String txtContent = String.valueOf(length); + DomUtil.addChildElement(elem, XML_LENGTH, ItemResourceConstants.NAMESPACE, txtContent); + } + return elem; + } + +} Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/property/LengthsProperty.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/webdav/jcr/property/NamespacesProperty.java =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/property/NamespacesProperty.java (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/property/NamespacesProperty.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.webdav.jcr.property; + +import org.apache.jackrabbit.webdav.DavException; +import org.apache.jackrabbit.webdav.DavServletResponse; +import org.apache.jackrabbit.webdav.jcr.ItemResourceConstants; +import org.apache.jackrabbit.webdav.property.AbstractDavProperty; +import org.apache.jackrabbit.webdav.property.DavProperty; +import org.apache.jackrabbit.webdav.xml.DomUtil; +import org.apache.jackrabbit.webdav.xml.Namespace; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +import javax.jcr.NamespaceRegistry; +import javax.jcr.RepositoryException; +import java.util.List; +import java.util.Map; +import java.util.HashMap; +import java.util.Collections; + +/** + * NamespacesProperty... + */ +public class NamespacesProperty extends AbstractDavProperty> implements ItemResourceConstants { + + private static Logger log = LoggerFactory.getLogger(NamespacesProperty.class); + + private final Map value = new HashMap(); + + public NamespacesProperty(NamespaceRegistry nsReg) throws RepositoryException { + super(JCR_NAMESPACES, false); + if (nsReg != null) { + for (String prefix : nsReg.getPrefixes()) { + value.put(prefix, nsReg.getURI(prefix)); + } + } + } + + public NamespacesProperty(Map namespaces) { + super(JCR_NAMESPACES, false); + value.putAll(namespaces); + } + + public NamespacesProperty(DavProperty property) throws DavException { + super(JCR_NAMESPACES, false); + Object v = property.getValue(); + if (!(v instanceof List)) { + log.warn("Unexpected structure of dcr:namespace property."); + throw new DavException(DavServletResponse.SC_INTERNAL_SERVER_ERROR); + } + // retrieve list of prefix/uri pairs that build the new values of + // the ns-registry + for (Object listEntry : (List) v) { + if (listEntry instanceof Element) { + Element e = (Element)listEntry; + if (XML_NAMESPACE.equals(e.getLocalName())) { + Element pElem = DomUtil.getChildElement(e, XML_PREFIX, ItemResourceConstants.NAMESPACE); + String prefix = DomUtil.getText(pElem, Namespace.EMPTY_NAMESPACE.getPrefix()); + Element uElem = DomUtil.getChildElement(e, XML_URI, ItemResourceConstants.NAMESPACE); + String uri = DomUtil.getText(uElem, Namespace.EMPTY_NAMESPACE.getURI()); + value.put(prefix, uri); + } + } + } + } + + public Map getNamespaces() { + return Collections.unmodifiableMap(value); + } + + public Map getValue() { + return Collections.unmodifiableMap(value); + } + + /** + * @see org.apache.jackrabbit.webdav.xml.XmlSerializable#toXml(Document) + */ + @Override + public Element toXml(Document document) { + Element elem = getName().toXml(document); + for (String prefix : value.keySet()) { + String uri = value.get(prefix); + Element nsElem = DomUtil.addChildElement(elem, XML_NAMESPACE, ItemResourceConstants.NAMESPACE); + DomUtil.addChildElement(nsElem, XML_PREFIX, ItemResourceConstants.NAMESPACE, prefix); + DomUtil.addChildElement(nsElem, XML_URI, ItemResourceConstants.NAMESPACE, uri); + } + return elem; + } + +} Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/property/NamespacesProperty.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/webdav/jcr/property/ValuesProperty.java =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/property/ValuesProperty.java (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/property/ValuesProperty.java (working copy) @@ -0,0 +1,191 @@ +/* + * 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.webdav.jcr.property; + +import org.apache.jackrabbit.commons.webdav.ValueUtil; +import org.apache.jackrabbit.value.ValueHelper; +import org.apache.jackrabbit.webdav.DavException; +import org.apache.jackrabbit.webdav.DavServletResponse; +import org.apache.jackrabbit.webdav.jcr.ItemResourceConstants; +import org.apache.jackrabbit.webdav.property.AbstractDavProperty; +import org.apache.jackrabbit.webdav.property.DavProperty; +import org.apache.jackrabbit.webdav.property.DavPropertyName; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +import javax.jcr.PropertyType; +import javax.jcr.RepositoryException; +import javax.jcr.Value; +import javax.jcr.ValueFormatException; +import javax.jcr.ValueFactory; + +/** + * ValuesProperty implements {@link org.apache.jackrabbit.webdav.property.DavProperty} + * providing utilities to handle the value(s) of a JCR property item resource. + * In case the property is multivalued the DavProperty value consists of + * an element named {@link #JCR_VALUES} otherwise its name is {@link #JCR_VALUE}. + */ +public class ValuesProperty extends AbstractDavProperty implements ItemResourceConstants { + + private static Logger log = LoggerFactory.getLogger(ValuesProperty.class); + + private final Value[] jcrValues; + + /** + * Create a new ValuesProperty from the given single {@link Value}. + * + * @param value Array of Value objects as obtained from the JCR property. + */ + public ValuesProperty(Value value) { + super(JCR_VALUE, false); + // finally set the value to the DavProperty + jcrValues = (value == null) ? new Value[0] : new Value[] {value}; + } + + /** + * Create a new ValuesProperty from the given {@link javax.jcr.Value Value + * array}. + * + * @param values Array of Value objects as obtained from the JCR property. + */ + public ValuesProperty(Value[] values) { + super(JCR_VALUES, false); + // finally set the value to the DavProperty + jcrValues = (values == null) ? new Value[0] : values; + } + + /** + * Wrap the specified DavProperty in a new ValuesProperty. + * + * @param property + * @param defaultType default type of the values to be deserialized. If however + * the {@link #XML_VALUE 'value'} elements provide a {@link #ATTR_VALUE_TYPE 'type'} + * attribute, the default value is ignored. + * @param valueFactory Factory used to retrieve JCR values from the value + * of the given DavProperty. + */ + public ValuesProperty(DavProperty property, int defaultType, + ValueFactory valueFactory) + throws RepositoryException, DavException { + super(property.getName(), false); + + if (!(JCR_VALUES.equals(property.getName()) || JCR_VALUE.equals(getName()))) { + throw new DavException(DavServletResponse.SC_BAD_REQUEST, "ValuesProperty may only be created with a property that has name="+JCR_VALUES.getName()); + } + + jcrValues = ValueUtil.valuesFromXml(property.getValue(), defaultType, valueFactory); + } + + private void checkPropertyName(DavPropertyName reqName) throws ValueFormatException { + if (!reqName.equals(getName())) { + throw new ValueFormatException("Attempt to retrieve multiple values from single property '" + getName() + "'."); + } + } + + /** + * Converts the value of this property to a {@link javax.jcr.Value value array}. + * + * @return Array of Value objects + * @throws ValueFormatException if converting the internal jcr values to + * the specified value type fails. + */ + public Value[] getJcrValues(int propertyType, ValueFactory valueFactory) throws ValueFormatException { + checkPropertyName(JCR_VALUES); + Value[] vs = new Value[jcrValues.length]; + for (int i = 0; i < jcrValues.length; i++) { + vs[i] = ValueHelper.convert(jcrValues[i], propertyType, valueFactory); + } + return vs; + } + + /** + * Returns the internal property value as jcr Value array + * + * @return the internal property value as jcr Value array + */ + public Value[] getJcrValues() throws ValueFormatException { + checkPropertyName(JCR_VALUES); + return jcrValues; + } + + /** + * + * @param propertyType + * @return + * @throws ValueFormatException + */ + public Value getJcrValue(int propertyType, ValueFactory valueFactory) throws ValueFormatException { + checkPropertyName(JCR_VALUE); + return (jcrValues.length == 0) + ? null + : ValueHelper.convert(jcrValues[0], propertyType, valueFactory); + } + + /** + * + * @return + * @throws ValueFormatException + */ + public Value getJcrValue() throws ValueFormatException { + checkPropertyName(JCR_VALUE); + return (jcrValues.length == 0) ? null : jcrValues[0]; + } + + /** + * Returns the type of the {@link Value value}s present in this property + * or {@link PropertyType#UNDEFINED} if no values are available. + * + * @return type of values or {@link PropertyType#UNDEFINED} + */ + public int getValueType() { + // TODO: check if correct behaviour if values array is empty + return (jcrValues.length > 0) ? jcrValues[0].getType() : PropertyType.UNDEFINED; + } + + /** + * Returns an array of {@link Value}s representing the value of this + * property. + * + * @return an array of {@link Value}s + * @see #getJcrValues() + * @see #getJcrValue() + */ + public Value[] getValue() { + return jcrValues; + } + + /** + * + * @param document + * @return the xml element + */ + @Override + public Element toXml(Document document) { + Element elem = getName().toXml(document); + try { + for (Value v : jcrValues) { + Element xmlValue = ValueUtil.valueToXml(v, document); + elem.appendChild(xmlValue); + } + } catch (RepositoryException e) { + log.error("Unexpected Error while converting jcr value to String: " + e.getMessage()); + } + return elem; + } +} Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/property/ValuesProperty.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/webdav/jcr/search/SearchResourceImpl.java =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/search/SearchResourceImpl.java (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/search/SearchResourceImpl.java (working copy) @@ -0,0 +1,403 @@ +/* + * 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.webdav.jcr.search; + +import org.apache.jackrabbit.JcrConstants; +import org.apache.jackrabbit.webdav.DavException; +import org.apache.jackrabbit.webdav.DavResourceLocator; +import org.apache.jackrabbit.webdav.DavServletResponse; +import org.apache.jackrabbit.webdav.MultiStatus; +import org.apache.jackrabbit.webdav.MultiStatusResponse; +import org.apache.jackrabbit.webdav.jcr.ItemResourceConstants; +import org.apache.jackrabbit.webdav.jcr.JcrDavException; +import org.apache.jackrabbit.webdav.jcr.JcrDavSession; +import org.apache.jackrabbit.webdav.search.QueryGrammerSet; +import org.apache.jackrabbit.webdav.search.SearchInfo; +import org.apache.jackrabbit.webdav.search.SearchResource; +import org.apache.jackrabbit.webdav.xml.Namespace; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.apache.jackrabbit.util.ISO9075; + +import javax.jcr.Node; +import javax.jcr.RepositoryException; +import javax.jcr.Session; +import javax.jcr.Value; +import javax.jcr.NamespaceRegistry; +import javax.jcr.ValueFactory; +import javax.jcr.PropertyType; +import javax.jcr.query.InvalidQueryException; +import javax.jcr.query.Query; +import javax.jcr.query.QueryManager; +import javax.jcr.query.QueryResult; +import javax.jcr.query.Row; +import javax.jcr.query.RowIterator; + +import java.util.Map; +import java.util.List; +import java.util.ArrayList; + +/** + * SearchResourceImpl... + */ +public class SearchResourceImpl implements SearchResource { + + private static Logger log = LoggerFactory.getLogger(SearchResourceImpl.class); + + private final JcrDavSession session; + private final DavResourceLocator locator; + + public SearchResourceImpl(DavResourceLocator locator, JcrDavSession session) { + this.session = session; + this.locator = locator; + } + + //-------------------------------------------< SearchResource interface >--- + /** + * @see SearchResource#getQueryGrammerSet() + */ + public QueryGrammerSet getQueryGrammerSet() { + QueryGrammerSet qgs = new QueryGrammerSet(); + try { + QueryManager qMgr = getRepositorySession().getWorkspace().getQueryManager(); + String[] langs = qMgr.getSupportedQueryLanguages(); + for (String lang : langs) { + // Note: Existing clients already assume that the + // query languages returned in the DASL header are + // not prefixed with any namespace, so we probably + // shouldn't use an explicit namespace here. + qgs.addQueryLanguage(lang, Namespace.EMPTY_NAMESPACE); + } + } catch (RepositoryException e) { + log.debug(e.getMessage()); + } + return qgs; + } + + /** + * Execute the query defined by the given sInfo. + * + * @see SearchResource#search(org.apache.jackrabbit.webdav.search.SearchInfo) + */ + public MultiStatus search(SearchInfo sInfo) throws DavException { + try { + QueryResult result = getQuery(sInfo).execute(); + + MultiStatus ms = new MultiStatus(); + + if (ItemResourceConstants.NAMESPACE.equals( + sInfo.getLanguageNameSpace())) { + ms.setResponseDescription( + "Columns: " + encode(result.getColumnNames()) + + "\nSelectors: " + encode(result.getSelectorNames())); + } else { + ms.setResponseDescription(encode(result.getColumnNames())); + } + + queryResultToMultiStatus(result, ms); + + return ms; + } catch (RepositoryException e) { + throw new JcrDavException(e); + } + } + + /** + * Create a query from the information present in the sInfo + * object.
The following JCR specific logic is applied: + *
    + *
  • If the requested resource represents a node with nodetype nt:query, the + * request body is ignored and the query defined with the node is executed + * instead.
  • + *
  • If the requested resource does not represent an existing item, the + * specified query is persisted by calling {@link Query#storeAsNode(String)}.
  • + *
+ * @param sInfo defining the query to be executed + * @return Query object. + * @throws javax.jcr.query.InvalidQueryException if the query defined by sInfo is invalid + * @throws RepositoryException the query manager cannot be accessed or if + * another error occurs. + * @throws DavException if sInfo is null and + * the underlying repository item is not an nt:query node or if an error + * occurs when calling {@link Query#storeAsNode(String)}/ + */ + private Query getQuery(SearchInfo sInfo) + throws InvalidQueryException, RepositoryException, DavException { + + Session session = getRepositorySession(); + NamespaceRegistry nsReg = session.getWorkspace().getNamespaceRegistry(); + Node rootNode = session.getRootNode(); + QueryManager qMgr = getRepositorySession().getWorkspace().getQueryManager(); + + // test if query is defined by requested repository node + String itemPath = locator.getRepositoryPath(); + if (itemPath != null && !rootNode.getPath().equals(itemPath)) { + String qNodeRelPath = itemPath.substring(1); + if (rootNode.hasNode(qNodeRelPath)) { + Node qNode = rootNode.getNode(qNodeRelPath); + if (qNode.isNodeType(JcrConstants.NT_QUERY)) { + return qMgr.getQuery(qNode); + } + } + } + + Query q; + if (sInfo != null) { + // apply namespace mappings to session + Map namespaces = sInfo.getNamespaces(); + try { + for (Map.Entry entry : namespaces.entrySet()) { + String prefix = entry.getKey(); + String uri = entry.getValue(); + session.setNamespacePrefix(prefix, uri); + } + q = qMgr.createQuery(sInfo.getQuery(), sInfo.getLanguageName()); + + if (SearchInfo.NRESULTS_UNDEFINED != sInfo.getNumberResults()) { + q.setLimit(sInfo.getNumberResults()); + } + if (SearchInfo.OFFSET_UNDEFINED != sInfo.getOffset()) { + q.setOffset(sInfo.getOffset()); + } + } finally { + // reset namespace mappings + for (String uri : namespaces.values()) { + try { + session.setNamespacePrefix(nsReg.getPrefix(uri), uri); + } catch (RepositoryException e) { + log.warn("Unable to reset mapping of namespace: " + uri); + } + } + } + } else { + throw new DavException(DavServletResponse.SC_BAD_REQUEST, locator.getResourcePath() + " is not a nt:query node -> searchRequest body required."); + } + + /* test if resource path does not exist -> thus indicating that + the query must be made persistent by calling Query.save(String) */ + if (itemPath != null && !getRepositorySession().itemExists(itemPath)) { + try { + q.storeAsNode(itemPath); + } catch (RepositoryException e) { + // ItemExistsException should never occur. + throw new JcrDavException(e); + } + } + return q; + } + + /** + * Build a MultiStatus object from the specified query result. + * + * @param query the query to execute. + * @return MultiStatus object listing the query result in + * Webdav compatible form. + * @throws RepositoryException if an error occurs. + */ + private void queryResultToMultiStatus(QueryResult result, MultiStatus ms) + throws RepositoryException { + List columnNames = new ArrayList(); + + ValueFactory vf = getRepositorySession().getValueFactory(); + List descr = new ArrayList(); + for (String columnName : result.getColumnNames()) { + if (!isPathOrScore(columnName)) { + columnNames.add(columnName); + descr.add(new PlainValue(columnName, null, vf)); + } + } + + // add path and score for each selector + String[] sns = result.getSelectorNames(); + boolean join = sns.length > 1; + for (String selectorName : sns) { + descr.add(new PathValue(JcrConstants.JCR_PATH, selectorName, vf)); + columnNames.add(JcrConstants.JCR_PATH); + descr.add(new ScoreValue(JcrConstants.JCR_SCORE, selectorName, vf)); + columnNames.add(JcrConstants.JCR_SCORE); + } + + int n = 0; + String root = getHref("/"); + String[] selectorNames = createSelectorNames(descr); + String[] colNames = columnNames.toArray(new String[columnNames.size()]); + RowIterator rowIter = result.getRows(); + while (rowIter.hasNext()) { + Row row = rowIter.nextRow(); + List values = new ArrayList(); + for (RowValue rv : descr) { + values.add(rv.getValue(row)); + } + + // create a new ms-response for this row of the result set + String href; + if (join) { + // We need a distinct href for each join result row to + // allow the MultiStatus response to keep them separate + href = root + "?" + n++; + } else { + href = getHref(row.getPath()); + } + MultiStatusResponse resp = new MultiStatusResponse(href, null); + + // build the s-r-property + SearchResultProperty srp = new SearchResultProperty(colNames, + selectorNames, values.toArray(new Value[values.size()])); + resp.add(srp); + ms.addResponse(resp); + } + } + + /** + * Returns the resource location of the given query result row. + * The result rows of join queries have no meaningful single resource + * location, so we'll just default to the root node for all such rows. + * + * @param row query result row + * @param join flag to indicate a join query + * @return resource location of the row + */ + private String getHref(String path) throws RepositoryException { + DavResourceLocator l = locator.getFactory().createResourceLocator( + locator.getPrefix(), locator.getWorkspacePath(), path, false); + return l.getHref(true); + } + + private String encode(String[] names) { + StringBuilder builder = new StringBuilder(); + String delim = ""; + for (String name : names) { + builder.append(delim); + builder.append(ISO9075.encode(name)); + delim = " "; + } + return builder.toString(); + } + + private static String[] createSelectorNames(Iterable rows) + throws RepositoryException { + List sn = new ArrayList(); + for (RowValue rv : rows) { + sn.add(rv.getSelectorName()); + } + return sn.toArray(new String[sn.size()]); + } + + /** + * @param columnName a column name. + * @return true if columnName is either + * jcr:path or jcr:score; + * false otherwise. + */ + private static boolean isPathOrScore(String columnName) { + return JcrConstants.JCR_PATH.equals(columnName) + || JcrConstants.JCR_SCORE.equals(columnName); + } + + /** + * @return the session associated with this resource. + */ + private Session getRepositorySession() { + return session.getRepositorySession(); + } + + private interface RowValue { + + public Value getValue(Row row) throws RepositoryException; + + public String getColumnName() throws RepositoryException; + + public String getSelectorName() throws RepositoryException; + } + + private static final class PlainValue extends SelectorValue { + + public PlainValue(String columnName, + String selectorName, + ValueFactory vf) { + super(columnName, selectorName, vf); + } + + public Value getValue(Row row) throws RepositoryException { + return row.getValue(columnName); + } + } + + private static abstract class SelectorValue implements RowValue { + + protected final String columnName; + + protected final String selectorName; + + protected final ValueFactory vf; + + public SelectorValue(String columnName, + String selectorName, + ValueFactory vf) { + this.columnName = columnName; + this.selectorName = selectorName; + this.vf = vf; + } + + public String getColumnName() throws RepositoryException { + return columnName; + } + + public String getSelectorName() throws RepositoryException { + return selectorName; + } + } + + private static final class ScoreValue extends SelectorValue { + + public ScoreValue(String columnName, + String selectorName, + ValueFactory vf) { + super(columnName, selectorName, vf); + } + + public Value getValue(Row row) throws RepositoryException { + double score; + if (selectorName != null) { + score = row.getScore(selectorName); + } else { + score = row.getScore(); + } + return vf.createValue(score); + } + } + + private static final class PathValue extends SelectorValue { + + public PathValue(String columnName, + String selectorName, + ValueFactory vf) { + super(columnName, selectorName, vf); + } + + public Value getValue(Row row) throws RepositoryException { + String path; + if (selectorName != null) { + path = row.getPath(selectorName); + } else { + path = row.getPath(); + } + return (path == null) ? null : vf.createValue(path, PropertyType.PATH); + } + } + +} \ No newline at end of file Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/search/SearchResourceImpl.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/webdav/jcr/search/SearchResultProperty.java =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/search/SearchResultProperty.java (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/search/SearchResultProperty.java (working copy) @@ -0,0 +1,201 @@ +/* + * 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.webdav.jcr.search; + +import org.apache.jackrabbit.commons.webdav.QueryUtil; +import org.apache.jackrabbit.value.ValueHelper; +import org.apache.jackrabbit.webdav.jcr.ItemResourceConstants; +import org.apache.jackrabbit.webdav.property.AbstractDavProperty; +import org.apache.jackrabbit.webdav.property.DavProperty; +import org.apache.jackrabbit.webdav.property.DavPropertyName; +import org.apache.jackrabbit.webdav.xml.DomUtil; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +import javax.jcr.PropertyType; +import javax.jcr.RepositoryException; +import javax.jcr.Value; +import javax.jcr.ValueFactory; +import java.util.ArrayList; +import java.util.List; + +/** + * SearchResultProperty... + */ +// todo: find proper solution for transporting search results... +public class SearchResultProperty extends AbstractDavProperty implements ItemResourceConstants { + + private static Logger log = LoggerFactory.getLogger(SearchResultProperty.class); + + private static final DavPropertyName SEARCH_RESULT_PROPERTY = DavPropertyName.create(JCR_QUERY_RESULT_LN, ItemResourceConstants.NAMESPACE); + + private final String[] columnNames; + private final String[] selectorNames; + private final Value[] values; + + /** + * Creates a new SearchResultProperty. + * + * @param columnNames the column names of the search row represented by + * this dav property. + * @param selectorNames the selector names of the row represented by this + * dav property. + * @param values the values present in the columns + */ + public SearchResultProperty(String[] columnNames, + String[] selectorNames, + Value[] values) { + super(SEARCH_RESULT_PROPERTY, true); + this.columnNames = columnNames; + this.selectorNames = selectorNames; + this.values = values; + } + + /** + * Wrap the specified DavProperty in a new SearchResultProperty. + * + * @param property + * @param valueFactory factory used to deserialize the xml value to a JCR value. + * @throws RepositoryException if an error occurs while build the property value + * @throws IllegalArgumentException if the specified property does have the + * required form. + * @see #getValues() + */ + public SearchResultProperty(DavProperty property, ValueFactory valueFactory) throws RepositoryException { + super(property.getName(), true); + if (!SEARCH_RESULT_PROPERTY.equals(getName())) { + throw new IllegalArgumentException("SearchResultProperty may only be created from a property named " + SEARCH_RESULT_PROPERTY.toString()); + } + + List colList = new ArrayList(); + List selList = new ArrayList(); + List valList = new ArrayList(); + + QueryUtil.parseResultPropertyValue(property.getValue(), colList, selList, valList, valueFactory); + + columnNames = colList.toArray(new String[colList.size()]); + selectorNames = selList.toArray(new String[selList.size()]); + values = valList.toArray(new Value[valList.size()]); + } + + /** + * Return the column names representing the names of the properties present + * in the {@link #getValues() values}. + * + * @return columnNames + */ + public String[] getColumnNames() { + return columnNames; + } + + /** + * @return the selector name for each of the columns in the result property. + */ + public String[] getSelectorNames() { + return selectorNames; + } + + /** + * Return the values representing the values of that row in the search + * result table. + * + * @return values + * @see javax.jcr.query.Row#getValues() + */ + public Value[] getValues() { + return values; + } + + + /** + * Same as {@link #getValues()} + * + * @return Array of JCR Value object + */ + public Value[] getValue() { + return values; + } + + /** + * Return the xml representation of this webdav property. For every value in + * the query result row a dcr:name, dcr:value, dcr:type and an optional + * dcr:selectorName element is created. + * Example: + *
+     * -----------------------------------------------------------
+     *   col-name  |   bla   |   bli   |  jcr:path  |  jcr:score
+     * -----------------------------------------------------------
+     *   value     |   xxx   |   111   |  /aNode    |    1
+     *   type      |    1    |    3    |     8      |    3
+     *   sel-name  |         |         |     S      |    S
+     * -----------------------------------------------------------
+     * 
+ * results in: + *
+     * <dcr:search-result-property xmlns:dcr="http://www.day.com/jcr/webdav/1.0">
+     *    <dcr:column>
+     *       <dcr:name>bla<dcr:name/>
+     *       <dcr:value dcr:type="String">xxx<dcr:value/>
+     *    </dcr:column>
+     *    <dcr:column>
+     *       <dcr:name>bli<dcr:name/>
+     *       <dcr:value dcr:type="Long">111<dcr:value/>
+     *    </dcr:column>
+     *    <dcr:column>
+     *       <dcr:name>jcr:path<dcr:name/>
+     *       <dcr:value dcr:type="Path">/aNode<dcr:value/>
+     *       <dcr:selectorName>S<dcr:selectorName/>
+     *    </dcr:column>
+     *    <dcr:column>
+     *       <dcr:name>jcr:score<dcr:name/>
+     *       <dcr:value dcr:type="Long">1<dcr:value/>
+     *       <dcr:selectorName>S<dcr:selectorName/>
+     *    </dcr:column>
+     * </dcr:search-result-property>
+     * 
+ * + * @see org.apache.jackrabbit.webdav.xml.XmlSerializable#toXml(org.w3c.dom.Document) + */ + @Override + public Element toXml(Document document) { + Element elem = getName().toXml(document); + for (int i = 0; i < columnNames.length; i++) { + String propertyName = columnNames[i]; + String selectorName = selectorNames[i]; + Value propertyValue = values[i]; + + Element columnEl = DomUtil.addChildElement(elem, XML_QUERY_RESULT_COLUMN, ItemResourceConstants.NAMESPACE); + DomUtil.addChildElement(columnEl, JCR_NAME.getName(), JCR_NAME.getNamespace(), propertyName); + if (propertyValue != null) { + try { + String serializedValue = ValueHelper.serialize(propertyValue, true); + Element xmlValue = DomUtil.addChildElement(columnEl, XML_VALUE, ItemResourceConstants.NAMESPACE, serializedValue); + String type = PropertyType.nameFromValue(propertyValue.getType()); + DomUtil.setAttribute(xmlValue, ATTR_VALUE_TYPE, ItemResourceConstants.NAMESPACE, type); + } catch (RepositoryException e) { + log.error(e.toString()); + } + } + if (selectorName != null) { + DomUtil.addChildElement(columnEl, JCR_SELECTOR_NAME.getName(), JCR_SELECTOR_NAME.getNamespace(), selectorName); + } + } + return elem; + } +} Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/search/SearchResultProperty.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/webdav/jcr/security/JcrSupportedPrivilegesProperty.java =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/security/JcrSupportedPrivilegesProperty.java (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/security/JcrSupportedPrivilegesProperty.java (working copy) @@ -0,0 +1,122 @@ +/* + * 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.webdav.jcr.security; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import javax.jcr.RepositoryException; +import javax.jcr.Session; +import javax.jcr.security.AccessControlManager; +import javax.jcr.security.Privilege; + +import org.apache.jackrabbit.util.Text; +import org.apache.jackrabbit.webdav.security.SupportedPrivilege; +import org.apache.jackrabbit.webdav.security.SupportedPrivilegeSetProperty; +import org.apache.jackrabbit.webdav.xml.Namespace; + +/** + * JcrSupportedPrivilegesProperty... + */ +public class JcrSupportedPrivilegesProperty { + + private final Session session; + private final String absPath; + private final Set privileges = new HashSet(); + + private final Map supportedPrivileges = new HashMap(); + private final HashSet aggregated = new HashSet(); + + /** + * Build supported privileges for the jcr:all privilege. + * + * @param session The reading session + */ + public JcrSupportedPrivilegesProperty(Session session) throws RepositoryException { + this.session = session; + this.absPath = null; + AccessControlManager acMgr = session.getAccessControlManager(); + Privilege jcrAll = acMgr.privilegeFromName(Privilege.JCR_ALL); + privileges.add(jcrAll); + } + + /** + * @param session The reading session + * @param absPath An absolute path to an existing JCR node or {@code null}. + */ + public JcrSupportedPrivilegesProperty(Session session, String absPath) { + this.session = session; + this.absPath = absPath; + } + + /** + * Calculated the supported privileges at {@code absPath} and build a + * {@link org.apache.jackrabbit.webdav.security.SupportedPrivilegeSetProperty} + * from the result. + * + * @return a new {@code SupportedPrivilegeSetProperty} property. + * @throws RepositoryException + */ + public SupportedPrivilegeSetProperty asDavProperty() throws RepositoryException { + if (privileges.isEmpty()) { + AccessControlManager acMgr = session.getAccessControlManager(); + privileges.addAll(Arrays.asList(acMgr.getSupportedPrivileges(absPath))); + } + for (Privilege p : privileges) { + if (!aggregated.contains(p.getName())) { + createSupportedPrivilege(p); + } + } + return new SupportedPrivilegeSetProperty(supportedPrivileges.values().toArray(new SupportedPrivilege[supportedPrivileges.size()])); + } + + private SupportedPrivilege createSupportedPrivilege(Privilege privilege) throws RepositoryException { + String privilegeName = privilege.getName(); + + String localName = Text.getLocalName(privilegeName); + String prefix = Text.getNamespacePrefix(privilegeName); + Namespace ns = (prefix.isEmpty()) ? Namespace.EMPTY_NAMESPACE : Namespace.getNamespace(prefix, session.getNamespaceURI(prefix)); + org.apache.jackrabbit.webdav.security.Privilege davPrivilege = org.apache.jackrabbit.webdav.security.Privilege.getPrivilege(localName, ns); + + SupportedPrivilege[] aggregates = (privilege.isAggregate()) ? getDeclaredAggregates(privilege) : null; + + SupportedPrivilege sp = new SupportedPrivilege(davPrivilege, null, null, privilege.isAbstract(), aggregates); + if (!aggregated.contains(privilegeName)) { + supportedPrivileges.put(privilegeName, sp); + } + return sp; + } + + private SupportedPrivilege[] getDeclaredAggregates(Privilege privilege) throws RepositoryException { + List declAggr = new ArrayList(); + for (Privilege decl : privilege.getDeclaredAggregatePrivileges()) { + String name = decl.getName(); + if (aggregated.add(name)) { + if (supportedPrivileges.containsKey(name)) { + declAggr.add(supportedPrivileges.remove(name)); + } else { + declAggr.add(createSupportedPrivilege(decl)); + } + } + } + return declAggr.toArray(new SupportedPrivilege[declAggr.size()]); + } +} \ No newline at end of file Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/security/JcrSupportedPrivilegesProperty.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/webdav/jcr/security/JcrUserPrivilegesProperty.java =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/security/JcrUserPrivilegesProperty.java (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/security/JcrUserPrivilegesProperty.java (working copy) @@ -0,0 +1,58 @@ +/* + * 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.webdav.jcr.security; + +import java.util.ArrayList; +import java.util.List; +import javax.jcr.RepositoryException; +import javax.jcr.Session; + +import org.apache.jackrabbit.util.Text; +import org.apache.jackrabbit.webdav.security.CurrentUserPrivilegeSetProperty; +import org.apache.jackrabbit.webdav.security.Privilege; +import org.apache.jackrabbit.webdav.xml.Namespace; + +/** + * JcrPrivilegesProperty... + */ +public class JcrUserPrivilegesProperty { + + private final Session session; + private final String absPath; + + /** + * @param session The reading session + * @param absPath An absolute path to an existing JCR node or {@code null}. + */ + public JcrUserPrivilegesProperty(Session session, String absPath) throws RepositoryException { + this.session = session; + this.absPath = absPath; + } + + public CurrentUserPrivilegeSetProperty asDavProperty() throws RepositoryException { + List davPrivs = new ArrayList(); + for (javax.jcr.security.Privilege privilege : session.getAccessControlManager().getPrivileges(absPath)) { + String privilegeName = privilege.getName(); + + String prefix = Text.getNamespacePrefix(privilegeName); + Namespace ns = (prefix.isEmpty()) ? Namespace.EMPTY_NAMESPACE : Namespace.getNamespace(prefix, session.getNamespaceURI(prefix)); + davPrivs.add(Privilege.getPrivilege(Text.getLocalName(privilegeName), ns)); + } + + return new CurrentUserPrivilegeSetProperty(davPrivs.toArray(new Privilege[davPrivs.size()])); + } +} \ No newline at end of file Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/security/JcrUserPrivilegesProperty.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/webdav/jcr/security/SecurityUtils.java =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/security/SecurityUtils.java (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/security/SecurityUtils.java (working copy) @@ -0,0 +1,30 @@ +/* + * 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.webdav.jcr.security; + +import javax.jcr.Repository; +import javax.jcr.Session; + +public final class SecurityUtils { + + private SecurityUtils() {} + + public static boolean supportsAccessControl(Session session) { + String desc = session.getRepository().getDescriptor(Repository.OPTION_ACCESS_CONTROL_SUPPORTED); + return Boolean.valueOf(desc); + } +} \ No newline at end of file Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/security/SecurityUtils.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/webdav/jcr/transaction/TransactionListener.java =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/transaction/TransactionListener.java (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/transaction/TransactionListener.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.webdav.jcr.transaction; + +import org.apache.jackrabbit.webdav.transaction.TransactionResource; + +/** + * TransactionListener provides callbacks when a transaction + * is committed. + */ +public interface TransactionListener { + + /** + * This method is called right before a transaction is committed. + * + * @param resource the transaction resource which will be committed. + * @param lockToken the lock token + */ + public void beforeCommit(TransactionResource resource, String lockToken); + + /** + * This method is called after the commit has been executed. + * + * @param resource the transaction resource which had been committed. + * @param lockToken the lock token. + * @param success if the commit was successful. + */ + public void afterCommit(TransactionResource resource, String lockToken, boolean success); +} Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/transaction/TransactionListener.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/webdav/jcr/transaction/TxLockManagerImpl.java =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/transaction/TxLockManagerImpl.java (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/transaction/TxLockManagerImpl.java (working copy) @@ -0,0 +1,796 @@ +/* + * 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.webdav.jcr.transaction; + +import org.apache.jackrabbit.util.Text; +import org.apache.jackrabbit.webdav.DavConstants; +import org.apache.jackrabbit.webdav.DavException; +import org.apache.jackrabbit.webdav.DavResource; +import org.apache.jackrabbit.webdav.DavResourceLocator; +import org.apache.jackrabbit.webdav.DavServletResponse; +import org.apache.jackrabbit.webdav.WebdavResponse; +import org.apache.jackrabbit.webdav.jcr.JcrDavException; +import org.apache.jackrabbit.webdav.jcr.JcrDavSession; +import org.apache.jackrabbit.webdav.lock.ActiveLock; +import org.apache.jackrabbit.webdav.lock.LockInfo; +import org.apache.jackrabbit.webdav.lock.LockManager; +import org.apache.jackrabbit.webdav.lock.Scope; +import org.apache.jackrabbit.webdav.lock.Type; +import org.apache.jackrabbit.webdav.transaction.TransactionConstants; +import org.apache.jackrabbit.webdav.transaction.TransactionInfo; +import org.apache.jackrabbit.webdav.transaction.TransactionResource; +import org.apache.jackrabbit.webdav.transaction.TxActiveLock; +import org.apache.jackrabbit.webdav.transaction.TxLockManager; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.jcr.Item; +import javax.jcr.PathNotFoundException; +import javax.jcr.RepositoryException; +import javax.jcr.Session; +import javax.transaction.xa.XAException; +import javax.transaction.xa.XAResource; +import javax.transaction.xa.Xid; +import java.util.HashMap; +import java.util.Iterator; +import java.util.IdentityHashMap; +import java.util.Map; + +/** + * TxLockManagerImpl manages locks with locktype + * '{@link TransactionConstants#TRANSACTION dcr:transaction}'. + *

+ */ + //todo: removing all expired locks + //todo: 'local' and 'global' are not accurate terms in the given context > replace + /*todo: the usage of the 'global' transaction is not according to the JTA specification, + which explicitly requires any transaction present on a servlet to be completed before + the service method returns. Starting/completing transactions on the session object, + which is possible with the jackrabbit implementation is a hack.*/ + /*todo: review of this transaction part is therefore required. Is there a use-case + for those 'global' transactions at all...*/ +public class TxLockManagerImpl implements TxLockManager { + + private static Logger log = LoggerFactory.getLogger(TxLockManagerImpl.class); + + private final TransactionMap map = new TransactionMap(); + + private final Map listeners = new IdentityHashMap(); + + /** + * Create a new lock. + * + * @param lockInfo as present in the request body. + * @param resource + * @return the lock + * @throws DavException if the lock could not be obtained. + * @throws IllegalArgumentException if the resource is null or + * does not implement {@link TransactionResource} interface. + * @see LockManager#createLock(org.apache.jackrabbit.webdav.lock.LockInfo, org.apache.jackrabbit.webdav.DavResource) + */ + public ActiveLock createLock(LockInfo lockInfo, DavResource resource) + throws DavException { + if (resource == null || !(resource instanceof TransactionResource)) { + throw new IllegalArgumentException("Invalid resource"); + } + return createLock(lockInfo, (TransactionResource) resource); + } + + /** + * Create a new lock. + * + * @param lockInfo + * @param resource + * @return the lock + * @throws DavException if the request lock has the wrong lock type or if + * the lock could not be obtained for any reason. + */ + private synchronized ActiveLock createLock(LockInfo lockInfo, TransactionResource resource) + throws DavException { + if (!lockInfo.isDeep() || !TransactionConstants.TRANSACTION.equals(lockInfo.getType())) { + throw new DavException(DavServletResponse.SC_PRECONDITION_FAILED); + } + + ActiveLock existing = getLock(lockInfo.getType(), lockInfo.getScope(), resource); + if (existing != null) { + throw new DavException(DavServletResponse.SC_LOCKED); + } + // TODO: check for locks on member resources is required as well for lock is always deep! + + Transaction tx = createTransaction(resource.getLocator(), lockInfo); + tx.start(resource); + + // keep references to this lock + addReferences(tx, getMap(resource), resource); + + return tx.getLock(); + } + + /** + * Build the transaction object associated by the lock. + * + * @param locator + * @param lockInfo + * @return + */ + private Transaction createTransaction(DavResourceLocator locator, LockInfo lockInfo) { + if (TransactionConstants.GLOBAL.equals(lockInfo.getScope())) { + return new GlobalTransaction(locator, new TxActiveLock(lockInfo)); + } else { + return new LocalTransaction(locator, new TxActiveLock(lockInfo)); + } + } + + /** + * Refresh the lock identified by the given lock token. + * + * @param lockInfo + * @param lockToken + * @param resource + * @return the lock + * @throws DavException + * @throws IllegalArgumentException if the resource is null or + * does not implement {@link TransactionResource} interface. + * @see LockManager#refreshLock(org.apache.jackrabbit.webdav.lock.LockInfo, String, org.apache.jackrabbit.webdav.DavResource) + */ + public ActiveLock refreshLock(LockInfo lockInfo, String lockToken, + DavResource resource) throws DavException { + if (resource == null || !(resource instanceof TransactionResource)) { + throw new IllegalArgumentException("Invalid resource"); + } + return refreshLock(lockInfo, lockToken, (TransactionResource) resource); + } + + /** + * Reset the timeout of the lock identified by the given lock token. + * + * @param lockInfo + * @param lockToken + * @param resource + * @return + * @throws DavException if the lock did not exist or is expired. + */ + private synchronized ActiveLock refreshLock(LockInfo lockInfo, String lockToken, + TransactionResource resource) throws DavException { + + TransactionMap responsibleMap = getMap(resource); + Transaction tx = responsibleMap.get(lockToken); + if (tx == null) { + throw new DavException(DavServletResponse.SC_PRECONDITION_FAILED, "No valid transaction lock found for resource '" + resource.getResourcePath() + "'"); + } else if (tx.getLock().isExpired()) { + removeExpired(tx, responsibleMap, resource); + throw new DavException(DavServletResponse.SC_PRECONDITION_FAILED, "Transaction lock for resource '" + resource.getResourcePath() + "' was already expired."); + } else { + tx.getLock().setTimeout(lockInfo.getTimeout()); + } + return tx.getLock(); + } + + /** + * Throws UnsupportedOperationException. + * + * @param lockToken + * @param resource + * @throws DavException + * @see LockManager#releaseLock(String, org.apache.jackrabbit.webdav.DavResource) + */ + public void releaseLock(String lockToken, DavResource resource) + throws DavException { + throw new UnsupportedOperationException("A transaction lock can only be release with a TransactionInfo object and a lock token."); + } + + /** + * Release the lock identified by the given lock token. + * + * @param lockInfo + * @param lockToken + * @param resource + * @throws DavException + */ + public synchronized void releaseLock(TransactionInfo lockInfo, String lockToken, + TransactionResource resource) throws DavException { + if (resource == null) { + throw new IllegalArgumentException("Resource must not be null."); + } + TransactionMap responsibleMap = getMap(resource); + Transaction tx = responsibleMap.get(lockToken); + + if (tx == null) { + throw new DavException(DavServletResponse.SC_PRECONDITION_FAILED, "No transaction lock found for resource '" + resource.getResourcePath() + "'"); + } else if (tx.getLock().isExpired()) { + removeExpired(tx, responsibleMap, resource); + throw new DavException(DavServletResponse.SC_PRECONDITION_FAILED, "Transaction lock for resource '" + resource.getResourcePath() + "' was already expired."); + } else { + if (lockInfo.isCommit()) { + TransactionListener[] txListeners; + synchronized (listeners) { + txListeners = listeners.values().toArray(new TransactionListener[listeners.values().size()]); + } + for (TransactionListener txListener : txListeners) { + txListener.beforeCommit(resource, lockToken); + } + DavException ex = null; + try { + tx.commit(resource); + } catch (DavException e) { + ex = e; + } + for (TransactionListener txListener : txListeners) { + txListener.afterCommit(resource, lockToken, ex == null); + } + if (ex != null) { + throw ex; + } + } else { + tx.rollback(resource); + } + removeReferences(tx, responsibleMap, resource); + } + } + + /** + * Always returns null + * + * @param type + * @param scope + * @param resource + * @return null + * @see #getLock(Type, Scope, TransactionResource) + * @see LockManager#getLock(org.apache.jackrabbit.webdav.lock.Type, org.apache.jackrabbit.webdav.lock.Scope, org.apache.jackrabbit.webdav.DavResource) + */ + public ActiveLock getLock(Type type, Scope scope, DavResource resource) { + return null; + } + + /** + * Returns true if the given lock token belongs to a lock that applies to + * the given resource, false otherwise. The token may either be retrieved + * from the {@link DavConstants#HEADER_LOCK_TOKEN Lock-Token header} or + * from the {@link TransactionConstants#HEADER_TRANSACTIONID TransactionId header}. + * + * @param token + * @param resource + * @return + * @see LockManager#hasLock(String token, DavResource resource) + */ + public boolean hasLock(String token, DavResource resource) { + return getLock(token, null, resource) != null; + } + + /** + * Return the lock applied to the given resource or null + * + * @param type + * @param scope + * @param resource + * @return lock applied to the given resource or null + * @see LockManager#getLock(Type, Scope, DavResource) + * todo: is it correct to return one that specific lock, the current session is token-holder of? + */ + public ActiveLock getLock(Type type, Scope scope, TransactionResource resource) { + ActiveLock lock = null; + if (TransactionConstants.TRANSACTION.equals(type)) { + String[] sessionTokens = resource.getSession().getLockTokens(); + int i = 0; + while (lock == null && i < sessionTokens.length) { + String lockToken = sessionTokens[i]; + lock = getLock(lockToken, scope, resource); + i++; + } + } + return lock; + } + + //-----------------------------< listener support >------------------------- + + /** + * Adds a transaction listener to this TxLockManager. + * @param listener the listener to add. + */ + public void addTransactionListener(TransactionListener listener) { + synchronized (listeners) { + listeners.put(listener, listener); + } + } + + /** + * Removes a transaction listener from this TxLockManager. + * @param listener the listener to remove. + */ + public void removeTransactionListener(TransactionListener listener) { + synchronized (listeners) { + listeners.remove(listener); + } + } + + /** + * @param lockToken + * @param resource + * @return + */ + private ActiveLock getLock(String lockToken, Scope scope, DavResource resource) { + if (!(resource instanceof TransactionResource)) { + log.warn("TransactionResource expected"); + return null; + } + + ActiveLock lock = null; + Transaction tx = null; + TransactionMap m = map; + // check if main-map contains that txId + if (m.containsKey(lockToken)) { + tx = m.get(lockToken); + } else { + // look through all the nested tx-maps (i.e. global txs) for the given txId + Iterator it = m.values().iterator(); + while (it.hasNext() && tx == null) { + Transaction txMap = it.next(); + if (!txMap.isLocal()) { + m = (TransactionMap) txMap; + if (m.containsKey(lockToken)) { + tx = ((TransactionMap) txMap).get(lockToken); + } + } + } + } + + if (tx != null) { + if (tx.getLock().isExpired()) { + removeExpired(tx, m, (TransactionResource) resource); + } else if (tx.appliesToResource(resource) && (scope == null || tx.getLock().getScope().equals(scope))) { + lock = tx.getLock(); + } + } + return lock; + } + + /** + * Return the map that may contain a transaction lock for the given resource. + * In case the resource provides a transactionId, the map must be a + * repository transaction that is identified by the given id and which in + * turn can act as map. + * + * @param resource + * @return responsible map. + * @throws DavException if no map could be retrieved. + */ + private TransactionMap getMap(TransactionResource resource) + throws DavException { + + String txKey = resource.getTransactionId(); + if (txKey == null) { + return map; + } else { + if (!map.containsKey(txKey)) { + throw new DavException(DavServletResponse.SC_PRECONDITION_FAILED, "Transaction map '" + map + " does not contain a transaction with TransactionId '" + txKey + "'."); + } + Transaction tx = map.get(txKey); + if (tx.isLocal()) { + throw new DavException(DavServletResponse.SC_PRECONDITION_FAILED, "TransactionId '" + txKey + "' points to a local transaction, that cannot act as transaction map"); + } else if (tx.getLock() != null && tx.getLock().isExpired()) { + removeExpired(tx, map, resource); + throw new DavException(DavServletResponse.SC_PRECONDITION_FAILED, "Attempt to retrieve an expired global transaction."); + } + // tx is a global transaction that acts as map as well. + return (TransactionMap) tx; + } + } + + /** + * Rollbacks the specified transaction and releases the lock. This includes + * the removal of all references. + * + * @param tx + * @param responsibleMap + * @param resource + */ + private static void removeExpired(Transaction tx, TransactionMap responsibleMap, + TransactionResource resource) { + log.debug("Removing expired transaction lock " + tx); + try { + tx.rollback(resource); + removeReferences(tx, responsibleMap, resource); + } catch (DavException e) { + log.error("Error while removing expired transaction lock: " + e.getMessage()); + } + } + + /** + * Create the required references to the new transaction specified by tx. + * + * @param tx + * @param responsibleMap + * @param resource + * @throws DavException + */ + private static void addReferences(Transaction tx, TransactionMap responsibleMap, + TransactionResource resource) { + log.debug("Adding transactionId '" + tx.getId() + "' as session lock token."); + resource.getSession().addLockToken(tx.getId()); + + responsibleMap.put(tx.getId(), tx); + resource.getSession().addReference(tx.getId()); + } + + /** + * Remove all references to the specified transaction. + * + * @param tx + * @param responsibleMap + * @param resource + */ + private static void removeReferences(Transaction tx, TransactionMap responsibleMap, + TransactionResource resource) { + log.debug("Removing transactionId '" + tx.getId() + "' from session lock tokens."); + resource.getSession().removeLockToken(tx.getId()); + + responsibleMap.remove(tx.getId()); + resource.getSession().removeReference(tx.getId()); + } + + /** + * @param resource + * @return JCR session + */ + private static Session getRepositorySession(TransactionResource resource) throws DavException { + return JcrDavSession.getRepositorySession(resource.getSession()); + } + + //------------------------------------------< inner classes, interfaces >--- + /** + * Internal Transaction interface + */ + private interface Transaction { + + TxActiveLock getLock(); + + /** + * @return the id of this transaction. + */ + String getId(); + + /** + * @return path of the lock holding resource + */ + String getResourcePath(); + + /** + * @param resource + * @return true if the lock defined by this transaction applies to the + * given resource, either due to the resource holding that lock or due + * to a deep lock hold by any ancestor resource. + */ + boolean appliesToResource(DavResource resource); + + /** + * @return true if this transaction is used to allow for transient changes + * on the underlying repository, that may be persisted with the final + * UNLOCK request only. + */ + boolean isLocal(); + + /** + * Start this transaction. + * + * @param resource + * @throws DavException if an error occurs. + */ + void start(TransactionResource resource) throws DavException; + + /** + * Commit this transaction + * + * @param resource + * @throws DavException if an error occurs. + */ + void commit(TransactionResource resource) throws DavException; + + /** + * Rollback this transaction. + * + * @param resource + * @throws DavException if an error occurs. + */ + void rollback(TransactionResource resource) throws DavException; + } + + /** + * Abstract transaction covering functionally to both implementations. + */ + private abstract static class AbstractTransaction extends TransactionMap implements Transaction { + + private final DavResourceLocator locator; + private final TxActiveLock lock; + + private AbstractTransaction(DavResourceLocator locator, TxActiveLock lock) { + this.locator = locator; + this.lock = lock; + } + + //----------------------------------------------------< Transaction >--- + /** + * @see #getLock() + */ + public TxActiveLock getLock() { + return lock; + } + + /** + * @see #getId() + */ + public String getId() { + return lock.getToken(); + } + + /** + * @see #getResourcePath() + */ + public String getResourcePath() { + return locator.getResourcePath(); + } + + /** + * @see #appliesToResource(DavResource) + */ + public boolean appliesToResource(DavResource resource) { + if (locator.isSameWorkspace(resource.getLocator())) { + String lockResourcePath = getResourcePath(); + String resPath = resource.getResourcePath(); + + while (!"".equals(resPath)) { + if (lockResourcePath.equals(resPath)) { + return true; + } + resPath = Text.getRelativeParent(resPath, 1); + } + } + return false; + } + } + + /** + * Local transaction + */ + private final static class LocalTransaction extends AbstractTransaction { + + private LocalTransaction(DavResourceLocator locator, TxActiveLock lock) { + super(locator, lock); + } + + //----------------------------------------------------< Transaction >--- + /** + * @see org.apache.jackrabbit.webdav.jcr.transaction.TxLockManagerImpl.Transaction#isLocal() + */ + public boolean isLocal() { + return true; + } + + /** + * @see org.apache.jackrabbit.webdav.jcr.transaction.TxLockManagerImpl.Transaction#start(TransactionResource) + */ + public void start(TransactionResource resource) throws DavException { + try { + // make sure, the given resource represents an existing repository item + if (!getRepositorySession(resource).itemExists(resource.getLocator().getRepositoryPath())) { + throw new DavException(DavServletResponse.SC_CONFLICT, "Unable to start local transaction: no repository item present at " + getResourcePath()); + } + } catch (RepositoryException e) { + log.error("Unexpected error: " + e.getMessage()); + throw new JcrDavException(e); + } + } + + /** + * @see org.apache.jackrabbit.webdav.jcr.transaction.TxLockManagerImpl.Transaction#commit(TransactionResource) + */ + public void commit(TransactionResource resource) throws DavException { + try { + getItem(resource).save(); + } catch (RepositoryException e) { + throw new JcrDavException(e); + } + } + + /** + * @see org.apache.jackrabbit.webdav.jcr.transaction.TxLockManagerImpl.Transaction#rollback(TransactionResource) + */ + public void rollback(TransactionResource resource) throws DavException { + try { + getItem(resource).refresh(false); + } catch (RepositoryException e) { + throw new JcrDavException(e); + } + } + + //-------------------------------------------------< TransactionMap >--- + /** + * Always throws DavException. + * + * @see TransactionMap#putTransaction(String, org.apache.jackrabbit.webdav.jcr.transaction.TxLockManagerImpl.Transaction) + */ + @Override + public Transaction putTransaction(String key, Transaction value) throws DavException { + throw new DavException(WebdavResponse.SC_PRECONDITION_FAILED, "Attempt to nest a new transaction into a local one."); + } + + //--------------------------------------------------------< private >--- + /** + * Retrieve the repository item from the given transaction resource. + * + * @param resource + * @return + * @throws PathNotFoundException + * @throws RepositoryException + * @throws DavException + */ + private Item getItem(TransactionResource resource) throws PathNotFoundException, RepositoryException, DavException { + String itemPath = resource.getLocator().getRepositoryPath(); + return getRepositorySession(resource).getItem(itemPath); + } + } + + /** + * Global transaction + */ + private static class GlobalTransaction extends AbstractTransaction { + + private Xid xid; + + private GlobalTransaction(DavResourceLocator locator, TxActiveLock lock) { + super(locator, lock); + xid = new XidImpl(lock.getToken()); + } + + //----------------------------------------------------< Transaction >--- + /** + * @see org.apache.jackrabbit.webdav.jcr.transaction.TxLockManagerImpl.Transaction#isLocal() + */ + public boolean isLocal() { + return false; + } + + /** + * @see org.apache.jackrabbit.webdav.jcr.transaction.TxLockManagerImpl.Transaction#start(TransactionResource) + */ + public void start(TransactionResource resource) throws DavException { + XAResource xaRes = getXAResource(resource); + try { + xaRes.setTransactionTimeout((int) getLock().getTimeout() / 1000); + xaRes.start(xid, XAResource.TMNOFLAGS); + } catch (XAException e) { + throw new DavException(DavServletResponse.SC_FORBIDDEN, e.getMessage()); + } + } + + /** + * @see org.apache.jackrabbit.webdav.jcr.transaction.TxLockManagerImpl.Transaction#commit(TransactionResource) + */ + public void commit(TransactionResource resource) throws DavException { + XAResource xaRes = getXAResource(resource); + try { + xaRes.commit(xid, false); + removeLocalTxReferences(resource); + } catch (XAException e) { + throw new DavException(DavServletResponse.SC_FORBIDDEN, e.getMessage()); + } + } + + /** + * @see org.apache.jackrabbit.webdav.jcr.transaction.TxLockManagerImpl.Transaction#rollback(TransactionResource) + */ + public void rollback(TransactionResource resource) throws DavException { + XAResource xaRes = getXAResource(resource); + try { + xaRes.rollback(xid); + removeLocalTxReferences(resource); + } catch (XAException e) { + throw new DavException(DavServletResponse.SC_FORBIDDEN, e.getMessage()); + } + } + + //-------------------------------------------------< TransactionMap >--- + @Override + public Transaction putTransaction(String key, Transaction value) throws DavException { + if (!(value instanceof LocalTransaction)) { + throw new DavException(WebdavResponse.SC_PRECONDITION_FAILED, "Attempt to nest global transaction into a global one."); + } + return super.put(key, value); + } + + //--------------------------------------------------------< private >--- + private XAResource getXAResource(TransactionResource resource) throws DavException { + /* + // commented, since server should be jackrabbit independent + Session session = resource.getSession().getRepositorySession(); + if (session instanceof XASession) { + return ((XASession)session).getXAResource(); + } else { + throw new DavException(DavServletResponse.SC_FORBIDDEN); + } + */ + throw new DavException(DavServletResponse.SC_FORBIDDEN); + } + + private void removeLocalTxReferences(TransactionResource resource) { + for (Object o : values()) { + Transaction tx = (Transaction) o; + removeReferences(tx, this, resource); + } + } + } + + /** + * + */ + private static class TransactionMap extends HashMap { + + public Transaction get(String key) { + Transaction tx = null; + if (containsKey(key)) { + tx = super.get(key); + } + return tx; + } + + public Transaction putTransaction(String key, Transaction value) throws DavException { + // any global and local transactions allowed. + return super.put(key, value); + } + } + + /** + * Private class implementing Xid interface. + */ + private static class XidImpl implements Xid { + + private final String id; + + /** + * Create a new Xid + * + * @param id + */ + private XidImpl(String id) { + this.id = id; + } + + /** + * @return 1 + * @see javax.transaction.xa.Xid#getFormatId() + */ + public int getFormatId() { + // todo: define reasonable format id + return 1; + } + + /** + * @return an empty byte array. + * @see javax.transaction.xa.Xid#getBranchQualifier() + */ + public byte[] getBranchQualifier() { + return new byte[0]; + } + + /** + * @return id as byte array + * @see javax.transaction.xa.Xid#getGlobalTransactionId() + */ + public byte[] getGlobalTransactionId() { + return id.getBytes(); + } + } +} Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/transaction/TxLockManagerImpl.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/webdav/jcr/version/VersionHistoryItemCollection.java =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/version/VersionHistoryItemCollection.java (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/version/VersionHistoryItemCollection.java (working copy) @@ -0,0 +1,178 @@ +/* + * 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.webdav.jcr.version; + +import org.apache.jackrabbit.webdav.DavException; +import org.apache.jackrabbit.webdav.DavResource; +import org.apache.jackrabbit.webdav.DavResourceFactory; +import org.apache.jackrabbit.webdav.DavResourceLocator; +import org.apache.jackrabbit.webdav.DavServletResponse; +import org.apache.jackrabbit.webdav.jcr.DefaultItemCollection; +import org.apache.jackrabbit.webdav.jcr.ItemResourceConstants; +import org.apache.jackrabbit.webdav.jcr.JcrDavException; +import org.apache.jackrabbit.webdav.jcr.JcrDavSession; +import org.apache.jackrabbit.webdav.jcr.property.JcrDavPropertyNameSet; +import org.apache.jackrabbit.webdav.property.DavProperty; +import org.apache.jackrabbit.webdav.property.DavPropertyName; +import org.apache.jackrabbit.webdav.property.DefaultDavProperty; +import org.apache.jackrabbit.webdav.property.HrefProperty; +import org.apache.jackrabbit.webdav.property.ResourceType; +import org.apache.jackrabbit.webdav.version.VersionHistoryResource; +import org.apache.jackrabbit.webdav.version.VersionResource; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.jcr.Item; +import javax.jcr.RepositoryException; +import javax.jcr.version.VersionHistory; +import javax.jcr.version.VersionIterator; +import java.util.ArrayList; + +/** + * VersionHistoryItemCollection represents a JCR version history. + * + * @see VersionHistory + */ +public class VersionHistoryItemCollection extends DefaultItemCollection + implements VersionHistoryResource { + + private static Logger log = LoggerFactory.getLogger(VersionHistoryItemCollection.class); + + /** + * Create a new VersionHistoryItemCollection resource. + * + * @param resourcePath + * @param session + * @param factory + */ + public VersionHistoryItemCollection(DavResourceLocator resourcePath, + JcrDavSession session, + DavResourceFactory factory, + Item item) { + super(resourcePath, session, factory, item); + if (item == null || !(item instanceof VersionHistory)) { + throw new IllegalArgumentException("VersionHistory item expected."); + } + } + + //----------------------------------------------< DavResource interface >--- + /** + * @see org.apache.jackrabbit.webdav.DavResource#getSupportedMethods() + */ + @Override + public String getSupportedMethods() { + StringBuffer sb = new StringBuffer(ItemResourceConstants.METHODS); + sb.append(", ").append(VersionHistoryResource.METHODS); + return sb.toString(); + } + + @Override + public DavProperty getProperty(DavPropertyName name) { + DavProperty prop = super.getProperty(name); + if (prop == null) { + // required, protected version-set property for version-history resource + try { + if (ROOT_VERSION.equals(name)) { + // required root-version property for version-history resource + String rootVersionHref = getLocatorFromItem(((VersionHistory)item).getRootVersion()).getHref(true); + prop = new HrefProperty(ROOT_VERSION, rootVersionHref, true); + } else if (VERSION_SET.equals(name)) { + VersionIterator vIter = ((VersionHistory) item).getAllVersions(); + prop = getHrefProperty(VERSION_SET, vIter, true); + } + } catch (RepositoryException e) { + log.error(e.getMessage()); + } + } + + return prop; + } + + /** + * Removing a version resource is achieved by calling removeVersion + * on the versionhistory item this version belongs to. + * + * @throws DavException if the version does not exist or if an error occurs + * while deleting. + * @see DavResource#removeMember(org.apache.jackrabbit.webdav.DavResource) + */ + @Override + public void removeMember(DavResource member) throws DavException { + if (exists()) { + VersionHistory versionHistory = (VersionHistory) item; + try { + versionHistory.removeVersion(getItemName(member.getLocator().getRepositoryPath())); + } catch (RepositoryException e) { + throw new JcrDavException(e); + } + } else { + throw new DavException(DavServletResponse.SC_NOT_FOUND); + } + } + //-----------------------------------< VersionHistoryResource interface >--- + /** + * Return an array of {@link VersionResource}s representing all versions + * present in the underlying JCR version history. + * + * @return array of {@link VersionResource}s representing all versions + * present in the underlying JCR version history. + * @throws DavException + * @see org.apache.jackrabbit.webdav.version.VersionHistoryResource#getVersions() + */ + public VersionResource[] getVersions() throws DavException { + try { + VersionIterator vIter = ((VersionHistory)item).getAllVersions(); + ArrayList l = new ArrayList(); + while (vIter.hasNext()) { + DavResourceLocator versionLoc = getLocatorFromItem(vIter.nextVersion()); + VersionResource vr = (VersionResource) createResourceFromLocator(versionLoc); + l.add(vr); + } + return l.toArray(new VersionResource[l.size()]); + } catch (RepositoryException e) { + throw new JcrDavException(e); + } + } + + //-------------------------------------------------------------------------- + @Override + protected void initPropertyNames() { + super.initPropertyNames(); + + if (exists()) { + names.addAll(JcrDavPropertyNameSet.VERSIONHISTORY_SET); + } + } + + /** + * Fill the property set for this resource. + */ + @Override + protected void initProperties() { + super.initProperties(); + + // change resource type defined by default item collection + properties.add(new ResourceType(ResourceType.VERSION_HISTORY)); + + // jcr specific property pointing to the node this history belongs to + try { + properties.add(new DefaultDavProperty(JCR_VERSIONABLEUUID, ((VersionHistory)item).getVersionableIdentifier())); + } catch (RepositoryException e) { + log.error(e.getMessage()); + } + } +} Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/version/VersionHistoryItemCollection.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/webdav/jcr/version/VersionItemCollection.java =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/version/VersionItemCollection.java (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/version/VersionItemCollection.java (working copy) @@ -0,0 +1,240 @@ +/* + * 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.webdav.jcr.version; + +import org.apache.jackrabbit.JcrConstants; +import org.apache.jackrabbit.webdav.DavException; +import org.apache.jackrabbit.webdav.DavResourceFactory; +import org.apache.jackrabbit.webdav.DavResourceLocator; +import org.apache.jackrabbit.webdav.DavServletResponse; +import org.apache.jackrabbit.webdav.jcr.property.JcrDavPropertyNameSet; +import org.apache.jackrabbit.webdav.property.DavProperty; +import org.apache.jackrabbit.webdav.util.HttpDateFormat; +import org.apache.jackrabbit.webdav.jcr.DefaultItemCollection; +import org.apache.jackrabbit.webdav.jcr.ItemResourceConstants; +import org.apache.jackrabbit.webdav.jcr.JcrDavException; +import org.apache.jackrabbit.webdav.jcr.JcrDavSession; +import org.apache.jackrabbit.webdav.property.DavPropertyName; +import org.apache.jackrabbit.webdav.property.DefaultDavProperty; +import org.apache.jackrabbit.webdav.property.HrefProperty; +import org.apache.jackrabbit.webdav.version.LabelInfo; +import org.apache.jackrabbit.webdav.version.LabelSetProperty; +import org.apache.jackrabbit.webdav.version.VersionHistoryResource; +import org.apache.jackrabbit.webdav.version.VersionResource; +import org.apache.jackrabbit.webdav.version.report.ReportType; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.jcr.Item; +import javax.jcr.Node; +import javax.jcr.Property; +import javax.jcr.PropertyIterator; +import javax.jcr.RepositoryException; +import javax.jcr.version.Version; +import javax.jcr.version.VersionHistory; +import java.util.ArrayList; +import java.util.List; + +/** + * VersionItemCollection represents a JCR version. + * + * @see Version + */ +public class VersionItemCollection extends DefaultItemCollection + implements VersionResource { + + private static Logger log = LoggerFactory.getLogger(VersionItemCollection.class); + + /** + * Create a new VersionItemCollection. + * + * @param locator + * @param session + * @param factory + */ + public VersionItemCollection(DavResourceLocator locator, + JcrDavSession session, + DavResourceFactory factory, Item item) { + super(locator, session, factory, item); + if (item == null || !(item instanceof Version)) { + throw new IllegalArgumentException("Version item expected."); + } + } + + @Override + public DavProperty getProperty(DavPropertyName name) { + DavProperty prop = super.getProperty(name); + if (prop == null && exists()) { + Version v = (Version) item; + try { + if (VERSION_NAME.equals(name)) { + // required, protected DAV:version-name property + prop = new DefaultDavProperty(VERSION_NAME, v.getName(), true); + } else if (VERSION_HISTORY.equals(name)) { + // required DAV:version-history (computed) property + String vhHref = getLocatorFromItem(getVersionHistoryItem()).getHref(true); + prop = new HrefProperty(VERSION_HISTORY, vhHref, true); + } else if (PREDECESSOR_SET.equals(name)) { + // required DAV:predecessor-set (protected) property + prop = getHrefProperty(VersionResource.PREDECESSOR_SET, v.getPredecessors(), true); + } else if (SUCCESSOR_SET.equals(name)) { + // required DAV:successor-set (computed) property + prop = getHrefProperty(SUCCESSOR_SET, v.getSuccessors(), true); + } else if (LABEL_NAME_SET.equals(name)) { + // required, protected DAV:label-name-set property + String[] labels = getVersionHistoryItem().getVersionLabels(v); + prop = new LabelSetProperty(labels); + } else if (CHECKOUT_SET.equals(name)) { + // required DAV:checkout-set (computed) property + PropertyIterator it = v.getReferences(); + List nodeList = new ArrayList(); + while (it.hasNext()) { + Property p = it.nextProperty(); + if (JcrConstants.JCR_BASEVERSION.equals(p.getName())) { + Node n = p.getParent(); + if (n.isCheckedOut()) { + nodeList.add(n); + } + } + } + prop = getHrefProperty(CHECKOUT_SET, nodeList.toArray(new Node[nodeList.size()]), true); + } + } catch (RepositoryException e) { + log.error(e.getMessage()); + } + } + + return prop; + } + + //----------------------------------------------< DavResource interface >--- + /** + * @see org.apache.jackrabbit.webdav.DavResource#getSupportedMethods() + */ + @Override + public String getSupportedMethods() { + StringBuffer sb = new StringBuffer(ItemResourceConstants.METHODS); + sb.append(", ").append(VersionResource.METHODS); + return sb.toString(); + } + + //------------------------------------------< VersionResource interface >--- + /** + * Modify the labels defined for the underlying repository version. + * + * @param labelInfo + * @throws org.apache.jackrabbit.webdav.DavException + * @see VersionResource#label(org.apache.jackrabbit.webdav.version.LabelInfo) + * @see VersionHistory#addVersionLabel(String, String, boolean) + * @see VersionHistory#removeVersionLabel(String) + */ + public void label(LabelInfo labelInfo) throws DavException { + if (labelInfo == null) { + throw new DavException(DavServletResponse.SC_BAD_REQUEST, "Valid label request body required."); + } + if (!exists()) { + throw new DavException(DavServletResponse.SC_NOT_FOUND); + } + try { + VersionHistory vh = getVersionHistoryItem(); + if (labelInfo.getType() == LabelInfo.TYPE_REMOVE) { + vh.removeVersionLabel(labelInfo.getLabelName()); + } else if (labelInfo.getType() == LabelInfo.TYPE_ADD) { + // ADD: only add if not yet existing + vh.addVersionLabel(item.getName(), labelInfo.getLabelName(), false); + } else { + // SET: move label if already existing + vh.addVersionLabel(item.getName(), labelInfo.getLabelName(), true); + } + } catch (RepositoryException e) { + throw new JcrDavException(e); + } + } + + /** + * Returns the {@link VersionHistory} associated with the repository version. + * Note: in contrast to a versionable node, the version history of a version + * item is always represented by its nearest ancestor. + * + * @return the {@link VersionHistoryResource} associated with this resource. + * @throws org.apache.jackrabbit.webdav.DavException + * @see org.apache.jackrabbit.webdav.version.VersionResource#getVersionHistory() + * @see javax.jcr.Item#getParent() + */ + public VersionHistoryResource getVersionHistory() throws DavException { + if (!exists()) { + throw new DavException(DavServletResponse.SC_NOT_FOUND); + } + + try { + VersionHistory vh = getVersionHistoryItem(); + DavResourceLocator loc = getLocatorFromItem(vh); + return (VersionHistoryResource) createResourceFromLocator(loc); + } catch (RepositoryException e) { + throw new JcrDavException(e); + } + } + + /** + * Return versionhistory that contains this version item + * + * @return versionhistory that contains this version item + * @throws RepositoryException + * @see javax.jcr.version.Version#getContainingHistory() + */ + private VersionHistory getVersionHistoryItem() throws RepositoryException { + return ((Version)item).getContainingHistory(); + } + + //-------------------------------------------------------------------------- + /** + * Define the set of reports supported by this resource. + * + * @see org.apache.jackrabbit.webdav.version.report.SupportedReportSetProperty + */ + @Override + protected void initSupportedReports() { + super.initSupportedReports(); + if (exists()) { + supportedReports.addReportType(ReportType.VERSION_TREE); + } + } + + @Override + protected void initPropertyNames() { + super.initPropertyNames(); + + if (exists()) { + names.addAll(JcrDavPropertyNameSet.VERSION_SET); + } + } + + @Override + protected String getCreationDate() { + if (exists()) { + Version v = (Version) item; + try { + return HttpDateFormat.creationDateFormat().format(v.getCreated().getTime()); + } catch (RepositoryException e) { + log.error(e.getMessage()); + } + } + + // fallback + return super.getCreationDate(); + } +} Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/version/VersionItemCollection.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/webdav/jcr/version/report/AbstractJcrReport.java =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/version/report/AbstractJcrReport.java (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/version/report/AbstractJcrReport.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.webdav.jcr.version.report; + +import javax.jcr.Session; + +import org.apache.jackrabbit.webdav.DavConstants; +import org.apache.jackrabbit.webdav.DavException; +import org.apache.jackrabbit.webdav.DavResource; +import org.apache.jackrabbit.webdav.DavServletResponse; +import org.apache.jackrabbit.webdav.DavSession; +import org.apache.jackrabbit.webdav.jcr.JcrDavSession; +import org.apache.jackrabbit.webdav.version.report.AbstractReport; +import org.apache.jackrabbit.webdav.version.report.Report; +import org.apache.jackrabbit.webdav.version.report.ReportInfo; + +/** + * AbstractJcrReport... + */ +public abstract class AbstractJcrReport extends AbstractReport { + + private Session session; + private ReportInfo reportInfo; + + /** + * Performs basic validation checks common to all JCR specific reports. + * + * @param resource + * @param info + * @throws DavException + * @see Report#init(DavResource, ReportInfo) + */ + public void init(DavResource resource, ReportInfo info) throws DavException { + if (resource == null || info == null) { + throw new DavException(DavServletResponse.SC_BAD_REQUEST, "Unable to run report: WebDAV Resource and ReportInfo must not be null."); + } + if (!getType().isRequestedReportType(info)) { + throw new DavException(DavServletResponse.SC_BAD_REQUEST, "Expected report type: '" + getType().getReportName() + "', found: '" + info.getReportName() + ";" + "'."); + } + if (info.getDepth() > DavConstants.DEPTH_0) { + throw new DavException(DavServletResponse.SC_BAD_REQUEST, "Invalid Depth header: " + info.getDepth()); + } + + DavSession davSession = resource.getSession(); + if (davSession == null) { + throw new DavException(DavServletResponse.SC_BAD_REQUEST, "The resource must provide a non-null session object in order to create '" + getType().getReportName()+ "' report."); + } + session = JcrDavSession.getRepositorySession(resource.getSession()); + if (session == null) { + throw new DavException(DavServletResponse.SC_INTERNAL_SERVER_ERROR, "Internal error: Unable to access repository session."); + } + reportInfo = info; + } + + //-----------------------------------------------------< implementation >--- + /** + * @return session Session object as obtained from the {@link DavSession}. + */ + Session getRepositorySession() { + return session; + } + + /** + * @return reportInfo the ReportInfo specifying the requested + * report details. + */ + ReportInfo getReportInfo() { + return reportInfo; + } +} Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/version/report/AbstractJcrReport.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/webdav/jcr/version/report/ExportViewReport.java =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/version/report/ExportViewReport.java (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/version/report/ExportViewReport.java (working copy) @@ -0,0 +1,159 @@ +/* + * 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.webdav.jcr.version.report; + +import org.apache.jackrabbit.commons.webdav.JcrRemotingConstants; +import org.apache.jackrabbit.util.Text; +import org.apache.jackrabbit.webdav.DavException; +import org.apache.jackrabbit.webdav.DavResource; +import org.apache.jackrabbit.webdav.jcr.ItemResourceConstants; +import org.apache.jackrabbit.webdav.jcr.JcrDavException; +import org.apache.jackrabbit.webdav.version.report.Report; +import org.apache.jackrabbit.webdav.version.report.ReportInfo; +import org.apache.jackrabbit.webdav.version.report.ReportType; +import org.apache.jackrabbit.webdav.xml.DomUtil; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.xml.sax.SAXException; + +import javax.jcr.PathNotFoundException; +import javax.jcr.RepositoryException; +import javax.jcr.Session; +import javax.xml.parsers.ParserConfigurationException; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; + +/** + * ExportViewReport handles REPORT requests for the 'exportview' + * report. The 'exportview' report is used to export + * {@link Session#exportDocumentView(String, java.io.OutputStream, boolean, boolean) DocView} + * and {@link Session#exportSystemView(String, java.io.OutputStream, boolean, boolean) SysView} + * of the {@link javax.jcr.Item item} represented by the requested resource. + *

+ * The request body must contain a {@link ItemResourceConstants#NAMESPACE dcr}:exportview + * element: + *

+ * <!ELEMENT exportview  ( (sysview | docview)?, skipbinary?, norecurse ) >
+ * <!ELEMENT sysview EMPTY >
+ * <!ELEMENT docview EMPTY >
+ * <!ELEMENT skipbinary EMPTY >
+ * <!ELEMENT norecurse EMPTY >
+ * 
+ * If no view type is specified the DocView is generated. + */ +public class ExportViewReport extends AbstractJcrReport { + + private static Logger log = LoggerFactory.getLogger(ExportViewReport.class); + + /** + * The exportview report type + */ + public static final ReportType EXPORTVIEW_REPORT = ReportType.register(JcrRemotingConstants.REPORT_EXPORT_VIEW, ItemResourceConstants.NAMESPACE, ExportViewReport.class); + + private String absNodePath; + + /** + * Returns {@link #EXPORTVIEW_REPORT} report type. + * + * @return {@link #EXPORTVIEW_REPORT} + * @see org.apache.jackrabbit.webdav.version.report.Report#getType() + */ + public ReportType getType() { + return EXPORTVIEW_REPORT; + } + + /** + * Always returns false. + * + * @return false + */ + public boolean isMultiStatusReport() { + return false; + } + + /** + * @see Report#init(DavResource, ReportInfo) + */ + @Override + public void init(DavResource resource, ReportInfo info) throws DavException { + // delegate validation to super class + super.init(resource, info); + // report specific validation: resource must represent an existing + // repository node + absNodePath = resource.getLocator().getRepositoryPath(); + try { + if (!(getRepositorySession().itemExists(absNodePath) && getRepositorySession().getItem(absNodePath).isNode())) { + throw new JcrDavException(new PathNotFoundException(absNodePath + " does not exist.")); + } + } catch (RepositoryException e) { + throw new JcrDavException(e); + } + + } + + /** + * Creates a Xml document from the generated view. + * + * @param document + * @return Xml element representing the output of the specified view. + * @see org.apache.jackrabbit.webdav.xml.XmlSerializable#toXml(Document) + */ + public Element toXml(Document document) { + boolean skipBinary = getReportInfo().containsContentElement("skipbinary", ItemResourceConstants.NAMESPACE); + boolean noRecurse = getReportInfo().containsContentElement("norecurse", ItemResourceConstants.NAMESPACE); + // todo improve... + try { + // create tmpFile in default system-tmp directory + String prefix = "_tmp_" + Text.getName(absNodePath); + File tmpfile = File.createTempFile(prefix, null, null); + tmpfile.deleteOnExit(); + + FileOutputStream out = new FileOutputStream(tmpfile); + if (getReportInfo().containsContentElement("sysview", ItemResourceConstants.NAMESPACE)) { + getRepositorySession().exportSystemView(absNodePath, out, skipBinary, noRecurse); + } else { + // default is docview + getRepositorySession().exportDocumentView(absNodePath, out, skipBinary, noRecurse); + } + out.close(); + + Document tmpDoc = + DomUtil.parseDocument(new FileInputStream(tmpfile)); + + // import the root node of the generated xml to the given document. + Element rootElem = (Element)document.importNode(tmpDoc.getDocumentElement(), true); + return rootElem; + + } catch (RepositoryException e) { + log.error(e.getMessage()); + } catch (FileNotFoundException e) { + log.error(e.getMessage()); + } catch (IOException e) { + log.error(e.getMessage()); + } catch (ParserConfigurationException e) { + log.error(e.getMessage()); + } catch (SAXException e) { + log.error(e.getMessage()); + } + return null; + } +} Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/version/report/ExportViewReport.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/webdav/jcr/version/report/JcrPrivilegeReport.java =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/version/report/JcrPrivilegeReport.java (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/version/report/JcrPrivilegeReport.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.webdav.jcr.version.report; + +import org.apache.jackrabbit.commons.webdav.JcrRemotingConstants; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.apache.jackrabbit.webdav.version.report.Report; +import org.apache.jackrabbit.webdav.version.report.ReportType; +import org.apache.jackrabbit.webdav.version.report.ReportInfo; +import org.apache.jackrabbit.webdav.jcr.ItemResourceConstants; +import org.apache.jackrabbit.webdav.MultiStatus; +import org.apache.jackrabbit.webdav.DavResource; +import org.apache.jackrabbit.webdav.DavException; +import org.apache.jackrabbit.webdav.DavConstants; +import org.apache.jackrabbit.webdav.MultiStatusResponse; +import org.apache.jackrabbit.webdav.DavServletResponse; +import org.apache.jackrabbit.webdav.DavResourceLocator; +import org.apache.jackrabbit.webdav.xml.DomUtil; +import org.apache.jackrabbit.webdav.security.Privilege; +import org.apache.jackrabbit.webdav.security.CurrentUserPrivilegeSetProperty; +import org.w3c.dom.Element; +import org.w3c.dom.Document; + +import javax.jcr.RepositoryException; +import java.util.List; +import java.util.ArrayList; + +/** + *

Report to retrieve the permissions granted to the reading session as defined + * by {@link javax.jcr.Session#hasPermission(String, String)}.

+ * + *

NOTE: the name of this report and the names of the privileges are + * misleading as they rather correspond to the actions defined by + * {@link javax.jcr.Session}; while the JCR privileges s.str. have only been + * specified as of JSR 283 in the {@link javax.jcr.security.Privilege} interface. + * A better name would have been JcrActionReport

+ * + * @see org.apache.jackrabbit.webdav.jcr.security.JcrUserPrivilegesProperty for + * the webdav correspondence to {@link javax.jcr.security.AccessControlManager#getPrivileges(String)} + * mapped to the {@link org.apache.jackrabbit.webdav.security.CurrentUserPrivilegeSetProperty}. + */ +public class JcrPrivilegeReport extends AbstractJcrReport { + + private static Logger log = LoggerFactory.getLogger(JcrPrivilegeReport.class); + + /** + * The exportview report type + */ + public static final ReportType PRIVILEGES_REPORT = ReportType.register(JcrRemotingConstants.REPORT_PRIVILEGES, ItemResourceConstants.NAMESPACE, JcrPrivilegeReport.class); + + private static final Privilege[] PRIVS = new Privilege[] { + ItemResourceConstants.PRIVILEGE_JCR_READ, + ItemResourceConstants.PRIVILEGE_JCR_ADD_NODE, + ItemResourceConstants.PRIVILEGE_JCR_SET_PROPERTY, + ItemResourceConstants.PRIVILEGE_JCR_REMOVE}; + + private final MultiStatus ms = new MultiStatus(); + + /** + * Returns {@link #PRIVILEGES_REPORT} report type. + * + * @return {@link #PRIVILEGES_REPORT} + * @see org.apache.jackrabbit.webdav.version.report.Report#getType() + */ + @Override + public ReportType getType() { + return PRIVILEGES_REPORT; + } + + /** + * Always returns true. + * + * @return true + * @see org.apache.jackrabbit.webdav.version.report.Report#isMultiStatusReport() + */ + @Override + public boolean isMultiStatusReport() { + return true; + } + + /** + * @see Report#init(DavResource, ReportInfo) + */ + @Override + public void init(DavResource resource, ReportInfo info) throws DavException { + // delegate basic validation to super class + super.init(resource, info); + // make also sure, the info contains a DAV:href child element + if (!info.containsContentElement(DavConstants.XML_HREF, DavConstants.NAMESPACE)) { + throw new DavException(DavServletResponse.SC_BAD_REQUEST, "dcr:privileges element must at least contain a single DAV:href child."); + } + // immediately build the final multistatus element + Element hrefElem = info.getContentElement(DavConstants.XML_HREF, DavConstants.NAMESPACE); + String href = DomUtil.getTextTrim(hrefElem); + href = normalizeResourceHref(obtainAbsolutePathFromUri(href)); // TODO: we should check whether the authority component matches + DavResourceLocator resourceLoc = resource.getLocator(); + DavResourceLocator loc = resourceLoc.getFactory().createResourceLocator(resourceLoc.getPrefix(), href); + // immediately build the final multistatus element + addResponses(loc); + } + + /** + * Creates a Xml document from the generated view. + * + * @param document + * @return Xml element representing the output of the specified view. + * @see org.apache.jackrabbit.webdav.xml.XmlSerializable#toXml(Document) + */ + @Override + public Element toXml(Document document) { + return ms.toXml(document); + } + + private void addResponses(DavResourceLocator locator) { + String repositoryPath = locator.getRepositoryPath(); + MultiStatusResponse resp = new MultiStatusResponse(locator.getHref(false), null); + List currentPrivs = new ArrayList(); + for (Privilege priv : PRIVS) { + try { + if (getRepositorySession().hasPermission(repositoryPath, priv.getName())) { + currentPrivs.add(priv); + } + } catch (RepositoryException e) { + // ignore + log.debug(e.toString()); + } + } + resp.add(new CurrentUserPrivilegeSetProperty(currentPrivs.toArray(new Privilege[currentPrivs.size()]))); + ms.addResponse(resp); + } + + private static String obtainAbsolutePathFromUri(String uri) { + try { + java.net.URI u = new java.net.URI(uri); + StringBuilder sb = new StringBuilder(); + sb.append(u.getRawPath()); + if (u.getRawQuery() != null) { + sb.append("?").append(u.getRawQuery()); + } + return sb.toString(); + } + catch (java.net.URISyntaxException ex) { + log.warn("parsing " + uri, ex); + return uri; + } + } +} Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/version/report/JcrPrivilegeReport.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/webdav/jcr/version/report/LocateByUuidReport.java =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/version/report/LocateByUuidReport.java (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/version/report/LocateByUuidReport.java (working copy) @@ -0,0 +1,117 @@ +/* + * 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.webdav.jcr.version.report; + +import org.apache.jackrabbit.commons.webdav.JcrRemotingConstants; +import org.apache.jackrabbit.webdav.DavConstants; +import org.apache.jackrabbit.webdav.DavException; +import org.apache.jackrabbit.webdav.DavResource; +import org.apache.jackrabbit.webdav.DavResourceLocator; +import org.apache.jackrabbit.webdav.DavServletResponse; +import org.apache.jackrabbit.webdav.MultiStatus; +import org.apache.jackrabbit.webdav.jcr.ItemResourceConstants; +import org.apache.jackrabbit.webdav.jcr.JcrDavException; +import org.apache.jackrabbit.webdav.version.report.Report; +import org.apache.jackrabbit.webdav.version.report.ReportInfo; +import org.apache.jackrabbit.webdav.version.report.ReportType; +import org.apache.jackrabbit.webdav.xml.DomUtil; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +import javax.jcr.Node; +import javax.jcr.RepositoryException; + +/** + * LocateByUuidReport handles REPORT requests for the 'locate-by-uuid' + * report. + *

+ * The request body must be a 'dcr:locate-by-uuid' XML element: + *

+ * <!ELEMENT locate-by-uuid ( href , prop? ) >
+ * 
+ * The response to a successful report request will be a Multi-Status response. + */ +public class LocateByUuidReport extends AbstractJcrReport { + + private static Logger log = LoggerFactory.getLogger(LocateByUuidReport.class); + + /** + * The exportview report type + */ + public static final ReportType LOCATE_BY_UUID_REPORT = ReportType.register(JcrRemotingConstants.REPORT_LOCATE_BY_UUID, ItemResourceConstants.NAMESPACE, LocateByUuidReport.class); + + private MultiStatus ms; + + /** + * Returns {@link #LOCATE_BY_UUID_REPORT} report type. + * + * @return {@link #LOCATE_BY_UUID_REPORT} + * @see org.apache.jackrabbit.webdav.version.report.Report#getType() + */ + public ReportType getType() { + return LOCATE_BY_UUID_REPORT; + } + + /** + * Always returns true. + * + * @return true + * @see org.apache.jackrabbit.webdav.version.report.Report#isMultiStatusReport() + */ + public boolean isMultiStatusReport() { + return true; + } + + /** + * @see Report#init(DavResource, ReportInfo) + */ + @Override + public void init(DavResource resource, ReportInfo info) throws DavException { + // delegate basic validation to super class + super.init(resource, info); + // make also sure, the info contains a DAV:href child element + if (!info.containsContentElement(DavConstants.XML_HREF, DavConstants.NAMESPACE)) { + throw new DavException(DavServletResponse.SC_BAD_REQUEST, "dcr:locate-by-uuid element must at least contain a single DAV:href child."); + } + // immediately build the final multistatus element + try { + Element hrefElem = info.getContentElement(DavConstants.XML_HREF, DavConstants.NAMESPACE); + String uuid = DomUtil.getTextTrim(hrefElem); + DavResourceLocator resourceLoc = resource.getLocator(); + Node n = getRepositorySession().getNodeByUUID(uuid); + DavResourceLocator loc = resourceLoc.getFactory().createResourceLocator(resourceLoc.getPrefix(), resourceLoc.getWorkspacePath(), n.getPath(), false); + DavResource locatedResource = resource.getFactory().createResource(loc, resource.getSession()); + ms = new MultiStatus(); + ms.addResourceProperties(locatedResource, info.getPropertyNameSet(), info.getDepth()); + } catch (RepositoryException e) { + throw new JcrDavException(e); + } + } + + /** + * Creates a Xml document from the generated view. + * + * @param document + * @return Xml element representing the output of the specified view. + * @see org.apache.jackrabbit.webdav.xml.XmlSerializable#toXml(Document) + */ + public Element toXml(Document document) { + return ms.toXml(document); + } +} Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/version/report/LocateByUuidReport.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/webdav/jcr/version/report/LocateCorrespondingNodeReport.java =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/version/report/LocateCorrespondingNodeReport.java (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/version/report/LocateCorrespondingNodeReport.java (working copy) @@ -0,0 +1,151 @@ +/* + * 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.webdav.jcr.version.report; + +import org.apache.jackrabbit.commons.webdav.JcrRemotingConstants; +import org.apache.jackrabbit.webdav.DavConstants; +import org.apache.jackrabbit.webdav.DavException; +import org.apache.jackrabbit.webdav.DavResource; +import org.apache.jackrabbit.webdav.DavResourceLocator; +import org.apache.jackrabbit.webdav.DavServletResponse; +import org.apache.jackrabbit.webdav.jcr.ItemResourceConstants; +import org.apache.jackrabbit.webdav.jcr.JcrDavException; +import org.apache.jackrabbit.webdav.version.DeltaVConstants; +import org.apache.jackrabbit.webdav.version.report.Report; +import org.apache.jackrabbit.webdav.version.report.ReportInfo; +import org.apache.jackrabbit.webdav.version.report.ReportType; +import org.apache.jackrabbit.webdav.xml.DomUtil; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +import javax.jcr.Item; +import javax.jcr.Node; +import javax.jcr.PathNotFoundException; +import javax.jcr.RepositoryException; +import javax.jcr.Session; + +/** + * LocateCorrespondingNodeReport is used to identify the resource that + * represents the corresponding node in another workspace. + * + *

+ * The request body must be a 'dcr:locate-corresponding-node' XML element, that + * contains the href of the source workspace, where the corresponding node should + * be searched: + *

+ * <!ELEMENT locate-corresponding-node ( workspace ) >
+ * <!ELEMENT workspace ( href ) >  (as defined by RFC 3253)
+ * 
+ * The response to a successful report request must be a 'dcr:locate-corresponding-node-report' + * element that contains the href of the corresponding node in the given source + * workspace: + * + *
+ * <!ELEMENT locate-corresponding-node-report ( href ) >
+ * 
+ * + * @see javax.jcr.Node#getCorrespondingNodePath(String) + */ +public class LocateCorrespondingNodeReport extends AbstractJcrReport { + + private static Logger log = LoggerFactory.getLogger(LocateCorrespondingNodeReport.class); + + private String correspHref; + + /** + * The corresponding-node report type + */ + public static final ReportType LOCATE_CORRESPONDING_NODE_REPORT = ReportType.register(JcrRemotingConstants.REPORT_LOCATE_CORRESPONDING_NODE, ItemResourceConstants.NAMESPACE, LocateByUuidReport.class); + + /** + * Returns {@link #LOCATE_CORRESPONDING_NODE_REPORT} + * + * @return always returns {@link #LOCATE_CORRESPONDING_NODE_REPORT} + * @see org.apache.jackrabbit.webdav.version.report.Report#getType() + */ + public ReportType getType() { + return LOCATE_CORRESPONDING_NODE_REPORT; + } + + /** + * Always returns false. + * + * @return false + * @see org.apache.jackrabbit.webdav.version.report.Report#isMultiStatusReport() + */ + public boolean isMultiStatusReport() { + return false; + } + + /** + * @see Report#init(DavResource, ReportInfo) + */ + @Override + public void init(DavResource resource, ReportInfo info) throws DavException { + // general validation checks + super.init(resource, info); + // specific for this report: a workspace href must be provided + Element workspace = info.getContentElement(DeltaVConstants.WORKSPACE.getName(), DeltaVConstants.WORKSPACE.getNamespace()); + String workspaceHref = normalizeResourceHref(DomUtil.getChildTextTrim(workspace, DavConstants.XML_HREF, DavConstants.NAMESPACE)); + if (workspaceHref == null || "".equals(workspaceHref)) { + throw new DavException(DavServletResponse.SC_BAD_REQUEST, "Request body must define the href of a source workspace"); + } + // retrieve href of the corresponding resource in the other workspace + try { + this.correspHref = getCorrespondingResourceHref(resource, getRepositorySession(), workspaceHref); + } catch (RepositoryException e) { + throw new JcrDavException(e); + } + } + + /** + * @see org.apache.jackrabbit.webdav.xml.XmlSerializable#toXml(Document) + */ + public Element toXml(Document document) { + Element elem = DomUtil.createElement(document, "locate-corresponding-node-report", ItemResourceConstants.NAMESPACE); + if (correspHref != null) { + elem.appendChild(DomUtil.hrefToXml(correspHref, document)); + } + return elem; + } + + /** + * Retrieve the href of the corresponding resource in the indicated workspace. + * + * @param resource + * @param session Session object used to access the {@link Node} object + * represented by the given resource. + * @param workspaceHref + * @return + * @throws RepositoryException + */ + private static String getCorrespondingResourceHref(DavResource resource, Session session, String workspaceHref) throws RepositoryException { + DavResourceLocator rLoc = resource.getLocator(); + String itemPath = rLoc.getRepositoryPath(); + Item item = session.getItem(itemPath); + if (item.isNode()) { + String workspaceName = rLoc.getFactory().createResourceLocator(rLoc.getPrefix(), workspaceHref).getWorkspaceName(); + String corrPath = ((Node)item).getCorrespondingNodePath(workspaceName); + DavResourceLocator corrLoc = rLoc.getFactory().createResourceLocator(rLoc.getPrefix(), "/" + workspaceName, corrPath, false); + return corrLoc.getHref(true); + } else { + throw new PathNotFoundException("Node with path " + itemPath + " does not exist."); + } + } +} Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/version/report/LocateCorrespondingNodeReport.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/webdav/jcr/version/report/NodeTypesReport.java =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/version/report/NodeTypesReport.java (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/version/report/NodeTypesReport.java (working copy) @@ -0,0 +1,202 @@ +/* + * 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.webdav.jcr.version.report; + +import org.apache.jackrabbit.commons.iterator.NodeTypeIteratorAdapter; +import org.apache.jackrabbit.commons.webdav.JcrRemotingConstants; +import org.apache.jackrabbit.commons.webdav.NodeTypeConstants; +import org.apache.jackrabbit.webdav.DavException; +import org.apache.jackrabbit.webdav.DavResource; +import org.apache.jackrabbit.webdav.DavServletResponse; +import org.apache.jackrabbit.webdav.jcr.ItemResourceConstants; +import org.apache.jackrabbit.webdav.jcr.JcrDavException; +import org.apache.jackrabbit.webdav.jcr.nodetype.NodeDefinitionImpl; +import org.apache.jackrabbit.webdav.jcr.nodetype.PropertyDefinitionImpl; +import org.apache.jackrabbit.webdav.version.report.Report; +import org.apache.jackrabbit.webdav.version.report.ReportInfo; +import org.apache.jackrabbit.webdav.version.report.ReportType; +import org.apache.jackrabbit.webdav.xml.DomUtil; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +import javax.jcr.RepositoryException; +import javax.jcr.Session; +import javax.jcr.nodetype.NodeDefinition; +import javax.jcr.nodetype.NodeType; +import javax.jcr.nodetype.NodeTypeIterator; +import javax.jcr.nodetype.NodeTypeManager; +import javax.jcr.nodetype.PropertyDefinition; +import java.util.ArrayList; +import java.util.List; + +/** + * NodeTypesReport allows to retrieve the definition of a single + * or multiple node types. The request body must be a 'dcr:nodetypes' element: + *
+ * <!ELEMENT nodetypes ( nodetype+ | all-nodetypes | mixin-nodetypes | primary-nodetypes ) >
+ *
+ * <!ELEMENT nodetype ( nodetypename ) >
+ * <!ELEMENT nodetypename (#PCDATA) >
+ *
+ * <!ELEMENT all-nodetypes EMPTY >
+ * <!ELEMENT mixin-nodetypes EMPTY >
+ * <!ELEMENT primary-nodetypes EMPTY >
+ * 
+ */ +//todo: currently the nodetype report is not consistent with the general way of representing nodetype names (with NodetypeElement) in order to be compatible with the jackrabbit nodetype registry... +//todo: for the same reason, not the complete nodetype-definition, but only the nodetype def as stored is represented. +//todo: no namespace definition with response (> jackrabbit)... and nodetype element has same name as the one used with dav-properties +public class NodeTypesReport extends AbstractJcrReport implements NodeTypeConstants { + + private static Logger log = LoggerFactory.getLogger(NodeTypesReport.class); + + /** + * The registered type of this report. + */ + public static final ReportType NODETYPES_REPORT = ReportType.register(JcrRemotingConstants.REPORT_NODETYPES, ItemResourceConstants.NAMESPACE, NodeTypesReport.class); + + private NodeTypeIterator ntIter; + + /** + * Returns {@link #NODETYPES_REPORT} type. + * @return {@link #NODETYPES_REPORT} + * @see org.apache.jackrabbit.webdav.version.report.Report#getType() + */ + public ReportType getType() { + return NODETYPES_REPORT; + } + + /** + * Always returns false. + * + * @return false + * @see org.apache.jackrabbit.webdav.version.report.Report#isMultiStatusReport() + */ + public boolean isMultiStatusReport() { + return false; + } + + /** + * @see Report#init(DavResource, ReportInfo) + */ + @Override + public void init(DavResource resource, ReportInfo info) throws DavException { + // delegate basic validation to super class + super.init(resource, info); + // report specific validation and preparation for xml serialization + try { + ntIter = getNodeTypes(getRepositorySession(), info); + } catch (RepositoryException e) { + throw new JcrDavException(e); + } + if (ntIter == null) { + throw new DavException(DavServletResponse.SC_INTERNAL_SERVER_ERROR); + } + } + + /** + * Returns a Xml representation of the node type definition(s) according + * to the info object. + * + * @param document + * @return Xml representation of the node type definition(s) + * @see org.apache.jackrabbit.webdav.xml.XmlSerializable#toXml(Document) + */ + public Element toXml(Document document) { + Element report = document.createElement(NODETYPES_ELEMENT); + // loop over the nodetypes to be returned in the report + while (ntIter.hasNext()) { + NodeType nt = ntIter.nextNodeType(); + Element ntDef = document.createElement(NODETYPE_ELEMENT); + ntDef.setAttribute(NAME_ATTRIBUTE, nt.getName()); + ntDef.setAttribute(ISMIXIN_ATTRIBUTE, Boolean.toString(nt.isMixin())); + ntDef.setAttribute(HASORDERABLECHILDNODES_ATTRIBUTE, Boolean.toString(nt.hasOrderableChildNodes())); + // JCR 2.0 extension + ntDef.setAttribute(ISABSTRACT_ATTRIBUTE, Boolean.toString(nt.isAbstract())); + // JCR 2.0 extension + ntDef.setAttribute(ISQUERYABLE_ATTRIBUTE, Boolean.toString(nt.isQueryable())); + + // declared supertypes + Element supertypes = DomUtil.addChildElement(ntDef, SUPERTYPES_ELEMENT, null); + for (NodeType snt : nt.getDeclaredSupertypes()) { + DomUtil.addChildElement(supertypes, SUPERTYPE_ELEMENT, null, snt.getName()); + } + + // declared child node definitions + for (NodeDefinition aCnd : nt.getChildNodeDefinitions()) { + if (aCnd.getDeclaringNodeType().getName().equals(nt.getName())) { + ntDef.appendChild(NodeDefinitionImpl.create(aCnd).toXml(document)); + } + } + + // declared property definitions + for (PropertyDefinition aPd : nt.getPropertyDefinitions()) { + if (aPd.getDeclaringNodeType().getName().equals(nt.getName())) { + ntDef.appendChild(PropertyDefinitionImpl.create(aPd).toXml(document)); + } + } + + String primaryItemName = nt.getPrimaryItemName(); + if (primaryItemName != null) { + ntDef.setAttribute(PRIMARYITEMNAME_ATTRIBUTE, primaryItemName); + } + report.appendChild(ntDef); + } + return report; + } + + /** + * Parse the Xml element in the info object an return an interator over + * the specified node types. + * + * @return + * @throws RepositoryException + * @throws DavException + */ + private static NodeTypeIterator getNodeTypes(Session session, ReportInfo info) throws RepositoryException, DavException { + NodeTypeManager ntMgr = session.getWorkspace().getNodeTypeManager(); + + // check the simple types first... + if (info.containsContentElement(XML_REPORT_ALLNODETYPES, ItemResourceConstants.NAMESPACE)) { + return ntMgr.getAllNodeTypes(); + } else if (info.containsContentElement(XML_REPORT_MIXINNODETYPES, ItemResourceConstants.NAMESPACE)) { + return ntMgr.getMixinNodeTypes(); + } else if (info.containsContentElement(XML_REPORT_PRIMARYNODETYPES, ItemResourceConstants.NAMESPACE)) { + return ntMgr.getPrimaryNodeTypes(); + } else { + // None of the simple types. test if a report for individual + // nodetype was request. If not, the request body is not valid. + List elemList = info.getContentElements(XML_NODETYPE, ItemResourceConstants.NAMESPACE); + if (elemList.isEmpty()) { + // throw exception if the request body does not contain a single nodetype element + throw new DavException(DavServletResponse.SC_BAD_REQUEST, "NodeTypes report: request body has invalid format."); + } + + // todo: find better solution... + List ntList = new ArrayList(); + for (Element el : elemList) { + String nodetypeName = DomUtil.getChildTextTrim(el, XML_NODETYPENAME, ItemResourceConstants.NAMESPACE); + if (nodetypeName != null) { + ntList.add(ntMgr.getNodeType(nodetypeName)); + } + } + return new NodeTypeIteratorAdapter(ntList); + } + } +} Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/version/report/NodeTypesReport.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/webdav/jcr/version/report/RegisteredNamespacesReport.java =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/version/report/RegisteredNamespacesReport.java (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/version/report/RegisteredNamespacesReport.java (working copy) @@ -0,0 +1,121 @@ +/* + * 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.webdav.jcr.version.report; + +import org.apache.jackrabbit.webdav.DavException; +import org.apache.jackrabbit.webdav.DavResource; +import org.apache.jackrabbit.webdav.DavServletResponse; +import org.apache.jackrabbit.webdav.jcr.ItemResourceConstants; +import org.apache.jackrabbit.webdav.version.report.Report; +import org.apache.jackrabbit.webdav.version.report.ReportInfo; +import org.apache.jackrabbit.webdav.version.report.ReportType; +import org.apache.jackrabbit.webdav.xml.DomUtil; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +import javax.jcr.NamespaceRegistry; +import javax.jcr.RepositoryException; + +/** + * RegisteredNamespacesReport let the client retrieve the namespaces + * registered on the repository. + *

+ * Request body: + *

+ * <!ELEMENT registerednamespaces EMPTY >
+ * 
+ * + * Response body: + *
+ * <!ELEMENT registerednamespaces-report (namespace)* >
+ * <!ELEMENT namespace (prefix, uri) >
+ * <!ELEMENT prefix (#PCDATA) >
+ * <!ELEMENT uri (#PCDATA) >
+ * 
+ * + * @see javax.jcr.Workspace#getNamespaceRegistry() + */ +public class RegisteredNamespacesReport extends AbstractJcrReport implements ItemResourceConstants { + + private static Logger log = LoggerFactory.getLogger(RegisteredNamespacesReport.class); + + /** + * The registered type of this report. + */ + public static final ReportType REGISTERED_NAMESPACES_REPORT = ReportType.register(REPORT_REGISTERED_NAMESPACES, ItemResourceConstants.NAMESPACE, RegisteredNamespacesReport.class); + + private NamespaceRegistry nsReg; + + /** + * Returns {@link #REGISTERED_NAMESPACES_REPORT} type. + * @return {@link #REGISTERED_NAMESPACES_REPORT} + * @see org.apache.jackrabbit.webdav.version.report.Report#getType() + */ + public ReportType getType() { + return REGISTERED_NAMESPACES_REPORT; + } + + /** + * Always returns false. + * + * @return false + * @see org.apache.jackrabbit.webdav.version.report.Report#isMultiStatusReport() + */ + public boolean isMultiStatusReport() { + return false; + } + + /** + * @see Report#init(DavResource, ReportInfo) + */ + @Override + public void init(DavResource resource, ReportInfo info) throws DavException { + // delegate validation to abstract super class + super.init(resource, info); + try { + nsReg = getRepositorySession().getWorkspace().getNamespaceRegistry(); + } catch (RepositoryException e) { + throw new DavException(DavServletResponse.SC_INTERNAL_SERVER_ERROR); + } + } + + /** + * Returns a Xml representation of the registered namespace(s). + * + * @return Xml representation of the registered namespace(s) + * error occurs while retrieving the namespaces. + * @see org.apache.jackrabbit.webdav.xml.XmlSerializable#toXml(Document) + * @param document + */ + public Element toXml(Document document) { + Element report = DomUtil.createElement(document, "registerednamespaces-report", NAMESPACE); + try { + for (String prefix : nsReg.getPrefixes()) { + Element elem = DomUtil.addChildElement(report, XML_NAMESPACE, NAMESPACE); + DomUtil.addChildElement(elem, XML_PREFIX, NAMESPACE, prefix); + DomUtil.addChildElement(elem, XML_URI, NAMESPACE, nsReg.getURI(prefix)); + } + } catch (RepositoryException e) { + // should not occur. + log.error(e.getMessage()); + } + return report; + } + +} Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/version/report/RegisteredNamespacesReport.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/webdav/jcr/version/report/RepositoryDescriptorsReport.java =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/version/report/RepositoryDescriptorsReport.java (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/version/report/RepositoryDescriptorsReport.java (working copy) @@ -0,0 +1,128 @@ +/* + * 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.webdav.jcr.version.report; + +import org.apache.jackrabbit.webdav.DavException; +import org.apache.jackrabbit.webdav.DavResource; +import org.apache.jackrabbit.webdav.jcr.ItemResourceConstants; +import org.apache.jackrabbit.webdav.version.report.Report; +import org.apache.jackrabbit.webdav.version.report.ReportInfo; +import org.apache.jackrabbit.webdav.version.report.ReportType; +import org.apache.jackrabbit.webdav.xml.DomUtil; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +import javax.jcr.Repository; +import javax.jcr.Value; +import javax.jcr.RepositoryException; +import javax.jcr.PropertyType; + +/** + * RepositoryDescriptorsReport allows to retrieve the repository + * descriptors. The request body must be an empty 'dcr:repositorydescriptors' element: + *
+ * <!ELEMENT repositorydescriptors EMPTY >
+ * 
+ *
+ * The response body must match the following format + * + *
+ * <!ELEMENT repositorydescriptors-report ( descriptor )* >
+ * <!ELEMENT descriptor ( descriptorkey, descriptorvalue+ ) >
+ * <!ELEMENT descriptorkey (#PCDATA) >
+ * <!ELEMENT descriptorvalue (#PCDATA) >
+ * <!ATTLIST descriptorvalue
+ *      type ( Reference | Path | Name | Boolean | String | Date | Double |
+               Long | Binary | WeakReference | URI | Decimal )
+   >
+ * 
+ * + * @see javax.jcr.Repository#getDescriptorKeys() + * @see javax.jcr.Repository#getDescriptor(String) + * @see javax.jcr.Repository#getDescriptorValue(String) + * @see javax.jcr.Repository#getDescriptorValues(String) + */ +public class RepositoryDescriptorsReport extends AbstractJcrReport implements ItemResourceConstants { + + private static Logger log = LoggerFactory.getLogger(RepositoryDescriptorsReport.class); + + /** + * The registered type of this report. + */ + public static final ReportType REPOSITORY_DESCRIPTORS_REPORT = ReportType.register(REPORT_REPOSITORY_DESCRIPTORS, ItemResourceConstants.NAMESPACE, RepositoryDescriptorsReport.class); + + /** + * Returns {@link #REPOSITORY_DESCRIPTORS_REPORT} type. + * @return {@link #REPOSITORY_DESCRIPTORS_REPORT} + * @see org.apache.jackrabbit.webdav.version.report.Report#getType() + */ + public ReportType getType() { + return REPOSITORY_DESCRIPTORS_REPORT; + } + + /** + * Always returns false. + * + * @return false + * @see org.apache.jackrabbit.webdav.version.report.Report#isMultiStatusReport() + */ + public boolean isMultiStatusReport() { + return false; + } + + /** + * @see Report#init(DavResource, ReportInfo) + */ + @Override + public void init(DavResource resource, ReportInfo info) throws DavException { + // delegate validation to abstract super class + super.init(resource, info); + } + + /** + * Returns a Xml representation of the repository descriptors according + * to the info object. + * + * @return Xml representation of the repository descriptors + * @see org.apache.jackrabbit.webdav.xml.XmlSerializable#toXml(Document) + * @param document + */ + public Element toXml(Document document) { + Repository repository = getRepositorySession().getRepository(); + Element report = DomUtil.createElement(document, "repositorydescriptors-report", NAMESPACE); + for (String key : repository.getDescriptorKeys()) { + Element elem = DomUtil.addChildElement(report, XML_DESCRIPTOR, NAMESPACE); + DomUtil.addChildElement(elem, XML_DESCRIPTORKEY, NAMESPACE, key); + for (Value v : repository.getDescriptorValues(key)) { + String value; + try { + value = v.getString(); + } catch (RepositoryException e) { + log.error("Internal error while reading descriptor value: ", e); + value = repository.getDescriptor(key); + } + Element child = DomUtil.addChildElement(elem, XML_DESCRIPTORVALUE, NAMESPACE, value); + if (PropertyType.STRING != v.getType()) { + child.setAttribute(ATTR_VALUE_TYPE, PropertyType.nameFromValue(v.getType())); + } + } + } + return report; + } +} Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/version/report/RepositoryDescriptorsReport.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/webdav/simple/DavResourceImpl.java =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/simple/DavResourceImpl.java (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/simple/DavResourceImpl.java (working copy) @@ -0,0 +1,1128 @@ +/* + * 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.webdav.simple; + +import org.apache.jackrabbit.JcrConstants; +import org.apache.jackrabbit.server.io.AbstractExportContext; +import org.apache.jackrabbit.server.io.CopyMoveContextImpl; +import org.apache.jackrabbit.server.io.DefaultIOListener; +import org.apache.jackrabbit.server.io.DeleteContextImpl; +import org.apache.jackrabbit.server.io.DeleteManager; +import org.apache.jackrabbit.server.io.ExportContext; +import org.apache.jackrabbit.server.io.ExportContextImpl; +import org.apache.jackrabbit.server.io.IOListener; +import org.apache.jackrabbit.server.io.IOManager; +import org.apache.jackrabbit.server.io.IOUtil; +import org.apache.jackrabbit.server.io.ImportContext; +import org.apache.jackrabbit.server.io.ImportContextImpl; +import org.apache.jackrabbit.server.io.PropertyExportContext; +import org.apache.jackrabbit.server.io.PropertyImportContext; +import org.apache.jackrabbit.util.Text; +import org.apache.jackrabbit.webdav.DavCompliance; +import org.apache.jackrabbit.webdav.DavException; +import org.apache.jackrabbit.webdav.DavResource; +import org.apache.jackrabbit.webdav.DavResourceFactory; +import org.apache.jackrabbit.webdav.DavResourceIterator; +import org.apache.jackrabbit.webdav.DavResourceIteratorImpl; +import org.apache.jackrabbit.webdav.DavResourceLocator; +import org.apache.jackrabbit.webdav.DavServletResponse; +import org.apache.jackrabbit.webdav.DavSession; +import org.apache.jackrabbit.webdav.MultiStatusResponse; +import org.apache.jackrabbit.webdav.bind.BindConstants; +import org.apache.jackrabbit.webdav.bind.BindableResource; +import org.apache.jackrabbit.webdav.bind.ParentElement; +import org.apache.jackrabbit.webdav.bind.ParentSet; +import org.apache.jackrabbit.webdav.io.InputContext; +import org.apache.jackrabbit.webdav.io.OutputContext; +import org.apache.jackrabbit.webdav.jcr.JcrDavException; +import org.apache.jackrabbit.webdav.jcr.JcrDavSession; +import org.apache.jackrabbit.webdav.jcr.lock.JcrActiveLock; +import org.apache.jackrabbit.webdav.lock.ActiveLock; +import org.apache.jackrabbit.webdav.lock.LockDiscovery; +import org.apache.jackrabbit.webdav.lock.LockInfo; +import org.apache.jackrabbit.webdav.lock.LockManager; +import org.apache.jackrabbit.webdav.lock.Scope; +import org.apache.jackrabbit.webdav.lock.SupportedLock; +import org.apache.jackrabbit.webdav.lock.Type; +import org.apache.jackrabbit.webdav.property.DavProperty; +import org.apache.jackrabbit.webdav.property.DavPropertyName; +import org.apache.jackrabbit.webdav.property.DavPropertySet; +import org.apache.jackrabbit.webdav.property.DefaultDavProperty; +import org.apache.jackrabbit.webdav.property.HrefProperty; +import org.apache.jackrabbit.webdav.property.ResourceType; +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.RepositoryException; +import javax.jcr.Session; +import javax.jcr.UnsupportedRepositoryOperationException; +import javax.jcr.Workspace; +import javax.jcr.lock.Lock; +import java.io.IOException; +import java.io.OutputStream; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Date; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.UUID; + +/** + * DavResourceImpl implements a DavResource. + */ +public class DavResourceImpl implements DavResource, BindableResource, JcrConstants { + + /** + * the default logger + */ + private static final Logger log = LoggerFactory.getLogger(DavResourceImpl.class); + + public static final String METHODS = DavResource.METHODS + ", " + BindConstants.METHODS; + + public static final String COMPLIANCE_CLASSES = DavCompliance.concatComplianceClasses( + new String[] { + DavCompliance._1_, + DavCompliance._2_, + DavCompliance._3_, + DavCompliance.BIND + } + ); + + private DavResourceFactory factory; + private LockManager lockManager; + private JcrDavSession session; + private Node node; + private DavResourceLocator locator; + + protected DavPropertySet properties = new DavPropertySet(); + protected boolean propsInitialized = false; + private boolean isCollection = true; + private String rfc4122Uri; + + private ResourceConfig config; + private long modificationTime = IOUtil.UNDEFINED_TIME; + + /** + * Create a new {@link DavResource}. + * + * @param locator + * @param factory + * @param session + * @param config + * @param isCollection + * @throws DavException + */ + public DavResourceImpl(DavResourceLocator locator, DavResourceFactory factory, + DavSession session, ResourceConfig config, + boolean isCollection) throws DavException { + this(locator, factory, session, config, null); + this.isCollection = isCollection; + } + + /** + * Create a new {@link DavResource}. + * + * @param locator + * @param factory + * @param session + * @param config + * @param node + * @throws DavException + */ + public DavResourceImpl(DavResourceLocator locator, DavResourceFactory factory, + DavSession session, ResourceConfig config, Node node) throws DavException { + if (locator == null || session == null || config == null) { + throw new IllegalArgumentException(); + } + JcrDavSession.checkImplementation(session); + this.session = (JcrDavSession)session; + this.factory = factory; + this.locator = locator; + this.config = config; + + if (locator.getResourcePath() != null) { + if (node != null) { + this.node = node; + // define what is a collection in webdav + isCollection = config.isCollectionResource(node); + initRfc4122Uri(); + } + } else { + throw new DavException(DavServletResponse.SC_NOT_FOUND); + } + } + + /** + * If the Node associated with this DavResource has a UUID that allows for the creation of a rfc4122 compliant + * URI, we use it as the value of the protected DAV property DAV:resource-id, which is defined by the BIND + * specification. + */ + private void initRfc4122Uri() { + try { + if (node.isNodeType(MIX_REFERENCEABLE)) { + String uuid = node.getUUID(); + try { + UUID.fromString(uuid); + rfc4122Uri = "urn:uuid:" + uuid; + } catch (IllegalArgumentException e) { + //no, this is not a UUID + } + } + } catch (RepositoryException e) { + log.warn("Error while detecting UUID", e); + } + } + + /** + * @see org.apache.jackrabbit.webdav.DavResource#getComplianceClass() + */ + public String getComplianceClass() { + return COMPLIANCE_CLASSES; + } + + /** + * @return DavResource#METHODS + * @see org.apache.jackrabbit.webdav.DavResource#getSupportedMethods() + */ + public String getSupportedMethods() { + return METHODS; + } + + /** + * @see DavResource#exists() ) + */ + public boolean exists() { + return node != null; + } + + /** + * @see DavResource#isCollection() + */ + public boolean isCollection() { + return isCollection; + } + + /** + * @see org.apache.jackrabbit.webdav.DavResource#getLocator() + */ + public DavResourceLocator getLocator() { + return locator; + } + + /** + * @see DavResource#getResourcePath() + */ + public String getResourcePath() { + return locator.getResourcePath(); + } + + /** + * @see DavResource#getHref() + */ + public String getHref() { + return locator.getHref(isCollection()); + } + + /** + * Returns the the last segment of the resource path.

+ * Note that this must not correspond to the name of the underlying + * repository item for two reasons:

    + *
  • SameNameSiblings have an index appended to their item name.
  • + *
  • the resource path may differ from the item path.
  • + *
+ * Using the item name as DAV:displayname caused problems with XP built-in + * client in case of resources representing SameNameSibling nodes. + * + * @see DavResource#getDisplayName() + */ + public String getDisplayName() { + String resPath = getResourcePath(); + return (resPath != null) ? Text.getName(resPath) : resPath; + } + + /** + * @see org.apache.jackrabbit.webdav.DavResource#getModificationTime() + */ + public long getModificationTime() { + initProperties(); + return modificationTime; + } + + /** + * If this resource exists and the specified context is not null + * this implementation build a new {@link ExportContext} based on the specified + * context and forwards the export to its IOManager. If the + * {@link IOManager#exportContent(ExportContext, DavResource)} fails, + * an IOException is thrown. + * + * @see DavResource#spool(OutputContext) + * @see ResourceConfig#getIOManager() + * @throws IOException if the export fails. + */ + public void spool(OutputContext outputContext) throws IOException { + if (exists() && outputContext != null) { + ExportContext exportCtx = getExportContext(outputContext); + if (!config.getIOManager().exportContent(exportCtx, this)) { + throw new IOException("Unexpected Error while spooling resource."); + } + } + } + + /** + * @see DavResource#getProperty(org.apache.jackrabbit.webdav.property.DavPropertyName) + */ + public DavProperty getProperty(DavPropertyName name) { + initProperties(); + return properties.get(name); + } + + /** + * @see DavResource#getProperties() + */ + public DavPropertySet getProperties() { + initProperties(); + return properties; + } + + /** + * @see DavResource#getPropertyNames() + */ + public DavPropertyName[] getPropertyNames() { + return getProperties().getPropertyNames(); + } + + /** + * Fill the set of properties + */ + protected void initProperties() { + if (!exists() || propsInitialized) { + return; + } + + try { + config.getPropertyManager().exportProperties(getPropertyExportContext(), isCollection()); + } catch (RepositoryException e) { + log.warn("Error while accessing resource properties", e); + } + + // set (or reset) fundamental properties + if (getDisplayName() != null) { + properties.add(new DefaultDavProperty(DavPropertyName.DISPLAYNAME, getDisplayName())); + } + if (isCollection()) { + properties.add(new ResourceType(ResourceType.COLLECTION)); + // Windows XP support + properties.add(new DefaultDavProperty(DavPropertyName.ISCOLLECTION, "1")); + } else { + properties.add(new ResourceType(ResourceType.DEFAULT_RESOURCE)); + // Windows XP support + properties.add(new DefaultDavProperty(DavPropertyName.ISCOLLECTION, "0")); + } + + if (rfc4122Uri != null) { + properties.add(new HrefProperty(BindConstants.RESOURCEID, rfc4122Uri, true)); + } + + Set parentElements = getParentElements(); + if (!parentElements.isEmpty()) { + properties.add(new ParentSet(parentElements)); + } + + /* set current lock information. If no lock is set to this resource, + an empty lock discovery will be returned in the response. */ + properties.add(new LockDiscovery(getLock(Type.WRITE, Scope.EXCLUSIVE))); + + /* lock support information: all locks are lockable. */ + SupportedLock supportedLock = new SupportedLock(); + supportedLock.addEntry(Type.WRITE, Scope.EXCLUSIVE); + properties.add(supportedLock); + + propsInitialized = true; + } + + /** + * @param property + * @throws DavException + * @see DavResource#setProperty(org.apache.jackrabbit.webdav.property.DavProperty) + */ + public void setProperty(DavProperty property) throws DavException { + alterProperty(property); + } + + /** + * @param propertyName + * @throws DavException + * @see DavResource#removeProperty(org.apache.jackrabbit.webdav.property.DavPropertyName) + */ + public void removeProperty(DavPropertyName propertyName) throws DavException { + alterProperty(propertyName); + } + + private void alterProperty(PropEntry prop) throws DavException { + if (isLocked(this)) { + throw new DavException(DavServletResponse.SC_LOCKED); + } + if (!exists()) { + throw new DavException(DavServletResponse.SC_NOT_FOUND); + } + try { + List list = Collections.singletonList(prop); + alterProperties(list); + Map failure = config.getPropertyManager().alterProperties(getPropertyImportContext(list), isCollection()); + if (failure.isEmpty()) { + node.save(); + } else { + node.refresh(false); + // TODO: retrieve specific error from failure-map + throw new DavException(DavServletResponse.SC_INTERNAL_SERVER_ERROR); + } + } catch (RepositoryException e) { + // revert any changes made so far + JcrDavException je = new JcrDavException(e); + try { + node.refresh(false); + } catch (RepositoryException re) { + // should not happen... + } + throw je; + } + } + + public MultiStatusResponse alterProperties(List changeList) throws DavException { + if (isLocked(this)) { + throw new DavException(DavServletResponse.SC_LOCKED); + } + if (!exists()) { + throw new DavException(DavServletResponse.SC_NOT_FOUND); + } + MultiStatusResponse msr = new MultiStatusResponse(getHref(), null); + try { + Map failures = config.getPropertyManager().alterProperties(getPropertyImportContext(changeList), isCollection()); + if (failures.isEmpty()) { + // save all changes together (reverted in case this fails) + node.save(); + } else { + // set/remove of at least a single prop failed: undo modifications. + node.refresh(false); + } + /* loop over list of properties/names that were successfully altered + and them to the multistatus response respecting the result of the + complete action. in case of failure set the status to 'failed-dependency' + in order to indicate, that altering those names/properties would + have succeeded, if no other error occured.*/ + for (PropEntry propEntry : changeList) { + int statusCode; + if (failures.containsKey(propEntry)) { + Object error = failures.get(propEntry); + statusCode = (error instanceof RepositoryException) + ? new JcrDavException((RepositoryException) error).getErrorCode() + : DavServletResponse.SC_INTERNAL_SERVER_ERROR; + } else { + statusCode = (failures.isEmpty()) ? DavServletResponse.SC_OK : DavServletResponse.SC_FAILED_DEPENDENCY; + } + if (propEntry instanceof DavProperty) { + msr.add(((DavProperty) propEntry).getName(), statusCode); + } else { + msr.add((DavPropertyName) propEntry, statusCode); + } + } + return msr; + } catch (RepositoryException e) { + // revert any changes made so far an throw exception + try { + node.refresh(false); + } catch (RepositoryException re) { + // should not happen + } + throw new JcrDavException(e); + } + } + + /** + * @see DavResource#getCollection() + */ + public DavResource getCollection() { + DavResource parent = null; + if (getResourcePath() != null && !getResourcePath().equals("/")) { + String parentPath = Text.getRelativeParent(getResourcePath(), 1); + if (parentPath.equals("")) { + parentPath = "/"; + } + DavResourceLocator parentloc = locator.getFactory().createResourceLocator(locator.getPrefix(), locator.getWorkspacePath(), parentPath); + try { + parent = factory.createResource(parentloc, session); + } catch (DavException e) { + // should not occur + } + } + return parent; + } + + /** + * @see DavResource#getMembers() + */ + public DavResourceIterator getMembers() { + ArrayList list = new ArrayList(); + if (exists() && isCollection()) { + try { + NodeIterator it = node.getNodes(); + while (it.hasNext()) { + Node n = it.nextNode(); + if (!isFilteredItem(n)) { + DavResourceLocator resourceLocator = locator.getFactory().createResourceLocator(locator.getPrefix(), locator.getWorkspacePath(), n.getPath(), false); + DavResource childRes = factory.createResource(resourceLocator, session); + list.add(childRes); + } else { + log.debug("Filtered resource '" + n.getName() + "'."); + } + } + } catch (RepositoryException e) { + // should not occur + } catch (DavException e) { + // should not occur + } + } + return new DavResourceIteratorImpl(list); + } + + /** + * Adds a new member to this resource. + * + * @see DavResource#addMember(DavResource, org.apache.jackrabbit.webdav.io.InputContext) + */ + public void addMember(DavResource member, InputContext inputContext) throws DavException { + if (!exists()) { + throw new DavException(DavServletResponse.SC_CONFLICT); + } + if (isLocked(this) || isLocked(member)) { + throw new DavException(DavServletResponse.SC_LOCKED); + } + try { + // don't allow creation of nodes if this resource represents a protected + // item or if the new resource would be filtered out + if (isFilteredResource(member) || node.getDefinition().isProtected()) { + log.debug("Forbidden to add member: " + member.getDisplayName()); + throw new DavException(DavServletResponse.SC_FORBIDDEN); + } + + String memberName = Text.getName(member.getLocator().getRepositoryPath()); + ImportContext ctx = getImportContext(inputContext, memberName); + if (!config.getIOManager().importContent(ctx, member)) { + // any changes should have been reverted in the importer + throw new DavException(DavServletResponse.SC_UNSUPPORTED_MEDIA_TYPE); + } + // persist changes after successful import + node.save(); + } catch (RepositoryException e) { + log.error("Error while importing resource: " + e.toString()); + throw new JcrDavException(e); + } catch (IOException e) { + log.error("Error while importing resource: " + e.toString()); + throw new DavException(DavServletResponse.SC_INTERNAL_SERVER_ERROR, e.getMessage()); + } + } + + /** + * @see DavResource#removeMember(DavResource) + */ + public void removeMember(DavResource member) throws DavException { + if (!exists() || !member.exists()) { + throw new DavException(DavServletResponse.SC_NOT_FOUND); + } + if (isLocked(this) || isLocked(member)) { + throw new DavException(DavServletResponse.SC_LOCKED); + } + + // don't allow removal of nodes, that would be filtered out + if (isFilteredResource(member)) { + log.debug("Avoid removal of filtered resource: " + member.getDisplayName()); + throw new DavException(DavServletResponse.SC_FORBIDDEN); + } + + DeleteManager dm = config.getDeleteManager(); + dm.delete(new DeleteContextImpl(getJcrSession()), member); + + // make sure, non-jcr locks are removed, once the removal is completed + try { + if (!isJcrLockable()) { + ActiveLock lock = getLock(Type.WRITE, Scope.EXCLUSIVE); + if (lock != null) { + lockManager.releaseLock(lock.getToken(), member); + } + } + } catch (DavException e) { + // since check for 'locked' exception has been performed before + // ignore any error here + } + } + + /** + * @see DavResource#move(DavResource) + */ + public void move(DavResource destination) throws DavException { + if (!exists()) { + throw new DavException(DavServletResponse.SC_NOT_FOUND); + } + if (isLocked(this)) { + throw new DavException(DavServletResponse.SC_LOCKED); + } + if (isFilteredResource(destination)) { + throw new DavException(DavServletResponse.SC_FORBIDDEN); + } + // make sure, that src and destination belong to the same workspace + checkSameWorkspace(destination.getLocator()); + if (!config.getCopyMoveManager().move(new CopyMoveContextImpl(getJcrSession()), this, destination)) { + throw new DavException(DavServletResponse.SC_UNSUPPORTED_MEDIA_TYPE); + } + } + + /** + * @see DavResource#copy(DavResource, boolean) + */ + public void copy(DavResource destination, boolean shallow) throws DavException { + if (!exists()) { + throw new DavException(DavServletResponse.SC_NOT_FOUND); + } + if (isLocked(destination)) { + throw new DavException(DavServletResponse.SC_LOCKED); + } + if (isFilteredResource(destination)) { + throw new DavException(DavServletResponse.SC_FORBIDDEN); + } + // make sure, that src and destination belong to the same workspace + checkSameWorkspace(destination.getLocator()); + if (!config.getCopyMoveManager().copy(new CopyMoveContextImpl(getJcrSession(), shallow), this, destination)) { + throw new DavException(DavServletResponse.SC_UNSUPPORTED_MEDIA_TYPE); + } + } + + /** + * @param type + * @param scope + * @return true if type is {@link Type#WRITE} and scope is {@link Scope#EXCLUSIVE} + * @see DavResource#isLockable(org.apache.jackrabbit.webdav.lock.Type, org.apache.jackrabbit.webdav.lock.Scope) + */ + public boolean isLockable(Type type, Scope scope) { + return Type.WRITE.equals(type) && Scope.EXCLUSIVE.equals(scope); + } + + /** + * @see DavResource#hasLock(org.apache.jackrabbit.webdav.lock.Type, org.apache.jackrabbit.webdav.lock.Scope) + */ + public boolean hasLock(Type type, Scope scope) { + return getLock(type, scope) != null; + } + + /** + * @see DavResource#getLock(Type, Scope) + */ + public ActiveLock getLock(Type type, Scope scope) { + ActiveLock lock = null; + if (exists() && Type.WRITE.equals(type) && Scope.EXCLUSIVE.equals(scope)) { + // try to retrieve the repository lock information first + try { + if (node.isLocked()) { + Lock jcrLock = node.getLock(); + if (jcrLock != null && jcrLock.isLive()) { + lock = new JcrActiveLock(jcrLock); + String lockroot = locator + .getFactory() + .createResourceLocator(locator.getPrefix(), locator.getWorkspacePath(), + jcrLock.getNode().getPath(), false).getHref(false); + lock.setLockroot(lockroot); + } + } + } catch (RepositoryException e) { + // LockException (no lock applies) >> should never occur + // RepositoryException, AccessDeniedException or another error >> ignore + } + + // could not retrieve a jcr-lock. test if a simple webdav lock is present. + if (lock == null) { + lock = lockManager.getLock(type, scope, this); + } + } + return lock; + } + + /** + * @see org.apache.jackrabbit.webdav.DavResource#getLocks() + */ + public ActiveLock[] getLocks() { + ActiveLock writeLock = getLock(Type.WRITE, Scope.EXCLUSIVE); + return (writeLock != null) ? new ActiveLock[]{writeLock} : new ActiveLock[0]; + } + + /** + * @see DavResource#lock(LockInfo) + */ + public ActiveLock lock(LockInfo lockInfo) throws DavException { + ActiveLock lock = null; + if (isLockable(lockInfo.getType(), lockInfo.getScope())) { + // TODO: deal with existing locks, that may have been created, before the node was jcr-lockable... + if (isJcrLockable()) { + try { + javax.jcr.lock.LockManager lockMgr = node.getSession().getWorkspace().getLockManager(); + long timeout = lockInfo.getTimeout(); + if (timeout == LockInfo.INFINITE_TIMEOUT) { + timeout = Long.MAX_VALUE; + } else { + timeout = timeout / 1000; + } + // try to execute the lock operation + Lock jcrLock = lockMgr.lock(node.getPath(), lockInfo.isDeep(), false, timeout, lockInfo.getOwner()); + if (jcrLock != null) { + lock = new JcrActiveLock(jcrLock); + } + } catch (RepositoryException e) { + throw new JcrDavException(e); + } + } else { + // create a new webdav lock + lock = lockManager.createLock(lockInfo, this); + } + } else { + throw new DavException(DavServletResponse.SC_PRECONDITION_FAILED, "Unsupported lock type or scope."); + } + return lock; + } + + /** + * @see DavResource#refreshLock(LockInfo, String) + */ + public ActiveLock refreshLock(LockInfo lockInfo, String lockToken) throws DavException { + if (!exists()) { + throw new DavException(DavServletResponse.SC_NOT_FOUND); + } + ActiveLock lock = getLock(lockInfo.getType(), lockInfo.getScope()); + if (lock == null) { + throw new DavException(DavServletResponse.SC_PRECONDITION_FAILED, "No lock with the given type/scope present on resource " + getResourcePath()); + } + + if (lock instanceof JcrActiveLock) { + try { + // refresh JCR lock and return the original lock object. + node.getLock().refresh(); + } catch (RepositoryException e) { + throw new JcrDavException(e); + } + } else { + lock = lockManager.refreshLock(lockInfo, lockToken, this); + } + /* since lock has infinite lock (simple) or undefined timeout (jcr) + return the lock as retrieved from getLock. */ + return lock; + } + + /** + * @see DavResource#unlock(String) + */ + public void unlock(String lockToken) throws DavException { + ActiveLock lock = getLock(Type.WRITE, Scope.EXCLUSIVE); + if (lock == null) { + throw new DavException(DavServletResponse.SC_PRECONDITION_FAILED); + } else if (lock.isLockedByToken(lockToken)) { + if (lock instanceof JcrActiveLock) { + try { + node.unlock(); + } catch (RepositoryException e) { + throw new JcrDavException(e); + } + } else { + lockManager.releaseLock(lockToken, this); + } + } else { + throw new DavException(DavServletResponse.SC_LOCKED); + } + } + + /** + * @see DavResource#addLockManager(org.apache.jackrabbit.webdav.lock.LockManager) + */ + public void addLockManager(LockManager lockMgr) { + this.lockManager = lockMgr; + } + + /** + * @see org.apache.jackrabbit.webdav.DavResource#getFactory() + */ + public DavResourceFactory getFactory() { + return factory; + } + + /** + * @see org.apache.jackrabbit.webdav.DavResource#getSession() + */ + public DavSession getSession() { + return session; + } + + + /** + * @see BindableResource#rebind(DavResource, DavResource) + */ + public void bind(DavResource collection, DavResource newBinding) throws DavException { + if (!exists()) { + //DAV:bind-source-exists + throw new DavException(DavServletResponse.SC_PRECONDITION_FAILED); + } + if (isLocked(collection)) { + //DAV:locked-update-allowed? + throw new DavException(DavServletResponse.SC_LOCKED); + } + if (isFilteredResource(newBinding)) { + throw new DavException(DavServletResponse.SC_FORBIDDEN); + } + checkSameWorkspace(collection.getLocator()); + try { + if (!node.isNodeType(MIX_SHAREABLE)) { + if (!node.canAddMixin(MIX_SHAREABLE)) { + //DAV:binding-allowed + throw new DavException(DavServletResponse.SC_PRECONDITION_FAILED); + } + node.addMixin(MIX_SHAREABLE); + node.save(); + } + Workspace workspace = session.getRepositorySession().getWorkspace(); + workspace.clone(workspace.getName(), node.getPath(), newBinding.getLocator().getRepositoryPath(), false); + + } catch (RepositoryException e) { + throw new JcrDavException(e); + } + + } + + /** + * @see BindableResource#rebind(DavResource, DavResource) + */ + public void rebind(DavResource collection, DavResource newBinding) throws DavException { + if (!exists()) { + //DAV:rebind-source-exists + throw new DavException(DavServletResponse.SC_PRECONDITION_FAILED); + } + if (isLocked(this)) { + //DAV:protected-source-url-deletion.allowed + throw new DavException(DavServletResponse.SC_PRECONDITION_FAILED); + } + if (isLocked(collection)) { + //DAV:locked-update-allowed? + throw new DavException(DavServletResponse.SC_LOCKED); + } + if (isFilteredResource(newBinding)) { + throw new DavException(DavServletResponse.SC_FORBIDDEN); + } + checkSameWorkspace(collection.getLocator()); + try { + if (!node.isNodeType(MIX_REFERENCEABLE)) { + throw new DavException(node.canAddMixin(MIX_REFERENCEABLE)? + DavServletResponse.SC_CONFLICT : DavServletResponse.SC_METHOD_NOT_ALLOWED); + } + getJcrSession().getWorkspace().move(locator.getRepositoryPath(), newBinding.getLocator().getRepositoryPath()); + } catch (RepositoryException e) { + throw new JcrDavException(e); + } + } + + /** + * @see org.apache.jackrabbit.webdav.bind.BindableResource#getParentElements() + */ + public Set getParentElements() { + try { + if (node.getDepth() > 0) { + Set ps = new HashSet(); + NodeIterator sharedSetIterator = node.getSharedSet(); + while (sharedSetIterator.hasNext()) { + Node sharednode = sharedSetIterator.nextNode(); + DavResourceLocator loc = locator.getFactory().createResourceLocator( + locator.getPrefix(), locator.getWorkspacePath(), sharednode.getParent().getPath(), false); + ps.add(new ParentElement(loc.getHref(true), sharednode.getName())); + } + return ps; + } + } catch (UnsupportedRepositoryOperationException e) { + log.debug("unable to calculate parent set", e); + } catch (RepositoryException e) { + log.warn("unable to calculate parent set", e); + } + return Collections.emptySet(); + } + + /** + * Returns the node that is wrapped by this resource. + * + * @return The underlying JCR node instance. + */ + protected Node getNode() { + return node; + } + + /** + * Returns a new ImportContext + * + * @param inputCtx + * @param systemId + * @return a new ImportContext + * @throws IOException + */ + protected ImportContext getImportContext(InputContext inputCtx, String systemId) throws IOException { + return new ImportContextImpl( + node, systemId, inputCtx, + (inputCtx != null) ? inputCtx.getInputStream() : null, + new DefaultIOListener(log), config.getDetector()); + } + + /** + * Returns a new ExportContext + * + * @param outputCtx + * @return a new ExportContext + * @throws IOException + */ + protected ExportContext getExportContext(OutputContext outputCtx) throws IOException { + return new ExportContextImpl(node, outputCtx); + } + + /** + * Returns a new PropertyImportContext. + * + * @param changeList + * @return a new PropertyImportContext. + */ + protected PropertyImportContext getPropertyImportContext(List changeList) { + return new PropertyImportCtx(changeList); + } + + /** + * Returns a new PropertyExportContext. + * + * @return a new PropertyExportContext + */ + protected PropertyExportContext getPropertyExportContext() { + return new PropertyExportCtx(); + } + + /** + * Returns true, if the underlying node is nodetype jcr:lockable, + * without checking its current lock status. If the node is not jcr-lockable + * an attempt is made to add the mix:lockable mixin type. + * + * @return true if this resource is lockable. + */ + private boolean isJcrLockable() { + boolean lockable = false; + if (exists()) { + try { + lockable = node.isNodeType(MIX_LOCKABLE); + // not jcr-lockable: try to make the node jcr-lockable + if (!lockable && node.canAddMixin(MIX_LOCKABLE)) { + node.addMixin(MIX_LOCKABLE); + node.save(); + lockable = true; + } + } catch (RepositoryException e) { + // -> node is definitely not jcr-lockable. + } + } + return lockable; + } + + /** + * Return true if this resource cannot be modified due to a write lock + * that is not owned by the given session. + * + * @return true if this resource cannot be modified due to a write lock + */ + private boolean isLocked(DavResource res) { + ActiveLock lock = res.getLock(Type.WRITE, Scope.EXCLUSIVE); + if (lock == null) { + return false; + } else { + for (String sLockToken : session.getLockTokens()) { + if (sLockToken.equals(lock.getToken())) { + return false; + } + } + return true; + } + } + + private Session getJcrSession() { + return session.getRepositorySession(); + } + + private boolean isFilteredResource(DavResource resource) { + // TODO: filtered nodetypes should be checked as well in order to prevent problems. + ItemFilter filter = config.getItemFilter(); + return filter != null && filter.isFilteredItem(resource.getDisplayName(), getJcrSession()); + } + + private boolean isFilteredItem(Item item) { + ItemFilter filter = config.getItemFilter(); + return filter != null && filter.isFilteredItem(item); + } + + private void checkSameWorkspace(DavResourceLocator otherLoc) throws DavException { + String wspname = getJcrSession().getWorkspace().getName(); + if (!wspname.equals(otherLoc.getWorkspaceName())) { + throw new DavException(DavServletResponse.SC_FORBIDDEN, "Workspace mismatch: expected '" + wspname + "'; found: '" + otherLoc.getWorkspaceName() + "'"); + } + } + + //--------------------------------------------------------< inner class >--- + /** + * ExportContext that writes the properties of this DavResource + * and provides not stream. + */ + private class PropertyExportCtx extends AbstractExportContext implements PropertyExportContext { + + private PropertyExportCtx() { + super(node, false, null); + // set defaults: + setCreationTime(IOUtil.UNDEFINED_TIME); + setModificationTime(IOUtil.UNDEFINED_TIME); + } + + public OutputStream getOutputStream() { + return null; + } + + public void setContentLanguage(String contentLanguage) { + if (contentLanguage != null) { + properties.add(new DefaultDavProperty(DavPropertyName.GETCONTENTLANGUAGE, contentLanguage)); + } + } + + public void setContentLength(long contentLength) { + if (contentLength > IOUtil.UNDEFINED_LENGTH) { + properties.add(new DefaultDavProperty(DavPropertyName.GETCONTENTLENGTH, contentLength + "")); + } + } + + public void setContentType(String mimeType, String encoding) { + String contentType = IOUtil.buildContentType(mimeType, encoding); + if (contentType != null) { + properties.add(new DefaultDavProperty(DavPropertyName.GETCONTENTTYPE, contentType)); + } + } + + public void setCreationTime(long creationTime) { + String created = IOUtil.getCreated(creationTime); + properties.add(new DefaultDavProperty(DavPropertyName.CREATIONDATE, created)); + } + + public void setModificationTime(long modTime) { + if (modTime <= IOUtil.UNDEFINED_TIME) { + modificationTime = new Date().getTime(); + } else { + modificationTime = modTime; + } + String lastModified = IOUtil.getLastModified(modificationTime); + properties.add(new DefaultDavProperty(DavPropertyName.GETLASTMODIFIED, lastModified)); + } + + public void setETag(String etag) { + if (etag != null) { + properties.add(new DefaultDavProperty(DavPropertyName.GETETAG, etag)); + } + } + + public void setProperty(Object propertyName, Object propertyValue) { + if (propertyValue == null) { + log.warn("Ignore 'setProperty' for " + propertyName + "with null value."); + return; + } + + if (propertyValue instanceof DavProperty) { + properties.add((DavProperty)propertyValue); + } else { + DavPropertyName pName; + if (propertyName instanceof DavPropertyName) { + pName = (DavPropertyName)propertyName; + } else { + // create property name with default DAV: namespace + pName = DavPropertyName.create(propertyName.toString()); + } + properties.add(new DefaultDavProperty(pName, propertyValue)); + } + } + } + + private class PropertyImportCtx implements PropertyImportContext { + + private final IOListener ioListener = new DefaultIOListener(log); + private final List changeList; + private boolean completed; + + private PropertyImportCtx(List changeList) { + this.changeList = changeList; + } + + /** + * @see PropertyImportContext#getImportRoot() + */ + public Item getImportRoot() { + return node; + } + + /** + * @see PropertyImportContext#getChangeList() + */ + public List getChangeList() { + return Collections.unmodifiableList(changeList); + } + + public IOListener getIOListener() { + return ioListener; + } + + public boolean hasStream() { + return false; + } + + /** + * @see PropertyImportContext#informCompleted(boolean) + */ + public void informCompleted(boolean success) { + checkCompleted(); + completed = true; + } + + /** + * @see PropertyImportContext#isCompleted() + */ + public boolean isCompleted() { + return completed; + } + + /** + * @throws IllegalStateException if the context is already completed. + * @see #isCompleted() + * @see #informCompleted(boolean) + */ + private void checkCompleted() { + if (completed) { + throw new IllegalStateException("PropertyImportContext has already been consumed."); + } + } + } +} Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/simple/DavResourceImpl.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/webdav/simple/DavSessionImpl.java =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/simple/DavSessionImpl.java (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/simple/DavSessionImpl.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.webdav.simple; + +import org.apache.jackrabbit.webdav.DavSession; +import org.apache.jackrabbit.webdav.jcr.JcrDavSession; + +import javax.jcr.Session; +import java.util.HashSet; + +/** + * Simple implementation of the {@link DavSession} interface. Stores + * lock tokens but does not yet store references. + */ +public class DavSessionImpl extends JcrDavSession { + + /** the lock tokens of this session */ + private final HashSet lockTokens = new HashSet(); + + /** + * Creates a new DavSession based on a jcr session + * @param session + */ + public DavSessionImpl(Session session) { + super(session); + } + + /** + * @see DavSession#addReference(Object) + */ + public void addReference(Object reference) { + throw new UnsupportedOperationException("No yet implemented."); + } + + /** + * @see DavSession#removeReference(Object) + */ + public void removeReference(Object reference) { + throw new UnsupportedOperationException("No yet implemented."); + } + + /** + * @see DavSession#addLockToken(String) + */ + @Override + public void addLockToken(String token) { + super.addLockToken(token); + lockTokens.add(token); + } + + /** + * @see DavSession#getLockTokens() + */ + @Override + public String[] getLockTokens() { + return lockTokens.toArray(new String[lockTokens.size()]); + } + + /** + * @see DavSession#removeLockToken(String) + */ + @Override + public void removeLockToken(String token) { + super.removeLockToken(token); + lockTokens.remove(token); + } +} Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/simple/DavSessionImpl.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/webdav/simple/DavSessionProviderImpl.java =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/simple/DavSessionProviderImpl.java (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/simple/DavSessionProviderImpl.java (working copy) @@ -0,0 +1,127 @@ +/* + * 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.webdav.simple; + +import org.apache.jackrabbit.server.CredentialsProvider; +import org.apache.jackrabbit.server.SessionProvider; +import org.apache.jackrabbit.webdav.DavException; +import org.apache.jackrabbit.webdav.DavServletResponse; +import org.apache.jackrabbit.webdav.DavSession; +import org.apache.jackrabbit.webdav.DavSessionProvider; +import org.apache.jackrabbit.webdav.WebdavRequest; +import org.apache.jackrabbit.webdav.jcr.JcrDavException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.jcr.NoSuchWorkspaceException; +import javax.jcr.Repository; +import javax.jcr.RepositoryException; +import javax.jcr.Session; +import javax.servlet.ServletException; + +/** + * Simple implementation of the {@link org.apache.jackrabbit.webdav.DavSessionProvider} + * interface that uses a {@link CredentialsProvider} to locate + * credentials in the request, log into the respository, and provide + * a {@link org.apache.jackrabbit.webdav.DavSession} to the request. + */ +public class DavSessionProviderImpl implements DavSessionProvider { + + private static Logger log = LoggerFactory.getLogger(DavSessionProviderImpl.class); + + /** + * the repository + */ + private final Repository repository; + + /** + * the credentials provider + */ + private final SessionProvider sesProvider; + + /** + * Creates a new DavSessionProviderImpl + * @param rep + * @param sesProvider + */ + public DavSessionProviderImpl(Repository rep, SessionProvider sesProvider) { + this.repository = rep; + this.sesProvider = sesProvider; + } + + /** + * Acquires a DavSession. Upon success, the WebdavRequest will + * reference that session. + * + * A session will not be available if an exception is thrown. + * + * @param request + * @throws org.apache.jackrabbit.webdav.DavException if a problem occurred while obtaining the session + * @see DavSessionProvider#attachSession(org.apache.jackrabbit.webdav.WebdavRequest) + */ + public boolean attachSession(WebdavRequest request) throws DavException { + try { + // retrieve the workspace name + String workspaceName = request.getRequestLocator().getWorkspaceName(); + // empty workspaceName rather means default -> must be 'null' + if (workspaceName != null && "".equals(workspaceName)) { + workspaceName = null; + } + // login to repository + Session repSession = sesProvider.getSession(request, repository, workspaceName); + if (repSession == null) { + log.debug("Could not to retrieve a repository session."); + return false; + } + DavSession ds = new DavSessionImpl(repSession); + log.debug("Attaching session '"+ ds + "' to request '" + request + "'"); + request.setDavSession(ds); + return true; + } catch (NoSuchWorkspaceException e) { + // the default error-code for NoSuchWorkspaceException is 409 conflict + // which seems not appropriate here + throw new JcrDavException(e, DavServletResponse.SC_NOT_FOUND); + } catch (RepositoryException e) { + throw new JcrDavException(e); + } catch (ServletException e) { + throw new DavException(DavServletResponse.SC_INTERNAL_SERVER_ERROR, e.getMessage()); + } + } + + /** + * Only removes the DavSession object from the given request object. + * and remove all the lock tokens from the underlying repository session + * in order make sure they can be reset when attaching a session to the + * next request. Finally the session provider is informed, that the + * session is no longer used. + * + * @param request + * @see DavSessionProvider#releaseSession(org.apache.jackrabbit.webdav.WebdavRequest) + */ + public void releaseSession(WebdavRequest request) { + DavSession ds = request.getDavSession(); + if (ds != null && ds instanceof DavSessionImpl) { + Session repSession = ((DavSessionImpl)ds).getRepositorySession(); + for (String lockToken : repSession.getLockTokens()) { + repSession.removeLockToken(lockToken); + } + sesProvider.releaseSession(repSession); + log.debug("Releasing session '"+ ds + "' from request '" + request + "'"); + } // else : session is null. nothing to be done. + request.setDavSession(null); + } +} Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/simple/DavSessionProviderImpl.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/webdav/simple/DefaultItemFilter.java =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/simple/DefaultItemFilter.java (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/simple/DefaultItemFilter.java (working copy) @@ -0,0 +1,158 @@ +/* + * 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.webdav.simple; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.jcr.Item; +import javax.jcr.Node; +import javax.jcr.Property; +import javax.jcr.RepositoryException; +import javax.jcr.Session; +import java.util.ArrayList; +import java.util.List; + +/** + * DefaultItemFilter... + */ +public class DefaultItemFilter implements ItemFilter { + + private static Logger log = LoggerFactory.getLogger(DefaultItemFilter.class); + + private List prefixFilter = new ArrayList(); + private List uriFilter = new ArrayList(); + private List nodetypeFilter = new ArrayList(); + + public DefaultItemFilter() { + } + + /** + * @see ItemFilter#setFilteredURIs(String[]) + */ + public void setFilteredURIs(String[] uris) { + if (uris != null) { + for (String uri : uris) { + uriFilter.add(uri); + } + } + } + + /** + * @see ItemFilter#setFilteredPrefixes(String[]) + */ + public void setFilteredPrefixes(String[] prefixes) { + if (prefixes != null) { + for (String prefix : prefixes) { + prefixFilter.add(prefix); + } + } + } + + /** + * @see ItemFilter#setFilteredNodetypes(String[]) + */ + public void setFilteredNodetypes(String[] nodetypeNames) { + if (nodetypeNames != null) { + for (String nodetypeName : nodetypeNames) { + nodetypeFilter.add(nodetypeName); + } + } + } + + /** + * Returns true if the given item matches either one of the namespace or + * of the the nodetype filters specified. + * + * @see ItemFilter#isFilteredItem(Item) + */ + public boolean isFilteredItem(Item item) { + return isFilteredNamespace(item) || isFilteredNodeType(item); + } + + /** + * @see ItemFilter#isFilteredItem(String, Session) + */ + public boolean isFilteredItem(String displayName, Session session) { + return isFilteredNamespace(displayName, session); + } + + /** + * + * @param name + * @param session + * @return + */ + private boolean isFilteredNamespace(String name, Session session) { + // shortcut + if (prefixFilter.isEmpty() && uriFilter.isEmpty()) { + return false; + } + int pos = name.indexOf(':'); + if (pos < 0) { + // no namespace info present + return false; + } + try { + String prefix = name.substring(0, pos); + String uri = session.getNamespaceURI(prefix); + return prefixFilter.contains(prefix) || uriFilter.contains(uri); + } catch (RepositoryException e) { + log.warn(e.getMessage()); + } + return false; + } + + /** + * + * @param item + * @return + */ + private boolean isFilteredNamespace(Item item) { + try { + return isFilteredNamespace(item.getName(), item.getSession()); + } catch (RepositoryException e) { + log.warn(e.getMessage()); + } + return false; + } + + /** + * + * @param item + * @return + */ + private boolean isFilteredNodeType(Item item) { + // shortcut + if (nodetypeFilter.isEmpty()) { + return false; + } + try { + String ntName; + if (item.isNode()) { + ntName = ((Node) item).getDefinition().getDeclaringNodeType().getName(); + } else { + ntName = ((Property) item).getDefinition().getDeclaringNodeType().getName(); + } + return nodetypeFilter.contains(ntName); + } catch (RepositoryException e) { + log.warn(e.getMessage()); + } + // nodetype info could not be retrieved + return false; + } +} Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/simple/DefaultItemFilter.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/webdav/simple/DeltaVResourceImpl.java =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/simple/DeltaVResourceImpl.java (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/simple/DeltaVResourceImpl.java (working copy) @@ -0,0 +1,274 @@ +/* + * 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.webdav.simple; + +import java.util.ArrayList; +import java.util.List; + +import javax.jcr.Item; +import javax.jcr.Node; +import javax.jcr.RepositoryException; +import javax.jcr.Property; +import javax.xml.parsers.ParserConfigurationException; + +import org.apache.jackrabbit.JcrConstants; +import org.apache.jackrabbit.webdav.DavCompliance; +import org.apache.jackrabbit.webdav.DavException; +import org.apache.jackrabbit.webdav.DavLocatorFactory; +import org.apache.jackrabbit.webdav.DavResource; +import org.apache.jackrabbit.webdav.DavResourceFactory; +import org.apache.jackrabbit.webdav.DavResourceLocator; +import org.apache.jackrabbit.webdav.DavServletResponse; +import org.apache.jackrabbit.webdav.DavSession; +import org.apache.jackrabbit.webdav.property.DavProperty; +import org.apache.jackrabbit.webdav.property.DavPropertyName; +import org.apache.jackrabbit.webdav.property.HrefProperty; +import org.apache.jackrabbit.webdav.property.DefaultDavProperty; +import org.apache.jackrabbit.webdav.version.DeltaVConstants; +import org.apache.jackrabbit.webdav.version.DeltaVResource; +import org.apache.jackrabbit.webdav.version.OptionsInfo; +import org.apache.jackrabbit.webdav.version.OptionsResponse; +import org.apache.jackrabbit.webdav.version.report.Report; +import org.apache.jackrabbit.webdav.version.report.ReportInfo; +import org.apache.jackrabbit.webdav.version.report.ReportType; +import org.apache.jackrabbit.webdav.version.report.SupportedReportSetProperty; +import org.apache.jackrabbit.webdav.xml.DomUtil; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.w3c.dom.Element; + +/** + * The DeltaVResourceImpl encapsulates the functionality common to all + * DeltaV compliant resources. + */ +public class DeltaVResourceImpl extends DavResourceImpl implements DeltaVResource { + + protected SupportedReportSetProperty supportedReports = new SupportedReportSetProperty(); + private static final Logger log = LoggerFactory.getLogger(DeltaVResourceImpl.class); + + private static final String DELTAV_COMPLIANCE_CLASSES = DavCompliance.concatComplianceClasses( + new String[] { + DavResourceImpl.COMPLIANCE_CLASSES, + DavCompliance.BIND, + } + ); + + public DeltaVResourceImpl(DavResourceLocator locator, DavResourceFactory factory, DavSession session, ResourceConfig config, Item item) throws DavException { + super(locator, factory, session, config, (Node)item); + initSupportedReports(); + } + + public DeltaVResourceImpl(DavResourceLocator locator, DavResourceFactory factory, DavSession session, ResourceConfig config, boolean isCollection) throws DavException { + super(locator, factory, session, config, isCollection); + initSupportedReports(); + } + + //---------------------------------------------------------< DavResource>--- + /** + * @see org.apache.jackrabbit.webdav.DavResource#getComplianceClass() + */ + @Override + public String getComplianceClass() { + return DELTAV_COMPLIANCE_CLASSES; + } + + //------------------------------------------------------< DeltaVResource>--- + /** + * @param optionsInfo + * @return object to be used in the OPTIONS response body or null + * @see DeltaVResource#getOptionResponse(org.apache.jackrabbit.webdav.version.OptionsInfo) + */ + public OptionsResponse getOptionResponse(OptionsInfo optionsInfo) { + OptionsResponse oR = null; + if (optionsInfo != null) { + oR = new OptionsResponse(); + // currently only DAV:version-history-collection-set is supported + if (optionsInfo.containsElement(DeltaVConstants.XML_VH_COLLECTION_SET, DeltaVConstants.NAMESPACE)) { + String[] hrefs = new String[] { + getLocatorFromNodePath("/"+JcrConstants.JCR_SYSTEM+"/"+JcrConstants.JCR_VERSIONSTORAGE).getHref(true) + }; + oR.addEntry(DeltaVConstants.XML_VH_COLLECTION_SET, DeltaVConstants.NAMESPACE, hrefs); + } + } + return oR; + } + + /** + * @param reportInfo + * @return the requested report + * @throws DavException + * @see DeltaVResource#getReport(org.apache.jackrabbit.webdav.version.report.ReportInfo) + */ + public Report getReport(ReportInfo reportInfo) throws DavException { + if (reportInfo == null) { + throw new DavException(DavServletResponse.SC_BAD_REQUEST, "A REPORT request must provide a valid XML request body."); + } + if (!exists()) { + throw new DavException(DavServletResponse.SC_NOT_FOUND); + } + + if (!supportedReports.isSupportedReport(reportInfo)) { + Element condition = null; + try { + condition = DomUtil.createDocument().createElementNS("DAV:", "supported-report"); + } catch (ParserConfigurationException ex) { + // we don't care THAT much + } + throw new DavException(DavServletResponse.SC_CONFLICT, + "Unknown report '" + reportInfo.getReportName() + "' requested.", null, condition); + } + return ReportType.getType(reportInfo).createReport(this, reportInfo); + } + + /** + * The JCR api does not provide methods to create new workspaces. Calling + * addWorkspace on this resource will always fail. + * + * @param workspace + * @throws DavException Always throws. + * @see DeltaVResource#addWorkspace(org.apache.jackrabbit.webdav.DavResource) + */ + public void addWorkspace(DavResource workspace) throws DavException { + throw new DavException(DavServletResponse.SC_FORBIDDEN); + } + + /** + * Return an array of DavResource objects that are referenced + * by the property with the specified name. + * + * @param hrefPropertyName + * @return array of DavResources + * @throws DavException + * @see DeltaVResource#getReferenceResources(org.apache.jackrabbit.webdav.property.DavPropertyName) + */ + public DavResource[] getReferenceResources(DavPropertyName hrefPropertyName) throws DavException { + DavProperty prop = getProperty(hrefPropertyName); + List resources = new ArrayList(); + if (prop != null && prop instanceof HrefProperty) { + HrefProperty hp = (HrefProperty)prop; + // process list of hrefs + for (String href : hp.getHrefs()) { + DavResourceLocator locator = getLocator().getFactory().createResourceLocator(getLocator().getPrefix(), href); + resources.add(createResourceFromLocator(locator)); + } + } else { + throw new DavException(DavServletResponse.SC_INTERNAL_SERVER_ERROR); + } + return resources.toArray(new DavResource[resources.size()]); + } + + /** + * Build a DavResourceLocator from the given nodePath path. + * + * @param nodePath + * @return a new DavResourceLocator + * @see DavLocatorFactory#createResourceLocator(String, String, String) + */ + protected DavResourceLocator getLocatorFromNodePath(String nodePath) { + DavResourceLocator loc = getLocator().getFactory().createResourceLocator(getLocator().getPrefix(), getLocator().getWorkspacePath(), nodePath, false); + return loc; + } + + + /** + * Build a new {@link DavResourceLocator} from the given repository node. + * + * @param repositoryNode + * @return a new locator for the specified node. + * @see #getLocatorFromNodePath(String) + */ + protected DavResourceLocator getLocatorFromNode(Node repositoryNode) { + String nodePath = null; + try { + if (repositoryNode != null) { + nodePath = repositoryNode.getPath(); + } + } catch (RepositoryException e) { + // ignore: should not occur + log.warn(e.getMessage()); + } + return getLocatorFromNodePath(nodePath); + } + + /** + * Create a new DavResource from the given locator. + * @param loc + * @return new DavResource + */ + protected DavResource createResourceFromLocator(DavResourceLocator loc) + throws DavException { + DavResource res = getFactory().createResource(loc, getSession()); + return res; + } + + /** + * Returns a {@link org.apache.jackrabbit.webdav.property.HrefProperty} with the + * specified property name and values. Each node present in the specified + * array is referenced in the resulting property. + * + * @param name + * @param values + * @param isProtected + * @return HrefProperty + */ + protected HrefProperty getHrefProperty(DavPropertyName name, Node[] values, + boolean isProtected, boolean isCollection) { + if (values == null) { + return null; + } + String[] pHref = new String[values.length]; + for (int i = 0; i < values.length; i++) { + pHref[i] = getLocatorFromNode(values[i]).getHref(isCollection); + } + return new HrefProperty(name, pHref, isProtected); + } + + /** + * Initialize the supported reports field + */ + protected void initSupportedReports() { + if (exists()) { + supportedReports.addReportType(ReportType.EXPAND_PROPERTY); + if (isCollection()) { + supportedReports.addReportType(ReportType.LOCATE_BY_HISTORY); + } + } + } + + /** + * Fill the property set for this resource. + */ + @Override + protected void initProperties() { + if (!propsInitialized) { + super.initProperties(); + if (exists()) { + properties.add(supportedReports); + + // DAV:creator-displayname -> use jcr:createBy if present. + Node n = getNode(); + try { + if (n.hasProperty(Property.JCR_CREATED_BY)) { + String createdBy = n.getProperty(Property.JCR_CREATED_BY).getString(); + properties.add(new DefaultDavProperty(DeltaVConstants.CREATOR_DISPLAYNAME, createdBy, true)); + } + } catch (RepositoryException e) { + log.debug("Error while accessing jcr:createdBy property"); + } + } + } + } +} Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/simple/DeltaVResourceImpl.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/webdav/simple/ItemFilter.java =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/simple/ItemFilter.java (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/simple/ItemFilter.java (working copy) @@ -0,0 +1,68 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.jackrabbit.webdav.simple; + +import javax.jcr.Item; +import javax.jcr.Session; + +/** + * ItemFilter + */ +public interface ItemFilter { + + /** + * Define the URIs that should be filtered out if present in the prefix + * of an items name. + * + * @param uris + */ + public void setFilteredURIs(String[] uris); + + /** + * Define the namespace prefixes that should be filtered if present in + * the prefix of an items name. + * + * @param prefixes + */ + public void setFilteredPrefixes(String[] prefixes); + + /** + * Set the nodetype names that should be used if a given item should be + * filtered. Note that not the nodetype(s) defined for a given item + * is relevant but rather the nodetype that defined the definition of the item. + * + * @param nodetypeNames + */ + public void setFilteredNodetypes(String[] nodetypeNames); + + /** + * Returns true if the given item should be filtered. + * + * @param item to be tested + * @return true if the given item should be filtered. + */ + public boolean isFilteredItem(Item item); + + /** + * Returns true if the resouce with the given name should be filtered. + * + * @param name to be tested for a filtered namespace prefix + * @param session used for looking up namespace mappings + * @return true if the given resource should be filtered. + */ + public boolean isFilteredItem(String name, Session session); +} \ No newline at end of file Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/simple/ItemFilter.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/webdav/simple/LocatorFactoryImpl.java =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/simple/LocatorFactoryImpl.java (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/simple/LocatorFactoryImpl.java (working copy) @@ -0,0 +1,165 @@ +/* + * 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.webdav.simple; + +import org.apache.jackrabbit.util.Text; +import org.apache.jackrabbit.webdav.DavLocatorFactory; +import org.apache.jackrabbit.webdav.DavResourceLocator; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * ResourceFactoryImpl implements a simple DavLocatorFactory + */ +// todo improve special handling of root item.... +public class LocatorFactoryImpl implements DavLocatorFactory { + + /** the default logger */ + private static final Logger log = LoggerFactory.getLogger(LocatorFactoryImpl.class); + + private final String repositoryPrefix; + + public LocatorFactoryImpl(String repositoryPrefix) { + this.repositoryPrefix = repositoryPrefix; + } + + public DavResourceLocator createResourceLocator(String prefix, String href) { + // build prefix string and remove all prefixes from the given href. + StringBuffer b = new StringBuffer(""); + if (prefix != null && prefix.length() > 0) { + b.append(prefix); + if (href.startsWith(prefix)) { + href = href.substring(prefix.length()); + } + } + if (repositoryPrefix != null && repositoryPrefix.length() > 0 && !prefix.endsWith(repositoryPrefix)) { + b.append(repositoryPrefix); + if (href.startsWith(repositoryPrefix)) { + href = href.substring(repositoryPrefix.length()); + } + } + + // special treatment for root item, that has no name but '/' path. + if (href == null || "".equals(href)) { + href = "/"; + } + return new Locator(b.toString(), Text.unescape(href), this); + } + + public DavResourceLocator createResourceLocator(String prefix, String workspacePath, String resourcePath) { + return createResourceLocator(prefix, workspacePath, resourcePath, true); + } + + public DavResourceLocator createResourceLocator(String prefix, String workspacePath, String path, boolean isResourcePath) { + return new Locator(prefix, path, this); + } + + //-------------------------------------------------------------------------- + private static class Locator implements DavResourceLocator { + + private final String prefix; + private final String resourcePath; + private final DavLocatorFactory factory; + private final String href; + + private Locator(String prefix, String resourcePath, DavLocatorFactory factory) { + this.prefix = prefix; + this.factory = factory; + // remove trailing '/' that is not part of the resourcePath except for the root item. + if (resourcePath.endsWith("/") && !"/".equals(resourcePath)) { + resourcePath = resourcePath.substring(0, resourcePath.length()-1); + } + this.resourcePath = resourcePath; + href = prefix + Text.escapePath(resourcePath); + } + + public String getPrefix() { + return prefix; + } + + public String getResourcePath() { + return resourcePath; + } + + public String getWorkspacePath() { + return ""; + } + + public String getWorkspaceName() { + return ""; + } + + public boolean isSameWorkspace(DavResourceLocator locator) { + return isSameWorkspace(locator.getWorkspaceName()); + } + + public boolean isSameWorkspace(String workspaceName) { + return getWorkspaceName().equals(workspaceName); + } + + public String getHref(boolean isCollection) { + // avoid doubled trailing '/' for the root item + String suffix = (isCollection && !isRootLocation()) ? "/" : ""; + return href + suffix; + } + + public boolean isRootLocation() { + return "/".equals(resourcePath); + } + + public DavLocatorFactory getFactory() { + return factory; + } + + /** + * Returns the same as {@link #getResourcePath()}. No encoding is performed + * at all. + * @see DavResourceLocator#getRepositoryPath() + */ + public String getRepositoryPath() { + return getResourcePath(); + } + + /** + * Computes the hash code from the href, which is built using the final + * fields prefix and resourcePath. + * + * @return the hash code + */ + @Override + public int hashCode() { + return href.hashCode(); + } + + /** + * Equality of path is achieved if the specified object is a DavResourceLocator + * object with the same hash code. + * + * @param obj the object to compare to + * @return true if the 2 objects are equal; + * false otherwise + */ + @Override + public boolean equals(Object obj) { + if (obj instanceof DavResourceLocator) { + DavResourceLocator other = (DavResourceLocator) obj; + return hashCode() == other.hashCode(); + } + return false; + } + } +} Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/simple/LocatorFactoryImpl.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/webdav/simple/LocatorFactoryImplEx.java =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/simple/LocatorFactoryImplEx.java (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/simple/LocatorFactoryImplEx.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.webdav.simple; + +import org.apache.jackrabbit.webdav.AbstractLocatorFactory; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * LocatorFactoryImplEx... + */ +public class LocatorFactoryImplEx extends AbstractLocatorFactory { + + private static Logger log = LoggerFactory.getLogger(LocatorFactoryImplEx.class); + + /** + * Create a new factory + * + * @param pathPrefix Prefix, that needs to be removed in order to retrieve + * the path of the repository item from a given DavResourceLocator. + */ + public LocatorFactoryImplEx(String pathPrefix) { + super(pathPrefix); + } + + /** + * + * @see AbstractLocatorFactory#getRepositoryPath(String, String) + */ + @Override + protected String getRepositoryPath(String resourcePath, String wspPath) { + if (resourcePath == null) { + return resourcePath; + } + + if (resourcePath.equals(wspPath) || startsWithWorkspace(resourcePath, wspPath)) { + String repositoryPath = resourcePath.substring(wspPath.length()); + return (repositoryPath.length() == 0) ? "/" : repositoryPath; + } else { + throw new IllegalArgumentException("Unexpected format of resource path: " + resourcePath + " (workspace: " + wspPath + ")"); + } + } + + /** + * + * @see AbstractLocatorFactory#getResourcePath(String, String) + */ + @Override + protected String getResourcePath(String repositoryPath, String wspPath) { + if (repositoryPath == null) { + throw new IllegalArgumentException("Cannot build resource path from 'null' repository path"); + } + return wspPath + repositoryPath; + } + + private boolean startsWithWorkspace(String repositoryPath, String wspPath) { + if (wspPath == null) { + return true; + } else { + return repositoryPath.startsWith(wspPath + "/"); + } + } +} Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/simple/LocatorFactoryImplEx.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/webdav/simple/ResourceConfig.java =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/simple/ResourceConfig.java (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/simple/ResourceConfig.java (working copy) @@ -0,0 +1,543 @@ +/* + * 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.webdav.simple; + +import java.io.IOException; +import java.io.InputStream; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.net.URL; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import javax.jcr.Item; +import javax.jcr.Node; +import javax.jcr.RepositoryException; +import javax.xml.parsers.ParserConfigurationException; + +import org.apache.jackrabbit.server.io.CopyMoveHandler; +import org.apache.jackrabbit.server.io.CopyMoveManager; +import org.apache.jackrabbit.server.io.CopyMoveManagerImpl; +import org.apache.jackrabbit.server.io.DefaultIOManager; +import org.apache.jackrabbit.server.io.DeleteManager; +import org.apache.jackrabbit.server.io.DeleteManagerImpl; +import org.apache.jackrabbit.server.io.IOHandler; +import org.apache.jackrabbit.server.io.IOManager; +import org.apache.jackrabbit.server.io.PropertyHandler; +import org.apache.jackrabbit.server.io.PropertyManager; +import org.apache.jackrabbit.server.io.PropertyManagerImpl; +import org.apache.jackrabbit.webdav.xml.DomUtil; +import org.apache.jackrabbit.webdav.xml.ElementIterator; +import org.apache.jackrabbit.webdav.xml.Namespace; +import org.apache.tika.detect.Detector; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.w3c.dom.Element; +import org.xml.sax.SAXException; + +/** + * ResourceConfig... + */ +public class ResourceConfig { + + private static Logger log = LoggerFactory.getLogger(ResourceConfig.class); + + private static final String ELEMENT_IOMANAGER = "iomanager"; + private static final String ELEMENT_IOHANDLER = "iohandler"; + + private static final String ELEMENT_PROPERTYMANAGER = "propertymanager"; + private static final String ELEMENT_PROPERTYHANDLER = "propertyhandler"; + + private static final String ELEMENT_COPYMOVEMANAGER = "copymovemanager"; + private static final String ELEMENT_COPYMOVEHANDLER = "copymovehandler"; + + private static final String ELEMENT_CLASS = "class"; + + private static final String ELEMENT_PARAM = "param"; + private static final String ATTR_NAME = "name"; + private static final String ATTR_VALUE = "value"; + + /** + * Content type detector. + */ + private final Detector detector; + + private ItemFilter itemFilter; + private IOManager ioManager; + private CopyMoveManager cmManager; + private PropertyManager propManager; + private DeleteManager deleteManager; + private String[] nodetypeNames = new String[0]; + private boolean collectionNames = false; + + public ResourceConfig(Detector detector) { + this.detector = detector; + } + + /** + * Tries to parse the given xml configuration file. + * The xml must match the following structure:
+ *
+     * <!ELEMENT config (iomanager, propertymanager, (collection | noncollection)?, filter?, mimetypeproperties?) >
+     * <!ELEMENT iomanager (class, iohandler*) >
+     * <!ELEMENT iohandler (class) >
+     * <!ELEMENT propertymanager (class, propertyhandler*) >
+     * <!ELEMENT propertyhandler (class) >
+     * <!ELEMENT collection (nodetypes) >
+     * <!ELEMENT noncollection (nodetypes) >
+     * <!ELEMENT filter (class, namespaces?, nodetypes?) >
+     * <!ELEMENT class >
+     *    <!ATTLIST class
+     *      name  CDATA #REQUIRED
+     *    >
+     * <!ELEMENT namespaces (prefix|uri)* >
+     * <!ELEMENT prefix (CDATA) >
+     * <!ELEMENT uri (CDATA) >
+     * <!ELEMENT nodetypes (nodetype)* >
+     * <!ELEMENT nodetype (CDATA) >
+     * <!ELEMENT mimetypeproperties (mimemapping*, defaultmimetype) >
+     * <!ELEMENT mimemapping >
+     *    <!ATTLIST mimemapping
+     *      extension  CDATA #REQUIRED
+     *      mimetype  CDATA #REQUIRED
+     *    >
+     * <!ELEMENT defaultmimetype (CDATA) >
+     * 
+ *

+ * The <mimetypeproperties/> settings have been deprecated and will + * be ignored with a warning. Instead you can use the + * {@link SimpleWebdavServlet#INIT_PARAM_MIME_INFO mime-info} + * servlet initialization parameter to customize the media type settings. + * + * @param configURL + */ + public void parse(URL configURL) { + try { + parse(configURL.openStream()); + } catch (IOException e) { + log.debug("Invalid resource configuration: " + e.getMessage()); + } + } + + /** + * Parses the given input stream into the xml configuration file. + * The xml must match the following structure:
+ *

+     * <!ELEMENT config (iomanager, propertymanager, (collection | noncollection)?, filter?, mimetypeproperties?) >
+     * <!ELEMENT iomanager (class, iohandler*) >
+     * <!ELEMENT iohandler (class) >
+     * <!ELEMENT propertymanager (class, propertyhandler*) >
+     * <!ELEMENT propertyhandler (class) >
+     * <!ELEMENT collection (nodetypes) >
+     * <!ELEMENT noncollection (nodetypes) >
+     * <!ELEMENT filter (class, namespaces?, nodetypes?) >
+     * <!ELEMENT class >
+     *    <!ATTLIST class
+     *      name  CDATA #REQUIRED
+     *    >
+     * <!ELEMENT namespaces (prefix|uri)* >
+     * <!ELEMENT prefix (CDATA) >
+     * <!ELEMENT uri (CDATA) >
+     * <!ELEMENT nodetypes (nodetype)* >
+     * <!ELEMENT nodetype (CDATA) >
+     * <!ELEMENT mimetypeproperties (mimemapping*, defaultmimetype) >
+     * <!ELEMENT mimemapping >
+     *    <!ATTLIST mimemapping
+     *      extension  CDATA #REQUIRED
+     *      mimetype  CDATA #REQUIRED
+     *    >
+     * <!ELEMENT defaultmimetype (CDATA) >
+     * 
+ *

+ * The <mimetypeproperties/> settings have been deprecated and will + * be ignored with a warning. Instead you can use the + * {@link SimpleWebdavServlet#INIT_PARAM_MIME_INFO mime-info} + * servlet initialization parameter to customize the media type settings. + * + * @param stream + */ + public void parse(InputStream stream) { + try { + Element config = DomUtil.parseDocument(stream).getDocumentElement(); + if (config == null) { + log.warn("Mandatory 'config' element is missing."); + return; + } + + // iomanager config entry + Element el = DomUtil.getChildElement(config, ELEMENT_IOMANAGER, null); + if (el != null) { + Object inst = buildClassFromConfig(el); + if (inst != null && inst instanceof IOManager) { + ioManager = (IOManager)inst; + ioManager.setDetector(detector); + // get optional 'iohandler' child elements and populate the + // ioManager with the instances + ElementIterator iohElements = DomUtil.getChildren(el, ELEMENT_IOHANDLER, null); + while (iohElements.hasNext()) { + Element iohEl = iohElements.nextElement(); + inst = buildClassFromConfig(iohEl); + if (inst != null && inst instanceof IOHandler) { + IOHandler handler = (IOHandler) inst; + setParameters(handler, iohEl); + ioManager.addIOHandler(handler); + } else { + log.warn("Not a valid IOHandler : " + getClassName(iohEl)); + } + } + } else { + log.warn("'iomanager' element does not define a valid IOManager."); + } + } else { + log.warn("'iomanager' element is missing."); + } + + // propertymanager config entry + el = DomUtil.getChildElement(config, ELEMENT_PROPERTYMANAGER, null); + if (el != null) { + Object inst = buildClassFromConfig(el); + if (inst != null && inst instanceof PropertyManager) { + propManager = (PropertyManager)inst; + // get optional 'iohandler' child elements and populate the + // ioManager with the instances + ElementIterator iohElements = DomUtil.getChildren(el, ELEMENT_PROPERTYHANDLER, null); + while (iohElements.hasNext()) { + Element iohEl = iohElements.nextElement(); + inst = buildClassFromConfig(iohEl); + if (inst != null && inst instanceof PropertyHandler) { + PropertyHandler handler = (PropertyHandler) inst; + setParameters(handler, iohEl); + propManager.addPropertyHandler(handler); + } else { + log.warn("Not a valid PropertyHandler : " + getClassName(iohEl)); + } + } + } else { + log.warn("'propertymanager' element does not define a valid PropertyManager."); + } + } else { + log.debug("'propertymanager' element is missing."); + } + + // copymovemanager config entry + el = DomUtil.getChildElement(config, ELEMENT_COPYMOVEMANAGER, null); + if (el != null) { + Object inst = buildClassFromConfig(el); + if (inst != null && inst instanceof CopyMoveManager) { + cmManager = (CopyMoveManager) inst; + // get optional 'copymovehandler' child elements and populate + // the copy move manager with the instances + ElementIterator iohElements = DomUtil.getChildren(el, ELEMENT_COPYMOVEHANDLER, null); + while (iohElements.hasNext()) { + Element iohEl = iohElements.nextElement(); + inst = buildClassFromConfig(iohEl); + if (inst != null && inst instanceof CopyMoveHandler) { + CopyMoveHandler handler = (CopyMoveHandler) inst; + setParameters(handler, iohEl); + cmManager.addCopyMoveHandler(handler); + } else { + log.warn("Not a valid CopyMoveHandler : " + getClassName(iohEl)); + } + } + } else { + log.warn("'copymovemanager' element does not define a valid CopyMoveManager."); + } + } else { + log.debug("'copymovemanager' element is missing."); + } + + // collection/non-collection config entry + el = DomUtil.getChildElement(config, "collection", null); + if (el != null) { + nodetypeNames = parseNodeTypesEntry(el); + collectionNames = true; + } else if ((el = DomUtil.getChildElement(config, "noncollection", null)) != null) { + nodetypeNames = parseNodeTypesEntry(el); + collectionNames = false; + } + // todo: should check if both 'noncollection' and 'collection' are present and write a warning + + // filter config entry + el = DomUtil.getChildElement(config, "filter", null); + if (el != null) { + Object inst = buildClassFromConfig(el); + if (inst != null && inst instanceof ItemFilter) { + itemFilter = (ItemFilter)inst; + } + if (itemFilter != null) { + itemFilter.setFilteredNodetypes(parseNodeTypesEntry(el)); + parseNamespacesEntry(el); + } + } else { + log.debug("No 'filter' element specified."); + } + + el = DomUtil.getChildElement(config, "mimetypeproperties", null); + if (el != null) { + log.warn("Ignoring deprecated mimetypeproperties settings"); + } + } catch (IOException e) { + log.debug("Invalid resource configuration: " + e.getMessage()); + } catch (ParserConfigurationException e) { + log.warn("Failed to parse resource configuration: " + e.getMessage()); + } catch (SAXException e) { + log.warn("Failed to parse resource configuration: " + e.getMessage()); + } + } + + private void parseNamespacesEntry(Element parent) { + Element namespaces = DomUtil.getChildElement(parent, "namespaces", null); + if (namespaces != null) { + List l = new ArrayList(); + // retrieve prefix child elements + ElementIterator it = DomUtil.getChildren(namespaces, "prefix", null); + while (it.hasNext()) { + Element e = it.nextElement(); + l.add(DomUtil.getText(e)); + } + String[] prefixes = l.toArray(new String[l.size()]); + l.clear(); + // retrieve uri child elements + it = DomUtil.getChildren(namespaces, "uri", null); + while (it.hasNext()) { + Element e = it.nextElement(); + l.add(DomUtil.getText(e)); + } + String[] uris = l.toArray(new String[l.size()]); + itemFilter.setFilteredPrefixes(prefixes); + itemFilter.setFilteredURIs(uris); + } + } + + private static String[] parseNodeTypesEntry(Element parent) { + String[] ntNames; + Element nodetypes = DomUtil.getChildElement(parent, "nodetypes", null); + if (nodetypes != null) { + List l = new ArrayList(); + ElementIterator it = DomUtil.getChildren(nodetypes, "nodetype", null); + while (it.hasNext()) { + Element e = it.nextElement(); + l.add(DomUtil.getText(e)); + } + ntNames = l.toArray(new String[l.size()]); + } else { + ntNames = new String[0]; + } + return ntNames; + } + + private static Object buildClassFromConfig(Element parent) { + Object instance = null; + Element classElem = DomUtil.getChildElement(parent, "class", null); + if (classElem != null) { + // contains a 'class' child node + try { + String className = DomUtil.getAttribute(classElem, "name", null); + if (className != null) { + Class c = Class.forName(className); + instance = c.newInstance(); + } else { + log.error("Invalid configuration: missing 'class' element"); + } + } catch (Exception e) { + log.error("Error while create class instance: " + e.getMessage()); + } + } + return instance; + } + + private static String getClassName(Element parent) { + String className = null; + Element classElem = DomUtil.getChildElement(parent, "class", null); + if (classElem != null) { + className = DomUtil.getAttribute(classElem, "name", null); + } + return (className == null) ? "" : className; + } + + /** + * Retrieve 'param' elements for the specified xmlElement and + * use the public setter methods of the given instance to set + * the corresponding instance fields. + * + * @param instance + * @param xmlElement + */ + private static void setParameters(Object instance, Element xmlElement) { + ElementIterator paramElems = DomUtil.getChildren(xmlElement, ELEMENT_PARAM, Namespace.EMPTY_NAMESPACE); + if (paramElems.hasNext()) { + Map setters = getSetters(instance.getClass()); + if (!setters.isEmpty()) { + while (paramElems.hasNext()) { + Element parameter = paramElems.next(); + String name = DomUtil.getAttribute(parameter, ATTR_NAME, null); + String value = DomUtil.getAttribute(parameter, ATTR_VALUE, null); + if (name == null || value == null) { + log.error("Parameter name or value missing -> ignore."); + continue; + } + Method setter = setters.get(name); + if (setter != null) { + Class type = setter.getParameterTypes()[0]; + try { + if (type.isAssignableFrom(String.class) + || type.isAssignableFrom(Object.class)) { + setter.invoke(instance, value); + } else if (type.isAssignableFrom(Boolean.TYPE) + || type.isAssignableFrom(Boolean.class)) { + setter.invoke(instance, Boolean.valueOf(value)); + } else if (type.isAssignableFrom(Integer.TYPE) + || type.isAssignableFrom(Integer.class)) { + setter.invoke(instance, Integer.valueOf(value)); + } else if (type.isAssignableFrom(Long.TYPE) + || type.isAssignableFrom(Long.class)) { + setter.invoke(instance, Long.valueOf(value)); + } else if (type.isAssignableFrom(Double.TYPE) + || type.isAssignableFrom(Double.class)) { + setter.invoke(instance, Double.valueOf(value)); + } else { + log.error("Cannot set configuration property " + name); + } + } catch (Exception e) { + log.error("Invalid format (" + value + ") for property " + name + " of class " + instance.getClass().getName(), e); + } + } + } + } + } + } + + private static Map getSetters(Class cl) { + Map methods = new HashMap(); + for (Method method : cl.getMethods()) { + String name = method.getName(); + if (name.startsWith("set") && name.length() > 3 + && Modifier.isPublic(method.getModifiers()) + && !Modifier.isStatic(method.getModifiers()) + && Void.TYPE.equals(method.getReturnType()) + && method.getParameterTypes().length == 1) { + methods.put(name.substring(3, 4).toLowerCase() + name.substring(4), method); + } + } + return methods; + } + + /** + * + * @return + */ + public IOManager getIOManager() { + if (ioManager == null) { + log.debug("Missing io-manager > building DefaultIOManager "); + ioManager = new DefaultIOManager(); + ioManager.setDetector(detector); + } + return ioManager; + } + + /** + * + * @return + */ + public PropertyManager getPropertyManager() { + if (propManager == null) { + log.debug("Missing property-manager > building default."); + propManager = PropertyManagerImpl.getDefaultManager(); + } + return propManager; + } + + /** + * + * @return + */ + public CopyMoveManager getCopyMoveManager() { + if (cmManager == null) { + log.debug("Missing copymove-manager > building default."); + cmManager = CopyMoveManagerImpl.getDefaultManager(); + } + return cmManager; + } + + /** + * Returns the delete manager. + * @return the delete manager + */ + public DeleteManager getDeleteManager() { + if (deleteManager == null) { + log.debug("Missing delete-manager > building default."); + deleteManager = DeleteManagerImpl.getDefaultManager(); + } + return deleteManager; + } + + /** + * Returns true, if the given item represents a {@link Node node} that is + * either any of the nodetypes specified to represent a collection or + * none of the nodetypes specified to represent a non-collection, respectively. + * If no valid configuration entry is present, this method returns true + * for node items. For items which are not a node, this method always + * returns false. + * + * @param item + * @return true if the given item is a node that represents a webdav + * collection, false otherwise. + */ + public boolean isCollectionResource(Item item) { + if (item.isNode()) { + boolean isCollection = true; + Node n = (Node)item; + try { + for (int i = 0; i < nodetypeNames.length && isCollection; i++) { + isCollection = collectionNames ? n.isNodeType(nodetypeNames[i]) : !n.isNodeType(nodetypeNames[i]); + } + } catch (RepositoryException e) { + log.warn(e.getMessage()); + } + return isCollection; + } else { + return false; + } + } + + /** + * Returns the item filter specified with the configuration or {@link DefaultItemFilter} + * if the configuration was missing the corresponding entry or the parser failed + * to build a ItemFilter instance from the configuration. + * + * @return item filter as defined by the config or {@link DefaultItemFilter} + */ + public ItemFilter getItemFilter() { + if (itemFilter == null) { + log.debug("Missing resource filter > building DefaultItemFilter "); + itemFilter = new DefaultItemFilter(); + } + return itemFilter; + } + + /** + * Returns the configured content type detector. + * + * @return content type detector + */ + public Detector getDetector() { + return detector; + } + +} Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/simple/ResourceConfig.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 \ No newline at end of property Index: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/simple/ResourceFactoryImpl.java =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/simple/ResourceFactoryImpl.java (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/simple/ResourceFactoryImpl.java (working copy) @@ -0,0 +1,208 @@ +/* + * 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.webdav.simple; + +import org.apache.jackrabbit.webdav.DavException; +import org.apache.jackrabbit.webdav.DavMethods; +import org.apache.jackrabbit.webdav.DavResource; +import org.apache.jackrabbit.webdav.DavResourceFactory; +import org.apache.jackrabbit.webdav.DavResourceLocator; +import org.apache.jackrabbit.webdav.DavServletRequest; +import org.apache.jackrabbit.webdav.DavServletResponse; +import org.apache.jackrabbit.webdav.DavSession; +import org.apache.jackrabbit.webdav.jcr.JcrDavSession; +import org.apache.jackrabbit.webdav.lock.LockManager; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.jcr.Item; +import javax.jcr.Node; +import javax.jcr.PathNotFoundException; +import javax.jcr.RepositoryException; +import javax.jcr.Repository; +import javax.jcr.Session; +import javax.jcr.version.Version; +import javax.jcr.version.VersionHistory; + +/** + * ResourceFactoryImpl implements a simple DavResourceFactory + */ +public class ResourceFactoryImpl implements DavResourceFactory { + + private static Logger log =LoggerFactory.getLogger(ResourceFactoryImpl.class); + + private final LockManager lockMgr; + private final ResourceConfig resourceConfig; + + /** + * Create a new ResourceFactory that uses the given lock + * manager and resource filter. + * + * @param lockMgr + * @param resourceConfig + */ + public ResourceFactoryImpl(LockManager lockMgr, ResourceConfig resourceConfig) { + this.lockMgr = lockMgr; + this.resourceConfig = resourceConfig; + } + + /** + * Create a new DavResource from the given locator and + * request. + * + * @param locator + * @param request + * @param response + * @return DavResource + * @throws DavException + * @see DavResourceFactory#createResource(DavResourceLocator, + * DavServletRequest, DavServletResponse) + */ + public DavResource createResource(DavResourceLocator locator, DavServletRequest request, + DavServletResponse response) throws DavException { + try { + Node node = getNode(request.getDavSession(), locator); + DavResource resource; + if (node == null) { + log.debug("Creating resource for non-existing repository node."); + boolean isCollection = DavMethods.isCreateCollectionRequest(request); + resource = createNullResource(locator, request.getDavSession(), isCollection); + } else { + resource = createResource(node, locator, request.getDavSession()); + } + resource.addLockManager(lockMgr); + return resource; + } catch (RepositoryException e) { + throw new DavException(DavServletResponse.SC_INTERNAL_SERVER_ERROR, e); + } + } + + /** + * Create a new DavResource from the given locator and webdav + * session. + * + * @param locator + * @param session + * @return + * @throws DavException + * @see DavResourceFactory#createResource(DavResourceLocator, DavSession) + */ + public DavResource createResource(DavResourceLocator locator, DavSession session) throws DavException { + try { + Node node = getNode(session, locator); + DavResource resource = createResource(node, locator, session); + resource.addLockManager(lockMgr); + return resource; + } catch (RepositoryException e) { + throw new DavException(DavServletResponse.SC_INTERNAL_SERVER_ERROR, e); + } + } + + /** + * Returns the Node corresponding to the given locator or + * null if it does not exist or if the existing item represents + * a Property. + * + * @param sessionImpl + * @param locator + * @return + * @throws RepositoryException + */ + private Node getNode(DavSession sessionImpl, DavResourceLocator locator) + throws RepositoryException { + Node node = null; + try { + String repoPath = locator.getRepositoryPath(); + if (repoPath != null) { + Session session = ((JcrDavSession)sessionImpl).getRepositorySession(); + Item item = session.getItem(repoPath); + if (item instanceof Node) { + node = (Node)item; + } // else: item is a property -> return null + } + } catch (PathNotFoundException e) { + // item does not exist (yet). return null -> create null-resource + } + return node; + } + + /** + * Create a 'null resource' + * + * @param locator + * @param session + * @param isCollection + * @return + * @throws DavException + */ + private DavResource createNullResource(DavResourceLocator locator, + DavSession session, + boolean isCollection) throws DavException { + JcrDavSession.checkImplementation(session); + JcrDavSession sessionImpl = (JcrDavSession)session; + + DavResource resource; + if (versioningSupported(sessionImpl.getRepositorySession())) { + resource = new VersionControlledResourceImpl(locator, this, sessionImpl, resourceConfig, isCollection); + } else { + resource = new DavResourceImpl(locator, this, sessionImpl, resourceConfig, isCollection); + } + return resource; + } + + /** + * Tries to retrieve the repository item defined by the locator's resource + * path and build the corresponding WebDAV resource. If the repository + * supports the versioning option different resources are created for + * version, versionhistory and common nodes. + * + * @param node + * @param locator + * @param session + * @return + * @throws DavException + */ + private DavResource createResource(Node node, DavResourceLocator locator, + DavSession session) throws DavException { + JcrDavSession.checkImplementation(session); + JcrDavSession sessionImpl = (JcrDavSession)session; + + DavResource resource; + if (versioningSupported(sessionImpl.getRepositorySession())) { + // create special resources for Version and VersionHistory + if (node instanceof Version) { + resource = new VersionResourceImpl(locator, this, sessionImpl, resourceConfig, node); + } else if (node instanceof VersionHistory) { + resource = new VersionHistoryResourceImpl(locator, this, sessionImpl, resourceConfig, node); + } else { + resource = new VersionControlledResourceImpl(locator, this, sessionImpl, resourceConfig, node); + } + } else { + resource = new DavResourceImpl(locator, this, session, resourceConfig, node); + } + return resource; + } + + /** + * @param repoSession + * @return true if the JCR repository supports versioning. + */ + private static boolean versioningSupported(Session repoSession) { + String desc = repoSession.getRepository().getDescriptor(Repository.OPTION_VERSIONING_SUPPORTED); + return Boolean.valueOf(desc); + } +} Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/simple/ResourceFactoryImpl.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/webdav/simple/SimpleWebdavServlet.java =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/simple/SimpleWebdavServlet.java (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/simple/SimpleWebdavServlet.java (working copy) @@ -0,0 +1,411 @@ +/* + * 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.webdav.simple; + +import org.apache.jackrabbit.server.BasicCredentialsProvider; +import org.apache.jackrabbit.server.CredentialsProvider; +import org.apache.jackrabbit.server.SessionProvider; +import org.apache.jackrabbit.server.SessionProviderImpl; +import org.apache.jackrabbit.webdav.DavLocatorFactory; +import org.apache.jackrabbit.webdav.DavResource; +import org.apache.jackrabbit.webdav.DavResourceFactory; +import org.apache.jackrabbit.webdav.DavSessionProvider; +import org.apache.jackrabbit.webdav.WebdavRequest; +import org.apache.jackrabbit.webdav.lock.LockManager; +import org.apache.jackrabbit.webdav.lock.SimpleLockManager; +import org.apache.jackrabbit.webdav.server.AbstractWebdavServlet; +import org.apache.jackrabbit.webdav.util.HttpDateTimeFormatter; +import org.apache.tika.detect.Detector; +import org.apache.tika.mime.MimeTypeException; +import org.apache.tika.mime.MimeTypesFactory; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.jcr.Repository; +import javax.servlet.ServletContext; +import javax.servlet.ServletException; + +import java.io.IOException; +import java.net.MalformedURLException; +import java.net.URL; +import java.time.format.DateTimeParseException; + +/** + * WebdavServlet provides WebDAV support (level + * {@link org.apache.jackrabbit.webdav.DavCompliance#_1_ 1}, + * {@link org.apache.jackrabbit.webdav.DavCompliance#_2_ 2}, + * {@link org.apache.jackrabbit.webdav.DavCompliance#_3_ 3} and + * {@link org.apache.jackrabbit.webdav.DavCompliance#BIND bind} compliant) for + * repository resources. + *

+ * Implementations of this abstract class must implement the + * {@link #getRepository()} method to access the repository. + */ +public abstract class SimpleWebdavServlet extends AbstractWebdavServlet { + + /** + * the default logger + */ + private static final Logger log = LoggerFactory.getLogger(SimpleWebdavServlet.class); + + /** + * init param name of the repository prefix + */ + public static final String INIT_PARAM_RESOURCE_PATH_PREFIX = "resource-path-prefix"; + + /** + * Name of the init parameter that specify a separate configuration used + * for filtering the resources displayed. + */ + public static final String INIT_PARAM_RESOURCE_CONFIG = "resource-config"; + + /** + * Name of the parameter that specifies the servlet resource path of + * a custom <mime-info/> configuration file. The default setting + * is to use the MIME media type database included in Apache Tika. + */ + public static final String INIT_PARAM_MIME_INFO = "mime-info"; + + /** + * Servlet context attribute used to store the path prefix instead of + * having a static field with this servlet. The latter causes problems + * when running multiple + */ + public static final String CTX_ATTR_RESOURCE_PATH_PREFIX = "jackrabbit.webdav.simple.resourcepath"; + + /** + * the resource path prefix + */ + private String resourcePathPrefix; + + /** + * Map used to remember any webdav lock created without being reflected + * in the underlying repository. + * This is needed because some clients rely on a successful locking + * mechanism in order to perform properly (e.g. mac OSX built-in dav client) + */ + private LockManager lockManager; + + /** + * the resource factory + */ + private DavResourceFactory resourceFactory; + + /** + * the locator factory + */ + private DavLocatorFactory locatorFactory; + + /** + * the webdav session provider + */ + private DavSessionProvider davSessionProvider; + + /** + * the repository session provider + */ + private SessionProvider sessionProvider; + + /** + * The config + */ + private ResourceConfig config; + + /** + * Init this servlet + * + * @throws ServletException + */ + @Override + public void init() throws ServletException { + super.init(); + + resourcePathPrefix = getInitParameter(INIT_PARAM_RESOURCE_PATH_PREFIX); + if (resourcePathPrefix == null) { + log.debug("Missing path prefix > setting to empty string."); + resourcePathPrefix = ""; + } else if (resourcePathPrefix.endsWith("/")) { + log.debug("Path prefix ends with '/' > removing trailing slash."); + resourcePathPrefix = resourcePathPrefix.substring(0, resourcePathPrefix.length() - 1); + } + getServletContext().setAttribute(CTX_ATTR_RESOURCE_PATH_PREFIX, resourcePathPrefix); + log.info(INIT_PARAM_RESOURCE_PATH_PREFIX + " = '" + resourcePathPrefix + "'"); + + config = new ResourceConfig(getDetector()); + String configParam = getInitParameter(INIT_PARAM_RESOURCE_CONFIG); + if (configParam != null) { + try { + config.parse(getServletContext().getResource(configParam)); + } catch (MalformedURLException e) { + log.debug("Unable to build resource filter provider", e); + } + } + } + + /** + * Reads and returns the configured <mime-info/> database. + * + * @see #INIT_PARAM_MIME_INFO + * @return MIME media type database + * @throws ServletException if the database is invalid or can not be read + */ + private Detector getDetector() throws ServletException { + URL url; + + String mimeInfo = getInitParameter(INIT_PARAM_MIME_INFO); + if (mimeInfo != null) { + try { + url = getServletContext().getResource(mimeInfo); + } catch (MalformedURLException e) { + throw new ServletException( + "Invalid " + INIT_PARAM_MIME_INFO + + " configuration setting: " + mimeInfo, e); + } + } else { + url = MimeTypesFactory.class.getResource("tika-mimetypes.xml"); + } + + try { + return MimeTypesFactory.create(url); + } catch (MimeTypeException e) { + throw new ServletException( + "Invalid MIME media type database: " + url, e); + } catch (IOException e) { + throw new ServletException( + "Unable to read MIME media type database: " + url, e); + } + } + + /** + * {@inheritDoc} + */ + @Override + protected boolean isPreconditionValid(WebdavRequest request, + DavResource resource) { + + long ifUnmodifiedSince = UNDEFINED_TIME; + try { + // will throw if multiple field lines present + String value = AbstractWebdavServlet.getSingletonField(request, "If-Unmodified-Since"); + if (value != null) { + ifUnmodifiedSince = HttpDateTimeFormatter.parse(value); + } + } catch (IllegalArgumentException | DateTimeParseException ex) { + log.debug("illegal value for if-unmodified-since ignored: " + ex.getMessage()); + } + + if (ifUnmodifiedSince > UNDEFINED_TIME && resource.exists()) { + if (resource.getModificationTime() / 1000 > ifUnmodifiedSince / 1000) { + return false; + } + } + + return !resource.exists() || request.matchesIfHeader(resource); + } + + /** + * Returns the configured path prefix + * + * @return resourcePathPrefix + * @see #INIT_PARAM_RESOURCE_PATH_PREFIX + */ + public String getPathPrefix() { + return resourcePathPrefix; + } + + /** + * Returns the configured path prefix + * + * @param ctx The servlet context. + * @return resourcePathPrefix + * @see #INIT_PARAM_RESOURCE_PATH_PREFIX + */ + public static String getPathPrefix(ServletContext ctx) { + return (String) ctx.getAttribute(CTX_ATTR_RESOURCE_PATH_PREFIX); + } + + /** + * Returns the DavLocatorFactory. If no locator factory has + * been set or created a new instance of {@link org.apache.jackrabbit.webdav.simple.LocatorFactoryImpl} is + * returned. + * + * @return the locator factory + * @see AbstractWebdavServlet#getLocatorFactory() + */ + @Override + public DavLocatorFactory getLocatorFactory() { + if (locatorFactory == null) { + locatorFactory = new LocatorFactoryImplEx(resourcePathPrefix); + } + return locatorFactory; + } + + /** + * Sets the DavLocatorFactory. + * + * @param locatorFactory The DavLocatorFactory to use. + * @see AbstractWebdavServlet#setLocatorFactory(DavLocatorFactory) + */ + @Override + public void setLocatorFactory(DavLocatorFactory locatorFactory) { + this.locatorFactory = locatorFactory; + } + + /** + * Returns the LockManager. If no lock manager has + * been set or created a new instance of {@link SimpleLockManager} is + * returned. + * + * @return the lock manager + */ + public LockManager getLockManager() { + if (lockManager == null) { + lockManager = new SimpleLockManager(); + } + return lockManager; + } + + /** + * Sets the LockManager. + * + * @param lockManager The LockManager to be used. + */ + public void setLockManager(LockManager lockManager) { + this.lockManager = lockManager; + } + + /** + * Returns the DavResourceFactory. If no request factory has + * been set or created a new instance of {@link ResourceFactoryImpl} is + * returned. + * + * @return the resource factory + * @see AbstractWebdavServlet#getResourceFactory() + */ + @Override + public DavResourceFactory getResourceFactory() { + if (resourceFactory == null) { + resourceFactory = new ResourceFactoryImpl(getLockManager(), getResourceConfig()); + } + return resourceFactory; + } + + /** + * Sets the DavResourceFactory. + * + * @param resourceFactory The DavResourceFactory to use. + * @see AbstractWebdavServlet#setResourceFactory(org.apache.jackrabbit.webdav.DavResourceFactory) + */ + @Override + public void setResourceFactory(DavResourceFactory resourceFactory) { + this.resourceFactory = resourceFactory; + } + + /** + * Returns the SessionProvider. If no session provider has been + * set or created a new instance of {@link SessionProviderImpl} that extracts + * credentials from the Authorization request header is + * returned. + * + * @return the session provider + */ + public synchronized SessionProvider getSessionProvider() { + if (sessionProvider == null) { + sessionProvider = new SessionProviderImpl(getCredentialsProvider()); + } + return sessionProvider; + } + + /** + * Factory method for creating the credentials provider to be used for + * accessing the credentials associated with a request. The default + * implementation returns a {@link BasicCredentialsProvider} instance, + * but subclasses can override this method to add support for other + * types of credentials. + * + * @return the credentials provider + * @since 1.3 + */ + protected CredentialsProvider getCredentialsProvider() { + return new BasicCredentialsProvider(getInitParameter(INIT_PARAM_MISSING_AUTH_MAPPING)); + } + + /** + * Sets the SessionProvider. + * + * @param sessionProvider The SessionProvider to use. + */ + public synchronized void setSessionProvider(SessionProvider sessionProvider) { + this.sessionProvider = sessionProvider; + } + + /** + * Returns the DavSessionProvider. If no session provider has + * been set or created a new instance of {@link DavSessionProviderImpl} + * is returned. + * + * @return the session provider + * @see AbstractWebdavServlet#getDavSessionProvider() + */ + @Override + public synchronized DavSessionProvider getDavSessionProvider() { + if (davSessionProvider == null) { + davSessionProvider = + new DavSessionProviderImpl(getRepository(), getSessionProvider()); + } + return davSessionProvider; + } + + /** + * Sets the DavSessionProvider. + * + * @param sessionProvider The DavSessionProvider to use. + * @see AbstractWebdavServlet#setDavSessionProvider(org.apache.jackrabbit.webdav.DavSessionProvider) + */ + @Override + public synchronized void setDavSessionProvider(DavSessionProvider sessionProvider) { + this.davSessionProvider = sessionProvider; + } + + /** + * Returns the resource configuration to be applied + * + * @return the resource configuration. + */ + public ResourceConfig getResourceConfig() { + return config; + } + + /** + * Set the resource configuration + * + * @param config The resource configuration. + */ + public void setResourceConfig(ResourceConfig config) { + this.config = config; + } + + /** + * Returns the Repository. If no repository has been set or + * created the repository initialized by RepositoryAccessServlet + * is returned. + * + * @return repository + */ + public abstract Repository getRepository(); + +} Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/simple/SimpleWebdavServlet.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/webdav/simple/VersionControlledResourceImpl.java =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/simple/VersionControlledResourceImpl.java (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/simple/VersionControlledResourceImpl.java (working copy) @@ -0,0 +1,379 @@ +/* + * 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.webdav.simple; + +import javax.jcr.Item; +import javax.jcr.Node; +import javax.jcr.RepositoryException; +import javax.jcr.Value; +import javax.jcr.version.Version; +import javax.jcr.version.VersionHistory; + +import org.apache.jackrabbit.JcrConstants; +import org.apache.jackrabbit.webdav.DavException; +import org.apache.jackrabbit.webdav.DavResource; +import org.apache.jackrabbit.webdav.DavResourceFactory; +import org.apache.jackrabbit.webdav.DavResourceLocator; +import org.apache.jackrabbit.webdav.DavServletResponse; +import org.apache.jackrabbit.webdav.DavSession; +import org.apache.jackrabbit.webdav.MultiStatus; +import org.apache.jackrabbit.webdav.DavMethods; +import org.apache.jackrabbit.webdav.jcr.JcrDavException; +import org.apache.jackrabbit.webdav.property.DefaultDavProperty; +import org.apache.jackrabbit.webdav.property.HrefProperty; +import org.apache.jackrabbit.webdav.version.LabelInfo; +import org.apache.jackrabbit.webdav.version.MergeInfo; +import org.apache.jackrabbit.webdav.version.UpdateInfo; +import org.apache.jackrabbit.webdav.version.VersionControlledResource; +import org.apache.jackrabbit.webdav.version.VersionHistoryResource; +import org.apache.jackrabbit.webdav.version.VersionResource; +import org.apache.jackrabbit.webdav.version.VersionableResource; +import org.apache.jackrabbit.webdav.version.report.ReportType; +import org.apache.jackrabbit.webdav.version.report.SupportedReportSetProperty; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + + + +/** + * VersionControlledResourceImpl represents a JCR node item and + * covers all functionality related to versioning of {@link Node}s. + * + * @see Node + */ +public class VersionControlledResourceImpl extends DeltaVResourceImpl + implements VersionControlledResource { + + private static final Logger log = LoggerFactory.getLogger(VersionControlledResourceImpl.class); + + /** + * Create a new {@link org.apache.jackrabbit.webdav.DavResource}. + * + * @param locator + * @param factory + * @param session + * @param config + * @param item + * @throws DavException + */ + public VersionControlledResourceImpl(DavResourceLocator locator, DavResourceFactory factory, DavSession session, ResourceConfig config, Item item) throws DavException { + super(locator, factory, session, config, item); + initSupportedReports(); + } + + /** + * Create a new {@link org.apache.jackrabbit.webdav.DavResource}. + * + * @param locator + * @param factory + * @param session + * @param config + * @param isCollection + * @throws DavException + */ + public VersionControlledResourceImpl(DavResourceLocator locator, DavResourceFactory factory, DavSession session, ResourceConfig config, boolean isCollection) throws DavException { + super(locator, factory, session, config, isCollection); + initSupportedReports(); + } + + //--------------------------------------------------------< DavResource >--- + /** + * Return a comma separated string listing the supported method names. + * + * @return the supported method names. + * @see org.apache.jackrabbit.webdav.DavResource#getSupportedMethods() + */ + @Override + public String getSupportedMethods() { + StringBuffer sb = new StringBuffer(super.getSupportedMethods()); + // Versioning support + sb.append(", ").append(VersionableResource.METHODS); + if (isVersionControlled()) { + try { + if (getNode().isCheckedOut()) { + sb.append(", ").append(DavMethods.METHOD_CHECKIN); + } else { + sb.append(", ").append(DavMethods.METHOD_CHECKOUT); + sb.append(", ").append(DavMethods.METHOD_LABEL); + } + } catch (RepositoryException e) { + // should not occur. + log.error(e.getMessage()); + } + } + return sb.toString(); + } + + //------------------------------------------< VersionControlledResource >--- + /** + * Adds version control to this resource. If the resource is already under + * version control, this method has no effect. If this resource is a Collection + * resource this method fails with {@link DavServletResponse#SC_METHOD_NOT_ALLOWED}. + * + * @throws org.apache.jackrabbit.webdav.DavException if this resource does not + * exist yet, is a collection or if an error occurs while making the + * underlying node versionable. + * @see org.apache.jackrabbit.webdav.version.VersionableResource#addVersionControl() + */ + public void addVersionControl() throws DavException { + if (!exists()) { + throw new DavException(DavServletResponse.SC_NOT_FOUND); + } + if (isCollection()) { + // since the version-controlled-collection feature is not supported + // collections may not be put under dav version control even if + // the underlying node was / could be made jcr versionable. + throw new DavException(DavServletResponse.SC_METHOD_NOT_ALLOWED); + } + if (!isVersionControlled()) { + Node item = getNode(); + try { + item.addMixin(JcrConstants.MIX_VERSIONABLE); + item.save(); + } catch (RepositoryException e) { + throw new JcrDavException(e); + } + } // else: is already version controlled -> ignore + } + + /** + * Calls {@link javax.jcr.Node#checkin()} on the underlying repository node. + * + * @throws org.apache.jackrabbit.webdav.DavException + * @see org.apache.jackrabbit.webdav.version.VersionControlledResource#checkin() + */ + public String checkin() throws DavException { + if (!exists()) { + throw new DavException(DavServletResponse.SC_NOT_FOUND); + } + if (!isVersionControlled()) { + throw new DavException(DavServletResponse.SC_METHOD_NOT_ALLOWED); + } + try { + Version v = getNode().checkin(); + String versionHref = getLocatorFromNode(v).getHref(false); + return versionHref; + } catch (RepositoryException e) { + // UnsupportedRepositoryException should not occur + throw new JcrDavException(e); + } + } + + /** + * Calls {@link javax.jcr.Node#checkout()} on the underlying repository node. + * + * @throws org.apache.jackrabbit.webdav.DavException + * @see org.apache.jackrabbit.webdav.version.VersionControlledResource#checkout() + */ + public void checkout() throws DavException { + if (!exists()) { + throw new DavException(DavServletResponse.SC_NOT_FOUND); + } + if (!isVersionControlled()) { + throw new DavException(DavServletResponse.SC_METHOD_NOT_ALLOWED); + } + try { + getNode().checkout(); + } catch (RepositoryException e) { + // UnsupportedRepositoryException should not occur + throw new JcrDavException(e); + } + } + + + /** + * UNCHECKOUT cannot be implemented on top of JSR 170 repository. + * Therefore this methods always throws a DavException with error code + * {@link org.apache.jackrabbit.webdav.DavServletResponse#SC_NOT_IMPLEMENTED}. + * + * @throws org.apache.jackrabbit.webdav.DavException + * @see org.apache.jackrabbit.webdav.version.VersionControlledResource#uncheckout() + */ + public void uncheckout() throws DavException { + throw new DavException(DavServletResponse.SC_NOT_IMPLEMENTED); + } + + /** + * UPDATE feature is not (yet) supported. This method allows fails with + * {@link DavServletResponse#SC_NOT_IMPLEMENTED}. + * + * @param updateInfo + * @return + * @throws DavException + * @see VersionControlledResource#update(UpdateInfo) + */ + public MultiStatus update(UpdateInfo updateInfo) throws DavException { + throw new DavException(DavServletResponse.SC_NOT_IMPLEMENTED); + } + + /** + * MERGE feature is not (yet) supported. This method allows fails with + * {@link DavServletResponse#SC_NOT_IMPLEMENTED}. + * + * @param mergeInfo + * @return + * @throws DavException + * @see VersionControlledResource#merge(MergeInfo) + */ + public MultiStatus merge(MergeInfo mergeInfo) throws DavException { + throw new DavException(DavServletResponse.SC_NOT_IMPLEMENTED); + } + + /** + * Modify the labels present with the versions of this resource. + * + * @param labelInfo + * @throws DavException + * @see VersionControlledResource#label(LabelInfo) + * @see javax.jcr.version.VersionHistory#addVersionLabel(String, String, boolean) + * @see javax.jcr.version.VersionHistory#removeVersionLabel(String) + */ + public void label(LabelInfo labelInfo) throws DavException { + if (labelInfo == null) { + throw new DavException(DavServletResponse.SC_BAD_REQUEST, "Valid label request body required."); + } + if (!exists()) { + throw new DavException(DavServletResponse.SC_NOT_FOUND); + } + + try { + if (!isVersionControlled() || getNode().isCheckedOut()) { + throw new DavException(DavServletResponse.SC_PRECONDITION_FAILED, "A LABEL request may only be applied to a version-controlled, checked-in resource."); + } + DavResource[] resArr = this.getReferenceResources(CHECKED_IN); + if (resArr.length == 1 && resArr[0] instanceof VersionResource) { + ((VersionResource)resArr[0]).label(labelInfo); + } else { + throw new DavException(DavServletResponse.SC_INTERNAL_SERVER_ERROR, "DAV:checked-in property on '" + getHref() + "' did not point to a single VersionResource."); + } + } catch (RepositoryException e) { + throw new JcrDavException(e); + } + } + + /** + * Returns the {@link javax.jcr.version.VersionHistory} associated with the repository node. + * If the node is not versionable an exception is thrown. + * + * @return the {@link VersionHistoryResource} associated with this resource. + * @throws org.apache.jackrabbit.webdav.DavException + * @see org.apache.jackrabbit.webdav.version.VersionControlledResource#getVersionHistory() + * @see javax.jcr.Node#getVersionHistory() + */ + public VersionHistoryResource getVersionHistory() throws DavException { + if (!exists()) { + throw new DavException(DavServletResponse.SC_NOT_FOUND); + } + if (!isVersionControlled()) { + throw new DavException(DavServletResponse.SC_FORBIDDEN); + } + try { + VersionHistory vh = getNode().getVersionHistory(); + DavResourceLocator loc = getLocatorFromNode(vh); + DavResource vhr = createResourceFromLocator(loc); + if (vhr instanceof VersionHistoryResource) { + return (VersionHistoryResource)vhr; + } else { + // severe error since resource factory doesn't behave correctly. + throw new DavException(DavServletResponse.SC_INTERNAL_SERVER_ERROR); + } + } catch (RepositoryException e) { + throw new JcrDavException(e); + } + } + + //-------------------------------------------------------------------------- + /** + * Define the set of reports supported by this resource. + * + * @see SupportedReportSetProperty + * @see DeltaVResourceImpl#initSupportedReports() + */ + @Override + protected void initSupportedReports() { + super.initSupportedReports(); + if (exists()) { + supportedReports.addReportType(ReportType.LOCATE_BY_HISTORY); + if (isVersionControlled()) { + supportedReports.addReportType(ReportType.VERSION_TREE); + } + } + } + + /** + * Fill the property set for this resource. + * @see DavResourceImpl#initProperties() + */ + @Override + protected void initProperties() { + if (!propsInitialized) { + super.initProperties(); + if (isVersionControlled()) { + Node n = getNode(); + // properties defined by RFC 3253 for version-controlled resources + try { + // DAV:version-history (computed) + String vhHref = getLocatorFromNode(n.getVersionHistory()).getHref(true); + properties.add(new HrefProperty(VERSION_HISTORY, vhHref, true)); + + // DAV:auto-version property: there is no auto version, explicit CHECKOUT is required. + properties.add(new DefaultDavProperty(AUTO_VERSION, null, true)); + + // baseVersion -> used for DAV:checked-out or DAV:checked-in + String baseVHref = getLocatorFromNode(n.getBaseVersion()).getHref(false); + if (n.isCheckedOut()) { + // DAV:predecessors property + if (n.hasProperty(JcrConstants.JCR_PREDECESSORS)) { + Value[] pv = n.getProperty(JcrConstants.JCR_PREDECESSORS).getValues(); + Node[] predecessors = new Node[pv.length]; + for (int i = 0; i < pv.length; i++) { + predecessors[i] = n.getSession().getNodeByIdentifier(pv[i].getString()); + } + properties.add(getHrefProperty(VersionResource.PREDECESSOR_SET, predecessors, true, false)); + } + // DAV:checked-out property (protected) + properties.add(new HrefProperty(CHECKED_OUT, baseVHref, true)); + } else { + // DAV:checked-in property (protected) + properties.add(new HrefProperty(CHECKED_IN, baseVHref, true)); + } + } catch (RepositoryException e) { + log.error(e.getMessage()); + } + } + } + } + + /** + * @return true, if this resource is a non-collection resource and represents + * an existing repository node that has the mixin nodetype 'mix:versionable' set. + */ + private boolean isVersionControlled() { + boolean vc = false; + // since the version-controlled-collection feature is not supported + // all collection are excluded from version-control even if the + // underlying node was JCR versionable. + if (exists() && !isCollection()) { + Node item = getNode(); + try { + vc = item.isNodeType(JcrConstants.MIX_VERSIONABLE); + } catch (RepositoryException e) { + log.warn(e.getMessage()); + } + } + return vc; + } +} Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/simple/VersionControlledResourceImpl.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/webdav/simple/VersionHistoryResourceImpl.java =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/simple/VersionHistoryResourceImpl.java (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/simple/VersionHistoryResourceImpl.java (working copy) @@ -0,0 +1,235 @@ +/* + * 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.webdav.simple; + +import org.apache.jackrabbit.util.Text; +import org.apache.jackrabbit.webdav.DavException; +import org.apache.jackrabbit.webdav.DavResource; +import org.apache.jackrabbit.webdav.DavResourceFactory; +import org.apache.jackrabbit.webdav.DavResourceLocator; +import org.apache.jackrabbit.webdav.DavServletResponse; +import org.apache.jackrabbit.webdav.DavSession; +import org.apache.jackrabbit.webdav.DavResourceIterator; +import org.apache.jackrabbit.webdav.DavResourceIteratorImpl; +import org.apache.jackrabbit.webdav.MultiStatusResponse; +import org.apache.jackrabbit.webdav.io.InputContext; +import org.apache.jackrabbit.webdav.jcr.JcrDavException; +import org.apache.jackrabbit.webdav.property.HrefProperty; +import org.apache.jackrabbit.webdav.property.ResourceType; +import org.apache.jackrabbit.webdav.property.DavProperty; +import org.apache.jackrabbit.webdav.property.DavPropertyName; +import org.apache.jackrabbit.webdav.property.PropEntry; +import org.apache.jackrabbit.webdav.version.VersionHistoryResource; +import org.apache.jackrabbit.webdav.version.VersionResource; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.jcr.Item; +import javax.jcr.RepositoryException; +import javax.jcr.version.VersionHistory; +import javax.jcr.version.VersionIterator; +import javax.jcr.version.Version; + +import java.util.ArrayList; +import java.util.List; + +/** + * VersionHistoryResourceImpl represents a JCR version history. + * + * @see VersionHistory + */ +public class VersionHistoryResourceImpl extends DeltaVResourceImpl implements VersionHistoryResource { + + private static final Logger log = LoggerFactory.getLogger(VersionHistoryResourceImpl.class); + + public VersionHistoryResourceImpl(DavResourceLocator locator, DavResourceFactory factory, DavSession session, ResourceConfig config, Item item) throws DavException { + super(locator, factory, session, config, item); + if (getNode() == null || !(getNode() instanceof VersionHistory)) { + throw new IllegalArgumentException("VersionHistory item expected."); + } + } + + //--------------------------------------------------------< DavResource >--- + /** + * Show all versions of this history as members. + * + * @return + * @see DavResource#getMembers() + */ + @Override + public DavResourceIterator getMembers() { + ArrayList list = new ArrayList(); + if (exists() && isCollection()) { + try { + // only display versions as members of the vh. the jcr:versionLabels + // node is an internal structure. + VersionIterator it = ((VersionHistory) getNode()).getAllVersions(); + while (it.hasNext()) { + // omit item filter here. if the version history is visible + // its versions should be visible as well. + Version v = it.nextVersion(); + DavResourceLocator vhLocator = getLocator(); + DavResourceLocator resourceLocator = vhLocator.getFactory().createResourceLocator(vhLocator.getPrefix(), vhLocator.getWorkspacePath(), v.getPath(), false); + DavResource childRes = getFactory().createResource(resourceLocator, getSession()); + list.add(childRes); + } + } catch (RepositoryException e) { + // should not occur + log.error("Unexpected error",e); + } catch (DavException e) { + // should not occur + log.error("Unexpected error",e); + } + } + return new DavResourceIteratorImpl(list); + } + + /** + * The version storage is read-only -> fails with 403. + * + * @see DavResource#addMember(DavResource, InputContext) + */ + @Override + public void addMember(DavResource member, InputContext inputContext) throws DavException { + throw new DavException(DavServletResponse.SC_FORBIDDEN); + } + + /** + * Removing a version resource is achieved by calling removeVersion + * on the versionhistory item this version belongs to. + * + * @throws DavException if the version does not exist or if an error occurs + * while deleting. + * @see DavResource#removeMember(org.apache.jackrabbit.webdav.DavResource) + */ + @Override + public void removeMember(DavResource member) throws DavException { + if (exists()) { + VersionHistory versionHistory = (VersionHistory) getNode(); + try { + String itemPath = member.getLocator().getRepositoryPath(); + // Retrieve the last segment of the given path and removes the index if present. + if (itemPath == null) { + throw new IllegalArgumentException("Cannot retrieve name from a 'null' item path."); + } + String name = Text.getName(itemPath); + // remove index + if (name.endsWith("]")) { + name = name.substring(0, name.lastIndexOf('[')); + } + versionHistory.removeVersion(name); + } catch (RepositoryException e) { + throw new JcrDavException(e); + } + } else { + throw new DavException(DavServletResponse.SC_NOT_FOUND); + } + } + + /** + * Version storage is read-only -> fails with 403. + * + * @see DavResource#setProperty(DavProperty) + */ + @Override + public void setProperty(DavProperty property) throws DavException { + throw new DavException(DavServletResponse.SC_FORBIDDEN); + } + + /** + * Version storage is read-only -> fails with 403. + * + * @see DavResource#removeProperty(DavPropertyName) + */ + @Override + public void removeProperty(DavPropertyName propertyName) throws DavException { + throw new DavException(DavServletResponse.SC_FORBIDDEN); + } + + /** + * Version storage is read-only -> fails with 403. + * + * @see DavResource#alterProperties(List) + */ + @Override + public MultiStatusResponse alterProperties(List changeList) throws DavException { + throw new DavException(DavServletResponse.SC_FORBIDDEN); + } + + //---------------------------------------------< VersionHistoryResource >--- + /** + * Return an array of {@link org.apache.jackrabbit.webdav.version.VersionResource}s representing all versions + * present in the underlying JCR version history. + * + * @return array of {@link org.apache.jackrabbit.webdav.version.VersionResource}s representing all versions + * present in the underlying JCR version history. + * @throws org.apache.jackrabbit.webdav.DavException + * @see org.apache.jackrabbit.webdav.version.VersionHistoryResource#getVersions() + */ + public VersionResource[] getVersions() throws DavException { + try { + VersionIterator vIter = ((VersionHistory)getNode()).getAllVersions(); + ArrayList l = new ArrayList(); + while (vIter.hasNext()) { + DavResourceLocator versionLoc = getLocatorFromNode(vIter.nextVersion()); + DavResource vr = createResourceFromLocator(versionLoc); + if (vr instanceof VersionResource) { + l.add((VersionResource) vr); + } else { + // severe error since resource factory doesn't behave correctly. + throw new DavException(DavServletResponse.SC_INTERNAL_SERVER_ERROR); + } + } + return l.toArray(new VersionResource[l.size()]); + } catch (RepositoryException e) { + throw new JcrDavException(e); + } + } + + //-------------------------------------------------------------------------- + /** + * Fill the property set for this resource. + */ + @Override + protected void initProperties() { + if (!propsInitialized) { + super.initProperties(); + + // change resource type defined by default item collection + properties.add(new ResourceType(new int[] {ResourceType.COLLECTION, ResourceType.VERSION_HISTORY})); + + // required root-version property for version-history resource + try { + String rootVersionHref = getLocatorFromNode(((VersionHistory)getNode()).getRootVersion()).getHref(false); + properties.add(new HrefProperty(VersionHistoryResource.ROOT_VERSION, rootVersionHref, false)); + } catch (RepositoryException e) { + log.error(e.getMessage()); + } + + // required, protected version-set property for version-history resource + try { + VersionIterator vIter = ((VersionHistory)getNode()).getAllVersions(); + ArrayList l = new ArrayList(); + while (vIter.hasNext()) { + l.add(vIter.nextVersion()); + } + properties.add(getHrefProperty(VersionHistoryResource.VERSION_SET, l.toArray(new Version[l.size()]), true, false)); + } catch (RepositoryException e) { + log.error(e.getMessage()); + } + } + } +} Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/simple/VersionHistoryResourceImpl.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/webdav/simple/VersionResourceImpl.java =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/simple/VersionResourceImpl.java (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/simple/VersionResourceImpl.java (working copy) @@ -0,0 +1,287 @@ +/* + * 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.webdav.simple; + +import org.apache.jackrabbit.JcrConstants; +import org.apache.jackrabbit.webdav.DavException; +import org.apache.jackrabbit.webdav.DavResource; +import org.apache.jackrabbit.webdav.DavResourceFactory; +import org.apache.jackrabbit.webdav.DavResourceLocator; +import org.apache.jackrabbit.webdav.DavServletResponse; +import org.apache.jackrabbit.webdav.DavSession; +import org.apache.jackrabbit.webdav.DavResourceIterator; +import org.apache.jackrabbit.webdav.DavResourceIteratorImpl; +import org.apache.jackrabbit.webdav.MultiStatusResponse; +import org.apache.jackrabbit.webdav.util.HttpDateFormat; +import org.apache.jackrabbit.webdav.io.InputContext; +import org.apache.jackrabbit.webdav.jcr.JcrDavException; +import org.apache.jackrabbit.webdav.property.DavPropertyName; +import org.apache.jackrabbit.webdav.property.DefaultDavProperty; +import org.apache.jackrabbit.webdav.property.HrefProperty; +import org.apache.jackrabbit.webdav.property.DavProperty; +import org.apache.jackrabbit.webdav.property.PropEntry; +import org.apache.jackrabbit.webdav.version.LabelInfo; +import org.apache.jackrabbit.webdav.version.LabelSetProperty; +import org.apache.jackrabbit.webdav.version.VersionHistoryResource; +import org.apache.jackrabbit.webdav.version.VersionResource; +import org.apache.jackrabbit.webdav.version.report.ReportType; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.jcr.Item; +import javax.jcr.Node; +import javax.jcr.Property; +import javax.jcr.PropertyIterator; +import javax.jcr.RepositoryException; +import javax.jcr.version.Version; +import javax.jcr.version.VersionHistory; + +import java.util.ArrayList; +import java.util.List; + +/** + * VersionResourceImpl represents a JCR version. + * + * @see Version + */ +public class VersionResourceImpl extends DeltaVResourceImpl implements VersionResource { + + private static final Logger log = LoggerFactory.getLogger(VersionResourceImpl.class); + + /** + * Create a new {@link org.apache.jackrabbit.webdav.DavResource}. + * @param locator + * @param factory + * @param session + * @param config + * @param item + * @throws DavException + * + */ + public VersionResourceImpl(DavResourceLocator locator, DavResourceFactory factory, DavSession session, ResourceConfig config, Item item) throws DavException { + super(locator, factory, session, config, item); + if (getNode() == null || !(getNode() instanceof Version)) { + throw new IllegalArgumentException("Version item expected."); + } + } + + //--------------------------------------------------------< DavResource >--- + /** + * Since this implementation of VersionResource never is a + * version belonging to a version controlled collection, this method always + * returns false not respecting the configuration. + * + * @return always false + */ + @Override + public boolean isCollection() { + return false; + } + + /** + * @return An empty DavResourceIterator + */ + @Override + public DavResourceIterator getMembers() { + return DavResourceIteratorImpl.EMPTY; + } + + /** + * The version storage is read-only -> fails with 403. + * + * @see DavResource#addMember(DavResource, InputContext) + */ + @Override + public void addMember(DavResource member, InputContext inputContext) throws DavException { + throw new DavException(DavServletResponse.SC_FORBIDDEN); + } + + /** + * The version storage is read-only -> fails with 403. + * + * @see DavResource#removeMember(DavResource) + */ + @Override + public void removeMember(DavResource member) throws DavException { + throw new DavException(DavServletResponse.SC_FORBIDDEN); + } + + /** + * Version storage is read-only -> fails with 403. + * + * @see DavResource#setProperty(DavProperty) + */ + @Override + public void setProperty(DavProperty property) throws DavException { + throw new DavException(DavServletResponse.SC_FORBIDDEN); + } + + /** + * Version storage is read-only -> fails with 403. + * + * @see DavResource#removeProperty(DavPropertyName) + */ + @Override + public void removeProperty(DavPropertyName propertyName) throws DavException { + throw new DavException(DavServletResponse.SC_FORBIDDEN); + } + + /** + * Version storage is read-only -> fails with 403. + * + * @see DavResource#alterProperties(List) + */ + @Override + public MultiStatusResponse alterProperties(List changeList) throws DavException { + throw new DavException(DavServletResponse.SC_FORBIDDEN); + } + + //----------------------------------------------------< VersionResource >--- + /** + * Modify the labels defined for the underlying repository version. + * + * @param labelInfo + * @throws org.apache.jackrabbit.webdav.DavException + * @see VersionResource#label(org.apache.jackrabbit.webdav.version.LabelInfo) + * @see javax.jcr.version.VersionHistory#addVersionLabel(String, String, boolean) + * @see javax.jcr.version.VersionHistory#removeVersionLabel(String) + */ + public void label(LabelInfo labelInfo) throws DavException { + if (labelInfo == null) { + throw new DavException(DavServletResponse.SC_BAD_REQUEST, "Valid label request body required."); + } + if (!exists()) { + throw new DavException(DavServletResponse.SC_NOT_FOUND); + } + try { + VersionHistory vh = getVersionHistoryItem(); + if (labelInfo.getType() == LabelInfo.TYPE_REMOVE) { + vh.removeVersionLabel(labelInfo.getLabelName()); + } else if (labelInfo.getType() == LabelInfo.TYPE_ADD) { + // ADD: only add if not yet existing + vh.addVersionLabel(getNode().getName(), labelInfo.getLabelName(), false); + } else { + // SET: move label if already existing + vh.addVersionLabel(getNode().getName(), labelInfo.getLabelName(), true); + } + } catch (RepositoryException e) { + throw new JcrDavException(e); + } + } + + /** + * Returns the {@link VersionHistory} associated with the repository version. + * Note: in contrast to a versionable node, the version history of a version + * item is always represented by its nearest ancestor. + * + * @return the {@link org.apache.jackrabbit.webdav.version.VersionHistoryResource} associated with this resource. + * @throws org.apache.jackrabbit.webdav.DavException + * @see org.apache.jackrabbit.webdav.version.VersionResource#getVersionHistory() + * @see javax.jcr.Item#getParent() + */ + public VersionHistoryResource getVersionHistory() throws DavException { + if (!exists()) { + throw new DavException(DavServletResponse.SC_NOT_FOUND); + } + + try { + VersionHistory vh = getVersionHistoryItem(); + DavResourceLocator loc = getLocatorFromNode(vh); + DavResource vhr = createResourceFromLocator(loc); + if (vhr instanceof VersionHistoryResource) { + return (VersionHistoryResource)vhr; + } else { + // severe error since resource factory doesn't behave correctly. + throw new DavException(DavServletResponse.SC_INTERNAL_SERVER_ERROR); + } + } catch (RepositoryException e) { + throw new JcrDavException(e); + } + } + + /** + * Return versionhistory that contains this version item + * + * @return versionhistory that contains this version item + * @throws RepositoryException + * @see javax.jcr.version.Version#getContainingHistory() + */ + private VersionHistory getVersionHistoryItem() throws RepositoryException { + return ((Version)getNode()).getContainingHistory(); + } + + //-------------------------------------------------------------------------- + /** + * Define the set of reports supported by this resource. + * + * @see org.apache.jackrabbit.webdav.version.report.SupportedReportSetProperty + */ + @Override + protected void initSupportedReports() { + super.initSupportedReports(); + if (exists()) { + supportedReports.addReportType(ReportType.VERSION_TREE); + } + } + + /** + * Fill the property set for this resource. + */ + @Override + protected void initProperties() { + if (!propsInitialized) { + super.initProperties(); + Version v = (Version) getNode(); + try { + String creationDate = HttpDateFormat.creationDateFormat().format(v.getCreated().getTime()); + // replace dummy creation date from default collection + properties.add(new DefaultDavProperty(DavPropertyName.CREATIONDATE, creationDate)); + + // required, protected DAV:version-name property + properties.add(new DefaultDavProperty(VERSION_NAME, v.getName(), true)); + + // required, protected DAV:label-name-set property + String[] labels = getVersionHistoryItem().getVersionLabels(v); + properties.add(new LabelSetProperty(labels)); + + // required DAV:predecessor-set (protected) and DAV:successor-set (computed) properties + properties.add(getHrefProperty(VersionResource.PREDECESSOR_SET, v.getPredecessors(), true, false)); + properties.add(getHrefProperty(SUCCESSOR_SET, v.getSuccessors(), true, false)); + + // required DAV:version-history (computed) property + String vhHref = getLocatorFromNode(getVersionHistoryItem()).getHref(true); + properties.add(new HrefProperty(VersionResource.VERSION_HISTORY, vhHref, true)); + + // required DAV:checkout-set (computed) property + PropertyIterator it = v.getReferences(); + List nodeList = new ArrayList(); + while (it.hasNext()) { + Property p = it.nextProperty(); + if (JcrConstants.JCR_BASEVERSION.equals(p.getName())) { + Node n = p.getParent(); + if (n.isCheckedOut()) { + nodeList.add(n); + } + } + } + properties.add(getHrefProperty(CHECKOUT_SET, nodeList.toArray(new Node[nodeList.size()]), true, false)); + + } catch (RepositoryException e) { + log.error(e.getMessage()); + } + } + } +} Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/simple/VersionResourceImpl.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/javadoc/org/apache/jackrabbit/server/io/package.html =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/javadoc/org/apache/jackrabbit/server/io/package.html (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/javadoc/org/apache/jackrabbit/server/io/package.html (working copy) @@ -0,0 +1,21 @@ + + +The jackrabbit webdav server uses the classes defined in this package in order +to perform import and export operations in order to respond to PUT, MKCOL, PROPPATCH +and PROPFIND, GET, HEAD requests, respectively. + Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/javadoc/org/apache/jackrabbit/server/io/package.html ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/javadoc/org/apache/jackrabbit/webdav/jcr/package.html =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/javadoc/org/apache/jackrabbit/webdav/jcr/package.html (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/javadoc/org/apache/jackrabbit/webdav/jcr/package.html (working copy) @@ -0,0 +1,19 @@ + + +Contains JCR specific implementations. + Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/javadoc/org/apache/jackrabbit/webdav/jcr/package.html ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/javadoc/org/apache/jackrabbit/webdav/jcr/version/package.html =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/javadoc/org/apache/jackrabbit/webdav/jcr/version/package.html (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/javadoc/org/apache/jackrabbit/webdav/jcr/version/package.html (working copy) @@ -0,0 +1,25 @@ + + +Contains JCR specific implementations for the following interfaces: +

    +
  • VersionableResource
  • +
  • VersionControlledResource
  • +
  • VersionResource
  • +
  • VersionHistoryResource
  • +
+ Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/javadoc/org/apache/jackrabbit/webdav/jcr/version/package.html ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/javadoc/org/apache/jackrabbit/webdav/jcr/version/report/package.html =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/javadoc/org/apache/jackrabbit/webdav/jcr/version/report/package.html (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/javadoc/org/apache/jackrabbit/webdav/jcr/version/report/package.html (working copy) @@ -0,0 +1,19 @@ + + +Contains JCR specific reports. + Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/javadoc/org/apache/jackrabbit/webdav/jcr/version/report/package.html ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/resources/OSGI-INF/l10n/metatype.properties =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/resources/OSGI-INF/l10n/metatype.properties (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/resources/OSGI-INF/l10n/metatype.properties (working copy) @@ -0,0 +1,58 @@ +# +# 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. +# + + +# +# This file contains localization strings for configuration labels and +# descriptions as used in the metatype.xml descriptor generated by the +# the SCR plugin + +dav.name = Apache Jackrabbit DavEx Servlet +dav.description = The DavEx Servlet allows direct access to the \ + complete Repository. + +alias.name = Root Path +alias.description = The root path at which the DavEx Servlet is \ + accessible. The default value is "/server". + +missing-auth-mapping.name = Missing Credentials Handling +missing-auth-mapping.description = Defines how a missing authorization \ + header should be handled. If this property is missing, a 401 response \ + is generated. This is suiteable for clients (eg. webdav clients) for \ + which sending a proper authorization header is not possible if the \ + server never sent a 401. If this property is present with an empty \ + value, null-credentials are returned, thus forcing an null login \ + on the repository. If this propert is present with the value \ + 'guestcredentials' java.jcr.GuestCredentials are used to login to the \ + repository. If this property has a 'user:password' value, the \ + respective simple credentials are generated. + +authenticate-header.name = Realm> +authenticate-header.description = Defines the value of the \ + 'WWW-Authenticate' header. Default is 'Basic realm="Jackrabbit Webdav Server"'. + +csrf-protection.name = CSRF Protection +csrf-protection.description = Configuration of referrer based CSRF \ + protection. If config is not configured or empty string the default \ + behaviour is to allow only requests with an empty referrer header or a \ + referrer host equal to the server host. A comma separated list of \ + additional allowed referrer hosts which are valid in addition to default \ + behaviour (see above). The value "disabled" may be used to disable the \ + referrer checking altogether. The default is "disabled" assuming that \ + a site-wide CSRF protection filter is installed. Index: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/server/BasicCredentialsProviderTest.java =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/server/BasicCredentialsProviderTest.java (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/server/BasicCredentialsProviderTest.java (working copy) @@ -0,0 +1,385 @@ +/* + * 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 junit.framework.TestCase; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.servlet.http.Cookie; +import javax.servlet.http.HttpSession; +import javax.servlet.http.HttpUpgradeHandler; +import javax.servlet.http.Part; +import javax.servlet.ServletInputStream; +import javax.servlet.ServletRequest; +import javax.servlet.ServletResponse; +import javax.servlet.AsyncContext; +import javax.servlet.DispatcherType; +import javax.servlet.RequestDispatcher; +import javax.servlet.ServletContext; +import javax.servlet.ServletException; +import javax.jcr.LoginException; +import javax.jcr.Credentials; +import javax.jcr.SimpleCredentials; +import javax.jcr.GuestCredentials; + +import java.util.Collection; +import java.util.Enumeration; +import java.util.Map; +import java.util.Locale; +import java.util.HashMap; +import java.security.Principal; +import java.io.UnsupportedEncodingException; +import java.io.IOException; +import java.io.BufferedReader; + +/** + * BasicCredentialsProviderTest... + */ +public class BasicCredentialsProviderTest extends TestCase { + + public void testMissingDefaultHeader() throws ServletException { + CredentialsProvider cb = new BasicCredentialsProvider(null); + try { + Credentials creds = cb.getCredentials(new RequestImpl(null)); + fail("LoginException expected"); + } catch (LoginException e) { + // ok + } + } + + public void testGuestCredentialsDefaultHeader() throws ServletException, LoginException { + CredentialsProvider cb = new BasicCredentialsProvider(BasicCredentialsProvider.GUEST_DEFAULT_HEADER_VALUE); + Credentials creds = cb.getCredentials(new RequestImpl(null)); + + assertTrue(creds instanceof GuestCredentials); + } + + public void testEmptyDefaultHeader() throws ServletException, LoginException { + CredentialsProvider cb = new BasicCredentialsProvider(BasicCredentialsProvider.EMPTY_DEFAULT_HEADER_VALUE); + Credentials creds = cb.getCredentials(new RequestImpl(null)); + + assertNull(creds); + } + + public void testDefaultPassword() throws ServletException, LoginException { + Map m = new HashMap(); + m.put("userId", new char[0]); + m.put("userId:", new char[0]); + m.put("userId:pw", "pw".toCharArray()); + + for (String uid : m.keySet()) { + char[] pw = m.get(uid); + + CredentialsProvider cb = new BasicCredentialsProvider(uid); + Credentials creds = cb.getCredentials(new RequestImpl(null)); + + assertNotNull(creds); + assertTrue(creds instanceof SimpleCredentials); + assertEquals("userId", ((SimpleCredentials) creds).getUserID()); + if (pw.length == 0) { + assertEquals(0, ((SimpleCredentials) creds).getPassword().length); + } else { + assertEquals(new String(pw), new String(((SimpleCredentials) creds).getPassword())); + } + } + } + + + + + private class RequestImpl implements HttpServletRequest { + + private final String authHeader; + + private RequestImpl(String authHeader) { + this.authHeader = authHeader; + } + + public String getAuthType() { + return null; + } + + public Cookie[] getCookies() { + return new Cookie[0]; + } + + public long getDateHeader(String name) { + return 0; + } + + public String getHeader(String name) { + return authHeader; + } + + public Enumeration getHeaders(String name) { + return null; + } + + public Enumeration getHeaderNames() { + return null; + } + + public int getIntHeader(String name) { + return 0; + } + + public String getMethod() { + return null; + } + + public String getPathInfo() { + return null; + } + + public String getPathTranslated() { + return null; + } + + public String getContextPath() { + return null; + } + + public String getQueryString() { + return null; + } + + public String getRemoteUser() { + return null; + } + + public boolean isUserInRole(String role) { + return false; + } + + public Principal getUserPrincipal() { + return null; + } + + public String getRequestedSessionId() { + return null; + } + + public String getRequestURI() { + return null; + } + + public StringBuffer getRequestURL() { + return null; + } + + public String getServletPath() { + return null; + } + + public HttpSession getSession(boolean create) { + return null; + } + + public HttpSession getSession() { + return null; + } + + public boolean isRequestedSessionIdValid() { + return false; + } + + public boolean isRequestedSessionIdFromCookie() { + return false; + } + + public boolean isRequestedSessionIdFromURL() { + return false; + } + + public boolean isRequestedSessionIdFromUrl() { + return false; + } + + public Object getAttribute(String name) { + return null; + } + + public Enumeration getAttributeNames() { + return null; + } + + public String getCharacterEncoding() { + return null; + } + + public void setCharacterEncoding(String s) throws UnsupportedEncodingException { + } + + public int getContentLength() { + return 0; + } + + public String getContentType() { + return null; + } + + public ServletInputStream getInputStream() throws IOException { + return null; + } + + public String getParameter(String name) { + return null; + } + + public Enumeration getParameterNames() { + return null; + } + + public String[] getParameterValues(String name) { + return new String[0]; + } + + public Map getParameterMap() { + return null; + } + + public String getProtocol() { + return null; + } + + public String getScheme() { + return null; + } + + public String getServerName() { + return null; + } + + public int getServerPort() { + return 0; + } + + public BufferedReader getReader() throws IOException { + return null; + } + + public String getRemoteAddr() { + return null; + } + + public String getRemoteHost() { + return null; + } + + public void setAttribute(String name, Object o) { + } + + public void removeAttribute(String name) { + } + + public Locale getLocale() { + return null; + } + + public Enumeration getLocales() { + return null; + } + + public boolean isSecure() { + return false; + } + + public RequestDispatcher getRequestDispatcher(String path) { + return null; + } + + public String getRealPath(String path) { + return null; + } + + public int getRemotePort() { + return 0; + } + + public String getLocalName() { + return null; + } + + public String getLocalAddr() { + return null; + } + + public int getLocalPort() { + return 0; + } + + public long getContentLengthLong() { + return 0; + } + + public ServletContext getServletContext() { + return null; + } + + public AsyncContext startAsync() throws IllegalStateException { + return null; + } + + public AsyncContext startAsync(ServletRequest servletRequest, ServletResponse servletResponse) + throws IllegalStateException { + return null; + } + + public boolean isAsyncStarted() { + return false; + } + + public boolean isAsyncSupported() { + return false; + } + + public AsyncContext getAsyncContext() { + return null; + } + + public DispatcherType getDispatcherType() { + return null; + } + + public String changeSessionId() { + return null; + } + + public boolean authenticate(HttpServletResponse response) throws IOException, ServletException { + return false; + } + + public void login(String username, String password) throws ServletException { + } + + public void logout() throws ServletException { + } + + public Collection getParts() throws IOException, ServletException { + return null; + } + + public Part getPart(String name) throws IOException, ServletException { + return null; + } + + public T upgrade(Class handlerClass) throws IOException, ServletException { + return null; + } + } +} Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/server/BasicCredentialsProviderTest.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/test/java/org/apache/jackrabbit/server/TestAll.java =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/server/TestAll.java (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/server/TestAll.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 junit.framework.Test; +import junit.framework.TestCase; +import junit.framework.TestSuite; + +/** + * Test suite that includes all testcases for package org.apache.jackrabbit.server. + */ +public class TestAll extends TestCase { + + /** + * Returns a Test suite that executes all tests inside this + * package. + */ + public static Test suite() { + TestSuite suite = new TestSuite("org.apache.jackrabbit.server tests"); + + suite.addTestSuite(BasicCredentialsProviderTest.class); + + return suite; + } +} Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/server/TestAll.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/test/java/org/apache/jackrabbit/server/remoting/davex/BatchReadConfigTest.java =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/server/remoting/davex/BatchReadConfigTest.java (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/server/remoting/davex/BatchReadConfigTest.java (working copy) @@ -0,0 +1,86 @@ +/* + * 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.remoting.davex; + +import junit.framework.TestCase; + +import java.util.Properties; + +/** + * BatchReadConfigTest... + */ +public class BatchReadConfigTest extends TestCase { + + public void testDefaultDepth() { + BatchReadConfig cnf = new BatchReadConfig(); + + assertEquals(BatchReadConfig.DEPTH_DEFAULT, cnf.getDefaultDepth()); + assertEquals(cnf.getDefaultDepth(), cnf.getDepth("nt:base")); + + cnf.setDefaultDepth(5); + assertEquals(5, cnf.getDefaultDepth()); + assertEquals(cnf.getDefaultDepth(), cnf.getDepth("nt:base")); + + cnf.setDefaultDepth(BatchReadConfig.DEPTH_INFINITE); + assertEquals(BatchReadConfig.DEPTH_INFINITE, cnf.getDefaultDepth()); + assertEquals(cnf.getDefaultDepth(), cnf.getDepth("nt:base")); + + try { + cnf.setDefaultDepth(-12); + fail("Invalid depth"); + } catch (IllegalArgumentException e) { + //ok + } + } + + public void testDepth() { + BatchReadConfig cnf = new BatchReadConfig(); + + cnf.setDepth("nt:file", 15); + assertEquals(15, cnf.getDepth("nt:file")); + assertEquals(cnf.getDefaultDepth(), cnf.getDepth("nt:base")); + + cnf.setDepth("nt:file", BatchReadConfig.DEPTH_INFINITE); + assertEquals(BatchReadConfig.DEPTH_INFINITE, cnf.getDepth("nt:file")); + assertEquals(cnf.getDefaultDepth(), cnf.getDepth("nt:base")); + + try { + cnf.setDepth("nt:file",-12); + fail("Invalid depth"); + } catch (IllegalArgumentException e) { + //ok + } + } + + public void testAdd() { + Properties props = new Properties(); + props.setProperty("nt:file", "15"); + props.setProperty("default", "-1"); + + BatchReadConfig cnf = new BatchReadConfig(); + cnf.add(props); + + assertEquals(15, cnf.getDepth("nt:file")); + assertEquals(BatchReadConfig.DEPTH_INFINITE, cnf.getDefaultDepth()); + assertEquals(cnf.getDefaultDepth(), cnf.getDepth("nt:base")); + + cnf.setDefaultDepth(BatchReadConfig.DEPTH_DEFAULT); + assertEquals(15, cnf.getDepth("nt:file")); + assertEquals(BatchReadConfig.DEPTH_DEFAULT, cnf.getDefaultDepth()); + assertEquals(cnf.getDefaultDepth(), cnf.getDepth("nt:base")); + } +} \ No newline at end of file Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/server/remoting/davex/BatchReadConfigTest.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/test/java/org/apache/jackrabbit/server/remoting/davex/DiffParserTest.java =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/server/remoting/davex/DiffParserTest.java (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/server/remoting/davex/DiffParserTest.java (working copy) @@ -0,0 +1,385 @@ +/* + * 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.remoting.davex; + +import junit.framework.TestCase; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +/** DiffParserTest... */ +public class DiffParserTest extends TestCase { + + public void testSetProperty() throws IOException, DiffException { + ArrayList l = new ArrayList(); + l.add("\"simple string\""); + l.add("2345"); + l.add("true"); + l.add("false"); + l.add("234.3455"); + l.add("null"); + + for (final String value : l) { + String diff = "^/a/prop : " + value; + + DummyDiffHandler handler = new DummyDiffHandler() { + @Override + public void setProperty(String targetPath, String diffValue) { + assertEquals(targetPath, "/a/prop"); + assertEquals(value, diffValue); + } + }; + DiffParser parser = new DiffParser(handler); + parser.parse(diff); + } + } + + public void testSetPropertyMissing() throws IOException, + DiffException { + ArrayList l = new ArrayList(); + l.add(""); + l.add(null); + + for (String value : l) { + String diff = "^/a/prop : " + ((value == null) ? "" : value); + + DummyDiffHandler handler = new DummyDiffHandler() { + @Override + public void setProperty(String targetPath, String diffValue) { + assertEquals(targetPath, "/a/prop"); + assertTrue(diffValue == null || "".equals(diffValue)); + } + }; + DiffParser parser = new DiffParser(handler); + parser.parse(diff); + } + } + + public void testSetPropertyWithUnicodeChars() throws IOException, + DiffException { + final String value = "\"String value containing \u2355\u8723 unicode chars.\""; + String diff = "^/a/prop : " + value; + + DiffHandler handler = new DummyDiffHandler() { + @Override + public void setProperty(String targetPath, String diffValue) { + assertEquals(targetPath, "/a/prop"); + assertEquals(value, diffValue); + } + }; + + DiffParser parser = new DiffParser(handler); + parser.parse(diff); + } + + public void testSetPropertyWithTrailingLineSep() throws IOException, + DiffException { + final String value = "\"String value ending with \r\r\n\n\r\n.\""; + String diff = "^/a/prop : " + value; + + DiffHandler handler = new DummyDiffHandler() { + @Override + public void setProperty(String targetPath, String diffValue) { + assertEquals(targetPath, "/a/prop"); + assertEquals(value, diffValue); + } + }; + + DiffParser parser = new DiffParser(handler); + parser.parse(diff); + } + + public void testSetPropertyWithSpecialChar() throws IOException, DiffException { + final String value = "+abc \\r+ \\n-ab >c \r\\r\\n+"; + String diff = "^/a/prop : " + value; + + DiffHandler handler = new DummyDiffHandler() { + @Override + public void setProperty(String targetPath, String diffValue) { + assertEquals(targetPath, "/a/prop"); + assertEquals(value, diffValue); + } + }; + + DiffParser parser = new DiffParser(handler); + parser.parse(diff); + } + + public void testSetPropertyUnterminatedString() throws IOException, + DiffException { + final String value = "\"String value ending with \r\r\n\n\r\n."; + String diff = "^/a/prop : " + value; + + DiffHandler handler = new DummyDiffHandler() { + @Override + public void setProperty(String targetPath, String diffValue) { + assertEquals(targetPath, "/a/prop"); + assertEquals(value, diffValue); + } + }; + DiffParser parser = new DiffParser(handler); + parser.parse(diff); + } + + public void testSetPropertyWithUnescapedAction() throws IOException, + DiffException { + String diff = "^abc : \r+def : \n-ghi : \r\n^jkl : \n\r>mno : \n"; + + DiffHandler handler = new DummyDiffHandler() { + @Override + public void addNode(String targetPath, String diffValue) { + assertEquals("def", targetPath); + assertEquals("", diffValue); + } + @Override + public void setProperty(String targetPath, String diffValue) { + assertTrue("abc".equals(targetPath) || "jkl".equals(targetPath)); + assertEquals("", diffValue); + } + @Override + public void remove(String targetPath, String diffValue) { + assertEquals("ghi", targetPath); + assertEquals("", diffValue); + } + + @Override + public void move(String targetPath, String diffValue) { + assertEquals("mno", targetPath); + assertEquals("\n", diffValue); + } + }; + + DiffParser parser = new DiffParser(handler); + parser.parse(diff); + } + + public void testValidDiffs() throws IOException, DiffException { + List l = new ArrayList(); + // unquoted string value + l.add(new String[] {"+/a/b : 134", "/a/b","134"}); + l.add(new String[] {"+/a/b : 2.3", "/a/b","2.3"}); + l.add(new String[] {"+/a/b : true", "/a/b","true"}); + // quoted string value + l.add(new String[] {"+/a/b : \"true\"", "/a/b","\"true\""}); + l.add(new String[] {"+/a/b : \"string value containing \u3456 unicode char.\"", "/a/b","\"string value containing \u3456unicode char.\""}); + // value consisting of quotes + l.add(new String[] {"+/a/b : \"", "/a/b","\""}); + l.add(new String[] {"+/a/b : \"\"", "/a/b","\"\""}); + // value consisting of single + l.add(new String[] {"+/a/b : '", "/a/b","'"}); + l.add(new String[] {"+/a/b : ''''", "/a/b","''''"}); + // value consisting of space(s) only + l.add(new String[] {"+/a/b : ", "/a/b"," "}); + l.add(new String[] {"+/a/b : ", "/a/b"," "}); + // value consisting of line separators only + l.add(new String[] {"+/a/b : \n", "/a/b","\n"}); + l.add(new String[] {"+/a/b : \r", "/a/b","\r"}); + l.add(new String[] {"+/a/b : \r\n", "/a/b","\r\n"}); + l.add(new String[] {"+/a/b : \r\n\n\r", "/a/b","\r\n\n\r"}); + // path containing white space + l.add(new String[] {"+/a /b : 123", "/a /b","123"}); + l.add(new String[] {"+/a\r\t/b : 123", "/a\r\t/b","123"}); + // path having trailing white space + l.add(new String[] {"+/a/b : 123", "/a/b","123"}); + l.add(new String[] {"+/a/b\r : 123", "/a/b\r","123"}); + l.add(new String[] {"+/a/b\r\n\n\r\n: 123", "/a/b\r\n\n\r\n","123"}); + // path containing reserved characters + l.add(new String[] {"++abc+ : val", "+abc+","val"}); + l.add(new String[] {"++++++ : val", "+++++","val"}); + // value containing reserved characters + l.add(new String[] {"+/a/b : +", "/a/b","+"}); + l.add(new String[] {"+/a/b : +->+-", "/a/b","+->+-"}); + l.add(new String[] {"+/a/b : \"+->+-\"", "/a/b","\"+->+-\""}); + // other white space than ' ' used as key-value separator + l.add(new String[] {"+/a/b :\r123", "/a/b","123"}); + l.add(new String[] {"+/a/b\r: 123", "/a/b","123"}); + l.add(new String[] {"+/a/b\r:\r123", "/a/b","123"}); + l.add(new String[] {"+/a/b\r:\n123", "/a/b","123"}); + l.add(new String[] {"+/a/b\t:\r123", "/a/b","123"}); + l.add(new String[] {"+/a/b\t:\t123", "/a/b","123"}); + // path containing colon + l.add(new String[] {"+/a:b/c:d : 123", "/a:b/c:d","123"}); + // value starting with colon -> ok + l.add(new String[] {"+/a/b : : val", "/a/b",": val"}); + // missing value + l.add(new String[] {"+/a/b : ", "/a/b", ""}); + l.add(new String[] {"+/a/b :\n", "/a/b", ""}); + + for (final String[] strs : l) { + DiffHandler hndl = new DummyDiffHandler() { + @Override + public void setProperty(String targetPath, String diffValue) { + assertEquals(strs[1], targetPath); + assertEquals(strs[2], diffValue); + } + }; + DiffParser parser = new DiffParser(hndl); + parser.parse(strs[0]); + } + + List l2 = new ArrayList(); + // multiple commands + l2.add("+abc :\n\n+def : val"); + l2.add("+abc :\n\n+def : val\n"); + l2.add("+abc : \r+def : val"); + l2.add("+/a/b : val\r+abc : \r "); + l2.add("+/a/b : val\r+abc :\n\n "); + // missing value in the last action. + l2.add("+/a/b : \r+abc :\n"); + l2.add("+/a/b : \\r+abc : abc\r\r+abc :\r"); + l2.add("+abc :\n\n+def : val\r\r>abc : "); + + for (String diff : l2) { + final List li = new ArrayList(); + DiffHandler dh = new DummyDiffHandler() { + @Override + public void addNode(String targetPath, String diffValue) { + li.add(diffValue); + } + }; + + DiffParser parser = new DiffParser(dh); + parser.parse(diff); + assertEquals(2, li.size()); + } + } + + public void testSeparatorLines() throws IOException, DiffException { + String diff = "+abc :\n\n+val : val"; + DiffHandler dh = new DummyDiffHandler() { + @Override + public void addNode(String targetPath, String diffValue) { + if ("abc".equals(targetPath)) { + assertEquals("", diffValue); + } else { + assertEquals("val", diffValue); + } + } + }; + new DiffParser(dh).parse(diff); + + diff = "+abc :\n+val : val"; + dh = new DummyDiffHandler() { + @Override + public void addNode(String targetPath, String diffValue) { + assertEquals("+val : val", diffValue); + } + }; + new DiffParser(dh).parse(diff); + + // TODO: check again: currently all line separation chars before an diff-char are ignored unless they are escaped in way the handler understands (e.g. JSON does: \\r for \r). + diff = "+abc :\r\r\r+def : val"; + dh = new DummyDiffHandler() { + @Override + public void addNode(String targetPath, String diffValue) { + if ("abc".equals(targetPath)) { + assertEquals("", diffValue); + } else { + assertEquals("val", diffValue); + } + } + }; + new DiffParser(dh).parse(diff); + + diff = "+abc : val\r+def :\n\n "; + dh = new DummyDiffHandler() { + @Override + public void addNode(String targetPath, String diffValue) { + if ("abc".equals(targetPath)) { + assertEquals("val", diffValue); + } else { + assertEquals("\n ", diffValue); + } + } + }; + new DiffParser(dh).parse(diff); + } + + public void testUnicodeLineSep() throws IOException, DiffException { + String diff = "+abc : val" + new String(new byte[] {Character.LINE_SEPARATOR}, "utf-8") + "+abc : val"; + DiffHandler dh = new DummyDiffHandler() { + @Override + public void addNode(String targetPath, String diffValue) { + assertEquals("abc", targetPath); + assertEquals("val", diffValue); + } + }; + new DiffParser(dh).parse(diff); + } + + public void testInvalidDiff() throws IOException, DiffException { + List l = new ArrayList(); + l.add(""); + // path, separator and value missing + l.add("+"); + l.add("+/a/b : val\r+"); + // path starting with white space, separator and value missing + l.add("+\n"); + // separator and value missing + l.add("+/a/b"); + l.add("+/a/b : val\r+abc\n"); + l.add("+/a/b :"); + // invalid for separator and value are missing (all : and white space + // is interpreted as part of the path. + l.add("+/a/b:"); + l.add("+/a/b:val"); + l.add("+/a/b: val"); + l.add("+/a/b:\rval"); + l.add("+/a/b :: val"); + // diff starting with white space + l.add(" +/a/b: val"); + l.add("\r\r\r\r\r\r+/a/b: val"); + // key starting with white space + l.add("+\r/a/b : 123"); + l.add("+ /a/b : 123"); + // key starting with colon + l.add("+:/a/b : 123"); + + for (String diff : l) { + try { + DiffParser parser = new DiffParser(new DummyDiffHandler()); + parser.parse(diff); + fail(diff + " is not a valid diff string -> should throw DiffException."); + } catch (DiffException e) { + // ok + } + } + } + + private class DummyDiffHandler implements DiffHandler { + + public void addNode(String targetPath, String diffValue) + throws DiffException { + // does nothing + } + + public void setProperty(String targetPath, String diffValue) + throws DiffException { + // does nothing + } + + public void remove(String targetPath, String diffValue) + throws DiffException { + // does nothing + } + + public void move(String targetPath, String diffValue) throws DiffException { + // does nothing + } + } +} Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/server/remoting/davex/DiffParserTest.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/test/java/org/apache/jackrabbit/server/remoting/davex/JsonDiffHandlerImportTest.java =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/server/remoting/davex/JsonDiffHandlerImportTest.java (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/server/remoting/davex/JsonDiffHandlerImportTest.java (working copy) @@ -0,0 +1,176 @@ +/* + * 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.remoting.davex; + +import java.util.ArrayList; +import java.util.List; +import javax.jcr.Node; +import javax.jcr.RepositoryException; +import javax.jcr.security.AccessControlEntry; +import javax.jcr.security.AccessControlList; +import javax.jcr.security.AccessControlManager; +import javax.jcr.security.AccessControlPolicy; +import javax.jcr.security.Privilege; + +import org.apache.jackrabbit.api.security.JackrabbitAccessControlEntry; +import org.apache.jackrabbit.api.security.JackrabbitAccessControlList; +import org.apache.jackrabbit.commons.jackrabbit.authorization.AccessControlUtils; +import org.apache.jackrabbit.core.security.principal.EveryonePrincipal; +import org.apache.jackrabbit.test.AbstractJCRTest; + +/** + * Tests for {@code JsonDiffHandler} that trigger the import mode. + */ +public class JsonDiffHandlerImportTest extends AbstractJCRTest { + + private static final String JSOP_POLICY_TREE = "+rep:policy : {" + + "\"jcr:primaryType\" : \"rep:ACL\"," + + "\"allow\" : {" + "\"jcr:primaryType\" : \"rep:GrantACE\"," + + "\"rep:principalName\" : \"everyone\"," + + "\"rep:privileges\" : [\"jcr:write\"]" + "}" + "}"; + + private static final List ADD_NODES = new ArrayList(); + static { + ADD_NODES.add( + "+node1 : {" + +"\"jcr:primaryType\" : \"nt:file\"," + + "\"jcr:mixinTypes\" : [\"rep:AccessControllable\"]," + +"\"jcr:uuid\" : \"0a0ca2e9-ab98-4433-a12b-d57283765207\"," + +"\"rep:policy\" : {" + +"\"jcr:primaryType\" : \"rep:ACL\"," + +"\"deny0\" : {" + +"\"jcr:primaryType\" : \"rep:DenyACE\"," + +"\"rep:principalName\" : \"everyone\"," + +"\"rep:privileges\" : [\"jcr:read\"]" + +"}"+"}"+"}"); + ADD_NODES.add( + "+node2 : {" + +"\"jcr:primaryType\" : \"nt:unstructured\"," + + "\"jcr:mixinTypes\" : [\"rep:AccessControllable\"]," + +"\"rep:policy\" : {" + +"\"jcr:primaryType\" : \"rep:ACL\"," + +"\"allow\" : {" + +"\"jcr:primaryType\" : \"rep:GrantACE\"," + +"\"rep:principalName\" : \"everyone\"," + +"\"rep:privileges\" : [\"jcr:read\"]" + +"}," + +"\"deny\" : {" + +"\"jcr:primaryType\" : \"rep:DenyACE\"," + +"\"rep:principalName\" : \"everyone\"," + +"\"rep:privileges\" : [\"jcr:write\"]" + +"}" + +"}"+"}"); + + } + + private AccessControlManager acMgr; + + @Override + protected void setUp() throws Exception { + super.setUp(); + acMgr = superuser.getAccessControlManager(); + } + + private static void assertPolicy(AccessControlManager acMgr, Node targetNode, int noACEs) throws RepositoryException { + AccessControlPolicy[] policies = acMgr.getPolicies(targetNode.getPath()); + assertEquals(policies.length, 1); + + AccessControlPolicy acl = policies[0]; + assertTrue(acl instanceof JackrabbitAccessControlList); + AccessControlEntry[] entries = ((JackrabbitAccessControlList) acl).getAccessControlEntries(); + assertEquals(noACEs, entries.length); + } + + /** + * Test two subsequent DIFF strings with policies, thus multiple addNode operations. + */ + public void testMultipleAddNodeOperations() throws Exception { + for(String jsonString : ADD_NODES) { + JsonDiffHandler h = new JsonDiffHandler(superuser, testRoot, null); + new DiffParser(h).parse(jsonString); + } + + assertPolicy(acMgr, testRootNode.getNode("node1"), 1); + assertPolicy(acMgr, testRootNode.getNode("node2"), 2); + } + + /** + * Test adding 'rep:policy' policy node as a child node of /testroot without + * intermediate node. + */ + public void testAllPolicyNode() throws Exception { + try { + testRootNode.addMixin("rep:AccessControllable"); + + JsonDiffHandler handler = new JsonDiffHandler(superuser, testRoot, null); + new DiffParser(handler).parse(JSOP_POLICY_TREE); + + assertTrue(testRootNode.hasNode("rep:policy")); + assertTrue(testRootNode.getNode("rep:policy").getDefinition().isProtected()); + + assertTrue(testRootNode.getNode("rep:policy").getPrimaryNodeType() + .getName().equals("rep:ACL")); + + assertPolicy(acMgr, testRootNode, 1); + + AccessControlEntry entry = ((AccessControlList) acMgr.getPolicies(testRoot)[0]).getAccessControlEntries()[0]; + assertEquals(EveryonePrincipal.NAME, entry.getPrincipal().getName()); + assertEquals(1, entry.getPrivileges().length); + assertEquals(acMgr.privilegeFromName(Privilege.JCR_WRITE), entry.getPrivileges()[0]); + + if (entry instanceof JackrabbitAccessControlEntry) { + assertTrue(((JackrabbitAccessControlEntry) entry).isAllow()); + } + + } finally { + superuser.refresh(false); + } + } + + /** + * Test adding 'rep:policy' policy node as a child node of /testroot without + * intermediate node. + */ + public void testUpdatePolicyNode() throws Exception { + try { + AccessControlUtils.addAccessControlEntry(superuser, testRoot, EveryonePrincipal.getInstance(), new String[] {Privilege.JCR_READ}, false); + + JsonDiffHandler handler = new JsonDiffHandler(superuser, testRoot, null); + new DiffParser(handler).parse(JSOP_POLICY_TREE); + + assertTrue(testRootNode.hasNode("rep:policy")); + assertTrue(testRootNode.getNode("rep:policy").getDefinition().isProtected()); + + assertTrue(testRootNode.getNode("rep:policy").getPrimaryNodeType() + .getName().equals("rep:ACL")); + + assertPolicy(acMgr, testRootNode, 1); + + AccessControlEntry entry = ((AccessControlList) acMgr.getPolicies(testRoot)[0]).getAccessControlEntries()[0]; + assertEquals(EveryonePrincipal.NAME, entry.getPrincipal().getName()); + assertEquals(1, entry.getPrivileges().length); + assertEquals(acMgr.privilegeFromName(Privilege.JCR_WRITE), entry.getPrivileges()[0]); + + if (entry instanceof JackrabbitAccessControlEntry) { + assertTrue(((JackrabbitAccessControlEntry) entry).isAllow()); + } + + } finally { + superuser.refresh(false); + } + } +} \ No newline at end of file Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/server/remoting/davex/JsonDiffHandlerImportTest.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/server/remoting/davex/JsonDiffHandlerTest.java =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/server/remoting/davex/JsonDiffHandlerTest.java (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/server/remoting/davex/JsonDiffHandlerTest.java (working copy) @@ -0,0 +1,267 @@ +/* + * 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.remoting.davex; + +import junit.framework.TestCase; +import org.xml.sax.ContentHandler; + +import javax.jcr.Credentials; +import javax.jcr.Item; +import javax.jcr.Node; +import javax.jcr.Property; +import javax.jcr.Repository; +import javax.jcr.Session; +import javax.jcr.ValueFactory; +import javax.jcr.Workspace; +import javax.jcr.retention.RetentionManager; +import javax.jcr.security.AccessControlManager; +import java.io.InputStream; +import java.io.OutputStream; +import java.security.AccessControlException; +import java.util.HashMap; +import java.util.Map; + +/** + * JsonDiffHandlerTest... + */ +public class JsonDiffHandlerTest extends TestCase { + + public void testGetItemPath() throws Exception { + Map m = new HashMap(); + m.put("abc", "/reqPath/abc"); + m.put("abc/def/ghi", "/reqPath/abc/def/ghi"); + m.put("/abc", "/abc"); + m.put("/abc/def/ghi", "/abc/def/ghi"); + m.put(".", "/reqPath"); + m.put("./abc", "/reqPath/abc"); + m.put("abc/./def", "/reqPath/abc/def"); + m.put("/abc/./def", "/abc/def"); + m.put("..", "/"); + m.put("../abc/def", "/abc/def"); + m.put("abc/../def/.", "/reqPath/def"); + m.put("abc/../def/..", "/reqPath"); + m.put("abc/../def/..", "/reqPath"); + m.put("abc/../def/..", "/reqPath"); + m.put("abc/../def/..", "/reqPath"); + m.put("abc/../def/..", "/reqPath"); + m.put("abc/../def/..", "/reqPath"); + m.put("./././././", "/reqPath"); + m.put("/./././././", "/"); + m.put("/./abc/def/../ghi", "/abc/ghi"); + + JsonDiffHandler handler = new JsonDiffHandler(new DummySession(), "/reqPath", null); + for (String targetPath : m.keySet()) { + String expItemPath = m.get(targetPath); + assertEquals(expItemPath, handler.getItemPath(targetPath)); + } + } + + private final class DummySession implements Session { + + @Override + public Repository getRepository() { + return null; + } + + @Override + public String getUserID() { + return null; + } + + @Override + public Object getAttribute(String name) { + return null; + } + + @Override + public String[] getAttributeNames() { + return new String[0]; + } + + @Override + public Workspace getWorkspace() { + return null; + } + + @Override + public Session impersonate(Credentials credentials) { + return null; + } + + @Override + public Node getRootNode() { + return null; + } + + @Override + public Node getNodeByUUID(String uuid) { + return null; + } + + @Override + public Item getItem(String absPath) { + return null; + } + + @Override + public boolean itemExists(String absPath) { + return false; + } + + @Override + public void move(String srcAbsPath, String destAbsPath) { + } + + @Override + public void save() { + } + + @Override + public void refresh(boolean keepChanges) { + } + + @Override + public boolean hasPendingChanges() { + return false; + } + + @Override + public ValueFactory getValueFactory() { + return null; + } + + @Override + public void checkPermission(String absPath, String actions) throws AccessControlException { + } + + @Override + public ContentHandler getImportContentHandler(String parentAbsPath, int uuidBehavior) { + return null; + } + + @Override + public void importXML(String parentAbsPath, InputStream in, int uuidBehavior) { + } + + @Override + public void exportSystemView(String absPath, ContentHandler contentHandler, boolean skipBinary, boolean noRecurse) { + } + + @Override + public void exportSystemView(String absPath, OutputStream out, boolean skipBinary, boolean noRecurse) { + } + + @Override + public void exportDocumentView(String absPath, ContentHandler contentHandler, boolean skipBinary, boolean noRecurse) { + } + + @Override + public void exportDocumentView(String absPath, OutputStream out, boolean skipBinary, boolean noRecurse) { + } + + @Override + public void setNamespacePrefix(String prefix, String uri) { + } + + @Override + public String[] getNamespacePrefixes() { + return new String[0]; + } + + @Override + public String getNamespaceURI(String prefix) { + return null; + } + + @Override + public String getNamespacePrefix(String uri) { + return null; + } + + @Override + public void logout() { + } + + @Override + public boolean isLive() { + return false; + } + + @Override + public void addLockToken(String lt) { + } + + @Override + public String[] getLockTokens() { + return new String[0]; + } + + @Override + public void removeLockToken(String lt) { + } + + @Override + public AccessControlManager getAccessControlManager() { + return null; + } + + @Override + public Node getNode(String arg0) { + return null; + } + + @Override + public Node getNodeByIdentifier(String arg0) { + return null; + } + + @Override + public Property getProperty(String arg0) { + return null; + } + + @Override + public RetentionManager getRetentionManager() { + return null; + } + + @Override + public boolean hasCapability(String arg0, Object arg1, Object[] arg2) { + return false; + } + + @Override + public boolean hasPermission(String arg0, String arg1) { + return false; + } + + @Override + public boolean nodeExists(String arg0) { + return false; + } + + @Override + public boolean propertyExists(String arg0) { + return false; + } + + @Override + public void removeItem(String arg0) { + + } + } +} Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/server/remoting/davex/JsonDiffHandlerTest.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/test/java/org/apache/jackrabbit/server/remoting/davex/JsonWriterTest.java =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/server/remoting/davex/JsonWriterTest.java (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/server/remoting/davex/JsonWriterTest.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.remoting.davex; + +import org.apache.jackrabbit.commons.iterator.NodeIteratorAdapter; +import org.apache.jackrabbit.commons.iterator.PropertyIteratorAdapter; +import org.easymock.EasyMockSupport; +import org.easymock.IAnswer; +import org.junit.Test; + +import javax.jcr.Node; +import javax.jcr.NodeIterator; +import javax.jcr.Property; +import javax.jcr.PropertyIterator; +import javax.jcr.PropertyType; +import javax.jcr.Value; +import java.io.StringWriter; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import static org.junit.Assert.*; +import static org.easymock.EasyMock.*; + +public class JsonWriterTest extends EasyMockSupport { + + @Test + public void testDoubleOutput() throws Exception { + StringWriter writer = new StringWriter(); + JsonWriter jsonWriter = new JsonWriter(writer); + + Node parent = createMock(Node.class); + Property doubleProperty = createMock(Property.class); + Value doublePropertyValue = createMock(Value.class); + expect(doubleProperty.getType()).andReturn(PropertyType.DOUBLE).anyTimes(); + expect(doubleProperty.getName()).andReturn("singleValued").anyTimes(); + expect(doubleProperty.isMultiple()).andReturn(false).anyTimes(); + expect(doubleProperty.getValue()).andReturn(doublePropertyValue).anyTimes(); + expect(doublePropertyValue.getType()).andReturn(PropertyType.DOUBLE).anyTimes(); + expect(doublePropertyValue.getDouble()).andReturn(5d).anyTimes(); + expect(doublePropertyValue.getString()).andReturn("5").anyTimes(); + + Property mvDoubleProperty = createMock(Property.class); + Value mvDoublePropertyValue1 = createMock(Value.class); + Value mvDoublePropertyValue2 = createMock(Value.class); + expect(mvDoubleProperty.getType()).andReturn(PropertyType.DOUBLE).anyTimes(); + expect(mvDoubleProperty.getName()).andReturn("multiValued").anyTimes(); + expect(mvDoubleProperty.isMultiple()).andReturn(true).anyTimes(); + expect(mvDoubleProperty.getValues()).andReturn(new Value[] { mvDoublePropertyValue1, mvDoublePropertyValue2}).anyTimes(); + expect(mvDoublePropertyValue1.getType()).andReturn(PropertyType.DOUBLE).anyTimes(); + expect(mvDoublePropertyValue1.getDouble()).andReturn(42d).anyTimes(); + expect(mvDoublePropertyValue1.getString()).andReturn("42").anyTimes(); + expect(mvDoublePropertyValue2.getType()).andReturn(PropertyType.DOUBLE).anyTimes(); + expect(mvDoublePropertyValue2.getDouble()).andReturn(98.6).anyTimes(); + expect(mvDoublePropertyValue2.getString()).andReturn("98.6").anyTimes(); + + final List properties = new ArrayList(); + properties.add(doubleProperty); + properties.add(mvDoubleProperty); + expect(parent.getProperties()).andAnswer(new IAnswer() { + @Override + public PropertyIterator answer() throws Throwable { + return new PropertyIteratorAdapter(properties.iterator()); + } + }); + expect(parent.getNodes()).andAnswer(new IAnswer() { + @Override + public NodeIterator answer() throws Throwable { + return new NodeIteratorAdapter(Collections.emptyIterator()); + } + }); + replayAll(); + + jsonWriter.write(parent, 1); + + assertEquals("{\":singleValued\":\"Double\",\"singleValued\":5,\":multiValued\":\"Double\",\"multiValued\":[42,98.6],\"::NodeIteratorSize\":0}", + writer.toString()); + + verifyAll(); + } + +} \ No newline at end of file Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/server/remoting/davex/JsonWriterTest.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/server/remoting/davex/TestAll.java =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/server/remoting/davex/TestAll.java (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/server/remoting/davex/TestAll.java (working copy) @@ -0,0 +1,42 @@ +/* + * 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.remoting.davex; + +import junit.framework.Test; +import junit.framework.TestCase; +import junit.framework.TestSuite; + +/** + * Test suite that includes all testcases for package org.apache.jackrabbit.server.remoting.davex. + */ +public class TestAll extends TestCase { + + /** + * Returns a Test suite that executes all tests inside this + * package. + */ + public static Test suite() { + TestSuite suite = new TestSuite("org.apache.jackrabbit.server.remoting.davex tests"); + + suite.addTestSuite(DiffParserTest.class); + suite.addTestSuite(JsonDiffHandlerImportTest.class); + suite.addTestSuite(JsonDiffHandlerTest.class); + suite.addTestSuite(BatchReadConfigTest.class); + + return suite; + } +} Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/server/remoting/davex/TestAll.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/test/java/org/apache/jackrabbit/webdav/jcr/JcrDavExceptionTest.java =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/jcr/JcrDavExceptionTest.java (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/jcr/JcrDavExceptionTest.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.webdav.jcr; + +import junit.framework.TestCase; + +import javax.jcr.lock.LockException; +import javax.jcr.RepositoryException; + +/** JcrDavExceptionTest... */ +public class JcrDavExceptionTest extends TestCase { + + public void testDerivedException() { + RepositoryException re = new DerievedRepositoryException(); + + // creating JcrDavException from the derived exception must not throw + // NPE (see issue https://issues.apache.org/jira/browse/JCR-1678) + JcrDavException jde = new JcrDavException(re); + + // error code must be the same as for LockException + assertEquals(new JcrDavException(new LockException()).getErrorCode(), + jde.getErrorCode()); + } + + public void testNullException() { + try { + new JcrDavException(null); + fail("Should throw NPE"); + } catch (NullPointerException e) { + // as documented in the javadoc + } + } + + /** + * Derived exception that does not extend from RepositoryException, which + * returns the 'default' error code. + */ + private static final class DerievedRepositoryException extends LockException { + } +} \ No newline at end of file Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/jcr/JcrDavExceptionTest.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/test/java/org/apache/jackrabbit/webdav/jcr/JcrValueTypeTest.java =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/jcr/JcrValueTypeTest.java (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/jcr/JcrValueTypeTest.java (working copy) @@ -0,0 +1,50 @@ +/* + * 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.webdav.jcr; + +import junit.framework.TestCase; + +import javax.jcr.PropertyType; + +import org.apache.jackrabbit.commons.webdav.JcrValueType; + +/** + * JcrValueTypeTest... + */ +public class JcrValueTypeTest extends TestCase { + + public void testTypeFromContentType() { + for (int i = PropertyType.UNDEFINED; i <= PropertyType.DECIMAL; i++) { + String ct = JcrValueType.contentTypeFromType(i); + assertEquals(i, JcrValueType.typeFromContentType(ct)); + } + } + + public void testTypeFromContentTypeIncludingCharSet() { + for (int i = PropertyType.UNDEFINED; i <= PropertyType.DECIMAL; i++) { + String ct = JcrValueType.contentTypeFromType(i) + "; charset=UTF-8"; + assertEquals(i, JcrValueType.typeFromContentType(ct)); + } + } + public void testTypeFromInvalidContentType() { + String[] invalids = new String[] {null, "", "jcr-value/invalid", "invalid/as-well"}; + + for (String invalid : invalids) { + assertEquals(PropertyType.UNDEFINED, JcrValueType.typeFromContentType(invalid)); + } + } +} \ No newline at end of file Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/jcr/JcrValueTypeTest.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/test/java/org/apache/jackrabbit/webdav/jcr/LockTimeOutFormatTest.java =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/jcr/LockTimeOutFormatTest.java (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/jcr/LockTimeOutFormatTest.java (working copy) @@ -0,0 +1,124 @@ +/* + * 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.webdav.jcr; + +import java.net.URISyntaxException; + +import javax.jcr.Node; +import javax.jcr.RepositoryException; +import javax.jcr.lock.Lock; +import javax.jcr.lock.LockException; +import javax.xml.parsers.ParserConfigurationException; + +import junit.framework.TestCase; + +import org.apache.jackrabbit.webdav.jcr.lock.JcrActiveLock; +import org.apache.jackrabbit.webdav.xml.DomUtil; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.NodeList; + +/** + * LockTimeOutFormatTest... + */ +public class LockTimeOutFormatTest extends TestCase { + + public void testOneSec() throws RepositoryException, URISyntaxException, ParserConfigurationException { + testfmt(1, "Second-1"); + } + + public void testInf() throws RepositoryException, URISyntaxException, ParserConfigurationException { + testfmt(Long.MAX_VALUE, "Infinite"); + } + + public void testTooLong() throws RepositoryException, URISyntaxException, ParserConfigurationException { + testfmt(Integer.MAX_VALUE + 100000L, "Infinite"); + } + + public void testNeg() throws RepositoryException, URISyntaxException, ParserConfigurationException { + // expired + testfmt(-1, null); + } + + private void testfmt(long jcrtimeout, String expectedString) throws RepositoryException, URISyntaxException, ParserConfigurationException { + + Lock l = new TestLock(jcrtimeout); + JcrActiveLock al = new JcrActiveLock(l); + + Document d = DomUtil.createDocument(); + Element activeLock = al.toXml(d); + assertEquals("activelock", activeLock.getLocalName()); + NodeList nl = activeLock.getElementsByTagNameNS("DAV:", "timeout"); + + if (expectedString == null) { + assertEquals(0, nl.getLength()); + } + else { + assertEquals(1, nl.getLength()); + Element timeout = (Element)nl.item(0); + String t = DomUtil.getText(timeout); + assertEquals(expectedString, t); + } + } + + /** + * Minimal Lock impl for tests above + */ + private static class TestLock implements Lock { + + private final long timeout; + + public TestLock(long timeout) { + this.timeout = timeout; + } + + public String getLockOwner() { + return null; + } + + public boolean isDeep() { + return false; + } + + public Node getNode() { + return null; + } + + public String getLockToken() { + return "foo"; + } + + public long getSecondsRemaining() throws RepositoryException { + return timeout; + } + + public boolean isLive() throws RepositoryException { + return timeout >= 0; + } + + public boolean isSessionScoped() { + return false; + } + + public boolean isLockOwningSession() { + return false; + } + + public void refresh() throws LockException, RepositoryException { + } + } +} Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/jcr/LockTimeOutFormatTest.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/jcr/LockTokenMappingTest.java =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/jcr/LockTokenMappingTest.java (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/jcr/LockTokenMappingTest.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.webdav.jcr; + +import java.net.URI; +import java.net.URISyntaxException; +import java.util.UUID; + +import javax.jcr.Node; +import javax.jcr.RepositoryException; +import javax.jcr.lock.Lock; +import javax.jcr.lock.LockException; + +import org.apache.jackrabbit.webdav.jcr.lock.LockTokenMapper; + +import junit.framework.TestCase; + +/** + * LockTokenMappingTest... + */ +public class LockTokenMappingTest extends TestCase { + + // test lock with a lock token similar to the ones assigned by Jackrabbit + public void testOpenScopedJcr() throws RepositoryException, URISyntaxException { + testRoundtrip(UUID.randomUUID().toString() + "-X"); + } + + // test a fancy lock string + public void testOpenScopedFancy() throws RepositoryException, URISyntaxException { + testRoundtrip("\n\u00c4 \u20ac"); + } + + private void testRoundtrip(String token) throws RepositoryException, URISyntaxException { + + Lock l = new TestLock(token); + String davtoken = LockTokenMapper.getDavLocktoken(l); + + // valid URI? + URI u = new URI(davtoken); + assertTrue("lock token must be absolute URI", u.isAbsolute()); + assertEquals("lock token URI must be all-ASCII", u.toASCIIString(), u.toString()); + + String jcrtoken = LockTokenMapper.getJcrLockToken(davtoken); + assertEquals(jcrtoken, l.getLockToken()); + } + + /** + * Minimal Lock impl for tests above + */ + private static class TestLock implements Lock { + + private final String token; + + public TestLock(String token) { + this.token = token; + } + + public String getLockOwner() { + return null; + } + + public boolean isDeep() { + return false; + } + + public Node getNode() { + return null; + } + + public String getLockToken() { + return token; + } + + public long getSecondsRemaining() throws RepositoryException { + return 0; + } + + public boolean isLive() throws RepositoryException { + return false; + } + + public boolean isSessionScoped() { + return false; + } + + public boolean isLockOwningSession() { + return false; + } + + public void refresh() throws LockException, RepositoryException { + } + } +} Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/jcr/LockTokenMappingTest.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/jcr/observation/InfoMapTest.java =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/jcr/observation/InfoMapTest.java (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/jcr/observation/InfoMapTest.java (working copy) @@ -0,0 +1,71 @@ +/* + * 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.webdav.jcr.observation; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; + +import javax.jcr.RepositoryException; +import javax.jcr.Session; +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.transform.TransformerException; + +import org.apache.jackrabbit.webdav.observation.ObservationConstants; +import org.apache.jackrabbit.webdav.xml.DomUtil; +import org.apache.jackrabbit.webdav.xml.Namespace; +import org.mockito.Mockito; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.xml.sax.SAXException; + +import junit.framework.TestCase; + +public class InfoMapTest extends TestCase { + + public void testInfoMap() + throws ParserConfigurationException, TransformerException, SAXException, IOException, RepositoryException { + + Session s = Mockito.mock(Session.class); + Mockito.when(s.getNamespaceURI("jcr")).thenReturn("http://www.jcp.org/jcr/1.0"); + + Map map = new HashMap(); + // mandated by JCR 2.0 + map.put("srcChildRelPath", "/x"); + // OAK extension, see https://issues.apache.org/jira/browse/OAK-1669 + map.put("jcr:primaryType", "nt:unstructured"); + Document doc = DomUtil.createDocument(); + Element container = DomUtil.createElement(doc, "x", null); + doc.appendChild(container); + SubscriptionImpl.serializeInfoMap(container, s, map); + ByteArrayOutputStream xml = new ByteArrayOutputStream(); + DomUtil.transformDocument(doc, xml); + + // reparse + Document tripped = DomUtil.parseDocument(new ByteArrayInputStream(xml.toByteArray())); + Element top = tripped.getDocumentElement(); + assertEquals("x", top.getLocalName()); + Element emap = DomUtil.getChildElement(top, ObservationConstants.N_EVENTINFO); + assertNotNull(emap); + Element path = DomUtil.getChildElement(emap, "srcChildRelPath", null); + assertNotNull(path); + Element type = DomUtil.getChildElement(emap, "primaryType", Namespace.getNamespace("http://www.jcp.org/jcr/1.0")); + assertNotNull(type); + } +} Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/jcr/observation/InfoMapTest.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/jcr/security/AbstractSecurityTest.java =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/jcr/security/AbstractSecurityTest.java (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/jcr/security/AbstractSecurityTest.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.webdav.jcr.security; + +import javax.jcr.Repository; +import javax.jcr.security.AccessControlManager; + +import org.apache.jackrabbit.test.AbstractJCRTest; +import org.apache.jackrabbit.test.NotExecutableException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public abstract class AbstractSecurityTest extends AbstractJCRTest { + + protected AccessControlManager acMgr; + + @Override + protected void setUp() throws Exception { + super.setUp(); + if (isSupported(Repository.OPTION_ACCESS_CONTROL_SUPPORTED)) { + acMgr = superuser.getAccessControlManager(); + } else { + throw new NotExecutableException(); + } + } +} \ No newline at end of file Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/jcr/security/AbstractSecurityTest.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/jcr/security/JcrSupportedPrivilegePropertyTest.java =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/jcr/security/JcrSupportedPrivilegePropertyTest.java (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/jcr/security/JcrSupportedPrivilegePropertyTest.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.webdav.jcr.security; + +import java.util.Arrays; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import javax.jcr.RepositoryException; +import javax.jcr.security.Privilege; + +import org.apache.jackrabbit.webdav.security.SupportedPrivilege; + +public class JcrSupportedPrivilegePropertyTest extends AbstractSecurityTest { + + public void testSupportedPrivileges() throws RepositoryException { + Set privs = new HashSet(Arrays.asList(acMgr.getSupportedPrivileges(testRoot))); + JcrSupportedPrivilegesProperty prop = new JcrSupportedPrivilegesProperty(superuser, testRoot); + List value = prop.asDavProperty().getValue(); + + if (privs.contains(acMgr.privilegeFromName(Privilege.JCR_ALL))) { + assertEquals(1, value.size()); + } + } + + public void testJcrAllPrivilege() throws RepositoryException { + JcrSupportedPrivilegesProperty prop = new JcrSupportedPrivilegesProperty(superuser); + List value = prop.asDavProperty().getValue(); + + assertEquals(1, value.size()); + } +} \ No newline at end of file Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/jcr/security/JcrSupportedPrivilegePropertyTest.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/jcr/security/JcrUserPrivilegesPropertyTest.java =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/jcr/security/JcrUserPrivilegesPropertyTest.java (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/jcr/security/JcrUserPrivilegesPropertyTest.java (working copy) @@ -0,0 +1,69 @@ +/* + * 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.webdav.jcr.security; + +import java.util.Collection; +import java.util.HashSet; +import java.util.Set; +import javax.jcr.RepositoryException; +import javax.jcr.Session; +import javax.jcr.security.AccessControlManager; + +import org.apache.jackrabbit.util.Text; +import org.apache.jackrabbit.webdav.security.Privilege; +import org.apache.jackrabbit.webdav.xml.Namespace; + +public class JcrUserPrivilegesPropertyTest extends AbstractSecurityTest { + + private Set getExpected(AccessControlManager acMgr, Session s) throws RepositoryException { + Set expected = new HashSet(); + for (javax.jcr.security.Privilege p : acMgr.getPrivileges(testRoot)) { + String localName = Text.getLocalName(p.getName()); + String prefix = Text.getNamespacePrefix(p.getName()); + Namespace ns = (prefix.isEmpty()) ? Namespace.EMPTY_NAMESPACE : Namespace.getNamespace(prefix, s.getNamespaceURI(prefix)); + expected.add(Privilege.getPrivilege(localName, ns)); + } + return expected; + } + + public void testAdminPrivileges() throws RepositoryException { + Set expected = getExpected(acMgr, superuser); + + JcrUserPrivilegesProperty upp = new JcrUserPrivilegesProperty(superuser, testRoot); + Collection davPrivs = upp.asDavProperty().getValue(); + + assertEquals(expected.size(), davPrivs.size()); + assertTrue(davPrivs.containsAll(expected)); + } + + public void testReadOnlyPrivileges() throws RepositoryException { + Session readOnly = getHelper().getReadOnlySession(); + try { + Set expected = getExpected(readOnly.getAccessControlManager(), readOnly); + + JcrUserPrivilegesProperty upp = new JcrUserPrivilegesProperty(readOnly, testRoot); + Collection davPrivs = upp.asDavProperty().getValue(); + + assertEquals(expected.size(), davPrivs.size()); + assertTrue(davPrivs.containsAll(expected)); + } finally { + if (readOnly != null) { + readOnly.logout(); + } + } + } +} \ No newline at end of file Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/jcr/security/JcrUserPrivilegesPropertyTest.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/server/BindTest.java =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/server/BindTest.java (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/server/BindTest.java (working copy) @@ -0,0 +1,603 @@ +/* + * 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.webdav.server; + +import java.io.IOException; +import java.net.URI; +import java.net.URISyntaxException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Set; + +import org.apache.http.HttpResponse; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.client.methods.HttpHead; +import org.apache.http.client.methods.HttpPut; +import org.apache.http.entity.ContentType; +import org.apache.http.entity.StringEntity; +import org.apache.http.util.EntityUtils; +import org.apache.jackrabbit.webdav.DavException; +import org.apache.jackrabbit.webdav.MultiStatus; +import org.apache.jackrabbit.webdav.MultiStatusResponse; +import org.apache.jackrabbit.webdav.bind.BindConstants; +import org.apache.jackrabbit.webdav.bind.BindInfo; +import org.apache.jackrabbit.webdav.bind.ParentElement; +import org.apache.jackrabbit.webdav.bind.RebindInfo; +import org.apache.jackrabbit.webdav.bind.UnbindInfo; +import org.apache.jackrabbit.webdav.client.methods.HttpBind; +import org.apache.jackrabbit.webdav.client.methods.HttpMkcol; +import org.apache.jackrabbit.webdav.client.methods.HttpMove; +import org.apache.jackrabbit.webdav.client.methods.HttpOptions; +import org.apache.jackrabbit.webdav.client.methods.HttpPropfind; +import org.apache.jackrabbit.webdav.client.methods.HttpRebind; +import org.apache.jackrabbit.webdav.client.methods.HttpUnbind; +import org.apache.jackrabbit.webdav.client.methods.HttpVersionControl; +import org.apache.jackrabbit.webdav.property.DavProperty; +import org.apache.jackrabbit.webdav.property.DavPropertyNameSet; +import org.w3c.dom.Element; +import org.w3c.dom.Node; + +/** + * Test cases for WebDAV BIND functionality (see RFC 5842 + */ +public class BindTest extends WebDAVTestBase { + + // http://greenbytes.de/tech/webdav/rfc5842.html#rfc.section.8.1 + public void testOptions() throws IOException { + HttpOptions options = new HttpOptions(this.uri); + HttpResponse response = this.client.execute(options, this.context); + int status = response.getStatusLine().getStatusCode(); + assertEquals(200, status); + Set allow = options.getAllowedMethods(response); + Set complianceClasses = options.getDavComplianceClasses(response); + assertTrue("DAV header should include 'bind' feature", complianceClasses.contains("bind")); + assertTrue("Allow header should include BIND method", allow.contains("BIND")); + assertTrue("Allow header should include REBIND method", allow.contains("REBIND")); + assertTrue("Allow header should include UNBIND method", allow.contains("UNBIND")); + } + + // create test resource, make it referenceable, check resource id, move resource, check again + public void testResourceId() throws IOException, DavException, URISyntaxException { + + String testcol = this.root + "testResourceId/"; + String testuri1 = testcol + "bindtest1"; + String testuri2 = testcol + "bindtest2"; + int status; + try { + HttpMkcol mkcol = new HttpMkcol(testcol); + status = this.client.execute(mkcol, this.context).getStatusLine().getStatusCode(); + assertEquals(201, status); + + HttpPut put = new HttpPut(testuri1); + put.setEntity(new StringEntity("foo", ContentType.create("text/plain", "UTF-8"))); + status = this.client.execute(put, this.context).getStatusLine().getStatusCode(); + assertEquals(201, status); + + // enabling version control always makes the resource referenceable + HttpVersionControl versioncontrol = new HttpVersionControl(testuri1); + status = this.client.execute(versioncontrol, this.context).getStatusLine().getStatusCode(); + assertTrue("status: " + status, status == 200 || status == 201); + + URI resourceId = getResourceId(testuri1); + + HttpMove move = new HttpMove(testuri1, testuri2, true); + status = this.client.execute(move, this.context).getStatusLine().getStatusCode(); + assertEquals(201, status); + + URI resourceId2 = getResourceId(testuri2); + assertEquals(resourceId, resourceId2); + } finally { + delete(testcol); + } + } + + // utility methods + + // see http://greenbytes.de/tech/webdav/rfc5842.html#rfc.section.3.1 + private URI getResourceId(String uri) throws IOException, DavException, URISyntaxException { + DavPropertyNameSet names = new DavPropertyNameSet(); + names.add(BindConstants.RESOURCEID); + HttpPropfind propfind = new HttpPropfind(uri, names, 0); + HttpResponse response = this.client.execute(propfind, this.context); + int status = response.getStatusLine().getStatusCode(); + assertEquals(207, status); + MultiStatus multistatus = propfind.getResponseBodyAsMultiStatus(response); + MultiStatusResponse[] responses = multistatus.getResponses(); + assertEquals(1, responses.length); + DavProperty resourceId = responses[0].getProperties(200).get(BindConstants.RESOURCEID); + assertNotNull(resourceId); + assertTrue(resourceId.getValue() instanceof Element); + Element href = (Element)resourceId.getValue(); + assertEquals("href", href.getLocalName()); + String text = getUri(href); + URI resid = new URI(text); + return resid; + } + + private DavProperty getParentSet(String uri) throws IOException, DavException, URISyntaxException { + DavPropertyNameSet names = new DavPropertyNameSet(); + names.add(BindConstants.PARENTSET); + HttpPropfind propfind = new HttpPropfind(uri, names, 0); + HttpResponse response = this.client.execute(propfind, this.context); + int status = response.getStatusLine().getStatusCode(); + assertEquals(207, status); + MultiStatus multistatus = propfind.getResponseBodyAsMultiStatus(response); + MultiStatusResponse[] responses = multistatus.getResponses(); + assertEquals(1, responses.length); + DavProperty parentset = responses[0].getProperties(200).get(BindConstants.PARENTSET); + assertNotNull(parentset); + return parentset; + } + + public void testSimpleBind() throws Exception { + String testcol = this.root + "testSimpleBind/"; + String subcol1 = testcol + "bindtest1/"; + String testres1 = subcol1 + "res1"; + String subcol2 = testcol + "bindtest2/"; + String testres2 = subcol2 + "res2"; + int status; + try { + HttpMkcol mkcol = new HttpMkcol(testcol); + status = this.client.execute(mkcol, this.context).getStatusLine().getStatusCode(); + assertEquals(201, status); + mkcol = new HttpMkcol(subcol1); + status = this.client.execute(mkcol, this.context).getStatusLine().getStatusCode(); + assertEquals(201, status); + mkcol = new HttpMkcol(subcol2); + status = this.client.execute(mkcol, this.context).getStatusLine().getStatusCode(); + assertEquals(201, status); + + //create new resource R with path bindtest1/res1 + HttpPut put = new HttpPut(testres1); + put.setEntity(new StringEntity("foo", ContentType.create("text/plain", "UTF-8"))); + status = this.client.execute(put, this.context).getStatusLine().getStatusCode(); + assertEquals(201, status); + + //create new binding of R with path bindtest2/res2 + HttpBind bind = new HttpBind(subcol2, new BindInfo(testres1, "res2")); + status = this.client.execute(bind, this.context).getStatusLine().getStatusCode(); + assertEquals(201, status); + //check if both bindings report the same DAV:resource-id + assertEquals(this.getResourceId(testres1), this.getResourceId(testres2)); + + //compare representations retrieved with both paths + HttpGet get = new HttpGet(testres1); + HttpResponse resp = this.client.execute(get, this.context); + status = resp.getStatusLine().getStatusCode(); + assertEquals(200, status); + assertEquals("foo", EntityUtils.toString(resp.getEntity())); + resp = this.client.execute(get, this.context); + status = resp.getStatusLine().getStatusCode(); + assertEquals(200, status); + assertEquals("foo", EntityUtils.toString(resp.getEntity())); + + //modify R using the new path + put = new HttpPut(testres2); + put.setEntity(new StringEntity("bar", ContentType.create("text/plain", "UTF-8"))); + status = this.client.execute(put, this.context).getStatusLine().getStatusCode(); + assertTrue("status: " + status, status == 200 || status == 204); + + //compare representations retrieved with both paths + get = new HttpGet(testres1); + resp = this.client.execute(get, this.context); + status = resp.getStatusLine().getStatusCode(); + assertEquals(200, status); + assertEquals("bar", EntityUtils.toString(resp.getEntity())); + get = new HttpGet(testres2); + resp = this.client.execute(get, this.context); + status = resp.getStatusLine().getStatusCode(); + assertEquals(200, status); + assertEquals("bar", EntityUtils.toString(resp.getEntity())); + } finally { + delete(testcol); + } + } + + public void testRebind() throws Exception { + String testcol = this.root + "testRebind/"; + String subcol1 = testcol + "bindtest1/"; + String testres1 = subcol1 + "res1"; + String subcol2 = testcol + "bindtest2/"; + String testres2 = subcol2 + "res2"; + int status; + try { + HttpMkcol mkcol = new HttpMkcol(testcol); + status = this.client.execute(mkcol, this.context).getStatusLine().getStatusCode(); + assertEquals(201, status); + mkcol = new HttpMkcol(subcol1); + status = this.client.execute(mkcol, this.context).getStatusLine().getStatusCode(); + assertEquals(201, status); + mkcol = new HttpMkcol(subcol2); + status = this.client.execute(mkcol, this.context).getStatusLine().getStatusCode(); + assertEquals(201, status); + + //create new resource R with path bindtest1/res1 + HttpPut put = new HttpPut(testres1); + put.setEntity(new StringEntity("foo", ContentType.create("text/plain", "UTF-8"))); + status = this.client.execute(put, this.context).getStatusLine().getStatusCode(); + assertEquals(201, status); + + // enabling version control always makes the resource referenceable + HttpVersionControl versioncontrol = new HttpVersionControl(testres1); + status = this.client.execute(versioncontrol, this.context).getStatusLine().getStatusCode(); + assertTrue("status: " + status, status == 200 || status == 201); + + URI r1 = this.getResourceId(testres1); + + HttpGet get = new HttpGet(testres1); + HttpResponse resp = this.client.execute(get, this.context); + status = resp.getStatusLine().getStatusCode(); + assertEquals(200, status); + assertEquals("foo", EntityUtils.toString(resp.getEntity())); + + //rebind R with path bindtest2/res2 + HttpRebind rebind = new HttpRebind(subcol2, new RebindInfo(testres1, "res2")); + status = this.client.execute(rebind, this.context).getStatusLine().getStatusCode(); + assertEquals(201, status); + + URI r2 = this.getResourceId(testres2); + + get = new HttpGet(testres2); + resp = this.client.execute(get, this.context); + status = resp.getStatusLine().getStatusCode(); + assertEquals(200, status); + assertEquals("foo", EntityUtils.toString(resp.getEntity())); + + //make sure that rebind did not change the resource-id + assertEquals(r1, r2); + + //verify that the initial binding is gone + HttpHead head = new HttpHead(testres1); + status = this.client.execute(head, this.context).getStatusLine().getStatusCode(); + assertEquals(404, status); + } finally { + delete(testcol); + } + } + + public void testBindOverwrite() throws Exception { + String testcol = this.root + "testSimpleBind/"; + String subcol1 = testcol + "bindtest1/"; + String testres1 = subcol1 + "res1"; + String subcol2 = testcol + "bindtest2/"; + String testres2 = subcol2 + "res2"; + int status; + try { + HttpMkcol mkcol = new HttpMkcol(testcol); + status = this.client.execute(mkcol, this.context).getStatusLine().getStatusCode(); + assertEquals(201, status); + mkcol = new HttpMkcol(subcol1); + status = this.client.execute(mkcol, this.context).getStatusLine().getStatusCode(); + assertEquals(201, status); + mkcol = new HttpMkcol(subcol2); + status = this.client.execute(mkcol, this.context).getStatusLine().getStatusCode(); + assertEquals(201, status); + + //create new resource R with path bindtest1/res1 + HttpPut put = new HttpPut(testres1); + put.setEntity(new StringEntity("foo", ContentType.create("text/plain", "UTF-8"))); + status = this.client.execute(put, this.context).getStatusLine().getStatusCode(); + assertEquals(201, status); + + //create new resource R' with path bindtest2/res2 + put = new HttpPut(testres2); + put.setEntity(new StringEntity("bar", ContentType.create("text/plain", "UTF-8"))); + status = this.client.execute(put, this.context).getStatusLine().getStatusCode(); + assertEquals(201, status); + + //try to create new binding of R with path bindtest2/res2 and Overwrite:F + HttpBind bind = new HttpBind(subcol2, new BindInfo(testres1, "res2")); + bind.addHeader("Overwrite", "F"); + status = this.client.execute(bind, this.context).getStatusLine().getStatusCode(); + assertEquals(412, status); + + //verify that bindtest2/res2 still points to R' + HttpGet get = new HttpGet(testres2); + HttpResponse resp = this.client.execute(get, this.context); + status = resp.getStatusLine().getStatusCode(); + assertEquals(200, status); + assertEquals("bar", EntityUtils.toString(resp.getEntity())); + + //create new binding of R with path bindtest2/res2 + bind = new HttpBind(subcol2, new BindInfo(testres1, "res2")); + status = this.client.execute(bind, this.context).getStatusLine().getStatusCode(); + assertTrue("status: " + status, status == 200 || status == 204); + + //verify that bindtest2/res2 now points to R + get = new HttpGet(testres2); + resp = this.client.execute(get, this.context); + status = resp.getStatusLine().getStatusCode(); + assertEquals(200, status); + assertEquals("foo", EntityUtils.toString(resp.getEntity())); + + //verify that the initial binding is still there + HttpHead head = new HttpHead(testres1); + status = this.client.execute(head, this.context).getStatusLine().getStatusCode(); + assertEquals(200, status); + } finally { + delete(testcol); + } + } + + public void testRebindOverwrite() throws Exception { + String testcol = this.root + "testSimpleBind/"; + String subcol1 = testcol + "bindtest1/"; + String testres1 = subcol1 + "res1"; + String subcol2 = testcol + "bindtest2/"; + String testres2 = subcol2 + "res2"; + int status; + try { + HttpMkcol mkcol = new HttpMkcol(testcol); + status = this.client.execute(mkcol, this.context).getStatusLine().getStatusCode(); + assertEquals(201, status); + mkcol = new HttpMkcol(subcol1); + status = this.client.execute(mkcol, this.context).getStatusLine().getStatusCode(); + assertEquals(201, status); + mkcol = new HttpMkcol(subcol2); + status = this.client.execute(mkcol, this.context).getStatusLine().getStatusCode(); + assertEquals(201, status); + + //create new resource R with path testSimpleBind/bindtest1/res1 + HttpPut put = new HttpPut(testres1); + put.setEntity(new StringEntity("foo", ContentType.create("text/plain", "UTF-8"))); + status = this.client.execute(put, this.context).getStatusLine().getStatusCode(); + assertEquals(201, status); + + // enabling version control always makes the resource referenceable + HttpVersionControl versioncontrol = new HttpVersionControl(testres1); + status = this.client.execute(versioncontrol, this.context).getStatusLine().getStatusCode(); + assertTrue("status: " + status, status == 200 || status == 201); + + //create new resource R' with path testSimpleBind/bindtest2/res2 + put = new HttpPut(testres2); + put.setEntity(new StringEntity("bar", ContentType.create("text/plain", "UTF-8"))); + status = this.client.execute(put, this.context).getStatusLine().getStatusCode(); + assertEquals(201, status); + + //try rebind R with path testSimpleBind/bindtest2/res2 and Overwrite:F + HttpRebind rebind = new HttpRebind(subcol2, new RebindInfo(testres1, "res2")); + rebind.addHeader("Overwrite", "F"); + status = this.client.execute(rebind, this.context).getStatusLine().getStatusCode(); + assertEquals(412, status); + + //verify that testSimpleBind/bindtest2/res2 still points to R' + HttpGet get = new HttpGet(testres2); + HttpResponse resp = this.client.execute(get, this.context); + status = resp.getStatusLine().getStatusCode(); + assertEquals(200, status); + assertEquals("bar", EntityUtils.toString(resp.getEntity())); + + //rebind R with path testSimpleBind/bindtest2/res2 + rebind = new HttpRebind(subcol2, new RebindInfo(testres1, "res2")); + status = this.client.execute(rebind, this.context).getStatusLine().getStatusCode(); + assertTrue("status: " + status, status == 200 || status == 204); + + //verify that testSimpleBind/bindtest2/res2 now points to R + get = new HttpGet(testres2); + resp = this.client.execute(get, this.context); + status = resp.getStatusLine().getStatusCode(); + assertEquals(200, status); + assertEquals("foo", EntityUtils.toString(resp.getEntity())); + + //verify that the initial binding is gone + HttpHead head = new HttpHead(testres1); + status = this.client.execute(head, this.context).getStatusLine().getStatusCode(); + assertEquals(404, status); + } finally { + delete(testcol); + } + } + + public void testParentSet() throws Exception { + String testcol = this.root + "testParentSet/"; + String subcol1 = testcol + "bindtest1/"; + String testres1 = subcol1 + "res1"; + String subcol2 = testcol + "bindtest2/"; + String testres2 = subcol2 + "res2"; + int status; + try { + HttpMkcol mkcol = new HttpMkcol(testcol); + status = this.client.execute(mkcol, this.context).getStatusLine().getStatusCode(); + assertEquals(201, status); + mkcol = new HttpMkcol(subcol1); + status = this.client.execute(mkcol, this.context).getStatusLine().getStatusCode(); + assertEquals(201, status); + mkcol = new HttpMkcol(subcol2); + status = this.client.execute(mkcol, this.context).getStatusLine().getStatusCode(); + assertEquals(201, status); + + //create new resource R with path testSimpleBind/bindtest1/res1 + HttpPut put = new HttpPut(testres1); + put.setEntity(new StringEntity("foo", ContentType.create("text/plain", "UTF-8"))); + status = this.client.execute(put, this.context).getStatusLine().getStatusCode(); + assertEquals(201, status); + + //create new binding of R with path testSimpleBind/bindtest2/res2 + HttpBind bind = new HttpBind(subcol2, new BindInfo(testres1, "res2")); + status = this.client.execute(bind, this.context).getStatusLine().getStatusCode(); + assertEquals(201, status); + //check if both bindings report the same DAV:resource-id + assertEquals(this.getResourceId(testres1), this.getResourceId(testres2)); + + //verify values of parent-set properties + List hrefs1 = new ArrayList(); + List segments1 = new ArrayList(); + List hrefs2 = new ArrayList(); + List segments2 = new ArrayList(); + Object ps1 = this.getParentSet(testres1).getValue(); + Object ps2 = this.getParentSet(testres2).getValue(); + assertTrue(ps1 instanceof List); + assertTrue(ps2 instanceof List); + List plist1 = (List) ps1; + List plist2 = (List) ps2; + assertEquals(2, plist1.size()); + assertEquals(2, plist2.size()); + for (int k = 0; k < 2; k++) { + Object pObj1 = plist1.get(k); + Object pObj2 = plist2.get(k); + assertTrue(pObj1 instanceof Element); + assertTrue(pObj2 instanceof Element); + ParentElement p1 = ParentElement.createFromXml((Element) pObj1); + ParentElement p2 = ParentElement.createFromXml((Element) pObj2); + hrefs1.add(p1.getHref()); + hrefs2.add(p2.getHref()); + segments1.add(p1.getSegment()); + segments2.add(p2.getSegment()); + } + Collections.sort(hrefs1); + Collections.sort(hrefs2); + Collections.sort(segments1); + Collections.sort(segments2); + assertEquals(hrefs1, hrefs2); + assertEquals(segments1, segments2); + } finally { + delete(testcol); + } + } + + public void testBindCollections() throws Exception { + String testcol = this.root + "testBindCollections/"; + String a1 = testcol + "a1/"; + String b1 = a1 + "b1/"; + String c1 = b1 + "c1/"; + String x1 = c1 + "x1"; + String a2 = testcol + "a2/"; + String b2 = a2 + "b2/"; + String c2 = b2 + "c2/"; + String x2 = c2 + "x2"; + int status; + try { + HttpMkcol mkcol = new HttpMkcol(testcol); + status = this.client.execute(mkcol, this.context).getStatusLine().getStatusCode(); + assertEquals(201, status); + mkcol = new HttpMkcol(a1); + status = this.client.execute(mkcol, this.context).getStatusLine().getStatusCode(); + assertEquals(201, status); + mkcol = new HttpMkcol(a2); + status = this.client.execute(mkcol, this.context).getStatusLine().getStatusCode(); + assertEquals(201, status); + + //create collection resource C + mkcol = new HttpMkcol(b1); + status = this.client.execute(mkcol, this.context).getStatusLine().getStatusCode(); + assertEquals(201, status); + mkcol = new HttpMkcol(c1); + status = this.client.execute(mkcol, this.context).getStatusLine().getStatusCode(); + assertEquals(201, status); + + //create plain resource R + HttpPut put = new HttpPut(x1); + put.setEntity(new StringEntity("foo", ContentType.create("text/plain", "UTF-8"))); + status = this.client.execute(put, this.context).getStatusLine().getStatusCode(); + assertEquals(201, status); + + //create new binding of C with path a2/b2 + HttpBind bind = new HttpBind(a2, new BindInfo(b1, "b2")); + status = this.client.execute(bind, this.context).getStatusLine().getStatusCode(); + assertEquals(201, status); + //check if both bindings report the same DAV:resource-id + assertEquals(this.getResourceId(b1), this.getResourceId(b2)); + + mkcol = new HttpMkcol(c2); + status = this.client.execute(mkcol, this.context).getStatusLine().getStatusCode(); + assertEquals(201, status); + + //create new binding of R with path a2/b2/c2/r2 + bind = new HttpBind(c2, new BindInfo(x1, "x2")); + status = this.client.execute(bind, this.context).getStatusLine().getStatusCode(); + assertEquals(201, status); + //check if both bindings report the same DAV:resource-id + assertEquals(this.getResourceId(x1), this.getResourceId(x2)); + + //verify different path alternatives + URI rid = this.getResourceId(x1); + assertEquals(rid, this.getResourceId(x2)); + assertEquals(rid, this.getResourceId(testcol + "a2/b2/c1/x1")); + assertEquals(rid, this.getResourceId(testcol + "a1/b1/c2/x2")); + Object ps = this.getParentSet(x1).getValue(); + assertTrue(ps instanceof List); + assertEquals(2, ((List) ps).size()); + ps = this.getParentSet(x2).getValue(); + assertTrue(ps instanceof List); + assertEquals(2, ((List) ps).size()); + } finally { + delete(testcol); + } + } + + //will fail until is fixed + public void testUnbind() throws Exception { + String testcol = this.root + "testUnbind/"; + String subcol1 = testcol + "bindtest1/"; + String testres1 = subcol1 + "res1"; + String subcol2 = testcol + "bindtest2/"; + String testres2 = subcol2 + "res2"; + int status; + try { + HttpMkcol mkcol = new HttpMkcol(testcol); + status = this.client.execute(mkcol, this.context).getStatusLine().getStatusCode(); + assertEquals(201, status); + mkcol = new HttpMkcol(subcol1); + status = this.client.execute(mkcol, this.context).getStatusLine().getStatusCode(); + assertEquals(201, status); + mkcol = new HttpMkcol(subcol2); + status = this.client.execute(mkcol, this.context).getStatusLine().getStatusCode(); + assertEquals(201, status); + + //create new resource R with path testSimpleBind/bindtest1/res1 + HttpPut put = new HttpPut(testres1); + put.setEntity(new StringEntity("foo", ContentType.create("text/plain", "UTF-8"))); + status = this.client.execute(put, this.context).getStatusLine().getStatusCode(); + assertEquals(201, status); + + //create new binding of R with path testSimpleBind/bindtest2/res2 + HttpBind bind = new HttpBind(subcol2, new BindInfo(testres1, "res2")); + status = this.client.execute(bind, this.context).getStatusLine().getStatusCode(); + assertEquals(201, status); + //check if both bindings report the same DAV:resource-id + assertEquals(this.getResourceId(testres1), this.getResourceId(testres2)); + + //remove new path + HttpUnbind unbind = new HttpUnbind(subcol2, new UnbindInfo("res2")); + status = this.client.execute(unbind, this.context).getStatusLine().getStatusCode(); + assertTrue("status: " + status, status == 200 || status == 204); + + //verify that the new binding is gone + HttpHead head = new HttpHead(testres2); + status = this.client.execute(head, this.context).getStatusLine().getStatusCode(); + assertEquals(404, status); + + //verify that the initial binding is still there + head = new HttpHead(testres1); + status = this.client.execute(head, this.context).getStatusLine().getStatusCode(); + assertEquals(200, status); + } finally { + delete(testcol); + } + } + + private String getUri(Element href) { + String s = ""; + for (Node c = href.getFirstChild(); c != null; c = c.getNextSibling()) { + if (c.getNodeType() == Node.TEXT_NODE) { + s += c.getNodeValue(); + } + } + return s; + } +} Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/server/BindTest.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/server/ConditionalsTest.java =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/server/ConditionalsTest.java (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/server/ConditionalsTest.java (working copy) @@ -0,0 +1,177 @@ +/* + * 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.webdav.server; + +import java.io.IOException; +import java.text.ParseException; + +import org.apache.http.Header; +import org.apache.http.HttpResponse; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.client.methods.HttpHead; +import org.apache.http.client.methods.HttpPut; +import org.apache.http.entity.StringEntity; +import org.apache.http.util.EntityUtils; + +public class ConditionalsTest extends WebDAVTestBase { + + // private DateFormat HTTPDATEFORMAT = new SimpleDateFormat("EEE, dd MMM + // yyyy HH:mm:ss ZZZ", Locale.ENGLISH); + + public void testPutCheckLastModified() throws IOException, ParseException { + String testUri = this.uri.toString() + (this.uri.toString().endsWith("/") ? "" : "/") + "testPutCheckLastModified"; + try { + // create test resource + { + HttpPut put = new HttpPut(testUri); + put.setEntity(new StringEntity("foobar")); + HttpResponse response = this.client.execute(put, this.context); + int status = response.getStatusLine().getStatusCode(); + assertEquals(201, status); + } + + long created = System.currentTimeMillis(); + + // get last modified date + Header etag = null; + Header lm = null; + { + HttpHead head = new HttpHead(testUri); + HttpResponse response = this.client.execute(head, this.context); + int status = response.getStatusLine().getStatusCode(); + assertEquals(200, status); + lm = response.getFirstHeader("last-modified"); + assertNotNull(lm); + etag = response.getFirstHeader("etag"); + } + + // Date created = HTTPDATEFORMAT.parse(lm.getValue()); + + // conditional GET + { + HttpGet get = new HttpGet(testUri); + get.setHeader("If-Modified-Since", lm.getValue()); + HttpResponse response = this.client.execute(get, this.context); + int status = response.getStatusLine().getStatusCode(); + assertEquals(304, status); + if (etag != null) { + Header newetag = response.getFirstHeader("etag"); + assertNotNull(newetag); + assertEquals(etag.getValue(), newetag.getValue()); + } + } + + // conditional HEAD + { + HttpHead head = new HttpHead(testUri); + head.setHeader("If-Modified-Since", lm.getValue()); + HttpResponse response = this.client.execute(head, this.context); + int status = response.getStatusLine().getStatusCode(); + assertEquals(304, status); + if (etag != null) { + Header newetag = response.getFirstHeader("etag"); + assertNotNull(newetag); + assertEquals(etag.getValue(), newetag.getValue()); + } + } + + // conditional HEAD with broken date (MUST ignore header field) + { + HttpHead head = new HttpHead(testUri); + head.setHeader("If-Modified-Since", "broken"); + HttpResponse response = this.client.execute(head, this.context); + int status = response.getStatusLine().getStatusCode(); + assertEquals(200, status); + } + + // conditional GET with broken date (MUST ignore header field) + { + HttpGet req = new HttpGet(testUri); + req.addHeader("If-Modified-Since", lm.getValue()); + req.addHeader("If-Modified-Since", "foo"); + HttpResponse response = this.client.execute(req, this.context); + int status = response.getStatusLine().getStatusCode(); + assertEquals(200, status); + EntityUtils.consume(response.getEntity()); + } + + // let one sec elapse + while (System.currentTimeMillis() < created + 1000) { + try { + Thread.sleep(100); + } catch (InterruptedException ignored) { + } + } + + // verify last modified did not change + { + HttpHead head = new HttpHead(testUri); + HttpResponse response = this.client.execute(head, this.context); + int status = response.getStatusLine().getStatusCode(); + assertEquals(200, status); + Header newlm = response.getFirstHeader("last-modified"); + assertNotNull(newlm); + assertEquals(lm.getValue(), newlm.getValue()); + } + + // conditional PUT + { + HttpPut put = new HttpPut(testUri); + put.setHeader("If-Unmodified-Since", lm.getValue()); + put.setEntity(new StringEntity("qux")); + HttpResponse response = this.client.execute(put, this.context); + int status = response.getStatusLine().getStatusCode(); + assertEquals(204, status); + } + + // conditional PUT once more should fail + { + HttpPut put = new HttpPut(testUri); + put.setHeader("If-Unmodified-Since", lm.getValue()); + put.setEntity(new StringEntity("lazydog")); + HttpResponse response = this.client.execute(put, this.context); + int status = response.getStatusLine().getStatusCode(); + assertEquals(412, status); + } + + // conditional PUT with broken If-Unmodified-Since should pass + { + HttpPut put = new HttpPut(testUri); + put.addHeader("If-Unmodified-Since", lm.getValue()); + put.addHeader("If-Unmodified-Since", "foo"); + put.setEntity(new StringEntity("qux")); + HttpResponse response = this.client.execute(put, this.context); + int status = response.getStatusLine().getStatusCode(); + assertEquals(204, status); + } + } finally { + delete(testUri); + } + } + + public void testGetCollectionEtag() throws IOException, ParseException { + String testUri = this.uri.toString() + (this.uri.toString().endsWith("/") ? "" : "/"); + HttpGet get = new HttpGet(testUri); + HttpResponse response = this.client.execute(get, this.context); + int status = response.getStatusLine().getStatusCode(); + assertEquals(200, status); + Header etag = response.getFirstHeader("etag"); + if (etag != null) { + assertFalse("etag must not be empty", "".equals(etag.getValue())); + } + } +} Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/server/ConditionalsTest.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/server/ContentCodingTest.java =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/server/ContentCodingTest.java (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/server/ContentCodingTest.java (working copy) @@ -0,0 +1,232 @@ +/* + * 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.webdav.server; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Locale; +import java.util.zip.DeflaterOutputStream; +import java.util.zip.GZIPOutputStream; + +import org.apache.http.Header; +import org.apache.http.HttpResponse; +import org.apache.http.client.methods.HttpHead; +import org.apache.http.client.methods.HttpPut; +import org.apache.http.entity.ByteArrayEntity; +import org.apache.http.entity.StringEntity; +import org.apache.http.message.BasicHeader; +import org.apache.jackrabbit.webdav.DavConstants; +import org.apache.jackrabbit.webdav.DavException; +import org.apache.jackrabbit.webdav.MultiStatusResponse; +import org.apache.jackrabbit.webdav.client.methods.HttpPropfind; + +public class ContentCodingTest extends WebDAVTestBase { + + public void testPutNoContentCoding() throws IOException { + String testUri = this.uri.toString() + (this.uri.toString().endsWith("/") ? "" : "/") + "testPutNoContentCoding"; + try { + HttpPut put = new HttpPut(testUri); + put.setEntity(new StringEntity("foobar")); + int status = this.client.execute(put, this.context).getStatusLine().getStatusCode(); + assertEquals(201, status); + } finally { + delete(testUri); + } + } + + public void testPutUnknownContentCoding() throws IOException { + String testUri = this.uri.toString() + (this.uri.toString().endsWith("/") ? "" : "/") + "testPutUnkownContentCoding"; + int status = -1; + try { + HttpPut put = new HttpPut(testUri); + StringEntity entity = new StringEntity("foobarfoobarfoobar"); + entity.setContentEncoding(new BasicHeader("Content-Encoding", "qux")); + put.setEntity(entity); + status = this.client.execute(put, this.context).getStatusLine().getStatusCode(); + assertTrue("server must signal error for unknown content coding, got: " + status, status == 415); + } finally { + if (status / 2 == 100) { + delete(testUri); + } + } + } + + public void testPutGzipContentCoding() throws IOException { + String testUri = this.uri.toString() + (this.uri.toString().endsWith("/") ? "" : "/") + "testPutGzipContentCoding"; + int status = -1; + try { + byte bytes[] = "foobarfoobarfoobar".getBytes("UTF-8"); + HttpPut put = new HttpPut(testUri); + byte gzbytes[] = asGzipOctets(bytes); + assertTrue(gzbytes.length != bytes.length); + ByteArrayEntity entity = new ByteArrayEntity(gzbytes); + entity.setContentEncoding(new BasicHeader("Content-Encoding", "gzip")); + put.setEntity(entity); + status = this.client.execute(put, this.context).getStatusLine().getStatusCode(); + assertTrue("server create or signal error, got: " + status, status == 201 || status == 415); + if (status / 2 == 100) { + // check length + HttpHead head = new HttpHead(testUri); + HttpResponse response = this.client.execute(head, this.context); + assertEquals(200, response.getStatusLine().getStatusCode()); + assertEquals(bytes.length, Integer.parseInt(response.getFirstHeader("Content-Length").getValue())); + } + } finally { + if (status / 2 == 100) { + delete(testUri); + } + } + } + + public void testPropfindNoContentCoding() throws IOException, DavException { + HttpPropfind propfind = new HttpPropfind(uri, DavConstants.PROPFIND_BY_PROPERTY, 0); + HttpResponse response = this.client.execute(propfind, this.context); + int status = response.getStatusLine().getStatusCode(); + assertEquals(207, status); + List encodings = getContentCodings(response); + assertTrue("Accept should list 'gzip' but did not: " + encodings, encodings.contains("gzip")); + assertTrue("Accept should list 'deflate' but did not: " + encodings, encodings.contains("deflate")); + } + + public void testPropfindAcceptReponseEncoding() throws IOException, DavException { + HttpPropfind propfind = new HttpPropfind(uri, DavConstants.PROPFIND_BY_PROPERTY, 0); + propfind.setHeader(new BasicHeader("Accept-Encoding", "gzip;q=0.555")); + HttpResponse response = this.client.execute(propfind, this.context); + int status = response.getStatusLine().getStatusCode(); + assertEquals(207, status); + MultiStatusResponse[] responses = propfind.getResponseBodyAsMultiStatus(response).getResponses(); + assertEquals(1, responses.length); + } + + private static String PF = ""; + + public void testPropfindUnknownContentCoding() throws IOException { + HttpPropfind propfind = new HttpPropfind(uri, DavConstants.PROPFIND_BY_PROPERTY, 0); + StringEntity entity = new StringEntity(PF); + entity.setContentEncoding(new BasicHeader("Content-Encoding", "qux")); + propfind.setEntity(entity); + HttpResponse response = this.client.execute(propfind, this.context); + int status = response.getStatusLine().getStatusCode(); + assertTrue("server must signal error for unknown content coding, got: " + status, status == 415); + List encodings = getContentCodings(response); + assertTrue("Accept should list 'gzip' but did not: " + encodings, encodings.contains("gzip")); + assertTrue("Accept should list 'deflate' but did not: " + encodings, encodings.contains("deflate")); + } + + public void testPropfindGzipContentCoding() throws IOException { + HttpPropfind propfind = new HttpPropfind(uri, DavConstants.PROPFIND_BY_PROPERTY, 0); + ByteArrayEntity entity = new ByteArrayEntity(asGzipOctets(PF)); + entity.setContentEncoding(new BasicHeader("Content-Encoding", "gzip")); + propfind.setEntity(entity); + int status = this.client.execute(propfind, this.context).getStatusLine().getStatusCode(); + assertEquals(207, status); + } + + // double encoded, empty list member in field value, mixed upper/lower in + // coding name + public void testPropfindGzipContentCodingTwice() throws IOException { + HttpPropfind propfind = new HttpPropfind(uri, DavConstants.PROPFIND_BY_PROPERTY, 0); + ByteArrayEntity entity = new ByteArrayEntity(asGzipOctets(asGzipOctets(PF))); + entity.setContentEncoding(new BasicHeader("Content-Encoding", "gziP,, Gzip")); + propfind.setEntity(entity); + int status = this.client.execute(propfind, this.context).getStatusLine().getStatusCode(); + assertEquals(207, status); + } + + // double encoded, but only when encoding in header field + public void testPropfindGzipContentCodingBadSpec() throws IOException { + HttpPropfind propfind = new HttpPropfind(uri, DavConstants.PROPFIND_BY_PROPERTY, 0); + ByteArrayEntity entity = new ByteArrayEntity(asGzipOctets(asGzipOctets(PF))); + entity.setContentEncoding(new BasicHeader("Content-Encoding", "gzip")); + propfind.setEntity(entity); + int status = this.client.execute(propfind, this.context).getStatusLine().getStatusCode(); + assertEquals(400, status); + } + + public void testPropfindDeflateContentCoding() throws IOException { + HttpPropfind propfind = new HttpPropfind(uri, DavConstants.PROPFIND_BY_PROPERTY, 0); + ByteArrayEntity entity = new ByteArrayEntity(asDeflateOctets(PF)); + entity.setContentEncoding(new BasicHeader("Content-Encoding", "deflate")); + propfind.setEntity(entity); + int status = this.client.execute(propfind, this.context).getStatusLine().getStatusCode(); + assertEquals(207, status); + } + + public void testPropfindGzipDeflateContentCoding() throws IOException { + HttpPropfind propfind = new HttpPropfind(uri, DavConstants.PROPFIND_BY_PROPERTY, 0); + ByteArrayEntity entity = new ByteArrayEntity(asDeflateOctets(asGzipOctets(PF))); + entity.setContentEncoding(new BasicHeader("Content-Encoding", "gzip, deflate")); + propfind.setEntity(entity); + int status = this.client.execute(propfind, this.context).getStatusLine().getStatusCode(); + assertEquals(207, status); + } + + public void testPropfindGzipDeflateContentCodingMislabeled() throws IOException { + HttpPropfind propfind = new HttpPropfind(uri, DavConstants.PROPFIND_BY_PROPERTY, 0); + ByteArrayEntity entity = new ByteArrayEntity(asDeflateOctets(asGzipOctets(PF))); + entity.setContentEncoding(new BasicHeader("Content-Encoding", "deflate, gzip")); + propfind.setEntity(entity); + int status = this.client.execute(propfind, this.context).getStatusLine().getStatusCode(); + assertEquals(400, status); + } + + private static byte[] asGzipOctets(String input) throws IOException { + return asGzipOctets(input.getBytes("UTF-8")); + } + + private static byte[] asGzipOctets(byte[] input) throws IOException { + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + OutputStream gos = new GZIPOutputStream(bos); + gos.write(input); + gos.flush(); + gos.close(); + return bos.toByteArray(); + } + + private static byte[] asDeflateOctets(String input) throws IOException { + return asDeflateOctets(input.getBytes("UTF-8")); + } + + private static byte[] asDeflateOctets(byte[] input) throws IOException { + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + OutputStream gos = new DeflaterOutputStream(bos); + gos.write(input); + gos.flush(); + gos.close(); + return bos.toByteArray(); + } + + private static List getContentCodings(HttpResponse response) { + List result = Collections.emptyList(); + for (Header l : response.getHeaders("Accept-Encoding")) { + for (String h : l.getValue().split(",")) { + if (!h.trim().isEmpty()) { + if (result.isEmpty()) { + result = new ArrayList(); + } + result.add(h.trim().toLowerCase(Locale.ENGLISH)); + } + } + } + + return result; + } +} Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/server/ContentCodingTest.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/server/HttpsSelfSignedTest.java =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/server/HttpsSelfSignedTest.java (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/server/HttpsSelfSignedTest.java (working copy) @@ -0,0 +1,42 @@ +/* + * 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.webdav.server; + +import java.io.IOException; +import java.text.ParseException; + +import javax.net.ssl.SSLHandshakeException; + +import org.apache.http.HttpResponse; +import org.apache.http.client.methods.HttpPut; +import org.apache.http.entity.StringEntity; + +public class HttpsSelfSignedTest extends WebDAVTestBase { + + // check that by default, the client will fail connecting to HTTPS due to + // self-signed certificate + public void testPutCheckLastModified() throws IOException, ParseException { + try { + String testUri = this.httpsUri.toString(); + HttpPut put = new HttpPut(testUri); + put.setEntity(new StringEntity("foobar")); + HttpResponse response = this.client.execute(put, this.context); + fail("should failt with SSLHandshakeException, but got: " + response); + } catch (SSLHandshakeException expected) { + } + } +} Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/server/HttpsSelfSignedTest.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/server/ProppatchTest.java =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/server/ProppatchTest.java (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/server/ProppatchTest.java (working copy) @@ -0,0 +1,79 @@ +/* + * 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.webdav.server; + +import java.io.IOException; + +import org.apache.http.HttpResponse; +import org.apache.http.client.methods.HttpPut; +import org.apache.http.entity.StringEntity; +import org.apache.http.util.EntityUtils; +import org.apache.jackrabbit.webdav.DavException; +import org.apache.jackrabbit.webdav.MultiStatusResponse; +import org.apache.jackrabbit.webdav.client.methods.HttpPropfind; +import org.apache.jackrabbit.webdav.client.methods.HttpProppatch; +import org.apache.jackrabbit.webdav.property.DavProperty; +import org.apache.jackrabbit.webdav.property.DavPropertyName; +import org.apache.jackrabbit.webdav.property.DavPropertyNameSet; +import org.apache.jackrabbit.webdav.property.DavPropertySet; +import org.apache.jackrabbit.webdav.property.DefaultDavProperty; +import org.apache.jackrabbit.webdav.xml.Namespace; + +public class ProppatchTest extends WebDAVTestBase { + + public void testPropPatchSurrogate() throws IOException, DavException { + + String testuri = this.root + "ppsurrogate"; + + try { + int status; + + HttpPut put = new HttpPut(testuri); + put.setEntity(new StringEntity("1")); + status = this.client.execute(put, this.context).getStatusLine().getStatusCode(); + assertEquals("status: " + status, 201, status); + + DavPropertyName name = DavPropertyName.create("foobar", Namespace.EMPTY_NAMESPACE); + DavPropertySet props = new DavPropertySet(); + DavProperty foobar = new DefaultDavProperty<>(name, "\uD83D\uDCA9"); + props.add(foobar); + HttpProppatch proppatch = new HttpProppatch(testuri, props, new DavPropertyNameSet()); + HttpResponse resp = this.client.execute(proppatch, this.context); + status = resp.getStatusLine().getStatusCode(); + assertEquals(207, status); + EntityUtils.consume(resp.getEntity()); + + DavPropertyNameSet names = new DavPropertyNameSet(); + names.add(name); + HttpPropfind propfind = new HttpPropfind(testuri, names, 0); + resp = this.client.execute(propfind, this.context); + status = resp.getStatusLine().getStatusCode(); + assertEquals(207, status); + MultiStatusResponse[] responses = propfind.getResponseBodyAsMultiStatus(resp).getResponses(); + assertEquals(1, responses.length); + + MultiStatusResponse response = responses[0]; + DavPropertySet found = response.getProperties(200); + + DavProperty f = found.get(name); + assertEquals("\uD83D\uDCA9", f.getValue()); + } finally { + delete(testuri); + } + } + +} Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/server/ProppatchTest.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/server/PutTest.java =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/server/PutTest.java (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/server/PutTest.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.webdav.server; + +import java.io.IOException; +import java.text.ParseException; + +import org.apache.http.HttpResponse; +import org.apache.http.client.methods.HttpPut; +import org.apache.http.entity.StringEntity; + +/** + * Test cases for HTTP PUT method + */ +public class PutTest extends WebDAVTestBase { + + public void testPutWithContentRange() throws IOException, ParseException { + String testUri = this.uri.toString() + (this.uri.toString().endsWith("/") ? "" : "/") + "testPutWithContentRange"; + HttpPut put = new HttpPut(testUri); + put.addHeader("Content-Range", "bytes 0-5/6"); + put.setEntity(new StringEntity("foobar")); + HttpResponse response = this.client.execute(put, this.context); + int status = response.getStatusLine().getStatusCode(); + assertEquals(400, status); + } +} Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/server/PutTest.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/server/RFC4918DestinationHeaderTest.java =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/server/RFC4918DestinationHeaderTest.java (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/server/RFC4918DestinationHeaderTest.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.webdav.server; + +import java.io.IOException; +import java.net.URI; +import java.net.URISyntaxException; + +import org.apache.http.client.methods.HttpDelete; +import org.apache.http.client.methods.HttpHead; +import org.apache.http.client.methods.HttpPut; +import org.apache.http.client.methods.HttpRequestBase; +import org.apache.jackrabbit.webdav.client.methods.HttpMove; + +/** + * Test cases for RFC 4918 Destination header functionality + * (see RFC 4918, Section 10.3 + */ +public class RFC4918DestinationHeaderTest extends WebDAVTestBase { + + public void testMove() throws IOException, URISyntaxException { + + String testuri = this.root + "movetest"; + String destinationuri = testuri + "2"; + String destinationpath = new URI(destinationuri).getRawPath(); + // make sure the scheme is removed + assertFalse(destinationpath.contains(":")); + + HttpRequestBase requestBase = null; + try { + requestBase = new HttpPut(testuri); + int status = this.client.execute(requestBase, this.context).getStatusLine().getStatusCode(); + assertTrue("status: " + status, status == 200 || status == 201 || status == 204); + requestBase.releaseConnection(); + + // try to move outside the servlet's name space + requestBase = new HttpMove(testuri, "/foobar", true); + status = this.client.execute(requestBase, this.context).getStatusLine().getStatusCode(); + assertTrue("status: " + status, status == 502); + requestBase.releaseConnection(); + + // try a relative path + requestBase = new HttpMove(testuri, "foobar", true); + status = this.client.execute(requestBase, this.context).getStatusLine().getStatusCode(); + assertTrue("status: " + status, status == 400); + requestBase.releaseConnection(); + + requestBase = new HttpMove(testuri, destinationpath, true); + status = this.client.execute(requestBase, this.context).getStatusLine().getStatusCode(); + assertTrue("status: " + status, status == 200 || status == 201 || status == 204); + requestBase.releaseConnection(); + + requestBase = new HttpHead(destinationuri); + status = this.client.execute(requestBase, this.context).getStatusLine().getStatusCode(); + assertTrue("status: " + status, status == 200); + requestBase.releaseConnection(); + + requestBase = new HttpHead(testuri); + status = this.client.execute(requestBase, this.context).getStatusLine().getStatusCode(); + assertTrue("status: " + status, status == 404); + } finally { + requestBase.releaseConnection(); + requestBase = new HttpDelete(testuri); + int status = this.client.execute(requestBase, this.context).getStatusLine().getStatusCode(); + assertTrue("status: " + status, status == 200 || status == 204 || status == 404); + requestBase.releaseConnection(); + requestBase = new HttpDelete(destinationuri); + status = this.client.execute(requestBase, this.context).getStatusLine().getStatusCode(); + assertTrue("status: " + status, status == 200 || status == 204 || status == 404); + requestBase.releaseConnection(); + } + } +} Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/server/RFC4918DestinationHeaderTest.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/server/RFC4918IfHeaderTest.java =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/server/RFC4918IfHeaderTest.java (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/server/RFC4918IfHeaderTest.java (working copy) @@ -0,0 +1,143 @@ +/* + * 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.webdav.server; + +import java.io.IOException; +import java.net.URI; +import java.net.URISyntaxException; + +import org.apache.http.HttpResponse; +import org.apache.http.client.methods.HttpDelete; +import org.apache.http.client.methods.HttpPut; +import org.apache.http.client.methods.HttpRequestBase; +import org.apache.http.entity.StringEntity; +import org.apache.jackrabbit.webdav.client.methods.HttpLock; +import org.apache.jackrabbit.webdav.lock.LockInfo; +import org.apache.jackrabbit.webdav.lock.Scope; +import org.apache.jackrabbit.webdav.lock.Type; + +/** + * Test cases for RFC 4918 If header functionality + * (see RFC 4918, Section 10.4 + */ + +public class RFC4918IfHeaderTest extends WebDAVTestBase { + + public void testPutIfEtag() throws IOException { + + String testuri = this.root + "iftest"; + HttpPut put = new HttpPut(testuri); + try { + put = new HttpPut(testuri); + String condition = "<" + testuri + "> ([" + "\"an-etag-this-testcase-invented\"" + "])"; + put.setEntity(new StringEntity("1")); + put.setHeader("If", condition); + int status = this.client.execute(put, this.context).getStatusLine().getStatusCode(); + assertEquals("status: " + status, 412, status); + put.releaseConnection(); + + } + finally { + put.releaseConnection(); + HttpDelete delete = new HttpDelete(testuri); + int status = this.client.execute(delete, this.context).getStatusLine().getStatusCode(); + assertTrue("status: " + status, status == 200 || status == 204 || status == 404); + delete.releaseConnection(); + } + } + + public void testPutIfLockToken() throws IOException, URISyntaxException { + + String testuri = this.root + "iflocktest"; + String locktoken = null; + + HttpRequestBase requestBase = null; + try { + requestBase = new HttpPut(testuri); + ((HttpPut)requestBase).setEntity(new StringEntity("1")); + int status = this.client.execute(requestBase, this.context).getStatusLine().getStatusCode(); + assertTrue("status: " + status, status == 200 || status == 201 || status == 204); + requestBase.releaseConnection(); + + requestBase = new HttpLock(testuri, new LockInfo( + Scope.EXCLUSIVE, Type.WRITE, "testcase", 10000, true)); + HttpResponse response = this.client.execute(requestBase, this.context); + status = response.getStatusLine().getStatusCode(); + assertEquals("status", 200, status); + locktoken = ((HttpLock)requestBase).getLockToken(response); + assertNotNull(locktoken); + requestBase.releaseConnection(); + + // try to overwrite without lock token + requestBase = new HttpPut(testuri); + ((HttpPut)requestBase).setEntity(new StringEntity("2")); + status = this.client.execute(requestBase, this.context).getStatusLine().getStatusCode(); + assertEquals("status: " + status, 423, status); + requestBase.releaseConnection(); + + // try to overwrite using bad lock token + requestBase = new HttpPut(testuri); + ((HttpPut)requestBase).setEntity(new StringEntity("2")); + requestBase.setHeader("If", "(<" + "DAV:foobar" + ">)"); + status = this.client.execute(requestBase, this.context).getStatusLine().getStatusCode(); + assertEquals("status: " + status, 412, status); + requestBase.releaseConnection(); + + // try to overwrite using correct lock token, using No-Tag-list format + requestBase = new HttpPut(testuri); + ((HttpPut)requestBase).setEntity(new StringEntity("2")); + requestBase.setHeader("If", "(<" + locktoken + ">)"); + status = this.client.execute(requestBase, this.context).getStatusLine().getStatusCode(); + assertTrue("status: " + status, status == 200 || status == 204); + requestBase.releaseConnection(); + + // try to overwrite using correct lock token, using Tagged-list format + // and full URI + requestBase = new HttpPut(testuri); + ((HttpPut)requestBase).setEntity(new StringEntity("3")); + requestBase.setHeader("If", "<" + testuri + ">" + "(<" + locktoken + ">)"); + status = this.client.execute(requestBase, this.context).getStatusLine().getStatusCode(); + assertTrue("status: " + status, status == 200 || status == 204); + requestBase.releaseConnection(); + + // try to overwrite using correct lock token, using Tagged-list format + // and absolute path only + requestBase = new HttpPut(testuri); + ((HttpPut)requestBase).setEntity(new StringEntity("4")); + requestBase.setHeader("If", "<" + new URI(testuri).getRawPath() + ">" + "(<" + locktoken + ">)"); + status = this.client.execute(requestBase, this.context).getStatusLine().getStatusCode(); + assertTrue("status: " + status, status == 200 || status == 204); + requestBase.releaseConnection(); + + // try to overwrite using correct lock token, using Tagged-list format + // and bad path + requestBase = new HttpPut(testuri); + ((HttpPut)requestBase).setEntity(new StringEntity("5")); + requestBase.setHeader("If", "" + "(<" + locktoken + ">)"); + status = this.client.execute(requestBase, this.context).getStatusLine().getStatusCode(); + assertTrue("status: " + status, status == 404 || status == 412); + } finally { + requestBase.releaseConnection(); + requestBase = new HttpDelete(testuri); + if (locktoken != null) { + requestBase.setHeader("If", "(<" + locktoken + ">)"); + } + int status = this.client.execute(requestBase, this.context).getStatusLine().getStatusCode(); + assertTrue("status: " + status, status == 200 || status == 204 || status == 404); + } + } +} Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/server/RFC4918IfHeaderTest.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/server/RFC4918PropfindTest.java =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/server/RFC4918PropfindTest.java (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/server/RFC4918PropfindTest.java (working copy) @@ -0,0 +1,78 @@ +/* + * 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.webdav.server; + +import java.io.IOException; + +import org.apache.http.HttpResponse; +import org.apache.http.client.methods.HttpPut; +import org.apache.http.entity.StringEntity; +import org.apache.jackrabbit.webdav.DavConstants; +import org.apache.jackrabbit.webdav.DavException; +import org.apache.jackrabbit.webdav.MultiStatus; +import org.apache.jackrabbit.webdav.MultiStatusResponse; +import org.apache.jackrabbit.webdav.client.methods.HttpOptions; +import org.apache.jackrabbit.webdav.client.methods.HttpPropfind; +import org.apache.jackrabbit.webdav.property.DavPropertyNameSet; +import org.apache.jackrabbit.webdav.property.DavPropertySet; +import org.apache.jackrabbit.webdav.version.DeltaVConstants; + +/** + * Test cases for RFC 4918 PROPFIND functionality + * (see RFC 4918, Section 9.1 + */ + +public class RFC4918PropfindTest extends WebDAVTestBase { + + public void testOptions() throws IOException { + HttpOptions options = new HttpOptions(this.root); + HttpResponse response = this.client.execute(options, this.context); + assertTrue(options.getDavComplianceClasses(response).contains("3")); + } + + public void testPropfindInclude() throws IOException, DavException { + + String testuri = this.root + "iftest"; + + int status; + try { + HttpPut put = new HttpPut(testuri); + put.setEntity(new StringEntity("1")); + status = this.client.execute(put, this.context).getStatusLine().getStatusCode(); + assertEquals("status: " + status, 201, status); + + DavPropertyNameSet names = new DavPropertyNameSet(); + names.add(DeltaVConstants.COMMENT); + HttpPropfind propfind = new HttpPropfind(testuri, DavConstants.PROPFIND_ALL_PROP_INCLUDE, names, 0); + HttpResponse resp = this.client.execute(propfind, this.context); + status = resp.getStatusLine().getStatusCode(); + assertEquals(207, status); + + MultiStatus multistatus = propfind.getResponseBodyAsMultiStatus(resp); + MultiStatusResponse[] responses = multistatus.getResponses(); + assertEquals(1, responses.length); + + MultiStatusResponse response = responses[0]; + DavPropertySet found = response.getProperties(200); + DavPropertySet notfound = response.getProperties(404); + + assertTrue(found.contains(DeltaVConstants.COMMENT) || notfound.contains(DeltaVConstants.COMMENT)); + } finally { + delete(testuri); + } + } +} Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/server/RFC4918PropfindTest.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/server/RemotingTest.java =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/server/RemotingTest.java (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/server/RemotingTest.java (working copy) @@ -0,0 +1,60 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.jackrabbit.webdav.server; + +import java.io.IOException; + +import org.apache.http.HttpResponse; +import org.apache.jackrabbit.webdav.DavConstants; +import org.apache.jackrabbit.webdav.DavException; +import org.apache.jackrabbit.webdav.MultiStatus; +import org.apache.jackrabbit.webdav.MultiStatusResponse; +import org.apache.jackrabbit.webdav.client.methods.HttpPropfind; +import org.apache.jackrabbit.webdav.observation.ObservationConstants; +import org.apache.jackrabbit.webdav.property.DavProperty; +import org.apache.jackrabbit.webdav.property.DavPropertyName; +import org.apache.jackrabbit.webdav.property.DavPropertyNameSet; +import org.apache.jackrabbit.webdav.property.DavPropertySet; +import org.apache.jackrabbit.webdav.xml.DomUtil; +import org.w3c.dom.Element; + +public class RemotingTest extends WebDAVTestBase { + + // simple test the verifies that we are indeed talking to the remoting + // servlet + public void testRoot() throws IOException, DavException { + String testuri = this.remotingUri.toASCIIString() + "default/jcr:root"; + DavPropertyName pntn = DavPropertyName.create("primarynodetype", ObservationConstants.NAMESPACE); + DavPropertyNameSet names = new DavPropertyNameSet(); + names.add(pntn); + + HttpPropfind propfind = new HttpPropfind(testuri, DavConstants.PROPFIND_BY_PROPERTY, names, 0); + HttpResponse resp = this.client.execute(propfind, this.context); + int status = resp.getStatusLine().getStatusCode(); + assertEquals(207, status); + + MultiStatus multistatus = propfind.getResponseBodyAsMultiStatus(resp); + MultiStatusResponse[] responses = multistatus.getResponses(); + assertEquals(1, responses.length); + + MultiStatusResponse response = responses[0]; + DavPropertySet found = response.getProperties(200); + DavProperty pnt = found.get(pntn); + Element el = (Element) pnt.getValue(); + assertEquals("rep:root", DomUtil.getText((Element) (el.getFirstChild()))); + } +} Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/server/RemotingTest.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/server/WebDAVTestBase.java =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/server/WebDAVTestBase.java (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/server/WebDAVTestBase.java (working copy) @@ -0,0 +1,238 @@ +/* + * 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.webdav.server; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.URI; + +import javax.jcr.Repository; +import javax.servlet.ServletException; + +import org.apache.commons.io.IOUtils; +import org.apache.http.HttpHost; +import org.apache.http.auth.AuthScope; +import org.apache.http.auth.UsernamePasswordCredentials; +import org.apache.http.client.AuthCache; +import org.apache.http.client.CredentialsProvider; +import org.apache.http.client.HttpClient; +import org.apache.http.client.methods.HttpDelete; +import org.apache.http.client.protocol.HttpClientContext; +import org.apache.http.impl.auth.BasicScheme; +import org.apache.http.impl.client.BasicAuthCache; +import org.apache.http.impl.client.BasicCredentialsProvider; +import org.apache.http.impl.client.HttpClients; +import org.apache.http.impl.conn.PoolingHttpClientConnectionManager; +import org.apache.jackrabbit.core.RepositoryContext; +import org.apache.jackrabbit.core.config.RepositoryConfig; +import org.apache.jackrabbit.server.remoting.davex.JcrRemotingServlet; +import org.apache.jackrabbit.test.AbstractJCRTest; +import org.apache.jackrabbit.test.RepositoryStubException; +import org.apache.jackrabbit.webdav.simple.SimpleWebdavServlet; +import org.eclipse.jetty.http.HttpVersion; +import org.eclipse.jetty.server.HttpConfiguration; +import org.eclipse.jetty.server.HttpConnectionFactory; +import org.eclipse.jetty.server.Server; +import org.eclipse.jetty.server.ServerConnector; +import org.eclipse.jetty.server.SslConnectionFactory; +import org.eclipse.jetty.servlet.ServletContextHandler; +import org.eclipse.jetty.servlet.ServletHolder; +import org.eclipse.jetty.util.resource.Resource; +import org.eclipse.jetty.util.ssl.SslContextFactory; + +import junit.framework.TestResult; + +/** + * Base class for WebDAV tests. + */ +public class WebDAVTestBase extends AbstractJCRTest { + + private static final String SIMPLE_WEBDAV_SERVLET_PATH_MAPPING = "/*"; + private static final String REMOTING_PREFIX = "/remoting"; + private static final String REMOTING_WEBDAV_SERVLET_PATH_MAPPING = REMOTING_PREFIX + "/*"; + + private static ServerConnector httpConnector; + private static ServerConnector httpsConnector; + private static Server server; + private static RepositoryContext repoContext; + + public URI uri; + public URI httpsUri; + public String root; + + // URI for remoting servlet, does not include workspace name + public URI remotingUri; + + public HttpClient client; + public HttpClientContext context; + + private static final String KEYSTORE = "keystore"; + private static final String KEYSTOREPW = "geheimer"; + + protected void setUp() throws Exception { + super.setUp(); + + File home = new File("target/jackrabbit-repository"); + if (!home.exists()) { + home.mkdirs(); + } + + File config = new File(home, "repository.xml"); + if (!config.exists()) { + createDefaultConfiguration(config); + } + + File keystore = new File(home, KEYSTORE); + if (!keystore.exists()) { + createKeystore(keystore); + } + + if (repoContext == null) { + repoContext = RepositoryContext.create(RepositoryConfig.create(config.toURI(), home.getPath())); + } + + if (server == null) { + server = new Server(); + + ServletHolder simple = new ServletHolder(new SimpleWebdavServlet() { + private static final long serialVersionUID = 8638589328461138178L; + + public Repository getRepository() { + return repoContext.getRepository(); + } + }); + simple.setInitParameter(SimpleWebdavServlet.INIT_PARAM_RESOURCE_CONFIG, "/config.xml"); + + ServletHolder remoting = new ServletHolder(new JcrRemotingServlet() { + private static final long serialVersionUID = -2969534124090379387L; + + public Repository getRepository() { + return repoContext.getRepository(); + } + }); + remoting.setInitParameter(JcrRemotingServlet.INIT_PARAM_RESOURCE_PATH_PREFIX, "/remoting"); + + ServletContextHandler schandler = new ServletContextHandler(server, "/"); + schandler.addServlet(simple, SIMPLE_WEBDAV_SERVLET_PATH_MAPPING); + schandler.addServlet(remoting, REMOTING_WEBDAV_SERVLET_PATH_MAPPING); + schandler.setBaseResource(Resource.newClassPathResource("/")); + + server.setHandler(schandler); + } + + if (httpConnector == null) { + httpConnector = new ServerConnector(server); + httpConnector.setHost("localhost"); + httpConnector.setPort(0); + server.addConnector(httpConnector); + } + + if (httpsConnector == null) { + SslContextFactory sslContextFactory = new SslContextFactory(); + sslContextFactory.setKeyStorePath(keystore.getPath()); + sslContextFactory.setKeyStorePassword(KEYSTOREPW); + sslContextFactory.setKeyManagerPassword(KEYSTOREPW); + sslContextFactory.setTrustStorePath(keystore.getPath()); + sslContextFactory.setTrustStorePassword(KEYSTOREPW); + SslConnectionFactory cfac = new SslConnectionFactory(sslContextFactory, HttpVersion.HTTP_1_1.asString()); + httpsConnector = new ServerConnector(server, cfac, new HttpConnectionFactory(new HttpConfiguration())); + httpsConnector.setHost("localhost"); + httpsConnector.setPort(0); + server.addConnector(httpsConnector); + } + + if (!server.isStarted()) { + try { + server.start(); + } catch (Exception e) { + throw new RepositoryStubException(e); + } + } + + this.uri = new URI("http", null, "localhost", httpConnector.getLocalPort(), "/default/", null, null); + this.remotingUri = new URI("http", null, "localhost", httpConnector.getLocalPort(), REMOTING_PREFIX + "/", null, null); + this.httpsUri = new URI("https", null, "localhost", httpsConnector.getLocalPort(), "/default/", null, null); + this.root = this.uri.toASCIIString(); + + PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager(); + //cm.setMaxTotal(100); + HttpHost targetHost = new HttpHost(uri.getHost(), uri.getPort()); + + CredentialsProvider credsProvider = new BasicCredentialsProvider(); + credsProvider.setCredentials( + new AuthScope(targetHost.getHostName(), targetHost.getPort()), + new UsernamePasswordCredentials("admin", "admin")); + + AuthCache authCache = new BasicAuthCache(); + // Generate BASIC scheme object and add it to the local auth cache + BasicScheme basicAuth = new BasicScheme(); + authCache.put(targetHost, basicAuth); + + // Add AuthCache to the execution context + this.context = HttpClientContext.create(); + this.context.setCredentialsProvider(credsProvider); + this.context.setAuthCache(authCache); + + this.client = HttpClients.custom().setConnectionManager(cm).build(); + + super.setUp(); + } + + protected void delete(String uri) throws IOException { + HttpDelete delete = new HttpDelete(uri); + int status = this.client.execute(delete, this.context).getStatusLine().getStatusCode(); + assertTrue("status: " + status, status == 200 || status == 204); + } + + public static Server getServer() { + return server; + } + + /** + * 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); + InputStream input = WebDAVTestBase.class.getResourceAsStream("/repository.xml")) { + IOUtils.copy(input, output); + } catch (IOException e) { + throw new ServletException("Failed to copy default configuration: " + config, e); + } + } + + private void createKeystore(File keystore) throws ServletException { + try (OutputStream output = new FileOutputStream(keystore); + InputStream input = WebDAVTestBase.class.getResourceAsStream("/" + KEYSTORE)) { + IOUtils.copy(input, output); + } catch (IOException e) { + throw new ServletException("Failed to copy keystore: " + keystore, e); + } + } + + @Override + public void run(TestResult testResult) { + if (Boolean.getBoolean("jackrabbit.test.integration")) { + super.run(testResult); + } + } +} Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/server/WebDAVTestBase.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/simple/LitmusTest.java =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/simple/LitmusTest.java (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/simple/LitmusTest.java (working copy) @@ -0,0 +1,130 @@ +/* + * 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.webdav.simple; + +import java.io.ByteArrayOutputStream; +import java.io.File; + +import javax.jcr.Repository; +import javax.jcr.Session; + +import junit.framework.TestCase; + +import org.apache.commons.io.IOUtils; +import org.apache.jackrabbit.commons.JcrUtils; +import org.apache.jackrabbit.util.Text; +import org.eclipse.jetty.server.Server; +import org.eclipse.jetty.server.ServerConnector; +import org.eclipse.jetty.servlet.ServletContextHandler; +import org.eclipse.jetty.servlet.ServletHolder; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class LitmusTest extends TestCase { + + /** + * Logger instance. + */ + private static final Logger log = LoggerFactory.getLogger(LitmusTest.class); + + public void testLitmus() throws Exception { + File dir = new File("target", "litmus"); + String litmus = System.getProperty("litmus", "litmus"); + + if (Boolean.getBoolean("jackrabbit.test.integration") + && isLitmusAvailable(litmus)) { + final Repository repository = JcrUtils.getRepository( + "jcr-jackrabbit://" + Text.escapePath(dir.getCanonicalPath())); + Session session = repository.login(); // for the TransientRepository + try { + Server server = new Server(); + + ServerConnector connector = new ServerConnector(server); + connector.setHost("localhost"); + connector.setPort(Integer.getInteger("litmus.port", 0)); + + server.addConnector(connector); + + ServletHolder holder = new ServletHolder( + new SimpleWebdavServlet() { + @Override + public Repository getRepository() { + return repository; + } + }); + holder.setInitParameter("resource-config", "/config.xml"); + + ServletContextHandler schandler = new ServletContextHandler(server, "/"); + schandler.addServlet(holder, "/*"); + + server.start(); + try { + int port = connector.getLocalPort(); + String url = "http://localhost:" + port + "/default"; + + ProcessBuilder builder = + new ProcessBuilder(litmus, url, "admin", "admin"); + builder.directory(dir); + builder.redirectErrorStream(); + + assertLitmus(builder, "basic", 0); + + assertLitmus(builder, "http", 0); + + assertLitmus(builder, "props", 0); + + // FIXME: JCR-2637: WebDAV shallow copy test failure + assertLitmus(builder, "copymove", 1); + + // FIXME: JCR-2638: Litmus locks test failures + assertLitmus(builder, "locks", 1); + } finally { + server.stop(); + } + } finally { + session.logout(); + } + } + } + + private void assertLitmus( + ProcessBuilder builder, String tests, int exit) throws Exception { + builder.environment().put("TESTS", tests); + Process process = builder.start(); + IOUtils.copy(process.getInputStream(), System.out); + assertEquals(exit, process.waitFor()); + } + + private static boolean isLitmusAvailable(String litmus) { + try { + ProcessBuilder builder = new ProcessBuilder(litmus, "--version"); + builder.redirectErrorStream(); + Process process = builder.start(); + + ByteArrayOutputStream buffer = new ByteArrayOutputStream(); + IOUtils.copy(process.getInputStream(), buffer); + int rv = process.waitFor(); + log.info("litmus version: {}", buffer.toString("US-ASCII").trim()); + + return rv == 0; + } catch (Exception e) { + log.warn("litmus is not available: " + litmus, e); + return false; + } + } + +} Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/simple/LitmusTest.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/simple/LocatorFactoryImplExTest.java =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/simple/LocatorFactoryImplExTest.java (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/simple/LocatorFactoryImplExTest.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.webdav.simple; + +import junit.framework.TestCase; +import org.apache.jackrabbit.webdav.DavLocatorFactory; +import org.apache.jackrabbit.webdav.DavResourceLocator; + +/** LocatorFactoryImplExTest... */ +public class LocatorFactoryImplExTest extends TestCase { + + private DavLocatorFactory factory; + + @Override + protected void setUp() throws Exception { + super.setUp(); + // for simplicity (not yet used) ignore the path prefix. + factory = new LocatorFactoryImplEx(null); + } + + /** + * Test for issue https://issues.apache.org/jira/browse/JCR-1679: An top + * level resource (node directly below the root) whose name equals the + * workspace name results in wrong collection behaviour (garbeled locator + * of child resources). + */ + public void testCollectionNameEqualsWorkspaceName() { + String prefix = "http://localhost:8080/jackrabbit/repository"; + String workspacePath = "/default"; + String nodePath = "/default/another"; + + DavResourceLocator locator = factory.createResourceLocator(prefix, workspacePath, nodePath, false); + assertTrue(locator.getHref(true).indexOf("/default/default") > 0); + + DavResourceLocator locator2 = factory.createResourceLocator(locator.getPrefix(), locator.getWorkspacePath(), locator.getResourcePath()); + assertEquals(locator, locator2); + assertEquals(nodePath, locator2.getRepositoryPath()); + } +} Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/simple/LocatorFactoryImplExTest.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/test/java/org/apache/jackrabbit/webdav/simple/ResourceConfigTest.java =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/simple/ResourceConfigTest.java (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/simple/ResourceConfigTest.java (working copy) @@ -0,0 +1,114 @@ +/* + * 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.webdav.simple; + +import junit.framework.TestCase; +import org.apache.jackrabbit.server.io.DefaultHandler; +import org.apache.jackrabbit.server.io.IOHandler; +import org.apache.jackrabbit.server.io.IOManager; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.ByteArrayInputStream; +import java.io.InputStream; + +/** + * ResourceConfigTest... + */ +public class ResourceConfigTest extends TestCase { + + /** + * logger instance + */ + private static final Logger log = LoggerFactory.getLogger(ResourceConfigTest.class); + + public void testIOManagerConfig() throws Exception { + InputStream in = new ByteArrayInputStream(CONFIG_1.getBytes("UTF-8")); + + ResourceConfig config = new ResourceConfig(null); + config.parse(in); + + IOManager ioMgr = config.getIOManager(); + assertNotNull(ioMgr); + assertEquals("org.apache.jackrabbit.server.io.IOManagerImpl", ioMgr.getClass().getName()); + + IOHandler[] handlers = ioMgr.getIOHandlers(); + assertNotNull(handlers); + assertEquals(1, handlers.length); + assertEquals("org.apache.jackrabbit.server.io.DefaultHandler", handlers[0].getName()); + } + + public void testIOManagerConfigWithParam() throws Exception { + InputStream in = new ByteArrayInputStream(CONFIG_2.getBytes("UTF-8")); + + ResourceConfig config = new ResourceConfig(null); + config.parse(in); + + IOManager ioMgr = config.getIOManager(); + assertNotNull(ioMgr); + assertEquals("org.apache.jackrabbit.server.io.IOManagerImpl", ioMgr.getClass().getName()); + + IOHandler[] handlers = ioMgr.getIOHandlers(); + assertNotNull(handlers); + assertEquals(1, handlers.length); + assertEquals("org.apache.jackrabbit.server.io.DefaultHandler", handlers[0].getName()); + DefaultHandler dh = (DefaultHandler) handlers[0]; + assertEquals("nt:unstructured", dh.getCollectionNodeType()); + assertEquals("nt:unstructured", dh.getNodeType()); + assertEquals("nt:resource", dh.getContentNodeType()); + } + + + private static final String CONFIG_1 = "\n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " " + + ""; + + private static final String CONFIG_2 = "\n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " " + + ""; +} \ No newline at end of file Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/simple/ResourceConfigTest.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/test/resources/config.xml =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/resources/config.xml (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/resources/config.xml (working copy) @@ -0,0 +1,184 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + nt:file + nt:resource + + + + + + + + + + + + + rep + jcr + + + + + + Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/resources/config.xml ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/resources/keystore =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/resources/keystore ___________________________________________________________________ Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/resources/logback-test.xml =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/resources/logback-test.xml (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/resources/logback-test.xml (working copy) @@ -0,0 +1,31 @@ + + + + + + target/jcr.log + + %date{HH:mm:ss.SSS} %-5level %-40([%thread] %F:%L) %msg%n + + + + + + + + Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/resources/logback-test.xml ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/resources/protectedHandlers.properties =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/resources/protectedHandlers.properties (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/resources/protectedHandlers.properties (working copy) @@ -0,0 +1,17 @@ +# 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. + +# ProtectedItemRemoveHandler implementation class +javax.jcr.tck.access.control.list.handler=org.apache.jackrabbit.server.remoting.davex.AclRemoveHandler Index: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/resources/protectedHandlersConfig.xml =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/resources/protectedHandlersConfig.xml (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/resources/protectedHandlersConfig.xml (working copy) @@ -0,0 +1,26 @@ + + + + + + + + Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/resources/protectedHandlersConfig.xml ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/resources/repository.xml =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/resources/repository.xml (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/resources/repository.xml (working copy) @@ -0,0 +1,166 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/resources/repository.xml ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/resources/repositoryStubImpl.properties =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/resources/repositoryStubImpl.properties (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/resources/repositoryStubImpl.properties (working copy) @@ -0,0 +1,23 @@ +# 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. + +# Stub implementation class +javax.jcr.tck.repository_stub_impl=org.apache.jackrabbit.core.JackrabbitRepositoryStub + +# the repository home +org.apache.jackrabbit.repository.home=target/repository + +# the repository configuration +org.apache.jackrabbit.repository.config=target/test-classes/repository.xml Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/resources/repositoryStubImpl.properties ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-jcr-server-project/jackrabbit-jcr-server =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server (working copy) Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server ___________________________________________________________________ Added: svn:ignore ## -0,0 +1,5 ## +*.iml +*.ipr +*.iws +target +.* Index: jackrabbit-jcr-server-project/jackrabbit-jcr-server-jakarta/.classpath =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server-jakarta/.classpath (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server-jakarta/.classpath (working copy) @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Index: jackrabbit-jcr-server-project/jackrabbit-jcr-server-jakarta/.project =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server-jakarta/.project (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server-jakarta/.project (working copy) @@ -0,0 +1,23 @@ + + + jackrabbit-jcr-server-jakarta + + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.m2e.core.maven2Builder + + + + + + org.eclipse.jdt.core.javanature + org.eclipse.m2e.core.maven2Nature + + Index: jackrabbit-jcr-server-project/jackrabbit-jcr-server-jakarta/.settings/org.eclipse.core.resources.prefs =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server-jakarta/.settings/org.eclipse.core.resources.prefs (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server-jakarta/.settings/org.eclipse.core.resources.prefs (working copy) @@ -0,0 +1,6 @@ +eclipse.preferences.version=1 +encoding//src/main/java=UTF-8 +encoding//src/main/resources=UTF-8 +encoding//src/test/java=UTF-8 +encoding//src/test/resources=UTF-8 +encoding/=UTF-8 Index: jackrabbit-jcr-server-project/jackrabbit-jcr-server-jakarta/.settings/org.eclipse.jdt.core.prefs =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server-jakarta/.settings/org.eclipse.jdt.core.prefs (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server-jakarta/.settings/org.eclipse.jdt.core.prefs (working copy) @@ -0,0 +1,8 @@ +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 +org.eclipse.jdt.core.compiler.compliance=1.8 +org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled +org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning +org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=ignore +org.eclipse.jdt.core.compiler.release=disabled +org.eclipse.jdt.core.compiler.source=1.8 Index: jackrabbit-jcr-server-project/jackrabbit-jcr-server-jakarta/.settings/org.eclipse.m2e.core.prefs =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server-jakarta/.settings/org.eclipse.m2e.core.prefs (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server-jakarta/.settings/org.eclipse.m2e.core.prefs (working copy) @@ -0,0 +1,4 @@ +activeProfiles= +eclipse.preferences.version=1 +resolveWorkspaceProjects=true +version=1 Index: jackrabbit-jcr-server-project/jackrabbit-jcr-server-jakarta/pom.xml =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server-jakarta/pom.xml (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server-jakarta/pom.xml (working copy) @@ -0,0 +1,88 @@ + + 4.0.0 + + org.apache.jackrabbit + jackrabbit-jcr-server-project + 2.21.16-SNAPSHOT + + jackrabbit-jcr-server-jakarta + + + + org.eclipse.transformer + transformer-maven-plugin + 0.5.0 + true + + + true + + + + + default-jar + + jar + + + + org.apache.jackrabbit + jackrabbit-jcr-server + ${project.version} + + + + + + + + + + apache-release + + + + org.eclipse.transformer + transformer-maven-plugin + 0.5.0 + true + + + true + + + + + source-jar + + jar + + + + org.apache.jackrabbit + jackrabbit-jcr-server + ${project.version} + sources + + + + + + + + + + + + org.apache.jackrabbit + jackrabbit-webdav-jakarta + ${project.version} + + + jakarta.servlet + jakarta.servlet-api + 5.0.0 + provided + + + \ No newline at end of file Index: jackrabbit-jcr-server-project/jackrabbit-jcr-server-jakarta/target/.plxarc =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server-jakarta/target/.plxarc (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server-jakarta/target/.plxarc (working copy) @@ -0,0 +1 @@ +maven-shared-archive-resources \ No newline at end of file Index: jackrabbit-jcr-server-project/jackrabbit-jcr-server-jakarta/target/classes/META-INF/DEPENDENCIES =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server-jakarta/target/classes/META-INF/DEPENDENCIES (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server-jakarta/target/classes/META-INF/DEPENDENCIES (working copy) @@ -0,0 +1,47 @@ +// ------------------------------------------------------------------ +// Transitive dependencies of this project determined from the +// maven pom organized by organization. +// ------------------------------------------------------------------ + +jackrabbit-jcr-server-jakarta + + +From: 'QOS.ch' (http://www.qos.ch) + - JCL 1.2 implemented over SLF4J (http://www.slf4j.org) org.slf4j:jcl-over-slf4j:jar:1.7.36 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - SLF4J API Module (http://www.slf4j.org) org.slf4j:slf4j-api:jar:1.7.36 + License: MIT License (http://www.opensource.org/licenses/mit-license.php) + +From: 'The Apache Software Foundation' (http://www.apache.org) + - Apache Tika core (https://tika.apache.org/) org.apache.tika:tika-core:bundle:2.4.1 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + +From: 'The Apache Software Foundation' (http://www.apache.org/) + - Apache Commons Logging (http://commons.apache.org/proper/commons-logging/) commons-logging:commons-logging:jar:1.2 + License: The Apache Software License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache HttpClient (http://hc.apache.org/httpcomponents-client-ga) org.apache.httpcomponents:httpclient:jar:4.5.14 + License: Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache HttpCore (http://hc.apache.org/httpcomponents-core-ga) org.apache.httpcomponents:httpcore:jar:4.4.16 + License: Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt) + +From: 'The Apache Software Foundation' (https://www.apache.org/) + - Apache Commons Codec (http://commons.apache.org/proper/commons-codec/) commons-codec:commons-codec:jar:1.11 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Commons FileUpload (https://commons.apache.org/proper/commons-fileupload/) commons-fileupload:commons-fileupload:jar:1.5 + License: Apache-2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Commons IO (https://commons.apache.org/proper/commons-io/) commons-io:commons-io:jar:2.11.0 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Commons Collections (https://commons.apache.org/proper/commons-collections/) org.apache.commons:commons-collections4:jar:4.4 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Jackrabbit JCR Commons (http://jackrabbit.apache.org/jackrabbit-jcr-commons/) org.apache.jackrabbit:jackrabbit-jcr-commons:bundle:2.21.16-SNAPSHOT + License: Apache-2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Jackrabbit SPI (http://jackrabbit.apache.org/jackrabbit-spi/) org.apache.jackrabbit:jackrabbit-spi:bundle:2.21.16-SNAPSHOT + License: Apache-2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Jackrabbit SPI Commons (http://jackrabbit.apache.org/jackrabbit-spi-commons/) org.apache.jackrabbit:jackrabbit-spi-commons:bundle:2.21.16-SNAPSHOT + License: Apache-2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - jackrabbit-webdav-jakarta (http://jackrabbit.apache.org/jackrabbit-webdav-project/jackrabbit-webdav-jakarta/) org.apache.jackrabbit:jackrabbit-webdav-jakarta:jar:2.21.16-SNAPSHOT + License: Apache-2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + + + + Index: jackrabbit-jcr-server-project/jackrabbit-jcr-server-jakarta/target/classes/META-INF/LICENSE =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server-jakarta/target/classes/META-INF/LICENSE (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server-jakarta/target/classes/META-INF/LICENSE (working copy) @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed 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. Index: jackrabbit-jcr-server-project/jackrabbit-jcr-server-jakarta/target/classes/META-INF/NOTICE =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server-jakarta/target/classes/META-INF/NOTICE (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server-jakarta/target/classes/META-INF/NOTICE (working copy) @@ -0,0 +1,8 @@ + +jackrabbit-jcr-server-jakarta +Copyright 2004-1970 The Apache Software Foundation + +This product includes software developed at +The Apache Software Foundation (http://www.apache.org/). + + Index: jackrabbit-jcr-server-project/jackrabbit-jcr-server-jakarta/target/classes/META-INF/maven/org.apache.jackrabbit/jackrabbit-jcr-server-jakarta/pom.properties =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server-jakarta/target/classes/META-INF/maven/org.apache.jackrabbit/jackrabbit-jcr-server-jakarta/pom.properties (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server-jakarta/target/classes/META-INF/maven/org.apache.jackrabbit/jackrabbit-jcr-server-jakarta/pom.properties (working copy) @@ -0,0 +1,7 @@ +#Generated by Maven Integration for Eclipse +#Wed Mar 01 12:32:10 CET 2023 +m2e.projectLocation=C\:\\Development\\JackRabbit\\trunk\\jackrabbit-jcr-server-project\\jackrabbit-jcr-server-jakarta +m2e.projectName=jackrabbit-jcr-server-jakarta +groupId=org.apache.jackrabbit +artifactId=jackrabbit-jcr-server-jakarta +version=2.21.16-SNAPSHOT Index: jackrabbit-jcr-server-project/jackrabbit-jcr-server-jakarta/target/classes/META-INF/maven/org.apache.jackrabbit/jackrabbit-jcr-server-jakarta/pom.xml =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server-jakarta/target/classes/META-INF/maven/org.apache.jackrabbit/jackrabbit-jcr-server-jakarta/pom.xml (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server-jakarta/target/classes/META-INF/maven/org.apache.jackrabbit/jackrabbit-jcr-server-jakarta/pom.xml (working copy) @@ -0,0 +1,88 @@ + + 4.0.0 + + org.apache.jackrabbit + jackrabbit-jcr-server-project + 2.21.16-SNAPSHOT + + jackrabbit-jcr-server-jakarta + + + + org.eclipse.transformer + transformer-maven-plugin + 0.5.0 + true + + + true + + + + + default-jar + + jar + + + + org.apache.jackrabbit + jackrabbit-jcr-server + ${project.version} + + + + + + + + + + apache-release + + + + org.eclipse.transformer + transformer-maven-plugin + 0.5.0 + true + + + true + + + + + source-jar + + jar + + + + org.apache.jackrabbit + jackrabbit-jcr-server + ${project.version} + sources + + + + + + + + + + + + org.apache.jackrabbit + jackrabbit-webdav-jakarta + ${project.version} + + + jakarta.servlet + jakarta.servlet-api + 5.0.0 + provided + + + \ No newline at end of file Index: jackrabbit-jcr-server-project/jackrabbit-jcr-server-jakarta/target/jackrabbit-jcr-server-jakarta-2.21.16-SNAPSHOT.jar =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server-jakarta/target/jackrabbit-jcr-server-jakarta-2.21.16-SNAPSHOT.jar ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: jackrabbit-jcr-server-project/jackrabbit-jcr-server-jakarta/target/maven-shared-archive-resources/META-INF/DEPENDENCIES =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server-jakarta/target/maven-shared-archive-resources/META-INF/DEPENDENCIES (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server-jakarta/target/maven-shared-archive-resources/META-INF/DEPENDENCIES (working copy) @@ -0,0 +1,47 @@ +// ------------------------------------------------------------------ +// Transitive dependencies of this project determined from the +// maven pom organized by organization. +// ------------------------------------------------------------------ + +jackrabbit-jcr-server-jakarta + + +From: 'QOS.ch' (http://www.qos.ch) + - JCL 1.2 implemented over SLF4J (http://www.slf4j.org) org.slf4j:jcl-over-slf4j:jar:1.7.36 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - SLF4J API Module (http://www.slf4j.org) org.slf4j:slf4j-api:jar:1.7.36 + License: MIT License (http://www.opensource.org/licenses/mit-license.php) + +From: 'The Apache Software Foundation' (http://www.apache.org) + - Apache Tika core (https://tika.apache.org/) org.apache.tika:tika-core:bundle:2.4.1 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + +From: 'The Apache Software Foundation' (http://www.apache.org/) + - Apache Commons Logging (http://commons.apache.org/proper/commons-logging/) commons-logging:commons-logging:jar:1.2 + License: The Apache Software License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache HttpClient (http://hc.apache.org/httpcomponents-client-ga) org.apache.httpcomponents:httpclient:jar:4.5.14 + License: Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache HttpCore (http://hc.apache.org/httpcomponents-core-ga) org.apache.httpcomponents:httpcore:jar:4.4.16 + License: Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt) + +From: 'The Apache Software Foundation' (https://www.apache.org/) + - Apache Commons Codec (http://commons.apache.org/proper/commons-codec/) commons-codec:commons-codec:jar:1.11 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Commons FileUpload (https://commons.apache.org/proper/commons-fileupload/) commons-fileupload:commons-fileupload:jar:1.5 + License: Apache-2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Commons IO (https://commons.apache.org/proper/commons-io/) commons-io:commons-io:jar:2.11.0 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Commons Collections (https://commons.apache.org/proper/commons-collections/) org.apache.commons:commons-collections4:jar:4.4 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Jackrabbit JCR Commons (http://jackrabbit.apache.org/jackrabbit-jcr-commons/) org.apache.jackrabbit:jackrabbit-jcr-commons:bundle:2.21.16-SNAPSHOT + License: Apache-2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Jackrabbit SPI (http://jackrabbit.apache.org/jackrabbit-spi/) org.apache.jackrabbit:jackrabbit-spi:bundle:2.21.16-SNAPSHOT + License: Apache-2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Jackrabbit SPI Commons (http://jackrabbit.apache.org/jackrabbit-spi-commons/) org.apache.jackrabbit:jackrabbit-spi-commons:bundle:2.21.16-SNAPSHOT + License: Apache-2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - jackrabbit-webdav-jakarta (http://jackrabbit.apache.org/jackrabbit-webdav-project/jackrabbit-webdav-jakarta/) org.apache.jackrabbit:jackrabbit-webdav-jakarta:jar:2.21.16-SNAPSHOT + License: Apache-2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + + + + Index: jackrabbit-jcr-server-project/jackrabbit-jcr-server-jakarta/target/maven-shared-archive-resources/META-INF/LICENSE =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server-jakarta/target/maven-shared-archive-resources/META-INF/LICENSE (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server-jakarta/target/maven-shared-archive-resources/META-INF/LICENSE (working copy) @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed 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. Index: jackrabbit-jcr-server-project/jackrabbit-jcr-server-jakarta/target/maven-shared-archive-resources/META-INF/NOTICE =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server-jakarta/target/maven-shared-archive-resources/META-INF/NOTICE (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server-jakarta/target/maven-shared-archive-resources/META-INF/NOTICE (working copy) @@ -0,0 +1,8 @@ + +jackrabbit-jcr-server-jakarta +Copyright 2004-1970 The Apache Software Foundation + +This product includes software developed at +The Apache Software Foundation (http://www.apache.org/). + + Index: jackrabbit-jcr-server-project/jackrabbit-jcr-server-jakarta/target/maven-status/maven-compiler-plugin/compile/default-compile/createdFiles.lst =================================================================== Index: jackrabbit-jcr-server-project/jackrabbit-jcr-server-jakarta/target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst =================================================================== Index: jackrabbit-jcr-server-project/jackrabbit-jcr-server-jakarta/target/maven-status/maven-compiler-plugin/testCompile/default-testCompile/createdFiles.lst =================================================================== Index: jackrabbit-jcr-server-project/jackrabbit-jcr-server-jakarta/target/maven-status/maven-compiler-plugin/testCompile/default-testCompile/inputFiles.lst =================================================================== Index: jackrabbit-jcr-server-project/jackrabbit-jcr-server-jakarta/target/test-classes/META-INF/DEPENDENCIES =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server-jakarta/target/test-classes/META-INF/DEPENDENCIES (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server-jakarta/target/test-classes/META-INF/DEPENDENCIES (working copy) @@ -0,0 +1,47 @@ +// ------------------------------------------------------------------ +// Transitive dependencies of this project determined from the +// maven pom organized by organization. +// ------------------------------------------------------------------ + +jackrabbit-jcr-server-jakarta + + +From: 'QOS.ch' (http://www.qos.ch) + - JCL 1.2 implemented over SLF4J (http://www.slf4j.org) org.slf4j:jcl-over-slf4j:jar:1.7.36 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - SLF4J API Module (http://www.slf4j.org) org.slf4j:slf4j-api:jar:1.7.36 + License: MIT License (http://www.opensource.org/licenses/mit-license.php) + +From: 'The Apache Software Foundation' (http://www.apache.org) + - Apache Tika core (https://tika.apache.org/) org.apache.tika:tika-core:bundle:2.4.1 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + +From: 'The Apache Software Foundation' (http://www.apache.org/) + - Apache Commons Logging (http://commons.apache.org/proper/commons-logging/) commons-logging:commons-logging:jar:1.2 + License: The Apache Software License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache HttpClient (http://hc.apache.org/httpcomponents-client-ga) org.apache.httpcomponents:httpclient:jar:4.5.14 + License: Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache HttpCore (http://hc.apache.org/httpcomponents-core-ga) org.apache.httpcomponents:httpcore:jar:4.4.16 + License: Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt) + +From: 'The Apache Software Foundation' (https://www.apache.org/) + - Apache Commons Codec (http://commons.apache.org/proper/commons-codec/) commons-codec:commons-codec:jar:1.11 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Commons FileUpload (https://commons.apache.org/proper/commons-fileupload/) commons-fileupload:commons-fileupload:jar:1.5 + License: Apache-2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Commons IO (https://commons.apache.org/proper/commons-io/) commons-io:commons-io:jar:2.11.0 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Commons Collections (https://commons.apache.org/proper/commons-collections/) org.apache.commons:commons-collections4:jar:4.4 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Jackrabbit JCR Commons (http://jackrabbit.apache.org/jackrabbit-jcr-commons/) org.apache.jackrabbit:jackrabbit-jcr-commons:bundle:2.21.16-SNAPSHOT + License: Apache-2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Jackrabbit SPI (http://jackrabbit.apache.org/jackrabbit-spi/) org.apache.jackrabbit:jackrabbit-spi:bundle:2.21.16-SNAPSHOT + License: Apache-2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Jackrabbit SPI Commons (http://jackrabbit.apache.org/jackrabbit-spi-commons/) org.apache.jackrabbit:jackrabbit-spi-commons:bundle:2.21.16-SNAPSHOT + License: Apache-2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - jackrabbit-webdav-jakarta (http://jackrabbit.apache.org/jackrabbit-webdav-project/jackrabbit-webdav-jakarta/) org.apache.jackrabbit:jackrabbit-webdav-jakarta:jar:2.21.16-SNAPSHOT + License: Apache-2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + + + + Index: jackrabbit-jcr-server-project/jackrabbit-jcr-server-jakarta/target/test-classes/META-INF/LICENSE =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server-jakarta/target/test-classes/META-INF/LICENSE (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server-jakarta/target/test-classes/META-INF/LICENSE (working copy) @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed 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. Index: jackrabbit-jcr-server-project/jackrabbit-jcr-server-jakarta/target/test-classes/META-INF/NOTICE =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server-jakarta/target/test-classes/META-INF/NOTICE (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server-jakarta/target/test-classes/META-INF/NOTICE (working copy) @@ -0,0 +1,8 @@ + +jackrabbit-jcr-server-jakarta +Copyright 2004-1970 The Apache Software Foundation + +This product includes software developed at +The Apache Software Foundation (http://www.apache.org/). + + Index: jackrabbit-jcr-server-project/pom.xml =================================================================== --- jackrabbit-jcr-server-project/pom.xml (nonexistent) +++ jackrabbit-jcr-server-project/pom.xml (working copy) @@ -0,0 +1,110 @@ + + 4.0.0 + + org.apache.jackrabbit + jackrabbit-parent + 2.21.16-SNAPSHOT + ../jackrabbit-parent/pom.xml + + jackrabbit-jcr-server-project + pom + + jackrabbit-jcr-server + jackrabbit-jcr-server-jakarta + + + + javax.jcr + jcr + + + org.apache.jackrabbit + jackrabbit-spi-commons + ${project.version} + + + org.apache.jackrabbit + jackrabbit-jcr-commons + ${project.version} + + + org.apache.tika + tika-core + + + org.slf4j + slf4j-api + + + commons-fileupload + commons-fileupload + + + + + org.osgi + org.osgi.compendium + 5.0.0 + provided + + + org.apache.felix + org.apache.felix.scr.annotations + 1.12.0 + provided + + + org.osgi + org.osgi.annotation + provided + + + + junit + junit + test + + + org.easymock + easymock + test + + + org.apache.jackrabbit + jackrabbit-core + ${project.version} + test + + + org.apache.jackrabbit + jackrabbit-jcr-tests + ${project.version} + test + + + org.eclipse.jetty + jetty-server + test + + + org.eclipse.jetty + jetty-servlet + test + + + ch.qos.logback + logback-classic + test + + + org.mockito + mockito-core + test + + + org.apache.derby + derby + test + + + \ No newline at end of file Index: jackrabbit-webapp/README.txt =================================================================== --- jackrabbit-webapp/README.txt (revision 1907912) +++ jackrabbit-webapp/README.txt (nonexistent) @@ -1,22 +0,0 @@ -===================================== -Welcome to Jackrabbit Web Application -===================================== - -This is the Web Application component of the Apache Jackrabbit project. -This component provides servlets used to access a Jackrabbit repository: - - * RepositoryAccessServlet.java - * LoggingServlet.java - * RepositoryStartupServlet.java - -In addition, the project contains 2 different WebDAV servlets: - - * SimpleWebdavServlet.java - Adds WebDAV support (DAV 1,2) to your jackrabbit repository. - - * JCRWebdavServerServlet.java - A servlet used to remote JSR170 calls via WebDAV. - IMPORTANT: Please note, that this servlet is not intended to provide - common WebDAV support to the repository. Instead the primary goal is to - remote JSR170 calls. - For the corresponding client see -> jackrabbit-jcr2dav (work in progress). Property changes on: jackrabbit-webapp/README.txt ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Deleted: svn:keywords ## -1 +0,0 ## -author date id revision \ No newline at end of property Index: jackrabbit-webapp/pom.xml =================================================================== --- jackrabbit-webapp/pom.xml (revision 1907912) +++ jackrabbit-webapp/pom.xml (nonexistent) @@ -1,211 +0,0 @@ - - - - - - 4.0.0 - - - - - - org.apache.jackrabbit - jackrabbit-parent - 2.21.16-SNAPSHOT - ../jackrabbit-parent/pom.xml - - jackrabbit-webapp - war - Jackrabbit Web Application - Web application that hosts and serves a Jackrabbit content repository - - - 8.5.85 - - - - - javax.jcr - jcr - compile - - - org.apache.jackrabbit - jackrabbit-core - ${project.version} - - - org.apache.tika - tika-parsers-standard-package - - - org.slf4j - jcl-over-slf4j - - - org.apache.jackrabbit - jackrabbit-jcr-server - ${project.version} - - - org.apache.jackrabbit - jackrabbit-jcr-servlet - ${project.version} - - - org.apache.jackrabbit - jackrabbit-jcr-rmi - ${project.version} - - - ch.qos.logback - logback-classic - - - commons-beanutils - commons-beanutils - - - org.apache.tomcat - tomcat-servlet-api - ${tomcat.version} - provided - - - - junit - junit - test - - - org.apache.tomcat - tomcat-catalina - ${tomcat.version} - test - - - org.apache.tomcat - tomcat-coyote - ${tomcat.version} - test - - - org.apache.tomcat - tomcat-jasper - ${tomcat.version} - test - - - net.sourceforge.htmlunit - htmlunit - 2.70.0 - test - - - commons-logging - commons-logging - - - - - org.slf4j - jul-to-slf4j - ${slf4j.version} - test - - - com.google.guava - guava - 31.1-jre - test - - - org.apache.derby - derby - - - - - - - - maven-antrun-plugin - - - package - - - - - - - run - - - - - - - org.codehaus.mojo - build-helper-maven-plugin - - - attach-artifacts - package - - attach-artifact - - - - - ${project.build.directory}/jackrabbit-webapp-${project.version}.jar - jar - - - - - - - - org.apache.rat - apache-rat-plugin - - - src/main/webapp/WEB-INF/log4j.dtd - - - - - - - - maven-failsafe-plugin - - - - derby.stream.error.file - target/derby.log - - - - - - - - - Property changes on: jackrabbit-webapp/pom.xml ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-webapp/src/main/java/org/apache/jackrabbit/j2ee/AbstractConfig.java =================================================================== --- jackrabbit-webapp/src/main/java/org/apache/jackrabbit/j2ee/AbstractConfig.java (revision 1907912) +++ jackrabbit-webapp/src/main/java/org/apache/jackrabbit/j2ee/AbstractConfig.java (nonexistent) @@ -1,110 +0,0 @@ -/* - * 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.j2ee; - -import org.apache.commons.beanutils.BeanMap; -import org.apache.jackrabbit.util.Text; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.Enumeration; -import java.util.Iterator; -import java.util.Properties; - -import javax.servlet.ServletConfig; -import javax.servlet.ServletException; - -/** - * Abstract configuration class that is based on a bean map. - */ -public abstract class AbstractConfig { - - /** - * default logger - */ - private static final Logger log = LoggerFactory.getLogger(AbstractConfig.class); - - protected boolean valid; - - private BeanMap map = new BeanMap(this); - - /** - * Initializes the configuration with values from the given properties - * @param props the configuration properties - */ - public void init(Properties props) throws ServletException { - Iterator iter = props.keySet().iterator(); - while (iter.hasNext()) { - String name = (String) iter.next(); - String mapName = toMapName(name, '.'); - try { - if (map.containsKey(mapName)) { - map.put(mapName, props.getProperty(name)); - } - } catch (Exception e) { - throw new ServletExceptionWithCause( - "Invalid configuration property: " + name, e); - } - } - } - - public void init(ServletConfig ctx) throws ServletException { - Enumeration names = ctx.getInitParameterNames(); - while (names.hasMoreElements()) { - String name = (String) names.nextElement(); - String mapName = toMapName(name, '-'); - try { - if (map.containsKey(mapName)) { - map.put(mapName, ctx.getInitParameter(name)); - } - } catch (Exception e) { - throw new ServletExceptionWithCause( - "Invalid servlet configuration option: " + name, e); - } - } - } - - public String toMapName(String name, char delim) { - StringBuffer ret = new StringBuffer(); - String[] elems = Text.explode(name, delim); - ret.append(elems[0]); - for (int i=1; i - * +-------------------+-------------------+ - * | Property Name | Init-Param Name | - * +-------------------+-------------------+ - * | repository.home | repository-home | - * | repository.config | repository-config | - * | repository.name | repository-name | - * +-------------------+-------------------+ - * - */ -public class BootstrapConfig extends AbstractConfig { - - private String repositoryHome; - - private String repositoryConfig; - - private String repositoryName; - - private JNDIConfig jndiConfig = new JNDIConfig(this); - - private RMIConfig rmiConfig = new RMIConfig(this); - - public void init(Properties props) throws ServletException { - super.init(props); - jndiConfig.init(props); - rmiConfig.init(props); - } - - public void init(ServletConfig ctx) throws ServletException { - super.init(ctx); - jndiConfig.init(ctx); - rmiConfig.init(ctx); - } - - public String getRepositoryHome() { - return repositoryHome; - } - - public void setRepositoryHome(String repositoryHome) { - this.repositoryHome = repositoryHome; - } - - public String getRepositoryConfig() { - return repositoryConfig; - } - - public void setRepositoryConfig(String repositoryConfig) { - this.repositoryConfig = repositoryConfig; - } - - public String getRepositoryName() { - return repositoryName; - } - - public void setRepositoryName(String repositoryName) { - this.repositoryName = repositoryName; - } - - public JNDIConfig getJndiConfig() { - return jndiConfig; - } - - public RMIConfig getRmiConfig() { - return rmiConfig; - } - - public void validate() { - valid = repositoryName != null; - jndiConfig.validate(); - rmiConfig.validate(); - } - - - public void logInfos() { - super.logInfos(); - if (jndiConfig.isValid()) { - jndiConfig.logInfos(); - } - if (rmiConfig.isValid()) { - rmiConfig.logInfos(); - } - } -} \ No newline at end of file Property changes on: jackrabbit-webapp/src/main/java/org/apache/jackrabbit/j2ee/BootstrapConfig.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-webapp/src/main/java/org/apache/jackrabbit/j2ee/DerbyShutdown.java =================================================================== --- jackrabbit-webapp/src/main/java/org/apache/jackrabbit/j2ee/DerbyShutdown.java (revision 1907912) +++ jackrabbit-webapp/src/main/java/org/apache/jackrabbit/j2ee/DerbyShutdown.java (nonexistent) @@ -1,76 +0,0 @@ -/* - * 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.j2ee; - -import java.lang.reflect.Method; -import java.sql.Driver; -import java.sql.DriverManager; -import java.sql.SQLException; -import java.util.Enumeration; - -import javax.servlet.ServletContextEvent; -import javax.servlet.ServletContextListener; - -/** - * Servlet context listener that releases all remaining Derby resources - * when the web application is undeployed. The resources are released only - * if the Derby classes were loaded from within this webapp. - * - * @see JCR-1301 - */ -public class DerbyShutdown implements ServletContextListener { - - public void contextInitialized(ServletContextEvent event) { - } - - public void contextDestroyed(ServletContextEvent event) { - ClassLoader loader = DerbyShutdown.class.getClassLoader(); - - // Deregister all JDBC drivers loaded from this webapp - Enumeration drivers = DriverManager.getDrivers(); - while (drivers.hasMoreElements()) { - Driver driver = drivers.nextElement(); - // Check if this driver comes from this webapp - if (driver.getClass().getClassLoader() == loader) { - try { - DriverManager.deregisterDriver(driver); - } catch (SQLException ignore) { - } - } - } - - // Explicitly tell Derby to release all remaining resources. - // Use reflection to avoid problems when the Derby is not used. - try { - Class monitorClass = - loader.loadClass("org.apache.derby.iapi.services.monitor.Monitor"); - if (monitorClass.getClassLoader() == loader) { - Method getMonitorMethod = - monitorClass.getMethod("getMonitor", new Class[0]); - Object monitor = - getMonitorMethod.invoke(null, new Object[0]); - if (monitor != null) { - Method shutdownMethod = - monitor.getClass().getMethod("shutdown", new Class[0]); - shutdownMethod.invoke(monitor, new Object[0]); - } - } - } catch (Exception ignore) { - } - } - -} \ No newline at end of file Property changes on: jackrabbit-webapp/src/main/java/org/apache/jackrabbit/j2ee/DerbyShutdown.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-webapp/src/main/java/org/apache/jackrabbit/j2ee/Installer.java =================================================================== --- jackrabbit-webapp/src/main/java/org/apache/jackrabbit/j2ee/Installer.java (revision 1907912) +++ jackrabbit-webapp/src/main/java/org/apache/jackrabbit/j2ee/Installer.java (nonexistent) @@ -1,234 +0,0 @@ -/* - * 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.j2ee; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.util.Properties; - -import javax.servlet.ServletContext; -import javax.servlet.ServletException; -import javax.servlet.http.HttpServletRequest; - -/** - * Provides very basic installation capabilities. - */ -public class Installer { - - /** - * the default logger - */ - private static final Logger log = LoggerFactory.getLogger(Installer.class); - - /** - * Return code for installation succeeded - */ - public static final int C_INSTALL_OK = 0; - - /** - * Return code for invalid input parameter - */ - public static final int C_INVALID_INPUT = 1; - - /** - * Return code for repository home already exists - */ - public static final int C_HOME_EXISTS = 2; - - /** - * Return code for repository home is missing - */ - public static final int C_HOME_MISSING = 3; - - /** - * Return code for repository config already exists - */ - public static final int C_CONFIG_EXISTS = 4; - - /** - * Return code for repository config is missing - */ - public static final int C_CONFIG_MISSING = 5; - - /** - * Return code for bootstrap config already exists - */ - public static final int C_BOOTSTRAP_EXISTS = 6; - - /** - * Return code for a general install error - */ - public static final int C_INSTALL_ERROR = 7; - - /** - * place to store the config file - */ - private final File bootstrapConfigFile; - - /** - * the servlet context - */ - private final ServletContext context; - - /** - * the place for the repository config template - * todo: to be configured - */ - private final String configTemplate = - "/org/apache/jackrabbit/core/repository.xml"; - - /** - * the place for the bootstrap properties template - * todo: to be configured - */ - private final String bootstrapTemplate = "/WEB-INF/templates/bootstrap.properties"; - - /** - * Creates a new installer - * @param bootstrapConfigFile the location for the config file - * @param context the servlet context for accessing resources - */ - public Installer(File bootstrapConfigFile, ServletContext context) { - this.bootstrapConfigFile = bootstrapConfigFile; - this.context = context; - } - - /** - * Handles the installation. - * - * @param req the servlet request with the input parameters - * @return the installation return code - * - * @throws ServletException if a servlet error occurs. - * @throws IOException if an I/O error occurs. - */ - public int installRepository(HttpServletRequest req) - throws ServletException, IOException { - String repHome = req.getParameter("repository_home"); - String repXml = req.getParameter("repository_xml"); - String mode = req.getParameter("mode"); - - if (repHome == null || mode == null) { - return C_INVALID_INPUT; - } - File home = new File(repHome); - - File config; - if (repXml == null || repXml.length() == 0) { - config = new File(home, "repository.xml"); - repXml = config.getPath(); - } else { - config = new File(repXml); - } - - if ("new".equals(mode)) { - // Test internal folder repository existence and not home because home is already created - // by org.apache.jackrabbit.server.remoting.davex.JcrRemotingServlet - if (new File(home, "repository").exists()) { - log.error("Trying to install new repository home '{}' but it already contain a repository", repHome); - return C_HOME_EXISTS; - } - if (config != null && config.exists()) { - log.error("Trying to install new repository config '{}' but already exists", repXml); - return C_CONFIG_EXISTS; - } - log.info("Creating new repository home '{}'", repHome); - home.mkdirs(); - - if (config != null) { - // install repository xml for Jackrabbit Classic - try { - installRepositoryConfig(config); - } catch (IOException e) { - log.error("Error while installing new repository config '{}': {}", repXml, e.toString()); - return C_BOOTSTRAP_EXISTS; - } - } - } else { - if (!home.exists()) { - log.error("Trying to use existing repository home '{}' but does not exists", repHome); - return C_HOME_MISSING; - } - if (config != null && !config.exists()) { - log.error("Trying to use existing repository config '{}' but does not exists", repXml); - return C_CONFIG_MISSING; - } - } - // install bootstrap.properties - try { - installBootstrap(bootstrapConfigFile, repHome, repXml); - } catch (IOException e) { - log.error("Error while installing '{}': {}", bootstrapConfigFile.getPath(), e.toString()); - return C_INSTALL_ERROR; - } - return C_INSTALL_OK; - } - - /** - * Installs the repository config file from the template - * @param dest the destination location - * @throws IOException if an I/O error occurs. - */ - private void installRepositoryConfig(File dest) throws IOException { - log.info("Creating new repository config: {}", dest.getPath()); - InputStream in = context.getResourceAsStream(configTemplate); - if (in == null) { - in = getClass().getResourceAsStream(configTemplate); - } - OutputStream out = new FileOutputStream(dest); - byte[] buffer = new byte[8192]; - int read; - while ((read = in.read(buffer)) >= 0) { - out.write(buffer, 0, read); - } - in.close(); - out.close(); - } - - /** - * Installs the bootstrap config file from the template - * @param dest the destination location - * @param repHome the repository home location - * @param repXml the repository xml location - * @throws IOException if an I/O error occurs - */ - private void installBootstrap(File dest, String repHome, String repXml) - throws IOException { - log.info("Creating new bootstrap properties: {}", dest.getPath()); - InputStream in = context.getResourceAsStream(bootstrapTemplate); - Properties props = new Properties(); - props.load(in); - props.setProperty("repository.home", repHome); - if (repXml != null) { - props.setProperty("repository.config", repXml); - } - in.close(); - if (!dest.getParentFile().exists()) { - dest.getParentFile().mkdirs(); - } - OutputStream out = new FileOutputStream(dest); - props.store(out, "bootstrap properties for the repository startup servlet."); - out.close(); - } - -} Property changes on: jackrabbit-webapp/src/main/java/org/apache/jackrabbit/j2ee/Installer.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Deleted: svn:keywords ## -1 +0,0 ## -author date id revision url rev \ No newline at end of property Index: jackrabbit-webapp/src/main/java/org/apache/jackrabbit/j2ee/JCRWebdavServerServlet.java =================================================================== --- jackrabbit-webapp/src/main/java/org/apache/jackrabbit/j2ee/JCRWebdavServerServlet.java (revision 1907912) +++ jackrabbit-webapp/src/main/java/org/apache/jackrabbit/j2ee/JCRWebdavServerServlet.java (nonexistent) @@ -1,36 +0,0 @@ -/* - * 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.j2ee; - -import javax.jcr.Repository; - -/** - * JCRWebdavServerServlet provides request/response handling for the - * JCRWebdavServer. - */ -public class JCRWebdavServerServlet extends - org.apache.jackrabbit.webdav.jcr.JCRWebdavServerServlet { - - /** - * Returns the repository available from the servlet context of this - * servlet. - */ - protected Repository getRepository() { - return RepositoryAccessServlet.getRepository(getServletContext()); - } - -} Property changes on: jackrabbit-webapp/src/main/java/org/apache/jackrabbit/j2ee/JCRWebdavServerServlet.java ___________________________________________________________________ Deleted: svn Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-webapp/src/main/java/org/apache/jackrabbit/j2ee/JNDIConfig.java =================================================================== --- jackrabbit-webapp/src/main/java/org/apache/jackrabbit/j2ee/JNDIConfig.java (revision 1907912) +++ jackrabbit-webapp/src/main/java/org/apache/jackrabbit/j2ee/JNDIConfig.java (nonexistent) @@ -1,112 +0,0 @@ -/* - * 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.j2ee; - -import java.util.Enumeration; -import java.util.Iterator; -import java.util.Properties; - -import javax.servlet.ServletConfig; -import javax.servlet.ServletException; - -/** - * The JNDI config hold information about JNDI connection details. - * - * It supports the following properties and init parameters: - *
- * +-------------------+--------------------+
- * | Property Name     | Init-Param Name    |
- * +-------------------+--------------------+
- * | jndi.enable       | {provider spec.}   |
- * | java.naming.*     | java.naming.*      |
- * +-------------------+--------------------+
- * 
- */ -public class JNDIConfig extends AbstractConfig { - - private boolean jndiEnabled; - - private String jndiName; - - private final BootstrapConfig parentConfig; - - private Properties jndiEnv = new Properties(); - - - public JNDIConfig(BootstrapConfig parentConfig) { - this.parentConfig = parentConfig; - } - - - public String getJndiName() { - return jndiName; - } - - public void setJndiName(String jndiName) { - this.jndiName = jndiName; - } - - public boolean enabled() { - return jndiEnabled; - } - - public String getJndiEnabled() { - return String.valueOf(jndiEnabled); - } - - public void setJndiEnabled(String jndiEnabled) { - this.jndiEnabled = Boolean.valueOf(jndiEnabled).booleanValue(); - } - - public Properties getJndiEnv() { - return jndiEnv; - } - - public void init(Properties props) throws ServletException { - super.init(props); - // add all props whose name starts with 'java.namming.' to the env - Iterator iter = props.keySet().iterator(); - while (iter.hasNext()) { - String name = (String) iter.next(); - if (name.startsWith("java.naming.")) { - jndiEnv.put(name, props.getProperty(name)); - } - } - } - - public void init(ServletConfig ctx) throws ServletException { - super.init(ctx); - // add all params whose name starts with 'java.namming.' to the env - Enumeration names = ctx.getInitParameterNames(); - while (names.hasMoreElements()) { - String name = (String) names.nextElement(); - if (name.startsWith("java.naming.")) { - jndiEnv.put(name, ctx.getInitParameter(name)); - } - } - // enable jndi if url is specified - jndiEnabled = jndiEnv.containsKey("java.naming.provider.url"); - } - - - public void validate() { - if (jndiName == null) { - jndiName = parentConfig.getRepositoryName(); - } - valid = true; - } -} \ No newline at end of file Property changes on: jackrabbit-webapp/src/main/java/org/apache/jackrabbit/j2ee/JNDIConfig.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Deleted: svn:keywords ## -1 +0,0 ## -author date id revision url rev \ No newline at end of property Index: jackrabbit-webapp/src/main/java/org/apache/jackrabbit/j2ee/JcrApiNotFoundException.java =================================================================== --- jackrabbit-webapp/src/main/java/org/apache/jackrabbit/j2ee/JcrApiNotFoundException.java (revision 1907912) +++ jackrabbit-webapp/src/main/java/org/apache/jackrabbit/j2ee/JcrApiNotFoundException.java (nonexistent) @@ -1,38 +0,0 @@ -/* - * 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.j2ee; - -/** - * Exception for signaling that the JCR API is not available. - */ -public class JcrApiNotFoundException extends ServletExceptionWithCause { - - /** - * Serial version UID - */ - private static final long serialVersionUID = -6439777923943394980L; - - /** - * Creates an exception to signal that the JCR API is not available. - * - * @param e the specific exception that indicates the lack of the JCR API - */ - public JcrApiNotFoundException(ClassNotFoundException e) { - super("JCR API (jcr-1.0.jar) not available in the classpath", e); - } - -} Property changes on: jackrabbit-webapp/src/main/java/org/apache/jackrabbit/j2ee/JcrApiNotFoundException.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-webapp/src/main/java/org/apache/jackrabbit/j2ee/JcrRemotingServlet.java =================================================================== --- jackrabbit-webapp/src/main/java/org/apache/jackrabbit/j2ee/JcrRemotingServlet.java (revision 1907912) +++ jackrabbit-webapp/src/main/java/org/apache/jackrabbit/j2ee/JcrRemotingServlet.java (nonexistent) @@ -1,33 +0,0 @@ -/* - * 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.j2ee; - -import javax.jcr.Repository; - -/** - * JcrRemotingServlet... - */ -public class JcrRemotingServlet extends org.apache.jackrabbit.server.remoting.davex.JcrRemotingServlet { - - /** - * Returns the repository available from the servlet context of this - * servlet. - */ - protected Repository getRepository() { - return RepositoryAccessServlet.getRepository(getServletContext()); - } -} \ No newline at end of file Property changes on: jackrabbit-webapp/src/main/java/org/apache/jackrabbit/j2ee/JcrRemotingServlet.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Deleted: svn:keywords ## -1 +0,0 ## -author date id revision url \ No newline at end of property Index: jackrabbit-webapp/src/main/java/org/apache/jackrabbit/j2ee/RMIConfig.java =================================================================== --- jackrabbit-webapp/src/main/java/org/apache/jackrabbit/j2ee/RMIConfig.java (revision 1907912) +++ jackrabbit-webapp/src/main/java/org/apache/jackrabbit/j2ee/RMIConfig.java (nonexistent) @@ -1,175 +0,0 @@ -/* - * 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.j2ee; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.net.URI; -import java.net.URISyntaxException; -import java.rmi.registry.Registry; - -import javax.servlet.ServletConfig; -import javax.servlet.ServletException; - -/** - * The RMI config hold information about RMI connection details. - * - * It supports the following properties and init parameters: - *
- * +-------------------+--------------------+
- * | Property Name     | Init-Param Name    |
- * +-------------------+--------------------+
- * | rmi.enable        | {rmi-port sepc.}   |
- * | rmi.host          | rmi-host           |
- * | rmi.port          | rmi-port           |
- * | rmi.name          | {repository name}  |
- * | rmi.url           | rmi-url            |
- * +-------------------+--------------------+
- * 
- */ -public class RMIConfig extends AbstractConfig { - - /** - * default logger - */ - private static final Logger log = LoggerFactory.getLogger(RMIConfig.class); - - private boolean rmiEnabled; - - private int rmiPort = -1; - - private String rmiHost; - - private String rmiName; - - private String rmiUri; - - private final BootstrapConfig parentConfig; - - - public RMIConfig(BootstrapConfig parentConfig) { - this.parentConfig = parentConfig; - } - - public void init(ServletConfig ctx) throws ServletException { - super.init(ctx); - // enable RMI if either port or url was defined - rmiEnabled = rmiPort >=0 || rmiUri != null; - } - - public String getRmiName() { - return rmiName; - } - - public void setRmiName(String rmiName) { - this.rmiName = rmiName; - } - - public boolean enabled() { - return rmiEnabled; - } - - public String getRmiEnabled() { - return String.valueOf(rmiEnabled); - } - - public void setRmiEnabled(String rmiEnabled) { - this.rmiEnabled = Boolean.valueOf(rmiEnabled).booleanValue(); - } - - public int rmiPort() { - return rmiPort; - } - - public String getRmiPort() { - return String.valueOf(rmiPort); - } - - public void setRmiPort(String rmiPort) { - this.rmiPort = Integer.decode(rmiPort).intValue(); - } - - public String getRmiHost() { - return rmiHost; - } - - public void setRmiHost(String rmiHost) { - this.rmiHost = rmiHost; - } - - public String getRmiUri() { - return rmiUri; - } - - public void setRmiUri(String rmiUri) { - this.rmiUri = rmiUri; - } - - public void validate() { - if (!rmiEnabled) { - return; - } - - if (rmiUri != null && rmiUri.length() > 0) { - // URI takes precedences, so check whether the configuration has to - // be set from the URI - try { - URI uri = new URI(rmiUri); - - // extract values from the URI, check later - rmiHost = uri.getHost(); - rmiPort = uri.getPort(); - rmiName = uri.getPath(); - - } catch (URISyntaxException e) { - log.warn("Cannot parse RMI URI '" + rmiUri + "'.", e); - rmiUri = null; // clear RMI URI use another one - rmiHost = null; // use default host, ignore rmi-host param - } - - // cut of leading slash from name if defined at all - if (rmiName != null && rmiName.startsWith("/")) { - rmiName = rmiName.substring(1); - } - } - - // check RMI port - if (rmiPort == -1 || rmiPort == 0) { - // accept -1 or 0 as a hint to use the default - rmiPort = Registry.REGISTRY_PORT; - } else if (rmiPort < -1 || rmiPort > 0xFFFF) { - // emit a warning if out of range, use defualt in this case - log.warn("Invalid port in rmi-port param " + rmiPort + ". using default port."); - rmiPort = Registry.REGISTRY_PORT; - } - - // check host - use an empty name if null (i.e. not configured) - if (rmiHost == null) { - rmiHost = ""; - } - - // check name - use repositoryName if empty or null - if (rmiName == null || rmiName.length() ==0) { - rmiName = parentConfig.getRepositoryName(); - } - - // reconstruct the rmiURI now because values might have been changed - rmiUri = "//" + rmiHost + ":" + rmiPort + "/" + rmiName; - valid = true; - } -} \ No newline at end of file Property changes on: jackrabbit-webapp/src/main/java/org/apache/jackrabbit/j2ee/RMIConfig.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Deleted: svn:keywords ## -1 +0,0 ## -author date id revision url rev \ No newline at end of property Index: jackrabbit-webapp/src/main/java/org/apache/jackrabbit/j2ee/RepositoryAccessServlet.java =================================================================== --- jackrabbit-webapp/src/main/java/org/apache/jackrabbit/j2ee/RepositoryAccessServlet.java (revision 1907912) +++ jackrabbit-webapp/src/main/java/org/apache/jackrabbit/j2ee/RepositoryAccessServlet.java (nonexistent) @@ -1,363 +0,0 @@ -/* - * 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.j2ee; - -import org.apache.jackrabbit.rmi.client.ClientRepositoryFactory; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.File; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.IOException; -import java.io.InputStream; -import java.net.MalformedURLException; -import java.rmi.NotBoundException; -import java.rmi.RemoteException; -import java.util.Properties; - -import javax.jcr.Repository; -import javax.naming.InitialContext; -import javax.naming.NamingException; -import javax.servlet.ServletContext; -import javax.servlet.ServletException; -import javax.servlet.http.HttpServlet; - -/** - * This Class implements a servlet that is used as unified mechanism to retrieve - * a jcr repository either through JNDI or RMI. - */ -public class RepositoryAccessServlet extends HttpServlet { - - /** - * default logger - */ - private static final Logger log = LoggerFactory.getLogger(RepositoryAccessServlet.class); - - /** - * initial param name for the bootstrap config location - */ - public final static String INIT_PARAM_BOOTSTRAP_CONFIG = "bootstrap-config"; - - /** - * Context parameter name for 'this' instance. - */ - private final static String CTX_PARAM_THIS = "repository.access.servlet"; - - /** - * Ugly hack to override the bootstrap file location in the test cases - */ - static String bootstrapOverride = null; - - /** - * the bootstrap config - */ - private BootstrapConfig config; - - /** - * the initialized initial context - */ - private InitialContext jndiContext; - - /** - * if this is set we try to get a Repository from the ServletContext - */ - private String repositoryContextAttributeName; - - /** - * the repository - */ - private Repository repository; - - /** - * Initializes the servlet.
- * Please note that only one repository startup servlet may exist per - * webapp. it registers itself as context attribute and acts as singleton. - * - * @throws ServletException if a same servlet is already registered or of - * another initialization error occurs. - */ - public void init() throws ServletException { - // check if servlet is defined twice - if (getServletContext().getAttribute(CTX_PARAM_THIS) != null) { - throw new ServletException("Only one repository access servlet allowed per web-app."); - } - getServletContext().setAttribute(CTX_PARAM_THIS, this); - - repositoryContextAttributeName = getServletConfig().getInitParameter("repository.context.attribute.name"); - - log.info("RepositoryAccessServlet initialized."); - } - - /** - * Returns the instance of this servlet - * @param ctx the servlet context - * @return this servlet - */ - public static RepositoryAccessServlet getInstance(ServletContext ctx) { - final RepositoryAccessServlet instance = (RepositoryAccessServlet) ctx.getAttribute(CTX_PARAM_THIS); - if(instance==null) { - throw new IllegalStateException( - "No RepositoryAccessServlet instance in ServletContext, RepositoryAccessServlet servlet not initialized?" - ); - } - return instance; - } - - /** - * Returns the bootstrap config - * @return the bootstrap config - * @throws ServletException if the config is not valid - */ - private BootstrapConfig getConfig() throws ServletException { - if (config == null) { - // check if there is a loadable bootstrap config - Properties bootstrapProps = new Properties(); - String bstrp = bootstrapOverride; - if (bstrp == null) { - bstrp = getServletConfig().getInitParameter(INIT_PARAM_BOOTSTRAP_CONFIG); - } - if (bstrp != null) { - // check if it's a web-resource - InputStream in = getServletContext().getResourceAsStream(bstrp); - if (in == null) { - // check if it's a file - File file = new File(bstrp); - if (file.canRead()) { - try { - in = new FileInputStream(file); - } catch (FileNotFoundException e) { - throw new ServletExceptionWithCause( - "Bootstrap configuration not found: " + bstrp, e); - } - } - } - if (in != null) { - try { - bootstrapProps.load(in); - } catch (IOException e) { - throw new ServletExceptionWithCause( - "Bootstrap configuration failure: " + bstrp, e); - } finally { - try { - in.close(); - } catch (IOException e) { - // ignore - } - } - } - } - - // read bootstrap config - BootstrapConfig tmpConfig = new BootstrapConfig(); - tmpConfig.init(getServletConfig()); - tmpConfig.init(bootstrapProps); - tmpConfig.validate(); - if (!tmpConfig.isValid()) { - throw new ServletException( - "Repository access configuration is not valid."); - } - tmpConfig.logInfos(); - config = tmpConfig; - } - return config; - } - - /** - * Returns the initial jndi context or null if the jndi access - * is not configured or erroous. - * @return the initial context or null - */ - private InitialContext getInitialContext() { - if (jndiContext == null && config.getJndiConfig().enabled()) { - // retrieve JNDI Context environment - try { - jndiContext = new InitialContext(config.getJndiConfig().getJndiEnv()); - } catch (NamingException e) { - log.error("Create initial context: " + e.toString()); - } - } - return jndiContext; - } - - /** - * Checks if the repository is available via JNDI and returns it. - * @return the repository or null - * @throws ServletException if this servlet is not properly configured. - */ - private Repository getRepositoryByJNDI() throws ServletException { - BootstrapConfig config = getConfig(); - if (!config.getJndiConfig().isValid() || !config.getJndiConfig().enabled()) { - return null; - } - // acquire via JNDI - String repositoryName = config.getRepositoryName(); - InitialContext ctx = getInitialContext(); - if (ctx == null) { - return null; - } - try { - Repository r = (Repository) ctx.lookup(repositoryName); - log.info("Acquired repository via JNDI."); - return r; - } catch (NamingException e) { - log.error("Error while retrieving repository using JNDI (name={})", repositoryName, e); - return null; - } - } - - /** - * Checks if the repository is available via RMI and returns it. - * @return the repository or null - * @throws ServletException if this servlet is not properly configured. - */ - private Repository getRepositoryByRMI() throws ServletException { - BootstrapConfig config = getConfig(); - if (!config.getRmiConfig().isValid() || !config.getRmiConfig().enabled()) { - return null; - } - - // acquire via RMI - String rmiURI = config.getRmiConfig().getRmiUri(); - if (rmiURI == null) { - return null; - } - log.info(" trying to retrieve repository using rmi. uri={}", rmiURI); - ClientFactoryDelegater cfd; - try { - Class clazz = Class.forName(getServerFactoryDelegaterClass()); - cfd = (ClientFactoryDelegater) clazz.newInstance(); - } catch (Throwable e) { - log.error("Unable to locate RMI ClientRepositoryFactory. Is jcr-rmi.jar missing?", e); - return null; - } - - try { - Repository r = cfd.getRepository(rmiURI); - log.info("Acquired repository via RMI."); - return r; - } catch (Exception e) { - log.error("Error while retrieving repository using RMI: {}", rmiURI, e); - return null; - } - } - - /** - * If our config said so, try to retrieve a Repository from the ServletContext - */ - protected Repository getRepositoryByContextAttribute() { - Repository result = null; - if(repositoryContextAttributeName!=null) { - result = (Repository)getServletContext().getAttribute(repositoryContextAttributeName); - - if(log.isDebugEnabled()) { - if(result!=null) { - log.debug("Got Repository from ServletContext attribute '{}'", repositoryContextAttributeName); - } else { - log.debug("ServletContext attribute '{}' does not provide a Repository", repositoryContextAttributeName); - } - } - } - return result; - } - - /** - * Return the fully qualified name of the class providing the client - * repository. The class whose name is returned must implement the - * {@link ClientFactoryDelegater} interface. - * - * @return the qfn of the factory class. - */ - protected String getServerFactoryDelegaterClass() { - return getClass().getName() + "$RMIClientFactoryDelegater"; - } - - /** - * Returns the JCR repository - * - * @return a JCR repository - * @throws IllegalStateException if the repository is not available in the context. - */ - public Repository getRepository() { - try { - if (repository == null) { - // try to get via context attribute - repository = getRepositoryByContextAttribute(); - } - if (repository == null) { - // try to retrieve via jndi - repository = getRepositoryByJNDI(); - } - if (repository == null) { - // try to get via rmi - repository = getRepositoryByRMI(); - } - if (repository == null) { - throw new ServletException("N/A"); - } - return repository; - } catch (ServletException e) { - throw new IllegalStateException( - "The repository is not available. Please check" - + " RepositoryAccessServlet configuration in web.xml.", e); - } - } - - /** - * Returns the JCR repository - * - * @param ctx the servlet context - * @return a JCR repository - * @throws IllegalStateException if the repository is not available in the context. - */ - public static Repository getRepository(ServletContext ctx) { - return getInstance(ctx).getRepository(); - } - - /** - * Returns the config that was used to bootstrap this servlet. - * @return the bootstrap config or null. - */ - public BootstrapConfig getBootstrapConfig() { - return config; - } - - /** - * optional class for RMI, will only be used, if RMI client is present - */ - protected static abstract class ClientFactoryDelegater { - - public abstract Repository getRepository(String uri) - throws RemoteException, MalformedURLException, NotBoundException; - } - - /** - * optional class for RMI, will only be used, if RMI server is present - */ - protected static class RMIClientFactoryDelegater extends ClientFactoryDelegater { - - // only used to enforce linking upon Class.forName() - static String FactoryClassName = ClientRepositoryFactory.class.getName(); - - public Repository getRepository(String uri) - throws MalformedURLException, NotBoundException, RemoteException { - System.setProperty("java.rmi.server.useCodebaseOnly", "true"); - return new ClientRepositoryFactory().getRepository(uri); - } - } -} - Property changes on: jackrabbit-webapp/src/main/java/org/apache/jackrabbit/j2ee/RepositoryAccessServlet.java ___________________________________________________________________ Deleted: svn Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-webapp/src/main/java/org/apache/jackrabbit/j2ee/RepositoryStartupServlet.java =================================================================== --- jackrabbit-webapp/src/main/java/org/apache/jackrabbit/j2ee/RepositoryStartupServlet.java (revision 1907912) +++ jackrabbit-webapp/src/main/java/org/apache/jackrabbit/j2ee/RepositoryStartupServlet.java (nonexistent) @@ -1,767 +0,0 @@ -/* - * 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.j2ee; - -import org.apache.jackrabbit.api.JackrabbitRepository; -import org.apache.jackrabbit.commons.repository.RepositoryFactory; -import org.apache.jackrabbit.core.RepositoryImpl; -import org.apache.jackrabbit.core.config.RepositoryConfig; -import org.apache.jackrabbit.rmi.server.RemoteAdapterFactory; -import org.apache.jackrabbit.rmi.server.ServerAdapterFactory; -import org.apache.jackrabbit.servlet.AbstractRepositoryServlet; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.xml.sax.InputSource; - -import java.io.File; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.IOException; -import java.io.InputStream; -import java.net.InetAddress; -import java.net.ServerSocket; -import java.net.UnknownHostException; -import java.rmi.AlreadyBoundException; -import java.rmi.Naming; -import java.rmi.NoSuchObjectException; -import java.rmi.Remote; -import java.rmi.RemoteException; -import java.rmi.registry.LocateRegistry; -import java.rmi.registry.Registry; -import java.rmi.server.RMIServerSocketFactory; -import java.rmi.server.UnicastRemoteObject; -import java.util.Properties; - -import javax.jcr.Repository; -import javax.jcr.RepositoryException; -import javax.naming.InitialContext; -import javax.naming.NamingException; -import javax.servlet.ServletContext; -import javax.servlet.ServletException; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -/** - * The RepositoryStartupServlet starts a jackrabbit repository and registers it - * to the JNDI environment and optional to the RMI registry. - *

- * Registration with RMI - *

- * Upon successfull creation of the repository in the {@link #init()} method, - * the repository is registered with an RMI registry if the web application is - * so configured. To register with RMI, the following web application - * init-params are considered: rmi-port designating - * the port on which the RMI registry is listening, rmi-host - * designating the interface on the local host on which the RMI registry is - * active, repository-name designating the name to which the - * repository is to be bound in the registry, and rmi-uri - * designating an RMI URI complete with host, optional port and name to which - * the object is bound. - *

- * If the rmi-uri parameter is configured with a non-empty value, - * the rmi-port and rmi-host parameters are ignored. - * The repository-name parameter is only considered if a non-empty - * rmi-uri parameter is configured if the latter does not contain - * a name to which to bind the repository. - *

- * This is the algorithm used to find out the host, port and name for RMI - * registration: - *

    - *
  1. If neither a rmi-uri nor a rmi-host nor a - * rmi-port parameter is configured, the repository is not - * registered with any RMI registry. - *
  2. If a non-empty rmi-uri parameter is configured extract the - * host name (or IP address), port number and name to bind to from the - * URI. If the URI is not valid, host defaults to 0.0.0.0 - * meaning all interfaces on the local host, port defaults to the RMI - * default port (1099) and the name defaults to the value - * of the repository-name parameter. - *
  3. If a non-empty rmi-uri is not configured, the host is taken - * from the rmi-host parameter, the port from the - * rmi-port parameter and the name to bind the repository to - * from the repository-name parameter. If the - * rmi-host parameter is empty or not configured, the host - * defaults to 0.0.0.0 meaning all interfaces on the local - * host. If the rmi-port parameter is empty, not configured, - * zero or a negative value, the default port for the RMI registry - * (1099) is used. - *
- *

- * After finding the host and port of the registry, the RMI registry itself - * is acquired. It is assumed, that host and port primarily designate an RMI - * registry, which should be active on the local host but has not been started - * yet. In this case, the LocateRegistry.createRegistry method is - * called to create a registry on the local host listening on the host and port - * configured. If creation fails, the LocateRegistry.getRegistry - * method is called to get a remote instance of the registry. Note, that - * getRegistry does not create an actual registry on the given - * host/port nor does it check, whether an RMI registry is active. - *

- * When the registry has been retrieved, either by creation or by just creating - * a remote instance, the repository is bound to the configured name in the - * registry. - *

- * Possible causes for registration failures include: - *

    - *
  • The web application is not configured to register with an RMI registry at - * all. - *
  • The registry is expected to be running on a remote host but does not. - *
  • The registry is expected to be running on the local host but cannot be - * accessed. Reasons include another application which does not act as an - * RMI registry is running on the configured port and thus blocks creation - * of a new RMI registry. - *
  • An object may already be bound to the same name as is configured to be - * used for the repository. - *
- *

- * Note: if a bootstrap-config init parameter is specified the - * servlet tries to read the respective resource, either as context resource or - * as file. The properties specified in this file override the init params - * specified in the web.xml. - *

- *

- * Setup Wizard Functionality
- * When using the first time, the configuration can miss the relevant - * repository parameters in the web.xml. if so, it must contain a - * bootstrap-config parameter that refers to a property file. - * This file must exist for proper working. If not, the repository is not - * started.
- * If the servlet is not configured correctly and accessed via http, it will - * provide a simple wizard for the first time configuration. It prompts for - * a new (or existing) repository home and will copy the templates of the - * repository.xml and bootstrap.properties to the respective location. - */ -public class RepositoryStartupServlet extends AbstractRepositoryServlet { - - /** - * the default logger - */ - private static final Logger log = LoggerFactory.getLogger(RepositoryStartupServlet.class); - - /** - * the context attribute name foe 'this' instance. - */ - private final static String CTX_PARAM_THIS = "repository.startup.servet"; - - /** - * initial param name for the bootstrap config location - */ - public final static String INIT_PARAM_BOOTSTRAP_CONFIG = "bootstrap-config"; - - /** - * Ugly hack to override the bootstrap file location in the test cases - */ - static String bootstrapOverride = null; - - /** - * the registered repository - */ - private Repository repository; - - /** - * the jndi context; created based on configuration - */ - private InitialContext jndiContext; - - private Registry rmiRegistry = null; - - /** - * Keeps a strong reference to the server side RMI repository instance to - * prevent the RMI distributed Garbage Collector from collecting the - * instance making the repository unaccessible though it should still be. - * This field is only set to a non-null value, if registration - * of the repository to an RMI registry succeeded in the - * {@link #registerRMI()} method. - * - * @see #registerRMI() - * @see #unregisterRMI() - */ - private Remote rmiRepository; - - /** - * the file to the bootstrap config - */ - private File bootstrapConfigFile; - - /** - * The bootstrap configuration - */ - private BootstrapConfig config; - - /** - * Initializes the servlet.
- * Please note that only one repository startup servlet may exist per - * webapp. it registers itself as context attribute and acts as singleton. - * - * @throws ServletException if a same servlet is already registered or of - * another initialization error occurs. - */ - public void init() throws ServletException { - super.init(); - // check if servlet is defined twice - if (getServletContext().getAttribute(CTX_PARAM_THIS) != null) { - throw new ServletException("Only one repository startup servlet allowed per web-app."); - } - getServletContext().setAttribute(CTX_PARAM_THIS, this); - startup(); - } - - /** - * Returns an instance of this servlet. Please note, that only 1 - * repository startup servlet can exist per webapp. - * - * @param context the servlet context - * @return this servlet - */ - public static RepositoryStartupServlet getInstance(ServletContext context) { - return (RepositoryStartupServlet) context.getAttribute(CTX_PARAM_THIS); - } - - /** - * Configures and starts the repository. It registers it then to the - * RMI registry and bind is to the JNDI context if so configured. - * @throws ServletException if an error occurs. - */ - public void startup() throws ServletException { - if (repository != null) { - log.error("Startup: Repository already running."); - throw new ServletException("Repository already running."); - } - log.info("RepositoryStartupServlet initializing..."); - try { - if (configure()) { - initRepository(); - registerRMI(); - registerJNDI(); - } - log.info("RepositoryStartupServlet initialized."); - } catch (ServletException e) { - // shutdown repository - shutdownRepository(); - log.error("RepositoryStartupServlet initializing failed: " + e, e); - } - } - - /** - * Does a shutdown of the repository and deregisters it from the RMI - * registry and unbinds if from the JNDI context if so configured. - */ - public void shutdown() { - if (repository == null) { - log.info("Shutdown: Repository already stopped."); - } else { - log.info("RepositoryStartupServlet shutting down..."); - shutdownRepository(); - unregisterRMI(); - unregisterJNDI(); - log.info("RepositoryStartupServlet shut down."); - } - } - - /** - * Restarts the repository. - * @throws ServletException if an error occurs. - * @see #shutdown() - * @see #startup() - */ - public void restart() throws ServletException { - if (repository != null) { - shutdown(); - } - startup(); - } - - /** - * destroy the servlet - */ - public void destroy() { - super.destroy(); - shutdown(); - } - - /** - * Returns the started repository or null if not started - * yet. - * @return the JCR repository - */ - public Repository getRepository() { - return repository; - } - - /** - * Returns a repository factory that returns the repository if available - * or throws an exception if not. - * - * @return repository factory - */ - public RepositoryFactory getRepositoryFactory() { - return new RepositoryFactory() { - public Repository getRepository() throws RepositoryException { - Repository r = repository; - if (r != null) { - return repository; - } else { - throw new RepositoryException("Repository not available"); - } - } - }; - } - - /** - * Reads the configuration and initializes the {@link #config} field if - * successful. - * @throws ServletException if an error occurs. - */ - private boolean configure() throws ServletException { - // check if there is a loadable bootstrap config - Properties bootstrapProps = new Properties(); - String bstrp = bootstrapOverride; - if (bstrp == null) { - bstrp = getServletConfig().getInitParameter(INIT_PARAM_BOOTSTRAP_CONFIG); - } - if (bstrp != null) { - // check if it's a web-resource - InputStream in = getServletContext().getResourceAsStream(bstrp); - if (in == null) { - // check if it's a file - bootstrapConfigFile = new File(bstrp); - if (bootstrapConfigFile.canRead()) { - try { - in = new FileInputStream(bootstrapConfigFile); - } catch (FileNotFoundException e) { - throw new ServletExceptionWithCause( - "Bootstrap configuration not found: " + bstrp, e); - } - } - } - if (in != null) { - try { - bootstrapProps.load(in); - } catch (IOException e) { - throw new ServletException( - "Bootstrap configuration failure: " + bstrp, e); - } finally { - try { - in.close(); - } catch (IOException e) { - // ignore - } - } - } - } - - // read bootstrap config - config = new BootstrapConfig(); - config.init(getServletConfig()); - config.init(bootstrapProps); - config.validate(); - if (!config.isValid() - || config.getRepositoryHome() == null) { - if (bstrp == null) { - log.error("Repository startup configuration is not valid."); - } else { - log.error("Repository startup configuration is not valid but a bootstrap config is specified."); - log.error("Either create the {} file or", bstrp); - log.error("use the '/config/index.jsp' for easy configuration."); - } - return false; - } else { - config.logInfos(); - return true; - } - } - - /** - * Creates a new Repository based on the configuration and initializes the - * {@link #repository} field if successful. - * - * @throws ServletException if an error occurs - */ - private void initRepository() throws ServletException { - // get repository config - File repHome; - try { - repHome = new File(config.getRepositoryHome()).getCanonicalFile(); - } catch (IOException e) { - throw new ServletExceptionWithCause( - "Repository configuration failure: " + config.getRepositoryHome(), e); - } - String repConfig = config.getRepositoryConfig(); - if (repConfig != null) { - InputStream in = getServletContext().getResourceAsStream(repConfig); - if (in == null) { - try { - in = new FileInputStream(new File(repConfig)); - } catch (FileNotFoundException e) { - // fallback to old config - try { - in = new FileInputStream(new File(repHome, repConfig)); - } catch (FileNotFoundException e1) { - throw new ServletExceptionWithCause( - "Repository configuration not found: " + repConfig, e); - } - } - } - - try { - repository = createRepository(new InputSource(in), repHome); - } catch (RepositoryException e) { - throw new ServletExceptionWithCause("Error while creating repository", e); - } - } else { - throw new ServletException("Missing configuration"); - } - } - - /** - * Shuts down the repository. If the repository is an instanceof - * {@link JackrabbitRepository} it's {@link JackrabbitRepository#shutdown()} - * method is called. in any case, the {@link #repository} field is - * nulled. - */ - private void shutdownRepository() { - if (repository instanceof JackrabbitRepository) { - ((JackrabbitRepository) repository).shutdown(); - } - repository = null; - } - - /** - * Creates the repository instance for the given config and homedir. - * Subclasses may override this method of providing own implementations of - * a {@link Repository}. - * - * @param is input source of the repository config - * @param homedir the repository home directory - * @return a new jcr repository. - * @throws RepositoryException if an error during creation occurs. - */ - protected Repository createRepository(InputSource is, File homedir) - throws RepositoryException { - RepositoryConfig config = RepositoryConfig.create(is, homedir.getAbsolutePath()); - return RepositoryImpl.create(config); - } - - /** - * Binds the repository to the JNDI context - * @throws ServletException if an error occurs. - */ - private void registerJNDI() throws ServletException { - JNDIConfig jc = config.getJndiConfig(); - if (jc.isValid() && jc.enabled()) { - try { - jndiContext = new InitialContext(jc.getJndiEnv()); - jndiContext.bind(jc.getJndiName(), repository); - log.info("Repository bound to JNDI with name: " + jc.getJndiName()); - } catch (NamingException e) { - throw new ServletExceptionWithCause( - "Unable to bind repository using JNDI: " + jc.getJndiName(), e); - } - } - } - - /** - * Unbinds the repository from the JNDI context. - */ - private void unregisterJNDI() { - if (jndiContext != null) { - try { - jndiContext.unbind(config.getJndiConfig().getJndiName()); - } catch (NamingException e) { - log("Error while unbinding repository from JNDI: " + e); - } - } - } - - /** - * Registers the repository to an RMI registry configured in the web - * application. See Registration with RMI in the - * class documentation for a description of the algorithms used to register - * the repository with an RMI registry. - * @throws ServletException if an error occurs. - */ - private void registerRMI() { - RMIConfig rc = config.getRmiConfig(); - if (!rc.isValid() || !rc.enabled()) { - return; - } - - // try to create remote repository - Remote remote; - try { - Class clazz = Class.forName(getRemoteFactoryDelegaterClass()); - RemoteFactoryDelegater rmf = (RemoteFactoryDelegater) clazz.newInstance(); - remote = rmf.createRemoteRepository(repository); - } catch (RemoteException e) { - log.warn("Unable to create RMI repository.", e); - return; - } catch (Throwable t) { - log.warn("Unable to create RMI repository." - + " The jcr-rmi jar might be missing.", t); - return; - } - - try { - System.setProperty("java.rmi.server.useCodebaseOnly", "true"); - Registry reg = null; - - // first try to create the registry, which will fail if another - // application is already running on the configured host/port - // or if the rmiHost is not local - try { - // find the server socket factory: use the default if the - // rmiHost is not configured - RMIServerSocketFactory sf; - if (rc.getRmiHost().length() > 0) { - log.debug("Creating RMIServerSocketFactory for host " + rc.getRmiHost()); - InetAddress hostAddress = InetAddress.getByName(rc.getRmiHost()); - sf = getRMIServerSocketFactory(hostAddress); - } else { - // have the RMI implementation decide which factory is the - // default actually - log.debug("Using default RMIServerSocketFactory"); - sf = null; - } - - // create a registry using the default client socket factory - // and the server socket factory retrieved above. This also - // binds to the server socket to the rmiHost:rmiPort. - reg = LocateRegistry.createRegistry(rc.rmiPort(), null, sf); - rmiRegistry = reg; - } catch (UnknownHostException uhe) { - // thrown if the rmiHost cannot be resolved into an IP-Address - // by getRMIServerSocketFactory - log.info("Cannot create Registry", uhe); - } catch (RemoteException e) { - // thrown by createRegistry if binding to the rmiHost:rmiPort - // fails, for example due to rmiHost being remote or another - // application already being bound to the port - log.info("Cannot create Registry", e); - } - - // if creation of the registry failed, we try to access an - // potentially active registry. We do not check yet, whether the - // registry is actually accessible. - if (reg == null) { - log.debug("Trying to access existing registry at " + rc.getRmiHost() - + ":" + rc.getRmiPort()); - try { - reg = LocateRegistry.getRegistry(rc.getRmiHost(), rc.rmiPort()); - } catch (RemoteException re) { - log.warn("Cannot create the reference to the registry at " - + rc.getRmiHost() + ":" + rc.getRmiPort(), re); - } - } - - // if we finally have a registry, register the repository with the - // rmiName - if (reg != null) { - log.debug("Registering repository as " + rc.getRmiName() - + " to registry " + reg); - reg.bind(rc.getRmiName(), remote); - - // when successfull, keep references - this.rmiRepository = remote; - log.info("Repository bound via RMI with name: " + rc.getRmiUri()); - } else { - log.info("RMI registry missing, cannot bind repository via RMI"); - } - } catch (RemoteException e) { - log.warn("Unable to bind repository via RMI: " + rc.getRmiUri(), e); - } catch (AlreadyBoundException e) { - log.warn("Unable to bind repository via RMI: " + rc.getRmiUri(), e); - } - } - - /** - * Unregisters the repository from the RMI registry, if it has previously - * been registered. - */ - private void unregisterRMI() { - if (rmiRepository != null) { - // Forcibly unexport the repository; - try { - UnicastRemoteObject.unexportObject(rmiRepository, true); - } catch (NoSuchObjectException e) { - log.warn("Odd, the RMI repository was not exported", e); - } - // drop strong reference to remote repository - rmiRepository = null; - - // unregister repository - try { - Naming.unbind(config.getRmiConfig().getRmiUri()); - } catch (Exception e) { - log("Error while unbinding repository from JNDI: " + e); - } - } - - if (rmiRegistry != null) { - try { - UnicastRemoteObject.unexportObject(rmiRegistry, true); - } catch (NoSuchObjectException e) { - log.warn("Odd, the RMI registry was not exported", e); - } - rmiRegistry = null; - } - } - - /** - * Returns the config that was used to bootstrap this servlet. - * @return the bootstrap config or null. - */ - public BootstrapConfig getBootstrapConfig() { - return config; - } - - /** - * Return the fully qualified name of the class providing the remote - * repository. The class whose name is returned must implement the - * {@link RemoteFactoryDelegater} interface. - *

- * Subclasses may override this method for providing a name of a own - * implementation. - * - * @return getClass().getName() + "$RMIRemoteFactoryDelegater" - */ - protected String getRemoteFactoryDelegaterClass() { - return getClass().getName() + "$RMIRemoteFactoryDelegater"; - } - - /** - * Returns an RMIServerSocketFactory used to create the server - * socket for a locally created RMI registry. - *

- * This implementation returns a new instance of a simple - * RMIServerSocketFactory which just creates instances of - * the java.net.ServerSocket class bound to the given - * hostAddress. Implementations may overwrite this method to - * provide factory instances, which provide more elaborate server socket - * creation, such as SSL server sockets. - * - * @param hostAddress The InetAddress instance representing the - * the interface on the local host to which the server sockets are - * bound. - * @return A new instance of a simple RMIServerSocketFactory - * creating java.net.ServerSocket instances bound to - * the rmiHost. - */ - protected RMIServerSocketFactory getRMIServerSocketFactory( - final InetAddress hostAddress) { - return new RMIServerSocketFactory() { - public ServerSocket createServerSocket(int port) throws IOException { - return new ServerSocket(port, -1, hostAddress); - } - }; - } - - /** - * optional class for RMI, will only be used, if RMI server is present - */ - protected static abstract class RemoteFactoryDelegater { - - public abstract Remote createRemoteRepository(Repository repository) - throws RemoteException; - } - - /** - * optional class for RMI, will only be used, if RMI server is present - */ - protected static class RMIRemoteFactoryDelegater extends RemoteFactoryDelegater { - - private static final RemoteAdapterFactory FACTORY = - new ServerAdapterFactory(); - - public Remote createRemoteRepository(Repository repository) - throws RemoteException { - return FACTORY.getRemoteRepository(repository); - } - - } - - //-------------------------------------------------< Installer Routines >--- - - /** - * {@inheritDoc} - */ - protected void doGet(HttpServletRequest req, HttpServletResponse resp) - throws ServletException, IOException { - if (repository == null) { - redirect(req, resp, "/bootstrap/missing.jsp"); - } else { - redirect(req, resp, "/bootstrap/running.jsp"); - } - } - - /** - * {@inheritDoc} - */ - protected void doPost(HttpServletRequest req, HttpServletResponse resp) - throws ServletException, IOException { - if (repository != null) { - redirect(req, resp, "/bootstrap/reconfigure.jsp"); - } else { - int rc = new Installer(bootstrapConfigFile, - getServletContext()).installRepository(req); - switch (rc) { - case Installer.C_INSTALL_OK: - // restart rep - restart(); - if (repository == null) { - redirect(req, resp, "/bootstrap/error.jsp"); - } else { - redirect(req, resp, "/bootstrap/success.jsp"); - } - break; - case Installer.C_INVALID_INPUT: - redirect(req, resp, "/bootstrap/missing.jsp"); - break; - case Installer.C_CONFIG_EXISTS: - case Installer.C_BOOTSTRAP_EXISTS: - case Installer.C_HOME_EXISTS: - redirect(req, resp, "/bootstrap/exists.jsp"); - break; - case Installer. C_HOME_MISSING: - case Installer.C_CONFIG_MISSING: - redirect(req, resp, "/bootstrap/notexists.jsp"); - break; - case Installer.C_INSTALL_ERROR: - redirect(req, resp, "/bootstrap/error.jsp"); - break; - } - } - } - - /** - * Helper function to send a redirect response respecting the context path. - * - * @param req the request - * @param resp the response - * @param loc the location for the redirect - * @throws IOException if an I/O error occurs. - */ - private void redirect(HttpServletRequest req, - HttpServletResponse resp, String loc) - throws IOException { - String cp = req.getContextPath(); - if (cp == null || cp.equals("/")) { - cp = ""; - } - resp.sendRedirect(cp + loc); - } -} - Property changes on: jackrabbit-webapp/src/main/java/org/apache/jackrabbit/j2ee/RepositoryStartupServlet.java ___________________________________________________________________ Deleted: svn Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-webapp/src/main/java/org/apache/jackrabbit/j2ee/ServletExceptionWithCause.java =================================================================== --- jackrabbit-webapp/src/main/java/org/apache/jackrabbit/j2ee/ServletExceptionWithCause.java (revision 1907912) +++ jackrabbit-webapp/src/main/java/org/apache/jackrabbit/j2ee/ServletExceptionWithCause.java (nonexistent) @@ -1,47 +0,0 @@ -/* - * 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.j2ee; - -import javax.servlet.ServletException; - -/** - * Utility class that links {@link ServletException} with support for - * the exception chaining mechanism in {@link Throwable}. - * - * @see JCR-1598 - */ -public class ServletExceptionWithCause extends ServletException { - - /** - * Serial version UID - */ - private static final long serialVersionUID = -7201954529718775444L; - - /** - * Creates a servlet exception with the given message and cause. - * - * @param message exception message - * @param cause cause of the exception - */ - public ServletExceptionWithCause(String message, Throwable cause) { - super(message, cause); - if (getCause() == null) { - initCause(cause); - } - } - -} Property changes on: jackrabbit-webapp/src/main/java/org/apache/jackrabbit/j2ee/ServletExceptionWithCause.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-webapp/src/main/java/org/apache/jackrabbit/j2ee/SimpleWebdavServlet.java =================================================================== --- jackrabbit-webapp/src/main/java/org/apache/jackrabbit/j2ee/SimpleWebdavServlet.java (revision 1907912) +++ jackrabbit-webapp/src/main/java/org/apache/jackrabbit/j2ee/SimpleWebdavServlet.java (nonexistent) @@ -1,55 +0,0 @@ -/* - * 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.j2ee; - -import javax.jcr.Repository; - -/** - * WebdavServlet provides webdav support (level 1 and 2 complient) for repository - * resources. - */ -public class SimpleWebdavServlet extends org.apache.jackrabbit.webdav.simple.SimpleWebdavServlet { - - /** - * the jcr repository - */ - private Repository repository; - - /** - * Returns the Repository. If no repository has been set or - * created the repository initialized by RepositoryAccessServlet - * is returned. - * - * @return repository - * @see RepositoryAccessServlet#getRepository(ServletContext) - */ - public Repository getRepository() { - if (repository == null) { - repository = RepositoryAccessServlet.getRepository(getServletContext()); - } - return repository; - } - - /** - * Sets the Repository. - * - * @param repository - */ - public void setRepository(Repository repository) { - this.repository = repository; - } -} Property changes on: jackrabbit-webapp/src/main/java/org/apache/jackrabbit/j2ee/SimpleWebdavServlet.java ___________________________________________________________________ Deleted: svn Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-webapp/src/main/resources/logback.xml =================================================================== --- jackrabbit-webapp/src/main/resources/logback.xml (revision 1907912) +++ jackrabbit-webapp/src/main/resources/logback.xml (nonexistent) @@ -1,30 +0,0 @@ - - - - - - - %d{yyyy-MM-dd HH:mm:ss.SSS} %-5level %-40([%thread] %F:%L) %msg%n - - - - - - - - Property changes on: jackrabbit-webapp/src/main/resources/logback.xml ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-webapp/src/main/webapp/META-INF/LICENSE =================================================================== --- jackrabbit-webapp/src/main/webapp/META-INF/LICENSE (revision 1907912) +++ jackrabbit-webapp/src/main/webapp/META-INF/LICENSE (nonexistent) @@ -1,1625 +0,0 @@ - - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright [yyyy] [name of copyright owner] - - Licensed 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. - - -APACHE JACKRABBIT SUBCOMPONENTS - -Apache Jackrabbit includes parts with separate copyright notices and license -terms. Your use of these subcomponents is subject to the terms and conditions -of the following licenses: - -XPath parser (jackrabbit-spi-commons) - - XPath 2.0/XQuery 1.0 Parser: - http://www.w3.org/2002/11/xquery-xpath-applets/xgrammar.zip - - Copyright (C) 2002 World Wide Web Consortium, (Massachusetts Institute of - Technology, European Research Consortium for Informatics and Mathematics, - Keio University). All Rights Reserved. - - This work is distributed under the W3C(R) Software License in the hope - that it will be useful, but WITHOUT ANY WARRANTY; without even the - implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - - W3C(R) SOFTWARE NOTICE AND LICENSE - http://www.w3.org/Consortium/Legal/2002/copyright-software-20021231 - - This work (and included software, documentation such as READMEs, or - other related items) is being provided by the copyright holders under - the following license. By obtaining, using and/or copying this work, - you (the licensee) agree that you have read, understood, and will comply - with the following terms and conditions. - - Permission to copy, modify, and distribute this software and its - documentation, with or without modification, for any purpose and - without fee or royalty is hereby granted, provided that you include - the following on ALL copies of the software and documentation or - portions thereof, including modifications: - - 1. The full text of this NOTICE in a location viewable to users - of the redistributed or derivative work. - - 2. Any pre-existing intellectual property disclaimers, notices, - or terms and conditions. If none exist, the W3C Software Short - Notice should be included (hypertext is preferred, text is - permitted) within the body of any redistributed or derivative code. - - 3. Notice of any changes or modifications to the files, including - the date changes were made. (We recommend you provide URIs to the - location from which the code is derived.) - - THIS SOFTWARE AND DOCUMENTATION IS PROVIDED "AS IS," AND COPYRIGHT - HOLDERS MAKE NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, - INCLUDING BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS - FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF THE SOFTWARE OR - DOCUMENTATION WILL NOT INFRINGE ANY THIRD PARTY PATENTS, COPYRIGHTS, - TRADEMARKS OR OTHER RIGHTS. - - COPYRIGHT HOLDERS WILL NOT BE LIABLE FOR ANY DIRECT, INDIRECT, SPECIAL - OR CONSEQUENTIAL DAMAGES ARISING OUT OF ANY USE OF THE SOFTWARE OR - DOCUMENTATION. - - The name and trademarks of copyright holders may NOT be used in - advertising or publicity pertaining to the software without specific, - written prior permission. Title to copyright in this software and - any associated documentation will at all times remain with - copyright holders. - -PDFBox libraries (pdfbox, jempbox, fontbox) - - Copyright (c) 2002-2007, www.pdfbox.org - Copyright (c) 2006-2007, www.jempbox.org - All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: - - 1. Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - - 2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - - 3. Neither the name of pdfbox; nor the names of its contributors may be - used to endorse or promote products derived from this software without - specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - SUCH DAMAGE. - -Adobe Font Metrics (AFM) for PDF Core 14 Fonts - - This file and the 14 PostScript(R) AFM files it accompanies may be used, - copied, and distributed for any purpose and without charge, with or without - modification, provided that all copyright notices are retained; that the - AFM files are not distributed without this file; that all modifications - to this file or any of the AFM files are prominently noted in the modified - file(s); and that this paragraph is not modified. Adobe Systems has no - responsibility or obligation to support the use of the AFM files. - -CMaps for PDF Fonts (http://www.adobe.com/devnet/font/#pcfi and -ftp://ftp.oreilly.com/pub/examples/nutshell/cjkv/adobe/) - - Copyright 1990-2001 Adobe Systems Incorporated. - All Rights Reserved. - - Patents Pending - - NOTICE: All information contained herein is the property - of Adobe Systems Incorporated. - - Permission is granted for redistribution of this file - provided this copyright notice is maintained intact and - that the contents of this file are not altered in any - way from its original form. - - PostScript and Display PostScript are trademarks of - Adobe Systems Incorporated which may be registered in - certain jurisdictions. - -Glyphlist (http://www.adobe.com/devnet/opentype/archives/glyph.html) - - Copyright (c) 1997,1998,2002,2007 Adobe Systems Incorporated - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this documentation file to use, copy, publish, distribute, - sublicense, and/or sell copies of the documentation, and to permit - others to do the same, provided that: - - No modification, editing or other alteration of this document is - allowed; and - - The above copyright notice and this permission notice shall be - included in all copies of the documentation. - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this documentation file, to create their own derivative works - from the content of this document to use, copy, publish, distribute, - sublicense, and/or sell the derivative works, and to permit others to do - the same, provided that the derived work is not represented as being a - copy or version of this document. - - Adobe shall not be liable to any party for any loss of revenue or profit - or for indirect, incidental, special, consequential, or other similar - damages, whether based on tort (including without limitation negligence - or strict liability), contract or other legal or equitable grounds even - if Adobe has been advised or had reason to know of the possibility of - such damages. The Adobe materials are provided on an "AS IS" basis. - Adobe specifically disclaims all express, statutory, or implied - warranties relating to the Adobe materials, including but not limited to - those concerning merchantability or fitness for a particular purpose or - non-infringement of any third party rights regarding the Adobe - materials. - -The International Components for Unicode (http://site.icu-project.org/) - - Copyright (c) 1995-2009 International Business Machines Corporation - and others - - All rights reserved. - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - "Software"), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, and/or sell copies of the Software, and to permit persons - to whom the Software is furnished to do so, provided that the above - copyright notice(s) and this permission notice appear in all copies - of the Software and that both the above copyright notice(s) and this - permission notice appear in supporting documentation. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. - IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN THIS NOTICE - BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, - OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, - WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, - ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS - SOFTWARE. - - Except as contained in this notice, the name of a copyright holder shall - not be used in advertising or otherwise to promote the sale, use or other - dealings in this Software without prior written authorization of the - copyright holder. - -MIME type information from file-4.26.tar.gz (http://www.darwinsys.com/file/) - - Copyright (c) Ian F. Darwin 1986, 1987, 1989, 1990, 1991, 1992, 1994, 1995. - Software written by Ian F. Darwin and others; - maintained 1994- Christos Zoulas. - - This software is not subject to any export provision of the United States - Department of Commerce, and may be exported to any country or planet. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions - are met: - 1. Redistributions of source code must retain the above copyright - notice immediately at the beginning of the file, without modification, - this list of conditions, and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - - THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR - ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - SUCH DAMAGE. - -Metadata extractor library (metadata-extractor) - - This is public domain software - that is, you can do whatever you want - with it, and include it software that is licensed under the GNU or the - BSD license, or whatever other licence you choose, including proprietary - closed source licenses. I do ask that you leave this header in tact. - - If you make modifications to this code that you think would benefit the - wider community, please send me a copy and I'll post it on my site. - - If you make use of this code, I'd appreciate hearing about it. - metadata_extractor [at] drewnoakes [dot] com - Latest version of this software kept at - http://drewnoakes.com/ - -ASM bytecode manipulation library (asm) - - Copyright (c) 2000-2005 INRIA, France Telecom - All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions - are met: - - 1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - - 2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - - 3. Neither the name of the copyright holders nor the names of its - contributors may be used to endorse or promote products derived from - this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - THE POSSIBILITY OF SUCH DAMAGE. - -SLF4J libraries (slf4j-api, log4j-over-slf4j, jcl-over-slf4j) - - Copyright (c) 2004-2008 QOS.ch - All rights reserved. - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - "Software"), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be - included in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE - LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -Logback library (logback-core, logback-classic) - - Logback: the reliable, generic, fast and flexible logging framework. - Copyright (C) 1999-2009, QOS.ch. All rights reserved. - - This program and the accompanying materials are dual-licensed under - either the terms of the Eclipse Public License v1.0 as published by - the Eclipse Foundation - - or (per the licensee's choosing) - - under the terms of the GNU Lesser General Public License version 2.1 - as published by the Free Software Foundation. - -XML API library, org.w3c classes (xml-apis) - - DOM Java Language Binding: - http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113/java-binding.html - - W3C IPR SOFTWARE NOTICE - Copyright (C) 2000 World Wide Web Consortium, (Massachusetts Institute of - Technology, Institut National de Recherche en Informatique et en - Automatique, Keio University). All Rights Reserved. - - The DOM bindings are published under the W3C Software Copyright Notice - and License. The software license requires "Notice of any changes or - modifications to the W3C files, including the date changes were made." - Consequently, modified versions of the DOM bindings must document that - they do not conform to the W3C standard; in the case of the IDL binding, - the pragma prefix can no longer be 'w3c.org'; in the case of the Java - binding, the package names can no longer be in the 'org.w3c' package. - - Note: The original version of the W3C Software Copyright Notice and - License could be found at - http://www.w3.org/Consortium/Legal/copyright-software-19980720 - - Copyright (C) 1994-2000 World Wide Web Consortium, (Massachusetts - Institute of Technology, Institut National de Recherche en Informatique - et en Automatique, Keio University). All Rights Reserved. - http://www.w3.org/Consortium/Legal/ - - This W3C work (including software, documents, or other related items) is - being provided by the copyright holders under the following license. By - obtaining, using and/or copying this work, you (the licensee) agree that - you have read, understood, and will comply with the following terms and - conditions: - - Permission to use, copy, and modify this software and its documentation, - with or without modification, for any purpose and without fee or royalty - is hereby granted, provided that you include the following on ALL copies - of the software and documentation or portions thereof, including - modifications, that you make: - - 1. The full text of this NOTICE in a location viewable to users of the - redistributed or derivative work. - - 2. Any pre-existing intellectual property disclaimers, notices, or - terms and conditions. If none exist, a short notice of the following - form (hypertext is preferred, text is permitted) should be used - within the body of any redistributed or derivative code: - "Copyright (C) [$date-of-software] World Wide Web Consortium, - (Massachusetts Institute of Technology, Institut National de - Recherche en Informatique et en Automatique, Keio University). - All Rights Reserved. http://www.w3.org/Consortium/Legal/" - - 3. Notice of any changes or modifications to the W3C files, including - the date changes were made. (We recommend you provide URIs to the - location from which the code is derived.) - - THIS SOFTWARE AND DOCUMENTATION IS PROVIDED "AS IS," AND COPYRIGHT HOLDERS - MAKE NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT - NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR - PURPOSE OR THAT THE USE OF THE SOFTWARE OR DOCUMENTATION WILL NOT INFRINGE - ANY THIRD PARTY PATENTS, COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS. - - COPYRIGHT HOLDERS WILL NOT BE LIABLE FOR ANY DIRECT, INDIRECT, SPECIAL - OR CONSEQUENTIAL DAMAGES ARISING OUT OF ANY USE OF THE SOFTWARE OR - DOCUMENTATION. - - The name and trademarks of copyright holders may NOT be used in - advertising or publicity pertaining to the software without specific, - written prior permission. Title to copyright in this software and any - associated documentation will at all times remain with copyright holders. - -XML API library, org.xml.sax classes (xml-apis) - - SAX2 is Free! - - I hereby abandon any property rights to SAX 2.0 (the Simple API for - XML), and release all of the SAX 2.0 source code, compiled code, and - documentation contained in this distribution into the Public Domain. - SAX comes with NO WARRANTY or guarantee of fitness for any purpose. - - David Megginson, david@megginson.com - 2000-05-05 - -Concurrent library (concurrent-1.3.4.jar) - - http://g.oswego.edu/dl/classes/EDU/oswego/cs/dl/util/concurrent/intro.html - - All classes are released to the public domain and may be used for any - purpose whatsoever without permission or acknowledgment. Portions of - the CopyOnWriteArrayList and ConcurrentReaderHashMap classes are adapted - from Sun JDK source code. These are copyright of Sun Microsystems, Inc, - and are used with their kind permission, as described in this license: - - TECHNOLOGY LICENSE FROM SUN MICROSYSTEMS, INC. TO DOUG LEA - - Whereas Doug Lea desires to utlized certain Java Software technologies - in the util.concurrent technology; and Whereas Sun Microsystems, Inc. - ("Sun") desires that Doug Lea utilize certain Java Software technologies - in the util.concurrent technology; - - Therefore the parties agree as follows, effective May 31, 2002: - - "Java Software technologies" means - - classes/java/util/ArrayList.java, and - classes/java/util/HashMap.java. - - The Java Software technologies are Copyright (c) 1994-2000 Sun - Microsystems, Inc. All rights reserved. - - Sun hereby grants Doug Lea a non-exclusive, worldwide, non-transferrable - license to use, reproduce, create derivate works of, and distribute the - Java Software and derivative works thereof in source and binary forms - as part of a larger work, and to sublicense the right to use, reproduce - and distribute the Java Software and Doug Lea's derivative works as the - part of larger works through multiple tiers of sublicensees provided that - the following conditions are met: - - -Neither the name of or trademarks of Sun may be used to endorse or - promote products including or derived from the Java Software technology - without specific prior written permission; and - -Redistributions of source or binary code must contain the above - copyright notice, this notice and and the following disclaimers: - - This software is provided "AS IS," without a warranty of any kind. - ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, - INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A - PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN - MICROSYSTEMS, INC. AND ITS LICENSORS SHALL NOT BE LIABLE FOR ANY DAMAGES - SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING - THE SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN MICROSYSTEMS, INC. - OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR - DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, - HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF - THE USE OF OR INABILITY TO USE SOFTWARE, EVEN IF SUN MICROSYSTEMS, INC. - HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. - - You acknowledge that Software is not designed,licensed or intended for - use in the design, construction, operation or maintenance of any nuclear - facility. - -Office Open XML schemas (ooxml-schemas-1.0.jar) - - The Office Open XML schema definitions used by Apache POI are - a part of the Office Open XML ECMA Specification (ECMA-376, [1]). - As defined in section 9.4 of the ECMA bylaws [2], this specification - is available to all interested parties without restriction: - - 9.4 All documents when approved shall be made available to - all interested parties without restriction. - - Furthermore, both Microsoft and Adobe have granted patent licenses - to this work [3,4,5]. - - [1] http://www.ecma-international.org/publications/standards/Ecma-376.htm - [2] http://www.ecma-international.org/memento/Ecmabylaws.htm - [3] http://www.microsoft.com/interop/osp/ - [4] http://www.ecma-international.org/publications/files/ECMA-ST/Ecma%20PATENT/ECMA-376%20Edition%201%20Microsoft%20Patent%20Declaration.pdf - [5] http://www.ecma-international.org/publications/files/ECMA-ST/Ecma%20PATENT/ga-2006-191.pdf - -DOM4J library (dom4j-1.6.1.jar) - - Copyright 2001-2005 (C) MetaStuff, Ltd. All Rights Reserved. - - Redistribution and use of this software and associated documentation - ("Software"), with or without modification, are permitted provided - that the following conditions are met: - - 1. Redistributions of source code must retain copyright - statements and notices. Redistributions must also contain a - copy of this document. - - 2. Redistributions in binary form must reproduce the - above copyright notice, this list of conditions and the - following disclaimer in the documentation and/or other - materials provided with the distribution. - - 3. The name "DOM4J" must not be used to endorse or promote - products derived from this Software without prior written - permission of MetaStuff, Ltd. For written permission, - please contact dom4j-info@metastuff.com. - - 4. Products derived from this Software may not be called "DOM4J" - nor may "DOM4J" appear in their names without prior written - permission of MetaStuff, Ltd. DOM4J is a registered - trademark of MetaStuff, Ltd. - - 5. Due credit should be given to the DOM4J Project - - http://www.dom4j.org - - THIS SOFTWARE IS PROVIDED BY METASTUFF, LTD. AND CONTRIBUTORS - ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT - NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND - FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL - METASTUFF, LTD. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED - OF THE POSSIBILITY OF SUCH DAMAGE. - -Unicode conversion code in Lucene Java (lucene-core) - - Copyright 2001-2004 Unicode, Inc. - - Disclaimer - - This source code is provided as is by Unicode, Inc. No claims are - made as to fitness for any particular purpose. No warranties of any - kind are expressed or implied. The recipient agrees to determine - applicability of information provided. If this file has been - purchased on magnetic or optical media from Unicode, Inc., the - sole remedy for any claim will be exchange of defective media - within 90 days of receipt. - - Limitations on Rights to Redistribute This Code - - Unicode, Inc. hereby grants the right to freely use the information - supplied in this file in the creation of products supporting the - Unicode Standard, and to make copies of this file in any form - for internal or external distribution as long as this notice - remains attached. - -Array utility code in Lucene Java (lucene-core) - - PSF LICENSE AGREEMENT FOR PYTHON 2.4 - ------------------------------------ - - 1. This LICENSE AGREEMENT is between the Python Software Foundation - ("PSF"), and the Individual or Organization ("Licensee") accessing and - otherwise using Python 2.4 software in source or binary form and its - associated documentation. - - 2. Subject to the terms and conditions of this License Agreement, PSF - hereby grants Licensee a nonexclusive, royalty-free, world-wide - license to reproduce, analyze, test, perform and/or display publicly, - prepare derivative works, distribute, and otherwise use Python 2.4 - alone or in any derivative version, provided, however, that PSF's - License Agreement and PSF's notice of copyright, i.e., "Copyright (c) - 2001, 2002, 2003, 2004 Python Software Foundation; All Rights Reserved" - are retained in Python 2.4 alone or in any derivative version prepared - by Licensee. - - 3. In the event Licensee prepares a derivative work that is based on - or incorporates Python 2.4 or any part thereof, and wants to make - the derivative work available to others as provided herein, then - Licensee hereby agrees to include in any such work a brief summary of - the changes made to Python 2.4. - - 4. PSF is making Python 2.4 available to Licensee on an "AS IS" - basis. PSF MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR - IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, PSF MAKES NO AND - DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS - FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF PYTHON 2.4 WILL NOT - INFRINGE ANY THIRD PARTY RIGHTS. - - 5. PSF SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF PYTHON - 2.4 FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS - A RESULT OF MODIFYING, DISTRIBUTING, OR OTHERWISE USING PYTHON 2.4, - OR ANY DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF. - - 6. This License Agreement will automatically terminate upon a material - breach of its terms and conditions. - - 7. Nothing in this License Agreement shall be deemed to create any - relationship of agency, partnership, or joint venture between PSF and - Licensee. This License Agreement does not grant permission to use PSF - trademarks or trade name in a trademark sense to endorse or promote - products or services of Licensee, or any third party. - - 8. By copying, installing or otherwise using Python 2.4, Licensee - agrees to be bound by the terms and conditions of this License - Agreement. - - BEOPEN.COM LICENSE AGREEMENT FOR PYTHON 2.0 - ------------------------------------------- - - BEOPEN PYTHON OPEN SOURCE LICENSE AGREEMENT VERSION 1 - - 1. This LICENSE AGREEMENT is between BeOpen.com ("BeOpen"), having an - office at 160 Saratoga Avenue, Santa Clara, CA 95051, and the - Individual or Organization ("Licensee") accessing and otherwise using - this software in source or binary form and its associated - documentation ("the Software"). - - 2. Subject to the terms and conditions of this BeOpen Python License - Agreement, BeOpen hereby grants Licensee a non-exclusive, - royalty-free, world-wide license to reproduce, analyze, test, perform - and/or display publicly, prepare derivative works, distribute, and - otherwise use the Software alone or in any derivative version, - provided, however, that the BeOpen Python License is retained in the - Software, alone or in any derivative version prepared by Licensee. - - 3. BeOpen is making the Software available to Licensee on an "AS IS" - basis. BEOPEN MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR - IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, BEOPEN MAKES NO AND - DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS - FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF THE SOFTWARE WILL NOT - INFRINGE ANY THIRD PARTY RIGHTS. - - 4. BEOPEN SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF THE - SOFTWARE FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS - AS A RESULT OF USING, MODIFYING OR DISTRIBUTING THE SOFTWARE, OR ANY - DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF. - - 5. This License Agreement will automatically terminate upon a material - breach of its terms and conditions. - - 6. This License Agreement shall be governed by and interpreted in all - respects by the law of the State of California, excluding conflict of - law provisions. Nothing in this License Agreement shall be deemed to - create any relationship of agency, partnership, or joint venture - between BeOpen and Licensee. This License Agreement does not grant - permission to use BeOpen trademarks or trade names in a trademark - sense to endorse or promote products or services of Licensee, or any - third party. As an exception, the "BeOpen Python" logos available at - http://www.pythonlabs.com/logos.html may be used according to the - permissions granted on that web page. - - 7. By copying, installing or otherwise using the software, Licensee - agrees to be bound by the terms and conditions of this License - Agreement. - - CNRI LICENSE AGREEMENT FOR PYTHON 1.6.1 - --------------------------------------- - - 1. This LICENSE AGREEMENT is between the Corporation for National - Research Initiatives, having an office at 1895 Preston White Drive, - Reston, VA 20191 ("CNRI"), and the Individual or Organization - ("Licensee") accessing and otherwise using Python 1.6.1 software in - source or binary form and its associated documentation. - - 2. Subject to the terms and conditions of this License Agreement, CNRI - hereby grants Licensee a nonexclusive, royalty-free, world-wide - license to reproduce, analyze, test, perform and/or display publicly, - prepare derivative works, distribute, and otherwise use Python 1.6.1 - alone or in any derivative version, provided, however, that CNRI's - License Agreement and CNRI's notice of copyright, i.e., "Copyright (c) - 1995-2001 Corporation for National Research Initiatives; All Rights - Reserved" are retained in Python 1.6.1 alone or in any derivative - version prepared by Licensee. Alternately, in lieu of CNRI's License - Agreement, Licensee may substitute the following text (omitting the - quotes): "Python 1.6.1 is made available subject to the terms and - conditions in CNRI's License Agreement. This Agreement together with - Python 1.6.1 may be located on the Internet using the following - unique, persistent identifier (known as a handle): 1895.22/1013. This - Agreement may also be obtained from a proxy server on the Internet - using the following URL: http://hdl.handle.net/1895.22/1013". - - 3. In the event Licensee prepares a derivative work that is based on - or incorporates Python 1.6.1 or any part thereof, and wants to make - the derivative work available to others as provided herein, then - Licensee hereby agrees to include in any such work a brief summary of - the changes made to Python 1.6.1. - - 4. CNRI is making Python 1.6.1 available to Licensee on an "AS IS" - basis. CNRI MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR - IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, CNRI MAKES NO AND - DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS - FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF PYTHON 1.6.1 WILL NOT - INFRINGE ANY THIRD PARTY RIGHTS. - - 5. CNRI SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF PYTHON - 1.6.1 FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS - A RESULT OF MODIFYING, DISTRIBUTING, OR OTHERWISE USING PYTHON 1.6.1, - OR ANY DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF. - - 6. This License Agreement will automatically terminate upon a material - breach of its terms and conditions. - - 7. This License Agreement shall be governed by the federal - intellectual property law of the United States, including without - limitation the federal copyright law, and, to the extent such - U.S. federal law does not apply, by the law of the Commonwealth of - Virginia, excluding Virginia's conflict of law provisions. - Notwithstanding the foregoing, with regard to derivative works based - on Python 1.6.1 that incorporate non-separable material that was - previously distributed under the GNU General Public License (GPL), the - law of the Commonwealth of Virginia shall govern this License - Agreement only as to issues arising under or with respect to - Paragraphs 4, 5, and 7 of this License Agreement. Nothing in this - License Agreement shall be deemed to create any relationship of - agency, partnership, or joint venture between CNRI and Licensee. This - License Agreement does not grant permission to use CNRI trademarks or - trade name in a trademark sense to endorse or promote products or - services of Licensee, or any third party. - - 8. By clicking on the "ACCEPT" button where indicated, or by copying, - installing or otherwise using Python 1.6.1, Licensee agrees to be - bound by the terms and conditions of this License Agreement. - - ACCEPT - - - CWI LICENSE AGREEMENT FOR PYTHON 0.9.0 THROUGH 1.2 - -------------------------------------------------- - - Copyright (c) 1991 - 1995, Stichting Mathematisch Centrum Amsterdam, - The Netherlands. All rights reserved. - - Permission to use, copy, modify, and distribute this software and its - documentation for any purpose and without fee is hereby granted, - provided that the above copyright notice appear in all copies and that - both that copyright notice and this permission notice appear in - supporting documentation, and that the name of Stichting Mathematisch - Centrum or CWI not be used in advertising or publicity pertaining to - distribution of the software without specific, written prior - permission. - - STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO - THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND - FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE - FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT - OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -AspectJ runtime library (aspectjrt) - - Eclipse Public License - v 1.0 - - THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS ECLIPSE - PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF - THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT. - - 1. DEFINITIONS - - "Contribution" means: - - a) in the case of the initial Contributor, the initial code and - documentation distributed under this Agreement, and - - b) in the case of each subsequent Contributor: - - i) changes to the Program, and - - ii) additions to the Program; - - where such changes and/or additions to the Program originate from and - are distributed by that particular Contributor. A Contribution - 'originates' from a Contributor if it was added to the Program by - such Contributor itself or anyone acting on such Contributor's behalf. - Contributions do not include additions to the Program which: (i) are - separate modules of software distributed in conjunction with the - Program under their own license agreement, and (ii) are not derivative - works of the Program. - - "Contributor" means any person or entity that distributes the Program. - - "Licensed Patents " mean patent claims licensable by a Contributor which - are necessarily infringed by the use or sale of its Contribution alone or - when combined with the Program. - - "Program" means the Contributions distributed in accordance with this - Agreement. - - "Recipient" means anyone who receives the Program under this Agreement, - including all Contributors. - - 2. GRANT OF RIGHTS - - a) Subject to the terms of this Agreement, each Contributor hereby grants - Recipient a non-exclusive, worldwide, royalty-free copyright license to - reproduce, prepare derivative works of, publicly display, publicly - perform, distribute and sublicense the Contribution of such - Contributor, if any, and such derivative works, in source code and - object code form. - - b) Subject to the terms of this Agreement, each Contributor hereby grants - Recipient a non-exclusive, worldwide, royalty-free patent license under - Licensed Patents to make, use, sell, offer to sell, import and - otherwise transfer the Contribution of such Contributor, if any, in - source code and object code form. This patent license shall apply to - the combination of the Contribution and the Program if, at the time - the Contribution is added by the Contributor, such addition of the - Contribution causes such combination to be covered by the Licensed - Patents. The patent license shall not apply to any other combinations - which include the Contribution. No hardware per se is licensed hereunder. - - c) Recipient understands that although each Contributor grants the - licenses to its Contributions set forth herein, no assurances are - provided by any Contributor that the Program does not infringe the - patent or other intellectual property rights of any other entity. Each - Contributor disclaims any liability to Recipient for claims brought by - any other entity based on infringement of intellectual property rights - or otherwise. As a condition to exercising the rights and licenses - granted hereunder, each Recipient hereby assumes sole responsibility - to secure any other intellectual property rights needed, if any. For - example, if a third party patent license is required to allow Recipient - to distribute the Program, it is Recipient's responsibility to acquire - that license before distributing the Program. - - d) Each Contributor represents that to its knowledge it has sufficient - copyright rights in its Contribution, if any, to grant the copyright - license set forth in this Agreement. - - 3. REQUIREMENTS - - A Contributor may choose to distribute the Program in object code form - under its own license agreement, provided that: - - a) it complies with the terms and conditions of this Agreement; and - - b) its license agreement: - - i) effectively disclaims on behalf of all Contributors all warranties - and conditions, express and implied, including warranties or - conditions of title and non-infringement, and implied warranties - or conditions of merchantability and fitness for a particular - purpose; - - ii) effectively excludes on behalf of all Contributors all liability - for damages, including direct, indirect, special, incidental and - consequential damages, such as lost profits; - - iii) states that any provisions which differ from this Agreement are - offered by that Contributor alone and not by any other party; and - - iv) states that source code for the Program is available from such - Contributor, and informs licensees how to obtain it in a - reasonable manner on or through a medium customarily used for - software exchange. - - When the Program is made available in source code form: - - a) it must be made available under this Agreement; and - - b) a copy of this Agreement must be included with each copy of the - Program. - - Contributors may not remove or alter any copyright notices contained - within the Program. - - Each Contributor must identify itself as the originator of its - Contribution, if any, in a manner that reasonably allows subsequent - Recipients to identify the originator of the Contribution. - - 4. COMMERCIAL DISTRIBUTION - - Commercial distributors of software may accept certain responsibilities - with respect to end users, business partners and the like. While this - license is intended to facilitate the commercial use of the Program, - the Contributor who includes the Program in a commercial product offering - should do so in a manner which does not create potential liability for - other Contributors. Therefore, if a Contributor includes the Program in - a commercial product offering, such Contributor ("Commercial Contributor") - hereby agrees to defend and indemnify every other Contributor - ("Indemnified Contributor") against any losses, damages and costs - (collectively "Losses") arising from claims, lawsuits and other legal - actions brought by a third party against the Indemnified Contributor to - the extent caused by the acts or omissions of such Commercial Contributor - in connection with its distribution of the Program in a commercial - product offering. The obligations in this section do not apply to any - claims or Losses relating to any actual or alleged intellectual property - infringement. In order to qualify, an Indemnified Contributor must: - a) promptly notify the Commercial Contributor in writing of such claim, - and b) allow the Commercial Contributor to control, and cooperate with - the Commercial Contributor in, the defense and any related settlement - negotiations. The Indemnified Contributor may participate in any such - claim at its own expense. - - For example, a Contributor might include the Program in a commercial - product offering, Product X. That Contributor is then a Commercial - Contributor. If that Commercial Contributor then makes performance claims, - or offers warranties related to Product X, those performance claims and - warranties are such Commercial Contributor's responsibility alone. Under - this section, the Commercial Contributor would have to defend claims - against the other Contributors related to those performance claims and - warranties, and if a court requires any other Contributor to pay any - damages as a result, the Commercial Contributor must pay those damages. - - 5. NO WARRANTY - - EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS PROVIDED - ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER - EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR - CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A - PARTICULAR PURPOSE. Each Recipient is solely responsible for determining - the appropriateness of using and distributing the Program and assumes all - risks associated with its exercise of rights under this Agreement , - including but not limited to the risks and costs of program errors, - compliance with applicable laws, damage to or loss of data, programs or - equipment, and unavailability or interruption of operations. - - 6. DISCLAIMER OF LIABILITY - - EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR - ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, - INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING - WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF - LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OR - DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED - HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. - - 7. GENERAL - - If any provision of this Agreement is invalid or unenforceable under - applicable law, it shall not affect the validity or enforceability of - the remainder of the terms of this Agreement, and without further action - by the parties hereto, such provision shall be reformed to the minimum - extent necessary to make such provision valid and enforceable. - - If Recipient institutes patent litigation against any entity (including - a cross-claim or counterclaim in a lawsuit) alleging that the Program - itself (excluding combinations of the Program with other software or - hardware) infringes such Recipient's patent(s), then such Recipient's - rights granted under Section 2(b) shall terminate as of the date such - litigation is filed. - - All Recipient's rights under this Agreement shall terminate if it fails - to comply with any of the material terms or conditions of this Agreement - and does not cure such failure in a reasonable period of time after - becoming aware of such noncompliance. If all Recipient's rights under - this Agreement terminate, Recipient agrees to cease use and distribution - of the Program as soon as reasonably practicable. However, Recipient's - obligations under this Agreement and any licenses granted by Recipient - relating to the Program shall continue and survive. - - Everyone is permitted to copy and distribute copies of this Agreement, - but in order to avoid inconsistency the Agreement is copyrighted and may - only be modified in the following manner. The Agreement Steward reserves - the right to publish new versions (including revisions) of this Agreement - from time to time. No one other than the Agreement Steward has the right - to modify this Agreement. The Eclipse Foundation is the initial Agreement - Steward. The Eclipse Foundation may assign the responsibility to serve as - the Agreement Steward to a suitable separate entity. Each new version of - the Agreement will be given a distinguishing version number. The Program - (including Contributions) may always be distributed subject to the version - of the Agreement under which it was received. In addition, after a new - version of the Agreement is published, Contributor may elect to distribute - the Program (including its Contributions) under the new version. Except as - expressly stated in Sections 2(a) and 2(b) above, Recipient receives no - rights or licenses to the intellectual property of any Contributor under - this Agreement, whether expressly, by implication, estoppel or otherwise. - All rights in the Program not expressly granted under this Agreement - are reserved. - - This Agreement is governed by the laws of the State of New York and the - intellectual property laws of the United States of America. No party to - this Agreement will bring a legal action under this Agreement more than - one year after the cause of action arose. Each party waives its rights to - a jury trial in any resulting litigation. - -juniversalchardet library (juniversalchardet) - - MOZILLA PUBLIC LICENSE - Version 1.1 - - --------------- - - 1. Definitions. - - 1.0.1. "Commercial Use" means distribution or otherwise making the - Covered Code available to a third party. - - 1.1. "Contributor" means each entity that creates or contributes to - the creation of Modifications. - - 1.2. "Contributor Version" means the combination of the Original - Code, prior Modifications used by a Contributor, and the Modifications - made by that particular Contributor. - - 1.3. "Covered Code" means the Original Code or Modifications or the - combination of the Original Code and Modifications, in each case - including portions thereof. - - 1.4. "Electronic Distribution Mechanism" means a mechanism generally - accepted in the software development community for the electronic - transfer of data. - - 1.5. "Executable" means Covered Code in any form other than Source - Code. - - 1.6. "Initial Developer" means the individual or entity identified - as the Initial Developer in the Source Code notice required by Exhibit - A. - - 1.7. "Larger Work" means a work which combines Covered Code or - portions thereof with code not governed by the terms of this License. - - 1.8. "License" means this document. - - 1.8.1. "Licensable" means having the right to grant, to the maximum - extent possible, whether at the time of the initial grant or - subsequently acquired, any and all of the rights conveyed herein. - - 1.9. "Modifications" means any addition to or deletion from the - substance or structure of either the Original Code or any previous - Modifications. When Covered Code is released as a series of files, a - Modification is: - A. Any addition to or deletion from the contents of a file - containing Original Code or previous Modifications. - - B. Any new file that contains any part of the Original Code or - previous Modifications. - - 1.10. "Original Code" means Source Code of computer software code - which is described in the Source Code notice required by Exhibit A as - Original Code, and which, at the time of its release under this - License is not already Covered Code governed by this License. - - 1.10.1. "Patent Claims" means any patent claim(s), now owned or - hereafter acquired, including without limitation, method, process, - and apparatus claims, in any patent Licensable by grantor. - - 1.11. "Source Code" means the preferred form of the Covered Code for - making modifications to it, including all modules it contains, plus - any associated interface definition files, scripts used to control - compilation and installation of an Executable, or source code - differential comparisons against either the Original Code or another - well known, available Covered Code of the Contributor's choice. The - Source Code can be in a compressed or archival form, provided the - appropriate decompression or de-archiving software is widely available - for no charge. - - 1.12. "You" (or "Your") means an individual or a legal entity - exercising rights under, and complying with all of the terms of, this - License or a future version of this License issued under Section 6.1. - For legal entities, "You" includes any entity which controls, is - controlled by, or is under common control with You. For purposes of - this definition, "control" means (a) the power, direct or indirect, - to cause the direction or management of such entity, whether by - contract or otherwise, or (b) ownership of more than fifty percent - (50%) of the outstanding shares or beneficial ownership of such - entity. - - 2. Source Code License. - - 2.1. The Initial Developer Grant. - The Initial Developer hereby grants You a world-wide, royalty-free, - non-exclusive license, subject to third party intellectual property - claims: - (a) under intellectual property rights (other than patent or - trademark) Licensable by Initial Developer to use, reproduce, - modify, display, perform, sublicense and distribute the Original - Code (or portions thereof) with or without Modifications, and/or - as part of a Larger Work; and - - (b) under Patents Claims infringed by the making, using or - selling of Original Code, to make, have made, use, practice, - sell, and offer for sale, and/or otherwise dispose of the - Original Code (or portions thereof). - - (c) the licenses granted in this Section 2.1(a) and (b) are - effective on the date Initial Developer first distributes - Original Code under the terms of this License. - - (d) Notwithstanding Section 2.1(b) above, no patent license is - granted: 1) for code that You delete from the Original Code; 2) - separate from the Original Code; or 3) for infringements caused - by: i) the modification of the Original Code or ii) the - combination of the Original Code with other software or devices. - - 2.2. Contributor Grant. - Subject to third party intellectual property claims, each Contributor - hereby grants You a world-wide, royalty-free, non-exclusive license - - (a) under intellectual property rights (other than patent or - trademark) Licensable by Contributor, to use, reproduce, modify, - display, perform, sublicense and distribute the Modifications - created by such Contributor (or portions thereof) either on an - unmodified basis, with other Modifications, as Covered Code - and/or as part of a Larger Work; and - - (b) under Patent Claims infringed by the making, using, or - selling of Modifications made by that Contributor either alone - and/or in combination with its Contributor Version (or portions - of such combination), to make, use, sell, offer for sale, have - made, and/or otherwise dispose of: 1) Modifications made by that - Contributor (or portions thereof); and 2) the combination of - Modifications made by that Contributor with its Contributor - Version (or portions of such combination). - - (c) the licenses granted in Sections 2.2(a) and 2.2(b) are - effective on the date Contributor first makes Commercial Use of - the Covered Code. - - (d) Notwithstanding Section 2.2(b) above, no patent license is - granted: 1) for any code that Contributor has deleted from the - Contributor Version; 2) separate from the Contributor Version; - 3) for infringements caused by: i) third party modifications of - Contributor Version or ii) the combination of Modifications made - by that Contributor with other software (except as part of the - Contributor Version) or other devices; or 4) under Patent Claims - infringed by Covered Code in the absence of Modifications made by - that Contributor. - - 3. Distribution Obligations. - - 3.1. Application of License. - The Modifications which You create or to which You contribute are - governed by the terms of this License, including without limitation - Section 2.2. The Source Code version of Covered Code may be - distributed only under the terms of this License or a future version - of this License released under Section 6.1, and You must include a - copy of this License with every copy of the Source Code You - distribute. You may not offer or impose any terms on any Source Code - version that alters or restricts the applicable version of this - License or the recipients' rights hereunder. However, You may include - an additional document offering the additional rights described in - Section 3.5. - - 3.2. Availability of Source Code. - Any Modification which You create or to which You contribute must be - made available in Source Code form under the terms of this License - either on the same media as an Executable version or via an accepted - Electronic Distribution Mechanism to anyone to whom you made an - Executable version available; and if made available via Electronic - Distribution Mechanism, must remain available for at least twelve (12) - months after the date it initially became available, or at least six - (6) months after a subsequent version of that particular Modification - has been made available to such recipients. You are responsible for - ensuring that the Source Code version remains available even if the - Electronic Distribution Mechanism is maintained by a third party. - - 3.3. Description of Modifications. - You must cause all Covered Code to which You contribute to contain a - file documenting the changes You made to create that Covered Code and - the date of any change. You must include a prominent statement that - the Modification is derived, directly or indirectly, from Original - Code provided by the Initial Developer and including the name of the - Initial Developer in (a) the Source Code, and (b) in any notice in an - Executable version or related documentation in which You describe the - origin or ownership of the Covered Code. - - 3.4. Intellectual Property Matters - (a) Third Party Claims. - If Contributor has knowledge that a license under a third party's - intellectual property rights is required to exercise the rights - granted by such Contributor under Sections 2.1 or 2.2, - Contributor must include a text file with the Source Code - distribution titled "LEGAL" which describes the claim and the - party making the claim in sufficient detail that a recipient will - know whom to contact. If Contributor obtains such knowledge after - the Modification is made available as described in Section 3.2, - Contributor shall promptly modify the LEGAL file in all copies - Contributor makes available thereafter and shall take other steps - (such as notifying appropriate mailing lists or newsgroups) - reasonably calculated to inform those who received the Covered - Code that new knowledge has been obtained. - - (b) Contributor APIs. - If Contributor's Modifications include an application programming - interface and Contributor has knowledge of patent licenses which - are reasonably necessary to implement that API, Contributor must - also include this information in the LEGAL file. - - (c) Representations. - Contributor represents that, except as disclosed pursuant to - Section 3.4(a) above, Contributor believes that Contributor's - Modifications are Contributor's original creation(s) and/or - Contributor has sufficient rights to grant the rights conveyed by - this License. - - 3.5. Required Notices. - You must duplicate the notice in Exhibit A in each file of the Source - Code. If it is not possible to put such notice in a particular Source - Code file due to its structure, then You must include such notice in a - location (such as a relevant directory) where a user would be likely - to look for such a notice. If You created one or more Modification(s) - You may add your name as a Contributor to the notice described in - Exhibit A. You must also duplicate this License in any documentation - for the Source Code where You describe recipients' rights or ownership - rights relating to Covered Code. You may choose to offer, and to - charge a fee for, warranty, support, indemnity or liability - obligations to one or more recipients of Covered Code. However, You - may do so only on Your own behalf, and not on behalf of the Initial - Developer or any Contributor. You must make it absolutely clear than - any such warranty, support, indemnity or liability obligation is - offered by You alone, and You hereby agree to indemnify the Initial - Developer and every Contributor for any liability incurred by the - Initial Developer or such Contributor as a result of warranty, - support, indemnity or liability terms You offer. - - 3.6. Distribution of Executable Versions. - You may distribute Covered Code in Executable form only if the - requirements of Section 3.1-3.5 have been met for that Covered Code, - and if You include a notice stating that the Source Code version of - the Covered Code is available under the terms of this License, - including a description of how and where You have fulfilled the - obligations of Section 3.2. The notice must be conspicuously included - in any notice in an Executable version, related documentation or - collateral in which You describe recipients' rights relating to the - Covered Code. You may distribute the Executable version of Covered - Code or ownership rights under a license of Your choice, which may - contain terms different from this License, provided that You are in - compliance with the terms of this License and that the license for the - Executable version does not attempt to limit or alter the recipient's - rights in the Source Code version from the rights set forth in this - License. If You distribute the Executable version under a different - license You must make it absolutely clear that any terms which differ - from this License are offered by You alone, not by the Initial - Developer or any Contributor. You hereby agree to indemnify the - Initial Developer and every Contributor for any liability incurred by - the Initial Developer or such Contributor as a result of any such - terms You offer. - - 3.7. Larger Works. - You may create a Larger Work by combining Covered Code with other code - not governed by the terms of this License and distribute the Larger - Work as a single product. In such a case, You must make sure the - requirements of this License are fulfilled for the Covered Code. - - 4. Inability to Comply Due to Statute or Regulation. - - If it is impossible for You to comply with any of the terms of this - License with respect to some or all of the Covered Code due to - statute, judicial order, or regulation then You must: (a) comply with - the terms of this License to the maximum extent possible; and (b) - describe the limitations and the code they affect. Such description - must be included in the LEGAL file described in Section 3.4 and must - be included with all distributions of the Source Code. Except to the - extent prohibited by statute or regulation, such description must be - sufficiently detailed for a recipient of ordinary skill to be able to - understand it. - - 5. Application of this License. - - This License applies to code to which the Initial Developer has - attached the notice in Exhibit A and to related Covered Code. - - 6. Versions of the License. - - 6.1. New Versions. - Netscape Communications Corporation ("Netscape") may publish revised - and/or new versions of the License from time to time. Each version - will be given a distinguishing version number. - - 6.2. Effect of New Versions. - Once Covered Code has been published under a particular version of the - License, You may always continue to use it under the terms of that - version. You may also choose to use such Covered Code under the terms - of any subsequent version of the License published by Netscape. No one - other than Netscape has the right to modify the terms applicable to - Covered Code created under this License. - - 6.3. Derivative Works. - If You create or use a modified version of this License (which you may - only do in order to apply it to code which is not already Covered Code - governed by this License), You must (a) rename Your license so that - the phrases "Mozilla", "MOZILLAPL", "MOZPL", "Netscape", - "MPL", "NPL" or any confusingly similar phrase do not appear in your - license (except to note that your license differs from this License) - and (b) otherwise make it clear that Your version of the license - contains terms which differ from the Mozilla Public License and - Netscape Public License. (Filling in the name of the Initial - Developer, Original Code or Contributor in the notice described in - Exhibit A shall not of themselves be deemed to be modifications of - this License.) - - 7. DISCLAIMER OF WARRANTY. - - COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, - WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, - WITHOUT LIMITATION, WARRANTIES THAT THE COVERED CODE IS FREE OF - DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE OR NON-INFRINGING. - THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED CODE - IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, - YOU (NOT THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE - COST OF ANY NECESSARY SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER - OF WARRANTY CONSTITUTES AN ESSENTIAL PART OF THIS LICENSE. NO USE OF - ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER THIS DISCLAIMER. - - 8. TERMINATION. - - 8.1. This License and the rights granted hereunder will terminate - automatically if You fail to comply with terms herein and fail to cure - such breach within 30 days of becoming aware of the breach. All - sublicenses to the Covered Code which are properly granted shall - survive any termination of this License. Provisions which, by their - nature, must remain in effect beyond the termination of this License - shall survive. - - 8.2. If You initiate litigation by asserting a patent infringement - claim (excluding declatory judgment actions) against Initial Developer - or a Contributor (the Initial Developer or Contributor against whom - You file such action is referred to as "Participant") alleging that: - - (a) such Participant's Contributor Version directly or indirectly - infringes any patent, then any and all rights granted by such - Participant to You under Sections 2.1 and/or 2.2 of this License - shall, upon 60 days notice from Participant terminate prospectively, - unless if within 60 days after receipt of notice You either: (i) - agree in writing to pay Participant a mutually agreeable reasonable - royalty for Your past and future use of Modifications made by such - Participant, or (ii) withdraw Your litigation claim with respect to - the Contributor Version against such Participant. If within 60 days - of notice, a reasonable royalty and payment arrangement are not - mutually agreed upon in writing by the parties or the litigation claim - is not withdrawn, the rights granted by Participant to You under - Sections 2.1 and/or 2.2 automatically terminate at the expiration of - the 60 day notice period specified above. - - (b) any software, hardware, or device, other than such Participant's - Contributor Version, directly or indirectly infringes any patent, then - any rights granted to You by such Participant under Sections 2.1(b) - and 2.2(b) are revoked effective as of the date You first made, used, - sold, distributed, or had made, Modifications made by that - Participant. - - 8.3. If You assert a patent infringement claim against Participant - alleging that such Participant's Contributor Version directly or - indirectly infringes any patent where such claim is resolved (such as - by license or settlement) prior to the initiation of patent - infringement litigation, then the reasonable value of the licenses - granted by such Participant under Sections 2.1 or 2.2 shall be taken - into account in determining the amount or value of any payment or - license. - - 8.4. In the event of termination under Sections 8.1 or 8.2 above, - all end user license agreements (excluding distributors and resellers) - which have been validly granted by You or any distributor hereunder - prior to termination shall survive termination. - - 9. LIMITATION OF LIABILITY. - - UNDER NO CIRCUMSTANCES AND UNDER NO LEGAL THEORY, WHETHER TORT - (INCLUDING NEGLIGENCE), CONTRACT, OR OTHERWISE, SHALL YOU, THE INITIAL - DEVELOPER, ANY OTHER CONTRIBUTOR, OR ANY DISTRIBUTOR OF COVERED CODE, - OR ANY SUPPLIER OF ANY OF SUCH PARTIES, BE LIABLE TO ANY PERSON FOR - ANY INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES OF ANY - CHARACTER INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF GOODWILL, - WORK STOPPAGE, COMPUTER FAILURE OR MALFUNCTION, OR ANY AND ALL OTHER - COMMERCIAL DAMAGES OR LOSSES, EVEN IF SUCH PARTY SHALL HAVE BEEN - INFORMED OF THE POSSIBILITY OF SUCH DAMAGES. THIS LIMITATION OF - LIABILITY SHALL NOT APPLY TO LIABILITY FOR DEATH OR PERSONAL INJURY - RESULTING FROM SUCH PARTY'S NEGLIGENCE TO THE EXTENT APPLICABLE LAW - PROHIBITS SUCH LIMITATION. SOME JURISDICTIONS DO NOT ALLOW THE - EXCLUSION OR LIMITATION OF INCIDENTAL OR CONSEQUENTIAL DAMAGES, SO - THIS EXCLUSION AND LIMITATION MAY NOT APPLY TO YOU. - - 10. U.S. GOVERNMENT END USERS. - - The Covered Code is a "commercial item," as that term is defined in - 48 C.F.R. 2.101 (Oct. 1995), consisting of "commercial computer - software" and "commercial computer software documentation," as such - terms are used in 48 C.F.R. 12.212 (Sept. 1995). Consistent with 48 - C.F.R. 12.212 and 48 C.F.R. 227.7202-1 through 227.7202-4 (June 1995), - all U.S. Government End Users acquire Covered Code with only those - rights set forth herein. - - 11. MISCELLANEOUS. - - This License represents the complete agreement concerning subject - matter hereof. If any provision of this License is held to be - unenforceable, such provision shall be reformed only to the extent - necessary to make it enforceable. This License shall be governed by - California law provisions (except to the extent applicable law, if - any, provides otherwise), excluding its conflict-of-law provisions. - With respect to disputes in which at least one party is a citizen of, - or an entity chartered or registered to do business in the United - States of America, any litigation relating to this License shall be - subject to the jurisdiction of the Federal Courts of the Northern - District of California, with venue lying in Santa Clara County, - California, with the losing party responsible for costs, including - without limitation, court costs and reasonable attorneys' fees and - expenses. The application of the United Nations Convention on - Contracts for the International Sale of Goods is expressly excluded. - Any law or regulation which provides that the language of a contract - shall be construed against the drafter shall not apply to this - License. - - 12. RESPONSIBILITY FOR CLAIMS. - - As between Initial Developer and the Contributors, each party is - responsible for claims and damages arising, directly or indirectly, - out of its utilization of rights under this License and You agree to - work with Initial Developer and Contributors to distribute such - responsibility on an equitable basis. Nothing herein is intended or - shall be deemed to constitute any admission of liability. - - 13. MULTIPLE-LICENSED CODE. - - Initial Developer may designate portions of the Covered Code as - "Multiple-Licensed". "Multiple-Licensed" means that the Initial - Developer permits you to utilize portions of the Covered Code under - Your choice of the NPL or the alternative licenses, if any, specified - by the Initial Developer in the file described in Exhibit A. - - EXHIBIT A -Mozilla Public License. - - ``The contents of this file are subject to the Mozilla Public License - Version 1.1 (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.mozilla.org/MPL/ - - Software distributed under the License is distributed on an "AS IS" - basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the - License for the specific language governing rights and limitations - under the License. - - The Original Code is ______________________________________. - - The Initial Developer of the Original Code is ________________________. - Portions created by ______________________ are Copyright (C) ______ - _______________________. All Rights Reserved. - - Contributor(s): ______________________________________. - - Alternatively, the contents of this file may be used under the terms - of the _____ license (the "[___] License"), in which case the - provisions of [______] License are applicable instead of those - above. If you wish to allow use of your version of this file only - under the terms of the [____] License and not to allow others to use - your version of this file under the MPL, indicate your decision by - deleting the provisions above and replace them with the notice and - other provisions required by the [___] License. If you do not delete - the provisions above, a recipient may use your version of this file - under either the MPL or the [___] License." - - [NOTE: The text of this Exhibit A may differ slightly from the text of - the notices in the Source Code files of the Original Code. You should - use the text of this Exhibit A rather than the text found in the - Original Code Source Code for Your Modifications.] Property changes on: jackrabbit-webapp/src/main/webapp/META-INF/LICENSE ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Deleted: svn:keywords ## -1 +0,0 ## -author date id revision \ No newline at end of property Index: jackrabbit-webapp/src/main/webapp/META-INF/NOTICE =================================================================== --- jackrabbit-webapp/src/main/webapp/META-INF/NOTICE (revision 1907912) +++ jackrabbit-webapp/src/main/webapp/META-INF/NOTICE (nonexistent) @@ -1,41 +0,0 @@ -Apache Jackrabbit -Copyright 2010 The Apache Software Foundation - -This product includes software developed at -The Apache Software Foundation (http://www.apache.org/). - -Based on source code originally developed by -Day Software (http://www.day.com/). - -This product includes software from the following contributions: - -Original BZip2 classes contributed by Keiron Liddle -, Aftex Software to the Apache Ant project - -Original Tar classes from contributors of the Apache Ant project - -Original Zip classes from contributors of the Apache Ant project - -Original CPIO classes contributed by Markus Kuss and the jRPM project -(jrpm.sourceforge.net) - -Portions of Derby were originally developed by International Business -Machines Corporation and are licensed to the Apache Software Foundation -under the "Software Grant and Corporate Contribution License Agreement", -informally known as the "Derby CLA". The following copyright notice(s) -were affixed to portions of the code with which this file is now or was -at one time distributed and are placed here unaltered. - - (C) Copyright 1997,2004 International Business Machines Corporation. - All rights reserved. - - (C) Copyright IBM Corp. 2003. - -The JDBC apis for small devices and JDBC3 (under java/stubs/jsr169 and -java/stubs/jdbc3) were produced by trimming sources supplied by the -Apache Harmony project. The following notice covers the Harmony sources: - - Portions of Harmony were originally developed by - Intel Corporation and are licensed to the Apache Software - Foundation under the "Software Grant and Corporate Contribution - License Agreement", informally known as the "Intel Harmony CLA". Property changes on: jackrabbit-webapp/src/main/webapp/META-INF/NOTICE ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Deleted: svn:keywords ## -1 +0,0 ## -author date id revision \ No newline at end of property Index: jackrabbit-webapp/src/main/webapp/WEB-INF/batchread.properties =================================================================== --- jackrabbit-webapp/src/main/webapp/WEB-INF/batchread.properties (revision 1907912) +++ jackrabbit-webapp/src/main/webapp/WEB-INF/batchread.properties (nonexistent) @@ -1,27 +0,0 @@ -# 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. - -# This file contains an example batch read configuration used by -# JcrRemotingServlet according to the 'batchread-config' init-param. -# -# key = node type name -# value = desired depth for any node having the node type as primary type. -# -# - Use 'default' to set the default depth -# - Depth may be any int >= -1. -# - Depth -1 indicates infinite depth. - -default=5 -nt\:file=-1 \ No newline at end of file Property changes on: jackrabbit-webapp/src/main/webapp/WEB-INF/batchread.properties ___________________________________________________________________ Deleted: svn Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-webapp/src/main/webapp/WEB-INF/config.xml =================================================================== --- jackrabbit-webapp/src/main/webapp/WEB-INF/config.xml (revision 1907912) +++ jackrabbit-webapp/src/main/webapp/WEB-INF/config.xml (nonexistent) @@ -1,184 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - nt:file - nt:resource - - - - - - - - - - - - - rep - jcr - - - - - - Property changes on: jackrabbit-webapp/src/main/webapp/WEB-INF/config.xml ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-webapp/src/main/webapp/WEB-INF/protectedHandlers.properties =================================================================== --- jackrabbit-webapp/src/main/webapp/WEB-INF/protectedHandlers.properties (revision 1907912) +++ jackrabbit-webapp/src/main/webapp/WEB-INF/protectedHandlers.properties (nonexistent) @@ -1,17 +0,0 @@ -# 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. - -# ProtectedItemRemoveHandler implementation class -javax.jcr.tck.access.control.list.handler=org.apache.jackrabbit.server.remoting.davex.AclRemoveHandler Index: jackrabbit-webapp/src/main/webapp/WEB-INF/templates/bootstrap.properties =================================================================== --- jackrabbit-webapp/src/main/webapp/WEB-INF/templates/bootstrap.properties (revision 1907912) +++ jackrabbit-webapp/src/main/webapp/WEB-INF/templates/bootstrap.properties (nonexistent) @@ -1,39 +0,0 @@ -# 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. - -# This is the template file for the 'bootstrap.properties' that will -# be placed in the repository home directory (or whatever is specified -# in the "bootstrap-config" init parameter. - -# Repository configuration settings (will be adjusted by installer) -repository.config=jackrabbit/repository/repository.xml -repository.home=jackrabbit/repository -repository.name=jackrabbit.repository - -# RMI Settings -rmi.enabled=true -rmi.port=0 -rmi.host=localhost -# If the URI is not specified, it's composed as follows: -#rmi.uri=//${rmi.host}:${rmi.port}/${repository.name} - -# JNDI Settings -# all properties starting with 'java.naming.' will go into the -# environment of the initial context -jndi.enabled=true -# if the name is not specified, it's initialized with the repository.name -#jndi.name=${repository.name} -java.naming.provider.url=http://www.apache.org/jackrabbit -java.naming.factory.initial=org.apache.jackrabbit.core.jndi.provider.DummyInitialContextFactory Property changes on: jackrabbit-webapp/src/main/webapp/WEB-INF/templates/bootstrap.properties ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-webapp/src/main/webapp/WEB-INF/web.xml =================================================================== --- jackrabbit-webapp/src/main/webapp/WEB-INF/web.xml (revision 1907912) +++ jackrabbit-webapp/src/main/webapp/WEB-INF/web.xml (nonexistent) @@ -1,407 +0,0 @@ - - - - - - Jackrabbit JCR Server - - - - - - org.apache.jackrabbit.j2ee.DerbyShutdown - - - - - - - - RepositoryStartup - - Repository servlet that starts the repository and registers it to JNDI ans RMI. - If you already have the repository registered in this appservers JNDI context, - or if its accessible via RMI, you do not need to use this servlet. - - org.apache.jackrabbit.j2ee.RepositoryStartupServlet - - - bootstrap-config - jackrabbit/bootstrap.properties - - Property file that hold the same initialization properties than - the init-params below. If a parameter is specified in both - places the one in the bootstrap-config wins. - - - - - - - - - - 2 - - - - - - - - Repository - - This servlet provides other servlets and jsps a common way to access - the repository. The repository can be accessed via JNDI, RMI or Webdav. - - org.apache.jackrabbit.j2ee.RepositoryAccessServlet - - - bootstrap-config - jackrabbit/bootstrap.properties - - Property file that hold the same initialization properties than - the init-params below. If a parameter is specified in both - places the one in the bootstrap-config wins. - - - - - - - - - - 3 - - - - - - - Webdav - - The webdav servlet that connects HTTP request to the repository. - - org.apache.jackrabbit.j2ee.SimpleWebdavServlet - - - resource-path-prefix - /repository - - defines the prefix for spooling resources out of the repository. - - - - - - - - resource-config - /WEB-INF/config.xml - - Defines various dav-resource configuration parameters. - - - - - 4 - - - - - - - JCRWebdavServer - - The servlet used to remote JCR calls over HTTP. - - org.apache.jackrabbit.j2ee.JcrRemotingServlet - - missing-auth-mapping - - - Defines how a missing authorization header should be handled. - 1) If this init-param is missing, a 401 response is generated. - This is suitable for clients (eg. webdav clients) for which - sending a proper authorization header is not possible if the - server never sent a 401. - 2) If this init-param is present with an empty value, - null-credentials are returned, thus forcing an null login - on the repository. - 3) If this init-param is present with the value 'guestcredentials' - java.jcr.GuestCredentials are used to login to the repository. - 4) If this init-param has a 'user:password' value, the respective - simple credentials are generated. - - - - - - resource-path-prefix - /server - - defines the prefix for spooling resources out of the repository. - - - - - - batchread-config - /WEB-INF/batchread.properties - JcrRemotingServlet: Optional mapping from node type names to default depth. - - - protectedhandlers-config - /WEB-INF/protectedHandlersConfig.xml - JcrRemotingServlet: Handlers for removing protected items. - - - - 5 - - - - - - - RMI - org.apache.jackrabbit.servlet.remote.RemoteBindingServlet - - - - - - - RepositoryStartup - /admin/* - - - Webdav - /repository/* - - - JCRWebdavServer - /server/* - - - RMI - /rmi - - - - - - - index.jsp - - - - org.apache.jackrabbit.j2ee.JcrApiNotFoundException - /error/classpath.jsp - - - javax.jcr.RepositoryException - /error/repository.jsp - - - Property changes on: jackrabbit-webapp/src/main/webapp/WEB-INF/web.xml ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-webapp/src/main/webapp/about.jsp =================================================================== --- jackrabbit-webapp/src/main/webapp/about.jsp (revision 1907912) +++ jackrabbit-webapp/src/main/webapp/about.jsp (nonexistent) @@ -1,73 +0,0 @@ -<%-- - 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. ---%><%@page import="java.io.InputStream, - java.io.InputStreamReader, - java.io.Reader"%><%! - - /** - * Escapes and outputs the contents of a given (UTF-8) text resource. - * TODO: There should be an easier way to do this! - * - * @param path path of the resource to output - * @param out the JSP output writer - * @throws Exception if something goes wrong - */ - private void output(String path, JspWriter out) throws Exception { - InputStream input = getServletContext().getResourceAsStream(path); - try { - Reader reader = new InputStreamReader(input, "UTF-8"); - for (int ch = reader.read(); ch != -1; ch = reader.read()) { - if (ch == '<') { - out.write("<"); - } else if (ch == '>') { - out.write(">"); - } else if (ch == '&') { - out.write("&"); - } else { - out.write((char) ch); - } - } - } finally { - input.close(); - } - } - -%><% request.setAttribute("title", "About Apache Jackrabbit"); -%> -

- Apache Jackrabbit is a fully - conforming implementation of the Content Repository for Java Technology API - (JCR). A content repository is a hierarchical content store with support for - structured and unstructured content, full text search, versioning, - transactions, observation, and more. Typical applications that use content - repositories include content management, document management, and records - management systems. -

-

- Version 1.0 of the JCR API was specified by the - Java Specification Request 170 - (JSR 170) and version 2.0 by the - Java Specification Request 283. -

-

- Apache Jackrabbit is a project of the - Apache Software Foundation. -

-

Copyright Notice

-
<% output("/META-INF/NOTICE", out); %>
-

License Information

-
<% output("/META-INF/LICENSE", out); %>
- Property changes on: jackrabbit-webapp/src/main/webapp/about.jsp ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-webapp/src/main/webapp/bootstrap/error.jsp =================================================================== --- jackrabbit-webapp/src/main/webapp/bootstrap/error.jsp (revision 1907912) +++ jackrabbit-webapp/src/main/webapp/bootstrap/error.jsp (nonexistent) @@ -1,23 +0,0 @@ -<%-- - 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. ---%><%@page import="org.apache.jackrabbit.util.Text"%><% -request.setAttribute("title", "Content Repository Error"); -%> -

- Some error occurred during setup. See the log files for details. -

-

back

- Property changes on: jackrabbit-webapp/src/main/webapp/bootstrap/error.jsp ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-webapp/src/main/webapp/bootstrap/exists.jsp =================================================================== --- jackrabbit-webapp/src/main/webapp/bootstrap/exists.jsp (revision 1907912) +++ jackrabbit-webapp/src/main/webapp/bootstrap/exists.jsp (nonexistent) @@ -1,28 +0,0 @@ -<%-- - 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. ---%><%@page import="org.apache.jackrabbit.util.Text"%><% -request.setAttribute("title", "Content Repository Exists"); -%> -

The repository home directory or configuration already exists.

-

-You have chosen to create a new repository but the specified home -directory or the configuration file already exist. -

-

-Please specify a correct location or choose to reuse an existing repository. -

-

back

- Property changes on: jackrabbit-webapp/src/main/webapp/bootstrap/exists.jsp ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-webapp/src/main/webapp/bootstrap/missing.jsp =================================================================== --- jackrabbit-webapp/src/main/webapp/bootstrap/missing.jsp (revision 1907912) +++ jackrabbit-webapp/src/main/webapp/bootstrap/missing.jsp (nonexistent) @@ -1,70 +0,0 @@ -<%-- - 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. ---%><%@page import="org.apache.jackrabbit.util.Text"%><% -request.setAttribute("title", "Content Repository Setup"); -%> -

- Your content repository is not properly configured yet. Please use - the forms below to setup the content repository. -

-

- Alternatively, you can directly modify the settings in the - WEB-INF/web.xml deployment descriptor and redeploy this - web application. -

- -

Create a new content repository

-
- -

- Use this form to create a new content repository in the given directory. - The directory is created by this web application and should not already - exist. The repository is created using a default configuration file. -

-

- -

-

-
- -

Use an existing content repository

-
- -

- Use this form to access an existing content repository in the given - directory. The repository configuration file should be available as - repository.xml within the given directory. -

-

- Note that the repository can not be concurrently accessed by multiple - applications. You must use WebDAV or RMI through this web application - if you want to access the repository remotely. Other web applications - running in the same servlet container can access the repository locally - using JNDI. -

-

- -

-

-
- - Property changes on: jackrabbit-webapp/src/main/webapp/bootstrap/missing.jsp ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-webapp/src/main/webapp/bootstrap/notexists.jsp =================================================================== --- jackrabbit-webapp/src/main/webapp/bootstrap/notexists.jsp (revision 1907912) +++ jackrabbit-webapp/src/main/webapp/bootstrap/notexists.jsp (nonexistent) @@ -1,28 +0,0 @@ -<%-- - 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. ---%><%@page import="org.apache.jackrabbit.util.Text"%><% -request.setAttribute("title", "Content Repository Not Found"); -%> -

The repository home directory or configuration do not exists.

-

-You have chosen to reuse an existing repository but the specified home -directory or the configuration file do not exist. -

-

-Please specify a correct location or choose to create a new repository. -

-

back

- Property changes on: jackrabbit-webapp/src/main/webapp/bootstrap/notexists.jsp ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-webapp/src/main/webapp/bootstrap/reconfigure.jsp =================================================================== --- jackrabbit-webapp/src/main/webapp/bootstrap/reconfigure.jsp (revision 1907912) +++ jackrabbit-webapp/src/main/webapp/bootstrap/reconfigure.jsp (nonexistent) @@ -1,25 +0,0 @@ -<%-- - 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. ---%><%@page import="org.apache.jackrabbit.util.Text"%><% -request.setAttribute("title", "Content Repository Already Running"); -%> -

Your repository is already properly configured an running.

-

-Your changes were discarded. To reconfigure or reinstall the repository modify -the respective configuration files or remove them. -

-

home

- Property changes on: jackrabbit-webapp/src/main/webapp/bootstrap/reconfigure.jsp ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-webapp/src/main/webapp/bootstrap/running.jsp =================================================================== --- jackrabbit-webapp/src/main/webapp/bootstrap/running.jsp (revision 1907912) +++ jackrabbit-webapp/src/main/webapp/bootstrap/running.jsp (nonexistent) @@ -1,25 +0,0 @@ -<%-- - 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. ---%><%@page import="org.apache.jackrabbit.util.Text"%><% -request.setAttribute("title", "Content Repository Ready"); -%> -

Your repository is properly configured an running.

-

-To reconfigure or reinstall the repository modify the respective configuration -files or remove them. -

-

home

- Property changes on: jackrabbit-webapp/src/main/webapp/bootstrap/running.jsp ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-webapp/src/main/webapp/bootstrap/success.jsp =================================================================== --- jackrabbit-webapp/src/main/webapp/bootstrap/success.jsp (revision 1907912) +++ jackrabbit-webapp/src/main/webapp/bootstrap/success.jsp (nonexistent) @@ -1,25 +0,0 @@ -<%-- - 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. ---%><%@page import="org.apache.jackrabbit.util.Text"%><% -request.setAttribute("title", "Content Repository Ready"); -%> -

Your repository is now properly configured an running.

-

-To reconfigure or reinstall the repository modify the respective configuration -files or remove them. -

-

home

- Property changes on: jackrabbit-webapp/src/main/webapp/bootstrap/success.jsp ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-webapp/src/main/webapp/css/default.css =================================================================== --- jackrabbit-webapp/src/main/webapp/css/default.css (revision 1907912) +++ jackrabbit-webapp/src/main/webapp/css/default.css (nonexistent) @@ -1,91 +0,0 @@ -/* - * 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. - */ - -body { font-family: Verdana, Helvetica, Arial, sans-serif; - font-size: small; color: #000000; - background-color: #e0e0e0; - margin: 1em 100px 1em 100px; - padding: 0; } - -#page { background-color: white; } - -a:link { color: #667C00; } -a:visited { color: #7C7C7C; } - -img { border: 0; } - -/* BANNER */ - -#banner { padding: 0 0 113px 0; - border-top: 6px solid black; - border-bottom: 2px solid black; } -#banner p { margin: 0; } -#jcr { float: left; } -#asf { float: right; } -#banner img { margin: 0; - padding: 10px 0 0 0; } -#banner a { text-decoration: none; } - -/* NAVIGATION */ - -#navigation { padding: 18px 0; - width: 180px; - float: left; - font-size: x-small; } - -#navigation ul - { margin: 0; - padding: 1ex 0 1ex 1em; - list-style: none; - font-weight: bold; } - -#navigation ul ul - { font-weight: normal; } - -#navigation a - { text-decoration: none; } - -a.external { font-style: italic; } - -/* CONTENT */ - -#content { margin: 1em 1em 1em 180px; } - -#content p { line-height: 1.3em; } - -h1, h2, h3 { color: #869900; } - -pre { background: #E0E0E0; - padding: 1em; - border: 1px dotted black; - overflow: auto; } - -td { font-size: small; } - -pre.code { font-family: monospace; font-size: small; - padding: 25px; } - -/* FOOTER */ - -#footer { clear: both; - border-top: 1px solid #999; - font-size: x-small; } - -#footer p { margin: 0; - text-align: center; } - -#footer a { text-decoration: none; } Property changes on: jackrabbit-webapp/src/main/webapp/css/default.css ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Deleted: svn:keywords ## -1 +0,0 ## -author date id revision \ No newline at end of property Index: jackrabbit-webapp/src/main/webapp/error/classpath.jsp =================================================================== --- jackrabbit-webapp/src/main/webapp/error/classpath.jsp (revision 1907912) +++ jackrabbit-webapp/src/main/webapp/error/classpath.jsp (nonexistent) @@ -1,29 +0,0 @@ -<%-- - 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. ---%><% -request.setAttribute("title", "JCR API Not Found"); -%> -

-The javax.jcr.Repository interface from the JCR API could not -be loaded. -

-

-To resolve this issue, you need to make the jcr-2.0.jar file -available in the shared classpath of the servlet container. The file is -available for download from the -JSR 283 web page. -

- Property changes on: jackrabbit-webapp/src/main/webapp/error/classpath.jsp ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-webapp/src/main/webapp/error/repository.jsp =================================================================== --- jackrabbit-webapp/src/main/webapp/error/repository.jsp (revision 1907912) +++ jackrabbit-webapp/src/main/webapp/error/repository.jsp (nonexistent) @@ -1,42 +0,0 @@ -<%-- - 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. ---%><%@ page isErrorPage="true" - import="org.apache.jackrabbit.util.Text, - java.io.StringWriter, - java.io.PrintWriter"%><% -request.setAttribute("title", "Repository Error"); -%> -

- The content repository operation failed with the following - <%= exception.getClass().getSimpleName() %> error: -

-
<%= Text.encodeIllegalXMLCharacters(exception.getMessage()) %>
-

- See the - troubleshooting page - for ideas on how to resolve this issue. -

- -

Exception stack trace

-

- Below is the full exception stack trace associated with this error: -

-<% -StringWriter buffer = new StringWriter(); -exception.printStackTrace(new PrintWriter(buffer)); -%> -
<%= Text.encodeIllegalXMLCharacters(buffer.toString()) %>
- Property changes on: jackrabbit-webapp/src/main/webapp/error/repository.jsp ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-webapp/src/main/webapp/footer.jsp =================================================================== --- jackrabbit-webapp/src/main/webapp/footer.jsp (revision 1907912) +++ jackrabbit-webapp/src/main/webapp/footer.jsp (nonexistent) @@ -1,26 +0,0 @@ -<%-- - 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. ---%> - - - - - Property changes on: jackrabbit-webapp/src/main/webapp/footer.jsp ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-webapp/src/main/webapp/header.jsp =================================================================== --- jackrabbit-webapp/src/main/webapp/header.jsp (revision 1907912) +++ jackrabbit-webapp/src/main/webapp/header.jsp (nonexistent) @@ -1,88 +0,0 @@ -<%-- - 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. ---%> -<%@page import="org.apache.jackrabbit.util.Text"%> -<% -String title = - Text.encodeIllegalXMLCharacters(request.getAttribute("title").toString()); -String context = - Text.encodeIllegalXMLCharacters(request.getContextPath()); -%> - - - - <%= title %> - - - - -
- - -
-

<%= title %>

Property changes on: jackrabbit-webapp/src/main/webapp/header.jsp ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-webapp/src/main/webapp/images/0.gif =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Property changes on: jackrabbit-webapp/src/main/webapp/images/0.gif ___________________________________________________________________ Deleted: svn:mime-type ## -1 +0,0 ## -application/octet-stream \ No newline at end of property Index: jackrabbit-webapp/src/main/webapp/images/asf-logo.gif =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Property changes on: jackrabbit-webapp/src/main/webapp/images/asf-logo.gif ___________________________________________________________________ Deleted: svn:mime-type ## -1 +0,0 ## -application/octet-stream \ No newline at end of property Index: jackrabbit-webapp/src/main/webapp/images/asf-logo.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = image/png Property changes on: jackrabbit-webapp/src/main/webapp/images/asf-logo.png ___________________________________________________________________ Deleted: svn:mime-type ## -1 +0,0 ## -image/png \ No newline at end of property Index: jackrabbit-webapp/src/main/webapp/images/favicon.ico =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Property changes on: jackrabbit-webapp/src/main/webapp/images/favicon.ico ___________________________________________________________________ Deleted: svn:mime-type ## -1 +0,0 ## -application/octet-stream \ No newline at end of property Index: jackrabbit-webapp/src/main/webapp/images/jackrabbit.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = image/png Property changes on: jackrabbit-webapp/src/main/webapp/images/jackrabbit.png ___________________________________________________________________ Deleted: svn:mime-type ## -1 +0,0 ## -image/png \ No newline at end of property Index: jackrabbit-webapp/src/main/webapp/images/jackrabbitlogo.gif =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Property changes on: jackrabbit-webapp/src/main/webapp/images/jackrabbitlogo.gif ___________________________________________________________________ Deleted: svn:mime-type ## -1 +0,0 ## -application/octet-stream \ No newline at end of property Index: jackrabbit-webapp/src/main/webapp/images/jlogo.gif =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Property changes on: jackrabbit-webapp/src/main/webapp/images/jlogo.gif ___________________________________________________________________ Deleted: svn:mime-type ## -1 +0,0 ## -application/octet-stream \ No newline at end of property Index: jackrabbit-webapp/src/main/webapp/index.jsp =================================================================== --- jackrabbit-webapp/src/main/webapp/index.jsp (revision 1907912) +++ jackrabbit-webapp/src/main/webapp/index.jsp (nonexistent) @@ -1,22 +0,0 @@ -<%-- - 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. ---%><% -try { - Class.forName("javax.jcr.Repository"); -} catch (ClassNotFoundException e) { - throw new org.apache.jackrabbit.j2ee.JcrApiNotFoundException(e); -} -%> \ No newline at end of file Property changes on: jackrabbit-webapp/src/main/webapp/index.jsp ___________________________________________________________________ Deleted: svn Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-webapp/src/main/webapp/local.jsp =================================================================== --- jackrabbit-webapp/src/main/webapp/local.jsp (revision 1907912) +++ jackrabbit-webapp/src/main/webapp/local.jsp (nonexistent) @@ -1,103 +0,0 @@ -<%-- - 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. ---%><%@page import="org.apache.jackrabbit.util.Text"%><% -request.setAttribute("title", "Local Repository Access"); -%> -

- The content repository within this web application can be accessed - locally by other web applications within the same servlet container. - Local access is much faster than remote access. -

-

- The content repository is made available both through JNDI and the - web application context. -

- -

Accessing the repository through JNDI

-

- By default the repository is only made available in a dummy JNDI directory - local to this web application. However, you can make the repository globally - available if your servlet container allows a web application to modify the - global JNDI directory or you are using some other JNDI directory that can - manage unserializable Java objects. -

-

- To bind the the repository to such a JNDI directory, you need to modify - the java.naming parameters in either the /WEB-INF/web.xml - deployment descriptor or the jackrabbit/bootstrap.properties file. You need - to redeploy this web application to activate the changes. -

-

- Use the following code to access a repository bound in a JNDI directory: -

-
-import javax.jcr.Repository;
-import javax.naming.Context;
-import javax.naming.InitialContext;
-
-Context context = new InitialContext(...);
-Repository repository = (Repository) context.lookup(...);
-
- -

Accessing the repository through servlet context

-

- This web application makes the repository available as the - javax.jcr.Repository attribute in the application context. - If your servlet container supports cross-context access, you can - access the repository directly using that attribute. -

-

- For example in Apache Tomcat - you can enable cross-context access by setting the crossContext - attribute to true in the <Context/> configuration. -

-

- Use the following code to access a repository through the servlet context: -

-
-import javax.jcr.Repository;
-import javax.servlet.ServletContext;
-
-ServletContext context = ...; // context of your servlet
-ServletContext jackrabbit =
-    context.getContext("<%= Text.encodeIllegalXMLCharacters(request.getContextPath()) %>");
-Repository repository = (Repository)
-    context.getAttribute(Repository.class.getName()).
-
- -

Using the jackrabbit-jcr-servlet component

-

- The jackrabbit-jcr-servlet component contains utility classes - for use within JCR web applications. With that component you can hide - both the above and the remote access options - from your code, and use just the following to access a repository: -

-
-import javax.jcr.Repository;
-import org.apache.jackrabbit.servlet.ServletRepository;
-
-public class MyServlet extends HttpServlet {
-
-    private final Repository repository = new ServletRepository(this);
-
-    // ...
-
-}
-
-

- See the jackrabbit-jcr-servlet documentation for more details. -

- Property changes on: jackrabbit-webapp/src/main/webapp/local.jsp ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-webapp/src/main/webapp/remote.jsp =================================================================== --- jackrabbit-webapp/src/main/webapp/remote.jsp (revision 1907912) +++ jackrabbit-webapp/src/main/webapp/remote.jsp (nonexistent) @@ -1,106 +0,0 @@ -<%@ page import="java.net.URI"%><%-- - 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. ---%><%@page import="org.apache.jackrabbit.util.Text"%><% -request.setAttribute("title", "Remote Repository Access"); - -URI uri = new URI(request.getRequestURL().toString()); -String base = - uri.getScheme() + "://" + uri.getHost() + ":" + uri.getPort() - + request.getContextPath(); -base = Text.encodeIllegalXMLCharacters(base); -%> -

- The content repository within this web application is made available - to remote clients through - RMI - and the jackrabbit-jcr-rmi component. -

-

- The remote repository stub is available both in the RMI registry - (one is started automatically by this web application if not already running) - and as a direct HTTP download. The default URLs for accessing the remote - repository are: -

-
    -
  • RMI registry: //localhost/jackrabbit.repository
  • -
  • HTTP download: <%= base %>/rmi
  • -
-

- Note that the above URLs are the defaults. You can disable or change them - by modifying the /WEB-INF/web.xml deployment descriptor. -

- -

Accessing the remote repository

-

- To access the remote content repository you need to use the - jackrabbit-jcr-rmi component in your application. If you use - Maven 2, you can declare the JCR and jackrabbit-jcr-rmi dependencies - like this: -

-
<dependency>
-  <groupId>javax.jcr</groupId>
-  <artifactId>jcr</artifactId>
-  <version>1.0</version>
-</dependency>
-<dependency>
-  <groupId>org.apache.jackrabbit</groupId>
-  <artifactId>jackrabbit-jcr-rmi</artifactId>
-  <version>1.4</version>
-</dependency>
-
-

- With that dependency in place, you can use either the RMI registry or - the direct HTTP download to access the repository. -

-

- The required code for accessing the repository using the RMI registry is: -

-
-import javax.jcr.Repository;
-import org.apache.jackrabbit.rmi.repository.RMIRemoteRepository;
-
-Repository repository =
-    new RMIRemoteRepository("//localhost/jackrabbit.repository");
-
-

- The required code for accessing the repository using the RMI registry is: -

-
-import javax.jcr.Repository;
-import org.apache.jackrabbit.rmi.repository.URLRemoteRepository;
-
-Repository repository =
-    new URLRemoteRepository("<%= base %>/rmi");
-
-

- See the JCR specification - and the - Repository - javadoc for details on what to do with the acquired Repository instance. -

- -

Remote access performance

-

- Note that the design goal of the current jackrabbit-jcr-rmi component - is correct and complete functionality instead of performance, so you should - not rely on remote access for performance-critical applications. -

-

- You may want to look at the Jackrabbit clustering feature for best - performance for concurrently accessing the repository on multiple separate - servers. -

- Property changes on: jackrabbit-webapp/src/main/webapp/remote.jsp ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-webapp/src/main/webapp/remoting/footer.jsp =================================================================== --- jackrabbit-webapp/src/main/webapp/remoting/footer.jsp (revision 1907912) +++ jackrabbit-webapp/src/main/webapp/remoting/footer.jsp (nonexistent) @@ -1,25 +0,0 @@ -<%-- - 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. ---%> - -
- - Property changes on: jackrabbit-webapp/src/main/webapp/remoting/footer.jsp ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Deleted: svn:keywords ## -1 +0,0 ## -author date id revision \ No newline at end of property Index: jackrabbit-webapp/src/main/webapp/remoting/header.jsp =================================================================== --- jackrabbit-webapp/src/main/webapp/remoting/header.jsp (revision 1907912) +++ jackrabbit-webapp/src/main/webapp/remoting/header.jsp (nonexistent) @@ -1,64 +0,0 @@ -<%-- - 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. ---%> -<%@page import="org.apache.jackrabbit.util.Text"%> -<% -String context = Text.encodeIllegalXMLCharacters(request.getContextPath()); -%> - - - - JCR Remoting Server - - - - -
- - Property changes on: jackrabbit-webapp/src/main/webapp/remoting/header.jsp ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Deleted: svn:keywords ## -1 +0,0 ## -author date id revision \ No newline at end of property Index: jackrabbit-webapp/src/main/webapp/remoting/index.jsp =================================================================== --- jackrabbit-webapp/src/main/webapp/remoting/index.jsp (revision 1907912) +++ jackrabbit-webapp/src/main/webapp/remoting/index.jsp (nonexistent) @@ -1,38 +0,0 @@ -<%-- - 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. ---%><% -%> -
-

JCR Remoting Server - Introduction

-

Ths section shortly overviews the batch read/write extensions - added to the JCR remoting feature. -

-

-

Some principals are demonstrated in the corresponding example section.

-
- \ No newline at end of file Property changes on: jackrabbit-webapp/src/main/webapp/remoting/index.jsp ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Deleted: svn:keywords ## -1 +0,0 ## -author date id revision \ No newline at end of property Index: jackrabbit-webapp/src/main/webapp/remoting/json.js =================================================================== --- jackrabbit-webapp/src/main/webapp/remoting/json.js (revision 1907912) +++ jackrabbit-webapp/src/main/webapp/remoting/json.js (nonexistent) @@ -1,222 +0,0 @@ -/* - 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. -*/ - -function getXMLHttpRequest(url, method, headers, params) { - var xmlhttp = null; - if (window.XMLHttpRequest) { - // code for all new browsers - xmlhttp = new XMLHttpRequest(); - } else if (window.ActiveXObject) { - // code for IE - try { - xmlhttp = new ActiveXObject("Msxml2.XMLHTTP"); - } catch (e) { - xmlhttp = new ActiveXObject("Microsoft.XMLHTTP"); - } - } - if (xmlhttp) { - if (!method) { - method = "GET"; - } - xmlhttp.open(method, url, false); - if (headers) { - for (var hdr in headers) { - xmlhttp.setRequestHeader(hdr, headers[hdr]); - } - } - xmlhttp.send(params); - return xmlhttp; - } else { - alert("Your browser does not support XMLHTTP."); - return null; - } -} - -var JsonFormatter = null; -(function() { - - JsonFormatter = new Object(); - JsonFormatter.clear = false; - - JsonFormatter.tree = function(jsonObj, baseHref) { - if (!jsonObj) { - return ""; - } - var indentionLevel = 0; - return JsonFormatter.objectTree("", jsonObj, indentionLevel, baseHref); - } - - JsonFormatter.format = function(jsonObj, clearSpecial) { - if (!jsonObj) { - return ""; - } - var indentionLevel = 0; - clear = clearSpecial; - return JsonFormatter.object(jsonObj, indentionLevel); - } - - JsonFormatter.addLineBreak = function(str) { - return str += "
"; - } - - JsonFormatter.addIndention = function(str, indention, indStr) { - for (var i = 0; i < indention; i++) { - str += indStr; - } - return str; - } - - JsonFormatter.object = function(value, indentionLevel) { - if (value instanceof Array) { - return JsonFormatter.array(value, indentionLevel); - } - - var str = "{"; - str = JsonFormatter.addLineBreak(str); - indentionLevel++; - var delim = false; - - for (var i in value) { - var v = value[i]; - if (clear && i.charAt(0) == ':') { - // skip special prop. - // TODO: evaluate and add to display info. - } else { - var fnctn = JsonFormatter[typeof v]; - if (fnctn) { - v = fnctn(v, indentionLevel); - if (typeof v == 'string') { - if (delim) { - str += ","; - str = JsonFormatter.addLineBreak(str); - } - str = JsonFormatter.addIndention(str, indentionLevel, "\t"); - str += JsonFormatter.string(i) + ' : ' + v; - delim = true; - } - } - } - } - indentionLevel--; - str = JsonFormatter.addLineBreak(str); - str = JsonFormatter.addIndention(str, indentionLevel, "\t"); - str += "}"; - return str; - } - - JsonFormatter.array = function(value, indentionLevel) { - var str = "["; - var delim = false; - for (var i in value) { - var arrVal = value[i]; - var fnctn = JsonFormatter[typeof arrVal]; - if (fnctn) { - arrVal = fnctn(arrVal); - if (delim) { - str += ", "; - } - str += arrVal; - delim = true; - } - } - str += "]"; - return str; - } - - JsonFormatter.boolean = function(value, indentionLevel) { - return String(value); - } - - JsonFormatter.string = function(value, indentionLevel) { - return '"' + value + '"'; - - } - - JsonFormatter.number = function(value, indentionLevel) { - return String(value); - } - - JsonFormatter.extractPropertyType = function(key, value) { - if (key == "::NodeIteratorSize") { - return null; - } else if (key.charAt(0) == ':' && typeof value == 'string') { - return value; - } else { - return null; - } - } - - JsonFormatter.buildKey = function(key, propType, href) { - var keyStr = key; - if (propType) { - var href = "javascript:alert('PropertyType = " + propType + "');"; - keyStr = "" + key + ""; - } else if (key.charAt(0) == ':') { - // binary - var propname = key.substring(1, key.length); - var binHref = href + "/" + propname; - keyStr = "" + propname + ""; - } - return keyStr; - } - - JsonFormatter.objectTree = function(key, value, indentionLevel, href) { - var str = "+ " + key; // + node-name - if (href && href.charAt(href.length - 1) == '/') { - href += key; - } else { - href += "/" + key; - } - - indentionLevel++; - var propType; - var childSize; - var delim = false; - - for (var i in value) { - var v = value[i]; - var pt = JsonFormatter.extractPropertyType(i, v); - if (pt) { - propType = pt; - continue; - } else if (i == "::NodeIteratorSize") { - continue; - } - str = JsonFormatter.addLineBreak(str); - str = JsonFormatter.addIndention(str, indentionLevel, "  "); - if (v instanceof Array) { - // value array - propname - var key = JsonFormatter.buildKey(i, propType, href); - propType = null; - str += "- " + key + ' = ' + JsonFormatter.array(v, indentionLevel); - } else if (v instanceof Object) { - str += JsonFormatter.objectTree(i, v, indentionLevel, href); - } else { - // simple value - propname - var fnctn = JsonFormatter[typeof v]; - if (fnctn) { - v = fnctn(v, indentionLevel); - var key = JsonFormatter.buildKey(i, propType, href); - propType = null; - str += "- " + key + ' = ' + v; - } - } - } - indentionLevel--; - return str; - } -})(); Property changes on: jackrabbit-webapp/src/main/webapp/remoting/json.js ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-webapp/src/main/webapp/remoting/read.jsp =================================================================== --- jackrabbit-webapp/src/main/webapp/remoting/read.jsp (revision 1907912) +++ jackrabbit-webapp/src/main/webapp/remoting/read.jsp (nonexistent) @@ -1,65 +0,0 @@ -<%@ page import="java.net.URI" %> -<%@ page import="org.apache.jackrabbit.j2ee.JcrRemotingServlet" %> -<%@ page import="org.apache.jackrabbit.util.Text" %> -<%-- - 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. ---%><% - -URI uri = new URI(request.getRequestURL().toString()); -String href = - uri.getScheme() + "://" + uri.getHost() + ":" + uri.getPort() - + request.getContextPath() - + JcrRemotingServlet.getPathPrefix(pageContext.getServletContext()); -href = Text.encodeIllegalXMLCharacters(href); -href += "/default/jcr:root"; - -%> -
-

Read

-

Default Reading

-

Reading remotely from the repository generally follows the rules described in - JCR_Webdav_Protocol.zip. -

-

Batch Read

-

Batch read is triggered by adding a '.json' extension to the resource - href. Optionally the client may explicitely specify the desired batch - read depth by appending '.depth.json' extension. If no json extension - is present the GET request is processed by applied the default - remoting rules. -

-

The response to a batch read request contains a plain text representing - a JSON object. Its member either represent nodes or properties. -

    -
  • The name element of the Item path is added as key
  • -
  • The value of a Node entry is a JSON object.
  • -
  • The value of a Property entry is either a JSON array or a simple JSON value.
  • -
-

-

In order to cope with property types that cannot be expressed with JSON - a couple of special rules are defined: -

    -
  • Binary properties: The key gets a leading ":", the value represents the - length of the property. In order to retrieve the binary value, the - client must follow the default rules (see above).
  • -
  • Date, Name, Path and Reference properties: The type information is passed with a separate JSON pair.
  • -
  • The value of a Property entry is either a JSON array or a simple JSON value.
  • -
-

- See Example: Batch Write for a demostration of - the batch read functionality. -

-
- \ No newline at end of file Property changes on: jackrabbit-webapp/src/main/webapp/remoting/read.jsp ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Deleted: svn:keywords ## -1 +0,0 ## -author date id revision \ No newline at end of property Index: jackrabbit-webapp/src/main/webapp/remoting/read_batch.jsp =================================================================== --- jackrabbit-webapp/src/main/webapp/remoting/read_batch.jsp (revision 1907912) +++ jackrabbit-webapp/src/main/webapp/remoting/read_batch.jsp (nonexistent) @@ -1,104 +0,0 @@ -<%@ page import="java.net.URI" %> -<%@ page import="org.apache.jackrabbit.j2ee.JcrRemotingServlet" %> -<%@ page import="org.apache.jackrabbit.util.Text" %> -<%-- - 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. ---%><% - -URI uri = new URI(request.getRequestURL().toString()); -String href = - uri.getScheme() + "://" + uri.getHost() + ":" + uri.getPort() - + request.getContextPath() - + JcrRemotingServlet.getPathPrefix(pageContext.getServletContext()); -href = Text.encodeIllegalXMLCharacters(href); -href += "/default/jcr:root"; - -%> - - -
-

Examples: Batch Read

-

- Enter the path of an existing node and the desired depth. -

- - - - - - - - - - - - - - -
Node Path
Depth
Result type
-

-


-
- \ No newline at end of file Property changes on: jackrabbit-webapp/src/main/webapp/remoting/read_batch.jsp ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Deleted: svn:keywords ## -1 +0,0 ## -author date id revision \ No newline at end of property Index: jackrabbit-webapp/src/main/webapp/remoting/write.jsp =================================================================== --- jackrabbit-webapp/src/main/webapp/remoting/write.jsp (revision 1907912) +++ jackrabbit-webapp/src/main/webapp/remoting/write.jsp (nonexistent) @@ -1,161 +0,0 @@ -<%@ page import="java.net.URI" %> -<%@ page import="org.apache.jackrabbit.j2ee.JcrRemotingServlet" %> -<%@ page import="org.apache.jackrabbit.util.Text" %> -<%-- - 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. ---%><% - -URI uri = new URI(request.getRequestURL().toString()); -String href = - uri.getScheme() + "://" + uri.getHost() + ":" + uri.getPort() - + request.getContextPath() - + JcrRemotingServlet.getPathPrefix(pageContext.getServletContext()); -href = Text.encodeIllegalXMLCharacters(href); -href += "/default/jcr:root"; - -%> -
-

Write

-

Default Writing

-

Writing remotely to the repository generally follows the rules described in - JCR_Webdav_Protocol.zip. -

-

Batch Write

-

A set of transient modifications can in addition be sent by using the - extended batch write: A single POST request that contains a custom - :diff parameter describing the changes to be applied. - The expected format is described in the - JavaDoc. -

- Some cases however can be easily demonstrated. The following examples can - be tested with the form provided at - Example: Batch Write. -

-

Examples

-

The following examples illustrate the basics of the diff format. It does - not cover the special treatment of properties with type Date, - Name, Path, Reference and Binary (see below).

-

Set properties

-
-^prop1  : "stringvalue"
-^prop1  : "changedvalue"
-^prop2  : true
-^prop3  : 100.010
-^prop4  : 1234567890
-^prop5  : ["multi","valued","string prop"]
-^.      : "change existing property at path."
-^/abs/path/to/the/new/prop : "some value."
-

Add new nodes (optionally including child items)

-
-+node   : {"title" : "title property of the new node"}
-+node2  : {"childN" : {}, "childN2" : {}}
-+/abs/path/to/the/new/node : {"text" : "some text"}
-

Move or rename nodes

-
->node   : rename
->rename : /moved/to/another/destination
-

Reorder nodes

-
->childN : childN2#after
->childN : #first
->childN : #last
->childN : childN2#before
-

Remove items

-
--prop4  :
--node2  :
--/moved/to/another/destination :
-

Dealing with Special Property Types

-

Property types that can not be covered unambigously, need some special - handling (see JavaDoc). This affects JCR properties being of type -

    -
  • Date,
  • -
  • Name,
  • -
  • Path,
  • -
  • Reference,
  • -
  • Binary.
  • -
- In order to set properties of any of the types listed, the value part in the - :diff param must be left empty and a separate request parameter must be - included. Its name equals the corresponding key in the :diff, its value represents - the property value. In addition the desired property type must be specified - using the conversion defined with - JcrValueType#contentTypeFromType(int). -

-

Set a Date property

-
-POST /jackrabbit/server/default/jcr%3aroot/testNode HTTP/1.1
-Content-Type: multipart/form-data; boundary=kTmAb2lkjCtxbMVFzHEplAJjHCUo5aQndaUu
-
---kTmAb2lkjCtxbMVFzHEplAJjHCUo5aQndaUu
-Content-Disposition: form-data; name="dateProp"
-Content-Type: jcr-value/date
-
-2009-02-12T10:19:40.778+01:00         
---kTmAb2lkjCtxbMVFzHEplAJjHCUo5aQndaUu
-Content-Disposition: form-data; name=":diff"
-Content-Type: text/plain
-
-^dateProp :  
---kTmAb2lkjCtxbMVFzHEplAJjHCUo5aQndaUu--
-    
-

Setting Binary, Name, Path or Reference - properties works accordingly. -

- -

Direct Content Editing

-

The functionality present with batch reading also enables very simplified - content editing using common HTML forms.

-

The :diff parameter is omitted altogether and each request parameter is - treated as property -

    -
  • param name : property name
  • -
  • param value : property value
  • -
- whereas the form action indicates the path of the parent node. -

-

If no node exists at the specified path an attempt is made to create the - missing intermediate nodes. The primary node type of the new node is - either retrieved from the corresponding jcr:primaryType param or - automatically determined by the implementation.

-

Setting a property can be tested at - Example: Simplified Writing -

-

Examples

-

The following examples illustrate the simplified writing.

-

Set string property -

    -
  • Existing or non-existing node at /testnode
  • -
  • Set property 'propName' with value "any string value"
  • -
-

-
-<form method="POST" action="<%= href %>/testnode">
-    <input type="text" name="propName" value="any string value"/>
-</form>
-

Add node with a defined node type and set a property

-
    -
  • Non-existing node at /testnode/nonexisting
  • -
  • Define its primary type to be "nt:unstructured"
  • -
  • Set property 'propName' with value "any string value"
  • -
-
-<form method="POST" action="<%= href %>/nonexisting">
-    <input type="text" name="jcr:primaryType" value="nt:unstructured"/>
-    <input type="text" name="propName" value="any string value"/>
-</form>
-
- \ No newline at end of file Property changes on: jackrabbit-webapp/src/main/webapp/remoting/write.jsp ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Deleted: svn:keywords ## -1 +0,0 ## -author date id revision \ No newline at end of property Index: jackrabbit-webapp/src/main/webapp/remoting/write_batch.jsp =================================================================== --- jackrabbit-webapp/src/main/webapp/remoting/write_batch.jsp (revision 1907912) +++ jackrabbit-webapp/src/main/webapp/remoting/write_batch.jsp (nonexistent) @@ -1,84 +0,0 @@ -<%@ page import="java.net.URI" %> -<%@ page import="org.apache.jackrabbit.j2ee.JcrRemotingServlet" %> -<%@ page import="org.apache.jackrabbit.util.Text" %> -<%-- - 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. ---%><% - -URI uri = new URI(request.getRequestURL().toString()); -String href = - uri.getScheme() + "://" + uri.getHost() + ":" + uri.getPort() - + request.getContextPath() - + JcrRemotingServlet.getPathPrefix(pageContext.getServletContext()); -href = Text.encodeIllegalXMLCharacters(href); -href += "/default/jcr:root"; - -%> - - -
-

Examples: Batch Write

-

- Enter the path of an existing node or property (depending on the desired - actions) and enter the :diff value. -

-

See the introduction to batched writing - for examples. -

- - - - - - - - - - -
Item Path
Diff
-

-


-
- \ No newline at end of file Property changes on: jackrabbit-webapp/src/main/webapp/remoting/write_batch.jsp ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Deleted: svn:keywords ## -1 +0,0 ## -author date id revision \ No newline at end of property Index: jackrabbit-webapp/src/main/webapp/remoting/write_simple.jsp =================================================================== --- jackrabbit-webapp/src/main/webapp/remoting/write_simple.jsp (revision 1907912) +++ jackrabbit-webapp/src/main/webapp/remoting/write_simple.jsp (nonexistent) @@ -1,101 +0,0 @@ -<%@ page import="java.net.URI" %> -<%@ page import="org.apache.jackrabbit.j2ee.JcrRemotingServlet" %> -<%@ page import="org.apache.jackrabbit.util.Text" %> -<%-- - 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. ---%><% - -URI uri = new URI(request.getRequestURL().toString()); -String href = - uri.getScheme() + "://" + uri.getHost() + ":" + uri.getPort() - + request.getContextPath() - + JcrRemotingServlet.getPathPrefix(pageContext.getServletContext()); -href = Text.encodeIllegalXMLCharacters(href); -href += "/default/jcr:root"; - -%> - - -
-

Examples: Simplified Writing

-

If the JCR node at the specified absolute path allows to set a properties - with name title or text, submitting the form below will - will set those properties to the given values.

-

If no JCR node exists at the specified absolute path, the missing - intermediate nodes will be created if an applicable node type for the - specified node name(s) can be determined.

- - - - - - - - - - - - - - -
Node Path
Title
Text
-

-


-
- \ No newline at end of file Property changes on: jackrabbit-webapp/src/main/webapp/remoting/write_simple.jsp ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Deleted: svn:keywords ## -1 +0,0 ## -author date id revision \ No newline at end of property Index: jackrabbit-webapp/src/main/webapp/search.jsp =================================================================== --- jackrabbit-webapp/src/main/webapp/search.jsp (revision 1907912) +++ jackrabbit-webapp/src/main/webapp/search.jsp (nonexistent) @@ -1,254 +0,0 @@ -<%-- - 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. ---%><%@ page import="javax.jcr.Repository, - org.apache.jackrabbit.j2ee.RepositoryAccessServlet, - org.apache.jackrabbit.util.Text, - javax.jcr.Session, - javax.jcr.SimpleCredentials, - javax.jcr.query.Query, - javax.jcr.query.RowIterator, - java.text.NumberFormat, - javax.jcr.query.Row, - javax.jcr.Node, - java.net.URLEncoder, - java.text.SimpleDateFormat, - java.text.DateFormat, - java.util.List, - java.util.ArrayList, - java.util.Iterator, - javax.jcr.Value, - javax.jcr.RepositoryException"%> -<%@ page contentType="text/html;charset=UTF-8" %><% - Repository rep; - Session jcrSession; - try { - rep = RepositoryAccessServlet.getRepository(pageContext.getServletContext()); - jcrSession = rep.login(new SimpleCredentials("anonymous", "".toCharArray())); - } catch (Throwable e) { - %>Error while accessing the repository: <%= Text.encodeIllegalXMLCharacters(e.getMessage()) %>
<% - %>Check the configuration or use the easy setup wizard.<% - return; - } - try { - String wspName = jcrSession.getWorkspace().getName(); - String q = request.getParameter("q"); - if (q == null) { - q = ""; - } else { - q = new String(q.getBytes("ISO-8859-1"), "UTF-8"); - } - if (request.getParameter("as_q") != null) { - q += " " + new String(request.getParameter("as_q").getBytes("ISO-8859-1"), "UTF-8"); - } - String executedIn = ""; - String queryTerms = ""; - String totalResults = ""; - long from = 0; - long to = 10; - long total = 0; - long maxPage = 0; - long minPage = 0; - long currentPageIndex = 0; - List indexes = new ArrayList(); - RowIterator rows = null; - String suggestedQuery = null; - if (q != null && q.length() > 0) { - String stmt; - if (q.startsWith("related:")) { - String path = q.substring("related:".length()); - path = path.replaceAll("'", "''"); - stmt = "//element(*, nt:file)[rep:similar(jcr:content, '" + path + "/jcr:content')]/rep:excerpt(.) order by @jcr:score descending"; - queryTerms = "similar to " + Text.encodeIllegalXMLCharacters(path) + ""; - } else { - queryTerms = "for " + Text.encodeIllegalXMLCharacters(q) + ""; - q = q.replaceAll("'", "''"); - stmt = "//element(*, nt:file)[jcr:contains(jcr:content, '" + q + "')]/rep:excerpt(.) order by @jcr:score descending"; - } - Query query = jcrSession.getWorkspace().getQueryManager().createQuery(stmt, Query.XPATH); - long time = System.currentTimeMillis(); - rows = query.execute().getRows(); - time = System.currentTimeMillis() - time; - NumberFormat nf = NumberFormat.getNumberInstance(); - nf.setMaximumFractionDigits(2); - nf.setMinimumFractionDigits(2); - executedIn = nf.format(((double) time) / 1000d); - nf.setMaximumFractionDigits(0); - totalResults = nf.format(rows.getSize()); - if (request.getParameter("start") != null) { - from = Long.parseLong(request.getParameter("start")); - try { - rows.skip(from); - } catch (Exception e) { - // make sure rows are consumed - while (rows.hasNext()) { - rows.nextRow(); - } - } - } - to = Math.min(from + 10, rows.getSize()); - - total = rows.getSize(); - maxPage = total / 10L; - if (total % 10L > 0) { - maxPage++; - } - currentPageIndex = from / 10L; - maxPage = Math.min(maxPage, currentPageIndex + 10); - minPage = Math.max(0, currentPageIndex - 10); - for (long i = minPage; i < maxPage; i++) { - indexes.add(new Long(i)); - } - - if (total < 10 && !q.startsWith("related:")) { - try { - Value v = jcrSession.getWorkspace().getQueryManager().createQuery( - "/jcr:root[rep:spellcheck('" + q + "')]/(rep:spellcheck())", - Query.XPATH).execute().getRows().nextRow().getValue("rep:spellcheck()"); - if (v != null) { - suggestedQuery = v.getString(); - } - } catch (RepositoryException e) { - // ignore - } - } - } -request.setAttribute("title", "Search workspace " + wspName); -%> - -
-

- -

-

-
-<% if (rows != null && rows.getSize() == 0) { %> -<% if (suggestedQuery != null) { %> -

Did you mean: - - <%= Text.encodeIllegalXMLCharacters(suggestedQuery) %> -
-

-<% } %> -

Your search - <%= Text.encodeIllegalXMLCharacters(q) %> - did not match any documents. -

Suggestions: -

    -
  • Make sure all words are spelled correctly.
  • -
  • Try different keywords.
  • -
  • Try more general keywords.
  • -
  • Try fewer keywords.
  • -
- <% - } else if (rows != null) { - %> - - - -
Results <%= from + 1 %> - <%= to %> of about <%= totalResults %> <%= queryTerms %>. (<%= executedIn %> seconds) 
-<% if (suggestedQuery != null) { %> -

- Did you mean: - - <%= Text.encodeIllegalXMLCharacters(suggestedQuery) %> -
-

-<% } %> -
- <% - while (rows.hasNext() && rows.getPosition() < to) { - Row r = rows.nextRow(); - Node file = (Node) jcrSession.getItem(r.getValue("jcr:path").getString()); - Node resource = file.getNode("jcr:content"); - String size = ""; - if (resource.hasProperty("jcr:data")) { - double length = resource.getProperty("jcr:data").getLength(); - size = String.valueOf(Math.round(Math.ceil(length / 1000d))) + "k"; - } - DateFormat df = SimpleDateFormat.getDateInstance(SimpleDateFormat.LONG); - String lastModified = df.format(resource.getProperty("jcr:lastModified").getDate().getTime()); - %> -
" class=l><%= Text.encodeIllegalXMLCharacters(file.getName()) %>
- - - -
<%= r.getValue("rep:excerpt(jcr:content)").getString() %> - <%= Text.encodeIllegalXMLCharacters(file.getPath()) %> - <%= size %> - <%= lastModified %> - ">Similar pages
- <% - } // while - %> -
- -
- <% - if (indexes.size() > 1) { - %> -
- - -
Result Page:  - <% - if (currentPageIndex != ((Long) indexes.get(0)).longValue()) { - %>&start=<%= (currentPageIndex - 1) * 10 %>>Previous<% - } else { - %><% - } - for (Iterator it = indexes.iterator(); it.hasNext(); ) { - long pageIdx = ((Long) it.next()).longValue(); - if (pageIdx == currentPageIndex) { - %><%= pageIdx + 1 %><% - } else { - %>&start=<%= pageIdx * 10 %>><%= pageIdx + 1 %><% - } - } - if (currentPageIndex < (maxPage - 1)) { - %>&start=<%= (currentPageIndex + 1) * 10 %>>Next<% - } else { - %><% - } - %> -
-
- <% - } - %> - - -

- - -

/search.jsp> - -
-
- Search within results | Dissatisfied? Help us improve
-
-
- - <% - } // if (rows != null) - - String tableClass = ""; - if (rows != null && rows.getSize() == 0) { - tableClass = " class=\"t n bt\""; - } - %> - -<% - } finally { - if (jcrSession != null) { - jcrSession.logout(); - } - } -%> \ No newline at end of file Property changes on: jackrabbit-webapp/src/main/webapp/search.jsp ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-webapp/src/main/webapp/swr.jsp =================================================================== --- jackrabbit-webapp/src/main/webapp/swr.jsp (revision 1907912) +++ jackrabbit-webapp/src/main/webapp/swr.jsp (nonexistent) @@ -1,69 +0,0 @@ -<%-- - 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. ---%><%@ page import="javax.jcr.Repository, - javax.jcr.Session, - org.apache.jackrabbit.j2ee.RepositoryAccessServlet, - org.apache.jackrabbit.util.Text, - javax.jcr.SimpleCredentials, - java.text.NumberFormat" -%><%@ page contentType="text/html;charset=UTF-8" %><% - Repository rep; - Session jcrSession; - try { - rep = RepositoryAccessServlet.getRepository(pageContext.getServletContext()); - jcrSession = rep.login(new SimpleCredentials("anonymous", "".toCharArray())); - } catch (Throwable e) { - %>Error while accessing the repository: <%= Text.encodeIllegalXMLCharacters(e.getMessage()) %>
<% - %>Check the configuration or use the easy setup wizard.<% - return; - } - try { - String q = new String(request.getParameter("q").getBytes("ISO-8859-1"), "UTF-8"); - String swrnum = request.getParameter("swrnum"); - String numResults = null; - try { - numResults = NumberFormat.getNumberInstance().format(Long.parseLong(swrnum)); - } catch (NumberFormatException e) { - // ignore - } - if (q == null || numResults == null) { - return; - } - - request.setAttribute("title", "Search within results"); - %> -
- - - -

There were about <%= numResults %> results for <%= Text.encodeIllegalXMLCharacters(q) %>.
- Use the search box below to search within these results.

-
-
- - - -
-
-
- -<% - } finally { - if (jcrSession != null) { - jcrSession.logout(); - } - } -%> \ No newline at end of file Property changes on: jackrabbit-webapp/src/main/webapp/swr.jsp ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-webapp/src/main/webapp/troubleshooting.jsp =================================================================== --- jackrabbit-webapp/src/main/webapp/troubleshooting.jsp (revision 1907912) +++ jackrabbit-webapp/src/main/webapp/troubleshooting.jsp (nonexistent) @@ -1,105 +0,0 @@ -<%-- - 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. ---%><%@page import="org.apache.jackrabbit.util.Text, - java.io.StringWriter, - java.io.PrintWriter"%><% -request.setAttribute("title", "Troubleshooting"); -%> -

- If you experience problems with the Jackrabbit JCR server, please - check the following: -

-
    -
  1. - Did you encounter an exception? Copy the exception stack trace somewhere - so you don't loose it. The stack trace contains valuable information - for the Jackrabbit developers if you need to file a bug report for the - problem you encountered. -
  2. -
  3. - Is the repository up and running? Try browsing the - default workspace - to check if you can still see any content in the repository. You will - see an error message if the repository is not available. -
  4. -
  5. - What were you trying to do? Try to verify that your client code or - other manner of repository use is correct. Did it work before or are - you trying to do something new? -
  6. -
  7. - Are there any notable log entries? Check the log files for any related - warnings or errors. By default the Jackrabbit JCR Server writes log - entries to the standard output of the servlet container. You can customize - logging by editing the /WEB-INF/log4j.xml file and - redeploying this web application. -
  8. -
-

- If none of the above steps help you identify or resolve the problem, - you can contact the Jackrabbit users mailing list or report the problem - in the Jackrabbit issue tracker to get support from the Jackrabbit community. - When contacting the community, please include any relevant details related - to the above questions and the environment information shown at the end - of this page. -

- -

Jackrabbit mailing list

-

- The Jackrabbit user mailing list, users@jackrabbit.apache.org, is the - place to discuss any problems or other issues regarding the use of - Apache Jackrabbit (or JCR content repositories in general). -

-

- Feel free to subscribe the mailing list or browse the archives listed as - described in the - Jackrabbit mailing lists - page. -

- -

Jackrabbit issue tracker

-

- If you think you've identified a defect in Jackrabbit, you're welcome - to file a bug report in the - Jackrabbit issue tracker. - You can also use the issue tracker to request new features and other - improvements. -

-

- You need an account in the issue tracker to report new issues or to comment - on existing. Use the - registration form - if you don't already have an account. No account is needed browsing - and searching existing issues. -

- -

Environment information

-

- This instance of the Jackrabbit JCR Server is running in - a <%= Text.encodeIllegalXMLCharacters(application.getServerInfo()) %> servlet container - that supports the Java Servlet API version - <%= application.getMajorVersion() %>.<%= application.getMinorVersion() %>. -

-

- Details of the Java and operating system environment are included in - the system properties shown below: -

-<% -StringWriter buffer = new StringWriter(); -System.getProperties().list(new PrintWriter(buffer)); -%> -
<%= Text.encodeIllegalXMLCharacters(buffer.toString()) %>
- Property changes on: jackrabbit-webapp/src/main/webapp/troubleshooting.jsp ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-webapp/src/main/webapp/webdav-jcr.jsp =================================================================== --- jackrabbit-webapp/src/main/webapp/webdav-jcr.jsp (revision 1907912) +++ jackrabbit-webapp/src/main/webapp/webdav-jcr.jsp (nonexistent) @@ -1,88 +0,0 @@ -<%@ page import="org.apache.jackrabbit.j2ee.JCRWebdavServerServlet, - java.net.URI" -%><%-- - 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. ---%><%@page import="org.apache.jackrabbit.util.Text"%><% -request.setAttribute("title", "JCR Remoting Server"); - -URI uri = new URI(request.getRequestURL().toString()); -int port = uri.getPort(); -String href = - uri.getScheme() + "://" + uri.getHost() + (port == -1 ? "" : (":" + port)) - + request.getContextPath() - + JCRWebdavServerServlet.getPathPrefix(pageContext.getServletContext()); -href = Text.encodeIllegalXMLCharacters(href); -String shref = href + "/default/jcr:root"; -%> -

- The JCR Remoting Server provides an item-based WebDAV view to the - JCR repository, mapping the functionality provided by JSR 170 to the - WebDAV protocol in order to allow remote content repository access - via WebDAV. -

-

- See the draft document - JCR_Webdav_Protocol.zip - for more details regarding this remoting protocol. -

-

- Batch read and write as well as the missing functionality (cross workspace - copy and clone) has been addressed with a extension - to the remoting server. -

- -

Access the content repository

-

- Use the following URLs to access the content repository in your remoting client: -

-
-
<%= href %>
-
to access all workspaces of your JCR repository
-
<%= shref %>
-
to access a single workspace (example with workspace named 'default')
-
- -

Supported WebDAV functionality

-

- This implementation focuses on replicating all JCR features for remote - access instead of providing standard WebDAV functionality or compatibility - with existing WebDAV clients. -

-

- The following RFCs are used to implement the remoting functionality: -

- - -

JCR Remoting Client

-

- For the client counterpart of this WebDAV servlet please take a look at the - Jackrabbit SPI2DAV - module. -

- -

Configuration

-
    -
  • Context Path: <%= Text.encodeIllegalXMLCharacters(request.getContextPath()) %>
  • -
  • Resource Path Prefix: <%= Text.encodeIllegalXMLCharacters(JCRWebdavServerServlet.getPathPrefix(pageContext.getServletContext())) %>
  • -
  • Workspace Name: optional (available workspaces are mapped as resources)
  • -
  • Additional servlet configuration: see /WEB-INF/web.xml
  • -
- Property changes on: jackrabbit-webapp/src/main/webapp/webdav-jcr.jsp ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-webapp/src/main/webapp/webdav-remoting.jsp =================================================================== --- jackrabbit-webapp/src/main/webapp/webdav-remoting.jsp (revision 1907912) +++ jackrabbit-webapp/src/main/webapp/webdav-remoting.jsp (nonexistent) @@ -1,92 +0,0 @@ -<%@ page import="org.apache.jackrabbit.j2ee.JCRWebdavServerServlet, - java.net.URI" -%><%-- - 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. ---%><%@page import="org.apache.jackrabbit.util.Text"%> -<%@ page import="org.apache.jackrabbit.j2ee.JcrRemotingServlet" %> -<% -request.setAttribute("title", "JCR Remoting Server with Batch Read/Write"); - -URI uri = new URI(request.getRequestURL().toString()); -int port = uri.getPort(); -String href = - uri.getScheme() + "://" + uri.getHost() + (port == -1 ? "" : (":" + port)) - + request.getContextPath() - + JCRWebdavServerServlet.getPathPrefix(pageContext.getServletContext()); -href = Text.encodeIllegalXMLCharacters(href); -String shref = href + "/default/jcr:root"; -%> -

- The JCR Remoting Server provides an item-based WebDAV view to the - JCR repository, mapping the functionality provided by JSR 170 to the - WebDAV protocol in order to allow remote content repository access - via WebDAV. -

-

- This implementation variant adds batch read and write functionality to the initial - JCR Remoting Server. In addition it supports - copy across workspaces and clone. -

- -

Access the content repository

-

- Use the following URLs to access the content repository in the remoting client: -

-
-
<%= href %>
-
to access all workspaces of your JCR repository
-
<%= shref %>
-
to access a single workspace (example with workspace named 'default')
-
- -

Supported WebDAV functionality

-

- See JCR Remoting Server. -

- -

Batch Read

-

-Composes a JSON object for a node (and its child items) up to a explicitely -specified or configuration determined depth. -
-See JavaDoc for details -or try the Examples. -

- -

Batch Write

-

-In contrast to the default JCR remoting this extended version allows to send -a block of modifications (SPI Batch) within a single POST request containing a -custom ":diff" parameter. -
-See the JavaDoc for details -or try the Examples. -

- -

JCR Remoting Client

-

- For the client counterpart of this WebDAV servlet please take a look at the extended SPI2DAV - project. -

- -

Configuration

-
    -
  • Context Path: <%= Text.encodeIllegalXMLCharacters(request.getContextPath()) %>
  • -
  • Resource Path Prefix: <%= Text.encodeIllegalXMLCharacters(JcrRemotingServlet.getPathPrefix(pageContext.getServletContext())) %>
  • -
  • Workspace Name: optional (available workspaces are mapped as resources)
  • -
  • Additional servlet configuration: see /WEB-INF/web.xml
  • -
- Property changes on: jackrabbit-webapp/src/main/webapp/webdav-remoting.jsp ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-webapp/src/main/webapp/webdav-simple.jsp =================================================================== --- jackrabbit-webapp/src/main/webapp/webdav-simple.jsp (revision 1907912) +++ jackrabbit-webapp/src/main/webapp/webdav-simple.jsp (nonexistent) @@ -1,84 +0,0 @@ -<%@ page import="org.apache.jackrabbit.j2ee.SimpleWebdavServlet, - java.net.URI" -%><%-- - 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. ---%><%@page import="org.apache.jackrabbit.util.Text"%><% -request.setAttribute("title", "Standard WebDAV Server"); - -URI uri = new URI(request.getRequestURL().toString()); -int port = uri.getPort(); -String href = - uri.getScheme() + "://" + uri.getHost() + (port == -1 ? "" : (":" + port)) - + request.getContextPath() - + SimpleWebdavServlet.getPathPrefix(pageContext.getServletContext()) - + "/default/"; -href = Text.encodeIllegalXMLCharacters(href); -%> - -

- The default WebDAV server (aka: Simple Server) is a - DAV 1,2 and - DeltaV - compliant WebDAV server implementation. It offers a file-based view to - the JCR repository, suitable for everybody looking for standard WebDAV - functionality. Essentially, the contents of the underlying content - repository are exposed as a hierarchical collection of files and folders. -

- -

Access the content repository

-

- Use the following URL to access the content repository in your WebDAV client: -

- -

- The server asks for authentication and will accept credentials for the default - admin user: admin/admin. You can modify this security policy in - the repository configuration file. -

-

- To access other workspace than the default one, replace the last part of - the URL (/default/) with the name of another workspace. -

-

- You can also search the default workspace. -

- -

File system access

-

- Many operating systems, including Windows and Mac OS X, allow you to - "mount" a WebDAV server as a shared network disk. You can use the above - URL to make the default workspace available as such a network disk, after - which you can use normal file system tools to copy files and folders to - and from the content repository. -

- -

Supported WebDAV functionality

- - -

Configuration

-
    -
  • Context path: <%= Text.encodeIllegalXMLCharacters(request.getContextPath()) %>
  • -
  • Resource path prefix: <%= Text.encodeIllegalXMLCharacters(SimpleWebdavServlet.getPathPrefix(pageContext.getServletContext())) %>
  • -
  • Servlet configuration: see /WEB-INF/web.xml
  • -
  • WebDAV specific resource configuration: see /WEB-INF/config.xml
  • -
- Property changes on: jackrabbit-webapp/src/main/webapp/webdav-simple.jsp ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-webapp/src/main/webapp/welcome.jsp =================================================================== --- jackrabbit-webapp/src/main/webapp/welcome.jsp (revision 1907912) +++ jackrabbit-webapp/src/main/webapp/welcome.jsp (nonexistent) @@ -1,60 +0,0 @@ -<%@ page import="org.apache.jackrabbit.j2ee.RepositoryAccessServlet, - javax.jcr.Repository" -%><%-- - 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. ---%><% - -Repository rep; -try { - rep = RepositoryAccessServlet.getRepository(pageContext.getServletContext()); -} catch (Throwable e) { - %><% -} - -request.setAttribute("title", "Apache Jackrabbit JCR Server"); -%> -

- Welcome to the Apache Jackrabbit JCR Server. This web application - contains a JCR content repository and makes it available to clients - through WebDAV and other means. -

-

- The following WebDAV view is provided for accessing the - content in the JCR content repository. -

- -

- In addition the JCR Server project provides means for JCR remoting over HTTP: -

- -

- Clients can also access the repository using the JCR API. Both local - and remote access is supported. -

- -

- For more information, including copyright and licensing details, visit the - About Apache Jackrabbit page. -

- Property changes on: jackrabbit-webapp/src/main/webapp/welcome.jsp ___________________________________________________________________ Deleted: svn Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-webapp/src/test/java/org/apache/jackrabbit/j2ee/TomcatIT.java =================================================================== --- jackrabbit-webapp/src/test/java/org/apache/jackrabbit/j2ee/TomcatIT.java (revision 1907912) +++ jackrabbit-webapp/src/test/java/org/apache/jackrabbit/j2ee/TomcatIT.java (nonexistent) @@ -1,137 +0,0 @@ -/* - * 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.j2ee; - -import java.io.BufferedWriter; -import java.io.File; -import java.io.IOException; -import java.net.URL; -import java.nio.charset.StandardCharsets; -import java.util.List; - -import junit.framework.TestCase; - -import org.apache.catalina.startup.Tomcat; -import org.apache.commons.io.FileUtils; -import org.slf4j.bridge.SLF4JBridgeHandler; - -import com.gargoylesoftware.htmlunit.WebClient; -import com.gargoylesoftware.htmlunit.html.HtmlElement; -import com.gargoylesoftware.htmlunit.html.HtmlForm; -import com.gargoylesoftware.htmlunit.html.HtmlInput; -import com.gargoylesoftware.htmlunit.html.HtmlPage; -import com.google.common.io.Files; - -public class TomcatIT extends TestCase { - - static { - SLF4JBridgeHandler.install(); - } - - private URL url; - - private Tomcat tomcat; - - private WebClient client; - - protected void setUp() throws Exception { - File war = null; - for (File f : new File("target").listFiles()) { - if (f.isDirectory() && new File(f, "WEB-INF/web.xml").isFile()) { - war = f; - break; - } - } - assertNotNull(war); - rewriteWebXml(war); - - File bootstrap = new File("target", "bootstrap.properties"); - bootstrap.delete(); - - File baseDir = new File("target", "tomcat"); - FileUtils.deleteQuietly(baseDir); - - File repoDir = new File("target", "repository"); - FileUtils.deleteQuietly(repoDir); - - url = new URL("http://localhost:12856/"); - - tomcat = new Tomcat(); - tomcat.setSilent(true); - tomcat.setBaseDir(baseDir.getPath()); - tomcat.setHostname(url.getHost()); - tomcat.setPort(url.getPort()); - - tomcat.addWebapp("", war.getAbsolutePath()); - - tomcat.start(); - - client = new WebClient(); - } - - public void testTomcat() throws Exception { - HtmlPage page = client.getPage(url); - assertEquals("Content Repository Setup", page.getTitleText()); - - page = submitNewRepositoryForm(page); - assertEquals("Content Repository Ready", page.getTitleText()); - - page = page.getAnchorByText("home").click(); - assertEquals("Apache Jackrabbit JCR Server", page.getTitleText()); - } - - private HtmlPage submitNewRepositoryForm(HtmlPage page) throws IOException { - for (HtmlForm form : page.getForms()) { - for (HtmlInput mode : form.getInputsByName("mode")) { - if ("new".equals(mode.getValueAttribute())) { - for (HtmlInput home : form.getInputsByName("repository_home")) { - home.setValueAttribute("target/repository"); - for (HtmlElement submit : form.getElementsByAttribute("input", "type", "submit")) { - return submit.click(); - } - } - } - } - } - fail(); - return null; - } - - private void rewriteWebXml(File war) throws IOException { - File webXml = new File(war, new File("WEB-INF","web.xml").getPath()); - assertTrue(webXml.exists()); - List lines = Files.readLines(webXml, StandardCharsets.UTF_8); - BufferedWriter writer = Files.newWriter(webXml, StandardCharsets.UTF_8); - try { - for (String line : lines) { - line = line.replace("jackrabbit/bootstrap.properties", - "target/bootstrap.properties"); - writer.write(line); - writer.write(System.lineSeparator()); - } - } finally { - writer.close(); - } - } - - protected void tearDown() throws Exception { - client.close(); - - tomcat.stop(); - } - -} Property changes on: jackrabbit-webapp/src/test/java/org/apache/jackrabbit/j2ee/TomcatIT.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-webapp/src/test/resources/compatibility.zip =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Property changes on: jackrabbit-webapp/src/test/resources/compatibility.zip ___________________________________________________________________ Deleted: svn:mime-type ## -1 +0,0 ## -application/octet-stream \ No newline at end of property Index: jackrabbit-webapp/src/test/resources/logback-test.xml =================================================================== --- jackrabbit-webapp/src/test/resources/logback-test.xml (revision 1907912) +++ jackrabbit-webapp/src/test/resources/logback-test.xml (nonexistent) @@ -1,31 +0,0 @@ - - - - - - target/jcr.log - - %date{HH:mm:ss.SSS} %-5level %-40([%thread] %F:%L) %msg%n - - - - - - - - Property changes on: jackrabbit-webapp/src/test/resources/logback-test.xml ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-webapp =================================================================== --- jackrabbit-webapp (revision 1907912) +++ jackrabbit-webapp (nonexistent) Property changes on: jackrabbit-webapp ___________________________________________________________________ Deleted: svn:ignore ## -1,5 +0,0 ## -target -.* -*.iws -*.ipr -*.iml 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 importProperties(PropertyImportContext importContext, boolean isCollection) throws RepositoryException { + if (!canImport(importContext, isCollection)) { + throw new RepositoryException("PropertyHandler " + getName() + " failed import properties"); + } + + // loop over List and remember all properties and propertyNames + // that failed to be imported (set or remove). + Map failures = new HashMap(); + List changeList = importContext.getChangeList(); + + // for collections the import-root is the target node where properties + // are altered. in contrast 'non-collections' are with the handler + // represented by 'file' nodes, that must have a jcr:content child + // node, which holds all properties except jcr:created. + // -> see canImport for the corresponding assertions + Node cn = (Node) importContext.getImportRoot(); + if (!isCollection && cn.hasNode(JcrConstants.JCR_CONTENT)) { + cn = cn.getNode(JcrConstants.JCR_CONTENT); + } + + if (changeList != null) { + 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(""); + writer.print(Text.encodeIllegalHTMLCharacters(repName)); + writer.print(" "); + writer.print(Text.encodeIllegalHTMLCharacters(repVersion)); + writer.print(" "); + writer.print(Text.encodeIllegalHTMLCharacters(item.getPath())); + writer.print(""); + writer.print("

"); + writer.print(Text.encodeIllegalHTMLCharacters(item.getPath())); + 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#exportContent(ExportContext, DavResource) + */ + public boolean exportContent(ExportContext context, DavResource resource) throws IOException { + if (!canExport(context, resource)) { + 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(""); + writer.print(Text.encodeIllegalHTMLCharacters(repName)); + writer.print(" "); + writer.print(Text.encodeIllegalHTMLCharacters(repVersion)); + writer.print(" "); + writer.print(Text.encodeIllegalHTMLCharacters(resource.getResourcePath())); + writer.print(""); + writer.print("

"); + writer.print(Text.encodeIllegalHTMLCharacters(resource.getResourcePath())); + 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 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 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 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 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 alterProperties(PropertyImportContext context, boolean isCollection) throws RepositoryException { + Map 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 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 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 referenceToSessionMap; + + /** + * Create a new session cache with the {@link #CONCURRENCY_LEVEL_DEFAULT default concurrency level}. + */ + private SessionCache() { + this(CONCURRENCY_LEVEL_DEFAULT); + } + + /** + * Create a new session cache with the specified the level of concurrency + * for this server. + * + * @param cacheConcurrencyLevel A positive int value specifying the + * concurrency level of the server. + */ + private SessionCache(int cacheConcurrencyLevel) { + sessionMap = new ConcurrentHashMap>(INITIAL_CAPACITY, .75f, cacheConcurrencyLevel); + referenceToSessionMap = new ConcurrentHashMap(INITIAL_CAPACITY_REF_TO_SESSION, .75f, cacheConcurrencyLevel); + } + + /** + * Try to retrieve DavSession if a TransactionId or + * SubscriptionId is present in the request header. If no cached session + * was found null is returned. + * + * @param request + * @return a cached DavSession or null. + * @throws DavException + */ + private DavSession get(WebdavRequest request) + throws DavException { + String txId = request.getTransactionId(); + String subscriptionId = request.getSubscriptionId(); + String lockToken = request.getLockToken(); + + DavSession session = null; + // try to retrieve a cached session + if (lockToken != null && containsReference(lockToken)) { + session = getSessionByReference(lockToken); + } else if (txId != null && containsReference(txId)) { + session = getSessionByReference(txId); + } else if (subscriptionId != null && containsReference(subscriptionId)) { + session = getSessionByReference(subscriptionId); + } + + if (session == null) { + // try tokens present in the if-header + IfHeader ifHeader = new IfHeader(request); + for (Iterator it = ifHeader.getAllTokens(); it.hasNext();) { + String token = it.next(); + if (containsReference(token)) { + session = getSessionByReference(token); + break; + } + } + } + + // no cached session present -> create new one. + if (session == null) { + Session repSession = getRepositorySession(request); + session = new DavSessionImpl(repSession); + + // TODO: review again if using ConcurrentMap#putIfAbsent() was more appropriate. + sessionMap.put(session, new HashSet()); + log.debug("login: User '" + repSession.getUserID() + "' logged in."); + } else { + log.debug("login: Retrieved cached session for user '" + getUserID(session) + "'"); + } + addReference(session, request); + return session; + } + + /** + * Add a references to the specified DavSession. + * + * @param session + * @param reference + */ + private void addReference(DavSession session, Object reference) { + Set referenceSet = sessionMap.get(session); + if (referenceSet != null) { + referenceSet.add(reference); + referenceToSessionMap.put(reference, session); + } else { + log.error("Failed to add reference to session. No entry in cache found."); + } + } + + /** + * Remove the given reference from the specified DavSession. + * + * @param session + * @param reference + */ + private void removeReference(DavSession session, Object reference) { + Set referenceSet = sessionMap.get(session); + if (referenceSet != null) { + if (referenceSet.remove(reference)) { + log.debug("Removed reference " + reference + " to session " + session); + referenceToSessionMap.remove(reference); + } else { + log.warn("Failed to remove reference " + reference + " to session " + session); + } + if (referenceSet.isEmpty()) { + log.debug("No more references present on webdav session -> clean up."); + sessionMap.remove(session); + try { + Session repSession = DavSessionImpl.getRepositorySession(session); + String usr = getUserID(session) ; + sessionProvider.releaseSession(repSession); + log.debug("Login: User '" + usr + "' logged out"); + } catch (DavException e) { + // should not occur, since we originally built a + // DavSessionImpl that wraps a repository session. + log.error("Unexpected error: " + e.getMessage(), e.getCause()); + } + } else { + log.debug(referenceSet.size() + " references remaining on webdav session " + session); + } + } else { + log.error("Failed to remove reference from session. No entry in cache found."); + } + } + + /** + * Returns true, if there exists a DavSession in the cache + * that is referenced by the specified object. + * + * @param reference + * @return true if a DavSession is referenced by the given + * object. + */ + private boolean containsReference(Object reference) { + return referenceToSessionMap.containsKey(reference); + } + + /** + * Returns the DavSession that is referenced by the + * specified reference object. + * + * @param reference + * @return DavSession that is referenced by this reference + * object. + * @see #containsReference(Object) + */ + private DavSession getSessionByReference(Object reference) { + return referenceToSessionMap.get(reference); + } + + /** + * Retrieve the {@link Session} object for the given request. + * + * @param request + * @return JCR session object used to build the DavSession + * @throws DavException + * @throws DavException in case a {@link javax.jcr.LoginException} or {@link javax.jcr.RepositoryException} occurs. + */ + private Session getRepositorySession(WebdavRequest request) throws DavException { + try { + String workspaceName = null; + if (DavMethods.DAV_MKWORKSPACE != DavMethods.getMethodCode(request.getMethod())) { + workspaceName = request.getRequestLocator().getWorkspaceName(); + } + + Session session = sessionProvider.getSession( + request, repository, workspaceName); + + // extract information from Link header fields + LinkHeaderFieldParser lhfp = + new LinkHeaderFieldParser(request.getHeaders("Link")); + setJcrUserData(session, lhfp); + setSessionIdentifier(session, lhfp); + + return session; + } catch (LoginException e) { + // LoginException results in UNAUTHORIZED, + throw new JcrDavException(e); + } catch (RepositoryException e) { + // RepositoryException results in FORBIDDEN + throw new JcrDavException(e); + } catch (ServletException e) { + throw new DavException(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); + } + } + + /** + * Find first link relation for JCR user data and set it as + * the user data of the observation manager of the given session. + */ + private void setJcrUserData( + Session session, LinkHeaderFieldParser lhfp) + throws RepositoryException { + String data = null; + + // extract User Data string from RFC 2397 "data" URI + // only supports the simple case of "data:,..." for now + String target = lhfp.getFirstTargetForRelation( + JcrRemotingConstants.RELATION_USER_DATA); + if (target != null) { + try { + URI uri = new URI(target); + // Poor Man's data: URI parsing + if ("data".equalsIgnoreCase(uri.getScheme())) { + String sspart = uri.getRawSchemeSpecificPart(); + if (sspart.startsWith(",")) { + data = Text.unescape(sspart.substring(1)); + } + } + } catch (URISyntaxException ex) { + // not a URI, skip + } + } + + try { + session.getWorkspace().getObservationManager().setUserData(data); + } catch (UnsupportedRepositoryOperationException ignore) { + } + } + + /** + * Find first link relation for remote session identifier and set + * it as an attribute of the given session. + */ + private void setSessionIdentifier( + Session session, LinkHeaderFieldParser lhfp) { + if (session instanceof SessionExtensions) { + String name = JcrRemotingConstants.RELATION_REMOTE_SESSION_ID; + String id = lhfp.getFirstTargetForRelation(name); + ((SessionExtensions) session).setAttribute(name, id); + } + } + + private String getUserID(DavSession session) { + try { + Session s = DavSessionImpl.getRepositorySession(session); + if (s != null) { + return s.getUserID(); + } + } catch (DavException e) { + log.error(e.toString()); + } + // fallback + return session.toString(); + } + } +} Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/jcr/JCRWebdavServer.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/package-info.java =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/package-info.java (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/package-info.java (working copy) @@ -0,0 +1,18 @@ +/* + * 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. + */ +@org.osgi.annotation.versioning.Version("1.0") +package org.apache.jackrabbit.server; Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/package-info.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/remoting/davex/AclRemoveHandler.java =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/remoting/davex/AclRemoveHandler.java (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/remoting/davex/AclRemoveHandler.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.remoting.davex; + +import javax.jcr.Item; +import javax.jcr.Node; +import javax.jcr.RepositoryException; +import javax.jcr.Session; +import javax.jcr.security.AccessControlManager; +import javax.jcr.security.AccessControlPolicy; + +import org.apache.jackrabbit.util.Text; + +public class AclRemoveHandler implements ProtectedItemRemoveHandler { + + private static final String NT_REP_ACL = "rep:ACL"; + + @Override + public boolean remove(Session session, String itemPath) throws RepositoryException { + if (canHandle(session, itemPath)) { + String controlledPath = Text.getRelativeParent(itemPath, 1); + AccessControlManager acMgr = session.getAccessControlManager(); + AccessControlPolicy[] policies = acMgr.getPolicies(controlledPath); + for (AccessControlPolicy policy : policies) { + acMgr.removePolicy(controlledPath, policy); + } + return true; + } + return false; + } + + // -----------------------------------------------------------< private >--- + private boolean canHandle(Session session, String itemPath) throws RepositoryException { + Item aclItem = session.getItem(itemPath); + if (aclItem.isNode() && itemPath.startsWith("/")) { + if (isJackrabbitAclNodeType((Node) aclItem)) { + return true; + } + } + return false; + } + + private boolean isJackrabbitAclNodeType(Node aclNode) throws RepositoryException { + String ntName = aclNode.getPrimaryNodeType().getName(); + return ntName.equals(NT_REP_ACL); + } +} Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/remoting/davex/AclRemoveHandler.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/remoting/davex/BatchReadConfig.java =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/remoting/davex/BatchReadConfig.java (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/remoting/davex/BatchReadConfig.java (working copy) @@ -0,0 +1,170 @@ +/* + * 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.remoting.davex; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.jcr.Node; +import javax.jcr.RepositoryException; +import java.util.Map; +import java.util.HashMap; +import java.util.Properties; +import java.util.Enumeration; +import java.io.InputStream; +import java.io.IOException; + +/** + * BatchReadConfig defines if and how deep child item + * information should be retrieved, when accessing a Node. + * The configuration is based on node type names. + */ +class BatchReadConfig { + + private static Logger log = LoggerFactory.getLogger(BatchReadConfig.class); + + private static final String NAME_DEFAULT = "default"; + public static final int DEPTH_DEFAULT = 0; + public static final int DEPTH_INFINITE = -1; + + private int defaultDepth = DEPTH_DEFAULT; + private final Map depthMap = new HashMap(); + + /** + * Create an empty batch-read config. + */ + BatchReadConfig() {} + + /** + * Load the batch read configuration. + * + * @param in An input stream. + * @throws IOException If an error occurs. + */ + public void load(InputStream in) throws IOException { + Properties props = new Properties(); + props.load(in); + add(props); + } + + /** + * Add the configuration entries present in the given properties. + * + * @param props + */ + public void add(Properties props) { + for (Enumeration en = props.propertyNames(); en.hasMoreElements();) { + String name = en.nextElement().toString(); + String depthStr = props.getProperty(name); + try { + int depth = Integer.parseInt(depthStr); + if (depth < DEPTH_INFINITE) { + log.warn("invalid depth " + depthStr + " -> ignoring."); + continue; + } + if (NAME_DEFAULT.equals(name)) { + setDefaultDepth(depth); + } else { + setDepth(name, depth); + } + } catch (NumberFormatException e) { + // invalid entry in the properties file -> ignore + log.warn("Invalid depth value for name " + name + ". " + depthStr + " cannot be parsed into an integer."); + } + } + } + + /** + * Return the depth for the given node type name. If the name is + * not defined in this configuration, the {@link #DEPTH_DEFAULT default value} + * is returned. + * + * @param ntName The jcr name of the node type. + * @return {@link #DEPTH_INFINITE -1} If all child infos should be return or + * any value greater than {@link #DEPTH_DEFAULT 0} if only parts of the + * subtree should be returned. If the given nodetype name is not defined + * in this configuration, the default depth {@link #DEPTH_DEFAULT 0} will + * be returned. + */ + public int getDepth(String ntName) { + if (depthMap.containsKey(ntName)) { + return depthMap.get(ntName); + } else { + return defaultDepth; + } + } + + /** + * Return the depth for the given node or the default depth if the config + * does not provide an specific entry for the given node. + * + * @param node The node for with depth information should be retrieved. + * @return {@link #DEPTH_INFINITE -1} If all child infos should be return or + * any value greater than {@link #DEPTH_DEFAULT 0} if only parts of the + * subtree should be returned. + */ + public int getDepth(Node node) { + int depth = defaultDepth; + try { + String ntName = node.getPrimaryNodeType().getName(); + if (depthMap.containsKey(ntName)) { + depth = depthMap.get(ntName); + } + } catch (RepositoryException e) { + // ignore and return default. + } + return depth; + } + + /** + * Define the batch-read depth for the given node type name. + * + * @param ntName jcr name of the node type for which depth is defined. + * @param depth Depth for the specified node type name. + * @throws IllegalArgumentException if ntName is null + * or depth is lower than {@link #DEPTH_INFINITE}. + */ + public void setDepth(String ntName, int depth) { + if (ntName == null || depth < DEPTH_INFINITE) { + throw new IllegalArgumentException(); + } + depthMap.put(ntName, depth); + } + + /** + * Returns the default depth. + * + * @return the default depth. + */ + public int getDefaultDepth() { + return defaultDepth; + } + + /** + * Set the default depth. + * + * @param depth The default depth. + * @throws IllegalArgumentException if depth is lower than + * {@link #DEPTH_INFINITE}. + */ + public void setDefaultDepth(int depth) { + if (depth < -1) { + throw new IllegalArgumentException(); + } + defaultDepth = depth; + } +} Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/remoting/davex/BatchReadConfig.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/remoting/davex/DavexServletService.java =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/remoting/davex/DavexServletService.java (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/remoting/davex/DavexServletService.java (working copy) @@ -0,0 +1,190 @@ +/* + * 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.remoting.davex; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.Set; + +import javax.jcr.LoginException; +import javax.jcr.Repository; +import javax.jcr.RepositoryException; +import javax.jcr.Session; +import javax.servlet.Servlet; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; + +import org.apache.felix.scr.annotations.Activate; +import org.apache.felix.scr.annotations.Component; +import org.apache.felix.scr.annotations.Properties; +import org.apache.felix.scr.annotations.Property; +import org.apache.felix.scr.annotations.Reference; +import org.apache.felix.scr.annotations.ReferenceCardinality; +import org.apache.felix.scr.annotations.ReferencePolicy; +import org.apache.felix.scr.annotations.Service; +import org.apache.jackrabbit.server.SessionProvider; +import org.apache.jackrabbit.webdav.server.AbstractWebdavServlet; +import org.apache.jackrabbit.webdav.util.CSRFUtil; + +@Component(metatype = true, label = "%dav.name", description = "%dav.description") +@Service(Servlet.class) +@Properties({ + @Property(name = "service.description", value = "Apache Jackrabbit JcrRemoting Servlet"), + @Property(name = JcrRemotingServlet.INIT_PARAM_AUTHENTICATE_HEADER, value = AbstractWebdavServlet.DEFAULT_AUTHENTICATE_HEADER), + @Property(name = JcrRemotingServlet.INIT_PARAM_CSRF_PROTECTION, value = CSRFUtil.DISABLED), + @Property(name = JcrRemotingServlet.INIT_PARAM_MISSING_AUTH_MAPPING, value = ""), + @Property(name = "contextId", value = "") }) +@Reference( + name = "providers", referenceInterface = SessionProvider.class, + policy = ReferencePolicy.DYNAMIC, + cardinality = ReferenceCardinality.OPTIONAL_MULTIPLE, + bind = "addSessionProvider", unbind = "removeSessionProvider") +public class DavexServletService extends JcrRemotingServlet + implements SessionProvider { + + /** Serial version UID */ + private static final long serialVersionUID = -901601294536148635L; + + private static final String DEFAULT_ALIAS = "/server"; + + @Property(value = DEFAULT_ALIAS) + private static final String PARAM_ALIAS = "alias"; + + @Reference + private Repository repository; + + private String alias; + + /** + * Currently available custom session providers. They're used + * first before the default provider gets consulted. The associated + * set of sessions is used to forcibly release all sessions acquired + * from a provider when that provider is being removed. + */ + private final Map> providers = + new LinkedHashMap>(); + + /** + * Currently active sessions. Used to link a session to the correct + * provider in the {@link #releaseSession(Session)} method. + */ + private final Map sessions = + new HashMap(); + + @Override + protected Repository getRepository() { + return repository; + } + + @Override + protected String getResourcePathPrefix() { + return alias; + } + + @Activate + public void activate(Map config) { + Object object = config.get(PARAM_ALIAS); + String string = ""; + if (object != null) { + string = object.toString(); + } + if (string.length() > 0) { + this.alias = string; + } else { + this.alias = DEFAULT_ALIAS; + } + } + + @Override + protected SessionProvider getSessionProvider() { + return this; + } + + /** + * Adds a custom session provider service. + * + * @param provider session provider + */ + public synchronized void addSessionProvider(SessionProvider provider) { + providers.put(provider, new HashSet()); + } + + /** + * Removes a custom session provider service. All active sessions + * acquired from that provider are forcibly released. + * + * @param provider session provider + */ + public synchronized void removeSessionProvider(SessionProvider provider) { + Set sessions = providers.remove(provider); + if (sessions != null) { + for (Session session : sessions) { + releaseSession(session); + } + } + } + + //-----------------------------------------------------< SessionProvider > + + /** + * Asks each available session provider in order for a session and + * returns the first session given. The default provider is used + * if no custom provider service is available or can provide a requested + * session. + */ + public synchronized Session getSession( + HttpServletRequest request, Repository repository, String workspace) + throws LoginException, ServletException, RepositoryException { + SessionProvider provider = null; + Session session = null; + + for (Map.Entry> entry : providers.entrySet()) { + provider = entry.getKey(); + session = provider.getSession(request, repository, workspace); + if (session != null) { + entry.getValue().add(session); + break; + } + } + + if (session == null) { + provider = super.getSessionProvider(); + session = provider.getSession(request, repository, workspace); + } + + if (session != null) { + sessions.put(session, provider); + } + + return session; + } + + /** + * Releases the given session using the provider from which it was acquired. + */ + public synchronized void releaseSession(Session session) { + SessionProvider provider = sessions.remove(session); + if (provider != null) { + provider.releaseSession(session); + } + } + +} Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/remoting/davex/DavexServletService.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/remoting/davex/DiffException.java =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/remoting/davex/DiffException.java (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/remoting/davex/DiffException.java (working copy) @@ -0,0 +1,41 @@ +/* + * 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.remoting.davex; + +import java.io.IOException; + +/** + * DiffException... + */ +class DiffException extends IOException { + + private Throwable cause; + + public DiffException(String message) { + super(message); + } + + public DiffException(String message, Throwable cause) { + super(message); + this.cause = cause; + } + + @Override + public Throwable getCause() { + return cause; + } +} Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/remoting/davex/DiffException.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/remoting/davex/DiffHandler.java =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/remoting/davex/DiffHandler.java (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/remoting/davex/DiffHandler.java (working copy) @@ -0,0 +1,31 @@ +/* + * 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.remoting.davex; + +/** + * DiffHandler... + */ +interface DiffHandler { + + void addNode(String targetPath, String diffValue) throws DiffException; + + void setProperty(String targetPath, String diffValue) throws DiffException; + + void remove(String targetPath, String diffValue) throws DiffException; + + void move(String targetPath, String diffValue) throws DiffException; +} Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/remoting/davex/DiffHandler.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/remoting/davex/DiffParser.java =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/remoting/davex/DiffParser.java (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/remoting/davex/DiffParser.java (working copy) @@ -0,0 +1,218 @@ +/* + * 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.remoting.davex; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.Reader; +import java.io.StringReader; +import java.io.InputStream; +import java.io.InputStreamReader; + +/** DiffParser... */ +class DiffParser { + + // TODO: review again: currently all line-sep. chars before an diff-char are + // TODO: ignored unless they are escaped in way the handler understands (e.g. + // TODO: JSON does: \\r for \r). + // TODO: in contrast line sep. at the end of the string are treated as value. + // TODO: ... similar: line sep. following by non-diff symbol. + + private final DiffHandler handler; + + private static final int EOF = -1; + + private static final char SYMBOL_ADD_NODE = '+'; + private static final char SYMBOL_MOVE = '>'; + private static final char SYMBOL_REMOVE = '-'; + private static final char SYMBOL_SET_PROPERTY = '^'; + + private static final int STATE_START_LINE = 0; + private static final int STATE_START_TARGET = 1; + private static final int STATE_TARGET = 2; + private static final int STATE_START_VALUE = 3; + private static final int STATE_VALUE = 4; + + /** + * + * @param handler + */ + public DiffParser(DiffHandler handler) { + this.handler = handler; + } + + public void parse(String str) throws IOException, DiffException { + parse(new BufferedReader(new StringReader(str))); + } + + public void parse(InputStream input, String charSetName) throws IOException, DiffException { + parse(new BufferedReader(new InputStreamReader(input, charSetName))); + } + + public void parse(Reader reader) throws IOException, DiffException { + int action = -1; + String path = null; + + StringBuffer lineSeparator = null; + StringBuffer bf = null; + + int state = STATE_START_LINE; + int next = reader.read(); + + while (next != EOF) { + switch (state) { + case STATE_START_LINE: + if (isSymbol(next)) { + // notify the last action read + if (action > -1) { + informAction(action, path, bf); + } + // ... and start recording the next action + action = next; + bf = null; + lineSeparator = null; + state = STATE_START_TARGET; + } else if (isLineSeparator(next)) { + // still line-separator -> append c to the lineSeparator + // buffer and keep state set to STATE_START_LINE + if (lineSeparator == null) { + throw new DiffException("Invalid start of new line."); + } else { + lineSeparator.append((char) next); + } + } else if (lineSeparator != null && bf != null) { + // append the collected return/linefeed chars as part + // of the value read and continued reading value. + bf.append(lineSeparator); + bf.append((char) next); + lineSeparator = null; + state = STATE_VALUE; + } else { + throw new DiffException("Invalid start of new line."); + } + break; + + case STATE_START_TARGET: + if (Character.isWhitespace((char) next) || next == ':') { + throw new DiffException("Invalid start of target path '" + next + "'"); + } + bf = new StringBuffer(); + bf.append((char) next); + state = STATE_TARGET; + break; + + case STATE_TARGET: + if (Character.isWhitespace((char) next) && endsWithDelim(bf)) { + // a sequence of 'wsp:wsp' indicates the delimiter between + // the target path and the diff value. + path = bf.substring(0, bf.lastIndexOf(":")).trim(); + state = STATE_START_VALUE; + // reset buffer + bf = null; + } else { + // continue reading the path into the buffer. + bf.append((char) next); + } + break; + + case STATE_START_VALUE: + if (isLineSeparator(next)) { + lineSeparator = new StringBuffer(); + lineSeparator.append((char) next); + bf = new StringBuffer(); + state = STATE_START_LINE; + } else { + bf = new StringBuffer(); + bf.append((char) next); + state = STATE_VALUE; + } + break; + + case STATE_VALUE: + if (isLineSeparator(next)) { + lineSeparator = new StringBuffer(); + lineSeparator.append((char) next); + state = STATE_START_LINE; + } else { + bf.append((char) next); + // keep state set to STATE_VALUE + } + break; + + } + // read the next character. + next = reader.read(); + } + + // a diff ending after a command or within the target is invalid. + if (state == STATE_START_TARGET || state == STATE_TARGET) { + throw new DiffException("Invalid end of DIFF string: missing separator and value."); + } + if (state == STATE_START_VALUE ) { + // line separator AND buffer must be null + if (!(lineSeparator == null && bf == null)) { + throw new DiffException("Invalid end of DIFF string."); + } + } + + // append eventual remaining line-separators to the value + if (lineSeparator != null) { + bf.append(lineSeparator); + } + // notify the last action read + informAction(action, path, bf); + } + + private void informAction(int action, String path, StringBuffer diffVal) throws DiffException { + if (path == null) { + throw new DiffException("Missing path for action " + action + "(diffValue = '"+ diffVal +"')"); + } + String value = (diffVal == null) ? null : diffVal.toString(); + switch (action) { + case SYMBOL_ADD_NODE: + handler.addNode(path, value); + break; + case SYMBOL_SET_PROPERTY: + handler.setProperty(path, value); + break; + case SYMBOL_MOVE: + handler.move(path, value); + break; + case SYMBOL_REMOVE: + handler.remove(path, value); + break; + default: + throw new DiffException("Invalid action " + action); + } + } + + private static boolean isSymbol(int c) { + return c == SYMBOL_ADD_NODE || c == SYMBOL_SET_PROPERTY || c == SYMBOL_MOVE || c == SYMBOL_REMOVE; + } + + private static boolean isLineSeparator(int c) { + return c == '\n' || c == '\r'; + + } + private static boolean endsWithDelim(StringBuffer bf) { + if (bf.length() < 2) { + return false; + } else { + return ':' == bf.charAt(bf.length()-1) && Character.isWhitespace(bf.charAt(bf.length()-2)); + } + } +} Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/remoting/davex/DiffParser.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/remoting/davex/JcrRemotingServlet.java =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/remoting/davex/JcrRemotingServlet.java (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/remoting/davex/JcrRemotingServlet.java (working copy) @@ -0,0 +1,812 @@ +/* + * 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.remoting.davex; + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashSet; +import java.util.Iterator; +import java.util.Locale; +import java.util.Set; + +import javax.jcr.Item; +import javax.jcr.ItemNotFoundException; +import javax.jcr.Node; +import javax.jcr.NodeIterator; +import javax.jcr.PathNotFoundException; +import javax.jcr.RepositoryException; +import javax.jcr.Session; +import javax.jcr.Workspace; +import javax.jcr.nodetype.NodeType; +import javax.servlet.ServletConfig; +import javax.servlet.ServletContext; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletResponse; + +import org.apache.jackrabbit.JcrConstants; +import org.apache.jackrabbit.server.util.RequestData; +import org.apache.jackrabbit.util.Text; +import org.apache.jackrabbit.webdav.DavException; +import org.apache.jackrabbit.webdav.DavLocatorFactory; +import org.apache.jackrabbit.webdav.DavMethods; +import org.apache.jackrabbit.webdav.DavResource; +import org.apache.jackrabbit.webdav.DavResourceFactory; +import org.apache.jackrabbit.webdav.DavResourceLocator; +import org.apache.jackrabbit.webdav.DavServletResponse; +import org.apache.jackrabbit.webdav.DavSession; +import org.apache.jackrabbit.webdav.WebdavRequest; +import org.apache.jackrabbit.webdav.WebdavResponse; +import org.apache.jackrabbit.webdav.jcr.JCRWebdavServerServlet; +import org.apache.jackrabbit.webdav.jcr.JcrDavException; +import org.apache.jackrabbit.webdav.jcr.JcrDavSession; +import org.apache.jackrabbit.webdav.jcr.transaction.TxLockManagerImpl; +import org.apache.jackrabbit.webdav.observation.SubscriptionManager; +import org.apache.jackrabbit.webdav.version.DeltaVConstants; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * JcrRemotingServlet is an extended version of the + * {@link org.apache.jackrabbit.webdav.jcr.JCRWebdavServerServlet JCR Remoting Servlet} + * that provides improved + * + * functionality and supports cross workspace copy and cloning. + * + *

Batch Read

+ * + * Upon RepositoryService.getItemInfos a JSON object is composed containing + * the information for the requested node and its child items up to a + * specified or configuration determined depth. + *

+ * Batch read is triggered by adding a '.json' extension to the resource href. + * Optionally the client may explicitly specify the desired batch read depth + * by appending '.depth.json' extension. If no json extension is present the + * GET request is processed by the base servlet. + *

+ * The JSON writer applies the following rules: + * + *

+ * - Nodes are represented as JSON objects.
+ *
+ * - Each Node has its properties included as JSON key/value pairs.
+ *
+ * - Single valued Properties are simple key/value pairs.
+ *
+ * - Multi valued Properties are represented as JSON array.
+ *
+ * - Each Node has its child nodes included as long a maximal depths is not reached.
+ * 
+ * - Nodes without any child nodes get a special JSON member named
+ *   ::NodeIteratorSize, whose value is zero.
+ *
+ * - If the maximal depth is reached only name, index and unique id of the
+ *   direct child are included (incomplete node info). In order to obtain
+ *   the complete information the client sends another GET with .json extension.
+ * 
+ * + * Same name sibling nodes and properties whose type cannot be unambiguously be + * extracted from the JSON on the client side need some special handling: + * + *
+ * - Node with index > 1, get a JSON key consisting of
+ *   Node.getName() + "[" + Node.getIndex() + "]" 
+ *
+ * - Binary Property
+ *   JSON value = length of the JCR value.
+ *   The JCR value must be retrieved separately.
+ *
+ * - Name, Path, Reference and Date Property
+ *   The JSON member representing the Property (name, value) is preceded by a
+ *   special member consisting of
+ *   JSON key = ":" + Property.getName()
+ *   JSON value = PropertyType.nameFromValue(Property.getType())
+ *
+ * - Multi valued properties with Property.getValues().length == 0 will be
+ *   treated as special property types above (extra property indicating the
+ *   type of the property).
+ *
+ * - Double Property
+ *   JSON value must not have any trailing ".0" removed.
+ * 
+ * + *

Multi Read

+ *

+ * Since Jackrabbit 2.3.6 it is also possible to request multiple subtrees + * in a single request. This is done by adding one or more ":include" + * parameters to a batch read request describe above. These extra parameters + * specify the (relative) paths of all the nodes to be included in the + * response. The response is a JSON object whose "nodes" property contains + * all the selected nodes keyed by path. Missing nodes are not included in + * the response. Each included node is serialized as defined above for + * batch read. + *

+ * Example: + *

+ * $ curl 'http://.../parent.json?:path=child1&:path=child2'
+ * {"nodes":{"/parent/child1":{...},"/parent/child2":{...}}}
+ * 
+ * + *

Batch Write

+ * + * The complete SPI Batch is sent to the server in a single request, currently a + * POST request containing a custom ":diff" parameter. + *
+ * NOTE that this is targeted to be replaced by a PATCH request. + * + *

Diff format

+ * + * The diff parameter currently consists of JSON-like key-value pairs with the + * following special requirements: + * + *
+ *   diff       ::= members
+ *   members    ::= pair | pairs
+ *   pair       ::= key " : " value
+ *   pairs      ::= pair line-end pair | pair line-end pairs
+ *   line-end   ::= "\r\n" | "\n" | "\r"
+ *   key        ::= diffchar path
+ *   diffchar   ::= "+" | "^" | "-" | ">"
+ *   path       ::= abspath | relpath
+ *   abspath    ::= * absolute path to an item *
+ *   relpath    ::= * relpath from item at request URI to an item *
+ *   value      ::= value+ | value- | value^ | value>
+ *   value+     ::= * a JSON object *
+ *   value-     ::= ""
+ *   value^     ::= * any JSON value except JSON object *
+ *   value>     ::= path | path "#before" | path "#after" | "#first" | "#last"
+ * 
+ * + * In other words: + *
    + *
  • diff consists of one or more key-value pair(s)
  • + *
  • key must start with a diffchar followed by a rel. or abs. item path
  • + *
  • diffchar being any of "+", "^", "-" or ">" representing the transient + * item modifications as follows + *
    + *   "+" addNode
    + *   "^" setProperty / setValue / removeProperty
    + *   "-" remove Item
    + *   ">" move / reorder Nodes
    + * 
    + *
  • + *
  • key must be separated from the value by a ":" surrounded by whitespace.
  • + *
  • two pairs must be separated by a line end
  • + *
  • the format of the value depends on the diffchar
  • + *
  • for moving around node the value must consist of a abs. or rel. path. + * in contrast reordering of existing nodes is achieved by appending a trailing + * order position hint (#first, #last, #before or #after)
  • + *
+ * + * NOTE the following special handling of JCR properties of type + * Binary, Name, Path, Date and Reference: + *
    + *
  • the JSON value must be missing
  • + *
  • the POST request is expected to contain extra multipart(s) or request + * parameter(s) for the property value(s)
  • + *
  • the content type of the extra parts/params must reflect the property + * type:"jcr-value/" + PropertyType.nameFromValue(Property.getType).toLowerCase()
  • + *
+ * + * @see www.json.org for the definition of + * JSON object and JSON value. + */ +public abstract class JcrRemotingServlet extends JCRWebdavServerServlet { + + private static Logger log = LoggerFactory.getLogger(JcrRemotingServlet.class); + + /** + * the home init parameter. other relative filesystem paths are + * relative to this location. + */ + public static final String INIT_PARAM_HOME = "home"; + + /** + * the 'temp-directory' init parameter + */ + public static final String INIT_PARAM_TMP_DIRECTORY = "temp-directory"; + /** + * temp-dir attribute to be set to the servlet-context + */ + public static final String ATTR_TMP_DIRECTORY = "remoting-servlet.tmpdir"; + + /** + * the 'temp-directory' init parameter + */ + public static final String INIT_PARAM_BATCHREAD_CONFIG = "batchread-config"; + + /** + * the 'protectedhandlers-config' init paramter. this parameter contains the XML + * configuration file for protected item remove handlers. + */ + public static final String INIT_PARAM_PROTECTED_HANDLERS_CONFIG = "protectedhandlers-config"; + + private static final String PARAM_DIFF = ":diff"; + private static final String PARAM_COPY = ":copy"; + private static final String PARAM_CLONE = ":clone"; + private static final String PARAM_INCLUDE = ":include"; + + private static final String CONTENT_TYPE_APPLICATION_JSON = "application/json"; + + private BatchReadConfig brConfig; + private ProtectedRemoveManager protectedRemoveManager; + + @Override + public void init() throws ServletException { + super.init(); + + brConfig = new BatchReadConfig(); + String brConfigParam = getServletConfig().getInitParameter(INIT_PARAM_BATCHREAD_CONFIG); + if (brConfigParam == null) { + // TODO: define default values. + log.debug("batchread-config missing -> initialize defaults."); + brConfig.setDepth("nt:file", BatchReadConfig.DEPTH_INFINITE); + brConfig.setDefaultDepth(5); + } else { + try { + InputStream in = getServletContext().getResourceAsStream(brConfigParam); + if (in != null) { + brConfig.load(in); + } + } catch (IOException e) { + log.debug("Unable to build BatchReadConfig from " + brConfigParam + "."); + } + } + + String protectedHandlerConfig = getServletConfig().getInitParameter(INIT_PARAM_PROTECTED_HANDLERS_CONFIG); + InputStream in = null; + try { + in = getServletContext().getResourceAsStream(protectedHandlerConfig); + if (in != null){ + protectedRemoveManager = new ProtectedRemoveManager(); + protectedRemoveManager.load(in); + } else { + //Config might be direct class implementation + protectedRemoveManager = new ProtectedRemoveManager(protectedHandlerConfig); + } + } catch (IOException e) { + log.debug("Unable to create ProtectedRemoveManager from " + protectedHandlerConfig , e); + } finally{ + if (in != null){ + try { + in.close(); + } catch (IOException ignore) { + } + } + } + + // Determine the configured location for temporary files used when + // processing file uploads. Since JCR-3029 the default is the + // standard java.io.tmpdir location, but the presence of explicit + // configuration parameters restores the original behavior. + File tmp = null; + ServletConfig config = getServletConfig(); + String paramHome = config.getInitParameter(INIT_PARAM_HOME); + String paramTemp = config.getInitParameter(INIT_PARAM_TMP_DIRECTORY); + if (paramHome != null || paramTemp != null) { + if (paramHome == null) { + log.debug("Missing init-param " + INIT_PARAM_HOME + + ". Using default: 'jackrabbit'"); + paramHome = "jackrabbit"; + } else if (paramTemp == null) { + log.debug("Missing init-param " + INIT_PARAM_TMP_DIRECTORY + + ". Using default: 'tmp'"); + paramTemp = "tmp"; + } + + tmp = new File(paramHome, paramTemp); + try { + tmp = tmp.getCanonicalFile(); + tmp.mkdirs(); + log.debug(" temp-directory = " + tmp.getPath()); + } catch (IOException e) { + log.warn("Invalid temporary directory " + tmp.getPath() + + ", using system default instead", e); + tmp = null; + } + } + getServletContext().setAttribute(ATTR_TMP_DIRECTORY, tmp); + + // force usage of custom locator factory. + super.setLocatorFactory(new DavLocatorFactoryImpl(getResourcePathPrefix())); + } + + protected String getResourcePathPrefix() { + return getInitParameter(INIT_PARAM_RESOURCE_PATH_PREFIX); + } + + @Override + public DavResourceFactory getResourceFactory() { + return new ResourceFactoryImpl(txMgr, subscriptionMgr); + } + + @Override + protected void doGet(WebdavRequest webdavRequest, + WebdavResponse webdavResponse, + DavResource davResource) throws IOException, DavException { + if (canHandle(DavMethods.DAV_GET, webdavRequest, davResource)) { + // return json representation of the requested resource + DavResourceLocator locator = davResource.getLocator(); + String path = locator.getRepositoryPath(); + + Session session = getRepositorySession(webdavRequest); + try { + Node node = session.getNode(path); + int depth = ((WrappingLocator) locator).getDepth(); + + webdavResponse.setContentType(CONTENT_TYPE_APPLICATION_JSON); + webdavResponse.setCharacterEncoding(StandardCharsets.UTF_8.name()); + webdavResponse.setStatus(DavServletResponse.SC_OK); + JsonWriter writer = new JsonWriter(webdavResponse.getWriter()); + + String[] includes = webdavRequest.getParameterValues(PARAM_INCLUDE); + if (includes == null) { + if (depth < BatchReadConfig.DEPTH_INFINITE) { + NodeType type = node.getPrimaryNodeType(); + depth = brConfig.getDepth(type.getName()); + } + writer.write(node, depth); + } else { + writeMultiple(writer, node, includes, depth); + } + } catch (PathNotFoundException e) { + // properties cannot be requested as json object. + throw new JcrDavException( + new ItemNotFoundException("No node at " + path), + DavServletResponse.SC_NOT_FOUND); + } catch (RepositoryException e) { + // should only get here if the item does not exist. + log.debug(e.getMessage()); + throw new JcrDavException(e); + } + } else { + super.doGet(webdavRequest, webdavResponse, davResource); + } + } + + private void writeMultiple( + JsonWriter writer, Node node, String[] includes, int depth) + throws RepositoryException, IOException { + Collection nodes = new ArrayList(); + Set alreadyAdded = new HashSet(); + for (String include : includes) { + try { + Node n; + if (include.startsWith("/")) { + n = node.getSession().getNode(include); + } else { + n = node.getNode(include); + } + String np = n.getPath(); + if (!alreadyAdded.contains(np)) { + nodes.add(n); + alreadyAdded.add(np); + } + } catch (PathNotFoundException e) { + // skip missing node + } + } + writer.write(nodes, depth); + } + + @Override + protected void doPost(WebdavRequest webdavRequest, WebdavResponse webdavResponse, DavResource davResource) + throws IOException, DavException { + if (canHandle(DavMethods.DAV_POST, webdavRequest, davResource)) { + // special remoting request: the defined parameters are exclusive + // and cannot be combined. + Session session = getRepositorySession(webdavRequest); + RequestData data = new RequestData(webdavRequest, getTempDirectory(getServletContext())); + String loc = null; + try { + String[] pValues; + String[] includes = null; // multi-read over POST + if ((pValues = data.getParameterValues(PARAM_CLONE)) != null) { + loc = clone(session, pValues, davResource.getLocator()); + } else if ((pValues = data.getParameterValues(PARAM_COPY)) != null) { + loc = copy(session, pValues, davResource.getLocator()); + } else if (data.getParameterValues(PARAM_DIFF) != null) { + String targetPath = davResource.getLocator().getRepositoryPath(); + processDiff(session, targetPath, data, protectedRemoveManager); + } else if ((pValues = data.getParameterValues(PARAM_INCLUDE)) != null + && canHandle(DavMethods.DAV_GET, webdavRequest, davResource)) { + includes = pValues; + } else { + String targetPath = davResource.getLocator().getRepositoryPath(); + loc = modifyContent(session, targetPath, data, protectedRemoveManager); + } + + // TODO: append entity + if (loc == null) { + webdavResponse.setStatus(HttpServletResponse.SC_OK); + if (includes != null) { + webdavResponse.setContentType(CONTENT_TYPE_APPLICATION_JSON); + webdavResponse.setCharacterEncoding(StandardCharsets.UTF_8.name()); + JsonWriter writer = new JsonWriter(webdavResponse.getWriter()); + + DavResourceLocator locator = davResource.getLocator(); + String path = locator.getRepositoryPath(); + + Node node = session.getNode(path); + int depth = ((WrappingLocator) locator).getDepth(); + + writeMultiple(writer, node, includes, depth); + } + } else { + webdavResponse.setHeader(DeltaVConstants.HEADER_LOCATION, loc); + webdavResponse.setStatus(HttpServletResponse.SC_CREATED); + } + } catch (RepositoryException e) { + log.warn(e.getMessage(), e); + throw new JcrDavException(e); + } catch (DiffException e) { + log.warn(e.getMessage()); + Throwable cause = e.getCause(); + if (cause instanceof RepositoryException) { + throw new JcrDavException((RepositoryException) cause); + } else { + throw new DavException(DavServletResponse.SC_BAD_REQUEST, "Invalid diff format."); + } + } finally { + data.dispose(); + } + } else { + super.doPost(webdavRequest, webdavResponse, davResource); + } + } + + private boolean canHandle(int methodCode, WebdavRequest request, DavResource davResource) { + DavResourceLocator locator = davResource.getLocator(); + switch (methodCode) { + case DavMethods.DAV_GET: + return davResource.exists() && (locator instanceof WrappingLocator) + && ((WrappingLocator) locator).isJsonRequest; + case DavMethods.DAV_POST: + String ct = request.getContentType(); + if (ct == null) { + return false; + } else { + int semicolon = ct.indexOf(';'); + if (semicolon >= 0) { + ct = ct.substring(0, semicolon); + } + ct = ct.trim().toLowerCase(Locale.ENGLISH); + return "multipart/form-data".equals(ct) || "application/x-www-form-urlencoded".equals(ct); + } + default: + return false; + } + } + + private static String clone(Session session, String[] cloneArgs, DavResourceLocator reqLocator) throws RepositoryException { + Workspace wsp = session.getWorkspace(); + String destPath = null; + for (String cloneArg : cloneArgs) { + String[] args = cloneArg.split(","); + if (args.length == 4) { + wsp.clone(args[0], args[1], args[2], Boolean.valueOf(args[3])); + destPath = args[2]; + } else { + throw new RepositoryException(":clone parameter must have a value consisting of the 4 args needed for a Workspace.clone() call."); + } + } + return buildLocationHref(session, destPath, reqLocator); + } + + private static String copy(Session session, String[] copyArgs, DavResourceLocator reqLocator) throws RepositoryException { + Workspace wsp = session.getWorkspace(); + String destPath = null; + for (String copyArg : copyArgs) { + String[] args = copyArg.split(","); + switch (args.length) { + case 2: + wsp.copy(args[0], args[1]); + destPath = args[1]; + break; + case 3: + wsp.copy(args[0], args[1], args[2]); + destPath = args[2]; + break; + default: + throw new RepositoryException(":copy parameter must have a value consisting of 2 jcr paths or workspaceName plus 2 jcr paths separated by ','."); + } + } + return buildLocationHref(session, destPath, reqLocator); + } + + private static String buildLocationHref(Session s, String destPath, DavResourceLocator reqLocator) throws RepositoryException { + if (destPath != null) { + NodeIterator it = s.getRootNode().getNodes(destPath.substring(1)); + Node n = null; + while (it.hasNext()) { + n = it.nextNode(); + } + if (n != null) { + DavResourceLocator loc = reqLocator.getFactory().createResourceLocator(reqLocator.getPrefix(), reqLocator.getWorkspacePath(), n.getPath(), false); + return loc.getHref(true); + } + } + + // unable to determine -> no location header sent back. + return null; + } + + private static void processDiff(Session session, String targetPath, RequestData data, ProtectedRemoveManager protectedRemoveManager) + throws RepositoryException, DiffException, IOException { + + String[] diffs = data.getParameterValues(PARAM_DIFF); + DiffHandler handler = new JsonDiffHandler(session, targetPath, data, protectedRemoveManager); + DiffParser parser = new DiffParser(handler); + + for (String diff : diffs) { + boolean success = false; + try { + parser.parse(diff); + + session.save(); + success = true; + } finally { + if (!success) { + session.refresh(false); + } + } + } + } + + /** + * TODO: doesn't work properly with intermediate SNS-nodes + * TODO: doesn't respect jcr:uuid properties. + */ + private static String modifyContent(Session session, String targetPath, RequestData data, ProtectedRemoveManager protectedRemoveManager) + throws RepositoryException, DiffException { + + JsonDiffHandler dh = new JsonDiffHandler(session, targetPath, data, protectedRemoveManager); + boolean success = false; + try { + for (Iterator pNames = data.getParameterNames(); pNames.hasNext();) { + String paramName = pNames.next(); + String propPath = dh.getItemPath(paramName); + String parentPath = Text.getRelativeParent(propPath, 1); + + if (!session.itemExists(parentPath) || !session.getItem(parentPath).isNode()) { + createNode(session, parentPath, data); + } + + if (JcrConstants.JCR_PRIMARYTYPE.equals(Text.getName(propPath))) { + // already handled by createNode above -> ignore + continue; + } + // none of the special properties -> let the diffhandler take care + // of the property creation/modification. + dh.setProperty(paramName, null); + } + + // save the complete set of modifications + session.save(); + success = true; + } finally { + if (!success) { + session.refresh(false); + } + } + return null; // TODO build loc-href if items were created. + } + + private static void createNode(Session session, String nodePath, RequestData data) throws RepositoryException { + Node parent = session.getRootNode(); + String[] smgts = Text.explode(nodePath, '/'); + + for (String nodeName : smgts) { + if (parent.hasNode(nodeName)) { + parent = parent.getNode(nodeName); + } else { + // need to create the node + // TODO: won't work for SNS + String nPath = parent.getPath() + "/" + nodeName; + String ntName = data.getParameter(nPath + "/" + JcrConstants.JCR_PRIMARYTYPE); + if (ntName == null) { + parent = parent.addNode(nodeName); + } else { + parent = parent.addNode(nodeName, ntName); + } + } + } + } + + private static Session getRepositorySession(WebdavRequest request) throws DavException { + DavSession ds = request.getDavSession(); + return JcrDavSession.getRepositorySession(ds); + } + + /** + * Returns the temp directory + * + * @return the temp directory + */ + private static File getTempDirectory(ServletContext servletCtx) { + return (File) servletCtx.getAttribute(ATTR_TMP_DIRECTORY); + } + + //-------------------------------------------------------------------------- + /** + * Locator factory that specially deals with hrefs having a .json extension. + */ + private static class DavLocatorFactoryImpl extends org.apache.jackrabbit.webdav.jcr.DavLocatorFactoryImpl { + + public DavLocatorFactoryImpl(String s) { + super(s); + } + + @Override + public DavResourceLocator createResourceLocator(String prefix, String href) { + return createResourceLocator(prefix, href, false); + } + + @Override + public DavResourceLocator createResourceLocator(String prefix, String href, boolean forDestination) { + DavResourceLocator loc = super.createResourceLocator(prefix, href); + if (!forDestination && endsWithJson(href)) { + loc = new WrappingLocator(super.createResourceLocator(prefix, href)); + } + return loc; + } + + @Override + public DavResourceLocator createResourceLocator(String prefix, String workspacePath, String path, boolean isResourcePath) { + DavResourceLocator loc = super.createResourceLocator(prefix, workspacePath, path, isResourcePath); + if (isResourcePath && endsWithJson(path)) { + loc = new WrappingLocator(loc); + } + return loc; + } + + private static boolean endsWithJson(String s) { + return s.endsWith(".json"); + } + } + + /** + * Resource locator that removes trailing .json extensions and depth + * selector that do not form part of the repository path. + * As the locator and it's factory do not have access to a JCR session + * the extraJson flag may be reset later on. + * + * @see ResourceFactoryImpl#getItem(org.apache.jackrabbit.webdav.jcr.JcrDavSession, org.apache.jackrabbit.webdav.DavResourceLocator) + */ + private static class WrappingLocator implements DavResourceLocator { + + private final DavResourceLocator loc; + private boolean isJsonRequest = true; + private int depth = Integer.MIN_VALUE; + private String repositoryPath; + + private WrappingLocator(DavResourceLocator loc) { + this.loc = loc; + } + + private void extract() { + String rp = loc.getRepositoryPath(); + rp = rp.substring(0, rp.lastIndexOf('.')); + int pos = rp.lastIndexOf('.'); + if (pos > -1) { + String depthStr = rp.substring(pos + 1); + try { + depth = Integer.parseInt(depthStr); + rp = rp.substring(0, pos); + } catch (NumberFormatException e) { + // apparently no depth-info -> ignore + } + } + repositoryPath = rp; + } + + private int getDepth() { + if (isJsonRequest) { + if (repositoryPath == null) { + extract(); + } + return depth; + } else { + return Integer.MIN_VALUE; + } + } + + public String getPrefix() { + return loc.getPrefix(); + } + public String getResourcePath() { + return loc.getResourcePath(); + } + public String getWorkspacePath() { + return loc.getWorkspacePath(); + } + public String getWorkspaceName() { + return loc.getWorkspaceName(); + } + public boolean isSameWorkspace(DavResourceLocator davResourceLocator) { + return loc.isSameWorkspace(davResourceLocator); + } + public boolean isSameWorkspace(String string) { + return loc.isSameWorkspace(string); + } + public String getHref(boolean b) { + return loc.getHref(b); + } + public boolean isRootLocation() { + return loc.isRootLocation(); + } + public DavLocatorFactory getFactory() { + return loc.getFactory(); + } + public String getRepositoryPath() { + if (isJsonRequest) { + if (repositoryPath == null) { + extract(); + } + return repositoryPath; + } else { + return loc.getRepositoryPath(); + } + } + } + + /** + * Resource factory used to make sure that the .json extension was properly + * interpreted. + */ + private static class ResourceFactoryImpl extends org.apache.jackrabbit.webdav.jcr.DavResourceFactoryImpl { + + /** + * Create a new DavResourceFactoryImpl. + * + * @param txMgr + * @param subsMgr + */ + public ResourceFactoryImpl(TxLockManagerImpl txMgr, SubscriptionManager subsMgr) { + super(txMgr, subsMgr); + } + + @Override + protected Item getItem(JcrDavSession sessionImpl, DavResourceLocator locator) throws PathNotFoundException, RepositoryException { + if (locator instanceof WrappingLocator && ((WrappingLocator)locator).isJsonRequest) { + // check if the .json extension has been correctly interpreted. + Session s = sessionImpl.getRepositorySession(); + try { + if (s.itemExists(((WrappingLocator)locator).loc.getRepositoryPath())) { + // an item exists with the original calculated repo-path + // -> assume that the repository item path ends with .json + // or .depth.json. i.e. .json wasn't an extra extension + // appended to request the json-serialization of the node. + // -> change the flag in the WrappingLocator correspondingly. + ((WrappingLocator) locator).isJsonRequest = false; + } + } catch (RepositoryException e) { + // if the unmodified repository path isn't valid (e.g. /a/b[2].5.json) + // -> ignore. + } + } + return super.getItem(sessionImpl, locator); + } + } +} Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/remoting/davex/JcrRemotingServlet.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/remoting/davex/JsonDiffHandler.java =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/remoting/davex/JsonDiffHandler.java (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/remoting/davex/JsonDiffHandler.java (working copy) @@ -0,0 +1,1022 @@ +/* + * 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.remoting.davex; + +import org.apache.jackrabbit.JcrConstants; +import org.apache.jackrabbit.commons.webdav.JcrValueType; +import org.apache.jackrabbit.server.util.RequestData; +import org.apache.jackrabbit.spi.Name; +import org.apache.jackrabbit.commons.json.JsonHandler; +import org.apache.jackrabbit.commons.json.JsonParser; +import org.apache.jackrabbit.util.Text; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.xml.sax.ContentHandler; +import org.xml.sax.SAXException; +import org.xml.sax.helpers.AttributesImpl; + +import javax.jcr.ImportUUIDBehavior; +import javax.jcr.Item; +import javax.jcr.ItemNotFoundException; +import javax.jcr.Node; +import javax.jcr.NodeIterator; +import javax.jcr.Property; +import javax.jcr.PropertyType; +import javax.jcr.RepositoryException; +import javax.jcr.Session; +import javax.jcr.Value; +import javax.jcr.ValueFactory; +import javax.jcr.ValueFormatException; +import javax.jcr.nodetype.ConstraintViolationException; +import javax.jcr.nodetype.ItemDefinition; +import javax.jcr.nodetype.NodeDefinition; +import javax.jcr.nodetype.NodeType; +import javax.jcr.nodetype.NodeTypeManager; +import javax.jcr.nodetype.PropertyDefinition; +import java.io.IOException; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Stack; +import java.util.LinkedList; + +/** JsonDiffHandler... */ +class JsonDiffHandler implements DiffHandler { + + private static final Logger log = LoggerFactory.getLogger(JsonDiffHandler.class); + + private static final String ORDER_POSITION_AFTER = "#after"; + private static final String ORDER_POSITION_BEFORE = "#before"; + private static final String ORDER_POSITION_FIRST = "#first"; + private static final String ORDER_POSITION_LAST = "#last"; + + private final Session session; + private final ValueFactory vf; + private final String requestItemPath; + private final RequestData data; + private final ProtectedRemoveManager protectedRemoveManager; + + private NodeTypeManager ntManager; + + JsonDiffHandler(Session session, String requestItemPath, RequestData data) throws RepositoryException { + this(session, requestItemPath, data, null); + } + + JsonDiffHandler(Session session, String requestItemPath, RequestData data, ProtectedRemoveManager protectedRemoveManager) throws RepositoryException { + this.session = session; + this.requestItemPath = requestItemPath; + this.data = data; + vf = session.getValueFactory(); + this.protectedRemoveManager = protectedRemoveManager; + } + + //--------------------------------------------------------< DiffHandler >--- + /** + * @see DiffHandler#addNode(String, String) + */ + @Override + public void addNode(String targetPath, String diffValue) throws DiffException { + if (diffValue == null || !(diffValue.startsWith("{") && diffValue.endsWith("}"))) { + throw new DiffException("Invalid 'addNode' value '" + diffValue + "'"); + } + + try { + String itemPath = getItemPath(targetPath); + String parentPath = Text.getRelativeParent(itemPath, 1); + String nodeName = Text.getName(itemPath); + + addNode(parentPath, nodeName, diffValue); + + } catch (RepositoryException e) { + throw new DiffException(e.getMessage(), e); + } + } + + /** + * @see DiffHandler#setProperty(String, String) + */ + @Override + public void setProperty(String targetPath, String diffValue) throws DiffException { + try { + String itemPath = getItemPath(targetPath); + Item item = session.getItem(Text.getRelativeParent(itemPath, 1)); + if (!item.isNode()) { + throw new DiffException("No such node " + itemPath, new ItemNotFoundException(itemPath)); + } + + Node parent = (Node) item; + String propName = Text.getName(itemPath); + + if (JcrConstants.JCR_MIXINTYPES.equals(propName)) { + setMixins(parent, extractValuesFromRequest(targetPath)); + } else if (JcrConstants.JCR_PRIMARYTYPE.equals(propName)) { + setPrimaryType(parent, extractValuesFromRequest(targetPath)); + } else { + if (diffValue == null || diffValue.length() == 0) { + // single valued property with value present in multipart. + Value[] vs = extractValuesFromRequest(targetPath); + if (vs.length == 0) { + if (parent.hasProperty(propName)) { + // avoid problems with single vs. multi valued props. + parent.getProperty(propName).remove(); + } else { + // property does not exist -> stick to rule that missing + // [] indicates single valued. + parent.setProperty(propName, (Value) null); + } + } else if (vs.length == 1) { + parent.setProperty(propName, vs[0]); + } else { + throw new DiffException("Unexpected number of values in multipart. Was " + vs.length + " but expected 1."); + } + } else if (diffValue.startsWith("[") && diffValue.endsWith("]")) { + // multivalued property + if (diffValue.length() == 2) { + // empty array OR values in multipart + Value[] vs = extractValuesFromRequest(targetPath); + parent.setProperty(propName, vs); + } else { + // json array + Value[] vs = extractValues(diffValue); + parent.setProperty(propName, vs); + } + } else { + // single prop value included in the diff + Value v = extractValue(diffValue); + parent.setProperty(propName, v); + } + } + } catch (RepositoryException e) { + throw new DiffException(e.getMessage(), e); + } catch (IOException e) { + if (e instanceof DiffException) { + throw (DiffException) e; + } else { + throw new DiffException(e.getMessage(), e); + } + } + } + + /** + * @see DiffHandler#remove(String, String) + */ + @Override + public void remove(String targetPath, String diffValue) throws DiffException { + if (!(diffValue == null || diffValue.trim().length() == 0)) { + throw new DiffException("'remove' may not have a diffValue."); + } + try { + String itemPath = getItemPath(targetPath); + Item item = session.getItem(itemPath); + + ItemDefinition def = (item.isNode()) ? ((Node) item).getDefinition() : ((Property) item).getDefinition(); + if (def.isProtected()) { + // delegate to the manager. + if (protectedRemoveManager == null || !protectedRemoveManager.remove(session, itemPath)) { + throw new ConstraintViolationException("Cannot remove protected node: no suitable handler configured."); + } + } else { + item.remove(); + } + } catch (RepositoryException e) { + throw new DiffException(e.getMessage(), e); + } + } + + /** + * @see DiffHandler#move(String, String) + */ + @Override + public void move(String targetPath, String diffValue) throws DiffException { + if (diffValue == null || diffValue.length() == 0) { + throw new DiffException("Invalid 'move' value '" + diffValue + "'"); + } + try { + String srcPath = getItemPath(targetPath); + String orderPosition = getOrderPosition(diffValue); + if (orderPosition == null) { + // simple move + String destPath = getItemPath(diffValue); + session.move(srcPath, destPath); + } else { + String srcName = Text.getName(srcPath); + int pos = diffValue.lastIndexOf('#'); + String destName = (pos == 0) ? null : Text.getName(diffValue.substring(0, pos)); + + Item item = session.getItem(Text.getRelativeParent(srcPath, 1)); + if (!item.isNode()) { + throw new ItemNotFoundException(srcPath); + } + Node parent = (Node) item; + + if (ORDER_POSITION_FIRST.equals(orderPosition)) { + if (destName != null) { + throw new DiffException(ORDER_POSITION_FIRST + " may not have a leading destination."); + } + destName = Text.getName(parent.getNodes().nextNode().getPath()); + parent.orderBefore(srcName, destName); + } else if (ORDER_POSITION_LAST.equals(orderPosition)) { + if (destName != null) { + throw new DiffException(ORDER_POSITION_LAST + " may not have a leading destination."); + } + parent.orderBefore(srcName, null); + } else if (ORDER_POSITION_AFTER.equals(orderPosition)) { + if (destName == null) { + throw new DiffException(ORDER_POSITION_AFTER + " must have a leading destination."); + } + for (NodeIterator it = parent.getNodes(); it.hasNext();) { + Node child = it.nextNode(); + if (destName.equals(child.getName())) { + if (it.hasNext()) { + destName = Text.getName(it.nextNode().getName()); + } else { + destName = null; + } + break; + } + } + // reorder... if no child node matches the original destName + // the reorder will fail. no extra check. + parent.orderBefore(srcName, destName); + } else { + // standard jcr reorder (before) + parent.orderBefore(srcName, destName); + } + } + + } catch (RepositoryException e) { + throw new DiffException(e.getMessage(), e); + } + } + + //-------------------------------------------------------------------------- + /** + * + * @param diffPath + * @return + * @throws RepositoryException + */ + String getItemPath(String diffPath) throws RepositoryException { + StringBuffer itemPath; + if (!diffPath.startsWith("/")) { + // diff path is relative to the item path retrieved from the + // request URI -> calculate item path. + itemPath = new StringBuffer(requestItemPath); + if (!requestItemPath.endsWith("/")) { + itemPath.append('/'); + } + itemPath.append(diffPath); + } else { + itemPath = new StringBuffer(diffPath); + } + return normalize(itemPath.toString()); + } + + private void addNode(String parentPath, String nodeName, String diffValue) + throws DiffException, RepositoryException { + Item item = session.getItem(parentPath); + if (!item.isNode()) { + throw new ItemNotFoundException(parentPath); + } + + Node parent = (Node) item; + try { + NodeHandler hndlr = new NodeHandler(parent, nodeName); + new JsonParser(hndlr).parse(diffValue); + } catch (IOException e) { + if (e instanceof DiffException) { + throw (DiffException) e; + } else { + throw new DiffException(e.getMessage(), e); + } + } + } + + private NodeTypeManager getNodeTypeManager() throws RepositoryException { + if (ntManager == null) { + ntManager = session.getWorkspace().getNodeTypeManager(); + } + return ntManager; + } + + private static String normalize(String path) { + if (path.indexOf('.') == -1) { + return path; + } + String[] elems = Text.explode(path, '/', false); + LinkedList queue = new LinkedList(); + String last = ".."; + for (String segm : elems) { + if ("..".equals(segm) && !"..".equals(last)) { + queue.removeLast(); + if (queue.isEmpty()) { + last = ".."; + } else { + last = queue.getLast(); + } + } else if (!".".equals(segm)) { + last = segm; + queue.add(last); + } + } + return "/" + Text.implode(queue.toArray(new String[queue.size()]), "/"); + } + + private static ContentHandler createContentHandler(Node parent) throws RepositoryException { + return parent.getSession().getImportContentHandler(parent.getPath(), ImportUUIDBehavior.IMPORT_UUID_COLLISION_THROW); + } + + private static Node importNode(Node parent, String nodeName, String ntName, + String uuid) throws RepositoryException { + + String uri = "http://www.jcp.org/jcr/sv/1.0"; + String prefix = "sv:"; + + ContentHandler ch = createContentHandler(parent); + try { + ch.startDocument(); + + String nN = "node"; + AttributesImpl attrs = new AttributesImpl(); + attrs.addAttribute(uri, "name", prefix + "name", "CDATA", nodeName); + ch.startElement(uri, nN, prefix + nN, attrs); + + // primary node type + String pN = "property"; + attrs = new AttributesImpl(); + attrs.addAttribute(uri, "name", prefix + "name", "CDATA", JcrConstants.JCR_PRIMARYTYPE); + attrs.addAttribute(uri, "type", prefix + "type", "CDATA", PropertyType.nameFromValue(PropertyType.NAME)); + ch.startElement(uri, pN, prefix + pN, attrs); + ch.startElement(uri, "value", prefix + "value", new AttributesImpl()); + char[] val = ntName.toCharArray(); + ch.characters(val, 0, val.length); + ch.endElement(uri, "value", prefix + "value"); + ch.endElement(uri, pN, prefix + pN); + + // uuid + attrs = new AttributesImpl(); + attrs.addAttribute(uri, "name", prefix + "name", "CDATA", JcrConstants.JCR_UUID); + attrs.addAttribute(uri, "type", prefix + "type", "CDATA", PropertyType.nameFromValue(PropertyType.STRING)); + ch.startElement(uri, pN, prefix + pN, attrs); + ch.startElement(uri, "value", prefix + "value", new AttributesImpl()); + val = uuid.toCharArray(); + ch.characters(val, 0, val.length); + ch.endElement(uri, "value", prefix + "value"); + ch.endElement(uri, pN, prefix + pN); + + ch.endElement(uri, nN, prefix + nN); + ch.endDocument(); + + } catch (SAXException e) { + throw new RepositoryException(e); + } + + Node n = null; + NodeIterator it = parent.getNodes(nodeName); + while (it.hasNext()) { + n = it.nextNode(); + } + if (n == null) { + throw new RepositoryException("Internal error: No child node added."); + } + return n; + } + + private static void setPrimaryType(Node n, Value[] values) throws RepositoryException, DiffException { + if (values.length == 1) { + String ntName = values[0].getString(); + if (!ntName.equals(n.getPrimaryNodeType().getName())) { + n.setPrimaryType(ntName); + } // else: same primaryType as before -> nothing to do. + } else { + throw new DiffException("Invalid diff: jcr:primarytype cannot have multiple values, nor can it's value be removed."); + } + } + + private static void setMixins(Node n, Value[] values) throws RepositoryException { + if (values.length == 0) { + // remove all mixins + NodeType[] mixins = n.getMixinNodeTypes(); + for (NodeType mixin : mixins) { + String mixinName = mixin.getName(); + n.removeMixin(mixinName); + } + } else { + List newMixins = new ArrayList(values.length); + for (Value value : values) { + newMixins.add(value.getString()); + } + NodeType[] mixins = n.getMixinNodeTypes(); + for (NodeType mixin : mixins) { + String mixinName = mixin.getName(); + if (!newMixins.remove(mixinName)) { + n.removeMixin(mixinName); + } + } + for (String newMixinName : newMixins) { + n.addMixin(newMixinName); + } + } + } + + private static String getOrderPosition(String diffValue) { + String position = null; + if (diffValue.indexOf('#') > -1) { + if (diffValue.endsWith(ORDER_POSITION_FIRST) || + diffValue.endsWith(ORDER_POSITION_LAST) || + diffValue.endsWith(ORDER_POSITION_BEFORE) || + diffValue.endsWith(ORDER_POSITION_AFTER)) { + position = diffValue.substring(diffValue.lastIndexOf('#')); + } // else: apparently # is part of the move path. + } + return position; + } + + private Value[] extractValuesFromRequest(String paramName) throws RepositoryException, IOException { + ValueFactory vf = session.getValueFactory(); + Value[] vs; + InputStream[] ins = data.getFileParameters(paramName); + if (ins != null) { + vs = new Value[ins.length]; + for (int i = 0; i < ins.length; i++) { + vs[i] = vf.createValue(ins[i]); + } + } else { + String[] strs = data.getParameterValues(paramName); + if (strs == null) { + vs = new Value[0]; + } else { + List valList = new ArrayList(strs.length); + for (int i = 0; i < strs.length; i++) { + if (strs[i] != null) { + String[] types = data.getParameterTypes(paramName); + int type = (types == null || types.length <= i) ? PropertyType.UNDEFINED : JcrValueType.typeFromContentType(types[i]); + if (type == PropertyType.UNDEFINED) { + valList.add(vf.createValue(strs[i])); + } else { + valList.add(vf.createValue(strs[i], type)); + } + } + } + vs = valList.toArray(new Value[valList.size()]); + } + } + return vs; + } + + private Value extractValue(String diffValue) throws RepositoryException, DiffException, IOException { + ValueHandler hndlr = new ValueHandler(); + // surround diff value { key : } to make it parsable + new JsonParser(hndlr).parse("{\"a\":"+diffValue+"}"); + + return hndlr.getValue(); + } + + private Value[] extractValues(String diffValue) throws RepositoryException, DiffException, IOException { + ValuesHandler hndlr = new ValuesHandler(); + // surround diff value { key : } to make it parsable + new JsonParser(hndlr).parse("{\"a\":" + diffValue + "}"); + + return hndlr.getValues(); + } + + //-------------------------------------------------------------------------- + /** + * Inner class used to parse a single value + */ + private final class ValueHandler implements JsonHandler { + private Value v; + + @Override + public void object() throws IOException { + // ignore + } + @Override + public void endObject() throws IOException { + // ignore + } + @Override + public void array() throws IOException { + // ignore + } + @Override + public void endArray() throws IOException { + // ignore + } + @Override + public void key(String key) throws IOException { + // ignore + } + + @Override + public void value(String value) throws IOException { + v = (value == null) ? null : vf.createValue(value); + } + @Override + public void value(boolean value) throws IOException { + v = vf.createValue(value); + } + @Override + public void value(long value) throws IOException { + v = vf.createValue(value); + } + @Override + public void value(double value) throws IOException { + v = vf.createValue(value); + } + + private Value getValue() { + return v; + } + } + + /** + * Inner class used to parse the values from a simple json array + */ + private final class ValuesHandler implements JsonHandler { + private List values = new ArrayList(); + + @Override + public void object() throws IOException { + // ignore + } + @Override + public void endObject() throws IOException { + // ignore + } + @Override + public void array() throws IOException { + // ignore + } + @Override + public void endArray() throws IOException { + // ignore + } + @Override + public void key(String key) throws IOException { + // ignore + } + + @Override + public void value(String value) throws IOException { + if (value != null) { + values.add(vf.createValue(value)); + } else { + log.warn("Null element for a multivalued property -> Ignore."); + } + } + @Override + public void value(boolean value) throws IOException { + values.add(vf.createValue(value)); + } + @Override + public void value(long value) throws IOException { + values.add(vf.createValue(value)); + } + @Override + public void value(double value) throws IOException { + values.add(vf.createValue(value)); + } + + private Value[] getValues() { + return values.toArray(new Value[values.size()]); + } + } + + /** + * Inner class for parsing a simple json object defining a node and its + * child nodes and/or child properties + */ + private final class NodeHandler implements JsonHandler { + private Node parent; + private String key; + + private Stack st = new Stack(); + + private NodeHandler(Node parent, String nodeName) throws IOException { + this.parent = parent; + key = nodeName; + } + + @Override + public void object() throws IOException { + ImportNode n; + if (st.isEmpty()) { + try { + n = new ImportNode(parent.getPath(), key); + } catch (RepositoryException e) { + throw new DiffException(e.getMessage(), e); + } + + } else { + ImportItem obj = st.peek(); + n = new ImportNode(obj.getPath(), key); + if (obj instanceof ImportNode) { + ((ImportNode) obj).addNode(n); + } else { + throw new DiffException("Invalid DIFF format: The JSONArray may only contain simple values."); + } + } + st.push(n); + } + + @Override + public void endObject() throws IOException { + // element on stack must be ImportMvProp since array may only + // contain simple values, no arrays/objects are allowed. + ImportItem obj = st.pop(); + if (!((obj instanceof ImportNode))) { + throw new DiffException("Invalid DIFF format."); + } + if (st.isEmpty()) { + // everything parsed -> start adding all nodes and properties + try { + if (obj.mandatesImport(parent)) { + obj.importItem(createContentHandler(parent)); + } else { + obj.createItem(parent); + } + } catch (IOException e) { + log.error(e.getMessage()); + throw new DiffException(e.getMessage(), e); + } catch (RepositoryException e) { + log.error(e.getMessage()); + throw new DiffException(e.getMessage(), e); + } + } + } + + @Override + public void array() throws IOException { + ImportItem obj = st.peek(); + ImportMvProp prop = new ImportMvProp(obj.getPath(), key); + if (obj instanceof ImportNode) { + ((ImportNode)obj).addProp(prop); + } else { + throw new DiffException("Invalid DIFF format: The JSONArray may only contain simple values."); + } + st.push(prop); + } + + @Override + public void endArray() throws IOException { + // element on stack must be ImportMvProp since array may only + // contain simple values, no arrays/objects are allowed. + ImportItem obj = st.pop(); + if (!((obj instanceof ImportMvProp))) { + throw new DiffException("Invalid DIFF format: The JSONArray may only contain simple values."); + } + } + + @Override + public void key(String key) throws IOException { + this.key = key; + } + + @Override + public void value(String value) throws IOException { + Value v = (value == null) ? null : vf.createValue(value); + value(v); + } + + @Override + public void value(boolean value) throws IOException { + value(vf.createValue(value)); + } + + @Override + public void value(long value) throws IOException { + Value v = vf.createValue(value); + value(v); + } + + @Override + public void value(double value) throws IOException { + value(vf.createValue(value)); + } + + private void value(Value v) throws IOException { + ImportItem obj = st.peek(); + if (obj instanceof ImportMvProp) { + ((ImportMvProp) obj).values.add(v); + } else { + ((ImportNode) obj).addProp(new ImportProp(obj.getPath(), key, v)); + } + } + } + + private abstract class ImportItem { + + static final String TYPE_CDATA = "CDATA"; + + final String parentPath; + final String name; + final String path; + + private ImportItem(String parentPath, String name) throws IOException { + if (name == null) { + throw new DiffException("Invalid DIFF format: NULL key."); + } + this.name = name; + this.parentPath = parentPath; + this.path = parentPath+"/"+name; + } + + void setNameAttribute(AttributesImpl attr) { + attr.addAttribute(Name.NS_SV_URI, "name", Name.NS_SV_PREFIX +":name", TYPE_CDATA, name); + } + + String getPath() { + return path; + } + + abstract boolean mandatesImport(Node parent); + + abstract void createItem(Node parent) throws RepositoryException, IOException; + + abstract void importItem(ContentHandler contentHandler) throws IOException; + } + + private final class ImportNode extends ImportItem { + + private static final String LOCAL_NAME = "node"; + + private ImportProp ntName; + private ImportProp uuid; + + private List childN = new ArrayList(); + private List childP = new ArrayList(); + + private ImportNode(String parentPath, String name) throws IOException { + super(parentPath, name); + } + + private String getUUID() { + if (uuid != null && uuid.value != null) { + try { + return uuid.value.getString(); + } catch (RepositoryException e) { + log.error(e.getMessage()); + } + } + return null; + } + + private String getPrimaryType() { + if (ntName != null && ntName.value != null) { + try { + return ntName.value.getString(); + } catch (RepositoryException e) { + log.error(e.getMessage()); + } + } + return null; + } + + @Override + boolean mandatesImport(Node parent) { + String primaryType = getPrimaryType(); + // Very simplistic and simplified test for protection that doesn't + // take mixin types into account and ignores all JCR primary types + if (!primaryType.startsWith(Name.NS_NT_PREFIX)) { + try { + NodeType nt = getNodeTypeManager().getNodeType(primaryType); + for (NodeDefinition nd : nt.getChildNodeDefinitions()) { + if (nd.isProtected()) { + return true; + } + } + for (PropertyDefinition pd : nt.getPropertyDefinitions()) { + if (!pd.getName().startsWith(Name.NS_JCR_PREFIX) && pd.isProtected()) { + return true; + } + } + } catch (RepositoryException e) { + log.warn(e.getMessage(), e); + } + } + return false; + } + + void addProp(ImportProp prop) { + if (prop.name.equals(JcrConstants.JCR_PRIMARYTYPE)) { + ntName = prop; + } else if (prop.name.equals(JcrConstants.JCR_UUID)) { + uuid = prop; + } else { + // regular property + childP.add(prop); + } + } + + void addProp(ImportMvProp prop) { + childP.add(prop); + } + + void addNode(ImportNode node) { + childN.add(node); + } + + @Override + void importItem(ContentHandler contentHandler) throws IOException { + try { + AttributesImpl attr = new AttributesImpl(); + setNameAttribute(attr); + contentHandler.startElement(Name.NS_SV_URI, LOCAL_NAME, Name.NS_SV_PREFIX+":"+LOCAL_NAME, attr); + + if (ntName != null && ntName.value != null) { + ntName.importItem(contentHandler); + } + if (uuid != null && uuid.value != null) { + uuid.importItem(contentHandler); + } + + for(ImportProperty prop : childP) { + prop.importItem(contentHandler); + } + + for(ImportNode node : childN) { + node.importItem(contentHandler); + } + contentHandler.endElement(Name.NS_SV_URI, LOCAL_NAME, Name.NS_SV_PREFIX+":"+LOCAL_NAME); + } catch(SAXException e) { + throw new DiffException(e.getMessage(), e); + } + } + + @Override + void createItem(Node parent) throws RepositoryException, IOException { + if (mandatesImport(parent)) { + ContentHandler ch = createContentHandler(parent); + try { + ch.startDocument(); + importItem(ch); + ch.endDocument(); + } catch (SAXException e) { + throw new DiffException(e.getMessage(), e); + } + } else { + Node n; + String uuidValue = getUUID(); + String primaryType = getPrimaryType(); + if (uuidValue == null) { + n = (primaryType == null) ? parent.addNode(name) : parent.addNode(name, primaryType); + } else { + n = importNode(parent, name, primaryType, uuidValue); + } + // create all properties + for (ImportItem obj : childP) { + obj.createItem(n); + } + // recursively create all child nodes + for (ImportItem obj : childN) { + obj.createItem(n); + } + } + } + } + + private abstract class ImportProperty extends ImportItem { + + static final String VALUE = "value"; + static final String TYPE = "type"; + static final String LOCAL_NAME = "property"; + + private ImportProperty(String parentPath, String name) throws IOException { + super(parentPath, name); + } + + @Override + boolean mandatesImport(Node parent) { + // TODO: verify again if a protected property (except for jcr:primaryType and jcr:mixinTypes) will ever change outside the scope of importing the whole tree. + return false; + } + + @Override + void importItem(ContentHandler contentHandler) throws IOException { + try { + AttributesImpl propAtts = new AttributesImpl(); + setNameAttribute(propAtts); + setTypeAttribute(propAtts); + contentHandler.startElement(Name.NS_SV_URI, LOCAL_NAME, Name.NS_SV_PREFIX+":"+LOCAL_NAME, propAtts); + startValueElement(contentHandler); + contentHandler.endElement(Name.NS_SV_URI, LOCAL_NAME, Name.NS_SV_PREFIX+":"+LOCAL_NAME); + } catch(SAXException e) { + throw new DiffException(e.getMessage(), e); + } + } + + void setTypeAttribute(AttributesImpl attr) { + String type = null; + if (name.equals(JcrConstants.JCR_PRIMARYTYPE)) { + type = PropertyType.nameFromValue(PropertyType.NAME); + } else if (name.equals(JcrConstants.JCR_MIXINTYPES)) { + type = PropertyType.nameFromValue(PropertyType.NAME); + } else if (name.equals(JcrConstants.JCR_UUID)) { + type = PropertyType.nameFromValue(PropertyType.STRING); + } else { + type = PropertyType.nameFromValue(PropertyType.UNDEFINED); + } + attr.addAttribute(Name.NS_SV_URI, TYPE, Name.NS_SV_PREFIX+":"+TYPE, TYPE_CDATA, type); + } + + abstract void startValueElement(ContentHandler contentHandler) throws IOException; + } + + private final class ImportProp extends ImportProperty { + + private final Value value; + + private ImportProp(String parentPath, String name, Value value) throws IOException { + super(parentPath, name); + try { + if (value == null) { + this.value = extractValuesFromRequest(getPath())[0]; + } else { + this.value = value; + } + } catch (RepositoryException e) { + throw new DiffException(e.getMessage(), e); + } + } + + @Override + void createItem(Node parent) throws RepositoryException { + parent.setProperty(name, value); + } + + @Override + void startValueElement(ContentHandler contentHandler) throws IOException { + try { + String str = value.getString(); + contentHandler.startElement(Name.NS_SV_URI, VALUE, Name.NS_SV_PREFIX + ":" + VALUE, new AttributesImpl()); + contentHandler.characters(str.toCharArray(), 0, str.length()); + contentHandler.endElement(Name.NS_SV_URI, VALUE, Name.NS_SV_PREFIX + ":" + VALUE); + } catch (SAXException e) { + throw new DiffException(e.getMessage()); + } catch (ValueFormatException e) { + throw new DiffException(e.getMessage()); + } catch (RepositoryException e) { + throw new DiffException(e.getMessage()); + } + } + } + + private final class ImportMvProp extends ImportProperty { + + private List values = new ArrayList(); + + private ImportMvProp(String parentPath, String name) throws IOException { + super(parentPath, name); + } + + @Override + void createItem(Node parent) throws RepositoryException { + Value[] vls = values.toArray(new Value[values.size()]); + if (JcrConstants.JCR_MIXINTYPES.equals(name)) { + setMixins(parent, vls); + } else { + parent.setProperty(name, vls); + } + } + + @Override + void startValueElement(ContentHandler contentHandler) throws IOException { + try { + // Multi-valued property with values present in the request + // multi-part + if (values.size() == 0) { + values = Arrays.asList(extractValuesFromRequest(getPath())); + } + + for (Value v : values) { + String str = v.getString(); + contentHandler.startElement(Name.NS_SV_URI, VALUE, Name.NS_SV_PREFIX + ":" + VALUE, new AttributesImpl()); + contentHandler.characters(str.toCharArray(), 0, str.length()); + contentHandler.endElement(Name.NS_SV_URI, VALUE, Name.NS_SV_PREFIX + ":" + VALUE); + } + } catch (SAXException e) { + throw new DiffException(e.getMessage()); + } catch (ValueFormatException e) { + throw new DiffException(e.getMessage()); + } catch (RepositoryException e) { + throw new DiffException(e.getMessage()); + } + } + } +} Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/remoting/davex/JsonDiffHandler.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/remoting/davex/JsonWriter.java =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/remoting/davex/JsonWriter.java (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/remoting/davex/JsonWriter.java (working copy) @@ -0,0 +1,292 @@ +/* + * 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.remoting.davex; + +import java.io.IOException; +import java.io.Writer; +import java.util.Collection; +import javax.jcr.Node; +import javax.jcr.NodeIterator; +import javax.jcr.Property; +import javax.jcr.PropertyIterator; +import javax.jcr.PropertyType; +import javax.jcr.RepositoryException; +import javax.jcr.Value; + +import org.apache.jackrabbit.JcrConstants; +import org.apache.jackrabbit.commons.json.JsonUtil; + +/** + * JsonWriter traverses a tree of JCR items and writes a JSON object + * exposing nodes as JSON object members and properties as JSON pairs. + *

+ * Note: Using JSON.org library is deliberately avoided for the + * following reasons. + *

    + *
  • JSONObject does not preserve the order of members added, which is required + * for JCR remoting.
  • + *
  • JSONObject#numberToString: + * Double numbers get their trailing '.0' stripped away, which removes + * the ability to distinguish between JCR values of type {@link PropertyType#DOUBLE} + * and {@link PropertyType#LONG}.
  • + *
+ */ +class JsonWriter { + + private final Writer writer; + + /** + * Create a new JsonItemWriter + * + * @param writer Writer to which the generated JSON string is written. + */ + JsonWriter(Writer writer) { + this.writer = writer; + } + + void write(Node node, int maxLevels) throws RepositoryException, IOException { + write(node, 0, maxLevels); + } + + void write(Collection nodes, int maxLevels) + throws RepositoryException, IOException { + writer.write('{'); + writeKey("nodes"); + writer.write('{'); + boolean first = true; + for (Node node : nodes) { + if (first) { + first = false; + } else { + writer.write(','); + } + writeKey(node.getPath()); + write(node, maxLevels); + } + writer.write('}'); + writer.write('}'); + } + + private void write(Node node, int currentLevel, int maxLevels) + throws RepositoryException, IOException { + // start of node info + writer.write('{'); + + // append the jcr properties as JSON pairs. + PropertyIterator props = node.getProperties(); + while (props.hasNext()) { + Property prop = props.nextProperty(); + writeProperty(prop); + // add separator: next json pair/member is either a property or + // a childnode or the special no-children-present pair. + writer.write(','); + } + + // for jcr child nodes include member unless the max-depths is reached. + // in case there are no children at all, append a special pair. + final NodeIterator children = node.getNodes(); + if (!children.hasNext()) { + // no child present at all -> add special property. + writeKeyValue("::NodeIteratorSize", 0); + } else { + // the child nodes + while (children.hasNext()) { + final Node n = children.nextNode(); + String name = n.getName(); + int index = n.getIndex(); + if (index > 1) { + writeKey(name + "[" + index + "]"); + } else { + writeKey(name); + } + if (maxLevels < 0 || currentLevel < maxLevels) { + write(n, currentLevel + 1, maxLevels); + } else { + /** + * In order to be able to compute the set of child-node entries + * upon Node creation -> add incomplete "node info" JSON + * object for the child node omitting properties and child + * information except for the jcr:uuid property (if present + * at all). + * the latter is required in order to build the correct SPI + * ChildInfo for Node n. + */ + writeChildInfo(n); + } + if (children.hasNext()) { + writer.write(','); + } + } + } + + // end of node info + writer.write('}'); + } + + /** + * Write child info without including the complete node info. + * + * @param n + * @throws RepositoryException + * @throws IOException + */ + private void writeChildInfo(Node n) throws RepositoryException, IOException { + // start child info + writer.write('{'); + + // make sure the SPI childInfo can be built correctly on the + // client side -> pass uuid if present. + if (n.isNodeType(JcrConstants.MIX_REFERENCEABLE) && + n.hasProperty(JcrConstants.JCR_UUID)) { + writeProperty(n.getProperty(JcrConstants.JCR_UUID)); + } + + // end child info + writer.write('}'); + } + + /** + * Write a single property + * + * @param p + * @throws javax.jcr.RepositoryException + * @throws java.io.IOException + */ + private void writeProperty(Property p) throws RepositoryException, IOException { + // special handling for binaries: we dump the length and not the length + int type = p.getType(); + if (type == PropertyType.BINARY) { + // mark binary properties with a leading ':' + // the value(s) reflect the jcr-values length instead of the binary data. + String key = ":" + p.getName(); + if (p.isMultiple()) { + long[] binLengths = p.getLengths(); + writeKeyArray(key, binLengths); + } else { + writeKeyValue(key, p.getLength()); + } + } else { + boolean isMultiple = p.isMultiple(); + if (requiresTypeInfo(p) || (isMultiple && p.getValues().length == 0)) { + /* special property types that have no correspondence in JSON + are transported as String. the type is transported with an + extra key-value pair, the key having a leading ':' the value + reflects the type. + the same applies for multivalued properties consisting of an + empty array -> property type guessing would not be possible. + */ + writeKeyValue(":" + p.getName(), PropertyType.nameFromValue(type), true); + } + /* append key-value pair containing the jcr value(s). + for String, Boolean, Double, Long -> types in json available */ + if (isMultiple) { + writeKeyArray(p.getName(), p.getValues()); + } else { + writeKeyValue(p.getName(), p.getValue()); + } + } + } + + private static boolean requiresTypeInfo(Property p) throws RepositoryException { + switch (p.getType()) { + case PropertyType.NAME: + case PropertyType.PATH: + case PropertyType.REFERENCE: + case PropertyType.DATE: + case PropertyType.WEAKREFERENCE: + case PropertyType.URI: + case PropertyType.DECIMAL: + case PropertyType.DOUBLE: + return true; + default: + // any other property type + return false; + } + } + + private void writeKeyValue(String key, String value, boolean hasNext) throws IOException { + writeKey(key); + writer.write(JsonUtil.getJsonString(value)); + if (hasNext) { + writer.write(','); + } + } + + private void writeKeyValue(String key, Value value) throws RepositoryException, IOException { + writeKey(key); + writeJsonValue(value); + } + + private void writeKeyArray(String key, Value[] values) throws RepositoryException, IOException { + writeKey(key); + writer.write('['); + for (int i = 0; i < values.length; i++) { + if (i > 0) { + writer.write(','); + } + writeJsonValue(values[i]); + } + writer.write(']'); + } + + private void writeKeyValue(String key, long binLength) throws IOException { + writeKey(key); + writer.write(String.valueOf(binLength)); + } + + private void writeKeyArray(String key, long[] binLengths) throws RepositoryException, IOException { + writeKey(key); + writer.write('['); + for (int i = 0; i < binLengths.length; i++) { + if (i > 0) { + writer.write(','); + } + writer.write(String.valueOf(binLengths[i])); + } + writer.write(']'); + } + + private void writeKey(String key) throws IOException { + writer.write(JsonUtil.getJsonString(key)); + writer.write(':'); + } + + private void writeJsonValue(Value v) throws RepositoryException, IOException { + + switch (v.getType()) { + case PropertyType.BINARY: + // should never get here + throw new IllegalArgumentException(); + + case PropertyType.BOOLEAN: + case PropertyType.LONG: + writer.write(v.getString()); + break; + case PropertyType.DOUBLE: + double d = v.getDouble(); + String str = v.getString(); + if (Double.isNaN(d) || Double.isInfinite(d)) { + str = JsonUtil.getJsonString(str); + } + writer.write(str); + break; + + default: + writer.write(JsonUtil.getJsonString(v.getString())); + } + } +} Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/remoting/davex/JsonWriter.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/remoting/davex/ProtectedItemRemoveHandler.java =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/remoting/davex/ProtectedItemRemoveHandler.java (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/remoting/davex/ProtectedItemRemoveHandler.java (working copy) @@ -0,0 +1,28 @@ +/* + * 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.remoting.davex; + +import javax.jcr.RepositoryException; +import javax.jcr.Session; + +/** + * ProtectedItemRemoveHandler... TODO + */ +public interface ProtectedItemRemoveHandler { + + public boolean remove(Session session, String itemPath) throws RepositoryException; +} Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/remoting/davex/ProtectedItemRemoveHandler.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/remoting/davex/ProtectedRemoveConfig.java =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/remoting/davex/ProtectedRemoveConfig.java (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/remoting/davex/ProtectedRemoveConfig.java (working copy) @@ -0,0 +1,83 @@ +/* + * 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.remoting.davex; + +import java.io.IOException; +import java.io.InputStream; + +import javax.xml.parsers.ParserConfigurationException; + +import org.apache.jackrabbit.webdav.xml.DomUtil; +import org.apache.jackrabbit.webdav.xml.ElementIterator; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.w3c.dom.Element; +import org.xml.sax.SAXException; + +/** + * A configuration of ProtectedItemRemoveHandler(s). + * + * ProtectedRemoveConfig + */ +class ProtectedRemoveConfig { + + private static final Logger log = LoggerFactory.getLogger(ProtectedRemoveConfig.class); + + private static final String ELEMENT_HANDLER = "protecteditemremovehandler"; + private static final String ELEMENT_CLASS = "class"; + private static final String ATTRIBUTE_NAME = "name"; + + private final ProtectedRemoveManager manager; + + ProtectedRemoveConfig(ProtectedRemoveManager manager) { + this.manager = manager; + } + + void parse(InputStream inputStream) throws IOException { + Element config; + ProtectedItemRemoveHandler instance = null; + try { + config = DomUtil.parseDocument(inputStream).getDocumentElement(); + if (config == null) { + log.warn("Missing mandatory config element"); + return; + } + ElementIterator handlers = DomUtil.getChildren(config, ELEMENT_HANDLER, null); + while (handlers.hasNext()) { + Element handler = handlers.nextElement(); + instance = createHandler(handler); + manager.addHandler(instance); + } + } catch (ParserConfigurationException e) { + log.error(e.getMessage(), e); + } catch (SAXException e) { + log.error(e.getMessage(), e); + } + } + + private ProtectedItemRemoveHandler createHandler(Element parent) { + ProtectedItemRemoveHandler instance = null; + Element classElem = DomUtil.getChildElement(parent, ELEMENT_CLASS, null); + if (classElem != null) { + String className = DomUtil.getAttribute(classElem, ATTRIBUTE_NAME, null); + if (className != null) { + instance = manager.createHandler(className); + } + } + return instance; + } +} Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/remoting/davex/ProtectedRemoveConfig.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/remoting/davex/ProtectedRemoveManager.java =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/remoting/davex/ProtectedRemoveManager.java (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/remoting/davex/ProtectedRemoveManager.java (working copy) @@ -0,0 +1,112 @@ +/* + * 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.remoting.davex; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.List; + +import javax.jcr.RepositoryException; +import javax.jcr.Session; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +class ProtectedRemoveManager { + + private static final Logger log = LoggerFactory.getLogger(ProtectedRemoveManager.class); + + private List handlers = new ArrayList(); + + ProtectedRemoveManager(){ + + } + + ProtectedRemoveManager(String config) throws IOException { + + if (config == null) { + log.warn("protectedhandlers-config is missing -> DIFF processing can fail for the Remove operation if the content to" + + "remove is protected!"); + } else { + File file = new File(config); + if (file.exists()) { + try { + InputStream fis = new FileInputStream(file); + load(fis); + } catch (FileNotFoundException e) { + throw new IOException(e.getMessage(), e); + } + } else { // config is an Impl class + if (!config.isEmpty()) { + ProtectedItemRemoveHandler handler = createHandler(config); + addHandler(handler); + } else { + log.debug("Fail to locate the protected-item-remove-handler properties file."); + } + } + } + } + + void load(InputStream fis) throws IOException { + ProtectedRemoveConfig prConfig = new ProtectedRemoveConfig(this); + prConfig.parse(fis); + } + + boolean remove(Session session, String itemPath) throws RepositoryException { + for (ProtectedItemRemoveHandler handler : handlers) { + if (handler.remove(session, itemPath)) { + return true; + } + } + return false; + } + + /** + * Instantiates and returns a concrete ProtectedItemRemoveHandler implementation. + * @param className + * @return + * @throws RepositoryException + */ + ProtectedItemRemoveHandler createHandler(String className) { + ProtectedItemRemoveHandler irHandler = null; + try { + if (!className.isEmpty()) { + Class irHandlerClass = Class.forName(className); + if (ProtectedItemRemoveHandler.class.isAssignableFrom(irHandlerClass)) { + irHandler = (ProtectedItemRemoveHandler) irHandlerClass.newInstance(); + } + } + } catch (ClassNotFoundException e) { + log.error(e.getMessage(), e); + } catch (InstantiationException e) { + log.error(e.getMessage(), e); + } catch (IllegalAccessException e) { + log.error(e.getMessage(), e); + } + return irHandler; + } + + void addHandler(ProtectedItemRemoveHandler instance) { + if (instance != null) { + handlers.add(instance); + } + } +} Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/remoting/davex/ProtectedRemoveManager.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/util/HttpMultipartPost.java =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/util/HttpMultipartPost.java (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/util/HttpMultipartPost.java (working copy) @@ -0,0 +1,286 @@ +/* + * 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.util; + +import org.apache.commons.fileupload.FileItem; +import org.apache.commons.fileupload.FileItemFactory; +import org.apache.commons.fileupload.FileUploadException; +import org.apache.commons.fileupload.disk.DiskFileItemFactory; +import org.apache.commons.fileupload.servlet.ServletFileUpload; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.servlet.http.HttpServletRequest; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; + +/** + * HttpMultipartPost... + */ +class HttpMultipartPost { + + private static final Logger log = LoggerFactory.getLogger(HttpMultipartPost.class); + + private final Map> nameToItems = new LinkedHashMap>(); + private final Set fileParamNames = new HashSet(); + + private boolean initialized; + + HttpMultipartPost(HttpServletRequest request, File tmpDir) throws IOException { + extractMultipart(request, tmpDir); + initialized = true; + } + + private static FileItemFactory getFileItemFactory(File tmpDir) { + DiskFileItemFactory fiFactory = new DiskFileItemFactory(DiskFileItemFactory.DEFAULT_SIZE_THRESHOLD, tmpDir); + return fiFactory; + } + + private void extractMultipart(HttpServletRequest request, File tmpDir) + throws IOException { + if (!ServletFileUpload.isMultipartContent(request)) { + log.debug("Request does not contain multipart content -> ignoring."); + return; + } + + ServletFileUpload upload = new ServletFileUpload(getFileItemFactory(tmpDir)); + // make sure the content disposition headers are read with the charset + // specified in the request content type (or UTF-8 if no charset is specified). + // see JCR + if (request.getCharacterEncoding() == null) { + upload.setHeaderEncoding("UTF-8"); + } + try { + @SuppressWarnings("unchecked") + List fileItems = upload.parseRequest(request); + for (FileItem fileItem : fileItems) { + addItem(fileItem); + } + } catch (FileUploadException e) { + log.error("Error while processing multipart.", e); + throw new IOException(e.toString()); + } + } + + /** + * Add the given file item to the list defined for its name and make the + * list is present in the map. If the item does not represent a simple + * form field its name is also added to the fileParamNames set. + * + * @param item The {@link FileItem} to add. + */ + private void addItem(FileItem item) { + String name = item.getFieldName(); + List l = nameToItems.get(item.getFieldName()); + if (l == null) { + l = new ArrayList(); + nameToItems.put(name, l); + } + l.add(item); + + // if file parameter, add name to the set of file parameters in order to + // be able to extract the file parameter values later on without iterating + // over all keys. + if (!item.isFormField()) { + fileParamNames.add(name); + } + } + + private void checkInitialized() { + if (!initialized) { + throw new IllegalStateException("HttpMultipartPost not initialized (or already disposed)."); + } + } + + /** + * Release all file items hold with the name-to-items map. Especially those + * having a temporary file associated with. + * + * @see FileItem#delete() + */ + synchronized void dispose() { + checkInitialized(); + + for (List fileItems : nameToItems.values()) { + for (FileItem fileItem : fileItems) { + fileItem.delete(); + } + } + + nameToItems.clear(); + fileParamNames.clear(); + initialized = false; + } + + /** + * Returns an iterator over all file item names. + * + * @return a set of strings. + */ + Set getParameterNames() { + checkInitialized(); + return nameToItems.keySet(); + } + + + /** + * Returns the content types of the parameters with the given name. If + * the parameter does not exist null is returned. If the content + * type of any of the parameter values is not known, the corresponding entry + * in the array returned is null. + *

+ * The content type of a parameter is only known here if the information + * has been sent by the client browser. This is generally only the case + * for file upload fields of HTML forms which have been posted using the + * HTTP POST with multipart/form-data encoding. + *

+ * Example : For the form + *

+         
+
+
+ +
+ *
+ * this method will return an array of two entries when called for the + * Upload parameter. The first entry will contain the content + * type (if transmitted by the client) of the file uploaded. The second + * entry will be null because the content type of the text + * input field will generally not be sent by the client. + * + * @param name The name of the parameter whose content type is to be + * returned. + * @return The content types of the file items with the specified name. + */ + String[] getParameterTypes(String name) { + checkInitialized(); + String[] cts = null; + List l = nameToItems.get(name); + if (l != null && !l.isEmpty()) { + cts = new String[l.size()]; + for (int i = 0; i < cts.length; i++) { + cts[i] = l.get(i).getContentType(); + } + } + return cts; + } + + /** + * Returns the first value of the file items with the given name. + * The byte to string conversion is done using either the content type of + * the file items or the formEncoding. + *

+ * Please note that if the addressed parameter is an uploaded file rather + * than a simple form entry, the name of the original file is returned + * instead of the content. + * + * @param name the name of the parameter + * @return the string of the first value or null if the + * parameter does not exist + */ + String getParameter(String name) { + checkInitialized(); + List l = nameToItems.get(name); + if (l == null || l.isEmpty()) { + return null; + } else { + FileItem item = l.get(0); + if (item.isFormField()) { + return item.getString(); + } else { + return item.getName(); + } + } + } + + /** + * Returns an array of Strings with all values of the parameter addressed + * by name. the byte to string conversion is done using either + * the content type of the multipart body or the formEncoding. + *

+ * Please note that if the addressed parameter is an uploaded file rather + * than a simple form entry, the name of the original file is returned + * instead of the content. + * + * @param name the name of the parameter + * @return a string array of values or null if no entry with the + * given name exists. + */ + String[] getParameterValues(String name) { + checkInitialized(); + List l = nameToItems.get(name); + if (l == null || l.isEmpty()) { + return null; + } else { + String[] values = new String[l.size()]; + for (int i = 0; i < values.length; i++) { + FileItem item = l.get(i); + if (item.isFormField()) { + values[i] = item.getString(); + } else { + values[i] = item.getName(); + } + } + return values; + } + } + + /** + * Returns a set of the file parameter names. An empty set if + * no file parameters were present in the request. + * + * @return an set of file item names representing the file + * parameters available with the request. + */ + Set getFileParameterNames() { + checkInitialized(); + return fileParamNames; + } + + /** + * Returns an array of input streams for uploaded file parameters. + * + * @param name the name of the file parameter(s) + * @return an array of input streams or null if no file params + * with the given name exist. + * @throws IOException if an I/O error occurs + */ + InputStream[] getFileParameterValues(String name) throws IOException { + checkInitialized(); + InputStream[] values = null; + if (fileParamNames.contains(name)) { + List l = nameToItems.get(name); + if (l != null && !l.isEmpty()) { + List ins = new ArrayList(l.size()); + for (FileItem item : l) { + if (!item.isFormField()) { + ins.add(item.getInputStream()); + } + } + values = ins.toArray(new InputStream[ins.size()]); + } + } + return values; + } +} Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/util/HttpMultipartPost.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/util/RequestData.java =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/util/RequestData.java (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/util/RequestData.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.util; + +import javax.servlet.http.HttpServletRequest; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.util.HashSet; +import java.util.Iterator; + +/** + * RequestData... + */ +public class RequestData { + + private final HttpServletRequest request; + private final HttpMultipartPost mpReq; + + public RequestData(HttpServletRequest request, File tmpDir) throws IOException { + this.request = request; + this.mpReq = new HttpMultipartPost(request, tmpDir); + } + + /** + * Dispose resources used. + */ + public void dispose() { + mpReq.dispose(); + } + + /** + * Returns an iterator over all parameter names. + * + * @return an iterator over strings. + */ + public Iterator getParameterNames() { + @SuppressWarnings("unchecked") + HashSet names = new HashSet(request.getParameterMap().keySet()); + names.addAll(mpReq.getParameterNames()); + + return names.iterator(); + } + + /** + * Returns the first value of the parameter with the given name. + * The byte to string conversion is done using either the content type of + * the parameter or the formEncoding. + *

+ * Please note that if the addressed parameter is a file parameter, the + * name of the original file is returned, and not its content. + * + * @param name the name of the parameter + * @return the string of the first value or null if the + * parameter does not exist + */ + public String getParameter(String name) { + String ret = mpReq.getParameter(name); + return (ret == null) ? request.getParameter(name) : ret; + } + + /** + * Returns the content types retrieved for parameters with the specified + * name from the multipart or null if the multipart does not + * contain parameter(s) with the given name. + * + * @param name parameter name + * @return the parameter types retrieved for the specified parameter + * name from the multipart or null. + */ + public String[] getParameterTypes(String name) { + String[] types = mpReq.getParameterTypes(name); + return types == null ? null : types; + } + + /** + * Returns an array of Strings with all values of the parameter addressed + * by name. the byte to string conversion is done using either + * the content type of the multipart body or the formEncoding. + *

+ * Please note that if the addressed parameter is a file parameter, the + * name of the original file is returned, and not its content. + * + * @param name the name of the parameter + * @return a string array of values or null if the parameter + * does not exist. + */ + public String[] getParameterValues(String name) { + String[] ret = mpReq.getParameterValues(name); + return ret == null ? request.getParameterValues(name) : ret; + } + + /** + * Returns an array of input streams for uploaded file parameters. + * + * @param name the name of the file parameter(s) + * @return an array of input streams or an empty array if no file params + * with the given name exist. + * @throws IOException if an I/O error occurs + */ + public InputStream[] getFileParameters(String name) throws IOException { + return mpReq.getFileParameterValues(name); + } +} Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/util/RequestData.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/webdav/jcr/AbstractItemResource.java =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/AbstractItemResource.java (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/AbstractItemResource.java (working copy) @@ -0,0 +1,482 @@ +/* + * 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.webdav.jcr; + +import org.apache.jackrabbit.util.Text; +import org.apache.jackrabbit.webdav.DavCompliance; +import org.apache.jackrabbit.webdav.DavException; +import org.apache.jackrabbit.webdav.DavResource; +import org.apache.jackrabbit.webdav.DavResourceFactory; +import org.apache.jackrabbit.webdav.DavResourceLocator; +import org.apache.jackrabbit.webdav.DavServletResponse; +import org.apache.jackrabbit.webdav.io.OutputContext; +import org.apache.jackrabbit.webdav.jcr.nodetype.ItemDefinitionImpl; +import org.apache.jackrabbit.webdav.jcr.nodetype.NodeDefinitionImpl; +import org.apache.jackrabbit.webdav.jcr.nodetype.PropertyDefinitionImpl; +import org.apache.jackrabbit.webdav.jcr.property.JcrDavPropertyNameSet; +import org.apache.jackrabbit.webdav.observation.EventDiscovery; +import org.apache.jackrabbit.webdav.observation.ObservationConstants; +import org.apache.jackrabbit.webdav.observation.ObservationResource; +import org.apache.jackrabbit.webdav.observation.Subscription; +import org.apache.jackrabbit.webdav.observation.SubscriptionInfo; +import org.apache.jackrabbit.webdav.observation.SubscriptionManager; +import org.apache.jackrabbit.webdav.property.DavProperty; +import org.apache.jackrabbit.webdav.property.DavPropertyName; +import org.apache.jackrabbit.webdav.property.DefaultDavProperty; +import org.apache.jackrabbit.webdav.property.HrefProperty; +import org.apache.jackrabbit.webdav.transaction.TxLockEntry; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.jcr.Item; +import javax.jcr.Node; +import javax.jcr.PathNotFoundException; +import javax.jcr.Property; +import javax.jcr.RepositoryException; +import javax.jcr.Workspace; +import java.io.IOException; + +/** + * AbstractItemResource covers common functionality for the various + * resources, that represent a repository item. + */ +abstract class AbstractItemResource extends AbstractResource implements + ObservationResource, ItemResourceConstants { + + private static Logger log = LoggerFactory.getLogger(AbstractItemResource.class); + + private SubscriptionManager subsMgr; + protected final Item item; + + /** + * Create a new AbstractItemResource. + * + * @param locator + * @param session + * @param factory + * @param item + */ + AbstractItemResource(DavResourceLocator locator, JcrDavSession session, + DavResourceFactory factory, Item item) { + super(locator, session, factory); + this.item = item; + + // initialize the supported locks and reports + initLockSupport(); + initSupportedReports(); + } + + //----------------------------------------------< DavResource interface >--- + /** + * @see org.apache.jackrabbit.webdav.DavResource#getComplianceClass() + */ + @Override + public String getComplianceClass() { + return DavCompliance.concatComplianceClasses( + new String[] { + super.getComplianceClass(), + DavCompliance.OBSERVATION, + } + ); + } + + @Override + public DavProperty getProperty(DavPropertyName name) { + DavProperty prop = super.getProperty(name); + if (prop == null) { + if (JCR_DEFINITION.equals(name)) { + if (exists()) { + try { + + // protected 'definition' property revealing the item definition + ItemDefinitionImpl val; + if (item.isNode()) { + val = NodeDefinitionImpl.create(((Node)item).getDefinition()); + } else { + val = PropertyDefinitionImpl.create(((Property)item).getDefinition()); + } + prop = new DefaultDavProperty(JCR_DEFINITION, val, true); + } catch (RepositoryException e) { + // should not get here + log.error("Error while accessing item definition: " + e.getMessage()); + } + } + } else if (JCR_ISNEW.equals(name)) { + // transaction resource additional protected properties + if (exists() && item.isNew()) { + prop = new DefaultDavProperty(JCR_ISNEW, null, true); + } + } else if (JCR_ISMODIFIED.equals(name)) { + // transaction resource additional protected properties + if (exists() && item.isModified()) { + prop = new DefaultDavProperty(JCR_ISMODIFIED, null, true); + } + } else if (ObservationConstants.SUBSCRIPTIONDISCOVERY.equals(name)) { + // observation resource + prop = subsMgr.getSubscriptionDiscovery(this); + } + } + + return prop; + } + + /** + * @see org.apache.jackrabbit.webdav.DavResource#getSupportedMethods() + */ + @Override + public String getSupportedMethods() { + return ItemResourceConstants.METHODS; + } + + /** + * Returns true if there exists a {@link Item repository item} with the given + * resource path, false otherwise. + * + * @see org.apache.jackrabbit.webdav.DavResource#exists() + */ + @Override + public boolean exists() { + return item != null; + } + + /** + * Retrieves the last segment of the item path (or the resource path if + * this resource does not exist). An item path is in addition first translated + * to the corresponding resource path.
+ * NOTE: the display name is not equivalent to {@link Item#getName() item name} + * which is exposed with the {@link ItemResourceConstants#JCR_NAME + * {http://www.day.com/jcr/webdav/1.0}name} property. + * + * @see org.apache.jackrabbit.webdav.DavResource#getDisplayName() + */ + @Override + public String getDisplayName() { + String resPath = getResourcePath(); + return (resPath != null) ? Text.getName(resPath) : resPath; + } + + /** + * Spools the properties of this resource to the context. Note that subclasses + * are in charge of spooling the data to the output stream provided by the + * context. + * + * @see DavResource#spool(OutputContext) + */ + @Override + public void spool(OutputContext outputContext) throws IOException { + if (!initedProps) { + initProperties(); + } + // export properties + outputContext.setModificationTime(getModificationTime()); + DavProperty etag = getProperty(DavPropertyName.GETETAG); + if (etag != null) { + outputContext.setETag(String.valueOf(etag.getValue())); + } + DavProperty contentType = getProperty(DavPropertyName.GETCONTENTTYPE); + if (contentType != null) { + outputContext.setContentType(String.valueOf(contentType.getValue())); + } + DavProperty contentLength = getProperty(DavPropertyName.GETCONTENTLENGTH); + if (contentLength != null) { + try { + long length = Long.parseLong(contentLength.getValue() + ""); + if (length > 0) { + outputContext.setContentLength(length); + } + } catch (NumberFormatException e) { + log.error("Could not build content length from property value '" + contentLength.getValue() + "'"); + } + } + DavProperty contentLanguage = getProperty(DavPropertyName.GETCONTENTLANGUAGE); + if (contentLanguage != null) { + outputContext.setContentLanguage(contentLanguage.getValue().toString()); + } + } + + /** + * Returns the resource representing the parent item of the repository item + * represented by this resource. If this resoure represents the root item + * a {@link RootCollection} is returned. + * + * @return the collection this resource is internal member of. Except for the + * repository root, the returned collection always represent the parent + * repository node. + * @see org.apache.jackrabbit.webdav.DavResource#getCollection() + */ + @Override + public DavResource getCollection() { + DavResource collection = null; + + String parentPath = Text.getRelativeParent(getResourcePath(), 1); + DavResourceLocator parentLoc = getLocator().getFactory().createResourceLocator(getLocator().getPrefix(), getLocator().getWorkspacePath(), parentPath); + try { + collection = createResourceFromLocator(parentLoc); + } catch (DavException e) { + log.error("Unexpected error while retrieving collection: " + e.getMessage()); + } + + return collection; + } + + /** + * Moves the underlying repository item to the indicated destination. + * + * @param destination + * @throws DavException + * @see DavResource#move(DavResource) + * @see javax.jcr.Session#move(String, String) + */ + @Override + public void move(DavResource destination) throws DavException { + if (!exists()) { + throw new DavException(DavServletResponse.SC_NOT_FOUND); + } + DavResourceLocator destLocator = destination.getLocator(); + if (!getLocator().isSameWorkspace(destLocator)) { + throw new DavException(DavServletResponse.SC_FORBIDDEN); + } + + try { + String itemPath = getLocator().getRepositoryPath(); + String destItemPath = destination.getLocator().getRepositoryPath(); + if (getTransactionId() == null) { + // if not part of a transaction directly import on workspace + getRepositorySession().getWorkspace().move(itemPath, destItemPath); + } else { + // changes will not be persisted unless the tx is completed. + getRepositorySession().move(itemPath, destItemPath); + } + // no use in calling 'complete' that would fail for a moved item anyway. + } catch (PathNotFoundException e) { + // according to rfc 2518 + throw new DavException(DavServletResponse.SC_CONFLICT, e.getMessage()); + } catch (RepositoryException e) { + throw new JcrDavException(e); + } + } + + /** + * Copies the underlying repository item to the indicated destination. If + * the locator of the specified destination resource indicates a different + * workspace, {@link Workspace#copy(String, String, String)} is used to perform + * the copy operation, {@link Workspace#copy(String, String)} otherwise. + *

+ * Note, that this implementation does not support shallow copy. + * + * @param destination + * @param shallow + * @throws DavException + * @see DavResource#copy(DavResource, boolean) + * @see Workspace#copy(String, String) + * @see Workspace#copy(String, String, String) + */ + @Override + public void copy(DavResource destination, boolean shallow) throws DavException { + if (!exists()) { + throw new DavException(DavServletResponse.SC_NOT_FOUND); + } + // TODO: support shallow and deep copy is required by RFC 2518 + if (shallow) { + throw new DavException(DavServletResponse.SC_FORBIDDEN, "Unable to perform shallow copy."); + } + + try { + String itemPath = getLocator().getRepositoryPath(); + String destItemPath = destination.getLocator().getRepositoryPath(); + Workspace workspace = getRepositorySession().getWorkspace(); + if (getLocator().isSameWorkspace(destination.getLocator())) { + workspace.copy(itemPath, destItemPath); + } else { + log.error("Copy between workspaces is not yet implemented (src: '" + getHref() + "', dest: '" + destination.getHref() + "')"); + throw new DavException(DavServletResponse.SC_NOT_IMPLEMENTED); + } + } catch (PathNotFoundException e) { + // according to RFC 2518, should not occur + throw new DavException(DavServletResponse.SC_NOT_FOUND, e.getMessage()); + } catch (RepositoryException e) { + throw new JcrDavException(e); + } + } + + //--------------------------------------< ObservationResource interface >--- + /** + * @see ObservationResource#init(SubscriptionManager) + */ + @Override + public void init(SubscriptionManager subsMgr) { + this.subsMgr = subsMgr; + } + + /** + * @see ObservationResource#subscribe(org.apache.jackrabbit.webdav.observation.SubscriptionInfo, String) + * @see SubscriptionManager#subscribe(org.apache.jackrabbit.webdav.observation.SubscriptionInfo, String, org.apache.jackrabbit.webdav.observation.ObservationResource) + */ + @Override + public Subscription subscribe(SubscriptionInfo info, String subscriptionId) + throws DavException { + return subsMgr.subscribe(info, subscriptionId, this); + } + + /** + * @see ObservationResource#unsubscribe(String) + * @see SubscriptionManager#unsubscribe(String, org.apache.jackrabbit.webdav.observation.ObservationResource) + */ + @Override + public void unsubscribe(String subscriptionId) throws DavException { + subsMgr.unsubscribe(subscriptionId, this); + } + + /** + * @see ObservationResource#poll(String, long) + * @see SubscriptionManager#poll(String, long, org.apache.jackrabbit.webdav.observation.ObservationResource) + */ + @Override + public EventDiscovery poll(String subscriptionId, long timeout) throws DavException { + return subsMgr.poll(subscriptionId, timeout, this); + } + + //-------------------------------------------------------------------------- + /** + * Initialize the {@link org.apache.jackrabbit.webdav.lock.SupportedLock} property + * with entries that are valid for any type item resources. + * + * @see org.apache.jackrabbit.webdav.lock.SupportedLock + * @see org.apache.jackrabbit.webdav.transaction.TxLockEntry + * @see AbstractResource#initLockSupport() + */ + @Override + protected void initLockSupport() { + if (exists()) { + // add supported lock entries for local and eventually for global + // transaction locks + supportedLock.addEntry(new TxLockEntry(true)); + supportedLock.addEntry(new TxLockEntry(false)); + } + } + + @Override + protected void initPropertyNames() { + super.initPropertyNames(); + if (exists()) { + names.addAll(JcrDavPropertyNameSet.EXISTING_ITEM_BASE_SET); + try { + if (item.getDepth() > 0) { + names.add(JCR_PARENT); + } + } catch (RepositoryException e) { + log.warn("Error while accessing node depth: " + e.getMessage()); + } + if (item.isNew()) { + names.add(JCR_ISNEW); + } else if (item.isModified()) { + names.add(JCR_ISMODIFIED); + } + } else { + names.addAll(JcrDavPropertyNameSet.ITEM_BASE_SET); + } + } + + /** + * Fill the property set for this resource. + */ + @Override + protected void initProperties() { + super.initProperties(); + if (exists()) { + try { + properties.add(new DefaultDavProperty(JCR_NAME, item.getName())); + properties.add(new DefaultDavProperty(JCR_PATH, item.getPath())); + int depth = item.getDepth(); + properties.add(new DefaultDavProperty(JCR_DEPTH, String.valueOf(depth))); + // add href-property for the items parent unless its the root item + if (depth > 0) { + String parentHref = getLocatorFromItem(item.getParent()).getHref(true); + properties.add(new HrefProperty(JCR_PARENT, parentHref, false)); + } + } catch (RepositoryException e) { + // should not get here + log.error("Error while accessing jcr properties: " + e.getMessage()); + } + } + } + + /** + * @return href of the workspace or null if this resource + * does not represent a repository item. + * + * @see AbstractResource#getWorkspaceHref() + */ + @Override + protected String getWorkspaceHref() { + String workspaceHref = null; + DavResourceLocator locator = getLocator(); + if (locator != null && locator.getWorkspacePath() != null) { + String wspPath = locator.getWorkspacePath(); + DavResourceLocator wspLocator = locator.getFactory().createResourceLocator(locator.getPrefix(), wspPath, wspPath); + workspaceHref = wspLocator.getHref(true); + } + log.debug(workspaceHref); + return workspaceHref; + } + + /** + * If this resource exists but does not contain a transaction id, complete + * will try to persist any modifications present on the underlying + * repository item. + * + * @throws DavException if calling {@link Item#save()} fails + */ + void complete() throws DavException { + if (exists() && getTransactionId() == null) { + try { + if (item.isModified()) { + item.save(); + } + } catch (RepositoryException e) { + // this includes LockException, ConstraintViolationException etc. not detected before + log.error("Error while completing request: " + e.getMessage() +" -> reverting changes."); + try { + item.refresh(false); + } catch (RepositoryException re) { + log.error("Error while reverting changes: " + re.getMessage()); + } + throw new JcrDavException(e); + } + } + } + + /** + * Retrieves the last segment of the given path and removes the index if + * present. + * + * @param itemPath + * @return valid jcr item name + */ + protected static String getItemName(String itemPath) { + if (itemPath == null) { + throw new IllegalArgumentException("Cannot retrieve name from a 'null' item path."); + } + // retrieve the last part of the path + String name = Text.getName(itemPath); + // remove index + if (name.endsWith("]")) { + name = name.substring(0, name.lastIndexOf('[')); + } + return name; + } +} Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/AbstractItemResource.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/webdav/jcr/AbstractResource.java =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/AbstractResource.java (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/AbstractResource.java (working copy) @@ -0,0 +1,861 @@ +/* + * 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.webdav.jcr; + +import org.apache.jackrabbit.server.io.IOUtil; +import org.apache.jackrabbit.webdav.DavException; +import org.apache.jackrabbit.webdav.DavLocatorFactory; +import org.apache.jackrabbit.webdav.DavResource; +import org.apache.jackrabbit.webdav.DavResourceFactory; +import org.apache.jackrabbit.webdav.DavResourceLocator; +import org.apache.jackrabbit.webdav.DavServletResponse; +import org.apache.jackrabbit.webdav.DavSession; +import org.apache.jackrabbit.webdav.MultiStatus; +import org.apache.jackrabbit.webdav.MultiStatusResponse; +import org.apache.jackrabbit.webdav.WebdavRequest; +import org.apache.jackrabbit.webdav.WebdavRequestContext; +import org.apache.jackrabbit.webdav.DavCompliance; +import org.apache.jackrabbit.webdav.jcr.property.JcrDavPropertyNameSet; +import org.apache.jackrabbit.webdav.util.HttpDateFormat; +import org.apache.jackrabbit.webdav.jcr.search.SearchResourceImpl; +import org.apache.jackrabbit.webdav.jcr.transaction.TxLockManagerImpl; +import org.apache.jackrabbit.webdav.jcr.version.report.NodeTypesReport; +import org.apache.jackrabbit.webdav.jcr.version.report.LocateByUuidReport; +import org.apache.jackrabbit.webdav.jcr.version.report.RegisteredNamespacesReport; +import org.apache.jackrabbit.webdav.jcr.version.report.RepositoryDescriptorsReport; +import org.apache.jackrabbit.webdav.lock.ActiveLock; +import org.apache.jackrabbit.webdav.lock.LockDiscovery; +import org.apache.jackrabbit.webdav.lock.LockInfo; +import org.apache.jackrabbit.webdav.lock.LockManager; +import org.apache.jackrabbit.webdav.lock.Scope; +import org.apache.jackrabbit.webdav.lock.SupportedLock; +import org.apache.jackrabbit.webdav.lock.Type; +import org.apache.jackrabbit.webdav.property.DavProperty; +import org.apache.jackrabbit.webdav.property.DavPropertyName; +import org.apache.jackrabbit.webdav.property.DavPropertyNameSet; +import org.apache.jackrabbit.webdav.property.DavPropertySet; +import org.apache.jackrabbit.webdav.property.DefaultDavProperty; +import org.apache.jackrabbit.webdav.property.HrefProperty; +import org.apache.jackrabbit.webdav.property.ResourceType; +import org.apache.jackrabbit.webdav.property.PropEntry; +import org.apache.jackrabbit.webdav.search.QueryGrammerSet; +import org.apache.jackrabbit.webdav.search.SearchInfo; +import org.apache.jackrabbit.webdav.search.SearchResource; +import org.apache.jackrabbit.webdav.server.WebdavRequestContextHolder; +import org.apache.jackrabbit.webdav.transaction.TransactionConstants; +import org.apache.jackrabbit.webdav.transaction.TransactionInfo; +import org.apache.jackrabbit.webdav.transaction.TransactionResource; +import org.apache.jackrabbit.webdav.transaction.TxLockManager; +import org.apache.jackrabbit.webdav.version.DeltaVConstants; +import org.apache.jackrabbit.webdav.version.DeltaVResource; +import org.apache.jackrabbit.webdav.version.OptionsInfo; +import org.apache.jackrabbit.webdav.version.OptionsResponse; +import org.apache.jackrabbit.webdav.version.SupportedMethodSetProperty; +import org.apache.jackrabbit.webdav.version.report.Report; +import org.apache.jackrabbit.webdav.version.report.ReportInfo; +import org.apache.jackrabbit.webdav.version.report.ReportType; +import org.apache.jackrabbit.webdav.version.report.SupportedReportSetProperty; +import org.apache.jackrabbit.webdav.xml.DomUtil; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.w3c.dom.Element; + +import javax.jcr.Item; +import javax.jcr.RepositoryException; +import javax.jcr.Session; +import javax.jcr.observation.EventListener; +import javax.jcr.observation.Event; +import javax.jcr.observation.EventIterator; +import javax.xml.parsers.ParserConfigurationException; + +import java.util.ArrayList; +import java.util.Date; +import java.util.Iterator; +import java.util.List; + +/** + * AbstractResource provides functionality common to all + * resources. + */ +abstract class AbstractResource implements DavResource, TransactionResource, + DeltaVResource, SearchResource { + + private static Logger log = LoggerFactory.getLogger(AbstractResource.class); + + private static final String COMPLIANCE_CLASSES = + DavCompliance.concatComplianceClasses(new String[] { + DavCompliance._1_, + DavCompliance._2_, + DavCompliance._3_, + DavCompliance.VERSION_CONTROL, + DavCompliance.VERSION_HISTORY, + DavCompliance.CHECKOUT_IN_PLACE, + DavCompliance.LABEL, + DavCompliance.MERGE, + DavCompliance.UPDATE, + DavCompliance.WORKSPACE + }); + + private final DavResourceLocator locator; + private final JcrDavSession session; + private final DavResourceFactory factory; + + private TxLockManagerImpl txMgr; + private String transactionId; + + protected boolean initedProps; + protected DavPropertySet properties = new DavPropertySet(); + protected DavPropertyNameSet names; + protected SupportedLock supportedLock = new SupportedLock(); + protected SupportedReportSetProperty supportedReports = new SupportedReportSetProperty(); + + /** + * Create a new AbstractResource + * + * @param locator + * @param session + * @param factory + */ + AbstractResource(DavResourceLocator locator, JcrDavSession session, + DavResourceFactory factory) { + if (session == null) { + throw new IllegalArgumentException("Creating AbstractItemResource: DavSession must not be null and must provide a JCR session."); + } + this.locator = locator; + this.session = session; + this.factory = factory; + } + + /** + * Returns a string listing the compliance classes for this resource as it + * is required for the DAV response header. This includes DAV 1, 2 which + * is supported by all derived classes as well as a subset of the + * classes defined by DeltaV: version-control, version-history, checkout-in-place, + * label, merge, update and workspace.
+ * Those compliance classes are added as required by RFC3253 since all + * all resources in the jcr-server support at least the reporting and some + * basic versioning functionality. + * + * @return string listing the compliance classes. + * @see org.apache.jackrabbit.webdav.DavResource#getComplianceClass() + */ + @Override + public String getComplianceClass() { + return COMPLIANCE_CLASSES; + } + + /** + * @see org.apache.jackrabbit.webdav.DavResource#getLocator() + */ + @Override + public DavResourceLocator getLocator() { + return locator; + } + + /** + * Returns the path of the underlying repository item or the item to + * be created (PUT/MKCOL). If the resource exists but does not represent + * a repository item null is returned. + * + * @return path of the underlying repository item. + * @see DavResource#getResourcePath() + * @see org.apache.jackrabbit.webdav.DavResourceLocator#getResourcePath() + */ + @Override + public String getResourcePath() { + return locator.getResourcePath(); + } + + /** + * @see DavResource#getHref() + * @see DavResourceLocator#getHref(boolean) + */ + @Override + public String getHref() { + return locator.getHref(isCollection()); + } + + /** + * @see org.apache.jackrabbit.webdav.DavResource#getPropertyNames() + */ + @Override + public DavPropertyName[] getPropertyNames() { + initPropertyNames(); + return names.getContent().toArray(new DavPropertyName[names.getContentSize()]); + } + + /** + * @see org.apache.jackrabbit.webdav.DavResource#getProperty(org.apache.jackrabbit.webdav.property.DavPropertyName) + */ + @Override + public DavProperty getProperty(DavPropertyName name) { + DavProperty prop = getProperties().get(name); + if (prop == null) { + if (DeltaVConstants.SUPPORTED_METHOD_SET.equals(name)) { + prop = new SupportedMethodSetProperty(getSupportedMethods().split(",\\s")); + } else if (DeltaVConstants.SUPPORTED_REPORT_SET.equals(name)) { + prop = supportedReports; + } else if (DeltaVConstants.CREATOR_DISPLAYNAME.equals(name)) { + // DAV:creator-displayname default value : not available + prop = new DefaultDavProperty(DeltaVConstants.CREATOR_DISPLAYNAME, getCreatorDisplayName(), true); + } else if (DeltaVConstants.COMMENT.equals(name)) { + // DAV:comment not value available from jcr + prop = new DefaultDavProperty(DeltaVConstants.COMMENT, null, true); + } else if (DeltaVConstants.WORKSPACE.equals(name)) { + // 'workspace' property as defined by RFC 3253 + String workspaceHref = getWorkspaceHref(); + if (workspaceHref != null) { + prop = new HrefProperty(DeltaVConstants.WORKSPACE, workspaceHref, true); + } + } + } + + // TODO: required supported-live-property-set + return prop; + } + + /** + * @see org.apache.jackrabbit.webdav.DavResource#getProperties() + */ + @Override + public DavPropertySet getProperties() { + if (!initedProps) { + initProperties(); + } + return properties; + } + + /** + * Throws {@link DavServletResponse#SC_METHOD_NOT_ALLOWED} + * + * @param property + * @throws DavException Always throws {@link DavServletResponse#SC_METHOD_NOT_ALLOWED} + * @see org.apache.jackrabbit.webdav.DavResource#setProperty(org.apache.jackrabbit.webdav.property.DavProperty) + */ + @Override + public void setProperty(DavProperty property) throws DavException { + throw new DavException(DavServletResponse.SC_METHOD_NOT_ALLOWED); + } + + /** + * Throws {@link DavServletResponse#SC_METHOD_NOT_ALLOWED} + * + * @param propertyName + * @throws DavException Always throws {@link DavServletResponse#SC_METHOD_NOT_ALLOWED} + * @see org.apache.jackrabbit.webdav.DavResource#removeProperty(org.apache.jackrabbit.webdav.property.DavPropertyName) + */ + @Override + public void removeProperty(DavPropertyName propertyName) throws DavException { + throw new DavException(DavServletResponse.SC_METHOD_NOT_ALLOWED); + } + + /** + * Throws {@link DavServletResponse#SC_METHOD_NOT_ALLOWED} + * + * @see DavResource#alterProperties(List) + */ + @Override + public MultiStatusResponse alterProperties(List changeList) throws DavException { + throw new DavException(DavServletResponse.SC_METHOD_NOT_ALLOWED); + } + + /** + * Throws {@link DavServletResponse#SC_METHOD_NOT_ALLOWED} + * + * @param destination + * @throws DavException Always throws {@link DavServletResponse#SC_METHOD_NOT_ALLOWED} + * @see DavResource#move(org.apache.jackrabbit.webdav.DavResource) + */ + @Override + public void move(DavResource destination) throws DavException { + throw new DavException(DavServletResponse.SC_METHOD_NOT_ALLOWED); + } + + /** + * Throws {@link DavServletResponse#SC_METHOD_NOT_ALLOWED} + * + * @param destination + * @param shallow + * @throws DavException Always throws {@link DavServletResponse#SC_METHOD_NOT_ALLOWED} + * @see DavResource#copy(org.apache.jackrabbit.webdav.DavResource, boolean) + */ + @Override + public void copy(DavResource destination, boolean shallow) throws DavException { + throw new DavException(DavServletResponse.SC_METHOD_NOT_ALLOWED); + } + + + /** + * Returns true, if the {@link SupportedLock} property contains an entry + * with the given type and scope. By default resources allow for {@link org.apache.jackrabbit.webdav.transaction.TransactionConstants#XML_TRANSACTION + * transaction} lock only. + * + * @param type + * @param scope + * @return true if this resource may be locked by the given type and scope. + * @see DavResource#isLockable(org.apache.jackrabbit.webdav.lock.Type, org.apache.jackrabbit.webdav.lock.Scope) + */ + @Override + public boolean isLockable(Type type, Scope scope) { + return supportedLock.isSupportedLock(type, scope); + } + + /** + * Returns true if this resource has a lock applied with the given type and scope. + * + * @param type + * @param scope + * @return true if this resource has a lock applied with the given type and scope. + * @see DavResource#hasLock(Type, Scope) + */ + @Override + public boolean hasLock(Type type, Scope scope) { + return getLock(type, scope) != null; + } + + /** + * @see DavResource#getLock(Type, Scope) + */ + @Override + public ActiveLock getLock(Type type, Scope scope) { + ActiveLock lock = null; + if (TransactionConstants.TRANSACTION.equals(type)) { + lock = txMgr.getLock(type, scope, this); + } + return lock; + } + + /** + * @see DavResource#getLocks() + * todo improve.... + */ + @Override + public ActiveLock[] getLocks() { + List locks = new ArrayList(); + // tx locks + ActiveLock l = getLock(TransactionConstants.TRANSACTION, TransactionConstants.LOCAL); + if (l != null) { + locks.add(l); + } + l = getLock(TransactionConstants.TRANSACTION, TransactionConstants.GLOBAL); + if (l != null) { + locks.add(l); + } + // write lock (either exclusive or session-scoped). + l = getLock(Type.WRITE, Scope.EXCLUSIVE); + if (l != null) { + locks.add(l); + } else { + l = getLock(Type.WRITE, ItemResourceConstants.EXCLUSIVE_SESSION); + if (l != null) { + locks.add(l); + } + } + return locks.toArray(new ActiveLock[locks.size()]); + } + + /** + * @see DavResource#lock(org.apache.jackrabbit.webdav.lock.LockInfo) + */ + @Override + public ActiveLock lock(LockInfo reqLockInfo) throws DavException { + if (isLockable(reqLockInfo.getType(), reqLockInfo.getScope())) { + return txMgr.createLock(reqLockInfo, this); + } else { + throw new DavException(DavServletResponse.SC_PRECONDITION_FAILED); + } + } + + /** + * Only transaction lock may be available on this resource. + * + * @param info + * @param lockToken + * @throws DavException + * @see DavResource#refreshLock(org.apache.jackrabbit.webdav.lock.LockInfo, String) + */ + @Override + public ActiveLock refreshLock(LockInfo info, String lockToken) throws DavException { + return txMgr.refreshLock(info, lockToken, this); + } + + /** + * Throws {@link DavServletResponse#SC_METHOD_NOT_ALLOWED} since only transaction + * locks may be present on this resource, that need to be released by calling + * {@link TransactionResource#unlock(String, org.apache.jackrabbit.webdav.transaction.TransactionInfo)}. + * + * @param lockToken + * @throws DavException Always throws {@link DavServletResponse#SC_METHOD_NOT_ALLOWED} + */ + @Override + public void unlock(String lockToken) throws DavException { + throw new DavException(DavServletResponse.SC_PRECONDITION_FAILED); + } + + /** + * @see DavResource#addLockManager(org.apache.jackrabbit.webdav.lock.LockManager) + */ + @Override + public void addLockManager(LockManager lockMgr) { + if (lockMgr instanceof TxLockManagerImpl) { + txMgr = (TxLockManagerImpl) lockMgr; + } + } + + /** + * @see org.apache.jackrabbit.webdav.DavResource#getFactory() + */ + @Override + public DavResourceFactory getFactory() { + return factory; + } + + //-------------------------------------------------------------------------- + /** + * @see org.apache.jackrabbit.webdav.transaction.TransactionResource#getSession() + * @see org.apache.jackrabbit.webdav.observation.ObservationResource#getSession() + */ + @Override + public DavSession getSession() { + return session; + } + + //--------------------------------------< TransactionResource interface >--- + /** + * @see TransactionResource#init(TxLockManager, String) + */ + @Override + public void init(TxLockManager txMgr, String transactionId) { + this.txMgr = (TxLockManagerImpl) txMgr; + this.transactionId = transactionId; + } + + /** + * @see TransactionResource#unlock(String, org.apache.jackrabbit.webdav.transaction.TransactionInfo) + */ + @Override + public void unlock(String lockToken, TransactionInfo tInfo) throws DavException { + txMgr.releaseLock(tInfo, lockToken, this); + } + + /** + * @see TransactionResource#getTransactionId() + */ + @Override + public String getTransactionId() { + return transactionId; + } + + //-------------------------------------------< DeltaVResource interface >--- + /** + * @param optionsInfo + * @return object to be used in the OPTIONS response body or null + * @see DeltaVResource#getOptionResponse(org.apache.jackrabbit.webdav.version.OptionsInfo) + */ + @Override + public OptionsResponse getOptionResponse(OptionsInfo optionsInfo) { + OptionsResponse oR = null; + if (optionsInfo != null) { + oR = new OptionsResponse(); + // currently only DAV:version-history-collection-set and + // DAV:workspace-collection-set is supported. + if (optionsInfo.containsElement(DeltaVConstants.XML_VH_COLLECTION_SET, DeltaVConstants.NAMESPACE)) { + String[] hrefs = new String[] { + getLocatorFromItemPath(ItemResourceConstants.VERSIONSTORAGE_PATH).getHref(true) + }; + oR.addEntry(DeltaVConstants.XML_VH_COLLECTION_SET, DeltaVConstants.NAMESPACE, hrefs); + } + if (optionsInfo.containsElement(DeltaVConstants.XML_WSP_COLLECTION_SET, DeltaVConstants.NAMESPACE)) { + // workspaces cannot be created anywhere. + oR.addEntry(DeltaVConstants.XML_WSP_COLLECTION_SET, DeltaVConstants.NAMESPACE, new String[0]); + } + } + return oR; + } + + /** + * @param reportInfo + * @return the requested report + * @throws DavException + * @see DeltaVResource#getReport(org.apache.jackrabbit.webdav.version.report.ReportInfo) + */ + @Override + public Report getReport(ReportInfo reportInfo) throws DavException { + if (reportInfo == null) { + throw new DavException(DavServletResponse.SC_BAD_REQUEST, "A REPORT request must provide a valid XML request body."); + } + if (!exists()) { + throw new DavException(DavServletResponse.SC_NOT_FOUND); + } + + if (!supportedReports.isSupportedReport(reportInfo)) { + Element condition = null; + try { + condition = DomUtil.createDocument().createElementNS("DAV:", "supported-report"); + } catch (ParserConfigurationException ex) { + // we don't care THAT much + } + throw new DavException(DavServletResponse.SC_CONFLICT, + "Unknown report '" + reportInfo.getReportName() + "' requested.", null, condition); + } + + return ReportType.getType(reportInfo).createReport(this, reportInfo); + } + + /** + * The JCR api does not provide methods to create new workspaces. Calling + * addWorkspace on this resource will always fail. + * + * @param workspace + * @throws DavException Always throws. + * @see DeltaVResource#addWorkspace(org.apache.jackrabbit.webdav.DavResource) + */ + @Override + public void addWorkspace(DavResource workspace) throws DavException { + throw new DavException(DavServletResponse.SC_FORBIDDEN); + } + + /** + * Return an array of DavResource objects that are referenced + * by the property with the specified name. + * + * @param hrefPropertyName + * @return array of DavResources + * @throws DavException + * @see DeltaVResource#getReferenceResources(org.apache.jackrabbit.webdav.property.DavPropertyName) + */ + @Override + public DavResource[] getReferenceResources(DavPropertyName hrefPropertyName) throws DavException { + DavProperty prop = getProperty(hrefPropertyName); + if (prop == null || !(prop instanceof HrefProperty)) { + throw new DavException(DavServletResponse.SC_CONFLICT, "Unknown Href-Property '" + hrefPropertyName + "' on resource " + getResourcePath()); + } + + List hrefs = ((HrefProperty)prop).getHrefs(); + DavResource[] refResources = new DavResource[hrefs.size()]; + Iterator hrefIter = hrefs.iterator(); + int i = 0; + while (hrefIter.hasNext()) { + refResources[i] = getResourceFromHref(hrefIter.next()); + i++; + } + return refResources; + } + + /** + * Retrieve the DavResource object that is represented by + * the given href String. + * + * @param href + * @return DavResource object + */ + private DavResource getResourceFromHref(String href) throws DavException { + // build a new locator: remove trailing prefix + DavResourceLocator locator = getLocator(); + String prefix = locator.getPrefix(); + DavResourceLocator loc = locator.getFactory().createResourceLocator(prefix, href); + + // create a new resource object + try { + DavResource res; + if (getRepositorySession().itemExists(loc.getRepositoryPath())) { + res = createResourceFromLocator(loc); + } else { + throw new DavException(DavServletResponse.SC_NOT_FOUND); + } + return res; + } catch (RepositoryException e) { + throw new JcrDavException(e); + } + } + + //-------------------------------------------< SearchResource interface >--- + /** + * @return + * @see org.apache.jackrabbit.webdav.search.SearchResource#getQueryGrammerSet() + */ + @Override + public QueryGrammerSet getQueryGrammerSet() { + return new SearchResourceImpl(getLocator(), session).getQueryGrammerSet(); + } + + /** + * @param sInfo + * @return + * @throws DavException + * @see SearchResource#search(org.apache.jackrabbit.webdav.search.SearchInfo) + */ + @Override + public MultiStatus search(SearchInfo sInfo) throws DavException { + return new SearchResourceImpl(getLocator(), session).search(sInfo); + } + + //-------------------------------------------------------------------------- + /** + * Property names common to all resources. + */ + protected void initPropertyNames() { + names = new DavPropertyNameSet(JcrDavPropertyNameSet.BASE_SET); + } + + /** + * Fill the set of default properties + */ + protected void initProperties() { + if (getDisplayName() != null) { + properties.add(new DefaultDavProperty(DavPropertyName.DISPLAYNAME, getDisplayName())); + } + if (isCollection()) { + properties.add(new ResourceType(ResourceType.COLLECTION)); + // Windows XP support + properties.add(new DefaultDavProperty(DavPropertyName.ISCOLLECTION, "1")); + } else { + properties.add(new ResourceType(ResourceType.DEFAULT_RESOURCE)); + // Windows XP support + properties.add(new DefaultDavProperty(DavPropertyName.ISCOLLECTION, "0")); + } + // todo: add etag + + // default last modified + String lastModified = IOUtil.getLastModified(getModificationTime()); + properties.add(new DefaultDavProperty(DavPropertyName.GETLASTMODIFIED, lastModified)); + + // default creation time + properties.add(new DefaultDavProperty(DavPropertyName.CREATIONDATE, getCreationDate())); + + // supported lock property + properties.add(supportedLock); + + // set current lock information. If no lock is applied to this resource, + // an empty xlockdiscovery will be returned in the response. + properties.add(new LockDiscovery(getLocks())); + + // name of the jcr workspace + properties.add(new DefaultDavProperty(ItemResourceConstants.JCR_WORKSPACE_NAME, + getRepositorySession().getWorkspace().getName())); + } + + /** + * Create a new DavResource from the given locator. + * @param loc + * @return new DavResource + * @throws org.apache.jackrabbit.webdav.DavException + */ + protected DavResource createResourceFromLocator(DavResourceLocator loc) + throws DavException { + DavResource res = factory.createResource(loc, session); + if (res instanceof AbstractResource) { + ((AbstractResource)res).transactionId = this.transactionId; + } + return res; + } + + /** + * Build a DavResourceLocator from the given itemPath path. + * + * @param itemPath + * @return a new DavResourceLocator + * @see DavLocatorFactory#createResourceLocator(String, String, String) + */ + protected DavResourceLocator getLocatorFromItemPath(String itemPath) { + DavResourceLocator loc = locator.getFactory().createResourceLocator(locator.getPrefix(), locator.getWorkspacePath(), itemPath, false); + return loc; + } + + /** + * Build a new {@link DavResourceLocator} from the given repository item. + * + * @param repositoryItem + * @return a new locator for the specified item. + * @see #getLocatorFromItemPath(String) + */ + protected DavResourceLocator getLocatorFromItem(Item repositoryItem) { + String itemPath = null; + try { + if (repositoryItem != null) { + itemPath = repositoryItem.getPath(); + } + } catch (RepositoryException e) { + // ignore: should not occur + log.warn(e.getMessage()); + } + return getLocatorFromItemPath(itemPath); + } + + /** + * Shortcut for getSession().getRepositorySession() + * + * @return repository session present in the {@link AbstractResource#session}. + */ + protected Session getRepositorySession() { + return session.getRepositorySession(); + } + + /** + * Define the set of locks supported by this resource. + * + * @see org.apache.jackrabbit.webdav.lock.SupportedLock + */ + abstract protected void initLockSupport(); + + /** + * Define the set of reports supported by this resource. + * + * @see org.apache.jackrabbit.webdav.version.report.SupportedReportSetProperty + */ + /** + * Define the set of reports supported by this resource. + * + * @see org.apache.jackrabbit.webdav.version.report.SupportedReportSetProperty + * @see AbstractResource#initSupportedReports() + */ + protected void initSupportedReports() { + if (exists()) { + supportedReports = new SupportedReportSetProperty(new ReportType[] { + ReportType.EXPAND_PROPERTY, + NodeTypesReport.NODETYPES_REPORT, + LocateByUuidReport.LOCATE_BY_UUID_REPORT, + RegisteredNamespacesReport.REGISTERED_NAMESPACES_REPORT, + RepositoryDescriptorsReport.REPOSITORY_DESCRIPTORS_REPORT + }); + } + } + + /** + * Retrieve the href of the workspace the current session belongs to. + * + * @return href of the workspace + */ + abstract protected String getWorkspaceHref(); + + /** + * Returns the display name of the creator which is used for the protected + * {@link DeltaVConstants#CREATOR_DISPLAYNAME} property. + * + * @return always null; subclasses may provide a regular value. + */ + protected String getCreatorDisplayName() { + return null; + } + + /** + * Returns the creation date which is used for the + * {@link DavPropertyName#CREATIONDATE} property. + * + * @return a dummy date; subclasses may provide a reasonable value. + */ + protected String getCreationDate() { + return HttpDateFormat.creationDateFormat().format(new Date(0)); + } + + /** + * Normalize the resource {@code href}. For example, remove contextPath prefix if found. + * @param href resource href + * @return normalized resource {@code href} + */ + protected String normalizeResourceHref(final String href) { + if (href == null) { + return href; + } + + final WebdavRequestContext requestContext = WebdavRequestContextHolder.getContext(); + final WebdavRequest request = (requestContext != null) ? requestContext.getRequest() : null; + + if (request == null) { + log.error("WebdavRequest is unavailable in the current execution context."); + return href; + } + + final String contextPath = request.getContextPath(); + + if (!contextPath.isEmpty() && href.startsWith(contextPath)) { + return href.substring(contextPath.length()); + } + + return href; + } + + //-------------------------------------------------------------------------- + /** + * Register the specified event listener with the observation manager present + * the repository session. + * + * @param listener + * @param nodePath + * @throws javax.jcr.RepositoryException + */ + void registerEventListener(EventListener listener, String nodePath) throws RepositoryException { + getRepositorySession().getWorkspace().getObservationManager().addEventListener(listener, EListener.ALL_EVENTS, nodePath, true, null, null, false); + } + + /** + * Unregister the specified event listener with the observation manager present + * the repository session. + * + * @param listener + * @throws javax.jcr.RepositoryException + */ + void unregisterEventListener(EventListener listener) throws RepositoryException { + getRepositorySession().getWorkspace().getObservationManager().removeEventListener(listener); + } + + //------------------------------------------------------< inner classes >--- + /** + * Simple EventListener that creates a new {@link org.apache.jackrabbit.webdav.MultiStatusResponse} object + * for each event and adds it to the specified {@link org.apache.jackrabbit.webdav.MultiStatus}. + */ + class EListener implements EventListener { + + private static final int ALL_EVENTS = Event.NODE_ADDED + | Event.NODE_REMOVED + | Event.PROPERTY_ADDED + | Event.PROPERTY_CHANGED + | Event.PROPERTY_REMOVED + | Event.NODE_MOVED + | Event.PERSIST; + + private final DavPropertyNameSet propNameSet; + private MultiStatus ms; + + EListener(DavPropertyNameSet propNameSet, MultiStatus ms) { + this.propNameSet = propNameSet; + this.ms = ms; + } + + /** + * @see EventListener#onEvent(javax.jcr.observation.EventIterator) + */ + @Override + public void onEvent(EventIterator events) { + while (events.hasNext()) { + try { + Event e = events.nextEvent(); + DavResourceLocator loc = getLocatorFromItemPath(e.getPath()); + DavResource res = createResourceFromLocator(loc); + ms.addResponse(new MultiStatusResponse(res, propNameSet)); + + } catch (DavException e) { + // should not occur + log.error("Error while building MultiStatusResponse from Event: " + e.getMessage()); + } catch (RepositoryException e) { + // should not occur + log.error("Error while building MultiStatusResponse from Event: " + e.getMessage()); + } + } + } + } +} Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/AbstractResource.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/webdav/jcr/DavLocatorFactoryImpl.java =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/DavLocatorFactoryImpl.java (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/DavLocatorFactoryImpl.java (working copy) @@ -0,0 +1,94 @@ +/* + * 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.webdav.jcr; + +import org.apache.jackrabbit.webdav.AbstractLocatorFactory; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * DavLocatorFactoryImpl... + */ +public class DavLocatorFactoryImpl extends AbstractLocatorFactory { + + private static Logger log = LoggerFactory.getLogger(DavLocatorFactoryImpl.class); + + /** + * Create a new factory + * + * @param pathPrefix Prefix, that needs to be removed in order to retrieve + * the repository path from a given href. + */ + public DavLocatorFactoryImpl(String pathPrefix) { + super(pathPrefix); + } + + //---------------------------------------------------------------------- + /** + * + * @param resourcePath + * @param wspPath + * @return + * @see AbstractLocatorFactory#getRepositoryPath(String, String) + */ + @Override + protected String getRepositoryPath(String resourcePath, String wspPath) { + if (resourcePath == null) { + return null; + } + if (resourcePath.equals(wspPath)) { + // workspace + log.debug("Resource path represents workspace path -> repository path is null."); + return null; + } else { + // a repository item -> remove wspPath + /jcr:root + String pfx = wspPath + ItemResourceConstants.ROOT_ITEM_RESOURCEPATH; + if (resourcePath.startsWith(pfx)) { + String repositoryPath = resourcePath.substring(pfx.length()); + return (repositoryPath.length() == 0) ? ItemResourceConstants.ROOT_ITEM_PATH : repositoryPath; + } else { + log.error("Unexpected format of resource path."); + throw new IllegalArgumentException("Unexpected format of resource path: " + resourcePath + " (workspace: " + wspPath + ")"); + } + } + } + + /** + * + * @param repositoryPath + * @param wspPath + * @return + * @see AbstractLocatorFactory#getResourcePath(String, String) + */ + @Override + protected String getResourcePath(String repositoryPath, String wspPath) { + if (wspPath != null) { + StringBuffer b = new StringBuffer(wspPath); + if (repositoryPath != null) { + b.append(ItemResourceConstants.ROOT_ITEM_RESOURCEPATH); + if (!ItemResourceConstants.ROOT_ITEM_PATH.equals(repositoryPath)) { + b.append(repositoryPath); + } + } + return b.toString(); + } else { + log.debug("Workspace path is 'null' -> 'null' resource path"); + return null; + } + } +} + Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/DavLocatorFactoryImpl.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/webdav/jcr/DavResourceFactoryImpl.java =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/DavResourceFactoryImpl.java (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/DavResourceFactoryImpl.java (working copy) @@ -0,0 +1,251 @@ +/* + * 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.webdav.jcr; + +import javax.jcr.AccessDeniedException; +import javax.jcr.Item; +import javax.jcr.Node; +import javax.jcr.PathNotFoundException; +import javax.jcr.RepositoryException; +import javax.jcr.observation.EventJournal; +import javax.jcr.version.Version; +import javax.jcr.version.VersionHistory; +import javax.servlet.http.HttpServletResponse; + +import org.apache.jackrabbit.JcrConstants; +import org.apache.jackrabbit.util.Text; +import org.apache.jackrabbit.webdav.DavException; +import org.apache.jackrabbit.webdav.DavMethods; +import org.apache.jackrabbit.webdav.DavResource; +import org.apache.jackrabbit.webdav.DavResourceFactory; +import org.apache.jackrabbit.webdav.DavResourceLocator; +import org.apache.jackrabbit.webdav.DavServletRequest; +import org.apache.jackrabbit.webdav.DavServletResponse; +import org.apache.jackrabbit.webdav.DavSession; +import org.apache.jackrabbit.webdav.jcr.transaction.TxLockManagerImpl; +import org.apache.jackrabbit.webdav.jcr.version.VersionHistoryItemCollection; +import org.apache.jackrabbit.webdav.jcr.version.VersionItemCollection; +import org.apache.jackrabbit.webdav.observation.ObservationResource; +import org.apache.jackrabbit.webdav.observation.SubscriptionManager; +import org.apache.jackrabbit.webdav.transaction.TransactionDavServletRequest; +import org.apache.jackrabbit.webdav.transaction.TransactionResource; +import org.apache.jackrabbit.webdav.version.DeltaVServletRequest; +import org.apache.jackrabbit.webdav.version.VersionControlledResource; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * DavResourceFactoryImpl... + */ +public class DavResourceFactoryImpl implements DavResourceFactory { + + private static Logger log = LoggerFactory.getLogger(DavResourceFactoryImpl.class); + + private final TxLockManagerImpl txMgr; + private final SubscriptionManager subsMgr; + + /** + * Create a new DavResourceFactoryImpl. + * + * @param txMgr + * @param subsMgr + */ + public DavResourceFactoryImpl(TxLockManagerImpl txMgr, SubscriptionManager subsMgr) { + this.txMgr = txMgr; + this.subsMgr = subsMgr; + } + + /** + * Create a new DavResource from the specified locator and request + * objects. Note, that in contrast to + * {@link #createResource(DavResourceLocator, DavSession)} the locator may + * point to a non-existing resource. + *

+ * If the request contains a {@link org.apache.jackrabbit.webdav.version.DeltaVServletRequest#getLabel() + * Label header}, the resource is build from the indicated + * {@link org.apache.jackrabbit.webdav.version.VersionResource version} instead. + * + * @param locator + * @param request + * @param response + * @return + * @see DavResourceFactory#createResource(org.apache.jackrabbit.webdav.DavResourceLocator, org.apache.jackrabbit.webdav.DavServletRequest, org.apache.jackrabbit.webdav.DavServletResponse) + */ + public DavResource createResource(DavResourceLocator locator, + DavServletRequest request, + DavServletResponse response) throws DavException { + JcrDavSession.checkImplementation(request.getDavSession()); + JcrDavSession session = (JcrDavSession)request.getDavSession(); + + DavResource resource; + String type = request.getParameter("type"); + + if (locator.isRootLocation()) { + // root + resource = new RootCollection(locator, session, this); + } else if ("journal".equals(type) && locator.getResourcePath().equals(locator.getWorkspacePath())) { + // feed/event journal resource + try { + EventJournal ej = session.getRepositorySession().getWorkspace().getObservationManager() + .getEventJournal(); + if (ej == null) { + throw new DavException(HttpServletResponse.SC_NOT_IMPLEMENTED, "event journal not supported"); + } + resource = new EventJournalResourceImpl(ej, locator, session, request, this); + } catch (AccessDeniedException ex) { + // EventJournal only allowed for admin? + throw new DavException(HttpServletResponse.SC_UNAUTHORIZED, ex); + } catch (RepositoryException ex) { + throw new DavException(HttpServletResponse.SC_BAD_REQUEST, ex); + } + } else if (locator.getResourcePath().equals(locator.getWorkspacePath())) { + // workspace resource + resource = new WorkspaceResourceImpl(locator, session, this); + } else { + // resource corresponds to a repository item + try { + resource = createResourceForItem(locator, session); + + Item item = getItem(session, locator); + boolean versionable = item.isNode() && ((Node) item).isNodeType(JcrConstants.MIX_VERSIONABLE); + + /* if the created resource is version-controlled and the request + contains a Label header, the corresponding Version must be used + instead.*/ + if (request instanceof DeltaVServletRequest && versionable) { + String labelHeader = ((DeltaVServletRequest)request).getLabel(); + if (labelHeader != null && DavMethods.isMethodAffectedByLabel(request) && isVersionControlled(resource)) { + Version v = ((Node)item).getVersionHistory().getVersionByLabel(labelHeader); + DavResourceLocator vloc = locator.getFactory().createResourceLocator(locator.getPrefix(), locator.getWorkspacePath(), v.getPath(), false); + resource = new VersionItemCollection(vloc, session, this, v); + } + } + } catch (PathNotFoundException e) { + /* item does not exist yet: create the default resources + Note: MKCOL request forces a collection-resource even if there already + exists a repository-property with the given path. the MKCOL will + in that particular case fail with a 405 (method not allowed).*/ + if (DavMethods.getMethodCode(request.getMethod()) == DavMethods.DAV_MKCOL) { + resource = new VersionControlledItemCollection(locator, session, this, null); + } else { + resource = new DefaultItemResource(locator, session, this, null); + } + } catch (RepositoryException e) { + log.error("Failed to build resource from item '"+ locator.getRepositoryPath() + "'"); + throw new JcrDavException(e); + } + } + + if (request instanceof TransactionDavServletRequest && resource instanceof TransactionResource) { + ((TransactionResource)resource).init(txMgr, ((TransactionDavServletRequest)request).getTransactionId()); + } + if (resource instanceof ObservationResource) { + ((ObservationResource)resource).init(subsMgr); + } + return resource; + } + + /** + * Create a new DavResource from the given locator and session. + * + * @param locator + * @param session + * @return DavResource representing either a repository item or the {@link RootCollection}. + * @throws DavException if the given locator does neither refer to a repository item + * nor does represent the {@link org.apache.jackrabbit.webdav.DavResourceLocator#isRootLocation() + * root location}. + */ + public DavResource createResource(DavResourceLocator locator, DavSession session) throws DavException { + JcrDavSession.checkImplementation(session); + JcrDavSession sessionImpl = (JcrDavSession)session; + + DavResource resource; + if (locator.isRootLocation()) { + resource = new RootCollection(locator, sessionImpl, this); + } else if (locator.getResourcePath().equals(locator.getWorkspacePath())) { + resource = new WorkspaceResourceImpl(locator, sessionImpl, this); + } else { + try { + resource = createResourceForItem(locator, sessionImpl); + } catch (RepositoryException e) { + log.debug("Creating resource for non-existing repository item: " + locator.getRepositoryPath()); + // todo: is this correct? + resource = new VersionControlledItemCollection(locator, sessionImpl, this, null); + } + } + + // todo: currently transactionId is set manually after creation > to be improved. + resource.addLockManager(txMgr); + if (resource instanceof ObservationResource) { + ((ObservationResource)resource).init(subsMgr); + } + return resource; + } + + /** + * Tries to retrieve the repository item defined by the locator's resource + * path and build the corresponding WebDAV resource. The following distinction + * is made between items: Version nodes, VersionHistory nodes, root node, + * unspecified nodes and finally property items. + * + * @param locator + * @param sessionImpl + * @return DavResource representing a repository item. + * @throws RepositoryException if {@link javax.jcr.Session#getItem(String)} fails. + */ + private DavResource createResourceForItem(DavResourceLocator locator, JcrDavSession sessionImpl) throws RepositoryException, DavException { + DavResource resource; + Item item = getItem(sessionImpl, locator); + if (item.isNode()) { + // create special resources for Version and VersionHistory + if (item instanceof Version) { + resource = new VersionItemCollection(locator, sessionImpl, this, item); + } else if (item instanceof VersionHistory) { + resource = new VersionHistoryItemCollection(locator, sessionImpl, this, item); + } else{ + resource = new VersionControlledItemCollection(locator, sessionImpl, this, item); + } + } else { + resource = new DefaultItemResource(locator, sessionImpl, this, item); + } + return resource; + } + + protected Item getItem(JcrDavSession sessionImpl, DavResourceLocator locator) + throws PathNotFoundException, RepositoryException { + return sessionImpl.getRepositorySession().getItem(locator.getRepositoryPath()); + } + + /** + * Returns true, if the specified resource is a {@link VersionControlledResource} + * and has a version history. + * + * @param resource + * @return true if the specified resource is version-controlled. + */ + private boolean isVersionControlled(DavResource resource) { + boolean vc = false; + if (resource instanceof VersionControlledResource) { + try { + vc = ((VersionControlledResource)resource).getVersionHistory() != null; + } catch (DavException e) { + log.debug("Resource '" + resource.getHref() + "' is not version-controlled."); + } + } + return vc; + } +} Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/DavResourceFactoryImpl.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/webdav/jcr/DefaultItemCollection.java =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/DefaultItemCollection.java (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/DefaultItemCollection.java (working copy) @@ -0,0 +1,1168 @@ +/* + * 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.webdav.jcr; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.OutputStream; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; +import java.util.Set; + +import javax.jcr.AccessDeniedException; +import javax.jcr.ImportUUIDBehavior; +import javax.jcr.Item; +import javax.jcr.ItemExistsException; +import javax.jcr.ItemNotFoundException; +import javax.jcr.Node; +import javax.jcr.NodeIterator; +import javax.jcr.PathNotFoundException; +import javax.jcr.Property; +import javax.jcr.PropertyIterator; +import javax.jcr.PropertyType; +import javax.jcr.RepositoryException; +import javax.jcr.Session; +import javax.jcr.UnsupportedRepositoryOperationException; +import javax.jcr.version.VersionIterator; +import javax.jcr.version.Version; +import javax.jcr.lock.Lock; +import javax.jcr.nodetype.NodeType; +import javax.xml.parsers.ParserConfigurationException; + +import org.apache.jackrabbit.JcrConstants; +import org.apache.jackrabbit.commons.webdav.JcrValueType; +import org.apache.jackrabbit.server.io.IOUtil; +import org.apache.jackrabbit.util.Text; +import org.apache.jackrabbit.webdav.DavCompliance; +import org.apache.jackrabbit.webdav.DavException; +import org.apache.jackrabbit.webdav.DavResource; +import org.apache.jackrabbit.webdav.DavResourceFactory; +import org.apache.jackrabbit.webdav.DavResourceIterator; +import org.apache.jackrabbit.webdav.DavResourceIteratorImpl; +import org.apache.jackrabbit.webdav.DavResourceLocator; +import org.apache.jackrabbit.webdav.DavServletResponse; +import org.apache.jackrabbit.webdav.MultiStatusResponse; +import org.apache.jackrabbit.webdav.jcr.property.JcrDavPropertyNameSet; +import org.apache.jackrabbit.webdav.jcr.security.JcrUserPrivilegesProperty; +import org.apache.jackrabbit.webdav.jcr.security.JcrSupportedPrivilegesProperty; +import org.apache.jackrabbit.webdav.jcr.security.SecurityUtils; +import org.apache.jackrabbit.webdav.security.SecurityConstants; +import org.apache.jackrabbit.webdav.util.HttpDateFormat; +import org.apache.jackrabbit.webdav.io.InputContext; +import org.apache.jackrabbit.webdav.io.OutputContext; +import org.apache.jackrabbit.webdav.jcr.lock.JcrActiveLock; +import org.apache.jackrabbit.webdav.jcr.lock.SessionScopedLockEntry; +import org.apache.jackrabbit.webdav.jcr.nodetype.NodeTypeProperty; +import org.apache.jackrabbit.webdav.jcr.property.ValuesProperty; +import org.apache.jackrabbit.webdav.jcr.version.report.ExportViewReport; +import org.apache.jackrabbit.webdav.jcr.version.report.LocateCorrespondingNodeReport; +import org.apache.jackrabbit.webdav.lock.ActiveLock; +import org.apache.jackrabbit.webdav.lock.LockInfo; +import org.apache.jackrabbit.webdav.lock.Scope; +import org.apache.jackrabbit.webdav.lock.Type; +import org.apache.jackrabbit.webdav.ordering.OrderPatch; +import org.apache.jackrabbit.webdav.ordering.OrderingConstants; +import org.apache.jackrabbit.webdav.ordering.OrderingResource; +import org.apache.jackrabbit.webdav.ordering.OrderingType; +import org.apache.jackrabbit.webdav.ordering.Position; +import org.apache.jackrabbit.webdav.property.DavProperty; +import org.apache.jackrabbit.webdav.property.DavPropertyName; +import org.apache.jackrabbit.webdav.property.DefaultDavProperty; +import org.apache.jackrabbit.webdav.property.HrefProperty; +import org.apache.jackrabbit.webdav.property.PropEntry; +import org.apache.jackrabbit.webdav.xml.DomUtil; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.w3c.dom.Document; +import org.xml.sax.SAXException; + +/** + * DefaultItemCollection represents a JCR node item. + */ +public class DefaultItemCollection extends AbstractItemResource + implements OrderingResource { + + private static Logger log = LoggerFactory.getLogger(DefaultItemCollection.class); + private static final String TMP_PREFIX = "_tmp_"; + + /** + * Create a new DefaultItemCollection. + * + * @param locator + * @param session + * @param factory + * @param item + */ + protected DefaultItemCollection(DavResourceLocator locator, + JcrDavSession session, + DavResourceFactory factory, Item item) { + super(locator, session, factory, item); + if (exists() && !(item instanceof Node)) { + throw new IllegalArgumentException("A collection resource can not be constructed from a Property item."); + } + } + + //----------------------------------------------< DavResource interface >--- + /** + * @see org.apache.jackrabbit.webdav.DavResource#getComplianceClass() + */ + @Override + public String getComplianceClass() { + String cc = super.getComplianceClass(); + if (isOrderable()) { + return DavCompliance.concatComplianceClasses( + new String[] { + cc, + DavCompliance.ORDERED_COLLECTIONS, + } + ); + } else { + return cc; + } + } + + @Override + public long getModificationTime() { + // retrieve mod-time from jcr:lastmodified property if existing + if (exists()) { + try { + if (((Node)item).hasProperty(JcrConstants.JCR_LASTMODIFIED)) { + return ((Node)item).getProperty(JcrConstants.JCR_LASTMODIFIED).getLong(); + } + } catch (RepositoryException e) { + log.warn("Error while accessing jcr:lastModified property"); + } + } + // fallback: return 'now' + return new Date().getTime(); + } + + /** + * @see org.apache.jackrabbit.webdav.DavResource#getSupportedMethods() + */ + @Override + public String getSupportedMethods() { + String ms = super.getSupportedMethods(); + if (isOrderable()) { + StringBuffer sb = new StringBuffer(ms); + sb.append(", ").append(OrderingResource.METHODS); + return sb.toString(); + } else { + return ms; + } + } + + /** + * Always returns true + * + * @return true + * @see org.apache.jackrabbit.webdav.DavResource#isCollection() + */ + @Override + public boolean isCollection() { + return true; + } + + /** + * If this resource represents an existing Node the system + * view is spooled as resource content. + * + * @param outputContext + * @throws IOException + * @see Session#exportSystemView(String, OutputStream, boolean, boolean) + */ + @Override + public void spool(OutputContext outputContext) throws IOException { + // spool properties + super.spool(outputContext); + // spool data + try { + OutputStream out = outputContext.getOutputStream(); + if (out != null && exists()) { + getRepositorySession().exportSystemView(item.getPath(), out, false, true); + } + } catch (PathNotFoundException e) { + log.error("Error while spooling resource content: " + e.getMessage()); + } catch (RepositoryException e) { + log.error("Error while spooling resource content: " + e.getMessage()); + } + } + + @Override + public DavProperty getProperty(DavPropertyName name) { + DavProperty prop = super.getProperty(name); + + if (prop == null && exists()) { + Node n = (Node) item; + + // add node-specific resource properties + try { + if (JCR_INDEX.equals(name)) { + prop = new DefaultDavProperty(JCR_INDEX, n.getIndex(), true); + } else if (JCR_REFERENCES.equals(name)) { + prop = getHrefProperty(JCR_REFERENCES, n.getReferences(), true); + } else if (JCR_WEAK_REFERENCES.equals(name)) { + prop = getHrefProperty(JCR_WEAK_REFERENCES, n.getWeakReferences(), true); + } else if (JCR_UUID.equals(name)) { + if (isReferenceable()) { + prop = new DefaultDavProperty(JCR_UUID, n.getUUID(), true); + } + } else if (JCR_PRIMARYITEM.equals(name)) { + if (hasPrimaryItem()) { + Item primaryItem = n.getPrimaryItem(); + prop = getHrefProperty(JCR_PRIMARYITEM, new Item[] {primaryItem}, true); + } + } else if (OrderingConstants.ORDERING_TYPE.equals(name) && isOrderable()) { + // property defined by RFC 3648: this resource always has custom ordering! + prop = new OrderingType(OrderingConstants.ORDERING_TYPE_CUSTOM); + } else if (SecurityConstants.SUPPORTED_PRIVILEGE_SET.equals(name)) { + prop = new JcrSupportedPrivilegesProperty(getRepositorySession(), n.getPath()).asDavProperty(); + } else if (SecurityConstants.CURRENT_USER_PRIVILEGE_SET.equals(name)) { + prop = new JcrUserPrivilegesProperty(getRepositorySession(), n.getPath()).asDavProperty(); + } + } catch (RepositoryException e) { + log.error("Failed to retrieve node-specific property: " + e); + } + } + + return prop; + } + + /** + * This implementation of the DavResource does only allow + * to set the mixinnodetypes property. Please note that the existing list of + * mixin nodetypes will be completely replaced.
+ * In order to add / set any other repository property on the underlying + * {@link javax.jcr.Node} use addMember(DavResource) or + * addMember(DavResource, InputStream) or modify the value + * of the corresponding resource. + * + * @param property + * @throws org.apache.jackrabbit.webdav.DavException + * @see org.apache.jackrabbit.webdav.DavResource#setProperty(org.apache.jackrabbit.webdav.property.DavProperty) + * @see #JCR_MIXINNODETYPES + */ + @Override + public void setProperty(DavProperty property) throws DavException { + internalSetProperty(property); + complete(); + } + + /** + * Internal method used to set or add the given property + * + * @param property + * @throws DavException + * @see #setProperty(DavProperty) + */ + private void internalSetProperty(DavProperty property) throws DavException { + if (!exists()) { + throw new DavException(DavServletResponse.SC_NOT_FOUND); + } + DavPropertyName propName = property.getName(); + if (JCR_MIXINNODETYPES.equals(propName)) { + Node n = (Node) item; + try { + NodeTypeProperty mix = new NodeTypeProperty(property); + Set mixins = mix.getNodeTypeNames(); + + for (NodeType existingMixin : n.getMixinNodeTypes()) { + String name = existingMixin.getName(); + if (mixins.contains(name)){ + // do not add existing mixins + mixins.remove(name); + } else { + // remove mixin that are not contained in the new list + n.removeMixin(name); + } + } + + // add the remaining mixing types that are not yet set + for (String mixin : mixins) { + n.addMixin(mixin); + } + } catch (RepositoryException e) { + throw new JcrDavException(e); + } + } else if (JCR_PRIMARYNODETYPE.equals(propName)) { + Node n = (Node) item; + try { + NodeTypeProperty ntProp = new NodeTypeProperty(property); + Set names = ntProp.getNodeTypeNames(); + if (names.size() == 1) { + String ntName = names.iterator().next(); + n.setPrimaryType(ntName); + } else { + // only a single node type can be primary node type. + throw new DavException(DavServletResponse.SC_BAD_REQUEST); + } + } catch (RepositoryException e) { + throw new JcrDavException(e); + } + } else { + // all props except for mixin node types and primaryType are read-only + throw new DavException(DavServletResponse.SC_CONFLICT); + } + } + + /** + * This implementation of the DavResource does only allow + * to remove the mixinnodetypes property. + * + * @param propertyName + * @throws org.apache.jackrabbit.webdav.DavException + * @see org.apache.jackrabbit.webdav.DavResource#removeProperty(org.apache.jackrabbit.webdav.property.DavPropertyName) + * @see #JCR_MIXINNODETYPES + */ + @Override + public void removeProperty(DavPropertyName propertyName) throws DavException { + internalRemoveProperty(propertyName); + complete(); + } + + /** + * Internal method used to remove the property with the given name. + * + * @param propertyName + * @throws DavException + * @see #removeProperty(DavPropertyName) + */ + private void internalRemoveProperty(DavPropertyName propertyName) throws DavException { + if (!exists()) { + throw new DavException(DavServletResponse.SC_NOT_FOUND); + } + if (JCR_MIXINNODETYPES.equals(propertyName)) { + // remove all mixin nodetypes + try { + Node n = (Node)item; + for (NodeType mixin : n.getMixinNodeTypes()) { + n.removeMixin(mixin.getName()); + } + } catch (RepositoryException e) { + // NoSuchNodeTypeException, ConstraintViolationException should never occur... + throw new JcrDavException(e); + } + } else { + // all props except for mixin node types are read-only + throw new DavException(DavServletResponse.SC_CONFLICT); + } + } + + /** + * Loops over the given Lists and alters the properties accordingly. + * Changes are persisted at the end according to the rules defined with + * the {@link AbstractItemResource#complete()} method.

+ * Please note: since there is only a single property + * ({@link ItemResourceConstants#JCR_MIXINNODETYPES} + * that can be set or removed with PROPPATCH, this method either succeeds + * or throws an exception, even if this violates RFC 2518. Thus no property + * specific multistatus will be created in case of an error. + * + * @param changeList + * @return + * @throws DavException + */ + @Override + public MultiStatusResponse alterProperties(List changeList) throws DavException { + for (PropEntry propEntry : changeList) { + if (propEntry instanceof DavPropertyName) { + // use the internal remove method in order to prevent premature 'save' + DavPropertyName propName = (DavPropertyName) propEntry; + internalRemoveProperty(propName); + } else if (propEntry instanceof DavProperty) { + // use the internal set method in order to prevent premature 'save' + DavProperty prop = (DavProperty) propEntry; + internalSetProperty(prop); + } else { + throw new IllegalArgumentException("unknown object in change list: " + propEntry.getClass().getName()); + } + } + // TODO: missing undo of successful set/remove if subsequent operation fails + // NOTE, that this is relevant with transactions only. + + // success: save all changes together if no error occurred + complete(); + return new MultiStatusResponse(getHref(), DavServletResponse.SC_OK); + } + + /** + * If the specified resource represents a collection, a new node is {@link Node#addNode(String) + * added} to the item represented by this resource. If an input stream is specified + * together with a collection resource {@link Session#importXML(String, java.io.InputStream, int)} + * is called instead and this resource path is used as parentAbsPath argument. + *

+ * However, if the specified resource is not of resource type collection a + * new {@link Property} is set or an existing one is changed by modifying its + * value.
+ * NOTE: with the current implementation it is not possible to create or + * modify multivalue JCR properties.
+ * NOTE: if the JCR property represented by the specified resource has an + * {@link PropertyType#UNDEFINED undefined} resource type, its value will be + * changed/set to type {@link PropertyType#BINARY binary}. + * + * @param resource + * @param inputContext + * @throws org.apache.jackrabbit.webdav.DavException + * @see org.apache.jackrabbit.webdav.DavResource#addMember(org.apache.jackrabbit.webdav.DavResource, InputContext) + * @see Node#addNode(String) + * @see Node#setProperty(String, java.io.InputStream) + */ + @Override + public void addMember(DavResource resource, InputContext inputContext) + throws DavException { + + /* RFC 2815 states that all 'parents' must exist in order all addition of members */ + if (!exists()) { + throw new DavException(DavServletResponse.SC_CONFLICT); + } + + File tmpFile = null; + try { + Node n = (Node) item; + InputStream in = (inputContext != null) ? inputContext.getInputStream() : null; + String itemPath = getLocator().getRepositoryPath(); + String memberName = getItemName(resource.getLocator().getRepositoryPath()); + if (resource.isCollection()) { + if (in == null) { + // MKCOL without a request body, try if a default-primary-type is defined. + n.addNode(memberName); + } else { + // MKCOL, which is not allowed for existing resources + int uuidBehavior = ImportUUIDBehavior.IMPORT_UUID_CREATE_NEW; + String str = inputContext.getProperty(IMPORT_UUID_BEHAVIOR); + if (str != null) { + try { + uuidBehavior = Integer.parseInt(str); + } catch (NumberFormatException e) { + throw new DavException(DavServletResponse.SC_BAD_REQUEST); + } + } + if (getTransactionId() == null) { + // if not part of a transaction directly import on workspace + // since changes would be explicitly saved in the + // complete-call. + getRepositorySession().getWorkspace().importXML(itemPath, in, uuidBehavior); + } else { + // changes will not be persisted unless the tx is completed. + getRepositorySession().importXML(itemPath, in, uuidBehavior); + } + } + } else { + if (in == null) { + // PUT: not possible without request body + throw new DavException(DavServletResponse.SC_BAD_REQUEST, "Cannot create a new non-collection resource without request body."); + } + // PUT : create new or overwrite existing property. + String ct = inputContext.getContentType(); + int type = JcrValueType.typeFromContentType(ct); + if (type != PropertyType.UNDEFINED) { + // no need to create value/values property. instead + // prop-value can be retrieved directly: + int pos = ct.indexOf(';'); + String charSet = (pos > -1) ? ct.substring(pos) : "UTF-8"; + if (type == PropertyType.BINARY) { + n.setProperty(memberName, inputContext.getInputStream()); + } else { + BufferedReader r = new BufferedReader(new InputStreamReader(inputContext.getInputStream(), charSet)); + String line; + StringBuffer value = new StringBuffer(); + while ((line = r.readLine()) != null) { + value.append(line); + } + n.setProperty(memberName, value.toString(), type); + } + } else { + // try to parse the request body into a 'values' property. + tmpFile = File.createTempFile(TMP_PREFIX + Text.escape(memberName), null, null); + FileOutputStream out = new FileOutputStream(tmpFile); + IOUtil.spool(in, out); + out.close(); + // try to parse the request body into a 'values' property. + ValuesProperty vp = buildValuesProperty(new FileInputStream(tmpFile)); + if (vp != null) { + if (JCR_VALUE.equals(vp.getName())) { + n.setProperty(memberName, vp.getJcrValue()); + } else { + n.setProperty(memberName, vp.getJcrValues()); + } + } else { + // request body cannot be parsed into a 'values' property. + // fallback: try to import as single value from stream. + n.setProperty(memberName, new FileInputStream(tmpFile)); + } + } + } + if (resource.exists() && resource instanceof AbstractItemResource) { + // PUT may modify value of existing jcr property. thus, this + // node is not modified by the 'addMember' call. + ((AbstractItemResource)resource).complete(); + } else { + complete(); + } + } catch (ItemExistsException e) { + // according to RFC 2518: MKCOL only possible on non-existing/deleted resource + throw new JcrDavException(e, DavServletResponse.SC_METHOD_NOT_ALLOWED); + } catch (RepositoryException e) { + throw new JcrDavException(e); + } catch (IOException e) { + throw new DavException(DavServletResponse.SC_UNPROCESSABLE_ENTITY, e.getMessage()); + } finally { + if (tmpFile != null) { + tmpFile.delete(); + } + } + } + + /** + * @see org.apache.jackrabbit.webdav.DavResource#getMembers() + */ + @Override + public DavResourceIterator getMembers() { + ArrayList memberList = new ArrayList(); + if (exists()) { + try { + Node n = (Node)item; + // add all node members + NodeIterator it = n.getNodes(); + while (it.hasNext()) { + Node node = it.nextNode(); + DavResourceLocator loc = getLocatorFromItem(node); + memberList.add(createResourceFromLocator(loc)); + } + // add all property members + PropertyIterator propIt = n.getProperties(); + while (propIt.hasNext()) { + Property prop = propIt.nextProperty(); + DavResourceLocator loc = getLocatorFromItem(prop); + memberList.add(createResourceFromLocator(loc)); + } + } catch (RepositoryException e) { + // ignore + log.error(e.getMessage()); + } catch (DavException e) { + // should never occur. + log.error(e.getMessage()); + } + } + return new DavResourceIteratorImpl(memberList); + } + + /** + * Removes the repository item represented by the specified member + * resource. + * + * @throws DavException if this resource does not exist or if an error occurs + * while deleting the underlying item. + * @see DavResource#removeMember(DavResource) + * @see javax.jcr.Item#remove() + */ + @Override + public void removeMember(DavResource member) throws DavException { + Session session = getRepositorySession(); + try { + String itemPath = member.getLocator().getRepositoryPath(); + if (!exists() || !session.itemExists(itemPath)) { + throw new DavException(DavServletResponse.SC_NOT_FOUND); + } + if (!getResourcePath().equals(Text.getRelativeParent(member.getResourcePath(), 1))) { + throw new DavException(DavServletResponse.SC_CONFLICT, member.getResourcePath() + "is not member of this resource (" + getResourcePath() + ")"); + } + getRepositorySession().getItem(itemPath).remove(); + complete(); + } catch (RepositoryException e) { + log.error("Unexpected error: " + e.getMessage()); + throw new JcrDavException(e); + } + } + + /** + * @param type + * @param scope + * @return true if a lock with the specified type and scope is present on + * this resource, false otherwise. If retrieving the corresponding information + * fails, false is returned. + * @see org.apache.jackrabbit.webdav.DavResource#hasLock(org.apache.jackrabbit.webdav.lock.Type, org.apache.jackrabbit.webdav.lock.Scope) + */ + @Override + public boolean hasLock(Type type, Scope scope) { + if (isLockable(type, scope)) { + if (Type.WRITE.equals(type)) { + try { + return ((Node) item).isLocked(); + } catch (RepositoryException e) { + log.error(e.getMessage()); + } + } else { + return super.hasLock(type, scope); + } + } + return false; + } + + /** + * Retrieve the lock with the specified type and scope. + * + * @param type + * @param scope + * @return lock with the specified type and scope is present on this + * resource or null. NOTE: If retrieving the write lock present + * on the underlying repository item fails, null is return. + * @see org.apache.jackrabbit.webdav.DavResource#getLock(org.apache.jackrabbit.webdav.lock.Type, org.apache.jackrabbit.webdav.lock.Scope) + * @see javax.jcr.Node#getLock() for the write locks. + */ + @Override + public ActiveLock getLock(Type type, Scope scope) { + ActiveLock lock = null; + if (Type.WRITE.equals(type)) { + try { + if (!exists()) { + log.warn("Unable to retrieve lock: no item found at '" + getResourcePath() + "'"); + } else if (((Node) item).isLocked()) { + Lock jcrLock = ((Node) item).getLock(); + lock = new JcrActiveLock(jcrLock); + DavResourceLocator locator = super.getLocator(); + String lockroot = locator + .getFactory() + .createResourceLocator(locator.getPrefix(), locator.getWorkspacePath(), jcrLock.getNode().getPath(), + false).getHref(false); + lock.setLockroot(lockroot); + } + } catch (AccessDeniedException e) { + log.error("Error while accessing resource lock: "+e.getMessage()); + } catch (UnsupportedRepositoryOperationException e) { + log.error("Error while accessing resource lock: "+e.getMessage()); + } catch (RepositoryException e) { + log.error("Error while accessing resource lock: "+e.getMessage()); + } + } else { + lock = super.getLock(type, scope); + } + return lock; + } + + /** + * Creates a lock on this resource by locking the underlying + * {@link javax.jcr.Node node}. Except for the {@link org.apache.jackrabbit.webdav.lock.LockInfo#isDeep()} } + * all information included in the LockInfo object is ignored. + * Lock timeout is defined by JCR implementation. + * + * @param reqLockInfo + * @return lock object representing the lock created on this resource. + * @throws org.apache.jackrabbit.webdav.DavException + * @see org.apache.jackrabbit.webdav.DavResource#lock(org.apache.jackrabbit.webdav.lock.LockInfo) + * @see Node#lock(boolean, boolean) + */ + @Override + public ActiveLock lock(LockInfo reqLockInfo) throws DavException { + + if (!isLockable(reqLockInfo.getType(), reqLockInfo.getScope())) { + throw new DavException(DavServletResponse.SC_PRECONDITION_FAILED); + } + + if (Type.WRITE.equals(reqLockInfo.getType())) { + if (!exists()) { + log.warn("Cannot create a write lock for non-existing JCR node (" + getResourcePath() + ")"); + throw new DavException(DavServletResponse.SC_NOT_FOUND); + } + try { + boolean sessionScoped = EXCLUSIVE_SESSION.equals(reqLockInfo.getScope()); + long timeout = reqLockInfo.getTimeout(); + if (timeout == LockInfo.INFINITE_TIMEOUT) { + timeout = Long.MAX_VALUE; + } else { + timeout = timeout/1000; + } + javax.jcr.lock.LockManager lockMgr = getRepositorySession().getWorkspace().getLockManager(); + Lock jcrLock = lockMgr.lock((item).getPath(), reqLockInfo.isDeep(), + sessionScoped, timeout, reqLockInfo.getOwner()); + ActiveLock lock = new JcrActiveLock(jcrLock); + // add reference to DAVSession for this lock + getSession().addReference(lock.getToken()); + return lock; + } catch (RepositoryException e) { + // UnsupportedRepositoryOperationException should not occur... + throw new JcrDavException(e); + } + } else { + return super.lock(reqLockInfo); + } + } + + /** + * Refreshes the lock on this resource. With this implementation the + * {@link javax.jcr.lock lock} present on the underlying {@link javax.jcr.Node node} + * is refreshed. The timeout indicated by the LockInfo + * object is ignored. + * + * @param reqLockInfo LockInfo as build from the request. + * @param lockToken + * @return the updated lock info object. + * @throws org.apache.jackrabbit.webdav.DavException in case the lock could not be refreshed. + * @see org.apache.jackrabbit.webdav.DavResource#refreshLock(org.apache.jackrabbit.webdav.lock.LockInfo, String) + * @see javax.jcr.lock.Lock#refresh() + */ + @Override + public ActiveLock refreshLock(LockInfo reqLockInfo, String lockToken) + throws DavException { + + if (lockToken == null) { + throw new DavException(DavServletResponse.SC_PRECONDITION_FAILED); + } + + ActiveLock lock = getLock(reqLockInfo.getType(), reqLockInfo.getScope()); + if (lock == null) { + throw new DavException(DavServletResponse.SC_PRECONDITION_FAILED, "No lock with the given scope/type present on this resource."); + } + + if (Type.WRITE.equals(lock.getType())) { + try { + Lock jcrLock = ((Node) item).getLock(); + jcrLock.refresh(); + return new JcrActiveLock(jcrLock); + } catch (RepositoryException e) { + /* + NOTE: LockException is only thrown by Lock.refresh() + the lock exception thrown by Node.getLock() was circumvented + by the init test if there is a lock applied... + NOTE: UnsupportedRepositoryOperationException should not occur + */ + throw new JcrDavException(e); + } + } else { + return super.refreshLock(reqLockInfo, lockToken); + } + } + + /** + * Remove the write lock from this resource by unlocking the underlying + * {@link javax.jcr.Node node}. + * + * @param lockToken + * @throws org.apache.jackrabbit.webdav.DavException + * @see org.apache.jackrabbit.webdav.DavResource#unlock(String) + * @see javax.jcr.Node#unlock() + */ + @Override + public void unlock(String lockToken) throws DavException { + ActiveLock lock = getWriteLock(); + if (lock != null && lockToken.equals(lock.getToken())) { + try { + ((Node) item).unlock(); + getSession().removeReference(lock.getToken()); + } catch (RepositoryException e) { + throw new JcrDavException(e); + } + } else { + super.unlock(lockToken); + } + } + + /** + * Returns the write lock present on this resource or null if + * no write lock exists. NOTE: that the scope of a write lock may either + * be {@link org.apache.jackrabbit.webdav.lock.Scope#EXCLUSIVE} or + * {@link ItemResourceConstants#EXCLUSIVE_SESSION}. + * + * @return write lock or null + * @throws DavException if this resource does not represent a repository item. + */ + private ActiveLock getWriteLock() throws DavException { + if (!exists()) { + throw new DavException(DavServletResponse.SC_NOT_FOUND, "Unable to retrieve write lock for non existing repository item (" + getResourcePath() + ")"); + } + ActiveLock writeLock = getLock(Type.WRITE, Scope.EXCLUSIVE); + if (writeLock == null) { + writeLock = getLock(Type.WRITE, EXCLUSIVE_SESSION); + } + return writeLock; + } + + //-----------------------------------------< OrderingResource interface >--- + /** + * Returns true if this resource exists and the nodetype defining the + * underlying repository node allow to reorder this nodes children. + * + * @return true if {@link DefaultItemCollection#orderMembers(OrderPatch)} + * can be called on this resource. + * @see org.apache.jackrabbit.webdav.ordering.OrderingResource#isOrderable() + * @see javax.jcr.nodetype.NodeType#hasOrderableChildNodes() + */ + @Override + public boolean isOrderable() { + boolean orderable = false; + if (exists()) { + try { + orderable = ((Node) item).getPrimaryNodeType().hasOrderableChildNodes(); + } catch (RepositoryException e) { + log.warn(e.getMessage()); + } + } + return orderable; + } + + /** + * Reorder the child nodes of the repository item represented by this + * resource as indicated by the specified {@link OrderPatch} object. + * + * @param orderPatch + * @throws org.apache.jackrabbit.webdav.DavException + * @see org.apache.jackrabbit.webdav.ordering.OrderingResource#orderMembers(org.apache.jackrabbit.webdav.ordering.OrderPatch) + * @see Node#orderBefore(String, String) + */ + @Override + public void orderMembers(OrderPatch orderPatch) throws DavException { + if (!isOrderable()) { + throw new DavException(DavServletResponse.SC_METHOD_NOT_ALLOWED); + } + // only custom ordering is allowed + if (!OrderingConstants.ORDERING_TYPE_CUSTOM.equalsIgnoreCase(orderPatch.getOrderingType())) { + throw new DavException(DavServletResponse.SC_UNPROCESSABLE_ENTITY, "Only DAV:custom ordering type supported."); + } + + Node n = (Node)item; + try { + for (OrderPatch.Member instruction : orderPatch.getOrderInstructions()) { + String srcRelPath = Text.unescape(instruction.getMemberHandle()); + Position pos = instruction.getPosition(); + String destRelPath = getRelDestinationPath(pos, n.getNodes()); + // preform the reordering + n.orderBefore(srcRelPath, destRelPath); + } + complete(); + } catch (RepositoryException e) { + // UnsupportedRepositoryException should not occur + throw new JcrDavException(e); + } + } + + /** + * Retrieve the relative path of the child node that acts as destination. + * A null destination path is used to place the child node indicated + * by the source path at the end of the list. + * + * @param position + * @param childNodes + * @return the relative path of the child node used as destination or null + * if the source node should be placed at the last position. + * @throws javax.jcr.RepositoryException + */ + private String getRelDestinationPath(Position position, NodeIterator childNodes) + throws RepositoryException { + + String destRelPath = null; + if (OrderingConstants.XML_FIRST.equals(position.getType())) { + if (childNodes.hasNext()) { + Node firstChild = childNodes.nextNode(); + // use last segment of node-path instead of name. + destRelPath = Text.getName(firstChild.getPath()); + } + // no child nodes available > reordering to 'first' position fails. + if (destRelPath == null) { + throw new ItemNotFoundException("No 'first' item found for reordering."); + } + } else if (OrderingConstants.XML_AFTER.equals(position.getType())) { + String afterRelPath = position.getSegment(); + boolean found = false; + // jcr only knows order-before > retrieve the node that follows the + // one indicated by the 'afterRelPath'. + while (childNodes.hasNext() && destRelPath == null) { + // compare to last segment of node-path instead of name. + String childRelPath = Text.getName(childNodes.nextNode().getPath()); + if (found) { + destRelPath = childRelPath; + } else { + found = afterRelPath.equals(childRelPath); + } + } + } else { + // before or last. in the latter case the segment is 'null' + destRelPath = position.getSegment(); + } + if (destRelPath != null) { + destRelPath = Text.unescape(destRelPath); + } + return destRelPath; + } + + //-------------------------------------------------------------------------- + /** + * Extend the general {@link AbstractResource#supportedLock} field by + * lock entries specific for this resource: write locks (exclusive or + * exclusive session-scoped) in case the underlying node has the node + * type mix:lockable. + * + * @see org.apache.jackrabbit.JcrConstants#MIX_LOCKABLE + */ + @Override + protected void initLockSupport() { + super.initLockSupport(); + // add exclusive write lock if allowed for the given node + try { + if (exists() && ((Node)item).isNodeType(JcrConstants.MIX_LOCKABLE)) { + supportedLock.addEntry(Type.WRITE, Scope.EXCLUSIVE); + supportedLock.addEntry(new SessionScopedLockEntry()); + } + } catch (RepositoryException e) { + log.warn(e.getMessage()); + } + } + + /** + * Defines the additional reports supported by this resource (reports + * specific for resources representing a repository {@link Node node}): + *

    + *
  • {@link ExportViewReport export view report}
  • + *
  • {@link LocateCorrespondingNodeReport locate corresponding node report}
  • + *
+ * + * @see org.apache.jackrabbit.webdav.version.report.SupportedReportSetProperty + */ + @Override + protected void initSupportedReports() { + super.initSupportedReports(); + if (exists()) { + supportedReports.addReportType(ExportViewReport.EXPORTVIEW_REPORT); + supportedReports.addReportType(LocateCorrespondingNodeReport.LOCATE_CORRESPONDING_NODE_REPORT); + } + } + + @Override + protected void initPropertyNames() { + super.initPropertyNames(); + + if (exists()) { + names.addAll(JcrDavPropertyNameSet.NODE_SET); + + if (isReferenceable()) { + names.add(JCR_UUID); + } + if (hasPrimaryItem()) { + names.add(JCR_PRIMARYITEM); + } + if (isOrderable()) { + names.add(OrderingConstants.ORDERING_TYPE); + } + if (SecurityUtils.supportsAccessControl(getRepositorySession())) { + names.add(SecurityConstants.SUPPORTED_PRIVILEGE_SET); + names.add(SecurityConstants.CURRENT_USER_PRIVILEGE_SET); + } + } + } + + /** + * Fill the property set for this resource. + */ + @Override + protected void initProperties() { + super.initProperties(); + if (exists()) { + // resource is serialized as system-view (xml) + properties.add(new DefaultDavProperty(DavPropertyName.GETCONTENTTYPE, "text/xml")); + Node n = (Node)item; + + // add node-specific resource properties + try { + properties.add(new NodeTypeProperty(JCR_PRIMARYNODETYPE, n.getPrimaryNodeType(), false)); + properties.add(new NodeTypeProperty(JCR_MIXINNODETYPES, n.getMixinNodeTypes(), false)); + } catch (RepositoryException e) { + log.error("Failed to retrieve node-specific property: " + e); + } + } + } + + @Override + protected String getCreatorDisplayName() { + // overwrite the default creation date and creator-displayname if possible + try { + // DAV:creator-displayname -> use jcr:createBy if present. + if (exists() && ((Node) item).hasProperty(Property.JCR_CREATED_BY)) { + return ((Node) item).getProperty(Property.JCR_CREATED_BY).getString(); + } + } catch (RepositoryException e) { + log.warn("Error while accessing jcr:createdBy property"); + } + + // fallback + return super.getCreatorDisplayName(); + } + + @Override + protected String getCreationDate() { + // overwrite the default creation date and creator-displayname if possible + try { + if (exists() && ((Node) item).hasProperty(JcrConstants.JCR_CREATED)) { + long creationTime = ((Node) item).getProperty(JcrConstants.JCR_CREATED).getValue().getLong(); + return HttpDateFormat.creationDateFormat().format(new Date(creationTime)); + } + } catch (RepositoryException e) { + log.warn("Error while accessing jcr:created property"); + } + + // fallback + return super.getCreationDate(); + } + + /** + * Creates a new HrefProperty with the specified name using the given + * array of items as value. + * + * @param name + * @param values + * @param isProtected + * @return + */ + protected HrefProperty getHrefProperty(DavPropertyName name, Item[] values, boolean isProtected) { + String[] pHref = new String[values.length]; + for (int i = 0; i < values.length; i++) { + pHref[i] = getLocatorFromItem(values[i]).getHref(true); + } + return new HrefProperty(name, pHref, isProtected); + } + + /** + * Add a {@link org.apache.jackrabbit.webdav.property.HrefProperty} with the + * specified property name and values. Each item present in the specified + * values array is referenced in the resulting property. + * + * @param name + * @param values + * @param isProtected + */ + protected void addHrefProperty(DavPropertyName name, Item[] values, boolean isProtected) { + properties.add(getHrefProperty(name, values, isProtected)); + } + + /** + * Creates a new {@link HrefProperty href property} to the property set, where + * all properties present in the specified iterator are referenced in the + * resulting property. + * + * @param name + * @param itemIterator + * @param isProtected + * @return + */ + protected HrefProperty getHrefProperty(DavPropertyName name, PropertyIterator itemIterator, + boolean isProtected) { + ArrayList l = new ArrayList(); + while (itemIterator.hasNext()) { + l.add(itemIterator.nextProperty()); + } + return getHrefProperty(name, l.toArray(new Property[l.size()]), isProtected); + } + + /** + * Add a new {@link HrefProperty href property} to the property set, where + * all properties present in the specified iterator are referenced in the + * resulting property. + * + * @param name + * @param itemIterator + * @param isProtected + * @see #addHrefProperty(DavPropertyName, Item[], boolean) + */ + protected void addHrefProperty(DavPropertyName name, PropertyIterator itemIterator, + boolean isProtected) { + properties.add(getHrefProperty(name, itemIterator, isProtected)); + } + + /** + * Add a new {@link HrefProperty href property} to the property set, where + * all versions present in the specified iterator are referenced in the + * resulting property. + * + * @param name + * @param itemIterator + * @param isProtected + */ + protected HrefProperty getHrefProperty(DavPropertyName name, VersionIterator itemIterator, + boolean isProtected) { + ArrayList l = new ArrayList(); + while (itemIterator.hasNext()) { + l.add(itemIterator.nextVersion()); + } + return getHrefProperty(name, l.toArray(new Version[l.size()]), isProtected); + } + + /** + * Add a new {@link HrefProperty href property} to the property set, where + * all versions present in the specified iterator are referenced in the + * resulting property. + * + * @param name + * @param itemIterator + * @param isProtected + */ + protected void addHrefProperty(DavPropertyName name, VersionIterator itemIterator, + boolean isProtected) { + properties.add(getHrefProperty(name, itemIterator, isProtected)); + } + + /** + * Tries to parse the given input stream as xml document and build a + * {@link ValuesProperty} out of it. + * + * @param in + * @return values property or 'null' if the given stream cannot be parsed + * into an XML document or if build the property fails. + */ + private ValuesProperty buildValuesProperty(InputStream in) { + String errorMsg = "Cannot parse stream into a 'ValuesProperty'."; + try { + Document reqBody = DomUtil.parseDocument(in); + DavProperty defaultProp = DefaultDavProperty.createFromXml(reqBody.getDocumentElement()); + ValuesProperty vp = new ValuesProperty(defaultProp, PropertyType.STRING, getRepositorySession().getValueFactory()); + return vp; + } catch (IOException e) { + log.debug(errorMsg, e); + } catch (ParserConfigurationException e) { + log.debug(errorMsg, e); + } catch (SAXException e) { + log.debug(errorMsg, e); + } catch (DavException e) { + log.debug(errorMsg, e); + } catch (RepositoryException e) { + log.debug(errorMsg, e); + } + // cannot parse request body into a 'values' property + return null; + } + + private boolean hasPrimaryItem() { + try { + return exists() && ((Node) item).getPrimaryNodeType().getPrimaryItemName() != null; + } catch (RepositoryException e) { + log.warn(e.getMessage()); + } + return false; + } + + private boolean isReferenceable() { + try { + return exists() && ((Node) item).isNodeType(JcrConstants.MIX_REFERENCEABLE); + } catch (RepositoryException e) { + log.warn(e.getMessage()); + } + return false; + } +} Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/DefaultItemCollection.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/webdav/jcr/DefaultItemResource.java =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/DefaultItemResource.java (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/DefaultItemResource.java (working copy) @@ -0,0 +1,421 @@ +/* + * 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.webdav.jcr; + +import org.apache.jackrabbit.commons.webdav.JcrValueType; +import org.apache.jackrabbit.commons.xml.SerializingContentHandler; +import org.apache.jackrabbit.server.io.IOUtil; +import org.apache.jackrabbit.webdav.DavException; +import org.apache.jackrabbit.webdav.DavResource; +import org.apache.jackrabbit.webdav.DavResourceFactory; +import org.apache.jackrabbit.webdav.DavResourceIterator; +import org.apache.jackrabbit.webdav.DavResourceIteratorImpl; +import org.apache.jackrabbit.webdav.DavResourceLocator; +import org.apache.jackrabbit.webdav.DavServletResponse; +import org.apache.jackrabbit.webdav.MultiStatusResponse; +import org.apache.jackrabbit.webdav.io.InputContext; +import org.apache.jackrabbit.webdav.io.OutputContext; +import org.apache.jackrabbit.webdav.jcr.property.JcrDavPropertyNameSet; +import org.apache.jackrabbit.webdav.jcr.property.LengthsProperty; +import org.apache.jackrabbit.webdav.jcr.property.ValuesProperty; +import org.apache.jackrabbit.webdav.lock.ActiveLock; +import org.apache.jackrabbit.webdav.lock.Scope; +import org.apache.jackrabbit.webdav.lock.Type; +import org.apache.jackrabbit.webdav.property.DavProperty; +import org.apache.jackrabbit.webdav.property.DavPropertyName; +import org.apache.jackrabbit.webdav.property.DavPropertyNameSet; +import org.apache.jackrabbit.webdav.property.DefaultDavProperty; +import org.apache.jackrabbit.webdav.property.PropEntry; +import org.apache.jackrabbit.webdav.xml.DomUtil; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.w3c.dom.Document; +import org.xml.sax.ContentHandler; +import org.xml.sax.SAXException; + +import javax.jcr.Binary; +import javax.jcr.Item; +import javax.jcr.Property; +import javax.jcr.PropertyType; +import javax.jcr.RepositoryException; +import javax.jcr.Value; +import javax.jcr.ValueFactory; +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.transform.Transformer; +import javax.xml.transform.TransformerConfigurationException; +import javax.xml.transform.TransformerException; +import javax.xml.transform.TransformerFactory; +import javax.xml.transform.dom.DOMSource; +import javax.xml.transform.sax.SAXResult; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.util.Collections; +import java.util.Date; +import java.util.List; + +/** + * DefaultItemResource represents JCR property item. + * + * @see Property + */ +public class DefaultItemResource extends AbstractItemResource { + + private static Logger log = LoggerFactory.getLogger(DefaultItemResource.class); + + /** + * Create a new DefaultItemResource. + * + * @param locator + * @param session + */ + public DefaultItemResource(DavResourceLocator locator, JcrDavSession session, + DavResourceFactory factory, Item item) { + super(locator, session, factory, item); + } + + //----------------------------------------------< DavResource interface >--- + /** + * Returns false. + * + * @return false + * @see DavResource#isCollection() + */ + @Override + public boolean isCollection() { + return false; + } + + /** + * Always returns 'now' + * + * @return + * @see DavResource#getModificationTime() + */ + @Override + public long getModificationTime() { + return new Date().getTime(); + } + + /** + * In case an underlying repository {@link Property property} exists the following + * logic is applied to spool the property content: + *
    + *
  • Property is not multi valued: Return the {@link javax.jcr.Value#getStream() + * stream representation} of the property value.
  • + *
  • Property is multivalue: Return the xml representation of the values.
  • + *
+ * + * @param outputContext + * @see DavResource#spool(OutputContext) + */ + @Override + public void spool(OutputContext outputContext) throws IOException { + // write properties + super.spool(outputContext); + // spool content + OutputStream out = outputContext.getOutputStream(); + if (out != null && exists()) { + if (isMultiple()) { + spoolMultiValued(out); + } else { + spoolSingleValued(out); + } + } + } + + private void spoolMultiValued(OutputStream out) { + try { + Document doc = DomUtil.createDocument(); + doc.appendChild(getProperty(JCR_VALUES).toXml(doc)); + + ContentHandler handler = + SerializingContentHandler.getSerializer(out); + + Transformer transformer = + TransformerFactory.newInstance().newTransformer(); + transformer.transform( + new DOMSource(doc), new SAXResult(handler)); + } catch (SAXException e) { + log.error("Failed to set up XML serializer for " + item, e); + } catch (TransformerConfigurationException e) { + log.error("Failed to set up XML transformer for " + item, e); + } catch (ParserConfigurationException e) { + log.error("Failed to set up XML document for " + item, e); + } catch (TransformerException e) { + log.error("Failed to serialize the values of " + item, e); + } + } + + private void spoolSingleValued(OutputStream out) throws IOException { + try { + Binary binary = ((Property) item).getBinary(); + try { + InputStream in = binary.getStream(); + try { + IOUtil.spool(in, out); + } finally { + in.close(); + } + } finally { + binary.dispose(); + } + } catch (RepositoryException e) { + log.error("Cannot obtain stream from " + item, e); + } + } + + @Override + public DavProperty getProperty(DavPropertyName name) { + DavProperty prop = super.getProperty(name); + + if (prop == null && exists()) { + try { + Property p = (Property) item; + if (isMultiple()) { + if (JCR_LENGTHS.equals(name)) { + prop = new LengthsProperty(p.getLengths()); + } + } else { + if (JCR_LENGTH.equals(name)) { + long length = p.getLength(); + prop = new DefaultDavProperty(JCR_LENGTH, String.valueOf(length), true); + } else if (JCR_GET_STRING.equals(name) && p.getType() != PropertyType.BINARY) { + // getstring property is only created for single value + // non-binary jcr properties + prop = new DefaultDavProperty(JCR_GET_STRING, p.getString(), true); + } + } + } catch (RepositoryException e) { + log.error("Failed to retrieve resource properties: "+e.getMessage()); + } + } + + return prop; + } + + /** + * Sets the given property. Note, that {@link #JCR_VALUE} and {@link #JCR_VALUES} + * are the only resource properties that are allowed to be modified. Any other + * property is read-only and will throw an exception ('Conflict'). + * + * @param property + * @throws DavException + * @see DavResource#setProperty(org.apache.jackrabbit.webdav.property.DavProperty) + */ + @Override + public void setProperty(DavProperty property) throws DavException { + internalSetProperty(property); + complete(); + } + + /** + * Internal method that performs the setting or adding of properties + * + * @param property + * @throws DavException + * @see #setProperty(DavProperty) + * @see #alterProperties(List) + */ + private void internalSetProperty(DavProperty property) throws DavException { + if (!exists()) { + throw new DavException(DavServletResponse.SC_NOT_FOUND); + } + try { + Property prop = (Property) item; + int defaultType = prop.getType(); + ValueFactory vfact = getRepositorySession().getValueFactory(); + ValuesProperty vp = new ValuesProperty(property, defaultType, vfact); + if (property.getName().equals(JCR_VALUE)) { + prop.setValue(vp.getJcrValue(vp.getValueType(), vfact)); + } else if (property.getName().equals(JCR_VALUES)) { + prop.setValue(vp.getJcrValues()); + } else { + throw new DavException(DavServletResponse.SC_CONFLICT); + } + } catch (RepositoryException e) { + throw new JcrDavException(e); + } + } + + /** + * Removing properties is not allowed, for a single-value JCR-property without + * a value does not exist. For multivalue properties an empty {@link Value values array} + * may be specified with by setting the {@link #JCR_VALUES 'values' webdav property}. + * + * @param propertyName + * @throws DavException + * @see org.apache.jackrabbit.webdav.DavResource#removeProperty(org.apache.jackrabbit.webdav.property.DavPropertyName) + */ + @Override + public void removeProperty(DavPropertyName propertyName) throws DavException { + if (!exists()) { + throw new DavException(DavServletResponse.SC_NOT_FOUND); + } + throw new DavException(DavServletResponse.SC_FORBIDDEN); + } + + /** + * Loops over the given List and alters the properties accordingly. + * Changes are persisted at the end only according to the rules defined with + * the {@link #complete()} method.

+ * Please note: since there is only a single property than can be set + * from a client (i.e. jcr:value OR jcr:values) this method either succeeds + * or throws an exception, even if this violates RFC 2518. + * + * @param changeList + * @throws DavException + * @see DavResource#alterProperties(List) + */ + @Override + public MultiStatusResponse alterProperties(List changeList) throws DavException { + for (PropEntry propEntry : changeList) { + if (propEntry instanceof DavPropertyName) { + // altering any properties fails if an attempt is made to remove + // a property + throw new DavException(DavServletResponse.SC_FORBIDDEN); + } else if (propEntry instanceof DavProperty) { + DavProperty prop = (DavProperty) propEntry; + internalSetProperty(prop); + } else { + throw new IllegalArgumentException("unknown object in change list: " + propEntry.getClass().getName()); + } + } + complete(); + return new MultiStatusResponse(getHref(), DavServletResponse.SC_OK); + } + + /** + * Method is not allowed. + * + * @see org.apache.jackrabbit.webdav.DavResource#addMember(org.apache.jackrabbit.webdav.DavResource, InputContext) + */ + @Override + public void addMember(DavResource resource, InputContext inputContext) throws DavException { + throw new DavException(DavServletResponse.SC_METHOD_NOT_ALLOWED, "Cannot add members to a non-collection resource"); + } + + /** + * Always returns an empty iterator for a non-collection resource might + * not have internal members. + * + * @return an empty iterator + * @see DavResource#getMembers() + */ + @Override + public DavResourceIterator getMembers() { + log.warn("A non-collection resource never has internal members."); + List drl = Collections.emptyList(); + return new DavResourceIteratorImpl(drl); + } + + /** + * Method is not allowed. + * + * @see DavResource#removeMember(DavResource) + */ + @Override + public void removeMember(DavResource member) throws DavException { + throw new DavException(DavServletResponse.SC_METHOD_NOT_ALLOWED, "Cannot remove members from a non-collection resource"); + } + + /** + * {@link javax.jcr.Property JCR properties} are locked if their + * parent node is locked; thus this method will always return the + * {@link ActiveLock lock} object from the collection this resource is + * internal member of. + * + * @param type + * @param scope + * @return lock present on this resource or null if this resource + * has no lock. + * @see DavResource#getLock(Type, Scope) + */ + @Override + public ActiveLock getLock(Type type, Scope scope) { + if (Type.WRITE.equals(type)) { + return getCollection().getLock(type, scope); + } else { + return super.getLock(type, scope); + } + } + + //-------------------------------------------------------------------------- + @Override + protected void initPropertyNames() { + super.initPropertyNames(); + if (exists()) { + DavPropertyNameSet propNames = (isMultiple() ? + JcrDavPropertyNameSet.PROPERTY_MV_SET : + JcrDavPropertyNameSet.PROPERTY_SET); + names.addAll(propNames); + } + } + + /** + * Add resource specific properties. + */ + @Override + protected void initProperties() { + super.initProperties(); + if (exists()) { + try { + Property prop = (Property)item; + int type = prop.getType(); + + // set the content type + String contentType; + if (isMultiple()) { + contentType = IOUtil.buildContentType("text/xml","utf-8"); + } else { + contentType = IOUtil.buildContentType(JcrValueType.contentTypeFromType(type), "utf-8"); + + } + properties.add(new DefaultDavProperty(DavPropertyName.GETCONTENTTYPE, contentType)); + + // add jcr-specific resource properties + properties.add(new DefaultDavProperty(JCR_TYPE, PropertyType.nameFromValue(type))); + if (isMultiple()) { + properties.add(new ValuesProperty(prop.getValues())); + } else { + properties.add(new ValuesProperty(prop.getValue())); + } + } catch (RepositoryException e) { + log.error("Failed to retrieve resource properties: "+e.getMessage()); + } + } + } + + /** + * Returns true if the JCR Property represented by this resource is a multi + * value property. Note: if this resource does not exist or if the definition + * could not be retrieved false is returned. + * + * @return true if the underlying resource is a multi value property. + */ + private boolean isMultiple() { + try { + if (exists() && ((Property)item).isMultiple()) { + return true; + } + } catch (RepositoryException e) { + log.error("Error while retrieving property definition: " + e.getMessage()); + } + return false; + } +} Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/DefaultItemResource.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/webdav/jcr/EventJournalResourceImpl.java =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/EventJournalResourceImpl.java (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/EventJournalResourceImpl.java (working copy) @@ -0,0 +1,483 @@ +/* + * 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.webdav.jcr; + +import java.io.IOException; +import java.io.OutputStream; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Calendar; +import java.util.Collections; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.Set; + +import javax.jcr.RepositoryException; +import javax.jcr.UnsupportedRepositoryOperationException; +import javax.jcr.observation.Event; +import javax.jcr.observation.EventJournal; +import javax.servlet.http.HttpServletRequest; +import javax.xml.transform.OutputKeys; +import javax.xml.transform.Transformer; +import javax.xml.transform.TransformerFactory; +import javax.xml.transform.sax.SAXTransformerFactory; +import javax.xml.transform.sax.TransformerHandler; +import javax.xml.transform.stream.StreamResult; + +import org.apache.jackrabbit.commons.webdav.AtomFeedConstants; +import org.apache.jackrabbit.commons.webdav.EventUtil; +import org.apache.jackrabbit.spi.Name; +import org.apache.jackrabbit.spi.commons.AdditionalEventInfo; +import org.apache.jackrabbit.util.ISO8601; +import org.apache.jackrabbit.webdav.DavConstants; +import org.apache.jackrabbit.webdav.DavException; +import org.apache.jackrabbit.webdav.DavResource; +import org.apache.jackrabbit.webdav.DavResourceFactory; +import org.apache.jackrabbit.webdav.DavResourceIterator; +import org.apache.jackrabbit.webdav.DavResourceIteratorImpl; +import org.apache.jackrabbit.webdav.DavResourceLocator; +import org.apache.jackrabbit.webdav.DavServletResponse; +import org.apache.jackrabbit.webdav.io.InputContext; +import org.apache.jackrabbit.webdav.io.OutputContext; +import org.apache.jackrabbit.webdav.observation.ObservationConstants; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.xml.sax.Attributes; +import org.xml.sax.SAXException; +import org.xml.sax.helpers.AttributesImpl; + +/** + * Implements a JCR {@link EventJournal} in terms of an RFC 4287 Atom feed. + *

+ * Each feed entry represents either a single event, or, if the repository + * supports the {@link Event#PERSIST} event, an event bundle. The actual event + * data is sent in the Atom <content> element and uses the same XML + * serialization as the one used for subscriptions. + *

+ * Skipping is implemented by specifying the desired time offset (represented + * as hexadecimal long in ms since the epoch) disguised as ETag in the HTTP "If-None-Match" + * header field. + *

+ * The generated feed may not be complete; the total number of events is limited in + * order not to overload the client. + *

+ * Furthermore, the number of events is limited by going up to 2000 ms into the future + * (based on the request time). This is supposed to limit the wait time for the client). + */ +public class EventJournalResourceImpl extends AbstractResource { + + public static final String RELURIFROMWORKSPACE = "?type=journal"; + + public static final String EVENTMEDIATYPE = "application/vnd.apache.jackrabbit.event+xml"; + + private static Logger log = LoggerFactory.getLogger(EventJournalResourceImpl.class); + + private final HttpServletRequest request; + private final EventJournal journal; + private final DavResourceLocator locator; + + EventJournalResourceImpl(EventJournal journal, DavResourceLocator locator, JcrDavSession session, + HttpServletRequest request, DavResourceFactory factory) { + super(locator, session, factory); + this.journal = journal; + this.locator = locator; + this.request = request; + } + + @Override + public String getSupportedMethods() { + return "GET, HEAD"; + } + + @Override + public boolean exists() { + try { + List available = Arrays.asList(getRepositorySession().getWorkspace().getAccessibleWorkspaceNames()); + return available.contains(getLocator().getWorkspaceName()); + } catch (RepositoryException e) { + log.warn(e.getMessage()); + return false; + } + } + + @Override + public boolean isCollection() { + return false; + } + + @Override + public String getDisplayName() { + return "event journal for " + getLocator().getWorkspaceName(); + } + + @Override + public long getModificationTime() { + return System.currentTimeMillis(); + } + + private static final String ATOMNS = AtomFeedConstants.NS_URI; + private static final String EVNS = ObservationConstants.NAMESPACE.getURI(); + + private static final String AUTHOR = AtomFeedConstants.XML_AUTHOR; + private static final String CONTENT = AtomFeedConstants.XML_CONTENT; + private static final String ENTRY = AtomFeedConstants.XML_ENTRY; + private static final String FEED = AtomFeedConstants.XML_FEED; + private static final String ID = AtomFeedConstants.XML_ID; + private static final String LINK = AtomFeedConstants.XML_LINK; + private static final String NAME = AtomFeedConstants.XML_NAME; + private static final String TITLE = AtomFeedConstants.XML_TITLE; + private static final String UPDATED = AtomFeedConstants.XML_UPDATED; + + private static final String E_EVENT = ObservationConstants.XML_EVENT; + private static final String E_EVENTDATE = ObservationConstants.XML_EVENTDATE; + private static final String E_EVENTIDENTIFIER = ObservationConstants.XML_EVENTIDENTIFIER; + private static final String E_EVENTINFO = ObservationConstants.XML_EVENTINFO; + private static final String E_EVENTTYPE = ObservationConstants.XML_EVENTTYPE; + private static final String E_EVENTMIXINNODETYPE = ObservationConstants.XML_EVENTMIXINNODETYPE; + private static final String E_EVENTPRIMARNODETYPE = ObservationConstants.XML_EVENTPRIMARNODETYPE; + private static final String E_EVENTUSERDATA = ObservationConstants.XML_EVENTUSERDATA; + + private static final int MAXWAIT = 2000; // maximal wait time + private static final int MAXEV = 10000; // maximal event number + + private static final Attributes NOATTRS = new AttributesImpl(); + + @Override + public void spool(OutputContext outputContext) throws IOException { + + Calendar cal = Calendar.getInstance(Locale.ENGLISH); + + try { + outputContext.setContentType("application/atom+xml; charset=UTF-8"); + outputContext.setProperty("Vary", "If-None-Match"); + // TODO: Content-Encoding: gzip + + // find out where to start + long prevts = -1; + String inm = request.getHeader("If-None-Match"); + if (inm != null) { + // TODO: proper parsing when comma-delimited + inm = inm.trim(); + if (inm.startsWith("\"") && inm.endsWith("\"")) { + String tmp = inm.substring(1, inm.length() - 1); + try { + prevts = Long.parseLong(tmp, 16); + journal.skipTo(prevts); + } catch (NumberFormatException ex) { + // broken etag + } + } + } + + boolean hasPersistEvents = false; + + if (outputContext.hasStream()) { + + long lastts = -1; + long now = System.currentTimeMillis(); + boolean done = false; + + // collect events + List events = new ArrayList(MAXEV); + + while (!done && journal.hasNext()) { + Event e = journal.nextEvent(); + + hasPersistEvents |= e.getType() == Event.PERSIST; + + if (e.getDate() != lastts) { + // consider stopping + if (events.size() > MAXEV) { + done = true; + } + if (e.getDate() > now + MAXWAIT) { + done = true; + } + } + + if (!done && (prevts == -1 || e.getDate() >= prevts)) { + events.add(e); + } + + lastts = e.getDate(); + } + + if (lastts >= 0) { + // construct ETag from newest event + outputContext.setETag("\"" + Long.toHexString(lastts) + "\""); + } + + OutputStream os = outputContext.getOutputStream(); + StreamResult streamResult = new StreamResult(os); + SAXTransformerFactory tf = (SAXTransformerFactory) TransformerFactory.newInstance(); + TransformerHandler th = tf.newTransformerHandler(); + Transformer s = th.getTransformer(); + s.setOutputProperty(OutputKeys.ENCODING, "UTF-8"); + s.setOutputProperty(OutputKeys.INDENT, "yes"); + s.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes"); + + th.setResult(streamResult); + + th.startDocument(); + + th.startElement(ATOMNS, FEED, FEED, NOATTRS); + + writeAtomElement(th, TITLE, "EventJournal for " + getLocator().getWorkspaceName()); + + th.startElement(ATOMNS, AUTHOR, AUTHOR, NOATTRS); + writeAtomElement(th, NAME, "Jackrabbit Event Journal Feed Generator"); + th.endElement(ATOMNS, AUTHOR, AUTHOR); + + String id = getFullUri(request); + writeAtomElement(th, ID, id); + + AttributesImpl linkattrs = new AttributesImpl(); + linkattrs.addAttribute(null, "self", "self", "CDATA", id); + writeAtomElement(th, LINK, linkattrs, null); + + cal.setTimeInMillis(lastts >= 0 ? lastts : now); + String upd = ISO8601.format(cal); + writeAtomElement(th, UPDATED, upd); + + String lastDateString = ""; + long lastTimeStamp = 0; + long index = 0; + + AttributesImpl contentatt = new AttributesImpl(); + contentatt.addAttribute(null, "type", "type", "CDATA", EVENTMEDIATYPE); + + while (!events.isEmpty()) { + + List bundle = null; + String path = null; + String op; + + if (hasPersistEvents) { + bundle = new ArrayList(); + Event e = null; + op = "operations"; + + do { + e = events.remove(0); + bundle.add(e); + + // compute common path + if (path == null) { + path = e.getPath(); + } else { + if (e.getPath() != null && e.getPath().length() < path.length()) { + path = e.getPath(); + } + } + } while (e.getType() != Event.PERSIST && !events.isEmpty()); + } else { + // no persist events + Event e = events.remove(0); + bundle = Collections.singletonList(e); + path = e.getPath(); + op = EventUtil.getEventName(e.getType()); + } + + Event firstEvent = bundle.get(0); + + String entryupd = lastDateString; + if (lastTimeStamp != firstEvent.getDate()) { + cal.setTimeInMillis(firstEvent.getDate()); + entryupd = ISO8601.format(cal); + index = 0; + } else { + index += 1; + } + + th.startElement(ATOMNS, ENTRY, ENTRY, NOATTRS); + + String entrytitle = op + (path != null ? (": " + path) : ""); + writeAtomElement(th, TITLE, entrytitle); + + String entryid = id + "?type=journal&ts=" + Long.toHexString(firstEvent.getDate()) + "-" + index; + writeAtomElement(th, ID, entryid); + + String author = firstEvent.getUserID() == null || firstEvent.getUserID().length() == 0 ? null + : firstEvent.getUserID(); + if (author != null) { + th.startElement(ATOMNS, AUTHOR, AUTHOR, NOATTRS); + writeAtomElement(th, NAME, author); + th.endElement(ATOMNS, AUTHOR, AUTHOR); + } + + writeAtomElement(th, UPDATED, entryupd); + + th.startElement(ATOMNS, CONTENT, CONTENT, contentatt); + + for (Event e : bundle) { + + // serialize the event + th.startElement(EVNS, E_EVENT, E_EVENT, NOATTRS); + + // DAV:href + if (e.getPath() != null) { + boolean isCollection = (e.getType() == Event.NODE_ADDED || e.getType() == Event.NODE_REMOVED); + String href = locator + .getFactory() + .createResourceLocator(locator.getPrefix(), locator.getWorkspacePath(), + e.getPath(), false).getHref(isCollection); + th.startElement(DavConstants.NAMESPACE.getURI(), DavConstants.XML_HREF, + DavConstants.XML_HREF, NOATTRS); + th.characters(href.toCharArray(), 0, href.length()); + th.endElement(DavConstants.NAMESPACE.getURI(), DavConstants.XML_HREF, DavConstants.XML_HREF); + } + + // event type + String evname = EventUtil.getEventName(e.getType()); + th.startElement(EVNS, E_EVENTTYPE, E_EVENTTYPE, NOATTRS); + th.startElement(EVNS, evname, evname, NOATTRS); + th.endElement(EVNS, evname, evname); + th.endElement(EVNS, E_EVENTTYPE, E_EVENTTYPE); + + // date + writeObsElement(th, E_EVENTDATE, Long.toString(e.getDate())); + + // user data + if (e.getUserData() != null && e.getUserData().length() > 0) { + writeObsElement(th, E_EVENTUSERDATA, firstEvent.getUserData()); + } + + // user id: already sent as Atom author/name + + // try to compute nodetype information + if (e instanceof AdditionalEventInfo) { + try { + Name pnt = ((AdditionalEventInfo) e).getPrimaryNodeTypeName(); + if (pnt != null) { + writeObsElement(th, E_EVENTPRIMARNODETYPE, pnt.toString()); + } + + Set mixins = ((AdditionalEventInfo) e).getMixinTypeNames(); + if (mixins != null) { + for (Name mixin : mixins) { + writeObsElement(th, E_EVENTMIXINNODETYPE, mixin.toString()); + } + } + + } catch (UnsupportedRepositoryOperationException ex) { + // optional + } + } + + // identifier + if (e.getIdentifier() != null) { + writeObsElement(th, E_EVENTIDENTIFIER, e.getIdentifier()); + } + + // info + if (!e.getInfo().isEmpty()) { + th.startElement(EVNS, E_EVENTINFO, E_EVENTINFO, NOATTRS); + Map m = e.getInfo(); + for (Map.Entry entry : m.entrySet()) { + String key = entry.getKey().toString(); + Object value = entry.getValue(); + String t = value != null ? value.toString() : null; + writeElement(th, null, key, NOATTRS, t); + } + th.endElement(EVNS, E_EVENTINFO, E_EVENTINFO); + } + + th.endElement(EVNS, E_EVENT, E_EVENT); + + lastTimeStamp = e.getDate(); + lastDateString = entryupd; + } + + th.endElement(ATOMNS, CONTENT, CONTENT); + th.endElement(ATOMNS, ENTRY, ENTRY); + } + + th.endElement(ATOMNS, FEED, FEED); + + th.endDocument(); + + os.flush(); + } + } catch (Exception ex) { + throw new IOException("error generating feed: " + ex.getMessage()); + } + } + + @Override + public DavResource getCollection() { + return null; + } + + @Override + public void addMember(DavResource resource, InputContext inputContext) throws DavException { + throw new DavException(DavServletResponse.SC_FORBIDDEN); + } + + @Override + public DavResourceIterator getMembers() { + return DavResourceIteratorImpl.EMPTY; + } + + @Override + public void removeMember(DavResource member) throws DavException { + throw new DavException(DavServletResponse.SC_FORBIDDEN); + } + + @Override + protected void initLockSupport() { + // lock not allowed + } + + @Override + protected String getWorkspaceHref() { + return getHref(); + } + + private void writeElement(TransformerHandler th, String ns, String name, Attributes attrs, String textContent) + throws SAXException { + th.startElement(ns, name, name, attrs); + if (textContent != null) { + th.characters(textContent.toCharArray(), 0, textContent.length()); + } + th.endElement(ns, name, name); + } + + private void writeAtomElement(TransformerHandler th, String name, Attributes attrs, String textContent) + throws SAXException { + writeElement(th, ATOMNS, name, attrs, textContent); + } + + private void writeAtomElement(TransformerHandler th, String name, String textContent) throws SAXException { + writeAtomElement(th, name, NOATTRS, textContent); + } + + private void writeObsElement(TransformerHandler th, String name, String textContent) throws SAXException { + writeElement(th, EVNS, name, NOATTRS, textContent); + } + + private String getFullUri(HttpServletRequest req) { + + String scheme = req.getScheme(); + int port = req.getServerPort(); + boolean isDefaultPort = (scheme.equals("http") && port == 80) || (scheme.equals("http") && port == 443); + String query = request.getQueryString() != null ? "?" + request.getQueryString() : ""; + + return String.format("%s://%s%s%s%s%s", scheme, req.getServerName(), isDefaultPort ? ":" : "", + isDefaultPort ? Integer.toString(port) : "", req.getRequestURI(), query); + } +} Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/EventJournalResourceImpl.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/webdav/jcr/ItemResourceConstants.java =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/ItemResourceConstants.java (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/ItemResourceConstants.java (working copy) @@ -0,0 +1,125 @@ +/* + * 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.webdav.jcr; + +import javax.jcr.Session; + +import org.apache.jackrabbit.commons.webdav.JcrRemotingConstants; +import org.apache.jackrabbit.webdav.DavResource; +import org.apache.jackrabbit.webdav.lock.Scope; +import org.apache.jackrabbit.webdav.observation.ObservationResource; +import org.apache.jackrabbit.webdav.property.DavPropertyName; +import org.apache.jackrabbit.webdav.search.SearchResource; +import org.apache.jackrabbit.webdav.security.Privilege; +import org.apache.jackrabbit.webdav.version.DeltaVResource; +import org.apache.jackrabbit.webdav.xml.Namespace; + +/** + * ItemResourceConstants provides constants for any resources + * representing repository items. + */ +public interface ItemResourceConstants extends JcrRemotingConstants { + + /** + * Methods common to all item resources. + */ + public static final String METHODS = DavResource.METHODS + ", " + ObservationResource.METHODS + ", " + SearchResource.METHODS + ", " +DeltaVResource.METHODS; + + /** + * The namespace for all jcr specific extensions. + */ + public static final Namespace NAMESPACE = Namespace.getNamespace(NS_PREFIX, NS_URI); + + /** + * Extension to the WebDAV 'exclusive' lock, that allows to distinguish + * the session-scoped and open-scoped locks on a JCR node. + * + * @see javax.jcr.Node#lock(boolean, boolean) + */ + public static final Scope EXCLUSIVE_SESSION = Scope.create(XML_EXCLUSIVE_SESSION_SCOPED, NAMESPACE); + + // name of the workspace for which the repository session has been created. + public static final DavPropertyName JCR_WORKSPACE_NAME = DavPropertyName.create(JCR_WORKSPACE_NAME_LN, NAMESPACE); + + // general property names + public static final DavPropertyName JCR_NAME = DavPropertyName.create(JCR_NAME_LN, NAMESPACE); + public static final DavPropertyName JCR_PATH = DavPropertyName.create(JCR_PATH_LN, NAMESPACE); + public static final DavPropertyName JCR_DEPTH = DavPropertyName.create(JCR_DEPTH_LN, NAMESPACE); + public static final DavPropertyName JCR_PARENT = DavPropertyName.create(JCR_PARENT_LN, NAMESPACE); + public static final DavPropertyName JCR_ISNEW = DavPropertyName.create(JCR_ISNEW_LN, NAMESPACE); + public static final DavPropertyName JCR_ISMODIFIED = DavPropertyName.create(JCR_ISMODIFIED_LN, NAMESPACE); + public static final DavPropertyName JCR_DEFINITION = DavPropertyName.create(JCR_DEFINITION_LN, NAMESPACE); + public static final DavPropertyName JCR_SELECTOR_NAME = DavPropertyName.create(JCR_SELECTOR_NAME_LN, NAMESPACE); + + // property names used for resources representing jcr-nodes + public static final DavPropertyName JCR_PRIMARYNODETYPE = DavPropertyName.create(JCR_PRIMARYNODETYPE_LN, NAMESPACE); + public static final DavPropertyName JCR_MIXINNODETYPES = DavPropertyName.create(JCR_MIXINNODETYPES_LN, NAMESPACE); + public static final DavPropertyName JCR_INDEX = DavPropertyName.create(JCR_INDEX_LN, NAMESPACE); + public static final DavPropertyName JCR_REFERENCES = DavPropertyName.create(JCR_REFERENCES_LN, NAMESPACE); + /** + * @since JCR 2.0 + */ + public static final DavPropertyName JCR_WEAK_REFERENCES = DavPropertyName.create(JCR_WEAK_REFERENCES_LN, NAMESPACE); + public static final DavPropertyName JCR_UUID = DavPropertyName.create(JCR_UUID_LN, NAMESPACE); + public static final DavPropertyName JCR_PRIMARYITEM = DavPropertyName.create(JCR_PRIMARYITEM_LN, NAMESPACE); + + // property names used for resources representing jcr-properties + public static final DavPropertyName JCR_TYPE = DavPropertyName.create(JCR_TYPE_LN, NAMESPACE); + public static final DavPropertyName JCR_VALUE = DavPropertyName.create(JCR_VALUE_LN, NAMESPACE); + public static final DavPropertyName JCR_VALUES = DavPropertyName.create(JCR_VALUES_LN, NAMESPACE); + public static final DavPropertyName JCR_LENGTH = DavPropertyName.create(JCR_LENGTH_LN, NAMESPACE); + public static final DavPropertyName JCR_LENGTHS = DavPropertyName.create(JCR_LENGTHS_LN, NAMESPACE); + public static final DavPropertyName JCR_GET_STRING = DavPropertyName.create(JCR_GET_STRING_LN, NAMESPACE); + + // property names used for resource representing a workspace + public static final DavPropertyName JCR_NAMESPACES = DavPropertyName.create(JCR_NAMESPACES_LN, NAMESPACE); + public static final DavPropertyName JCR_NODETYPES_CND = DavPropertyName.create(JCR_NODETYPES_CND_LN, NAMESPACE); + + // property names used for resource representing a version history + public static final DavPropertyName JCR_VERSIONABLEUUID = DavPropertyName.create(JCR_VERSIONABLEUUID_LN, NAMESPACE); + + //-----------------------------------------< JSR170 specific privileges >--- + /** + * Privilege representing the JSR170 'read' action. + *

Note: the name of this constant is somewhat misleading + * as it corresponds to {@link javax.jcr.Session#ACTION_READ} and not + * to {@link javax.jcr.security.Privilege#JCR_READ}.

+ */ + public static final Privilege PRIVILEGE_JCR_READ = Privilege.getPrivilege(Session.ACTION_READ, NAMESPACE); + /** + * Privilege representing the JSR170 'add_node' action. + *

Note: the name of this constant is somewhat misleading + * as it corresponds to {@link javax.jcr.Session#ACTION_ADD_NODE} and not + * to {@link javax.jcr.security.Privilege#JCR_ADD_CHILD_NODES}.

+ */ + public static final Privilege PRIVILEGE_JCR_ADD_NODE = Privilege.getPrivilege(Session.ACTION_ADD_NODE, NAMESPACE); + /** + * Privilege representing the JSR170 'set_property' action. + *

Note: the name of this constant is somewhat misleading + * as it corresponds to {@link javax.jcr.Session#ACTION_SET_PROPERTY} and not + * to {@link javax.jcr.security.Privilege#JCR_MODIFY_PROPERTIES}.

+ */ + public static final Privilege PRIVILEGE_JCR_SET_PROPERTY = Privilege.getPrivilege(Session.ACTION_SET_PROPERTY, NAMESPACE); + /** + * Privilege representing the JSR170 'remove' action. + *

Note: the name of this constant is somewhat misleading + * as it corresponds to {@link javax.jcr.Session#ACTION_REMOVE} and not + * to {@link javax.jcr.security.Privilege#JCR_REMOVE_NODE} or + * {@link javax.jcr.security.Privilege#JCR_REMOVE_CHILD_NODES}.

+ */ + public static final Privilege PRIVILEGE_JCR_REMOVE = Privilege.getPrivilege(Session.ACTION_REMOVE, NAMESPACE); +} Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/ItemResourceConstants.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/webdav/jcr/JCRWebdavServerServlet.java =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/JCRWebdavServerServlet.java (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/JCRWebdavServerServlet.java (working copy) @@ -0,0 +1,321 @@ +/* + * 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.webdav.jcr; + +import org.apache.jackrabbit.server.BasicCredentialsProvider; +import org.apache.jackrabbit.server.CredentialsProvider; +import org.apache.jackrabbit.server.SessionProvider; +import org.apache.jackrabbit.server.SessionProviderImpl; +import org.apache.jackrabbit.server.jcr.JCRWebdavServer; +import org.apache.jackrabbit.webdav.DavException; +import org.apache.jackrabbit.webdav.DavLocatorFactory; +import org.apache.jackrabbit.webdav.DavMethods; +import org.apache.jackrabbit.webdav.DavResource; +import org.apache.jackrabbit.webdav.DavResourceFactory; +import org.apache.jackrabbit.webdav.DavServletResponse; +import org.apache.jackrabbit.webdav.DavSessionProvider; +import org.apache.jackrabbit.webdav.WebdavRequest; +import org.apache.jackrabbit.webdav.jcr.observation.SubscriptionManagerImpl; +import org.apache.jackrabbit.webdav.jcr.transaction.TxLockManagerImpl; +import org.apache.jackrabbit.webdav.observation.SubscriptionManager; +import org.apache.jackrabbit.webdav.server.AbstractWebdavServlet; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.jcr.Repository; +import javax.jcr.Session; +import javax.servlet.ServletContext; +import javax.servlet.ServletException; + +/** + * JCRWebdavServerServlet provides request/response handling for the + * JCRWebdavServer. + *

+ * Implementations of this abstract class must implement the + * {@link #getRepository()} method to access the repository. + */ +public abstract class JCRWebdavServerServlet extends AbstractWebdavServlet { + + /** + * the default logger + */ + private static Logger log = LoggerFactory.getLogger(JCRWebdavServerServlet.class); + + /** + * Init parameter specifying the prefix used with the resource path. + */ + public static final String INIT_PARAM_RESOURCE_PATH_PREFIX = "resource-path-prefix"; + + /** + * Optional 'concurrency-level' parameter defining the concurrency level + * within the jcr-server. If the parameter is omitted the internal default + * value (50) is used. + */ + public final static String INIT_PARAM_CONCURRENCY_LEVEL = "concurrency-level"; + + /** + * Servlet context attribute used to store the path prefix instead of + * having a static field with this servlet. The latter causes problems + * when running multiple + */ + public static final String CTX_ATTR_RESOURCE_PATH_PREFIX = "jackrabbit.webdav.jcr.resourcepath"; + + private String pathPrefix; + + private JCRWebdavServer server; + private DavResourceFactory resourceFactory; + private DavLocatorFactory locatorFactory; + protected TxLockManagerImpl txMgr; + protected SubscriptionManager subscriptionMgr; + + /** + * Initializes the servlet set reads the following parameter from the + * servlet configuration: + *

    + *
  • resource-path-prefix: optional prefix for all resources.
  • + *
+ * + * @throws ServletException + */ + @Override + public void init() throws ServletException { + super.init(); + + // set resource path prefix + pathPrefix = getInitParameter(INIT_PARAM_RESOURCE_PATH_PREFIX); + getServletContext().setAttribute(CTX_ATTR_RESOURCE_PATH_PREFIX, pathPrefix); + log.debug(INIT_PARAM_RESOURCE_PATH_PREFIX + " = " + pathPrefix); + + txMgr = new TxLockManagerImpl(); + subscriptionMgr = new SubscriptionManagerImpl(); + txMgr.addTransactionListener((SubscriptionManagerImpl) subscriptionMgr); + + // todo: eventually make configurable + resourceFactory = new DavResourceFactoryImpl(txMgr, subscriptionMgr); + locatorFactory = new DavLocatorFactoryImpl(pathPrefix); + } + + /** + * Returns true if the preconditions are met. This includes validation of + * {@link WebdavRequest#matchesIfHeader(DavResource) If header} and validation + * of {@link org.apache.jackrabbit.webdav.transaction.TransactionConstants#HEADER_TRANSACTIONID + * TransactionId header}. This method will also return false if the requested + * resource resides within a different workspace as is assigned to the repository + * session attached to the given request. + * + * @see AbstractWebdavServlet#isPreconditionValid(WebdavRequest, DavResource) + */ + @Override + protected boolean isPreconditionValid(WebdavRequest request, DavResource resource) { + // first check matching If header + if (!request.matchesIfHeader(resource)) { + return false; + } + + // test if the requested path matches to the existing session + // this may occur if the session was retrieved from the cache. + try { + Session repositorySesssion = JcrDavSession.getRepositorySession(request.getDavSession()); + String reqWspName = resource.getLocator().getWorkspaceName(); + String wsName = repositorySesssion.getWorkspace().getName(); + // compare workspace names if the requested resource isn't the + // root-collection and the request not MKWORKSPACE. + if (DavMethods.DAV_MKWORKSPACE != DavMethods.getMethodCode(request.getMethod()) && + reqWspName != null && !reqWspName.equals(wsName)) { + return false; + } + } catch (DavException e) { + log.error("Internal error: " + e.toString()); + return false; + } + + + // make sure, the TransactionId header is valid + String txId = request.getTransactionId(); + return txId == null || txMgr.hasLock(txId, resource); + } + + /** + * Returns the DavSessionProvider + * + * @return server + * @see AbstractWebdavServlet#getDavSessionProvider() + */ + @Override + public DavSessionProvider getDavSessionProvider() { + if (server == null) { + Repository repository = getRepository(); + String cl = getInitParameter(INIT_PARAM_CONCURRENCY_LEVEL); + if (cl != null) { + try { + server = new JCRWebdavServer(repository, getSessionProvider(), Integer.parseInt(cl)); + } catch (NumberFormatException e) { + log.debug("Invalid value '" + cl+ "' for init-param 'concurrency-level'. Using default instead."); + server = new JCRWebdavServer(repository, getSessionProvider()); + } + } else { + server = new JCRWebdavServer(repository, getSessionProvider()); + } + } + return server; + } + + /** + * Throws UnsupportedOperationException. + * + * @see AbstractWebdavServlet#setDavSessionProvider(DavSessionProvider) + */ + @Override + public void setDavSessionProvider(DavSessionProvider davSessionProvider) { + throw new UnsupportedOperationException("Not implemented. DavSession(s) are provided by the 'JCRWebdavServer'"); + } + + /** + * Returns the DavLocatorFactory + * + * @see AbstractWebdavServlet#getLocatorFactory() + */ + @Override + public DavLocatorFactory getLocatorFactory() { + if (locatorFactory == null) { + locatorFactory = new DavLocatorFactoryImpl(pathPrefix); + } + return locatorFactory; + } + + /** + * Sets the DavLocatorFactory + * + * @see AbstractWebdavServlet#setLocatorFactory(DavLocatorFactory) + */ + @Override + public void setLocatorFactory(DavLocatorFactory locatorFactory) { + this.locatorFactory = locatorFactory; + } + + /** + * Returns the DavResourceFactory. + * + * @see AbstractWebdavServlet#getResourceFactory() + */ + @Override + public DavResourceFactory getResourceFactory() { + if (resourceFactory == null) { + resourceFactory = new DavResourceFactoryImpl(txMgr, subscriptionMgr); + } + return resourceFactory; + } + + /** + * Sets the DavResourceFactory. + * + * @see AbstractWebdavServlet#setResourceFactory(org.apache.jackrabbit.webdav.DavResourceFactory) + */ + @Override + public void setResourceFactory(DavResourceFactory resourceFactory) { + this.resourceFactory = resourceFactory; + } + + /** + * Modified variant needed for JCR move and copy that isn't compliant to + * WebDAV. The latter requires both methods to fail if the destination already + * exists and Overwrite is set to F (false); in JCR however this depends on + * the node type characteristics of the parent (SNSiblings allowed or not). + * + * @param destResource destination resource to be validated. + * @param request The webdav request + * @param checkHeader flag indicating if the destination header must be present. + * @return status code indicating whether the destination is valid. + */ + @Override + protected int validateDestination(DavResource destResource, WebdavRequest request, boolean checkHeader) + throws DavException { + + if (checkHeader) { + String destHeader = request.getHeader(HEADER_DESTINATION); + if (destHeader == null || "".equals(destHeader)) { + return DavServletResponse.SC_BAD_REQUEST; + } + } + if (destResource.getLocator().equals(request.getRequestLocator())) { + return DavServletResponse.SC_FORBIDDEN; + } + + int status; + if (destResource.exists()) { + if (request.isOverwrite()) { + // matching if-header required for existing resources + if (!request.matchesIfHeader(destResource)) { + return DavServletResponse.SC_PRECONDITION_FAILED; + } else { + // overwrite existing resource + destResource.getCollection().removeMember(destResource); + status = DavServletResponse.SC_NO_CONTENT; + } + } else { + /* NO overwrite header: + + but, instead of return the 412 Precondition-Failed code required + by the WebDAV specification(s) leave the validation to the + JCR repository. + */ + status = DavServletResponse.SC_CREATED; + } + + } else { + // destination does not exist >> copy/move can be performed + status = DavServletResponse.SC_CREATED; + } + return status; + } + + /** + * Returns the configured path prefix + * + * @param ctx The servlet context. + * @return resourcePathPrefix + * @see #INIT_PARAM_RESOURCE_PATH_PREFIX + */ + public static String getPathPrefix(ServletContext ctx) { + return (String) ctx.getAttribute(CTX_ATTR_RESOURCE_PATH_PREFIX); + } + + /** + * Returns the repository to be used by this servlet. + * + * @return the JCR repository to be used by this servlet + */ + protected abstract Repository getRepository(); + + /** + * Returns a new instanceof BasicCredentialsProvider. + * + * @return a new credentials provider + */ + protected CredentialsProvider getCredentialsProvider() { + return new BasicCredentialsProvider(getInitParameter(INIT_PARAM_MISSING_AUTH_MAPPING)); + } + + /** + * Returns a new instanceof SessionProviderImpl. + * + * @return a new session provider + */ + protected SessionProvider getSessionProvider() { + return new SessionProviderImpl(getCredentialsProvider()); + } +} Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/JCRWebdavServerServlet.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/webdav/jcr/JcrDavException.java =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/JcrDavException.java (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/JcrDavException.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.webdav.jcr; + +import org.apache.jackrabbit.webdav.DavConstants; +import org.apache.jackrabbit.webdav.DavException; +import org.apache.jackrabbit.webdav.DavServletResponse; +import org.apache.jackrabbit.webdav.xml.DomUtil; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +import javax.jcr.AccessDeniedException; +import javax.jcr.InvalidItemStateException; +import javax.jcr.InvalidSerializedDataException; +import javax.jcr.ItemExistsException; +import javax.jcr.ItemNotFoundException; +import javax.jcr.LoginException; +import javax.jcr.MergeException; +import javax.jcr.NamespaceException; +import javax.jcr.NoSuchWorkspaceException; +import javax.jcr.PathNotFoundException; +import javax.jcr.ReferentialIntegrityException; +import javax.jcr.RepositoryException; +import javax.jcr.UnsupportedRepositoryOperationException; +import javax.jcr.ValueFormatException; +import javax.jcr.lock.LockException; +import javax.jcr.nodetype.ConstraintViolationException; +import javax.jcr.nodetype.NoSuchNodeTypeException; +import javax.jcr.query.InvalidQueryException; +import javax.jcr.version.VersionException; +import java.util.Map; +import java.util.LinkedHashMap; + + +/** + * JcrDavException extends the {@link DavException} in order to + * wrap various repository exceptions. + */ +public class JcrDavException extends DavException { + + private static Logger log = LoggerFactory.getLogger(JcrDavException.class); + + // ordered mapping of Jcr exceptions to error codes. + private static Map, Integer> codeMap = new LinkedHashMap, Integer>(20); + static { + codeMap.put(AccessDeniedException.class, DavServletResponse.SC_FORBIDDEN); + codeMap.put(ConstraintViolationException.class, DavServletResponse.SC_CONFLICT); + codeMap.put(InvalidItemStateException.class, DavServletResponse.SC_CONFLICT); + codeMap.put(InvalidSerializedDataException.class, DavServletResponse.SC_BAD_REQUEST); + codeMap.put(InvalidQueryException.class, DavServletResponse.SC_BAD_REQUEST); + codeMap.put(ItemExistsException.class, DavServletResponse.SC_CONFLICT); + codeMap.put(ItemNotFoundException.class, DavServletResponse.SC_FORBIDDEN); + codeMap.put(LockException.class, DavServletResponse.SC_LOCKED); + codeMap.put(MergeException.class, DavServletResponse.SC_CONFLICT); + codeMap.put(NamespaceException.class, DavServletResponse.SC_CONFLICT); + codeMap.put(NoSuchNodeTypeException.class, DavServletResponse.SC_CONFLICT); + codeMap.put(NoSuchWorkspaceException.class, DavServletResponse.SC_CONFLICT); + codeMap.put(PathNotFoundException.class, DavServletResponse.SC_CONFLICT); + codeMap.put(ReferentialIntegrityException.class, DavServletResponse.SC_CONFLICT); + codeMap.put(LoginException.class, DavServletResponse.SC_UNAUTHORIZED); + codeMap.put(UnsupportedRepositoryOperationException.class, DavServletResponse.SC_NOT_IMPLEMENTED); + codeMap.put(ValueFormatException.class, DavServletResponse.SC_CONFLICT); + codeMap.put(VersionException.class, DavServletResponse.SC_CONFLICT); + codeMap.put(RepositoryException.class, DavServletResponse.SC_FORBIDDEN); + } + + private static int lookupErrorCode(Class exceptionClass) { + Integer code = codeMap.get(exceptionClass); + if (code == null) { + for (Class jcrExceptionClass : codeMap.keySet()) { + if (jcrExceptionClass.isAssignableFrom(exceptionClass)) { + code = codeMap.get(jcrExceptionClass); + break; + } + } + if (code == null) { + code = DavServletResponse.SC_FORBIDDEN; // fallback + } + } + return code; + } + + /** + * The exception wrapped by this DavException instance. + */ + private Class exceptionClass; + + /** + * Create a new JcrDavException. + * + * @param cause The original cause of this DavException. Note, that + * in contrast to {@link Throwable#Throwable(Throwable)}, {@link Throwable#Throwable(String, Throwable)} and + * {@link Throwable#initCause(Throwable)} the cause must not be null. + * @param errorCode Status code for the response. + * @throws NullPointerException if the given exception is null. + * @see DavException#DavException(int, String) + * @see DavException#DavException(int) + */ + public JcrDavException(Throwable cause, int errorCode) { + super(errorCode, cause.getMessage(), cause, null); + exceptionClass = cause.getClass(); + if (log.isDebugEnabled()) { + log.debug("Handling exception with error code " + errorCode, cause); + } + } + + /** + * Same as {@link JcrDavException#JcrDavException(Throwable, int)} where the + * error code is retrieved from an internal mapping. + * + * @param cause Cause of this DavException + * @throws NullPointerException if the given exception is null. + * @see JcrDavException#JcrDavException(Throwable, int) + */ + public JcrDavException(RepositoryException cause) { + this(cause, lookupErrorCode(cause.getClass())); + } + + /** + * Always returns true. + * + * @return true + */ + @Override + public boolean hasErrorCondition() { + return true; + } + + /** + * Returns a DAV:error Xml element containing the exceptions class and the + * message as child elements. + * + * @return Xml representation of this exception. + * @see org.apache.jackrabbit.webdav.xml.XmlSerializable#toXml(Document) + * @param document + */ + @Override + public Element toXml(Document document) { + Element error = DomUtil.createElement(document, XML_ERROR, DavConstants.NAMESPACE); + Element excep = DomUtil.createElement(document, "exception", ItemResourceConstants.NAMESPACE); + DomUtil.addChildElement(excep, "class", ItemResourceConstants.NAMESPACE, exceptionClass.getName()); + DomUtil.addChildElement(excep, "message", ItemResourceConstants.NAMESPACE, getMessage()); + error.appendChild(excep); + return error; + } +} Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/JcrDavException.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/webdav/jcr/JcrDavSession.java =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/JcrDavSession.java (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/JcrDavSession.java (working copy) @@ -0,0 +1,140 @@ +/* + * 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.webdav.jcr; + +import org.apache.jackrabbit.webdav.DavException; +import org.apache.jackrabbit.webdav.DavServletResponse; +import org.apache.jackrabbit.webdav.DavSession; +import org.apache.jackrabbit.webdav.jcr.lock.LockTokenMapper; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.jcr.RepositoryException; +import javax.jcr.Session; +import java.util.HashSet; + +/** + * JcrDavSession specific base implementation of the + * DavSession interface, which simply wraps a {@link Session} + * object. This implementation adds a utility method that allows to + * {@link #getRepositorySession() unwrap} the underlying repository session. + *
+ * Note, that in this basic implementation the following methods are simply + * forwarded to the corresponding call on Session: + *
    + *
  • {@link #getLockTokens()} => {@link Session#getLockTokens()}
  • + *
  • {@link #addLockToken(String)} => {@link Session#addLockToken(String)}
  • + *
  • {@link #removeLockToken(String)} => {@link Session#removeLockToken(String)}
  • + *
+ * Subclasses may overwrite or extend this behaviour. + */ +public abstract class JcrDavSession implements DavSession { + + private static Logger log = LoggerFactory.getLogger(JcrDavSession.class); + + /** the underlying jcr session */ + private final Session session; + + /** the lock tokens of this session */ + private final HashSet lockTokens = new HashSet(); + + /** + * + * @param session + */ + protected JcrDavSession(Session session) { + this.session = session; + } + + /** + * + * @param davSession + * @throws DavException + */ + public static void checkImplementation(DavSession davSession) throws DavException { + if (!(davSession instanceof JcrDavSession)) { + throw new DavException(DavServletResponse.SC_INTERNAL_SERVER_ERROR, "JCR specific DavSession expected. Found: " + davSession); + } + } + + /** + * + * @param davSession + * @return + * @throws DavException + */ + public static Session getRepositorySession(DavSession davSession) throws DavException { + checkImplementation(davSession); + return ((JcrDavSession)davSession).getRepositorySession(); + } + + /** + * Unwrap the {@link Session repository session} object. + * + * @return the session object wrapped by this DavSession + */ + public Session getRepositorySession() { + return session; + } + + //---------------------------------------------------------< DavSession >--- + /** + * + * @param token + * @see DavSession#addLockToken(String) + */ + @Override + public void addLockToken(String token) { + if (!LockTokenMapper.isForSessionScopedLock(token)) { + try { + session.getWorkspace().getLockManager().addLockToken(LockTokenMapper.getJcrLockToken(token)); + } + catch (RepositoryException ex) { + log.debug("trying to add lock token " + token + " to session", ex); + } + } + lockTokens.add(token); + } + + /** + * + * @return + * @see DavSession#getLockTokens() + */ + @Override + public String[] getLockTokens() { + return lockTokens.toArray(new String[lockTokens.size()]); + } + + /** + * + * @param token + * @see DavSession#removeLockToken(String) + */ + @Override + public void removeLockToken(String token) { + if (!LockTokenMapper.isForSessionScopedLock(token)) { + try { + session.getWorkspace().getLockManager().removeLockToken(LockTokenMapper.getJcrLockToken(token)); + } + catch (RepositoryException ex) { + log.debug("trying to remove lock token " + token + " to session", ex); + } + } + lockTokens.remove(token); + } +} Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/JcrDavSession.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/webdav/jcr/JcrValueType.java =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/JcrValueType.java (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/JcrValueType.java (working copy) @@ -0,0 +1,25 @@ +/* + * 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.webdav.jcr; + +/** JcrValueType... + * + * @deprecated As of Jackrabbit 2.2. Please Use {@link org.apache.jackrabbit.commons.webdav.JcrValueType} instead. + */ +public final class JcrValueType extends org.apache.jackrabbit.commons.webdav.JcrValueType { + +} \ No newline at end of file Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/JcrValueType.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/webdav/jcr/RootCollection.java =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/RootCollection.java (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/RootCollection.java (working copy) @@ -0,0 +1,310 @@ +/* + * 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.webdav.jcr; + +import java.io.IOException; +import java.io.OutputStreamWriter; +import java.io.PrintWriter; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; +import javax.jcr.Repository; +import javax.jcr.RepositoryException; +import javax.jcr.Session; +import javax.jcr.Workspace; + +import org.apache.jackrabbit.util.Text; +import org.apache.jackrabbit.webdav.DavException; +import org.apache.jackrabbit.webdav.DavResource; +import org.apache.jackrabbit.webdav.DavResourceFactory; +import org.apache.jackrabbit.webdav.DavResourceIterator; +import org.apache.jackrabbit.webdav.DavResourceIteratorImpl; +import org.apache.jackrabbit.webdav.DavResourceLocator; +import org.apache.jackrabbit.webdav.DavServletResponse; +import org.apache.jackrabbit.webdav.io.InputContext; +import org.apache.jackrabbit.webdav.io.OutputContext; +import org.apache.jackrabbit.webdav.jcr.security.JcrSupportedPrivilegesProperty; +import org.apache.jackrabbit.webdav.jcr.security.SecurityUtils; +import org.apache.jackrabbit.webdav.property.DavProperty; +import org.apache.jackrabbit.webdav.property.DavPropertyName; +import org.apache.jackrabbit.webdav.search.SearchResource; +import org.apache.jackrabbit.webdav.security.SecurityConstants; +import org.apache.jackrabbit.webdav.version.DeltaVResource; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * RootCollection represent the WebDAV root resource that does not + * represent any repository item. A call to getMembers() returns a + * DavResourceIterator containing only workspace resources + * resources, thus revealing the names of the accessible JCR workspaces. + */ +public class RootCollection extends AbstractResource { + + private static Logger log = LoggerFactory.getLogger(RootCollection.class); + + /** + * Create a new RootCollection. + * + * @param locator + * @param session + * @param factory + */ + protected RootCollection(DavResourceLocator locator, JcrDavSession session, + DavResourceFactory factory) { + super(locator, session, factory); + + // initialize the supported locks and reports + initLockSupport(); + initSupportedReports(); + } + + //--------------------------------------------------------< DavResource >--- + /** + * Returns a string listing the METHODS for this resource as it + * is required for the "Allow" response header. + * + * @return string listing the METHODS allowed + * @see org.apache.jackrabbit.webdav.DavResource#getSupportedMethods() + */ + @Override + public String getSupportedMethods() { + StringBuilder sb = new StringBuilder(DavResource.METHODS); + sb.append(", "); + sb.append(DeltaVResource.METHODS_INCL_MKWORKSPACE); + sb.append(", "); + sb.append(SearchResource.METHODS); + return sb.toString(); + } + + /** + * Returns true + * + * @return true + * @see org.apache.jackrabbit.webdav.DavResource#exists() + */ + @Override + public boolean exists() { + return true; + } + + @Override + public DavProperty getProperty(DavPropertyName name) { + DavProperty prop = super.getProperty(name); + if (prop == null) { + try { + if (SecurityConstants.SUPPORTED_PRIVILEGE_SET.equals(name)) { + prop = new JcrSupportedPrivilegesProperty(getRepositorySession()).asDavProperty(); + } + } catch (RepositoryException e) { + log.error("Failed to build SupportedPrivilegeSet property: " + e.getMessage()); + } + } + return prop; + } + + /** + * Returns true + * + * @return true + * @see org.apache.jackrabbit.webdav.DavResource#isCollection() + */ + @Override + public boolean isCollection() { + return true; + } + + /** + * Returns an empty string. + * + * @return empty string + * @see org.apache.jackrabbit.webdav.DavResource#getDisplayName() + */ + @Override + public String getDisplayName() { + return ""; + } + + /** + * Always returns 'now' + * + * @return + * @see org.apache.jackrabbit.webdav.DavResource#getModificationTime() + */ + @Override + public long getModificationTime() { + return new Date().getTime(); + } + + /** + * Sets content lengths to '0' and retrieves the modification time. + * + * @param outputContext + * @throws IOException + * @see DavResource#spool(org.apache.jackrabbit.webdav.io.OutputContext) + */ + @Override + public void spool(OutputContext outputContext) throws IOException { + if (outputContext.hasStream()) { + Session session = getRepositorySession(); + Repository rep = session.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); + String repostr = repName + " " + repVersion; + + StringBuilder sb = new StringBuilder(); + sb.append(""); + sb.append(repostr); + sb.append(""); + sb.append("

").append(repostr).append("

"); + sb.append("

Available Workspace Resources:


Powered by ").append(repName); + sb.append(" ").append(repVersion); + sb.append(""); + + outputContext.setContentLength(sb.length()); + outputContext.setModificationTime(getModificationTime()); + PrintWriter writer = new PrintWriter(new OutputStreamWriter(outputContext.getOutputStream(), "utf8")); + writer.print(sb.toString()); + writer.close(); + } else { + outputContext.setContentLength(0); + outputContext.setModificationTime(getModificationTime()); + } + } + + /** + * Always returns null + * + * @return null for the root resource is not internal member + * of any resource. + * @see org.apache.jackrabbit.webdav.DavResource#getCollection() + */ + @Override + public DavResource getCollection() { + return null; + } + + /** + * Throws exception: 403 Forbidden. + * @see DavResource#addMember(DavResource, InputContext) + */ + @Override + public void addMember(DavResource resource, InputContext inputContext) throws DavException { + throw new DavException(DavServletResponse.SC_FORBIDDEN); + } + + /** + * Returns an iterator over the member resources, which are all + * workspace resources available. + * + * @return members of this collection + * @see org.apache.jackrabbit.webdav.DavResource#getMembers() + */ + @Override + public DavResourceIterator getMembers() { + List memberList = new ArrayList(); + try { + String[] wsNames = getRepositorySession().getWorkspace().getAccessibleWorkspaceNames(); + for (String wsName : wsNames) { + String wspPath = "/" + wsName; + DavResourceLocator childLoc = getLocator().getFactory().createResourceLocator(getLocator().getPrefix(), wspPath, wspPath); + memberList.add(createResourceFromLocator(childLoc)); + } + } catch (RepositoryException e) { + log.error(e.getMessage()); + } catch (DavException e) { + // should never occur + log.error(e.getMessage()); + } + return new DavResourceIteratorImpl(memberList); + } + + /** + * Calls {@link Workspace#deleteWorkspace(String)} for the workspace with + * the name as indicated by the specified member. + * + * @see DavResource#removeMember(org.apache.jackrabbit.webdav.DavResource) + */ + @Override + public void removeMember(DavResource member) throws DavException { + Workspace wsp = getRepositorySession().getWorkspace(); + String name = Text.getName(member.getResourcePath()); + try { + wsp.deleteWorkspace(name); + } catch (RepositoryException e) { + throw new JcrDavException(e); + } + } + + //-----------------------------------------------------< DeltaVResource >--- + /** + * @see DeltaVResource#addWorkspace(org.apache.jackrabbit.webdav.DavResource) + */ + @Override + public void addWorkspace(DavResource workspace) throws DavException { + Workspace wsp = getRepositorySession().getWorkspace(); + String name = workspace.getDisplayName(); + try { + wsp.createWorkspace(name); + } catch (RepositoryException e) { + throw new JcrDavException(e); + } + } + + //-------------------------------------------------------------------------- + /** + * @see AbstractResource#initLockSupport() + */ + @Override + protected void initLockSupport() { + // no locking supported + } + + /** + * Since the root resource does not represent a repository item and therefore + * is not member of a workspace resource, this method always returns + * null. + * + * @return null + * @see AbstractResource#getWorkspaceHref() + */ + @Override + protected String getWorkspaceHref() { + return null; + } + + @Override + protected void initPropertyNames() { + super.initPropertyNames(); + if (SecurityUtils.supportsAccessControl(getRepositorySession())) { + names.add(SecurityConstants.SUPPORTED_PRIVILEGE_SET); + } + } +} Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/RootCollection.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/webdav/jcr/VersionControlledItemCollection.java =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/VersionControlledItemCollection.java (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/VersionControlledItemCollection.java (working copy) @@ -0,0 +1,704 @@ +/* + * 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.webdav.jcr; + +import org.apache.jackrabbit.JcrConstants; +import org.apache.jackrabbit.webdav.DavConstants; +import org.apache.jackrabbit.webdav.DavException; +import org.apache.jackrabbit.webdav.DavLocatorFactory; +import org.apache.jackrabbit.webdav.DavResource; +import org.apache.jackrabbit.webdav.DavResourceFactory; +import org.apache.jackrabbit.webdav.DavResourceLocator; +import org.apache.jackrabbit.webdav.DavServletResponse; +import org.apache.jackrabbit.webdav.MultiStatus; +import org.apache.jackrabbit.webdav.MultiStatusResponse; +import org.apache.jackrabbit.webdav.jcr.property.JcrDavPropertyNameSet; +import org.apache.jackrabbit.webdav.property.DavPropertyName; +import org.apache.jackrabbit.webdav.property.DefaultDavProperty; +import org.apache.jackrabbit.webdav.property.HrefProperty; +import org.apache.jackrabbit.webdav.property.DavProperty; +import org.apache.jackrabbit.webdav.property.PropEntry; +import org.apache.jackrabbit.webdav.version.LabelInfo; +import org.apache.jackrabbit.webdav.version.MergeInfo; +import org.apache.jackrabbit.webdav.version.UpdateInfo; +import org.apache.jackrabbit.webdav.version.VersionControlledResource; +import org.apache.jackrabbit.webdav.version.VersionHistoryResource; +import org.apache.jackrabbit.webdav.version.VersionResource; +import org.apache.jackrabbit.webdav.version.VersionableResource; +import org.apache.jackrabbit.webdav.version.report.ReportType; +import org.apache.jackrabbit.webdav.version.report.SupportedReportSetProperty; +import org.apache.jackrabbit.webdav.xml.DomUtil; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.w3c.dom.Element; + +import javax.jcr.Item; +import javax.jcr.Node; +import javax.jcr.NodeIterator; +import javax.jcr.RepositoryException; +import javax.jcr.Session; +import javax.jcr.Value; +import javax.jcr.ValueFormatException; +import javax.jcr.observation.EventListener; +import javax.jcr.version.Version; +import javax.jcr.version.VersionHistory; +import javax.jcr.version.VersionManager; +import java.util.List; +import java.util.Collections; + +/** + * VersionControlledItemCollection represents a JCR node item and + * covers all functionality related to versioning of {@link Node}s. + * + * @see Node + */ +public class VersionControlledItemCollection extends DefaultItemCollection + implements VersionControlledResource { + + private static Logger log = LoggerFactory.getLogger(VersionControlledItemCollection.class); + + /** + * Create a new VersionControlledItemCollection. + * + * @param locator + * @param session + * @param factory + * @param item + */ + public VersionControlledItemCollection(DavResourceLocator locator, + JcrDavSession session, + DavResourceFactory factory, + Item item) { + super(locator, session, factory, item); + if (exists() && !(item instanceof Node)) { + throw new IllegalArgumentException("A collection resource can not be constructed from a Property item."); + } + } + + //----------------------------------------------< DavResource interface >--- + /** + * Return a comma separated string listing the supported method names. + * + * @return the supported method names. + * @see org.apache.jackrabbit.webdav.DavResource#getSupportedMethods() + */ + @Override + public String getSupportedMethods() { + StringBuffer sb = new StringBuffer(super.getSupportedMethods()); + // Versioning support + sb.append(", ").append(VersionableResource.METHODS); + if (isVersionControlled()) { + try { + if (((Node)item).isCheckedOut()) { + sb.append(", ").append(VersionControlledResource.methods_checkedOut); + } else { + sb.append(", ").append(VersionControlledResource.methods_checkedIn); + } + } catch (RepositoryException e) { + // should not occur. + log.error(e.getMessage()); + } + } + return sb.toString(); + } + + @Override + public DavProperty getProperty(DavPropertyName name) { + DavProperty prop = super.getProperty(name); + if (prop == null && isVersionControlled()) { + Node n = (Node) item; + // properties defined by RFC 3253 for version-controlled resources + // workspace property already set in AbstractResource.initProperties() + try { + if (VERSION_HISTORY.equals(name)) { + // DAV:version-history (computed) + String vhHref = getLocatorFromItem(n.getVersionHistory()).getHref(true); + prop = new HrefProperty(VERSION_HISTORY, vhHref, true); + } else if (CHECKED_OUT.equals(name) && n.isCheckedOut()) { + // DAV:checked-out property (protected) + String baseVHref = getLocatorFromItem(n.getBaseVersion()).getHref(true); + prop = new HrefProperty(CHECKED_OUT, baseVHref, true); + } else if (CHECKED_IN.equals(name) && !n.isCheckedOut()) { + // DAV:checked-in property (protected) + String baseVHref = getLocatorFromItem(n.getBaseVersion()).getHref(true); + prop = new HrefProperty(CHECKED_IN, baseVHref, true); + } + } catch (RepositoryException e) { + log.error(e.getMessage()); + } + } + + return prop; + } + + /** + * @param changeList + * @throws DavException + * @see DefaultItemCollection#alterProperties(List) + * for additional description of non-compliant behaviour. + */ + @Override + public MultiStatusResponse alterProperties(List changeList) throws DavException { + /* first resolve merge conflict since they cannot be handled by + setting property values in jcr (and are persisted immediately). + NOTE: this violates RFC 2518 that requires that proppatch + is processed in the order entries are present in the xml and that + required that no changes must be persisted if any set/remove fails. + */ + // TODO: solve violation of RFC 2518 + resolveMergeConflict(changeList); + // alter other properties only if merge-conflicts could be handled + return super.alterProperties(changeList); + } + + /** + * Resolve one or multiple merge conflicts present on this resource. Please + * note that the 'setProperties' or 'removeProperties' set my contain additional + * resource properties, that need to be changed. Those properties are left + * untouched, whereas the {@link #AUTO_MERGE_SET DAV:auto-merge-set}, is + * removed from the list upon successful resolution of a merge conflict.
+ * If the removeProperties or setProperties set do not contain the mentioned + * merge conflict resource properties or if the value of those properties do + * not allow for a resolution of an existing merge conflict, this method + * returns silently. + * + * @param changeList + * @throws org.apache.jackrabbit.webdav.DavException + * @see Node#doneMerge(Version) + * @see Node#cancelMerge(Version) + */ + private void resolveMergeConflict(List changeList) throws DavException { + if (!exists()) { + throw new DavException(DavServletResponse.SC_NOT_FOUND); + } + try { + Node n = (Node) item; + VersionManager vMgr = getVersionManager(); + String path = item.getPath(); + + DavProperty autoMergeSet = null; + DavProperty predecessorSet = null; + /* find DAV:auto-merge-set entries. If none exists no attempt is made + to resolve merge conflict > return silently */ + for (int i = 0; i < changeList.size(); i++) { + PropEntry propEntry = changeList.get(i); + // If DAV:auto-merge-set is DavPropertyName all remaining merge + // conflicts are resolved with 'cancel' + if (propEntry instanceof DavPropertyName && AUTO_MERGE_SET.equals(propEntry)) { + // retrieve the current jcr:mergeFailed property values + if (!n.hasProperty(JcrConstants.JCR_MERGEFAILED)) { + throw new DavException(DavServletResponse.SC_CONFLICT, "Attempt to resolve non-existing merge conflicts."); + } + Value[] mergeFailed = n.getProperty(JcrConstants.JCR_MERGEFAILED).getValues(); + for (Value value : mergeFailed) { + vMgr.cancelMerge(path, (Version) getRepositorySession().getNodeByIdentifier(value.getString())); + } + // remove this entry from the changeList + changeList.remove(propEntry); + } else if (propEntry instanceof DavProperty) { + if (AUTO_MERGE_SET.equals(((DavProperty)propEntry).getName())) { + autoMergeSet = (DavProperty) propEntry; + } else if (PREDECESSOR_SET.equals(((DavProperty)propEntry).getName())) { + predecessorSet = (DavProperty) propEntry; + } + } + } + + // If DAV:auto-merge-set is a DavProperty merge conflicts need to be + // resolved individually according to the DAV:predecessor-set property. + if (autoMergeSet != null) { + // retrieve the current jcr:mergeFailed property values + if (!n.hasProperty(JcrConstants.JCR_MERGEFAILED)) { + throw new DavException(DavServletResponse.SC_CONFLICT, "Attempt to resolve non-existing merge conflicts."); + } + + List mergeset = new HrefProperty(autoMergeSet).getHrefs(); + List predecL; + if (predecessorSet == null) { + predecL = Collections.emptyList(); + } else { + predecL = new HrefProperty(predecessorSet).getHrefs(); + } + + Session session = getRepositorySession(); + // loop over the mergeFailed values (versions) and test whether they are + // removed from the DAV:auto-merge-set thus indicating resolution. + Value[] mergeFailed = n.getProperty(JcrConstants.JCR_MERGEFAILED).getValues(); + for (Value value : mergeFailed) { + // build version-href from each entry in the jcr:mergeFailed property + // in order to be able to compare to the entries in the HrefProperty. + Version version = (Version) session.getNodeByIdentifier(value.getString()); + String href = getLocatorFromItem(version).getHref(true); + + // Test if that version has been removed from the merge-set. + // thus indicating that this merge conflict needs to be resolved. + if (!mergeset.contains(href)) { + // If the conflict value has been moved over from DAV:auto-merge-set + // to the predecessor-set, resolution with 'doneMerge' is + // appropriate. If the value has been removed from the + // merge-set but not added to the predecessors 'cancelMerge' + // must be called. + if (predecL.contains(href)) { + vMgr.doneMerge(path, version); + } else { + vMgr.cancelMerge(path, version); + } + } + } + // after successful resolution of merge-conflicts according to + // DAV:auto-merge-set and DAV:predecessor-set remove these entries + // from the changeList. + changeList.remove(autoMergeSet); + if (predecessorSet != null) { + changeList.remove(predecessorSet); + } + } + } catch (RepositoryException e) { + throw new JcrDavException(e); + } + } + + //--------------------------------------< VersionableResource interface >--- + /** + * Adds version control to this resource. If the resource is already under + * version control, this method has no effect. + * + * @throws org.apache.jackrabbit.webdav.DavException if this resource does not + * exist yet or if an error occurs while making the underlying node versionable. + * @see org.apache.jackrabbit.webdav.version.VersionableResource#addVersionControl() + */ + @Override + public void addVersionControl() throws DavException { + if (!exists()) { + throw new DavException(DavServletResponse.SC_NOT_FOUND); + } + if (!isVersionControlled()) { + try { + ((Node)item).addMixin(JcrConstants.MIX_VERSIONABLE); + item.save(); + } catch (RepositoryException e) { + throw new JcrDavException(e); + } + } // else: is already version controlled -> ignore + } + + //--------------------------------< VersionControlledResource interface >--- + /** + * Calls {@link javax.jcr.Node#checkin()} on the underlying repository node. + * + * @throws org.apache.jackrabbit.webdav.DavException + * @see org.apache.jackrabbit.webdav.version.VersionControlledResource#checkin() + */ + @Override + public String checkin() throws DavException { + if (!exists()) { + throw new DavException(DavServletResponse.SC_NOT_FOUND); + } + if (!isVersionControlled()) { + throw new DavException(DavServletResponse.SC_METHOD_NOT_ALLOWED); + } + try { + Version v = getVersionManager().checkin(item.getPath()); + String versionHref = getLocatorFromItem(v).getHref(true); + return versionHref; + } catch (RepositoryException e) { + // UnsupportedRepositoryException should not occur + throw new JcrDavException(e); + } + } + + /** + * Calls {@link javax.jcr.Node#checkout()} on the underlying repository node. + * + * @throws org.apache.jackrabbit.webdav.DavException + * @see org.apache.jackrabbit.webdav.version.VersionControlledResource#checkout() + */ + @Override + public void checkout() throws DavException { + if (!exists()) { + throw new DavException(DavServletResponse.SC_NOT_FOUND); + } + if (!isVersionControlled()) { + throw new DavException(DavServletResponse.SC_METHOD_NOT_ALLOWED); + } + try { + getVersionManager().checkout(item.getPath()); + } catch (RepositoryException e) { + // UnsupportedRepositoryException should not occur + throw new JcrDavException(e); + } + } + + /** + * Not implemented. Always throws a DavException with error code + * {@link org.apache.jackrabbit.webdav.DavServletResponse#SC_NOT_IMPLEMENTED}. + * + * @throws org.apache.jackrabbit.webdav.DavException + * @see org.apache.jackrabbit.webdav.version.VersionControlledResource#uncheckout() + */ + @Override + public void uncheckout() throws DavException { + throw new DavException(DavServletResponse.SC_NOT_IMPLEMENTED); + } + + /** + * Perform an update on this resource. Depending on the format of the updateInfo + * this is translated to one of the following methods defined by the JCR API: + *
    + *
  • {@link Node#restore(javax.jcr.version.Version, boolean)}
  • + *
  • {@link Node#restore(javax.jcr.version.Version, String, boolean)}
  • + *
  • {@link Node#restoreByLabel(String, boolean)}
  • + *
  • {@link Node#update(String)}
  • + *
+ *

+ * Limitation: note that the MultiStatus returned by this method + * will not list any nodes that have been removed due to an Uuid conflict. + * + * @param updateInfo + * @return + * @throws org.apache.jackrabbit.webdav.DavException + * @see org.apache.jackrabbit.webdav.version.VersionControlledResource#update(org.apache.jackrabbit.webdav.version.UpdateInfo) + */ + //TODO: with jcr the node must not be versionable in order to perform Node.update. + @Override + public MultiStatus update(UpdateInfo updateInfo) throws DavException { + if (updateInfo == null) { + throw new DavException(DavServletResponse.SC_BAD_REQUEST, "Valid update request body required."); + } + if (!exists()) { + throw new DavException(DavServletResponse.SC_NOT_FOUND); + } + + MultiStatus ms = new MultiStatus(); + try { + Node node = (Node)item; + Element udElem = updateInfo.getUpdateElement(); + boolean removeExisting = DomUtil.hasChildElement(udElem, XML_REMOVEEXISTING, NAMESPACE); + + // register eventListener in order to be able to report the modified resources. + EventListener el = new EListener(updateInfo.getPropertyNameSet(), ms); + registerEventListener(el, node.getPath()); + + // perform the update/restore according to the update info + if (updateInfo.getVersionHref() != null) { + String[] hrefs = updateInfo.getVersionHref(); + if (hrefs.length != 1) { + throw new DavException(DavServletResponse.SC_BAD_REQUEST, "Invalid update request body missing version href or containing multiple version hrefs."); + } + + final String href = normalizeResourceHref(hrefs[0]); + String versionPath = getLocatorFromHref(href).getRepositoryPath(); + String versionName = getItemName(versionPath); + + String relPath = DomUtil.getChildText(udElem, XML_RELPATH, NAMESPACE); + if (relPath == null) { + // restore version by name + node.restore(versionName, removeExisting); + } else if (node.hasNode(relPath)) { + Version v = node.getNode(relPath).getVersionHistory().getVersion(versionName); + node.restore(v, relPath, removeExisting); + } else { + Version v = (Version) getRepositorySession().getNode(versionPath); + node.restore(v, relPath, removeExisting); + } + + } else if (updateInfo.getLabelName() != null) { + String[] labels = updateInfo.getLabelName(); + if (labels.length != 1) { + throw new DavException(DavServletResponse.SC_BAD_REQUEST, "Invalid update request body: Multiple labels specified."); + } + node.restoreByLabel(labels[0], removeExisting); + + } else if (updateInfo.getWorkspaceHref() != null) { + String href = normalizeResourceHref(obtainAbsolutePathFromUri(updateInfo.getWorkspaceHref())); + String workspaceName = getLocatorFromHref(href).getWorkspaceName(); + node.update(workspaceName); + } else { + throw new DavException(DavServletResponse.SC_BAD_REQUEST, "Invalid update request body."); + } + + // unregister the event listener again + unregisterEventListener(el); + + } catch (RepositoryException e) { + throw new JcrDavException(e); + } + return ms; + } + + /** + * Merge the repository node represented by this resource according to the + * information present in the given {@link MergeInfo} object. + * + * @param mergeInfo + * @return MultiStatus recording all repository items modified + * by this merge call as well as the resources that a client must modify to + * complete the merge (see RFC 3253) + * @throws org.apache.jackrabbit.webdav.DavException + * @see org.apache.jackrabbit.webdav.version.VersionControlledResource#merge(org.apache.jackrabbit.webdav.version.MergeInfo) + * @see Node#merge(String, boolean) + */ + //TODO: with jcr the node must not be versionable in order to perform Node.merge + @Override + public MultiStatus merge(MergeInfo mergeInfo) throws DavException { + if (mergeInfo == null) { + throw new DavException(DavServletResponse.SC_BAD_REQUEST); + } + if (!exists()) { + throw new DavException(DavServletResponse.SC_NOT_FOUND); + } + + MultiStatus ms = new MultiStatus(); + try { + // NOTE: RFC requires that all modified resources are reported in the + // multistatus response. this doesn't work however with the remoting + // there is no way to distinguish the 'failedId's from any other + // resources that got modified by this merge operation -> omitted. + + // todo: RFC allows multiple href elements inside the DAV:source element + final String href = normalizeResourceHref(mergeInfo.getSourceHrefs()[0]); + String workspaceName = getLocatorFromHref(href).getWorkspaceName(); + + String depth = DomUtil.getChildTextTrim(mergeInfo.getMergeElement(), DavConstants.XML_DEPTH, DavConstants.NAMESPACE); + boolean isShallow = "0".equals(depth); + + NodeIterator failed = getVersionManager().merge(item.getPath(), workspaceName, !mergeInfo.isNoAutoMerge(), isShallow); + + // add resources to the multistatus, that failed to be merged + while (failed.hasNext()) { + Node failedNode = failed.nextNode(); + DavResourceLocator loc = getLocatorFromItem(failedNode); + DavResource res = createResourceFromLocator(loc); + ms.addResponse(new MultiStatusResponse(res, mergeInfo.getPropertyNameSet())); + } + + } catch (RepositoryException e) { + throw new JcrDavException(e); + } + + return ms; + } + + /** + * Modify the labels present with the versions of this resource. + * + * @param labelInfo + * @throws DavException + * @see VersionHistory#addVersionLabel(String, String, boolean) + * @see VersionHistory#removeVersionLabel(String) + */ + @Override + public void label(LabelInfo labelInfo) throws DavException { + if (labelInfo == null) { + throw new DavException(DavServletResponse.SC_BAD_REQUEST, "Valid label request body required."); + } + if (!exists()) { + throw new DavException(DavServletResponse.SC_NOT_FOUND); + } + + try { + if (!isVersionControlled() || ((Node)item).isCheckedOut()) { + throw new DavException(DavServletResponse.SC_PRECONDITION_FAILED, "A LABEL request may only be applied to a version-controlled, checked-in resource."); + } + DavResource[] resArr = this.getReferenceResources(CHECKED_IN); + if (resArr.length == 1 && resArr[0] instanceof VersionResource) { + ((VersionResource)resArr[0]).label(labelInfo); + } else { + throw new DavException(DavServletResponse.SC_INTERNAL_SERVER_ERROR, "DAV:checked-in property on '" + getHref() + "' did not point to a single VersionResource."); + } + } catch (RepositoryException e) { + throw new JcrDavException(e); + } + } + + /** + * Returns the {@link VersionHistory} associated with the repository node. + * If the node is not versionable an exception is thrown. + * + * @return the {@link VersionHistoryResource} associated with this resource. + * @throws org.apache.jackrabbit.webdav.DavException + * @see org.apache.jackrabbit.webdav.version.VersionControlledResource#getVersionHistory() + * @see javax.jcr.Node#getVersionHistory() + */ + @Override + public VersionHistoryResource getVersionHistory() throws DavException { + if (!exists()) { + throw new DavException(DavServletResponse.SC_NOT_FOUND); + } + + try { + VersionHistory vh = ((Node)item).getVersionHistory(); + DavResourceLocator loc = getLocatorFromItem(vh); + return (VersionHistoryResource) createResourceFromLocator(loc); + } catch (RepositoryException e) { + throw new JcrDavException(e); + } + } + + //-------------------------------------------------------------------------- + /** + * Define the set of reports supported by this resource. + * + * @see SupportedReportSetProperty + */ + @Override + protected void initSupportedReports() { + super.initSupportedReports(); + if (exists()) { + supportedReports.addReportType(ReportType.LOCATE_BY_HISTORY); + if (this.isVersionControlled()) { + supportedReports.addReportType(ReportType.VERSION_TREE); + } + } + } + + @Override + protected void initPropertyNames() { + super.initPropertyNames(); + + if (isVersionControlled()) { + names.addAll(JcrDavPropertyNameSet.VERSIONABLE_SET); + + Node n = (Node) item; + try { + if (n.isCheckedOut()) { + names.add(CHECKED_OUT); + if (n.hasProperty(JcrConstants.JCR_PREDECESSORS)) { + names.add(PREDECESSOR_SET); + } + if (n.hasProperty(JcrConstants.JCR_MERGEFAILED)) { + names.add(AUTO_MERGE_SET); + } + // todo: checkout-fork, checkin-fork + } else { + names.add(CHECKED_IN); + } + } catch (RepositoryException e) { + log.warn(e.getMessage()); + } + } + } + + /** + * Fill the property set for this resource. + */ + @Override + protected void initProperties() { + super.initProperties(); + if (isVersionControlled()) { + Node n = (Node)item; + // properties defined by RFC 3253 for version-controlled resources + // workspace property already set in AbstractResource.initProperties() + try { + // DAV:version-history (computed) + String vhHref = getLocatorFromItem(n.getVersionHistory()).getHref(true); + properties.add(new HrefProperty(VERSION_HISTORY, vhHref, true)); + + // DAV:auto-version property: there is no auto version, explicit CHECKOUT is required. + properties.add(new DefaultDavProperty(AUTO_VERSION, null, false)); + + String baseVHref = getLocatorFromItem(n.getBaseVersion()).getHref(true); + if (n.isCheckedOut()) { + // DAV:predecessors property + if (n.hasProperty(JcrConstants.JCR_PREDECESSORS)) { + Value[] predec = n.getProperty(JcrConstants.JCR_PREDECESSORS).getValues(); + addHrefProperty(PREDECESSOR_SET, predec, false); + } + // DAV:auto-merge-set property. NOTE: the DAV:merge-set + // never occurs, because merging without bestEffort flag + // being set results in an exception on failure. + if (n.hasProperty(JcrConstants.JCR_MERGEFAILED)) { + Value[] mergeFailed = n.getProperty(JcrConstants.JCR_MERGEFAILED).getValues(); + addHrefProperty(AUTO_MERGE_SET, mergeFailed, false); + } + // todo: checkout-fork, checkin-fork + } + } catch (RepositoryException e) { + log.error(e.getMessage()); + } + } + } + + /** + * Add a {@link org.apache.jackrabbit.webdav.property.HrefProperty} with the + * specified property name and values. + * + * @param name + * @param values Array of {@link Value}s. + * @param isProtected + * @throws javax.jcr.ValueFormatException + * @throws IllegalStateException + * @throws javax.jcr.RepositoryException + */ + private void addHrefProperty(DavPropertyName name, Value[] values, + boolean isProtected) + throws ValueFormatException, IllegalStateException, RepositoryException { + Node[] nodes = new Node[values.length]; + for (int i = 0; i < values.length; i++) { + nodes[i] = getRepositorySession().getNodeByIdentifier(values[i].getString()); + } + addHrefProperty(name, nodes, isProtected); + } + + /** + * @return true, if this resource represents an existing repository node + * that has the mixin nodetype 'mix:versionable' set. + */ + private boolean isVersionControlled() { + boolean vc = false; + if (exists()) { + try { + vc = ((Node) item).isNodeType(JcrConstants.MIX_VERSIONABLE); + } catch (RepositoryException e) { + log.warn(e.getMessage()); + } + } + return vc; + } + + /** + * Build a new locator for the given href. + * + * @param href + * @return + */ + private DavResourceLocator getLocatorFromHref(String href) { + DavLocatorFactory f = getLocator().getFactory(); + String prefix = getLocator().getPrefix(); + return f.createResourceLocator(prefix, href); + } + + private VersionManager getVersionManager() throws RepositoryException { + return getRepositorySession().getWorkspace().getVersionManager(); + } + + private static String obtainAbsolutePathFromUri(String uri) { + try { + java.net.URI u = new java.net.URI(uri); + StringBuilder sb = new StringBuilder(); + sb.append(u.getRawPath()); + if (u.getRawQuery() != null) { + sb.append("?").append(u.getRawQuery()); + } + return sb.toString(); + } + catch (java.net.URISyntaxException ex) { + log.warn("parsing " + uri, ex); + return uri; + } + } +} Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/VersionControlledItemCollection.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/webdav/jcr/WorkspaceResourceImpl.java =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/WorkspaceResourceImpl.java (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/WorkspaceResourceImpl.java (working copy) @@ -0,0 +1,627 @@ +/* + * 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.webdav.jcr; + +import org.apache.jackrabbit.commons.cnd.CompactNodeTypeDefReader; +import org.apache.jackrabbit.commons.cnd.CompactNodeTypeDefWriter; +import org.apache.jackrabbit.commons.cnd.DefinitionBuilderFactory; +import org.apache.jackrabbit.commons.cnd.ParseException; +import org.apache.jackrabbit.commons.cnd.TemplateBuilderFactory; +import org.apache.jackrabbit.commons.webdav.AtomFeedConstants; +import org.apache.jackrabbit.webdav.DavException; +import org.apache.jackrabbit.webdav.DavMethods; +import org.apache.jackrabbit.webdav.DavResource; +import org.apache.jackrabbit.webdav.DavResourceFactory; +import org.apache.jackrabbit.webdav.DavResourceIterator; +import org.apache.jackrabbit.webdav.DavResourceIteratorImpl; +import org.apache.jackrabbit.webdav.DavResourceLocator; +import org.apache.jackrabbit.webdav.DavServletResponse; +import org.apache.jackrabbit.webdav.MultiStatus; +import org.apache.jackrabbit.webdav.MultiStatusResponse; +import org.apache.jackrabbit.webdav.io.InputContext; +import org.apache.jackrabbit.webdav.io.OutputContext; +import org.apache.jackrabbit.webdav.jcr.property.JcrDavPropertyNameSet; +import org.apache.jackrabbit.webdav.jcr.property.NamespacesProperty; +import org.apache.jackrabbit.webdav.jcr.security.JcrUserPrivilegesProperty; +import org.apache.jackrabbit.webdav.jcr.security.JcrSupportedPrivilegesProperty; +import org.apache.jackrabbit.webdav.jcr.security.SecurityUtils; +import org.apache.jackrabbit.webdav.jcr.version.report.JcrPrivilegeReport; +import org.apache.jackrabbit.webdav.property.DavProperty; +import org.apache.jackrabbit.webdav.property.DavPropertyName; +import org.apache.jackrabbit.webdav.property.DefaultDavProperty; +import org.apache.jackrabbit.webdav.property.PropEntry; +import org.apache.jackrabbit.webdav.search.SearchResource; +import org.apache.jackrabbit.webdav.security.SecurityConstants; +import org.apache.jackrabbit.webdav.version.DeltaVResource; +import org.apache.jackrabbit.webdav.version.LabelInfo; +import org.apache.jackrabbit.webdav.version.MergeInfo; +import org.apache.jackrabbit.webdav.version.UpdateInfo; +import org.apache.jackrabbit.webdav.version.VersionControlledResource; +import org.apache.jackrabbit.webdav.version.VersionHistoryResource; +import org.apache.jackrabbit.webdav.version.WorkspaceResource; +import org.apache.jackrabbit.webdav.xml.DomUtil; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.w3c.dom.Element; + +import javax.jcr.Item; +import javax.jcr.NamespaceRegistry; +import javax.jcr.Repository; +import javax.jcr.RepositoryException; +import javax.jcr.Session; +import javax.jcr.Workspace; +import javax.jcr.nodetype.NodeTypeIterator; +import javax.jcr.nodetype.NodeTypeManager; +import javax.jcr.nodetype.NodeTypeTemplate; +import javax.jcr.observation.EventListener; +import javax.jcr.version.Version; +import java.io.IOException; +import java.io.OutputStreamWriter; +import java.io.PrintWriter; +import java.io.StringReader; +import java.io.StringWriter; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.Date; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * WorkspaceResourceImpl... + */ +public class WorkspaceResourceImpl extends AbstractResource + implements WorkspaceResource, VersionControlledResource { + + private static Logger log = LoggerFactory.getLogger(WorkspaceResourceImpl.class); + + /** + * Create a new WorkspaceResourceImpl + * + * @param locator + * @param session + * @param factory + */ + WorkspaceResourceImpl(DavResourceLocator locator, JcrDavSession session, DavResourceFactory factory) { + super(locator, session, factory); + + // initialize the supported locks and reports + initLockSupport(); + initSupportedReports(); + } + + @Override + public DavProperty getProperty(DavPropertyName name) { + DavProperty prop = super.getProperty(name); + if (prop == null) { + StringWriter writer = null; + try { + if (ItemResourceConstants.JCR_NODETYPES_CND.equals(name)) { + writer = new StringWriter(); + Session s = getRepositorySession(); + + CompactNodeTypeDefWriter cndWriter = new CompactNodeTypeDefWriter(writer, s, true); + NodeTypeIterator ntIterator = s.getWorkspace().getNodeTypeManager().getAllNodeTypes(); + while (ntIterator.hasNext()) { + cndWriter.write(ntIterator.nextNodeType()); + } + cndWriter.close(); + /* + NOTE: avoid having JCR_NODETYPES_CND exposed upon allprop + PROPFIND request since it needs to be calculated. + nevertheless, this property can be altered using + PROPPATCH, which is not consistent with the specification + */ + prop = new DefaultDavProperty(ItemResourceConstants.JCR_NODETYPES_CND, writer.toString(), true); + + } else if (SecurityConstants.SUPPORTED_PRIVILEGE_SET.equals(name)) { + prop = new JcrSupportedPrivilegesProperty(getRepositorySession(), null).asDavProperty(); + } else if (SecurityConstants.CURRENT_USER_PRIVILEGE_SET.equals(name)) { + prop = new JcrUserPrivilegesProperty(getRepositorySession(), null).asDavProperty(); + } + } catch (RepositoryException e) { + log.error("Failed to access NodeTypeManager: " + e.getMessage()); + } catch (IOException e) { + log.error("Failed to write compact node definition: " + e.getMessage()); + } finally { + if (writer != null) { + try { + writer.close(); + } catch (IOException e) { + log.error(e.getMessage()); + } + } + } + } + + // TODO: required property DAV:workspace-checkout-set (computed) + + return prop; + } + + //--------------------------------------------------------< DavResource >--- + + @Override + public String getSupportedMethods() { + StringBuilder sb = new StringBuilder(DavResource.METHODS); + sb.append(", "); + sb.append(DeltaVResource.METHODS_INCL_MKWORKSPACE); + sb.append(", "); + sb.append(SearchResource.METHODS); + // from vc-resource methods only UPDATE is supported + sb.append(", "); + sb.append(DavMethods.METHOD_UPDATE); + return sb.toString(); + } + + /** + * @return true if the workspace name (see {@link #getDisplayName()} is + * present in the list of available workspace names such as exposed by + * the editing JCR session. + */ + @Override + public boolean exists() { + try { + List available = Arrays.asList(getRepositorySession().getWorkspace().getAccessibleWorkspaceNames()); + return available.contains(getDisplayName()); + } catch (RepositoryException e) { + log.warn(e.getMessage()); + return false; + } + } + + /** + * @return true + */ + @Override + public boolean isCollection() { + return true; + } + + /** + * Returns the name of the workspace. + * + * @return The workspace name + * @see org.apache.jackrabbit.webdav.DavResource#getDisplayName() + * @see javax.jcr.Workspace#getName() + */ + @Override + public String getDisplayName() { + return getLocator().getWorkspaceName(); + } + + /** + * Always returns 'now' + * + * @return + */ + @Override + public long getModificationTime() { + return new Date().getTime(); + } + + /** + * @param outputContext + * @throws IOException + */ + @Override + public void spool(OutputContext outputContext) throws IOException { + + outputContext.setProperty("Link", "; title=\"Event Journal\"; rel=alternate; type=\"" + AtomFeedConstants.MEDIATYPE + "\""); + + if (outputContext.hasStream()) { + Session session = getRepositorySession(); + Repository rep = session.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); + String repostr = repName + " " + repVersion; + + StringBuilder sb = new StringBuilder(); + sb.append(""); + sb.append(repostr); + sb.append(""); + sb.append(""); + sb.append(""); + sb.append("

").append(repostr).append("


Powered by ").append(repName); + sb.append(" ").append(repVersion); + sb.append(""); + + outputContext.setContentLength(sb.length()); + outputContext.setModificationTime(getModificationTime()); + PrintWriter writer = new PrintWriter(new OutputStreamWriter(outputContext.getOutputStream(), "utf8")); + writer.print(sb.toString()); + writer.close(); + } else { + outputContext.setContentLength(0); + outputContext.setModificationTime(getModificationTime()); + } + } + + /** + * Retrieve the collection that has all workspace collections + * as internal members. + * + * @see org.apache.jackrabbit.webdav.DavResource#getCollection() + */ + @Override + public DavResource getCollection() { + DavResource collection = null; + // create location with 'null' values for workspace-path and resource-path + DavResourceLocator parentLoc = getLocator().getFactory().createResourceLocator(getLocator().getPrefix(), null, null, false); + try { + collection = createResourceFromLocator(parentLoc); + } catch (DavException e) { + log.error("Unexpected error while retrieving collection: " + e.getMessage()); + } + return collection; + } + + /** + * Throws 403 exception (Forbidden) + * + * @param resource + * @param inputContext + * @throws DavException + */ + @Override + public void addMember(DavResource resource, InputContext inputContext) throws DavException { + log.error("Cannot add a new member to the workspace resource."); + throw new DavException(DavServletResponse.SC_FORBIDDEN); + } + + /** + * Returns the resource representing the JCR root node. + * + * @return + */ + @Override + public DavResourceIterator getMembers() { + try { + DavResourceLocator loc = getLocatorFromItem(getRepositorySession().getRootNode()); + List list = Collections.singletonList(createResourceFromLocator(loc)); + return new DavResourceIteratorImpl(list); + } catch (DavException e) { + log.error("Internal error while building resource for the root node.", e); + return DavResourceIteratorImpl.EMPTY; + } catch (RepositoryException e) { + log.error("Internal error while building resource for the root node.", e); + return DavResourceIteratorImpl.EMPTY; + } + } + + /** + * Throws 403 exception (Forbidden) + * + * @param member + * @throws DavException + */ + @Override + public void removeMember(DavResource member) throws DavException { + log.error("Cannot add a remove the root node."); + throw new DavException(DavServletResponse.SC_FORBIDDEN); + } + + /** + * Allows to alter the registered namespaces ({@link ItemResourceConstants#JCR_NAMESPACES}) + * or register node types {@link ItemResourceConstants#JCR_NODETYPES_CND} + * where the passed value is a cnd string containing the definition + * and forwards any other property to the super class. + *

+ * Note that again no property status is set. Any failure while setting + * a property results in an exception (violating RFC 2518). + * + * @param property + * @throws DavException + * @see DavResource#setProperty(org.apache.jackrabbit.webdav.property.DavProperty) + */ + @Override + public void setProperty(DavProperty property) throws DavException { + if (ItemResourceConstants.JCR_NAMESPACES.equals(property.getName())) { + NamespacesProperty nsp = new NamespacesProperty(property); + try { + Map changes = new HashMap(nsp.getNamespaces()); + NamespaceRegistry nsReg = getRepositorySession().getWorkspace().getNamespaceRegistry(); + for (String prefix : nsReg.getPrefixes()) { + if (!changes.containsKey(prefix)) { + // prefix not present amongst the new values any more > unregister + nsReg.unregisterNamespace(prefix); + } else if (changes.get(prefix).equals(nsReg.getURI(prefix))) { + // present with same uri-value >> no action required + changes.remove(prefix); + } + } + + // try to register any prefix/uri pair that has a changed uri or + // it has not been present before. + for (String prefix : changes.keySet()) { + String uri = changes.get(prefix); + nsReg.registerNamespace(prefix, uri); + } + } catch (RepositoryException e) { + throw new JcrDavException(e); + } + } else if (ItemResourceConstants.JCR_NODETYPES_CND.equals(property.getName())) { + try { + Object value = property.getValue(); + List cmds; + if (value instanceof List) { + cmds = (List) value; + } else if (value instanceof Element) { + cmds = Collections.singletonList(value); + } else { + log.warn("Unexpected structure of dcr:nodetypes-cnd property."); + throw new DavException(DavServletResponse.SC_INTERNAL_SERVER_ERROR); + } + + String registerCnd = null; + boolean allowUpdate = false; + List unregisterNames = new ArrayList(); + + for (Object listEntry : cmds) { + if (listEntry instanceof Element) { + Element e = (Element) listEntry; + String localName = e.getLocalName(); + if (ItemResourceConstants.XML_CND.equals(localName)) { + registerCnd = DomUtil.getText(e); + } else if (ItemResourceConstants.XML_ALLOWUPDATE.equals(localName)) { + String allow = DomUtil.getTextTrim(e); + allowUpdate = Boolean.parseBoolean(allow); + } else if (ItemResourceConstants.XML_NODETYPENAME.equals(localName)) { + unregisterNames.add(DomUtil.getTextTrim(e)); + } + } + } + + // TODO: for simplicity it's currently either registration or unregistration as nt-modifications are immediately persisted. + Session s = getRepositorySession(); + NodeTypeManager ntMgr = s.getWorkspace().getNodeTypeManager(); + if (registerCnd != null) { + StringReader reader = new StringReader(registerCnd); + DefinitionBuilderFactory factory = + new TemplateBuilderFactory(ntMgr, s.getValueFactory(), s.getWorkspace().getNamespaceRegistry()); + + CompactNodeTypeDefReader cndReader = + new CompactNodeTypeDefReader(reader, "davex", factory); + + List ntts = cndReader.getNodeTypeDefinitions(); + ntMgr.registerNodeTypes(ntts.toArray(new NodeTypeTemplate[ntts.size()]), allowUpdate); + } else if (!unregisterNames.isEmpty()) { + ntMgr.unregisterNodeTypes(unregisterNames.toArray(new String[unregisterNames.size()])); + } + + } catch (ParseException e) { + throw new DavException(DavServletResponse.SC_BAD_REQUEST, e); + } + catch (RepositoryException e) { + throw new JcrDavException(e); + } + } else { + // only jcr:namespace or node types can be modified + throw new DavException(DavServletResponse.SC_CONFLICT); + } + } + + /** + * Handles an attempt to set {@link ItemResourceConstants#JCR_NAMESPACES} + * and forwards any other set or remove requests to the super class. + * + * @see #setProperty(DavProperty) + * @see DefaultItemCollection#alterProperties(List) + */ + @Override + public MultiStatusResponse alterProperties(List changeList) throws DavException { + if (changeList.size() == 1) { + PropEntry propEntry = changeList.get(0); + // only modification of prop is allowed. removal is not possible + if (propEntry instanceof DavProperty + && (ItemResourceConstants.JCR_NAMESPACES.equals(((DavProperty)propEntry).getName()) + || ItemResourceConstants.JCR_NODETYPES_CND.equals(((DavProperty)propEntry).getName()))) { + setProperty((DavProperty) propEntry); + } else { + // attempt to remove the namespace property + throw new DavException(DavServletResponse.SC_CONFLICT); + } + } else { + // change list contains more than the jcr:namespaces property + // TODO: build multistatus instead + throw new DavException(DavServletResponse.SC_CONFLICT); + } + return new MultiStatusResponse(getHref(), DavServletResponse.SC_OK); + } + + //------------------------------------------------< VersionableResource >--- + /** + * @throws DavException (403) since workspace is not versionable. implementing + * VersionControlledResource only for 'update'. + */ + @Override + public void addVersionControl() throws DavException { + throw new DavException(DavServletResponse.SC_FORBIDDEN); + } + + //------------------------------------------< VersionControlledResource >--- + /** + * @throws DavException (403) since workspace is not versionable. implementing + * VersionControlledResource only for 'update'. + */ + @Override + public String checkin() throws DavException { + throw new DavException(DavServletResponse.SC_FORBIDDEN); + } + + /** + * @throws DavException (403) since workspace is not versionable. implementing + * VersionControlledResource only for 'update'. + */ + @Override + public void checkout() throws DavException { + throw new DavException(DavServletResponse.SC_FORBIDDEN); + } + + /** + * @throws DavException (403) since workspace is not versionable. implementing + * VersionControlledResource only for 'update'. + */ + @Override + public void uncheckout() throws DavException { + throw new DavException(DavServletResponse.SC_FORBIDDEN); + } + + /** + * While RFC 3253 does not define any version-related operations for the + * workspace resource, this implementation uses {@link VersionControlledResource#update(UpdateInfo)} + * to map {@link Workspace#restore(javax.jcr.version.Version[], boolean)} to + * a WebDAV call. + *

+ * Limitation: note that the MultiStatus returned by this method + * will not list any nodes that have been removed due to an Uuid conflict. + * + * @param updateInfo + * @return + * @throws org.apache.jackrabbit.webdav.DavException + * @see org.apache.jackrabbit.webdav.version.VersionControlledResource#update(org.apache.jackrabbit.webdav.version.UpdateInfo) + */ + @Override + public MultiStatus update(UpdateInfo updateInfo) throws DavException { + if (updateInfo == null) { + throw new DavException(DavServletResponse.SC_BAD_REQUEST, "Valid update request body required."); + } + if (!exists()) { + throw new DavException(DavServletResponse.SC_NOT_FOUND); + } + + Session session = getRepositorySession(); + MultiStatus ms = new MultiStatus(); + try { + Element udElem = updateInfo.getUpdateElement(); + boolean removeExisting = DomUtil.hasChildElement(udElem, ItemResourceConstants.XML_REMOVEEXISTING, ItemResourceConstants.NAMESPACE); + + // register eventListener in order to be able to report the modified resources. + EventListener el = new EListener(updateInfo.getPropertyNameSet(), ms); + registerEventListener(el, session.getRootNode().getPath()); + + String[] hrefs = updateInfo.getVersionHref(); + if (hrefs == null || hrefs.length < 1) { + throw new DavException(DavServletResponse.SC_BAD_REQUEST, "Invalid update request body: at least a single version href must be specified."); + } + // perform the update/restore according to the update info + Version[] versions = new Version[hrefs.length]; + for (int i = 0; i < hrefs.length; i++) { + final String href = normalizeResourceHref(hrefs[i]); + DavResourceLocator vLoc = getLocator().getFactory().createResourceLocator(getLocator().getPrefix(), href); + String versionPath = vLoc.getRepositoryPath(); + Item item = getRepositorySession().getItem(versionPath); + if (item instanceof Version) { + versions[i] = (Version) item; + } else { + throw new DavException(DavServletResponse.SC_BAD_REQUEST, "Invalid update request body: href does not identify a version " + hrefs[i]); + } + } + session.getWorkspace().restore(versions, removeExisting); + + // unregister the event listener again + unregisterEventListener(el); + + } catch (RepositoryException e) { + throw new JcrDavException(e); + } + return ms; + } + + /** + * @throws DavException (403) since workspace is not versionable. implementing + * VersionControlledResource only for 'update'. + */ + @Override + public MultiStatus merge(MergeInfo mergeInfo) throws DavException { + throw new DavException(DavServletResponse.SC_FORBIDDEN); + } + + /** + * @throws DavException (403) since workspace is not versionable. implementing + * VersionControlledResource only for 'update'. + */ + @Override + public void label(LabelInfo labelInfo) throws DavException { + throw new DavException(DavServletResponse.SC_FORBIDDEN); + } + + /** + * @throws DavException (403) since workspace is not versionable. implementing + * VersionControlledResource only for 'update'. + */ + @Override + public VersionHistoryResource getVersionHistory() throws DavException { + throw new DavException(DavServletResponse.SC_FORBIDDEN); + } + + //---------------------------------------------------< AbstractResource >--- + @Override + protected void initLockSupport() { + // lock not allowed + } + + @Override + protected void initSupportedReports() { + super.initSupportedReports(); + supportedReports.addReportType(JcrPrivilegeReport.PRIVILEGES_REPORT); + } + + @Override + protected String getWorkspaceHref() { + return getHref(); + } + + @Override + protected void initPropertyNames() { + super.initPropertyNames(); + names.addAll(JcrDavPropertyNameSet.WORKSPACE_SET); + if (SecurityUtils.supportsAccessControl(getRepositorySession())) { + names.add(SecurityConstants.SUPPORTED_PRIVILEGE_SET); + names.add(SecurityConstants.CURRENT_USER_PRIVILEGE_SET); + } + } + + @Override + protected void initProperties() { + super.initProperties(); + try { + // init workspace specific properties + NamespaceRegistry nsReg = getRepositorySession().getWorkspace().getNamespaceRegistry(); + DavProperty namespacesProp = new NamespacesProperty(nsReg); + properties.add(namespacesProp); + } catch (RepositoryException e) { + log.error("Failed to access NamespaceRegistry: " + e.getMessage()); + } + } +} Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/WorkspaceResourceImpl.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/webdav/jcr/lock/JcrActiveLock.java =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/lock/JcrActiveLock.java (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/lock/JcrActiveLock.java (working copy) @@ -0,0 +1,192 @@ +/* + * 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.webdav.jcr.lock; + +import org.apache.jackrabbit.webdav.DavConstants; +import org.apache.jackrabbit.webdav.jcr.ItemResourceConstants; +import org.apache.jackrabbit.webdav.lock.AbstractActiveLock; +import org.apache.jackrabbit.webdav.lock.ActiveLock; +import org.apache.jackrabbit.webdav.lock.Scope; +import org.apache.jackrabbit.webdav.lock.Type; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.jcr.RepositoryException; +import javax.jcr.lock.Lock; + +/** + * JcrActiveLock wraps a {@link Lock JCR lock} object. + */ +public class JcrActiveLock extends AbstractActiveLock implements ActiveLock, DavConstants { + + private static Logger log = LoggerFactory.getLogger(JcrActiveLock.class); + + private final Lock lock; + + /** + * Create a new ActiveLock object with type '{@link Type#WRITE write}' + * and scope '{@link Scope#EXCLUSIVE exclusive}'. + * + * @param lock + */ + public JcrActiveLock(Lock lock) { + if (lock == null) { + throw new IllegalArgumentException("Can not create a ActiveLock with a 'null' argument."); + } + this.lock = lock; + } + + /** + * Return true if the given lock token equals the token holding that lock. + * + * @param lockToken + * @return true if the given lock token equals this locks token. + * @see org.apache.jackrabbit.webdav.lock.ActiveLock#isLockedByToken(String) + */ + public boolean isLockedByToken(String lockToken) { + if (lockToken != null && lockToken.equals(getToken())) { + return true; + } + return false; + } + + /** + * @see ActiveLock#isExpired() + */ + public boolean isExpired() { + try { + return !lock.isLive(); + } catch (RepositoryException e) { + log.error("Unexpected error: " + e.getMessage()); + return false; + } + } + + /** + * Return the lock token if the {@link javax.jcr.Session} that obtained the lock + * is the lock token holder, null otherwise.
+ * NOTE: currently the token generated by the underlying JCR repository + * is not checked for compliance with RFC 2518 ("OpaqueLockToken-URI = "opaquelocktoken:" + * UUID [Extension] ; The UUID production is the string representation of a + * UUID, as defined in [ISO-11578]. Note that white space (LWS) is not allowed + * between elements of this production."). + *

+ * In case of session-scoped JCR 2.0 locks, the token is never exposed even + * if the current session is lock holder. In order to cope with DAV specific + * requirements and the fulfill the requirement stated above, the node's + * identifier is subsequently exposed as DAV-token. + * + * @see ActiveLock#getToken() + */ + public String getToken() { + try { + return LockTokenMapper.getDavLocktoken(lock); + } catch (RepositoryException e) { + // should never get here + log.warn("Unexpected error while retrieving node identifier for building a DAV specific lock token. {}", + e.getMessage()); + return null; + } + } + + /** + * @see ActiveLock#getOwner() + */ + public String getOwner() { + return lock.getLockOwner(); + } + + /** + * @see ActiveLock#setOwner(String) + */ + public void setOwner(String owner) { + throw new UnsupportedOperationException("setOwner is not implemented"); + } + + /** + * Calculates the milliseconds of the timeout from + * {@link javax.jcr.lock.Lock#getSecondsRemaining()}. If the timeout of + * jcr lock is undefined or infinite {@link #INFINITE_TIMEOUT} is + * returned. + * + * @see ActiveLock#getTimeout() + */ + public long getTimeout() { + try { + long to = lock.getSecondsRemaining(); + long reportAs; + + if (to == Long.MAX_VALUE) { + reportAs = INFINITE_TIMEOUT; + } + else if (to / 1000 <= Long.MAX_VALUE / 1000) { + // expressible as long? + reportAs = to * 1000; + } + else { + reportAs = INFINITE_TIMEOUT; + } + + return reportAs; + } catch (RepositoryException e) { + return INFINITE_TIMEOUT; + } + } + + /** + * Throws UnsupportedOperationException + * + * @see ActiveLock#setTimeout(long) + */ + public void setTimeout(long timeout) { + throw new UnsupportedOperationException("setTimeout is not implemented"); + } + + /** + * @see ActiveLock#isDeep() + */ + public boolean isDeep() { + return lock.isDeep(); + } + + /** + * @see ActiveLock#setIsDeep(boolean) + */ + public void setIsDeep(boolean isDeep) { + throw new UnsupportedOperationException("setIsDeep is not implemented"); + } + + /** + * Always returns {@link Type#WRITE}. + * + * @return {@link Type#WRITE} + * @see ActiveLock#getType() + */ + public Type getType() { + return Type.WRITE; + } + + /** + * @return The scope of this lock, which may either by an {@link Scope#EXCLUSIVE exclusive} + * or {@link ItemResourceConstants#EXCLUSIVE_SESSION exclusive session scoped} + * lock. + * @see ActiveLock#getScope() + */ + public Scope getScope() { + return (lock.isSessionScoped()) ? ItemResourceConstants.EXCLUSIVE_SESSION : Scope.EXCLUSIVE; + } +} Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/lock/JcrActiveLock.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/webdav/jcr/lock/LockTokenMapper.java =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/lock/LockTokenMapper.java (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/lock/LockTokenMapper.java (working copy) @@ -0,0 +1,74 @@ +/* + * 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.webdav.jcr.lock; + +import javax.jcr.RepositoryException; +import javax.jcr.lock.Lock; + +import org.apache.jackrabbit.util.Text; + +/** + * Maps between WebDAV lock tokens and JCR lock tokens. + *

+ * The following notations are used: + * + *

+ * opaquelocktoken:SESSIONSCOPED:NODEIDENTIFIER
+ * opaquelocktoken:OPENSCOPED:JCRLOCKTOKEN
+ * 
+ * + * The first format is used if the JCR lock does not reveal a lock token, such + * as when it is a session-scoped lock (where SESSIONSCOPED is a constant UUID + * defined below, and NODEIDENTIFIER is the suitably escaped JCR Node + * identifier). + *

+ * The second format is used for open-scoped locks (where OPENSCOPED is another + * constant UUID defined below, and JCRLOCKTOKEN is the suitably escaped JCR + * lock token). + */ +public class LockTokenMapper { + + private static final String OL = "opaquelocktoken:"; + + private static final String SESSIONSCOPED = "4403ef44-4124-11e1-b965-00059a3c7a00"; + private static final String OPENSCOPED = "dccce564-412e-11e1-b969-00059a3c7a00"; + + private static final String SESSPREFIX = OL + SESSIONSCOPED + ":"; + private static final String OPENPREFIX = OL + OPENSCOPED + ":"; + + public static String getDavLocktoken(Lock lock) throws RepositoryException { + String jcrLockToken = lock.getLockToken(); + + if (jcrLockToken == null) { + return SESSPREFIX + Text.escape(lock.getNode().getIdentifier()); + } else { + return OPENPREFIX + Text.escape(jcrLockToken); + } + } + + public static String getJcrLockToken(String token) throws RepositoryException { + if (token.startsWith(OPENPREFIX)) { + return Text.unescape(token.substring(OPENPREFIX.length())); + } else { + throw new RepositoryException("not a token for an open-scoped JCR lock: " + token); + } + } + + public static boolean isForSessionScopedLock(String token) { + return token.startsWith(SESSPREFIX); + } +} Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/lock/LockTokenMapper.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/webdav/jcr/lock/SessionScopedLockEntry.java =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/lock/SessionScopedLockEntry.java (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/lock/SessionScopedLockEntry.java (working copy) @@ -0,0 +1,50 @@ +/* + * 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.webdav.jcr.lock; + +import org.apache.jackrabbit.webdav.jcr.ItemResourceConstants; +import org.apache.jackrabbit.webdav.lock.AbstractLockEntry; +import org.apache.jackrabbit.webdav.lock.LockEntry; +import org.apache.jackrabbit.webdav.lock.Scope; +import org.apache.jackrabbit.webdav.lock.Type; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * SessionScopedLockEntry represents the 'session-scoped' write + * lock as defined by JCR. + */ +public class SessionScopedLockEntry extends AbstractLockEntry { + + private static Logger log = LoggerFactory.getLogger(SessionScopedLockEntry.class); + + /** + * @return always returns {@link Type#WRITE write}. + * @see LockEntry#getType() + */ + public Type getType() { + return Type.WRITE; + } + + /** + * @return returns {@link ItemResourceConstants#EXCLUSIVE_SESSION}. + * @see LockEntry#getScope() + */ + public Scope getScope() { + return ItemResourceConstants.EXCLUSIVE_SESSION; + } +} \ No newline at end of file Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/lock/SessionScopedLockEntry.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/webdav/jcr/nodetype/ItemDefinitionImpl.java =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/nodetype/ItemDefinitionImpl.java (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/nodetype/ItemDefinitionImpl.java (working copy) @@ -0,0 +1,126 @@ +/* + * 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.webdav.jcr.nodetype; + +import org.apache.jackrabbit.commons.webdav.NodeTypeConstants; +import org.apache.jackrabbit.webdav.xml.XmlSerializable; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +import javax.jcr.nodetype.ItemDefinition; +import javax.jcr.nodetype.NodeType; +import javax.jcr.version.OnParentVersionAction; + +/** + * ItemDefinitionImpl... + */ +abstract public class ItemDefinitionImpl implements ItemDefinition, NodeTypeConstants, XmlSerializable { + + private static Logger log = LoggerFactory.getLogger(ItemDefinitionImpl.class); + + private final String name; + private NodeType declaringNodeType; + private final boolean isAutoCreated; + private final boolean isMandatory; + private final boolean isProtected; + private final int onParentVersion; + + ItemDefinitionImpl(ItemDefinition definition) { + if (definition == null) { + throw new IllegalArgumentException("PropDef argument can not be null"); + } + name = definition.getName(); + declaringNodeType = definition.getDeclaringNodeType(); + isAutoCreated = definition.isAutoCreated(); + isMandatory = definition.isMandatory(); + isProtected = definition.isProtected(); + onParentVersion = definition.getOnParentVersion(); + } + + /** + * @see ItemDefinition#getDeclaringNodeType() + */ + public NodeType getDeclaringNodeType() { + return declaringNodeType; + } + + /** + * @see ItemDefinition#getName() + */ + public String getName() { + return name; + } + + /** + * @see ItemDefinition#isAutoCreated() + */ + public boolean isAutoCreated() { + return isAutoCreated; + } + + /** + * @see ItemDefinition#isMandatory() + */ + public boolean isMandatory() { + return isMandatory; + } + + /** + * @see ItemDefinition#getOnParentVersion() + */ + public int getOnParentVersion() { + return onParentVersion; + } + + /** + * @see ItemDefinition#isProtected() + */ + public boolean isProtected() { + return isProtected; + } + + //------------------------------------------< XmlSerializable interface >--- + /** + * Returns the Xml representation of a {@link ItemDefinition} object. + * + * @return Xml representation of the specified {@link ItemDefinition def}. + * @param document + */ + public Element toXml(Document document) { + Element elem = document.createElement(getElementName()); + NodeType dnt = getDeclaringNodeType(); + if (dnt != null) { + elem.setAttribute(DECLARINGNODETYPE_ATTRIBUTE, dnt.getName()); + } + elem.setAttribute(NAME_ATTRIBUTE, getName()); + elem.setAttribute(AUTOCREATED_ATTRIBUTE, Boolean.toString(isAutoCreated())); + elem.setAttribute(MANDATORY_ATTRIBUTE, Boolean.toString(isMandatory())); + elem.setAttribute(ONPARENTVERSION_ATTRIBUTE, OnParentVersionAction.nameFromValue(getOnParentVersion())); + elem.setAttribute(PROTECTED_ATTRIBUTE, Boolean.toString(isProtected())); + return elem; + } + + //-------------------------------------< implementation specific method >--- + /** + * Returns the name of the root element + * + * @return the name of the root element + */ + abstract String getElementName(); +} \ No newline at end of file Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/nodetype/ItemDefinitionImpl.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/webdav/jcr/nodetype/NodeDefinitionImpl.java =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/nodetype/NodeDefinitionImpl.java (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/nodetype/NodeDefinitionImpl.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.webdav.jcr.nodetype; + +import org.apache.jackrabbit.webdav.xml.DomUtil; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +import javax.jcr.nodetype.NodeDefinition; +import javax.jcr.nodetype.NodeType; + +/** + * NodeDefinitionImpl... + */ +public final class NodeDefinitionImpl extends ItemDefinitionImpl implements NodeDefinition { + + private static Logger log = LoggerFactory.getLogger(NodeDefinitionImpl.class); + + private final NodeType[] requiredPrimaryTypes; + private final NodeType defaultPrimaryType; + private final boolean allowsSameNameSiblings; + + private NodeDefinitionImpl(NodeDefinition definition) { + super(definition); + + requiredPrimaryTypes = definition.getRequiredPrimaryTypes(); + defaultPrimaryType = definition.getDefaultPrimaryType(); + allowsSameNameSiblings = definition.allowsSameNameSiblings(); + } + + public static NodeDefinitionImpl create(NodeDefinition definition) { + if (definition instanceof NodeDefinitionImpl) { + return (NodeDefinitionImpl) definition; + } else { + return new NodeDefinitionImpl(definition); + } + } + + //-----------------------------------------------------< NodeDefinition >--- + /** + * @see javax.jcr.nodetype.NodeDefinition#getRequiredPrimaryTypes() + */ + public NodeType[] getRequiredPrimaryTypes() { + return requiredPrimaryTypes; + } + + /** + * @see javax.jcr.nodetype.NodeDefinition#getDefaultPrimaryType() + */ + public NodeType getDefaultPrimaryType() { + return defaultPrimaryType; + } + + /** + * @see javax.jcr.nodetype.NodeDefinition#allowsSameNameSiblings() + */ + public boolean allowsSameNameSiblings() { + return allowsSameNameSiblings; + } + + /** + * @see javax.jcr.nodetype.NodeDefinition#getDefaultPrimaryTypeName() + */ + public String getDefaultPrimaryTypeName() { + return defaultPrimaryType.getName(); + } + + /** + * @see javax.jcr.nodetype.NodeDefinition#getRequiredPrimaryTypeNames() + */ + public String[] getRequiredPrimaryTypeNames() { + String[] names = new String[requiredPrimaryTypes.length]; + for (int i = 0; i < requiredPrimaryTypes.length; i++) { + names[i] = requiredPrimaryTypes[i].getName(); + } + return names; + } + + //-------------------------------------< implementation specific method >--- + /** + * Returns xml representation + * + * @return xml representation + * @param document + */ + @Override + public Element toXml(Document document) { + Element elem = super.toXml(document); + elem.setAttribute(SAMENAMESIBLINGS_ATTRIBUTE, Boolean.toString(allowsSameNameSiblings())); + // defaultPrimaryType can be 'null' + NodeType defaultPrimaryType = getDefaultPrimaryType(); + if (defaultPrimaryType != null) { + elem.setAttribute(DEFAULTPRIMARYTYPE_ATTRIBUTE, defaultPrimaryType.getName()); + } + // reqPrimaryTypes: minimal set is nt:base. + Element reqPrimaryTypes = document.createElement(REQUIREDPRIMARYTYPES_ELEMENT); + for (NodeType nt : getRequiredPrimaryTypes()) { + Element rptElem = document.createElement(REQUIREDPRIMARYTYPE_ELEMENT); + DomUtil.setText(rptElem, nt.getName()); + reqPrimaryTypes.appendChild(rptElem); + + } + elem.appendChild(reqPrimaryTypes); + return elem; + } + + /** + * Returns {@link #CHILDNODEDEFINITION_ELEMENT} + * + * @return always returns {@link #CHILDNODEDEFINITION_ELEMENT}. + */ + @Override + String getElementName() { + return CHILDNODEDEFINITION_ELEMENT; + } + +} Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/nodetype/NodeDefinitionImpl.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/webdav/jcr/nodetype/NodeTypeProperty.java =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/nodetype/NodeTypeProperty.java (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/nodetype/NodeTypeProperty.java (working copy) @@ -0,0 +1,105 @@ +/* + * 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.webdav.jcr.nodetype; + +import org.apache.jackrabbit.commons.webdav.NodeTypeConstants; +import org.apache.jackrabbit.commons.webdav.NodeTypeUtil; +import org.apache.jackrabbit.webdav.property.AbstractDavProperty; +import org.apache.jackrabbit.webdav.property.DavProperty; +import org.apache.jackrabbit.webdav.property.DavPropertyName; +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +import javax.jcr.nodetype.NodeType; +import java.util.Collections; +import java.util.HashSet; +import java.util.Set; + +/** + * NodeTypeProperty... + */ +public class NodeTypeProperty extends AbstractDavProperty> implements NodeTypeConstants { + + private final Set nodetypeNames = new HashSet(); + + public NodeTypeProperty(DavPropertyName name, NodeType nodeType, boolean isProtected) { + this(name, new NodeType[]{nodeType}, isProtected); + } + + public NodeTypeProperty(DavPropertyName name, NodeType[] nodeTypes, boolean isProtected) { + super(name, isProtected); + for (NodeType nt : nodeTypes) { + if (nt != null) { + nodetypeNames.add(nt.getName()); + } + } + } + + public NodeTypeProperty(DavPropertyName name, String[] nodeTypeNames, boolean isProtected) { + super(name, isProtected); + for (String nodeTypeName : nodeTypeNames) { + if (nodeTypeName != null) { + nodetypeNames.add(nodeTypeName); + } + } + } + + /** + * Create a new NodeTypeProperty from the specified general + * DavProperty object. + * + * @param property + */ + public NodeTypeProperty(DavProperty property) { + super(property.getName(), property.isInvisibleInAllprop()); + if (property instanceof NodeTypeProperty) { + nodetypeNames.addAll(((NodeTypeProperty) property).nodetypeNames); + } else { + nodetypeNames.addAll(NodeTypeUtil.ntNamesFromXml(property.getValue())); + } + } + + /** + * Return a set of node type names present in this property. + * + * @return set of node type names + */ + public Set getNodeTypeNames() { + return Collections.unmodifiableSet(nodetypeNames); + } + + /** + * Returns the value of this property which is a Set of nodetype names. + * + * @return a Set of nodetype names (String). + */ + public Set getValue() { + return Collections.unmodifiableSet(nodetypeNames); + } + + /** + * @see org.apache.jackrabbit.webdav.xml.XmlSerializable#toXml(Document) + */ + @Override + public Element toXml(Document document) { + Element elem = getName().toXml(document); + for (String name : getNodeTypeNames()) { + elem.appendChild(NodeTypeUtil.ntNameToXml(name, document)); + } + return elem; + } +} Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/nodetype/NodeTypeProperty.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/webdav/jcr/nodetype/PropertyDefinitionImpl.java =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/nodetype/PropertyDefinitionImpl.java (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/nodetype/PropertyDefinitionImpl.java (working copy) @@ -0,0 +1,179 @@ +/* + * 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.webdav.jcr.nodetype; + +import org.apache.jackrabbit.webdav.xml.DomUtil; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +import javax.jcr.PropertyType; +import javax.jcr.RepositoryException; +import javax.jcr.Value; +import javax.jcr.nodetype.PropertyDefinition; + +/** + * PropertyDefinitionImpl... + */ +public final class PropertyDefinitionImpl extends ItemDefinitionImpl implements PropertyDefinition { + + private static Logger log = LoggerFactory.getLogger(PropertyDefinitionImpl.class); + + private final int type; + private final String[] valueConstraints; + private final Value[] defaultValues; + private final boolean isMultiple; + private final String[] availableQueryOperators; + private final boolean isFullTextSearchable; + private final boolean isQueryOrderable; + + private PropertyDefinitionImpl(PropertyDefinition definition) { + super(definition); + + type = definition.getRequiredType(); + valueConstraints = definition.getValueConstraints(); + defaultValues = definition.getDefaultValues(); + isMultiple = definition.isMultiple(); + availableQueryOperators = definition.getAvailableQueryOperators(); + isFullTextSearchable = definition.isFullTextSearchable(); + isQueryOrderable = definition.isQueryOrderable(); + } + + public static PropertyDefinitionImpl create(PropertyDefinition definition) { + if (definition instanceof PropertyDefinitionImpl) { + return (PropertyDefinitionImpl)definition; + } else { + return new PropertyDefinitionImpl(definition); + } + } + + //----------------------------------------< PropertyDefintion interface >--- + /** + * @see PropertyDefinition#getRequiredType() + */ + public int getRequiredType() { + return type; + } + + /** + * @see PropertyDefinition#getValueConstraints() + */ + public String[] getValueConstraints() { + return valueConstraints; + } + + /** + * @see PropertyDefinition#getDefaultValues() + */ + public Value[] getDefaultValues() { + return defaultValues; + } + + /** + * @see PropertyDefinition#isMultiple() + */ + public boolean isMultiple() { + return isMultiple; + } + + /** + * @see PropertyDefinition#getAvailableQueryOperators() + */ + public String[] getAvailableQueryOperators() { + return availableQueryOperators; + } + + /** + * @see PropertyDefinition#isFullTextSearchable() + */ + public boolean isFullTextSearchable() { + return isFullTextSearchable; + } + + /** + * @see PropertyDefinition#isQueryOrderable() + */ + public boolean isQueryOrderable() { + return isQueryOrderable; + } + + //-------------------------------------< implementation specific method >--- + /** + * Return xml representation + * + * @return xml representation + * @param document + */ + @Override + public Element toXml(Document document) { + Element elem = super.toXml(document); + + elem.setAttribute(MULTIPLE_ATTRIBUTE, Boolean.toString(isMultiple())); + elem.setAttribute(REQUIREDTYPE_ATTRIBUTE, PropertyType.nameFromValue(getRequiredType())); + + // JCR 2.0 extensions + elem.setAttribute(FULL_TEXT_SEARCHABLE_ATTRIBUTE, Boolean.toString(isFullTextSearchable())); + elem.setAttribute(QUERY_ORDERABLE_ATTRIBUTE, Boolean.toString(isQueryOrderable())); + + // default values may be 'null' + Value[] values = getDefaultValues(); + if (values != null) { + Element dvElement = document.createElement(DEFAULTVALUES_ELEMENT); + for (Value value : values) { + try { + Element valElem = document.createElement(DEFAULTVALUE_ELEMENT); + DomUtil.setText(valElem, value.getString()); + dvElement.appendChild(valElem); + } catch (RepositoryException e) { + // should not occur + log.error(e.getMessage()); + } + } + elem.appendChild(dvElement); + } + // value constraints array is never null. + Element constrElem = document.createElement(VALUECONSTRAINTS_ELEMENT); + for (String constraint : getValueConstraints()) { + Element vcElem = document.createElement(VALUECONSTRAINT_ELEMENT); + DomUtil.setText(vcElem, constraint); + constrElem.appendChild(vcElem); + } + elem.appendChild(constrElem); + + // JCR 2.0 extension + Element qopElem = document.createElement(AVAILABLE_QUERY_OPERATORS_ELEMENT); + for (String qop : getAvailableQueryOperators()) { + Element opElem = document.createElement(AVAILABLE_QUERY_OPERATOR_ELEMENT); + DomUtil.setText(opElem, qop); + qopElem.appendChild(opElem); + } + elem.appendChild(qopElem); + + return elem; + } + + /** + * Returns {@link #PROPERTYDEFINITION_ELEMENT}. + * + * @return always returns {@link #PROPERTYDEFINITION_ELEMENT} + */ + @Override + String getElementName() { + return PROPERTYDEFINITION_ELEMENT; + } +} Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/nodetype/PropertyDefinitionImpl.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/webdav/jcr/observation/SubscriptionImpl.java =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/observation/SubscriptionImpl.java (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/observation/SubscriptionImpl.java (working copy) @@ -0,0 +1,637 @@ +/* + * 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.webdav.jcr.observation; + +import org.apache.jackrabbit.commons.webdav.EventUtil; +import org.apache.jackrabbit.commons.webdav.JcrRemotingConstants; +import org.apache.jackrabbit.spi.Name; +import org.apache.jackrabbit.spi.commons.AdditionalEventInfo; +import org.apache.jackrabbit.spi.commons.SessionExtensions; +import org.apache.jackrabbit.webdav.DavException; +import org.apache.jackrabbit.webdav.DavResourceLocator; +import org.apache.jackrabbit.webdav.DavServletResponse; +import org.apache.jackrabbit.webdav.transaction.TransactionResource; +import org.apache.jackrabbit.webdav.jcr.transaction.TransactionListener; +import org.apache.jackrabbit.webdav.jcr.JcrDavException; +import org.apache.jackrabbit.webdav.jcr.JcrDavSession; +import org.apache.jackrabbit.webdav.observation.EventBundle; +import org.apache.jackrabbit.webdav.observation.EventDiscovery; +import org.apache.jackrabbit.webdav.observation.EventType; +import org.apache.jackrabbit.webdav.observation.Filter; +import org.apache.jackrabbit.webdav.observation.ObservationConstants; +import org.apache.jackrabbit.webdav.observation.ObservationResource; +import org.apache.jackrabbit.webdav.observation.Subscription; +import org.apache.jackrabbit.webdav.observation.SubscriptionInfo; +import org.apache.jackrabbit.webdav.observation.DefaultEventType; +import org.apache.jackrabbit.webdav.xml.DomUtil; +import org.apache.jackrabbit.webdav.xml.Namespace; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +import javax.jcr.RepositoryException; +import javax.jcr.Session; +import javax.jcr.UnsupportedRepositoryOperationException; +import javax.jcr.observation.Event; +import javax.jcr.observation.EventIterator; +import javax.jcr.observation.EventListener; +import javax.jcr.observation.ObservationManager; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.UUID; + +/** + * The Subscription class encapsulates a single subscription with + * the following responsibilities:

    + *
  • Providing access to the subscription info,
  • + *
  • Recording events this subscription is interested in,
  • + *
  • Providing access to the events.
  • + *
+ */ +public class SubscriptionImpl implements Subscription, ObservationConstants, EventListener { + + private static Logger log = LoggerFactory.getLogger(SubscriptionImpl.class); + private static final long DEFAULT_TIMEOUT = 300000; // 5 minutes + + private SubscriptionInfo info; + private long expirationTime; + + private final DavResourceLocator locator; + private final String subscriptionId = UUID.randomUUID().toString(); + private final List eventBundles = new ArrayList(); + private final ObservationManager obsMgr; + private final Session session; + + /** + * Create a new Subscription with the given {@link SubscriptionInfo} + * and {@link org.apache.jackrabbit.webdav.observation.ObservationResource resource}. + * + * @param info + * @param resource + * @throws DavException if resource is not based on a JCR repository or + * the repository does not support observation. + */ + public SubscriptionImpl(SubscriptionInfo info, ObservationResource resource) + throws DavException { + setInfo(info); + locator = resource.getLocator(); + session = JcrDavSession.getRepositorySession(resource.getSession()); + try { + obsMgr = session.getWorkspace().getObservationManager(); + } catch (RepositoryException e) { + throw new DavException(DavServletResponse.SC_INTERNAL_SERVER_ERROR, e); + } + } + + //-------------------------------------------------------< Subscription >--- + /** + * Returns the id of this subscription. + * + * @return subscriptionId + */ + public String getSubscriptionId() { + return subscriptionId; + } + + public boolean eventsProvideNodeTypeInformation() { + String t = session.getRepository().getDescriptor("org.apache.jackrabbit.spi.commons.AdditionalEventInfo"); + return t == null ? false : Boolean.parseBoolean(t); + } + + public boolean eventsProvideNoLocalFlag() { + return session instanceof SessionExtensions; + } + + //----------------------------------------------------< XmlSerializable >--- + /** + * Return the Xml representation of this Subscription as required + * for the {@link org.apache.jackrabbit.webdav.observation.SubscriptionDiscovery} + * webdav property that in included in the response body of a successful SUBSCRIBE + * request or as part of a PROPFIND response. + * + * @return Xml representation + * @see org.apache.jackrabbit.webdav.xml.XmlSerializable#toXml(Document) + * @param document + */ + public Element toXml(Document document) { + Element subscr = DomUtil.createElement(document, XML_SUBSCRIPTION, NAMESPACE); + + subscr.appendChild(info.toXml(document)); + subscr.appendChild(DomUtil.depthToXml(info.isDeep(), document)); + subscr.appendChild(DomUtil.timeoutToXml(info.getTimeOut(), document)); + + if (getSubscriptionId() != null) { + Element id = DomUtil.addChildElement(subscr, XML_SUBSCRIPTIONID, NAMESPACE); + id.appendChild(DomUtil.hrefToXml(getSubscriptionId(), document)); + } + + DomUtil.addChildElement(subscr, XML_EVENTSWITHTYPES, NAMESPACE, + Boolean.toString(eventsProvideNodeTypeInformation())); + DomUtil.addChildElement(subscr, XML_EVENTSWITHLOCALFLAG, NAMESPACE, + Boolean.toString(eventsProvideNoLocalFlag())); + + return subscr; + } + + //--------------------------------------------< implementation specific >--- + /** + * Modify the {@link SubscriptionInfo} for this subscription. + * + * @param info + */ + void setInfo(SubscriptionInfo info) { + this.info = info; + // validate the timeout and adjust value, if it is invalid or missing + long timeout = info.getTimeOut(); + if (timeout <= 0) { + timeout = DEFAULT_TIMEOUT; + } + expirationTime = System.currentTimeMillis() + timeout; + } + + /** + * @return JCR compliant integer representation of the event types defined + * for this {@link SubscriptionInfo}. + */ + int getJcrEventTypes() throws DavException { + EventType[] eventTypes = info.getEventTypes(); + int events = 0; + for (EventType eventType : eventTypes) { + events |= getJcrEventType(eventType); + } + return events; + } + + /** + * @return a String array with size > 0 or null + */ + String[] getUuidFilters() { + return getFilterValues(XML_UUID); + } + + /** + * @return a String array with size > 0 or null + */ + String[] getNodetypeNameFilters() { + return getFilterValues(XML_NODETYPE_NAME); + } + + private String[] getFilterValues(String filterLocalName) { + List values = new ArrayList(); + for (Filter filter : info.getFilters(filterLocalName, NAMESPACE)) { + String val = filter.getValue(); + if (val != null) { + values.add(val); + } + } + return (values.size() > 0) ? values.toArray(new String[values.size()]) : null; + } + + /** + * + * @return true if a {@link ObservationConstants#XML_NOLOCAL} element + * is present in the {@link SubscriptionInfo}. + */ + boolean isNoLocal() { + return info.isNoLocal(); + } + + /** + * @return true if this subscription is intended to be deep. + */ + boolean isDeep() { + return info.isDeep(); + } + + /** + * @return the locator of the {@link ObservationResource resource} this + * Subscription was requested for. + */ + DavResourceLocator getLocator() { + return locator; + } + + /** + * Returns true if this Subscription matches the given + * resource. + * + * @param resource + * @return true if this Subscription matches the given + * resource. + */ + boolean isSubscribedToResource(ObservationResource resource) { + return locator.getResourcePath().equals(resource.getResourcePath()); + } + + /** + * Returns true if this Subscription is expired and therefore + * stopped recording events. + * + * @return true if this Subscription is expired + */ + boolean isExpired() { + return System.currentTimeMillis() > expirationTime; + } + + /** + * Returns a {@link org.apache.jackrabbit.webdav.observation.EventDiscovery} object listing all events that were + * recorded since the last call to this method and clears the list of event + * bundles. + * + * @param timeout time in milliseconds to wait at most for events if none + * are present currently. + * @return object listing all events that were recorded. + * @see #onEvent(EventIterator) + */ + synchronized EventDiscovery discoverEvents(long timeout) { + EventDiscovery ed = new EventDiscovery(); + if (eventBundles.isEmpty() && timeout > 0) { + try { + wait(timeout); + } catch (InterruptedException e) { + // continue and possibly return empty event discovery + } + } + for (EventBundle eb : eventBundles) { + ed.addEventBundle(eb); + } + // clear list + eventBundles.clear(); + return ed; + } + + /** + * Creates a new transaction listener for the scope of a transaction + * commit (save call). + * @return a transaction listener for this subscription. + */ + TransactionListener createTransactionListener() { + if (info.isNoLocal()) { + // a subscription which is not interested in local changes does + // not need the transaction id + return new TransactionEvent() { + @Override + public void onEvent(EventIterator events) { + // ignore + } + + @Override + public void beforeCommit(TransactionResource resource, String lockToken) { + // ignore + } + + @Override + public void afterCommit(TransactionResource resource, + String lockToken, + boolean success) { + // ignore + } + }; + } else { + return new TransactionEvent(); + } + } + + /** + * Suspend this subscription. This call will remove this subscription as + * event listener from the observation manager. + */ + void suspend() throws DavException { + try { + obsMgr.removeEventListener(this); + } catch (RepositoryException e) { + throw new JcrDavException(e); + } + } + + /** + * Resumes this subscription. This call will register this subscription + * again as event listener to the observation manager. + */ + void resume() throws DavException { + try { + obsMgr.addEventListener(this, getJcrEventTypes(), + getLocator().getRepositoryPath(), isDeep(), getUuidFilters(), + getNodetypeNameFilters(), isNoLocal()); + } catch (RepositoryException e) { + throw new JcrDavException(e); + } + } + + //--------------------------------------------< EventListener interface >--- + /** + * Records the events passed as a new event bundle in order to make them + * available with the next {@link #discoverEvents(long)} request. If this + * subscription is expired it will remove itself as listener from the + * observation manager. + * + * @param events to be recorded. + * @see EventListener#onEvent(EventIterator) + * @see #discoverEvents(long) + */ + public synchronized void onEvent(EventIterator events) { + if (!isExpired()) { + eventBundles.add(new EventBundleImpl(events)); + } else { + // expired -> unsubscribe + try { + obsMgr.removeEventListener(this); + } catch (RepositoryException e) { + log.warn("Exception while unsubscribing: " + e); + } + } + notifyAll(); + } + + //-------------------------------------------------------------------------- + /** + * Static utility method to convert the type defined by a + * {@link javax.jcr.observation.Event JCR event} into an EventType + * object. + * + * @param jcrEventType + * @return EventType representation of the given JCR event type. + * @throws IllegalArgumentException if the given int does not represent a + * valid type constants as defined by {@link Event}.
+ * Valid values are + *
    + *
  • {@link Event#NODE_ADDED}
  • + *
  • {@link Event#NODE_REMOVED}
  • + *
  • {@link Event#PROPERTY_ADDED}
  • + *
  • {@link Event#PROPERTY_REMOVED}
  • + *
  • {@link Event#PROPERTY_CHANGED}
  • + *
  • {@link Event#NODE_MOVED}
  • + *
  • {@link Event#PERSIST}
  • + *
+ */ + public static EventType getEventType(int jcrEventType) { + String localName = EventUtil.getEventName(jcrEventType); + return DefaultEventType.create(localName, NAMESPACE); + } + + /** + * @return The DAV event type representation for all known JCR event types. + */ + public static EventType[] getAllEventTypes() { + EventType[] types = DefaultEventType.create(EventUtil.EVENT_ALL, NAMESPACE); + return types; + } + + /** + * Static utility method to convert an EventType as present in + * the Xml body into the corresponding JCR event constant defined by + * {@link javax.jcr.observation.Event}. + * + * @param eventType + * @return Any of the event types defined by {@link Event}.
+ * Possible values are + *
    + *
  • {@link Event#NODE_ADDED}
  • + *
  • {@link Event#NODE_REMOVED}
  • + *
  • {@link Event#PROPERTY_ADDED}
  • + *
  • {@link Event#PROPERTY_REMOVED}
  • + *
  • {@link Event#PROPERTY_CHANGED}
  • + *
  • {@link Event#NODE_MOVED}
  • + *
  • {@link Event#PERSIST}
  • + *
+ * @throws DavException if the given event type does not define a valid + * JCR event type, such as returned by {@link #getEventType(int)}. + */ + public static int getJcrEventType(EventType eventType) throws DavException { + if (eventType == null || !NAMESPACE.equals(eventType.getNamespace())) { + throw new DavException(DavServletResponse.SC_UNPROCESSABLE_ENTITY, "Invalid JCR event type: "+ eventType + ": Namespace mismatch."); + } + String eventName = eventType.getName(); + if (!EventUtil.isValidEventName(eventName)) { + throw new DavException(DavServletResponse.SC_UNPROCESSABLE_ENTITY, "Invalid event type: "+eventName); + } + return EventUtil.getJcrEventType(eventName); + } + + /** + * Inner class EventBundle encapsulates an event bundle as + * recorded {@link SubscriptionImpl#onEvent(EventIterator) on event} and + * provides the possibility to retrieve the Xml representation of the + * bundle and the events included in order to respond to a POLL request. + * + * @see SubscriptionImpl#discoverEvents(long) + */ + private class EventBundleImpl implements EventBundle { + + private final EventIterator events; + + private final String transactionId; + + private EventBundleImpl(EventIterator events) { + this(events, null); + } + + private EventBundleImpl(EventIterator events, String transactionId) { + this.events = events; + this.transactionId = transactionId; + } + + public Element toXml(Document document) { + Element bundle = DomUtil.createElement(document, XML_EVENTBUNDLE, NAMESPACE); + // TODO: this appears to be unused now + if (transactionId != null) { + DomUtil.setAttribute(bundle, XML_EVENT_TRANSACTION_ID, NAMESPACE, transactionId); + } + + boolean localFlagSet = false; + + while (events.hasNext()) { + Event event = events.nextEvent(); + + if (!localFlagSet) { + // obtain remote session identifier + localFlagSet = true; + String name = JcrRemotingConstants.RELATION_REMOTE_SESSION_ID; + Object forSessionId = session.getAttribute(name); + // calculate "local" flags + if (forSessionId != null + && event instanceof AdditionalEventInfo) { + AdditionalEventInfo aei = (AdditionalEventInfo) event; + try { + boolean isLocal = forSessionId.equals( + aei.getSessionAttribute(name)); + DomUtil.setAttribute( + bundle, XML_EVENT_LOCAL, null, + Boolean.toString(isLocal)); + } catch (UnsupportedRepositoryOperationException ex) { + // optional feature + } + } + } + + Element eventElem = DomUtil.addChildElement(bundle, XML_EVENT, NAMESPACE); + // href + String eHref = ""; + try { + boolean isCollection = (event.getType() == Event.NODE_ADDED || event.getType() == Event.NODE_REMOVED); + eHref = locator.getFactory().createResourceLocator(locator.getPrefix(), locator.getWorkspacePath(), event.getPath(), false).getHref(isCollection); + } catch (RepositoryException e) { + // should not occur.... + log.error(e.getMessage()); + } + eventElem.appendChild(DomUtil.hrefToXml(eHref, document)); + // event type + Element eType = DomUtil.addChildElement(eventElem, XML_EVENTTYPE, NAMESPACE); + eType.appendChild(getEventType(event.getType()).toXml(document)); + // user id + DomUtil.addChildElement(eventElem, XML_EVENTUSERID, NAMESPACE, event.getUserID()); + + // try to compute nodetype information + if (event instanceof AdditionalEventInfo) { + try { + DomUtil.addChildElement(eventElem, + XML_EVENTPRIMARNODETYPE, NAMESPACE, + ((AdditionalEventInfo) event) + .getPrimaryNodeTypeName().toString()); + for (Name mixin : ((AdditionalEventInfo) event) + .getMixinTypeNames()) { + DomUtil.addChildElement(eventElem, + XML_EVENTMIXINNODETYPE, NAMESPACE, + mixin.toString()); + } + } catch (UnsupportedRepositoryOperationException ex) { + // optional + } + } + + // Additional JCR 2.0 event information + // user data + try { + DomUtil.addChildElement(eventElem, XML_EVENTUSERDATA, NAMESPACE, event.getUserData()); + } catch (RepositoryException e) { + log.error("Internal error while retrieving event user data. {}", e.getMessage()); + } + // time stamp + try { + DomUtil.addChildElement(eventElem, XML_EVENTDATE, NAMESPACE, String.valueOf(event.getDate())); + } catch (RepositoryException e) { + log.error("Internal error while retrieving event date. {}", e.getMessage()); + } + // identifier + try { + DomUtil.addChildElement(eventElem, XML_EVENTIDENTIFIER, NAMESPACE, event.getIdentifier()); + } catch (RepositoryException e) { + log.error("Internal error while retrieving event identifier. {}", e.getMessage()); + } + // info + try { + serializeInfoMap(eventElem, session, event.getInfo()); + } catch (RepositoryException e) { + log.error("Internal error while retrieving event info. {}", e.getMessage()); + } + } + return bundle; + } + } + + protected static void serializeInfoMap(Element eventElem, Session session, Map map) { + // info + Element info = DomUtil.addChildElement(eventElem, XML_EVENTINFO, NAMESPACE); + Map m = map; + for (Map.Entry entry : m.entrySet()) { + try { + String key = entry.getKey().toString(); + Namespace ns = Namespace.EMPTY_NAMESPACE; + int colon = key.indexOf(':'); + if (colon >= 0) { + String prefix = key.substring(0, colon); + String localname = key.substring(colon + 1); + ns = Namespace.getNamespace(prefix, session.getNamespaceURI(prefix)); + key = localname; + } + Object value = entry.getValue(); + if (value != null) { + DomUtil.addChildElement(info, key, ns, value.toString()); + } else { + DomUtil.addChildElement(info, key, ns); + } + } catch (RepositoryException nse) { + log.error("Internal error while getting namespaceUri, info map field skipped for {}", entry.getKey()); + } + } + } + + //----------------------------< TransactionEvent >------------------------ + + /** + * Implements a transaction event which listeners for events during a save + * call on the repository. + */ + private class TransactionEvent implements EventListener, TransactionListener { + + private String transactionId; + + /** + * {@inheritDoc} + */ + public void onEvent(EventIterator events) { + String tId = transactionId; + if (tId == null) { + tId = UUID.randomUUID().toString(); + } + synchronized (SubscriptionImpl.this) { + eventBundles.add(new EventBundleImpl(events, tId)); + SubscriptionImpl.this.notifyAll(); + } + } + + //-----------------------------< TransactionListener >------------------ + + /** + * {@inheritDoc} + */ + public void beforeCommit(TransactionResource resource, String lockToken) { + try { + transactionId = lockToken; + obsMgr.addEventListener(this, getJcrEventTypes(), + getLocator().getRepositoryPath(), isDeep(), getUuidFilters(), + getNodetypeNameFilters(), isNoLocal()); + // suspend the subscription + suspend(); + } catch (RepositoryException e) { + log.warn("Unable to register TransactionListener: " + e); + } catch (DavException e) { + log.warn("Unable to register TransactionListener: " + e); + } + } + + /** + * {@inheritDoc} + */ + public void afterCommit(TransactionResource resource, + String lockToken, + boolean success) { + try { + // resume the subscription + resume(); + // remove this transaction event + obsMgr.removeEventListener(this); + } catch (RepositoryException e) { + log.warn("Unable to remove listener: " + e); + } catch (DavException e) { + log.warn("Unable to resume Subscription: " + e); + } + } + } +} Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/observation/SubscriptionImpl.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/webdav/jcr/observation/SubscriptionManagerImpl.java =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/observation/SubscriptionManagerImpl.java (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/observation/SubscriptionManagerImpl.java (working copy) @@ -0,0 +1,358 @@ +/* + * 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.webdav.jcr.observation; + +import org.apache.jackrabbit.webdav.DavException; +import org.apache.jackrabbit.webdav.DavResourceLocator; +import org.apache.jackrabbit.webdav.DavServletResponse; +import org.apache.jackrabbit.webdav.transaction.TransactionResource; +import org.apache.jackrabbit.webdav.jcr.JcrDavException; +import org.apache.jackrabbit.webdav.jcr.JcrDavSession; +import org.apache.jackrabbit.webdav.jcr.transaction.TransactionListener; +import org.apache.jackrabbit.webdav.observation.EventDiscovery; +import org.apache.jackrabbit.webdav.observation.ObservationResource; +import org.apache.jackrabbit.webdav.observation.Subscription; +import org.apache.jackrabbit.webdav.observation.SubscriptionDiscovery; +import org.apache.jackrabbit.webdav.observation.SubscriptionInfo; +import org.apache.jackrabbit.webdav.observation.SubscriptionManager; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.w3c.dom.Element; +import org.w3c.dom.Document; + +import javax.jcr.RepositoryException; +import javax.jcr.Session; +import javax.jcr.observation.ObservationManager; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.Set; +import java.util.Map; +import java.util.List; +import java.util.ArrayList; + +/** + * SubscriptionManager collects all subscriptions requested, handles + * the subscription timeout and provides METHODS to discover subscriptions + * present on a given resource as well as events for an specific subscription. + */ +// todo: make sure all expired subscriptions are removed! +public class SubscriptionManagerImpl implements SubscriptionManager, TransactionListener { + + private static Logger log = LoggerFactory.getLogger(SubscriptionManagerImpl.class); + + /** + * Map containing all {@link org.apache.jackrabbit.webdav.observation.Subscription subscriptions}. + */ + private final SubscriptionMap subscriptions = new SubscriptionMap(); + + private final Map> transactionListenerById = new HashMap>(); + + /** + * Retrieve the {@link org.apache.jackrabbit.webdav.observation.SubscriptionDiscovery} + * object for the given resource. Note, that the discovery object will be empty + * if there are no subscriptions present.
+ * Note that all subscriptions present on the given resource are returned. + * However, the subscription id will not be visible in order to avoid abuse + * by clients not having registered the subscription originally. + * + * @param resource + */ + public SubscriptionDiscovery getSubscriptionDiscovery(ObservationResource resource) { + Subscription[] subsForResource = subscriptions.getByPath(resource.getLocator()); + return new SubscriptionDiscovery(subsForResource); + } + + /** + * Create a new Subscription or update an existing Subscription + * and add it as eventlistener to the {@link javax.jcr.observation.ObservationManager}. + * + * @param info + * @param subscriptionId + * @param resource + * @return Subscription that has been added to the {@link javax.jcr.observation.ObservationManager} + * @throws DavException if the subscription fails + */ + public Subscription subscribe(SubscriptionInfo info, String subscriptionId, + ObservationResource resource) + throws DavException { + + Subscription subscription; + if (subscriptionId == null) { + // new subscription + SubscriptionImpl newSubs = new SubscriptionImpl(info, resource); + registerSubscription(newSubs, resource); + + // adjust references to this subscription + subscriptions.put(newSubs.getSubscriptionId(), newSubs); + resource.getSession().addReference(newSubs.getSubscriptionId()); + subscription = newSubs; + } else { + // refresh/modify existing one + SubscriptionImpl existing = validate(subscriptionId, resource); + existing.setInfo(info); + registerSubscription(existing, resource); + + subscription = new WrappedSubscription(existing); + } + return subscription; + } + + /** + * Register the event listener defined by the given subscription to the + * repository's observation manager. + * + * @param subscription + * @param resource + * @throws DavException + */ + private void registerSubscription(SubscriptionImpl subscription, + ObservationResource resource) throws DavException { + try { + Session session = getRepositorySession(resource); + ObservationManager oMgr = session.getWorkspace().getObservationManager(); + String itemPath = subscription.getLocator().getRepositoryPath(); + oMgr.addEventListener(subscription, subscription.getJcrEventTypes(), + itemPath, subscription.isDeep(), + subscription.getUuidFilters(), + subscription.getNodetypeNameFilters(), + subscription.isNoLocal()); + } catch (RepositoryException e) { + log.error("Unable to register eventlistener: "+e.getMessage()); + throw new JcrDavException(e); + } + } + + /** + * Unsubscribe the Subscription with the given id and remove it + * from the {@link javax.jcr.observation.ObservationManager} as well as + * from the internal map. + * + * @param subscriptionId + * @param resource + * @throws DavException + */ + public void unsubscribe(String subscriptionId, ObservationResource resource) + throws DavException { + + SubscriptionImpl subs = validate(subscriptionId, resource); + unregisterSubscription(subs, resource); + } + + /** + * Remove the event listener defined by the specified subscription from + * the repository's observation manager and clean up the references present + * on the DavSession. + * + * @param subscription + * @param resource + * @throws DavException + */ + private void unregisterSubscription(SubscriptionImpl subscription, + ObservationResource resource) throws DavException { + try { + Session session = getRepositorySession(resource); + session.getWorkspace().getObservationManager().removeEventListener(subscription); + String sId = subscription.getSubscriptionId(); + + // clean up any references + subscriptions.remove(sId); + resource.getSession().removeReference(sId); + + } catch (RepositoryException e) { + log.error("Unable to remove eventlistener: "+e.getMessage()); + throw new JcrDavException(e); + } + } + + /** + * Retrieve all event bundles accumulated since for the subscription specified + * by the given id. + * + * @param subscriptionId + * @param timeout timeout in milliseconds + * @param resource + * @return object encapsulating the events. + */ + public EventDiscovery poll(String subscriptionId, long timeout, ObservationResource resource) + throws DavException { + + SubscriptionImpl subs = validate(subscriptionId, resource); + return subs.discoverEvents(timeout); + } + + /** + * Validate the given subscription id. The validation will fail under the following + * conditions:
    + *
  • The subscription with the given id does not exist,
  • + *
  • DavResource path does not match the subscription id,
  • + *
  • The subscription with the given id is already expired.
  • + *
+ * + * @param subscriptionId + * @param resource + * @return Subscription with the given id. + * @throws DavException if an error occurred while retrieving the Subscription + */ + private SubscriptionImpl validate(String subscriptionId, ObservationResource resource) + throws DavException { + + SubscriptionImpl subs; + if (subscriptions.contains(subscriptionId)) { + subs = subscriptions.get(subscriptionId); + if (!subs.isSubscribedToResource(resource)) { + throw new DavException(DavServletResponse.SC_PRECONDITION_FAILED, "Attempt to operate on subscription with invalid resource path."); + } + if (subs.isExpired()) { + unregisterSubscription(subs, resource); + throw new DavException(DavServletResponse.SC_PRECONDITION_FAILED, "Attempt to operate on expired subscription."); + } + return subs; + } else { + throw new DavException(DavServletResponse.SC_PRECONDITION_FAILED, "Attempt to modify or to poll for non-existing subscription."); + } + } + + /** + * @param resource + * @return JCR session + */ + private static Session getRepositorySession(ObservationResource resource) throws DavException { + return JcrDavSession.getRepositorySession(resource.getSession()); + } + + //---------------------------< TransactionListener >------------------------ + + /** + * {@inheritDoc} + */ + public synchronized void beforeCommit(TransactionResource resource, + String lockToken) { + // suspend regular subscriptions during a commit + List transactionListeners = new ArrayList(); + for (Iterator it = subscriptions.iterator(); it.hasNext(); ) { + SubscriptionImpl sub = it.next(); + TransactionListener tl = sub.createTransactionListener(); + tl.beforeCommit(resource, lockToken); + transactionListeners.add(tl); + } + transactionListenerById.put(lockToken, transactionListeners); + } + + /** + * {@inheritDoc} + */ + public void afterCommit(TransactionResource resource, String lockToken, boolean success) { + List transactionListeners = transactionListenerById.remove(lockToken); + if (transactionListeners != null) { + for (TransactionListener txListener : transactionListeners) { + txListener.afterCommit(resource, lockToken, success); + } + } + } + + //----------------------------------------------< private inner classes >--- + /** + * Private inner class wrapping around an Subscription as + * present in the internal map. This allows to hide the subscription Id + * from other sessions, that did create the subscription. + */ + private static class WrappedSubscription implements Subscription { + + private final Subscription delegatee; + + private WrappedSubscription(Subscription subsc) { + this.delegatee = subsc; + } + + public String getSubscriptionId() { + // always return null, since the subscription id must not be exposed + // but to the client, that created the subscription. + return null; + } + + public Element toXml(Document document) { + return delegatee.toXml(document); + } + + public boolean eventsProvideNodeTypeInformation() { + return delegatee.eventsProvideNodeTypeInformation(); + } + + public boolean eventsProvideNoLocalFlag() { + return delegatee.eventsProvideNoLocalFlag(); + } + } + + /** + * Private inner class SubscriptionMap that allows for quick + * access by resource path as well as by subscription id. + */ + private class SubscriptionMap { + + private HashMap subscriptions = new HashMap(); + private HashMap> ids = new HashMap>(); + + private boolean contains(String subscriptionId) { + return subscriptions.containsKey(subscriptionId); + } + + private SubscriptionImpl get(String subscriptionId) { + return subscriptions.get(subscriptionId); + } + + private Iterator iterator() { + return subscriptions.values().iterator(); + } + + private void put(String subscriptionId, SubscriptionImpl subscription) { + subscriptions.put(subscriptionId, subscription); + DavResourceLocator key = subscription.getLocator(); + Set idSet; + if (ids.containsKey(key)) { + idSet = ids.get(key); + } else { + idSet = new HashSet(); + ids.put(key, idSet); + } + if (!idSet.contains(subscriptionId)) { + idSet.add(subscriptionId); + } + } + + private void remove(String subscriptionId) { + SubscriptionImpl sub = subscriptions.remove(subscriptionId); + ids.get(sub.getLocator()).remove(subscriptionId); + } + + private Subscription[] getByPath(DavResourceLocator locator) { + Set idSet = ids.get(locator); + if (idSet != null && !idSet.isEmpty()) { + Subscription[] subsForResource = new Subscription[idSet.size()]; + int i = 0; + for (String id : idSet) { + SubscriptionImpl s = subscriptions.get(id); + subsForResource[i] = new WrappedSubscription(s); + i++; + } + return subsForResource; + } else { + return new Subscription[0]; + } + } + } +} Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/observation/SubscriptionManagerImpl.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/webdav/jcr/property/JcrDavPropertyNameSet.java =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/property/JcrDavPropertyNameSet.java (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/property/JcrDavPropertyNameSet.java (working copy) @@ -0,0 +1,155 @@ +/* + * 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.webdav.jcr.property; + +import org.apache.jackrabbit.webdav.jcr.ItemResourceConstants; +import org.apache.jackrabbit.webdav.observation.ObservationConstants; +import org.apache.jackrabbit.webdav.property.DavPropertyName; +import org.apache.jackrabbit.webdav.property.DavPropertyNameSet; +import org.apache.jackrabbit.webdav.version.DeltaVConstants; +import org.apache.jackrabbit.webdav.version.VersionControlledResource; +import org.apache.jackrabbit.webdav.version.VersionHistoryResource; +import org.apache.jackrabbit.webdav.version.VersionResource; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * JcrDavPropertyNameSet... + */ +public final class JcrDavPropertyNameSet implements ItemResourceConstants { + + /** + * logger instance + */ + private static final Logger log = LoggerFactory.getLogger(JcrDavPropertyNameSet.class); + + + //------------------------------------------------< property name sets >---- + /** + * Default property names present with all resources. + */ + public static final DavPropertyNameSet BASE_SET = new DavPropertyNameSet(); + static { + BASE_SET.add(DavPropertyName.DISPLAYNAME); + BASE_SET.add(DavPropertyName.RESOURCETYPE); + BASE_SET.add(DavPropertyName.ISCOLLECTION); + BASE_SET.add(DavPropertyName.GETLASTMODIFIED); + BASE_SET.add(DavPropertyName.CREATIONDATE); + BASE_SET.add(DavPropertyName.SUPPORTEDLOCK); + BASE_SET.add(DavPropertyName.LOCKDISCOVERY); + BASE_SET.add(DeltaVConstants.SUPPORTED_METHOD_SET); + BASE_SET.add(DeltaVConstants.SUPPORTED_REPORT_SET); + BASE_SET.add(DeltaVConstants.CREATOR_DISPLAYNAME); + BASE_SET.add(DeltaVConstants.COMMENT); + BASE_SET.add(JCR_WORKSPACE_NAME); + } + + /** + * Property names defined for JCR workspace resources. + */ + public static final DavPropertyNameSet WORKSPACE_SET = new DavPropertyNameSet(); + static { + WORKSPACE_SET.add(DeltaVConstants.WORKSPACE); + WORKSPACE_SET.add(JCR_NAMESPACES); + WORKSPACE_SET.add(JCR_NODETYPES_CND); + } + + /** + * Additional property names defined for existing and non-existing item resources. + */ + public static final DavPropertyNameSet ITEM_BASE_SET = new DavPropertyNameSet(); + static { + ITEM_BASE_SET.add(DavPropertyName.GETCONTENTTYPE); + ITEM_BASE_SET.add(DeltaVConstants.WORKSPACE); + ITEM_BASE_SET.add(ObservationConstants.SUBSCRIPTIONDISCOVERY); + } + + /** + * Additional property names defined for existing item resources. + */ + public static final DavPropertyNameSet EXISTING_ITEM_BASE_SET = new DavPropertyNameSet(ITEM_BASE_SET); + static { + EXISTING_ITEM_BASE_SET.add(JCR_NAME); + EXISTING_ITEM_BASE_SET.add(JCR_PATH); + EXISTING_ITEM_BASE_SET.add(JCR_DEPTH); + EXISTING_ITEM_BASE_SET.add(JCR_DEFINITION); + } + + /** + * Additional property names defined by single value JCR properties. + */ + public static final DavPropertyNameSet PROPERTY_SET = new DavPropertyNameSet(); + static { + PROPERTY_SET.add(JCR_TYPE); + PROPERTY_SET.add(JCR_VALUE); + PROPERTY_SET.add(JCR_LENGTH); + } + + /** + * Additional property names defined by single value JCR properties. + */ + public static final DavPropertyNameSet PROPERTY_MV_SET = new DavPropertyNameSet(); + static { + PROPERTY_MV_SET.add(JCR_TYPE); + PROPERTY_MV_SET.add(JCR_VALUES); + PROPERTY_MV_SET.add(JCR_LENGTHS); + } + + /** + * Additional property names defined by regular JCR nodes. + */ + public static final DavPropertyNameSet NODE_SET = new DavPropertyNameSet(); + static { + NODE_SET.add(JCR_PRIMARYNODETYPE); + NODE_SET.add(JCR_MIXINNODETYPES); + NODE_SET.add(JCR_INDEX); + NODE_SET.add(JCR_REFERENCES); + NODE_SET.add(JCR_WEAK_REFERENCES); + } + + /** + * Additional property names defined by versionable JCR nodes. + */ + public static final DavPropertyNameSet VERSIONABLE_SET = new DavPropertyNameSet(); + static { + VERSIONABLE_SET.add(VersionControlledResource.VERSION_HISTORY); + VERSIONABLE_SET.add(VersionControlledResource.AUTO_VERSION); + } + + /** + * Additional property names defined by JCR version nodes. + */ + public static final DavPropertyNameSet VERSION_SET = new DavPropertyNameSet(); + static { + VERSION_SET.add(VersionResource.VERSION_NAME); + VERSION_SET.add(VersionResource.LABEL_NAME_SET); + VERSION_SET.add(VersionResource.PREDECESSOR_SET); + VERSION_SET.add(VersionResource.SUCCESSOR_SET); + VERSION_SET.add(VersionResource.VERSION_HISTORY); + VERSION_SET.add(VersionResource.CHECKOUT_SET); + } + + /** + * Additional property names defined by JCR version history nodes. + */ + public static final DavPropertyNameSet VERSIONHISTORY_SET = new DavPropertyNameSet(); + static { + VERSIONHISTORY_SET.add(VersionHistoryResource.ROOT_VERSION); + VERSIONHISTORY_SET.add(VersionHistoryResource.VERSION_SET); + VERSIONHISTORY_SET.add(JCR_VERSIONABLEUUID); + } +} \ No newline at end of file Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/property/JcrDavPropertyNameSet.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/webdav/jcr/property/LengthsProperty.java =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/property/LengthsProperty.java (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/property/LengthsProperty.java (working copy) @@ -0,0 +1,67 @@ +/* + * 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.webdav.jcr.property; + +import org.apache.jackrabbit.webdav.jcr.ItemResourceConstants; +import org.apache.jackrabbit.webdav.property.AbstractDavProperty; +import org.apache.jackrabbit.webdav.xml.DomUtil; +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +/** + * LengthsProperty extends {@link org.apache.jackrabbit.webdav.property.DavProperty} providing + * utilities to handle the multiple lengths of the property item represented + * by this resource. + */ +public class LengthsProperty extends AbstractDavProperty implements ItemResourceConstants { + + private final long[] value; + + /** + * Create a new LengthsProperty from the given long array. + * + * @param lengths as retrieved from the JCR property + */ + public LengthsProperty(long[] lengths) { + super(JCR_LENGTHS, true); + this.value = lengths; + } + + /** + * Returns an array of {@link long}s representing the value of this + * property. + * + * @return an array of {@link long}s + */ + public long[] getValue() { + return value; + } + + /** + * @see org.apache.jackrabbit.webdav.xml.XmlSerializable#toXml(Document) + */ + @Override + public Element toXml(Document document) { + Element elem = getName().toXml(document); + for (long length : value) { + String txtContent = String.valueOf(length); + DomUtil.addChildElement(elem, XML_LENGTH, ItemResourceConstants.NAMESPACE, txtContent); + } + return elem; + } + +} Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/property/LengthsProperty.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/webdav/jcr/property/NamespacesProperty.java =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/property/NamespacesProperty.java (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/property/NamespacesProperty.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.webdav.jcr.property; + +import org.apache.jackrabbit.webdav.DavException; +import org.apache.jackrabbit.webdav.DavServletResponse; +import org.apache.jackrabbit.webdav.jcr.ItemResourceConstants; +import org.apache.jackrabbit.webdav.property.AbstractDavProperty; +import org.apache.jackrabbit.webdav.property.DavProperty; +import org.apache.jackrabbit.webdav.xml.DomUtil; +import org.apache.jackrabbit.webdav.xml.Namespace; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +import javax.jcr.NamespaceRegistry; +import javax.jcr.RepositoryException; +import java.util.List; +import java.util.Map; +import java.util.HashMap; +import java.util.Collections; + +/** + * NamespacesProperty... + */ +public class NamespacesProperty extends AbstractDavProperty> implements ItemResourceConstants { + + private static Logger log = LoggerFactory.getLogger(NamespacesProperty.class); + + private final Map value = new HashMap(); + + public NamespacesProperty(NamespaceRegistry nsReg) throws RepositoryException { + super(JCR_NAMESPACES, false); + if (nsReg != null) { + for (String prefix : nsReg.getPrefixes()) { + value.put(prefix, nsReg.getURI(prefix)); + } + } + } + + public NamespacesProperty(Map namespaces) { + super(JCR_NAMESPACES, false); + value.putAll(namespaces); + } + + public NamespacesProperty(DavProperty property) throws DavException { + super(JCR_NAMESPACES, false); + Object v = property.getValue(); + if (!(v instanceof List)) { + log.warn("Unexpected structure of dcr:namespace property."); + throw new DavException(DavServletResponse.SC_INTERNAL_SERVER_ERROR); + } + // retrieve list of prefix/uri pairs that build the new values of + // the ns-registry + for (Object listEntry : (List) v) { + if (listEntry instanceof Element) { + Element e = (Element)listEntry; + if (XML_NAMESPACE.equals(e.getLocalName())) { + Element pElem = DomUtil.getChildElement(e, XML_PREFIX, ItemResourceConstants.NAMESPACE); + String prefix = DomUtil.getText(pElem, Namespace.EMPTY_NAMESPACE.getPrefix()); + Element uElem = DomUtil.getChildElement(e, XML_URI, ItemResourceConstants.NAMESPACE); + String uri = DomUtil.getText(uElem, Namespace.EMPTY_NAMESPACE.getURI()); + value.put(prefix, uri); + } + } + } + } + + public Map getNamespaces() { + return Collections.unmodifiableMap(value); + } + + public Map getValue() { + return Collections.unmodifiableMap(value); + } + + /** + * @see org.apache.jackrabbit.webdav.xml.XmlSerializable#toXml(Document) + */ + @Override + public Element toXml(Document document) { + Element elem = getName().toXml(document); + for (String prefix : value.keySet()) { + String uri = value.get(prefix); + Element nsElem = DomUtil.addChildElement(elem, XML_NAMESPACE, ItemResourceConstants.NAMESPACE); + DomUtil.addChildElement(nsElem, XML_PREFIX, ItemResourceConstants.NAMESPACE, prefix); + DomUtil.addChildElement(nsElem, XML_URI, ItemResourceConstants.NAMESPACE, uri); + } + return elem; + } + +} Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/property/NamespacesProperty.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/webdav/jcr/property/ValuesProperty.java =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/property/ValuesProperty.java (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/property/ValuesProperty.java (working copy) @@ -0,0 +1,191 @@ +/* + * 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.webdav.jcr.property; + +import org.apache.jackrabbit.commons.webdav.ValueUtil; +import org.apache.jackrabbit.value.ValueHelper; +import org.apache.jackrabbit.webdav.DavException; +import org.apache.jackrabbit.webdav.DavServletResponse; +import org.apache.jackrabbit.webdav.jcr.ItemResourceConstants; +import org.apache.jackrabbit.webdav.property.AbstractDavProperty; +import org.apache.jackrabbit.webdav.property.DavProperty; +import org.apache.jackrabbit.webdav.property.DavPropertyName; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +import javax.jcr.PropertyType; +import javax.jcr.RepositoryException; +import javax.jcr.Value; +import javax.jcr.ValueFormatException; +import javax.jcr.ValueFactory; + +/** + * ValuesProperty implements {@link org.apache.jackrabbit.webdav.property.DavProperty} + * providing utilities to handle the value(s) of a JCR property item resource. + * In case the property is multivalued the DavProperty value consists of + * an element named {@link #JCR_VALUES} otherwise its name is {@link #JCR_VALUE}. + */ +public class ValuesProperty extends AbstractDavProperty implements ItemResourceConstants { + + private static Logger log = LoggerFactory.getLogger(ValuesProperty.class); + + private final Value[] jcrValues; + + /** + * Create a new ValuesProperty from the given single {@link Value}. + * + * @param value Array of Value objects as obtained from the JCR property. + */ + public ValuesProperty(Value value) { + super(JCR_VALUE, false); + // finally set the value to the DavProperty + jcrValues = (value == null) ? new Value[0] : new Value[] {value}; + } + + /** + * Create a new ValuesProperty from the given {@link javax.jcr.Value Value + * array}. + * + * @param values Array of Value objects as obtained from the JCR property. + */ + public ValuesProperty(Value[] values) { + super(JCR_VALUES, false); + // finally set the value to the DavProperty + jcrValues = (values == null) ? new Value[0] : values; + } + + /** + * Wrap the specified DavProperty in a new ValuesProperty. + * + * @param property + * @param defaultType default type of the values to be deserialized. If however + * the {@link #XML_VALUE 'value'} elements provide a {@link #ATTR_VALUE_TYPE 'type'} + * attribute, the default value is ignored. + * @param valueFactory Factory used to retrieve JCR values from the value + * of the given DavProperty. + */ + public ValuesProperty(DavProperty property, int defaultType, + ValueFactory valueFactory) + throws RepositoryException, DavException { + super(property.getName(), false); + + if (!(JCR_VALUES.equals(property.getName()) || JCR_VALUE.equals(getName()))) { + throw new DavException(DavServletResponse.SC_BAD_REQUEST, "ValuesProperty may only be created with a property that has name="+JCR_VALUES.getName()); + } + + jcrValues = ValueUtil.valuesFromXml(property.getValue(), defaultType, valueFactory); + } + + private void checkPropertyName(DavPropertyName reqName) throws ValueFormatException { + if (!reqName.equals(getName())) { + throw new ValueFormatException("Attempt to retrieve multiple values from single property '" + getName() + "'."); + } + } + + /** + * Converts the value of this property to a {@link javax.jcr.Value value array}. + * + * @return Array of Value objects + * @throws ValueFormatException if converting the internal jcr values to + * the specified value type fails. + */ + public Value[] getJcrValues(int propertyType, ValueFactory valueFactory) throws ValueFormatException { + checkPropertyName(JCR_VALUES); + Value[] vs = new Value[jcrValues.length]; + for (int i = 0; i < jcrValues.length; i++) { + vs[i] = ValueHelper.convert(jcrValues[i], propertyType, valueFactory); + } + return vs; + } + + /** + * Returns the internal property value as jcr Value array + * + * @return the internal property value as jcr Value array + */ + public Value[] getJcrValues() throws ValueFormatException { + checkPropertyName(JCR_VALUES); + return jcrValues; + } + + /** + * + * @param propertyType + * @return + * @throws ValueFormatException + */ + public Value getJcrValue(int propertyType, ValueFactory valueFactory) throws ValueFormatException { + checkPropertyName(JCR_VALUE); + return (jcrValues.length == 0) + ? null + : ValueHelper.convert(jcrValues[0], propertyType, valueFactory); + } + + /** + * + * @return + * @throws ValueFormatException + */ + public Value getJcrValue() throws ValueFormatException { + checkPropertyName(JCR_VALUE); + return (jcrValues.length == 0) ? null : jcrValues[0]; + } + + /** + * Returns the type of the {@link Value value}s present in this property + * or {@link PropertyType#UNDEFINED} if no values are available. + * + * @return type of values or {@link PropertyType#UNDEFINED} + */ + public int getValueType() { + // TODO: check if correct behaviour if values array is empty + return (jcrValues.length > 0) ? jcrValues[0].getType() : PropertyType.UNDEFINED; + } + + /** + * Returns an array of {@link Value}s representing the value of this + * property. + * + * @return an array of {@link Value}s + * @see #getJcrValues() + * @see #getJcrValue() + */ + public Value[] getValue() { + return jcrValues; + } + + /** + * + * @param document + * @return the xml element + */ + @Override + public Element toXml(Document document) { + Element elem = getName().toXml(document); + try { + for (Value v : jcrValues) { + Element xmlValue = ValueUtil.valueToXml(v, document); + elem.appendChild(xmlValue); + } + } catch (RepositoryException e) { + log.error("Unexpected Error while converting jcr value to String: " + e.getMessage()); + } + return elem; + } +} Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/property/ValuesProperty.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/webdav/jcr/search/SearchResourceImpl.java =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/search/SearchResourceImpl.java (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/search/SearchResourceImpl.java (working copy) @@ -0,0 +1,403 @@ +/* + * 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.webdav.jcr.search; + +import org.apache.jackrabbit.JcrConstants; +import org.apache.jackrabbit.webdav.DavException; +import org.apache.jackrabbit.webdav.DavResourceLocator; +import org.apache.jackrabbit.webdav.DavServletResponse; +import org.apache.jackrabbit.webdav.MultiStatus; +import org.apache.jackrabbit.webdav.MultiStatusResponse; +import org.apache.jackrabbit.webdav.jcr.ItemResourceConstants; +import org.apache.jackrabbit.webdav.jcr.JcrDavException; +import org.apache.jackrabbit.webdav.jcr.JcrDavSession; +import org.apache.jackrabbit.webdav.search.QueryGrammerSet; +import org.apache.jackrabbit.webdav.search.SearchInfo; +import org.apache.jackrabbit.webdav.search.SearchResource; +import org.apache.jackrabbit.webdav.xml.Namespace; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.apache.jackrabbit.util.ISO9075; + +import javax.jcr.Node; +import javax.jcr.RepositoryException; +import javax.jcr.Session; +import javax.jcr.Value; +import javax.jcr.NamespaceRegistry; +import javax.jcr.ValueFactory; +import javax.jcr.PropertyType; +import javax.jcr.query.InvalidQueryException; +import javax.jcr.query.Query; +import javax.jcr.query.QueryManager; +import javax.jcr.query.QueryResult; +import javax.jcr.query.Row; +import javax.jcr.query.RowIterator; + +import java.util.Map; +import java.util.List; +import java.util.ArrayList; + +/** + * SearchResourceImpl... + */ +public class SearchResourceImpl implements SearchResource { + + private static Logger log = LoggerFactory.getLogger(SearchResourceImpl.class); + + private final JcrDavSession session; + private final DavResourceLocator locator; + + public SearchResourceImpl(DavResourceLocator locator, JcrDavSession session) { + this.session = session; + this.locator = locator; + } + + //-------------------------------------------< SearchResource interface >--- + /** + * @see SearchResource#getQueryGrammerSet() + */ + public QueryGrammerSet getQueryGrammerSet() { + QueryGrammerSet qgs = new QueryGrammerSet(); + try { + QueryManager qMgr = getRepositorySession().getWorkspace().getQueryManager(); + String[] langs = qMgr.getSupportedQueryLanguages(); + for (String lang : langs) { + // Note: Existing clients already assume that the + // query languages returned in the DASL header are + // not prefixed with any namespace, so we probably + // shouldn't use an explicit namespace here. + qgs.addQueryLanguage(lang, Namespace.EMPTY_NAMESPACE); + } + } catch (RepositoryException e) { + log.debug(e.getMessage()); + } + return qgs; + } + + /** + * Execute the query defined by the given sInfo. + * + * @see SearchResource#search(org.apache.jackrabbit.webdav.search.SearchInfo) + */ + public MultiStatus search(SearchInfo sInfo) throws DavException { + try { + QueryResult result = getQuery(sInfo).execute(); + + MultiStatus ms = new MultiStatus(); + + if (ItemResourceConstants.NAMESPACE.equals( + sInfo.getLanguageNameSpace())) { + ms.setResponseDescription( + "Columns: " + encode(result.getColumnNames()) + + "\nSelectors: " + encode(result.getSelectorNames())); + } else { + ms.setResponseDescription(encode(result.getColumnNames())); + } + + queryResultToMultiStatus(result, ms); + + return ms; + } catch (RepositoryException e) { + throw new JcrDavException(e); + } + } + + /** + * Create a query from the information present in the sInfo + * object.
The following JCR specific logic is applied: + *
    + *
  • If the requested resource represents a node with nodetype nt:query, the + * request body is ignored and the query defined with the node is executed + * instead.
  • + *
  • If the requested resource does not represent an existing item, the + * specified query is persisted by calling {@link Query#storeAsNode(String)}.
  • + *
+ * @param sInfo defining the query to be executed + * @return Query object. + * @throws javax.jcr.query.InvalidQueryException if the query defined by sInfo is invalid + * @throws RepositoryException the query manager cannot be accessed or if + * another error occurs. + * @throws DavException if sInfo is null and + * the underlying repository item is not an nt:query node or if an error + * occurs when calling {@link Query#storeAsNode(String)}/ + */ + private Query getQuery(SearchInfo sInfo) + throws InvalidQueryException, RepositoryException, DavException { + + Session session = getRepositorySession(); + NamespaceRegistry nsReg = session.getWorkspace().getNamespaceRegistry(); + Node rootNode = session.getRootNode(); + QueryManager qMgr = getRepositorySession().getWorkspace().getQueryManager(); + + // test if query is defined by requested repository node + String itemPath = locator.getRepositoryPath(); + if (itemPath != null && !rootNode.getPath().equals(itemPath)) { + String qNodeRelPath = itemPath.substring(1); + if (rootNode.hasNode(qNodeRelPath)) { + Node qNode = rootNode.getNode(qNodeRelPath); + if (qNode.isNodeType(JcrConstants.NT_QUERY)) { + return qMgr.getQuery(qNode); + } + } + } + + Query q; + if (sInfo != null) { + // apply namespace mappings to session + Map namespaces = sInfo.getNamespaces(); + try { + for (Map.Entry entry : namespaces.entrySet()) { + String prefix = entry.getKey(); + String uri = entry.getValue(); + session.setNamespacePrefix(prefix, uri); + } + q = qMgr.createQuery(sInfo.getQuery(), sInfo.getLanguageName()); + + if (SearchInfo.NRESULTS_UNDEFINED != sInfo.getNumberResults()) { + q.setLimit(sInfo.getNumberResults()); + } + if (SearchInfo.OFFSET_UNDEFINED != sInfo.getOffset()) { + q.setOffset(sInfo.getOffset()); + } + } finally { + // reset namespace mappings + for (String uri : namespaces.values()) { + try { + session.setNamespacePrefix(nsReg.getPrefix(uri), uri); + } catch (RepositoryException e) { + log.warn("Unable to reset mapping of namespace: " + uri); + } + } + } + } else { + throw new DavException(DavServletResponse.SC_BAD_REQUEST, locator.getResourcePath() + " is not a nt:query node -> searchRequest body required."); + } + + /* test if resource path does not exist -> thus indicating that + the query must be made persistent by calling Query.save(String) */ + if (itemPath != null && !getRepositorySession().itemExists(itemPath)) { + try { + q.storeAsNode(itemPath); + } catch (RepositoryException e) { + // ItemExistsException should never occur. + throw new JcrDavException(e); + } + } + return q; + } + + /** + * Build a MultiStatus object from the specified query result. + * + * @param query the query to execute. + * @return MultiStatus object listing the query result in + * Webdav compatible form. + * @throws RepositoryException if an error occurs. + */ + private void queryResultToMultiStatus(QueryResult result, MultiStatus ms) + throws RepositoryException { + List columnNames = new ArrayList(); + + ValueFactory vf = getRepositorySession().getValueFactory(); + List descr = new ArrayList(); + for (String columnName : result.getColumnNames()) { + if (!isPathOrScore(columnName)) { + columnNames.add(columnName); + descr.add(new PlainValue(columnName, null, vf)); + } + } + + // add path and score for each selector + String[] sns = result.getSelectorNames(); + boolean join = sns.length > 1; + for (String selectorName : sns) { + descr.add(new PathValue(JcrConstants.JCR_PATH, selectorName, vf)); + columnNames.add(JcrConstants.JCR_PATH); + descr.add(new ScoreValue(JcrConstants.JCR_SCORE, selectorName, vf)); + columnNames.add(JcrConstants.JCR_SCORE); + } + + int n = 0; + String root = getHref("/"); + String[] selectorNames = createSelectorNames(descr); + String[] colNames = columnNames.toArray(new String[columnNames.size()]); + RowIterator rowIter = result.getRows(); + while (rowIter.hasNext()) { + Row row = rowIter.nextRow(); + List values = new ArrayList(); + for (RowValue rv : descr) { + values.add(rv.getValue(row)); + } + + // create a new ms-response for this row of the result set + String href; + if (join) { + // We need a distinct href for each join result row to + // allow the MultiStatus response to keep them separate + href = root + "?" + n++; + } else { + href = getHref(row.getPath()); + } + MultiStatusResponse resp = new MultiStatusResponse(href, null); + + // build the s-r-property + SearchResultProperty srp = new SearchResultProperty(colNames, + selectorNames, values.toArray(new Value[values.size()])); + resp.add(srp); + ms.addResponse(resp); + } + } + + /** + * Returns the resource location of the given query result row. + * The result rows of join queries have no meaningful single resource + * location, so we'll just default to the root node for all such rows. + * + * @param row query result row + * @param join flag to indicate a join query + * @return resource location of the row + */ + private String getHref(String path) throws RepositoryException { + DavResourceLocator l = locator.getFactory().createResourceLocator( + locator.getPrefix(), locator.getWorkspacePath(), path, false); + return l.getHref(true); + } + + private String encode(String[] names) { + StringBuilder builder = new StringBuilder(); + String delim = ""; + for (String name : names) { + builder.append(delim); + builder.append(ISO9075.encode(name)); + delim = " "; + } + return builder.toString(); + } + + private static String[] createSelectorNames(Iterable rows) + throws RepositoryException { + List sn = new ArrayList(); + for (RowValue rv : rows) { + sn.add(rv.getSelectorName()); + } + return sn.toArray(new String[sn.size()]); + } + + /** + * @param columnName a column name. + * @return true if columnName is either + * jcr:path or jcr:score; + * false otherwise. + */ + private static boolean isPathOrScore(String columnName) { + return JcrConstants.JCR_PATH.equals(columnName) + || JcrConstants.JCR_SCORE.equals(columnName); + } + + /** + * @return the session associated with this resource. + */ + private Session getRepositorySession() { + return session.getRepositorySession(); + } + + private interface RowValue { + + public Value getValue(Row row) throws RepositoryException; + + public String getColumnName() throws RepositoryException; + + public String getSelectorName() throws RepositoryException; + } + + private static final class PlainValue extends SelectorValue { + + public PlainValue(String columnName, + String selectorName, + ValueFactory vf) { + super(columnName, selectorName, vf); + } + + public Value getValue(Row row) throws RepositoryException { + return row.getValue(columnName); + } + } + + private static abstract class SelectorValue implements RowValue { + + protected final String columnName; + + protected final String selectorName; + + protected final ValueFactory vf; + + public SelectorValue(String columnName, + String selectorName, + ValueFactory vf) { + this.columnName = columnName; + this.selectorName = selectorName; + this.vf = vf; + } + + public String getColumnName() throws RepositoryException { + return columnName; + } + + public String getSelectorName() throws RepositoryException { + return selectorName; + } + } + + private static final class ScoreValue extends SelectorValue { + + public ScoreValue(String columnName, + String selectorName, + ValueFactory vf) { + super(columnName, selectorName, vf); + } + + public Value getValue(Row row) throws RepositoryException { + double score; + if (selectorName != null) { + score = row.getScore(selectorName); + } else { + score = row.getScore(); + } + return vf.createValue(score); + } + } + + private static final class PathValue extends SelectorValue { + + public PathValue(String columnName, + String selectorName, + ValueFactory vf) { + super(columnName, selectorName, vf); + } + + public Value getValue(Row row) throws RepositoryException { + String path; + if (selectorName != null) { + path = row.getPath(selectorName); + } else { + path = row.getPath(); + } + return (path == null) ? null : vf.createValue(path, PropertyType.PATH); + } + } + +} \ No newline at end of file Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/search/SearchResourceImpl.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/webdav/jcr/search/SearchResultProperty.java =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/search/SearchResultProperty.java (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/search/SearchResultProperty.java (working copy) @@ -0,0 +1,201 @@ +/* + * 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.webdav.jcr.search; + +import org.apache.jackrabbit.commons.webdav.QueryUtil; +import org.apache.jackrabbit.value.ValueHelper; +import org.apache.jackrabbit.webdav.jcr.ItemResourceConstants; +import org.apache.jackrabbit.webdav.property.AbstractDavProperty; +import org.apache.jackrabbit.webdav.property.DavProperty; +import org.apache.jackrabbit.webdav.property.DavPropertyName; +import org.apache.jackrabbit.webdav.xml.DomUtil; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +import javax.jcr.PropertyType; +import javax.jcr.RepositoryException; +import javax.jcr.Value; +import javax.jcr.ValueFactory; +import java.util.ArrayList; +import java.util.List; + +/** + * SearchResultProperty... + */ +// todo: find proper solution for transporting search results... +public class SearchResultProperty extends AbstractDavProperty implements ItemResourceConstants { + + private static Logger log = LoggerFactory.getLogger(SearchResultProperty.class); + + private static final DavPropertyName SEARCH_RESULT_PROPERTY = DavPropertyName.create(JCR_QUERY_RESULT_LN, ItemResourceConstants.NAMESPACE); + + private final String[] columnNames; + private final String[] selectorNames; + private final Value[] values; + + /** + * Creates a new SearchResultProperty. + * + * @param columnNames the column names of the search row represented by + * this dav property. + * @param selectorNames the selector names of the row represented by this + * dav property. + * @param values the values present in the columns + */ + public SearchResultProperty(String[] columnNames, + String[] selectorNames, + Value[] values) { + super(SEARCH_RESULT_PROPERTY, true); + this.columnNames = columnNames; + this.selectorNames = selectorNames; + this.values = values; + } + + /** + * Wrap the specified DavProperty in a new SearchResultProperty. + * + * @param property + * @param valueFactory factory used to deserialize the xml value to a JCR value. + * @throws RepositoryException if an error occurs while build the property value + * @throws IllegalArgumentException if the specified property does have the + * required form. + * @see #getValues() + */ + public SearchResultProperty(DavProperty property, ValueFactory valueFactory) throws RepositoryException { + super(property.getName(), true); + if (!SEARCH_RESULT_PROPERTY.equals(getName())) { + throw new IllegalArgumentException("SearchResultProperty may only be created from a property named " + SEARCH_RESULT_PROPERTY.toString()); + } + + List colList = new ArrayList(); + List selList = new ArrayList(); + List valList = new ArrayList(); + + QueryUtil.parseResultPropertyValue(property.getValue(), colList, selList, valList, valueFactory); + + columnNames = colList.toArray(new String[colList.size()]); + selectorNames = selList.toArray(new String[selList.size()]); + values = valList.toArray(new Value[valList.size()]); + } + + /** + * Return the column names representing the names of the properties present + * in the {@link #getValues() values}. + * + * @return columnNames + */ + public String[] getColumnNames() { + return columnNames; + } + + /** + * @return the selector name for each of the columns in the result property. + */ + public String[] getSelectorNames() { + return selectorNames; + } + + /** + * Return the values representing the values of that row in the search + * result table. + * + * @return values + * @see javax.jcr.query.Row#getValues() + */ + public Value[] getValues() { + return values; + } + + + /** + * Same as {@link #getValues()} + * + * @return Array of JCR Value object + */ + public Value[] getValue() { + return values; + } + + /** + * Return the xml representation of this webdav property. For every value in + * the query result row a dcr:name, dcr:value, dcr:type and an optional + * dcr:selectorName element is created. + * Example: + *
+     * -----------------------------------------------------------
+     *   col-name  |   bla   |   bli   |  jcr:path  |  jcr:score
+     * -----------------------------------------------------------
+     *   value     |   xxx   |   111   |  /aNode    |    1
+     *   type      |    1    |    3    |     8      |    3
+     *   sel-name  |         |         |     S      |    S
+     * -----------------------------------------------------------
+     * 
+ * results in: + *
+     * <dcr:search-result-property xmlns:dcr="http://www.day.com/jcr/webdav/1.0">
+     *    <dcr:column>
+     *       <dcr:name>bla<dcr:name/>
+     *       <dcr:value dcr:type="String">xxx<dcr:value/>
+     *    </dcr:column>
+     *    <dcr:column>
+     *       <dcr:name>bli<dcr:name/>
+     *       <dcr:value dcr:type="Long">111<dcr:value/>
+     *    </dcr:column>
+     *    <dcr:column>
+     *       <dcr:name>jcr:path<dcr:name/>
+     *       <dcr:value dcr:type="Path">/aNode<dcr:value/>
+     *       <dcr:selectorName>S<dcr:selectorName/>
+     *    </dcr:column>
+     *    <dcr:column>
+     *       <dcr:name>jcr:score<dcr:name/>
+     *       <dcr:value dcr:type="Long">1<dcr:value/>
+     *       <dcr:selectorName>S<dcr:selectorName/>
+     *    </dcr:column>
+     * </dcr:search-result-property>
+     * 
+ * + * @see org.apache.jackrabbit.webdav.xml.XmlSerializable#toXml(org.w3c.dom.Document) + */ + @Override + public Element toXml(Document document) { + Element elem = getName().toXml(document); + for (int i = 0; i < columnNames.length; i++) { + String propertyName = columnNames[i]; + String selectorName = selectorNames[i]; + Value propertyValue = values[i]; + + Element columnEl = DomUtil.addChildElement(elem, XML_QUERY_RESULT_COLUMN, ItemResourceConstants.NAMESPACE); + DomUtil.addChildElement(columnEl, JCR_NAME.getName(), JCR_NAME.getNamespace(), propertyName); + if (propertyValue != null) { + try { + String serializedValue = ValueHelper.serialize(propertyValue, true); + Element xmlValue = DomUtil.addChildElement(columnEl, XML_VALUE, ItemResourceConstants.NAMESPACE, serializedValue); + String type = PropertyType.nameFromValue(propertyValue.getType()); + DomUtil.setAttribute(xmlValue, ATTR_VALUE_TYPE, ItemResourceConstants.NAMESPACE, type); + } catch (RepositoryException e) { + log.error(e.toString()); + } + } + if (selectorName != null) { + DomUtil.addChildElement(columnEl, JCR_SELECTOR_NAME.getName(), JCR_SELECTOR_NAME.getNamespace(), selectorName); + } + } + return elem; + } +} Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/search/SearchResultProperty.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/webdav/jcr/security/JcrSupportedPrivilegesProperty.java =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/security/JcrSupportedPrivilegesProperty.java (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/security/JcrSupportedPrivilegesProperty.java (working copy) @@ -0,0 +1,122 @@ +/* + * 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.webdav.jcr.security; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import javax.jcr.RepositoryException; +import javax.jcr.Session; +import javax.jcr.security.AccessControlManager; +import javax.jcr.security.Privilege; + +import org.apache.jackrabbit.util.Text; +import org.apache.jackrabbit.webdav.security.SupportedPrivilege; +import org.apache.jackrabbit.webdav.security.SupportedPrivilegeSetProperty; +import org.apache.jackrabbit.webdav.xml.Namespace; + +/** + * JcrSupportedPrivilegesProperty... + */ +public class JcrSupportedPrivilegesProperty { + + private final Session session; + private final String absPath; + private final Set privileges = new HashSet(); + + private final Map supportedPrivileges = new HashMap(); + private final HashSet aggregated = new HashSet(); + + /** + * Build supported privileges for the jcr:all privilege. + * + * @param session The reading session + */ + public JcrSupportedPrivilegesProperty(Session session) throws RepositoryException { + this.session = session; + this.absPath = null; + AccessControlManager acMgr = session.getAccessControlManager(); + Privilege jcrAll = acMgr.privilegeFromName(Privilege.JCR_ALL); + privileges.add(jcrAll); + } + + /** + * @param session The reading session + * @param absPath An absolute path to an existing JCR node or {@code null}. + */ + public JcrSupportedPrivilegesProperty(Session session, String absPath) { + this.session = session; + this.absPath = absPath; + } + + /** + * Calculated the supported privileges at {@code absPath} and build a + * {@link org.apache.jackrabbit.webdav.security.SupportedPrivilegeSetProperty} + * from the result. + * + * @return a new {@code SupportedPrivilegeSetProperty} property. + * @throws RepositoryException + */ + public SupportedPrivilegeSetProperty asDavProperty() throws RepositoryException { + if (privileges.isEmpty()) { + AccessControlManager acMgr = session.getAccessControlManager(); + privileges.addAll(Arrays.asList(acMgr.getSupportedPrivileges(absPath))); + } + for (Privilege p : privileges) { + if (!aggregated.contains(p.getName())) { + createSupportedPrivilege(p); + } + } + return new SupportedPrivilegeSetProperty(supportedPrivileges.values().toArray(new SupportedPrivilege[supportedPrivileges.size()])); + } + + private SupportedPrivilege createSupportedPrivilege(Privilege privilege) throws RepositoryException { + String privilegeName = privilege.getName(); + + String localName = Text.getLocalName(privilegeName); + String prefix = Text.getNamespacePrefix(privilegeName); + Namespace ns = (prefix.isEmpty()) ? Namespace.EMPTY_NAMESPACE : Namespace.getNamespace(prefix, session.getNamespaceURI(prefix)); + org.apache.jackrabbit.webdav.security.Privilege davPrivilege = org.apache.jackrabbit.webdav.security.Privilege.getPrivilege(localName, ns); + + SupportedPrivilege[] aggregates = (privilege.isAggregate()) ? getDeclaredAggregates(privilege) : null; + + SupportedPrivilege sp = new SupportedPrivilege(davPrivilege, null, null, privilege.isAbstract(), aggregates); + if (!aggregated.contains(privilegeName)) { + supportedPrivileges.put(privilegeName, sp); + } + return sp; + } + + private SupportedPrivilege[] getDeclaredAggregates(Privilege privilege) throws RepositoryException { + List declAggr = new ArrayList(); + for (Privilege decl : privilege.getDeclaredAggregatePrivileges()) { + String name = decl.getName(); + if (aggregated.add(name)) { + if (supportedPrivileges.containsKey(name)) { + declAggr.add(supportedPrivileges.remove(name)); + } else { + declAggr.add(createSupportedPrivilege(decl)); + } + } + } + return declAggr.toArray(new SupportedPrivilege[declAggr.size()]); + } +} \ No newline at end of file Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/security/JcrSupportedPrivilegesProperty.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/webdav/jcr/security/JcrUserPrivilegesProperty.java =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/security/JcrUserPrivilegesProperty.java (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/security/JcrUserPrivilegesProperty.java (working copy) @@ -0,0 +1,58 @@ +/* + * 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.webdav.jcr.security; + +import java.util.ArrayList; +import java.util.List; +import javax.jcr.RepositoryException; +import javax.jcr.Session; + +import org.apache.jackrabbit.util.Text; +import org.apache.jackrabbit.webdav.security.CurrentUserPrivilegeSetProperty; +import org.apache.jackrabbit.webdav.security.Privilege; +import org.apache.jackrabbit.webdav.xml.Namespace; + +/** + * JcrPrivilegesProperty... + */ +public class JcrUserPrivilegesProperty { + + private final Session session; + private final String absPath; + + /** + * @param session The reading session + * @param absPath An absolute path to an existing JCR node or {@code null}. + */ + public JcrUserPrivilegesProperty(Session session, String absPath) throws RepositoryException { + this.session = session; + this.absPath = absPath; + } + + public CurrentUserPrivilegeSetProperty asDavProperty() throws RepositoryException { + List davPrivs = new ArrayList(); + for (javax.jcr.security.Privilege privilege : session.getAccessControlManager().getPrivileges(absPath)) { + String privilegeName = privilege.getName(); + + String prefix = Text.getNamespacePrefix(privilegeName); + Namespace ns = (prefix.isEmpty()) ? Namespace.EMPTY_NAMESPACE : Namespace.getNamespace(prefix, session.getNamespaceURI(prefix)); + davPrivs.add(Privilege.getPrivilege(Text.getLocalName(privilegeName), ns)); + } + + return new CurrentUserPrivilegeSetProperty(davPrivs.toArray(new Privilege[davPrivs.size()])); + } +} \ No newline at end of file Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/security/JcrUserPrivilegesProperty.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/webdav/jcr/security/SecurityUtils.java =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/security/SecurityUtils.java (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/security/SecurityUtils.java (working copy) @@ -0,0 +1,30 @@ +/* + * 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.webdav.jcr.security; + +import javax.jcr.Repository; +import javax.jcr.Session; + +public final class SecurityUtils { + + private SecurityUtils() {} + + public static boolean supportsAccessControl(Session session) { + String desc = session.getRepository().getDescriptor(Repository.OPTION_ACCESS_CONTROL_SUPPORTED); + return Boolean.valueOf(desc); + } +} \ No newline at end of file Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/security/SecurityUtils.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/webdav/jcr/transaction/TransactionListener.java =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/transaction/TransactionListener.java (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/transaction/TransactionListener.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.webdav.jcr.transaction; + +import org.apache.jackrabbit.webdav.transaction.TransactionResource; + +/** + * TransactionListener provides callbacks when a transaction + * is committed. + */ +public interface TransactionListener { + + /** + * This method is called right before a transaction is committed. + * + * @param resource the transaction resource which will be committed. + * @param lockToken the lock token + */ + public void beforeCommit(TransactionResource resource, String lockToken); + + /** + * This method is called after the commit has been executed. + * + * @param resource the transaction resource which had been committed. + * @param lockToken the lock token. + * @param success if the commit was successful. + */ + public void afterCommit(TransactionResource resource, String lockToken, boolean success); +} Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/transaction/TransactionListener.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/webdav/jcr/transaction/TxLockManagerImpl.java =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/transaction/TxLockManagerImpl.java (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/transaction/TxLockManagerImpl.java (working copy) @@ -0,0 +1,796 @@ +/* + * 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.webdav.jcr.transaction; + +import org.apache.jackrabbit.util.Text; +import org.apache.jackrabbit.webdav.DavConstants; +import org.apache.jackrabbit.webdav.DavException; +import org.apache.jackrabbit.webdav.DavResource; +import org.apache.jackrabbit.webdav.DavResourceLocator; +import org.apache.jackrabbit.webdav.DavServletResponse; +import org.apache.jackrabbit.webdav.WebdavResponse; +import org.apache.jackrabbit.webdav.jcr.JcrDavException; +import org.apache.jackrabbit.webdav.jcr.JcrDavSession; +import org.apache.jackrabbit.webdav.lock.ActiveLock; +import org.apache.jackrabbit.webdav.lock.LockInfo; +import org.apache.jackrabbit.webdav.lock.LockManager; +import org.apache.jackrabbit.webdav.lock.Scope; +import org.apache.jackrabbit.webdav.lock.Type; +import org.apache.jackrabbit.webdav.transaction.TransactionConstants; +import org.apache.jackrabbit.webdav.transaction.TransactionInfo; +import org.apache.jackrabbit.webdav.transaction.TransactionResource; +import org.apache.jackrabbit.webdav.transaction.TxActiveLock; +import org.apache.jackrabbit.webdav.transaction.TxLockManager; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.jcr.Item; +import javax.jcr.PathNotFoundException; +import javax.jcr.RepositoryException; +import javax.jcr.Session; +import javax.transaction.xa.XAException; +import javax.transaction.xa.XAResource; +import javax.transaction.xa.Xid; +import java.util.HashMap; +import java.util.Iterator; +import java.util.IdentityHashMap; +import java.util.Map; + +/** + * TxLockManagerImpl manages locks with locktype + * '{@link TransactionConstants#TRANSACTION dcr:transaction}'. + *

+ */ + //todo: removing all expired locks + //todo: 'local' and 'global' are not accurate terms in the given context > replace + /*todo: the usage of the 'global' transaction is not according to the JTA specification, + which explicitly requires any transaction present on a servlet to be completed before + the service method returns. Starting/completing transactions on the session object, + which is possible with the jackrabbit implementation is a hack.*/ + /*todo: review of this transaction part is therefore required. Is there a use-case + for those 'global' transactions at all...*/ +public class TxLockManagerImpl implements TxLockManager { + + private static Logger log = LoggerFactory.getLogger(TxLockManagerImpl.class); + + private final TransactionMap map = new TransactionMap(); + + private final Map listeners = new IdentityHashMap(); + + /** + * Create a new lock. + * + * @param lockInfo as present in the request body. + * @param resource + * @return the lock + * @throws DavException if the lock could not be obtained. + * @throws IllegalArgumentException if the resource is null or + * does not implement {@link TransactionResource} interface. + * @see LockManager#createLock(org.apache.jackrabbit.webdav.lock.LockInfo, org.apache.jackrabbit.webdav.DavResource) + */ + public ActiveLock createLock(LockInfo lockInfo, DavResource resource) + throws DavException { + if (resource == null || !(resource instanceof TransactionResource)) { + throw new IllegalArgumentException("Invalid resource"); + } + return createLock(lockInfo, (TransactionResource) resource); + } + + /** + * Create a new lock. + * + * @param lockInfo + * @param resource + * @return the lock + * @throws DavException if the request lock has the wrong lock type or if + * the lock could not be obtained for any reason. + */ + private synchronized ActiveLock createLock(LockInfo lockInfo, TransactionResource resource) + throws DavException { + if (!lockInfo.isDeep() || !TransactionConstants.TRANSACTION.equals(lockInfo.getType())) { + throw new DavException(DavServletResponse.SC_PRECONDITION_FAILED); + } + + ActiveLock existing = getLock(lockInfo.getType(), lockInfo.getScope(), resource); + if (existing != null) { + throw new DavException(DavServletResponse.SC_LOCKED); + } + // TODO: check for locks on member resources is required as well for lock is always deep! + + Transaction tx = createTransaction(resource.getLocator(), lockInfo); + tx.start(resource); + + // keep references to this lock + addReferences(tx, getMap(resource), resource); + + return tx.getLock(); + } + + /** + * Build the transaction object associated by the lock. + * + * @param locator + * @param lockInfo + * @return + */ + private Transaction createTransaction(DavResourceLocator locator, LockInfo lockInfo) { + if (TransactionConstants.GLOBAL.equals(lockInfo.getScope())) { + return new GlobalTransaction(locator, new TxActiveLock(lockInfo)); + } else { + return new LocalTransaction(locator, new TxActiveLock(lockInfo)); + } + } + + /** + * Refresh the lock identified by the given lock token. + * + * @param lockInfo + * @param lockToken + * @param resource + * @return the lock + * @throws DavException + * @throws IllegalArgumentException if the resource is null or + * does not implement {@link TransactionResource} interface. + * @see LockManager#refreshLock(org.apache.jackrabbit.webdav.lock.LockInfo, String, org.apache.jackrabbit.webdav.DavResource) + */ + public ActiveLock refreshLock(LockInfo lockInfo, String lockToken, + DavResource resource) throws DavException { + if (resource == null || !(resource instanceof TransactionResource)) { + throw new IllegalArgumentException("Invalid resource"); + } + return refreshLock(lockInfo, lockToken, (TransactionResource) resource); + } + + /** + * Reset the timeout of the lock identified by the given lock token. + * + * @param lockInfo + * @param lockToken + * @param resource + * @return + * @throws DavException if the lock did not exist or is expired. + */ + private synchronized ActiveLock refreshLock(LockInfo lockInfo, String lockToken, + TransactionResource resource) throws DavException { + + TransactionMap responsibleMap = getMap(resource); + Transaction tx = responsibleMap.get(lockToken); + if (tx == null) { + throw new DavException(DavServletResponse.SC_PRECONDITION_FAILED, "No valid transaction lock found for resource '" + resource.getResourcePath() + "'"); + } else if (tx.getLock().isExpired()) { + removeExpired(tx, responsibleMap, resource); + throw new DavException(DavServletResponse.SC_PRECONDITION_FAILED, "Transaction lock for resource '" + resource.getResourcePath() + "' was already expired."); + } else { + tx.getLock().setTimeout(lockInfo.getTimeout()); + } + return tx.getLock(); + } + + /** + * Throws UnsupportedOperationException. + * + * @param lockToken + * @param resource + * @throws DavException + * @see LockManager#releaseLock(String, org.apache.jackrabbit.webdav.DavResource) + */ + public void releaseLock(String lockToken, DavResource resource) + throws DavException { + throw new UnsupportedOperationException("A transaction lock can only be release with a TransactionInfo object and a lock token."); + } + + /** + * Release the lock identified by the given lock token. + * + * @param lockInfo + * @param lockToken + * @param resource + * @throws DavException + */ + public synchronized void releaseLock(TransactionInfo lockInfo, String lockToken, + TransactionResource resource) throws DavException { + if (resource == null) { + throw new IllegalArgumentException("Resource must not be null."); + } + TransactionMap responsibleMap = getMap(resource); + Transaction tx = responsibleMap.get(lockToken); + + if (tx == null) { + throw new DavException(DavServletResponse.SC_PRECONDITION_FAILED, "No transaction lock found for resource '" + resource.getResourcePath() + "'"); + } else if (tx.getLock().isExpired()) { + removeExpired(tx, responsibleMap, resource); + throw new DavException(DavServletResponse.SC_PRECONDITION_FAILED, "Transaction lock for resource '" + resource.getResourcePath() + "' was already expired."); + } else { + if (lockInfo.isCommit()) { + TransactionListener[] txListeners; + synchronized (listeners) { + txListeners = listeners.values().toArray(new TransactionListener[listeners.values().size()]); + } + for (TransactionListener txListener : txListeners) { + txListener.beforeCommit(resource, lockToken); + } + DavException ex = null; + try { + tx.commit(resource); + } catch (DavException e) { + ex = e; + } + for (TransactionListener txListener : txListeners) { + txListener.afterCommit(resource, lockToken, ex == null); + } + if (ex != null) { + throw ex; + } + } else { + tx.rollback(resource); + } + removeReferences(tx, responsibleMap, resource); + } + } + + /** + * Always returns null + * + * @param type + * @param scope + * @param resource + * @return null + * @see #getLock(Type, Scope, TransactionResource) + * @see LockManager#getLock(org.apache.jackrabbit.webdav.lock.Type, org.apache.jackrabbit.webdav.lock.Scope, org.apache.jackrabbit.webdav.DavResource) + */ + public ActiveLock getLock(Type type, Scope scope, DavResource resource) { + return null; + } + + /** + * Returns true if the given lock token belongs to a lock that applies to + * the given resource, false otherwise. The token may either be retrieved + * from the {@link DavConstants#HEADER_LOCK_TOKEN Lock-Token header} or + * from the {@link TransactionConstants#HEADER_TRANSACTIONID TransactionId header}. + * + * @param token + * @param resource + * @return + * @see LockManager#hasLock(String token, DavResource resource) + */ + public boolean hasLock(String token, DavResource resource) { + return getLock(token, null, resource) != null; + } + + /** + * Return the lock applied to the given resource or null + * + * @param type + * @param scope + * @param resource + * @return lock applied to the given resource or null + * @see LockManager#getLock(Type, Scope, DavResource) + * todo: is it correct to return one that specific lock, the current session is token-holder of? + */ + public ActiveLock getLock(Type type, Scope scope, TransactionResource resource) { + ActiveLock lock = null; + if (TransactionConstants.TRANSACTION.equals(type)) { + String[] sessionTokens = resource.getSession().getLockTokens(); + int i = 0; + while (lock == null && i < sessionTokens.length) { + String lockToken = sessionTokens[i]; + lock = getLock(lockToken, scope, resource); + i++; + } + } + return lock; + } + + //-----------------------------< listener support >------------------------- + + /** + * Adds a transaction listener to this TxLockManager. + * @param listener the listener to add. + */ + public void addTransactionListener(TransactionListener listener) { + synchronized (listeners) { + listeners.put(listener, listener); + } + } + + /** + * Removes a transaction listener from this TxLockManager. + * @param listener the listener to remove. + */ + public void removeTransactionListener(TransactionListener listener) { + synchronized (listeners) { + listeners.remove(listener); + } + } + + /** + * @param lockToken + * @param resource + * @return + */ + private ActiveLock getLock(String lockToken, Scope scope, DavResource resource) { + if (!(resource instanceof TransactionResource)) { + log.warn("TransactionResource expected"); + return null; + } + + ActiveLock lock = null; + Transaction tx = null; + TransactionMap m = map; + // check if main-map contains that txId + if (m.containsKey(lockToken)) { + tx = m.get(lockToken); + } else { + // look through all the nested tx-maps (i.e. global txs) for the given txId + Iterator it = m.values().iterator(); + while (it.hasNext() && tx == null) { + Transaction txMap = it.next(); + if (!txMap.isLocal()) { + m = (TransactionMap) txMap; + if (m.containsKey(lockToken)) { + tx = ((TransactionMap) txMap).get(lockToken); + } + } + } + } + + if (tx != null) { + if (tx.getLock().isExpired()) { + removeExpired(tx, m, (TransactionResource) resource); + } else if (tx.appliesToResource(resource) && (scope == null || tx.getLock().getScope().equals(scope))) { + lock = tx.getLock(); + } + } + return lock; + } + + /** + * Return the map that may contain a transaction lock for the given resource. + * In case the resource provides a transactionId, the map must be a + * repository transaction that is identified by the given id and which in + * turn can act as map. + * + * @param resource + * @return responsible map. + * @throws DavException if no map could be retrieved. + */ + private TransactionMap getMap(TransactionResource resource) + throws DavException { + + String txKey = resource.getTransactionId(); + if (txKey == null) { + return map; + } else { + if (!map.containsKey(txKey)) { + throw new DavException(DavServletResponse.SC_PRECONDITION_FAILED, "Transaction map '" + map + " does not contain a transaction with TransactionId '" + txKey + "'."); + } + Transaction tx = map.get(txKey); + if (tx.isLocal()) { + throw new DavException(DavServletResponse.SC_PRECONDITION_FAILED, "TransactionId '" + txKey + "' points to a local transaction, that cannot act as transaction map"); + } else if (tx.getLock() != null && tx.getLock().isExpired()) { + removeExpired(tx, map, resource); + throw new DavException(DavServletResponse.SC_PRECONDITION_FAILED, "Attempt to retrieve an expired global transaction."); + } + // tx is a global transaction that acts as map as well. + return (TransactionMap) tx; + } + } + + /** + * Rollbacks the specified transaction and releases the lock. This includes + * the removal of all references. + * + * @param tx + * @param responsibleMap + * @param resource + */ + private static void removeExpired(Transaction tx, TransactionMap responsibleMap, + TransactionResource resource) { + log.debug("Removing expired transaction lock " + tx); + try { + tx.rollback(resource); + removeReferences(tx, responsibleMap, resource); + } catch (DavException e) { + log.error("Error while removing expired transaction lock: " + e.getMessage()); + } + } + + /** + * Create the required references to the new transaction specified by tx. + * + * @param tx + * @param responsibleMap + * @param resource + * @throws DavException + */ + private static void addReferences(Transaction tx, TransactionMap responsibleMap, + TransactionResource resource) { + log.debug("Adding transactionId '" + tx.getId() + "' as session lock token."); + resource.getSession().addLockToken(tx.getId()); + + responsibleMap.put(tx.getId(), tx); + resource.getSession().addReference(tx.getId()); + } + + /** + * Remove all references to the specified transaction. + * + * @param tx + * @param responsibleMap + * @param resource + */ + private static void removeReferences(Transaction tx, TransactionMap responsibleMap, + TransactionResource resource) { + log.debug("Removing transactionId '" + tx.getId() + "' from session lock tokens."); + resource.getSession().removeLockToken(tx.getId()); + + responsibleMap.remove(tx.getId()); + resource.getSession().removeReference(tx.getId()); + } + + /** + * @param resource + * @return JCR session + */ + private static Session getRepositorySession(TransactionResource resource) throws DavException { + return JcrDavSession.getRepositorySession(resource.getSession()); + } + + //------------------------------------------< inner classes, interfaces >--- + /** + * Internal Transaction interface + */ + private interface Transaction { + + TxActiveLock getLock(); + + /** + * @return the id of this transaction. + */ + String getId(); + + /** + * @return path of the lock holding resource + */ + String getResourcePath(); + + /** + * @param resource + * @return true if the lock defined by this transaction applies to the + * given resource, either due to the resource holding that lock or due + * to a deep lock hold by any ancestor resource. + */ + boolean appliesToResource(DavResource resource); + + /** + * @return true if this transaction is used to allow for transient changes + * on the underlying repository, that may be persisted with the final + * UNLOCK request only. + */ + boolean isLocal(); + + /** + * Start this transaction. + * + * @param resource + * @throws DavException if an error occurs. + */ + void start(TransactionResource resource) throws DavException; + + /** + * Commit this transaction + * + * @param resource + * @throws DavException if an error occurs. + */ + void commit(TransactionResource resource) throws DavException; + + /** + * Rollback this transaction. + * + * @param resource + * @throws DavException if an error occurs. + */ + void rollback(TransactionResource resource) throws DavException; + } + + /** + * Abstract transaction covering functionally to both implementations. + */ + private abstract static class AbstractTransaction extends TransactionMap implements Transaction { + + private final DavResourceLocator locator; + private final TxActiveLock lock; + + private AbstractTransaction(DavResourceLocator locator, TxActiveLock lock) { + this.locator = locator; + this.lock = lock; + } + + //----------------------------------------------------< Transaction >--- + /** + * @see #getLock() + */ + public TxActiveLock getLock() { + return lock; + } + + /** + * @see #getId() + */ + public String getId() { + return lock.getToken(); + } + + /** + * @see #getResourcePath() + */ + public String getResourcePath() { + return locator.getResourcePath(); + } + + /** + * @see #appliesToResource(DavResource) + */ + public boolean appliesToResource(DavResource resource) { + if (locator.isSameWorkspace(resource.getLocator())) { + String lockResourcePath = getResourcePath(); + String resPath = resource.getResourcePath(); + + while (!"".equals(resPath)) { + if (lockResourcePath.equals(resPath)) { + return true; + } + resPath = Text.getRelativeParent(resPath, 1); + } + } + return false; + } + } + + /** + * Local transaction + */ + private final static class LocalTransaction extends AbstractTransaction { + + private LocalTransaction(DavResourceLocator locator, TxActiveLock lock) { + super(locator, lock); + } + + //----------------------------------------------------< Transaction >--- + /** + * @see org.apache.jackrabbit.webdav.jcr.transaction.TxLockManagerImpl.Transaction#isLocal() + */ + public boolean isLocal() { + return true; + } + + /** + * @see org.apache.jackrabbit.webdav.jcr.transaction.TxLockManagerImpl.Transaction#start(TransactionResource) + */ + public void start(TransactionResource resource) throws DavException { + try { + // make sure, the given resource represents an existing repository item + if (!getRepositorySession(resource).itemExists(resource.getLocator().getRepositoryPath())) { + throw new DavException(DavServletResponse.SC_CONFLICT, "Unable to start local transaction: no repository item present at " + getResourcePath()); + } + } catch (RepositoryException e) { + log.error("Unexpected error: " + e.getMessage()); + throw new JcrDavException(e); + } + } + + /** + * @see org.apache.jackrabbit.webdav.jcr.transaction.TxLockManagerImpl.Transaction#commit(TransactionResource) + */ + public void commit(TransactionResource resource) throws DavException { + try { + getItem(resource).save(); + } catch (RepositoryException e) { + throw new JcrDavException(e); + } + } + + /** + * @see org.apache.jackrabbit.webdav.jcr.transaction.TxLockManagerImpl.Transaction#rollback(TransactionResource) + */ + public void rollback(TransactionResource resource) throws DavException { + try { + getItem(resource).refresh(false); + } catch (RepositoryException e) { + throw new JcrDavException(e); + } + } + + //-------------------------------------------------< TransactionMap >--- + /** + * Always throws DavException. + * + * @see TransactionMap#putTransaction(String, org.apache.jackrabbit.webdav.jcr.transaction.TxLockManagerImpl.Transaction) + */ + @Override + public Transaction putTransaction(String key, Transaction value) throws DavException { + throw new DavException(WebdavResponse.SC_PRECONDITION_FAILED, "Attempt to nest a new transaction into a local one."); + } + + //--------------------------------------------------------< private >--- + /** + * Retrieve the repository item from the given transaction resource. + * + * @param resource + * @return + * @throws PathNotFoundException + * @throws RepositoryException + * @throws DavException + */ + private Item getItem(TransactionResource resource) throws PathNotFoundException, RepositoryException, DavException { + String itemPath = resource.getLocator().getRepositoryPath(); + return getRepositorySession(resource).getItem(itemPath); + } + } + + /** + * Global transaction + */ + private static class GlobalTransaction extends AbstractTransaction { + + private Xid xid; + + private GlobalTransaction(DavResourceLocator locator, TxActiveLock lock) { + super(locator, lock); + xid = new XidImpl(lock.getToken()); + } + + //----------------------------------------------------< Transaction >--- + /** + * @see org.apache.jackrabbit.webdav.jcr.transaction.TxLockManagerImpl.Transaction#isLocal() + */ + public boolean isLocal() { + return false; + } + + /** + * @see org.apache.jackrabbit.webdav.jcr.transaction.TxLockManagerImpl.Transaction#start(TransactionResource) + */ + public void start(TransactionResource resource) throws DavException { + XAResource xaRes = getXAResource(resource); + try { + xaRes.setTransactionTimeout((int) getLock().getTimeout() / 1000); + xaRes.start(xid, XAResource.TMNOFLAGS); + } catch (XAException e) { + throw new DavException(DavServletResponse.SC_FORBIDDEN, e.getMessage()); + } + } + + /** + * @see org.apache.jackrabbit.webdav.jcr.transaction.TxLockManagerImpl.Transaction#commit(TransactionResource) + */ + public void commit(TransactionResource resource) throws DavException { + XAResource xaRes = getXAResource(resource); + try { + xaRes.commit(xid, false); + removeLocalTxReferences(resource); + } catch (XAException e) { + throw new DavException(DavServletResponse.SC_FORBIDDEN, e.getMessage()); + } + } + + /** + * @see org.apache.jackrabbit.webdav.jcr.transaction.TxLockManagerImpl.Transaction#rollback(TransactionResource) + */ + public void rollback(TransactionResource resource) throws DavException { + XAResource xaRes = getXAResource(resource); + try { + xaRes.rollback(xid); + removeLocalTxReferences(resource); + } catch (XAException e) { + throw new DavException(DavServletResponse.SC_FORBIDDEN, e.getMessage()); + } + } + + //-------------------------------------------------< TransactionMap >--- + @Override + public Transaction putTransaction(String key, Transaction value) throws DavException { + if (!(value instanceof LocalTransaction)) { + throw new DavException(WebdavResponse.SC_PRECONDITION_FAILED, "Attempt to nest global transaction into a global one."); + } + return super.put(key, value); + } + + //--------------------------------------------------------< private >--- + private XAResource getXAResource(TransactionResource resource) throws DavException { + /* + // commented, since server should be jackrabbit independent + Session session = resource.getSession().getRepositorySession(); + if (session instanceof XASession) { + return ((XASession)session).getXAResource(); + } else { + throw new DavException(DavServletResponse.SC_FORBIDDEN); + } + */ + throw new DavException(DavServletResponse.SC_FORBIDDEN); + } + + private void removeLocalTxReferences(TransactionResource resource) { + for (Object o : values()) { + Transaction tx = (Transaction) o; + removeReferences(tx, this, resource); + } + } + } + + /** + * + */ + private static class TransactionMap extends HashMap { + + public Transaction get(String key) { + Transaction tx = null; + if (containsKey(key)) { + tx = super.get(key); + } + return tx; + } + + public Transaction putTransaction(String key, Transaction value) throws DavException { + // any global and local transactions allowed. + return super.put(key, value); + } + } + + /** + * Private class implementing Xid interface. + */ + private static class XidImpl implements Xid { + + private final String id; + + /** + * Create a new Xid + * + * @param id + */ + private XidImpl(String id) { + this.id = id; + } + + /** + * @return 1 + * @see javax.transaction.xa.Xid#getFormatId() + */ + public int getFormatId() { + // todo: define reasonable format id + return 1; + } + + /** + * @return an empty byte array. + * @see javax.transaction.xa.Xid#getBranchQualifier() + */ + public byte[] getBranchQualifier() { + return new byte[0]; + } + + /** + * @return id as byte array + * @see javax.transaction.xa.Xid#getGlobalTransactionId() + */ + public byte[] getGlobalTransactionId() { + return id.getBytes(); + } + } +} Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/transaction/TxLockManagerImpl.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/webdav/jcr/version/VersionHistoryItemCollection.java =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/version/VersionHistoryItemCollection.java (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/version/VersionHistoryItemCollection.java (working copy) @@ -0,0 +1,178 @@ +/* + * 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.webdav.jcr.version; + +import org.apache.jackrabbit.webdav.DavException; +import org.apache.jackrabbit.webdav.DavResource; +import org.apache.jackrabbit.webdav.DavResourceFactory; +import org.apache.jackrabbit.webdav.DavResourceLocator; +import org.apache.jackrabbit.webdav.DavServletResponse; +import org.apache.jackrabbit.webdav.jcr.DefaultItemCollection; +import org.apache.jackrabbit.webdav.jcr.ItemResourceConstants; +import org.apache.jackrabbit.webdav.jcr.JcrDavException; +import org.apache.jackrabbit.webdav.jcr.JcrDavSession; +import org.apache.jackrabbit.webdav.jcr.property.JcrDavPropertyNameSet; +import org.apache.jackrabbit.webdav.property.DavProperty; +import org.apache.jackrabbit.webdav.property.DavPropertyName; +import org.apache.jackrabbit.webdav.property.DefaultDavProperty; +import org.apache.jackrabbit.webdav.property.HrefProperty; +import org.apache.jackrabbit.webdav.property.ResourceType; +import org.apache.jackrabbit.webdav.version.VersionHistoryResource; +import org.apache.jackrabbit.webdav.version.VersionResource; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.jcr.Item; +import javax.jcr.RepositoryException; +import javax.jcr.version.VersionHistory; +import javax.jcr.version.VersionIterator; +import java.util.ArrayList; + +/** + * VersionHistoryItemCollection represents a JCR version history. + * + * @see VersionHistory + */ +public class VersionHistoryItemCollection extends DefaultItemCollection + implements VersionHistoryResource { + + private static Logger log = LoggerFactory.getLogger(VersionHistoryItemCollection.class); + + /** + * Create a new VersionHistoryItemCollection resource. + * + * @param resourcePath + * @param session + * @param factory + */ + public VersionHistoryItemCollection(DavResourceLocator resourcePath, + JcrDavSession session, + DavResourceFactory factory, + Item item) { + super(resourcePath, session, factory, item); + if (item == null || !(item instanceof VersionHistory)) { + throw new IllegalArgumentException("VersionHistory item expected."); + } + } + + //----------------------------------------------< DavResource interface >--- + /** + * @see org.apache.jackrabbit.webdav.DavResource#getSupportedMethods() + */ + @Override + public String getSupportedMethods() { + StringBuffer sb = new StringBuffer(ItemResourceConstants.METHODS); + sb.append(", ").append(VersionHistoryResource.METHODS); + return sb.toString(); + } + + @Override + public DavProperty getProperty(DavPropertyName name) { + DavProperty prop = super.getProperty(name); + if (prop == null) { + // required, protected version-set property for version-history resource + try { + if (ROOT_VERSION.equals(name)) { + // required root-version property for version-history resource + String rootVersionHref = getLocatorFromItem(((VersionHistory)item).getRootVersion()).getHref(true); + prop = new HrefProperty(ROOT_VERSION, rootVersionHref, true); + } else if (VERSION_SET.equals(name)) { + VersionIterator vIter = ((VersionHistory) item).getAllVersions(); + prop = getHrefProperty(VERSION_SET, vIter, true); + } + } catch (RepositoryException e) { + log.error(e.getMessage()); + } + } + + return prop; + } + + /** + * Removing a version resource is achieved by calling removeVersion + * on the versionhistory item this version belongs to. + * + * @throws DavException if the version does not exist or if an error occurs + * while deleting. + * @see DavResource#removeMember(org.apache.jackrabbit.webdav.DavResource) + */ + @Override + public void removeMember(DavResource member) throws DavException { + if (exists()) { + VersionHistory versionHistory = (VersionHistory) item; + try { + versionHistory.removeVersion(getItemName(member.getLocator().getRepositoryPath())); + } catch (RepositoryException e) { + throw new JcrDavException(e); + } + } else { + throw new DavException(DavServletResponse.SC_NOT_FOUND); + } + } + //-----------------------------------< VersionHistoryResource interface >--- + /** + * Return an array of {@link VersionResource}s representing all versions + * present in the underlying JCR version history. + * + * @return array of {@link VersionResource}s representing all versions + * present in the underlying JCR version history. + * @throws DavException + * @see org.apache.jackrabbit.webdav.version.VersionHistoryResource#getVersions() + */ + public VersionResource[] getVersions() throws DavException { + try { + VersionIterator vIter = ((VersionHistory)item).getAllVersions(); + ArrayList l = new ArrayList(); + while (vIter.hasNext()) { + DavResourceLocator versionLoc = getLocatorFromItem(vIter.nextVersion()); + VersionResource vr = (VersionResource) createResourceFromLocator(versionLoc); + l.add(vr); + } + return l.toArray(new VersionResource[l.size()]); + } catch (RepositoryException e) { + throw new JcrDavException(e); + } + } + + //-------------------------------------------------------------------------- + @Override + protected void initPropertyNames() { + super.initPropertyNames(); + + if (exists()) { + names.addAll(JcrDavPropertyNameSet.VERSIONHISTORY_SET); + } + } + + /** + * Fill the property set for this resource. + */ + @Override + protected void initProperties() { + super.initProperties(); + + // change resource type defined by default item collection + properties.add(new ResourceType(ResourceType.VERSION_HISTORY)); + + // jcr specific property pointing to the node this history belongs to + try { + properties.add(new DefaultDavProperty(JCR_VERSIONABLEUUID, ((VersionHistory)item).getVersionableIdentifier())); + } catch (RepositoryException e) { + log.error(e.getMessage()); + } + } +} Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/version/VersionHistoryItemCollection.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/webdav/jcr/version/VersionItemCollection.java =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/version/VersionItemCollection.java (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/version/VersionItemCollection.java (working copy) @@ -0,0 +1,240 @@ +/* + * 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.webdav.jcr.version; + +import org.apache.jackrabbit.JcrConstants; +import org.apache.jackrabbit.webdav.DavException; +import org.apache.jackrabbit.webdav.DavResourceFactory; +import org.apache.jackrabbit.webdav.DavResourceLocator; +import org.apache.jackrabbit.webdav.DavServletResponse; +import org.apache.jackrabbit.webdav.jcr.property.JcrDavPropertyNameSet; +import org.apache.jackrabbit.webdav.property.DavProperty; +import org.apache.jackrabbit.webdav.util.HttpDateFormat; +import org.apache.jackrabbit.webdav.jcr.DefaultItemCollection; +import org.apache.jackrabbit.webdav.jcr.ItemResourceConstants; +import org.apache.jackrabbit.webdav.jcr.JcrDavException; +import org.apache.jackrabbit.webdav.jcr.JcrDavSession; +import org.apache.jackrabbit.webdav.property.DavPropertyName; +import org.apache.jackrabbit.webdav.property.DefaultDavProperty; +import org.apache.jackrabbit.webdav.property.HrefProperty; +import org.apache.jackrabbit.webdav.version.LabelInfo; +import org.apache.jackrabbit.webdav.version.LabelSetProperty; +import org.apache.jackrabbit.webdav.version.VersionHistoryResource; +import org.apache.jackrabbit.webdav.version.VersionResource; +import org.apache.jackrabbit.webdav.version.report.ReportType; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.jcr.Item; +import javax.jcr.Node; +import javax.jcr.Property; +import javax.jcr.PropertyIterator; +import javax.jcr.RepositoryException; +import javax.jcr.version.Version; +import javax.jcr.version.VersionHistory; +import java.util.ArrayList; +import java.util.List; + +/** + * VersionItemCollection represents a JCR version. + * + * @see Version + */ +public class VersionItemCollection extends DefaultItemCollection + implements VersionResource { + + private static Logger log = LoggerFactory.getLogger(VersionItemCollection.class); + + /** + * Create a new VersionItemCollection. + * + * @param locator + * @param session + * @param factory + */ + public VersionItemCollection(DavResourceLocator locator, + JcrDavSession session, + DavResourceFactory factory, Item item) { + super(locator, session, factory, item); + if (item == null || !(item instanceof Version)) { + throw new IllegalArgumentException("Version item expected."); + } + } + + @Override + public DavProperty getProperty(DavPropertyName name) { + DavProperty prop = super.getProperty(name); + if (prop == null && exists()) { + Version v = (Version) item; + try { + if (VERSION_NAME.equals(name)) { + // required, protected DAV:version-name property + prop = new DefaultDavProperty(VERSION_NAME, v.getName(), true); + } else if (VERSION_HISTORY.equals(name)) { + // required DAV:version-history (computed) property + String vhHref = getLocatorFromItem(getVersionHistoryItem()).getHref(true); + prop = new HrefProperty(VERSION_HISTORY, vhHref, true); + } else if (PREDECESSOR_SET.equals(name)) { + // required DAV:predecessor-set (protected) property + prop = getHrefProperty(VersionResource.PREDECESSOR_SET, v.getPredecessors(), true); + } else if (SUCCESSOR_SET.equals(name)) { + // required DAV:successor-set (computed) property + prop = getHrefProperty(SUCCESSOR_SET, v.getSuccessors(), true); + } else if (LABEL_NAME_SET.equals(name)) { + // required, protected DAV:label-name-set property + String[] labels = getVersionHistoryItem().getVersionLabels(v); + prop = new LabelSetProperty(labels); + } else if (CHECKOUT_SET.equals(name)) { + // required DAV:checkout-set (computed) property + PropertyIterator it = v.getReferences(); + List nodeList = new ArrayList(); + while (it.hasNext()) { + Property p = it.nextProperty(); + if (JcrConstants.JCR_BASEVERSION.equals(p.getName())) { + Node n = p.getParent(); + if (n.isCheckedOut()) { + nodeList.add(n); + } + } + } + prop = getHrefProperty(CHECKOUT_SET, nodeList.toArray(new Node[nodeList.size()]), true); + } + } catch (RepositoryException e) { + log.error(e.getMessage()); + } + } + + return prop; + } + + //----------------------------------------------< DavResource interface >--- + /** + * @see org.apache.jackrabbit.webdav.DavResource#getSupportedMethods() + */ + @Override + public String getSupportedMethods() { + StringBuffer sb = new StringBuffer(ItemResourceConstants.METHODS); + sb.append(", ").append(VersionResource.METHODS); + return sb.toString(); + } + + //------------------------------------------< VersionResource interface >--- + /** + * Modify the labels defined for the underlying repository version. + * + * @param labelInfo + * @throws org.apache.jackrabbit.webdav.DavException + * @see VersionResource#label(org.apache.jackrabbit.webdav.version.LabelInfo) + * @see VersionHistory#addVersionLabel(String, String, boolean) + * @see VersionHistory#removeVersionLabel(String) + */ + public void label(LabelInfo labelInfo) throws DavException { + if (labelInfo == null) { + throw new DavException(DavServletResponse.SC_BAD_REQUEST, "Valid label request body required."); + } + if (!exists()) { + throw new DavException(DavServletResponse.SC_NOT_FOUND); + } + try { + VersionHistory vh = getVersionHistoryItem(); + if (labelInfo.getType() == LabelInfo.TYPE_REMOVE) { + vh.removeVersionLabel(labelInfo.getLabelName()); + } else if (labelInfo.getType() == LabelInfo.TYPE_ADD) { + // ADD: only add if not yet existing + vh.addVersionLabel(item.getName(), labelInfo.getLabelName(), false); + } else { + // SET: move label if already existing + vh.addVersionLabel(item.getName(), labelInfo.getLabelName(), true); + } + } catch (RepositoryException e) { + throw new JcrDavException(e); + } + } + + /** + * Returns the {@link VersionHistory} associated with the repository version. + * Note: in contrast to a versionable node, the version history of a version + * item is always represented by its nearest ancestor. + * + * @return the {@link VersionHistoryResource} associated with this resource. + * @throws org.apache.jackrabbit.webdav.DavException + * @see org.apache.jackrabbit.webdav.version.VersionResource#getVersionHistory() + * @see javax.jcr.Item#getParent() + */ + public VersionHistoryResource getVersionHistory() throws DavException { + if (!exists()) { + throw new DavException(DavServletResponse.SC_NOT_FOUND); + } + + try { + VersionHistory vh = getVersionHistoryItem(); + DavResourceLocator loc = getLocatorFromItem(vh); + return (VersionHistoryResource) createResourceFromLocator(loc); + } catch (RepositoryException e) { + throw new JcrDavException(e); + } + } + + /** + * Return versionhistory that contains this version item + * + * @return versionhistory that contains this version item + * @throws RepositoryException + * @see javax.jcr.version.Version#getContainingHistory() + */ + private VersionHistory getVersionHistoryItem() throws RepositoryException { + return ((Version)item).getContainingHistory(); + } + + //-------------------------------------------------------------------------- + /** + * Define the set of reports supported by this resource. + * + * @see org.apache.jackrabbit.webdav.version.report.SupportedReportSetProperty + */ + @Override + protected void initSupportedReports() { + super.initSupportedReports(); + if (exists()) { + supportedReports.addReportType(ReportType.VERSION_TREE); + } + } + + @Override + protected void initPropertyNames() { + super.initPropertyNames(); + + if (exists()) { + names.addAll(JcrDavPropertyNameSet.VERSION_SET); + } + } + + @Override + protected String getCreationDate() { + if (exists()) { + Version v = (Version) item; + try { + return HttpDateFormat.creationDateFormat().format(v.getCreated().getTime()); + } catch (RepositoryException e) { + log.error(e.getMessage()); + } + } + + // fallback + return super.getCreationDate(); + } +} Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/version/VersionItemCollection.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/webdav/jcr/version/report/AbstractJcrReport.java =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/version/report/AbstractJcrReport.java (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/version/report/AbstractJcrReport.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.webdav.jcr.version.report; + +import javax.jcr.Session; + +import org.apache.jackrabbit.webdav.DavConstants; +import org.apache.jackrabbit.webdav.DavException; +import org.apache.jackrabbit.webdav.DavResource; +import org.apache.jackrabbit.webdav.DavServletResponse; +import org.apache.jackrabbit.webdav.DavSession; +import org.apache.jackrabbit.webdav.jcr.JcrDavSession; +import org.apache.jackrabbit.webdav.version.report.AbstractReport; +import org.apache.jackrabbit.webdav.version.report.Report; +import org.apache.jackrabbit.webdav.version.report.ReportInfo; + +/** + * AbstractJcrReport... + */ +public abstract class AbstractJcrReport extends AbstractReport { + + private Session session; + private ReportInfo reportInfo; + + /** + * Performs basic validation checks common to all JCR specific reports. + * + * @param resource + * @param info + * @throws DavException + * @see Report#init(DavResource, ReportInfo) + */ + public void init(DavResource resource, ReportInfo info) throws DavException { + if (resource == null || info == null) { + throw new DavException(DavServletResponse.SC_BAD_REQUEST, "Unable to run report: WebDAV Resource and ReportInfo must not be null."); + } + if (!getType().isRequestedReportType(info)) { + throw new DavException(DavServletResponse.SC_BAD_REQUEST, "Expected report type: '" + getType().getReportName() + "', found: '" + info.getReportName() + ";" + "'."); + } + if (info.getDepth() > DavConstants.DEPTH_0) { + throw new DavException(DavServletResponse.SC_BAD_REQUEST, "Invalid Depth header: " + info.getDepth()); + } + + DavSession davSession = resource.getSession(); + if (davSession == null) { + throw new DavException(DavServletResponse.SC_BAD_REQUEST, "The resource must provide a non-null session object in order to create '" + getType().getReportName()+ "' report."); + } + session = JcrDavSession.getRepositorySession(resource.getSession()); + if (session == null) { + throw new DavException(DavServletResponse.SC_INTERNAL_SERVER_ERROR, "Internal error: Unable to access repository session."); + } + reportInfo = info; + } + + //-----------------------------------------------------< implementation >--- + /** + * @return session Session object as obtained from the {@link DavSession}. + */ + Session getRepositorySession() { + return session; + } + + /** + * @return reportInfo the ReportInfo specifying the requested + * report details. + */ + ReportInfo getReportInfo() { + return reportInfo; + } +} Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/version/report/AbstractJcrReport.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/webdav/jcr/version/report/ExportViewReport.java =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/version/report/ExportViewReport.java (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/version/report/ExportViewReport.java (working copy) @@ -0,0 +1,159 @@ +/* + * 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.webdav.jcr.version.report; + +import org.apache.jackrabbit.commons.webdav.JcrRemotingConstants; +import org.apache.jackrabbit.util.Text; +import org.apache.jackrabbit.webdav.DavException; +import org.apache.jackrabbit.webdav.DavResource; +import org.apache.jackrabbit.webdav.jcr.ItemResourceConstants; +import org.apache.jackrabbit.webdav.jcr.JcrDavException; +import org.apache.jackrabbit.webdav.version.report.Report; +import org.apache.jackrabbit.webdav.version.report.ReportInfo; +import org.apache.jackrabbit.webdav.version.report.ReportType; +import org.apache.jackrabbit.webdav.xml.DomUtil; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.xml.sax.SAXException; + +import javax.jcr.PathNotFoundException; +import javax.jcr.RepositoryException; +import javax.jcr.Session; +import javax.xml.parsers.ParserConfigurationException; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; + +/** + * ExportViewReport handles REPORT requests for the 'exportview' + * report. The 'exportview' report is used to export + * {@link Session#exportDocumentView(String, java.io.OutputStream, boolean, boolean) DocView} + * and {@link Session#exportSystemView(String, java.io.OutputStream, boolean, boolean) SysView} + * of the {@link javax.jcr.Item item} represented by the requested resource. + *

+ * The request body must contain a {@link ItemResourceConstants#NAMESPACE dcr}:exportview + * element: + *

+ * <!ELEMENT exportview  ( (sysview | docview)?, skipbinary?, norecurse ) >
+ * <!ELEMENT sysview EMPTY >
+ * <!ELEMENT docview EMPTY >
+ * <!ELEMENT skipbinary EMPTY >
+ * <!ELEMENT norecurse EMPTY >
+ * 
+ * If no view type is specified the DocView is generated. + */ +public class ExportViewReport extends AbstractJcrReport { + + private static Logger log = LoggerFactory.getLogger(ExportViewReport.class); + + /** + * The exportview report type + */ + public static final ReportType EXPORTVIEW_REPORT = ReportType.register(JcrRemotingConstants.REPORT_EXPORT_VIEW, ItemResourceConstants.NAMESPACE, ExportViewReport.class); + + private String absNodePath; + + /** + * Returns {@link #EXPORTVIEW_REPORT} report type. + * + * @return {@link #EXPORTVIEW_REPORT} + * @see org.apache.jackrabbit.webdav.version.report.Report#getType() + */ + public ReportType getType() { + return EXPORTVIEW_REPORT; + } + + /** + * Always returns false. + * + * @return false + */ + public boolean isMultiStatusReport() { + return false; + } + + /** + * @see Report#init(DavResource, ReportInfo) + */ + @Override + public void init(DavResource resource, ReportInfo info) throws DavException { + // delegate validation to super class + super.init(resource, info); + // report specific validation: resource must represent an existing + // repository node + absNodePath = resource.getLocator().getRepositoryPath(); + try { + if (!(getRepositorySession().itemExists(absNodePath) && getRepositorySession().getItem(absNodePath).isNode())) { + throw new JcrDavException(new PathNotFoundException(absNodePath + " does not exist.")); + } + } catch (RepositoryException e) { + throw new JcrDavException(e); + } + + } + + /** + * Creates a Xml document from the generated view. + * + * @param document + * @return Xml element representing the output of the specified view. + * @see org.apache.jackrabbit.webdav.xml.XmlSerializable#toXml(Document) + */ + public Element toXml(Document document) { + boolean skipBinary = getReportInfo().containsContentElement("skipbinary", ItemResourceConstants.NAMESPACE); + boolean noRecurse = getReportInfo().containsContentElement("norecurse", ItemResourceConstants.NAMESPACE); + // todo improve... + try { + // create tmpFile in default system-tmp directory + String prefix = "_tmp_" + Text.getName(absNodePath); + File tmpfile = File.createTempFile(prefix, null, null); + tmpfile.deleteOnExit(); + + FileOutputStream out = new FileOutputStream(tmpfile); + if (getReportInfo().containsContentElement("sysview", ItemResourceConstants.NAMESPACE)) { + getRepositorySession().exportSystemView(absNodePath, out, skipBinary, noRecurse); + } else { + // default is docview + getRepositorySession().exportDocumentView(absNodePath, out, skipBinary, noRecurse); + } + out.close(); + + Document tmpDoc = + DomUtil.parseDocument(new FileInputStream(tmpfile)); + + // import the root node of the generated xml to the given document. + Element rootElem = (Element)document.importNode(tmpDoc.getDocumentElement(), true); + return rootElem; + + } catch (RepositoryException e) { + log.error(e.getMessage()); + } catch (FileNotFoundException e) { + log.error(e.getMessage()); + } catch (IOException e) { + log.error(e.getMessage()); + } catch (ParserConfigurationException e) { + log.error(e.getMessage()); + } catch (SAXException e) { + log.error(e.getMessage()); + } + return null; + } +} Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/version/report/ExportViewReport.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/webdav/jcr/version/report/JcrPrivilegeReport.java =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/version/report/JcrPrivilegeReport.java (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/version/report/JcrPrivilegeReport.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.webdav.jcr.version.report; + +import org.apache.jackrabbit.commons.webdav.JcrRemotingConstants; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.apache.jackrabbit.webdav.version.report.Report; +import org.apache.jackrabbit.webdav.version.report.ReportType; +import org.apache.jackrabbit.webdav.version.report.ReportInfo; +import org.apache.jackrabbit.webdav.jcr.ItemResourceConstants; +import org.apache.jackrabbit.webdav.MultiStatus; +import org.apache.jackrabbit.webdav.DavResource; +import org.apache.jackrabbit.webdav.DavException; +import org.apache.jackrabbit.webdav.DavConstants; +import org.apache.jackrabbit.webdav.MultiStatusResponse; +import org.apache.jackrabbit.webdav.DavServletResponse; +import org.apache.jackrabbit.webdav.DavResourceLocator; +import org.apache.jackrabbit.webdav.xml.DomUtil; +import org.apache.jackrabbit.webdav.security.Privilege; +import org.apache.jackrabbit.webdav.security.CurrentUserPrivilegeSetProperty; +import org.w3c.dom.Element; +import org.w3c.dom.Document; + +import javax.jcr.RepositoryException; +import java.util.List; +import java.util.ArrayList; + +/** + *

Report to retrieve the permissions granted to the reading session as defined + * by {@link javax.jcr.Session#hasPermission(String, String)}.

+ * + *

NOTE: the name of this report and the names of the privileges are + * misleading as they rather correspond to the actions defined by + * {@link javax.jcr.Session}; while the JCR privileges s.str. have only been + * specified as of JSR 283 in the {@link javax.jcr.security.Privilege} interface. + * A better name would have been JcrActionReport

+ * + * @see org.apache.jackrabbit.webdav.jcr.security.JcrUserPrivilegesProperty for + * the webdav correspondence to {@link javax.jcr.security.AccessControlManager#getPrivileges(String)} + * mapped to the {@link org.apache.jackrabbit.webdav.security.CurrentUserPrivilegeSetProperty}. + */ +public class JcrPrivilegeReport extends AbstractJcrReport { + + private static Logger log = LoggerFactory.getLogger(JcrPrivilegeReport.class); + + /** + * The exportview report type + */ + public static final ReportType PRIVILEGES_REPORT = ReportType.register(JcrRemotingConstants.REPORT_PRIVILEGES, ItemResourceConstants.NAMESPACE, JcrPrivilegeReport.class); + + private static final Privilege[] PRIVS = new Privilege[] { + ItemResourceConstants.PRIVILEGE_JCR_READ, + ItemResourceConstants.PRIVILEGE_JCR_ADD_NODE, + ItemResourceConstants.PRIVILEGE_JCR_SET_PROPERTY, + ItemResourceConstants.PRIVILEGE_JCR_REMOVE}; + + private final MultiStatus ms = new MultiStatus(); + + /** + * Returns {@link #PRIVILEGES_REPORT} report type. + * + * @return {@link #PRIVILEGES_REPORT} + * @see org.apache.jackrabbit.webdav.version.report.Report#getType() + */ + @Override + public ReportType getType() { + return PRIVILEGES_REPORT; + } + + /** + * Always returns true. + * + * @return true + * @see org.apache.jackrabbit.webdav.version.report.Report#isMultiStatusReport() + */ + @Override + public boolean isMultiStatusReport() { + return true; + } + + /** + * @see Report#init(DavResource, ReportInfo) + */ + @Override + public void init(DavResource resource, ReportInfo info) throws DavException { + // delegate basic validation to super class + super.init(resource, info); + // make also sure, the info contains a DAV:href child element + if (!info.containsContentElement(DavConstants.XML_HREF, DavConstants.NAMESPACE)) { + throw new DavException(DavServletResponse.SC_BAD_REQUEST, "dcr:privileges element must at least contain a single DAV:href child."); + } + // immediately build the final multistatus element + Element hrefElem = info.getContentElement(DavConstants.XML_HREF, DavConstants.NAMESPACE); + String href = DomUtil.getTextTrim(hrefElem); + href = normalizeResourceHref(obtainAbsolutePathFromUri(href)); // TODO: we should check whether the authority component matches + DavResourceLocator resourceLoc = resource.getLocator(); + DavResourceLocator loc = resourceLoc.getFactory().createResourceLocator(resourceLoc.getPrefix(), href); + // immediately build the final multistatus element + addResponses(loc); + } + + /** + * Creates a Xml document from the generated view. + * + * @param document + * @return Xml element representing the output of the specified view. + * @see org.apache.jackrabbit.webdav.xml.XmlSerializable#toXml(Document) + */ + @Override + public Element toXml(Document document) { + return ms.toXml(document); + } + + private void addResponses(DavResourceLocator locator) { + String repositoryPath = locator.getRepositoryPath(); + MultiStatusResponse resp = new MultiStatusResponse(locator.getHref(false), null); + List currentPrivs = new ArrayList(); + for (Privilege priv : PRIVS) { + try { + if (getRepositorySession().hasPermission(repositoryPath, priv.getName())) { + currentPrivs.add(priv); + } + } catch (RepositoryException e) { + // ignore + log.debug(e.toString()); + } + } + resp.add(new CurrentUserPrivilegeSetProperty(currentPrivs.toArray(new Privilege[currentPrivs.size()]))); + ms.addResponse(resp); + } + + private static String obtainAbsolutePathFromUri(String uri) { + try { + java.net.URI u = new java.net.URI(uri); + StringBuilder sb = new StringBuilder(); + sb.append(u.getRawPath()); + if (u.getRawQuery() != null) { + sb.append("?").append(u.getRawQuery()); + } + return sb.toString(); + } + catch (java.net.URISyntaxException ex) { + log.warn("parsing " + uri, ex); + return uri; + } + } +} Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/version/report/JcrPrivilegeReport.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/webdav/jcr/version/report/LocateByUuidReport.java =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/version/report/LocateByUuidReport.java (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/version/report/LocateByUuidReport.java (working copy) @@ -0,0 +1,117 @@ +/* + * 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.webdav.jcr.version.report; + +import org.apache.jackrabbit.commons.webdav.JcrRemotingConstants; +import org.apache.jackrabbit.webdav.DavConstants; +import org.apache.jackrabbit.webdav.DavException; +import org.apache.jackrabbit.webdav.DavResource; +import org.apache.jackrabbit.webdav.DavResourceLocator; +import org.apache.jackrabbit.webdav.DavServletResponse; +import org.apache.jackrabbit.webdav.MultiStatus; +import org.apache.jackrabbit.webdav.jcr.ItemResourceConstants; +import org.apache.jackrabbit.webdav.jcr.JcrDavException; +import org.apache.jackrabbit.webdav.version.report.Report; +import org.apache.jackrabbit.webdav.version.report.ReportInfo; +import org.apache.jackrabbit.webdav.version.report.ReportType; +import org.apache.jackrabbit.webdav.xml.DomUtil; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +import javax.jcr.Node; +import javax.jcr.RepositoryException; + +/** + * LocateByUuidReport handles REPORT requests for the 'locate-by-uuid' + * report. + *

+ * The request body must be a 'dcr:locate-by-uuid' XML element: + *

+ * <!ELEMENT locate-by-uuid ( href , prop? ) >
+ * 
+ * The response to a successful report request will be a Multi-Status response. + */ +public class LocateByUuidReport extends AbstractJcrReport { + + private static Logger log = LoggerFactory.getLogger(LocateByUuidReport.class); + + /** + * The exportview report type + */ + public static final ReportType LOCATE_BY_UUID_REPORT = ReportType.register(JcrRemotingConstants.REPORT_LOCATE_BY_UUID, ItemResourceConstants.NAMESPACE, LocateByUuidReport.class); + + private MultiStatus ms; + + /** + * Returns {@link #LOCATE_BY_UUID_REPORT} report type. + * + * @return {@link #LOCATE_BY_UUID_REPORT} + * @see org.apache.jackrabbit.webdav.version.report.Report#getType() + */ + public ReportType getType() { + return LOCATE_BY_UUID_REPORT; + } + + /** + * Always returns true. + * + * @return true + * @see org.apache.jackrabbit.webdav.version.report.Report#isMultiStatusReport() + */ + public boolean isMultiStatusReport() { + return true; + } + + /** + * @see Report#init(DavResource, ReportInfo) + */ + @Override + public void init(DavResource resource, ReportInfo info) throws DavException { + // delegate basic validation to super class + super.init(resource, info); + // make also sure, the info contains a DAV:href child element + if (!info.containsContentElement(DavConstants.XML_HREF, DavConstants.NAMESPACE)) { + throw new DavException(DavServletResponse.SC_BAD_REQUEST, "dcr:locate-by-uuid element must at least contain a single DAV:href child."); + } + // immediately build the final multistatus element + try { + Element hrefElem = info.getContentElement(DavConstants.XML_HREF, DavConstants.NAMESPACE); + String uuid = DomUtil.getTextTrim(hrefElem); + DavResourceLocator resourceLoc = resource.getLocator(); + Node n = getRepositorySession().getNodeByUUID(uuid); + DavResourceLocator loc = resourceLoc.getFactory().createResourceLocator(resourceLoc.getPrefix(), resourceLoc.getWorkspacePath(), n.getPath(), false); + DavResource locatedResource = resource.getFactory().createResource(loc, resource.getSession()); + ms = new MultiStatus(); + ms.addResourceProperties(locatedResource, info.getPropertyNameSet(), info.getDepth()); + } catch (RepositoryException e) { + throw new JcrDavException(e); + } + } + + /** + * Creates a Xml document from the generated view. + * + * @param document + * @return Xml element representing the output of the specified view. + * @see org.apache.jackrabbit.webdav.xml.XmlSerializable#toXml(Document) + */ + public Element toXml(Document document) { + return ms.toXml(document); + } +} Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/version/report/LocateByUuidReport.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/webdav/jcr/version/report/LocateCorrespondingNodeReport.java =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/version/report/LocateCorrespondingNodeReport.java (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/version/report/LocateCorrespondingNodeReport.java (working copy) @@ -0,0 +1,151 @@ +/* + * 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.webdav.jcr.version.report; + +import org.apache.jackrabbit.commons.webdav.JcrRemotingConstants; +import org.apache.jackrabbit.webdav.DavConstants; +import org.apache.jackrabbit.webdav.DavException; +import org.apache.jackrabbit.webdav.DavResource; +import org.apache.jackrabbit.webdav.DavResourceLocator; +import org.apache.jackrabbit.webdav.DavServletResponse; +import org.apache.jackrabbit.webdav.jcr.ItemResourceConstants; +import org.apache.jackrabbit.webdav.jcr.JcrDavException; +import org.apache.jackrabbit.webdav.version.DeltaVConstants; +import org.apache.jackrabbit.webdav.version.report.Report; +import org.apache.jackrabbit.webdav.version.report.ReportInfo; +import org.apache.jackrabbit.webdav.version.report.ReportType; +import org.apache.jackrabbit.webdav.xml.DomUtil; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +import javax.jcr.Item; +import javax.jcr.Node; +import javax.jcr.PathNotFoundException; +import javax.jcr.RepositoryException; +import javax.jcr.Session; + +/** + * LocateCorrespondingNodeReport is used to identify the resource that + * represents the corresponding node in another workspace. + * + *

+ * The request body must be a 'dcr:locate-corresponding-node' XML element, that + * contains the href of the source workspace, where the corresponding node should + * be searched: + *

+ * <!ELEMENT locate-corresponding-node ( workspace ) >
+ * <!ELEMENT workspace ( href ) >  (as defined by RFC 3253)
+ * 
+ * The response to a successful report request must be a 'dcr:locate-corresponding-node-report' + * element that contains the href of the corresponding node in the given source + * workspace: + * + *
+ * <!ELEMENT locate-corresponding-node-report ( href ) >
+ * 
+ * + * @see javax.jcr.Node#getCorrespondingNodePath(String) + */ +public class LocateCorrespondingNodeReport extends AbstractJcrReport { + + private static Logger log = LoggerFactory.getLogger(LocateCorrespondingNodeReport.class); + + private String correspHref; + + /** + * The corresponding-node report type + */ + public static final ReportType LOCATE_CORRESPONDING_NODE_REPORT = ReportType.register(JcrRemotingConstants.REPORT_LOCATE_CORRESPONDING_NODE, ItemResourceConstants.NAMESPACE, LocateByUuidReport.class); + + /** + * Returns {@link #LOCATE_CORRESPONDING_NODE_REPORT} + * + * @return always returns {@link #LOCATE_CORRESPONDING_NODE_REPORT} + * @see org.apache.jackrabbit.webdav.version.report.Report#getType() + */ + public ReportType getType() { + return LOCATE_CORRESPONDING_NODE_REPORT; + } + + /** + * Always returns false. + * + * @return false + * @see org.apache.jackrabbit.webdav.version.report.Report#isMultiStatusReport() + */ + public boolean isMultiStatusReport() { + return false; + } + + /** + * @see Report#init(DavResource, ReportInfo) + */ + @Override + public void init(DavResource resource, ReportInfo info) throws DavException { + // general validation checks + super.init(resource, info); + // specific for this report: a workspace href must be provided + Element workspace = info.getContentElement(DeltaVConstants.WORKSPACE.getName(), DeltaVConstants.WORKSPACE.getNamespace()); + String workspaceHref = normalizeResourceHref(DomUtil.getChildTextTrim(workspace, DavConstants.XML_HREF, DavConstants.NAMESPACE)); + if (workspaceHref == null || "".equals(workspaceHref)) { + throw new DavException(DavServletResponse.SC_BAD_REQUEST, "Request body must define the href of a source workspace"); + } + // retrieve href of the corresponding resource in the other workspace + try { + this.correspHref = getCorrespondingResourceHref(resource, getRepositorySession(), workspaceHref); + } catch (RepositoryException e) { + throw new JcrDavException(e); + } + } + + /** + * @see org.apache.jackrabbit.webdav.xml.XmlSerializable#toXml(Document) + */ + public Element toXml(Document document) { + Element elem = DomUtil.createElement(document, "locate-corresponding-node-report", ItemResourceConstants.NAMESPACE); + if (correspHref != null) { + elem.appendChild(DomUtil.hrefToXml(correspHref, document)); + } + return elem; + } + + /** + * Retrieve the href of the corresponding resource in the indicated workspace. + * + * @param resource + * @param session Session object used to access the {@link Node} object + * represented by the given resource. + * @param workspaceHref + * @return + * @throws RepositoryException + */ + private static String getCorrespondingResourceHref(DavResource resource, Session session, String workspaceHref) throws RepositoryException { + DavResourceLocator rLoc = resource.getLocator(); + String itemPath = rLoc.getRepositoryPath(); + Item item = session.getItem(itemPath); + if (item.isNode()) { + String workspaceName = rLoc.getFactory().createResourceLocator(rLoc.getPrefix(), workspaceHref).getWorkspaceName(); + String corrPath = ((Node)item).getCorrespondingNodePath(workspaceName); + DavResourceLocator corrLoc = rLoc.getFactory().createResourceLocator(rLoc.getPrefix(), "/" + workspaceName, corrPath, false); + return corrLoc.getHref(true); + } else { + throw new PathNotFoundException("Node with path " + itemPath + " does not exist."); + } + } +} Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/version/report/LocateCorrespondingNodeReport.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/webdav/jcr/version/report/NodeTypesReport.java =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/version/report/NodeTypesReport.java (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/version/report/NodeTypesReport.java (working copy) @@ -0,0 +1,202 @@ +/* + * 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.webdav.jcr.version.report; + +import org.apache.jackrabbit.commons.iterator.NodeTypeIteratorAdapter; +import org.apache.jackrabbit.commons.webdav.JcrRemotingConstants; +import org.apache.jackrabbit.commons.webdav.NodeTypeConstants; +import org.apache.jackrabbit.webdav.DavException; +import org.apache.jackrabbit.webdav.DavResource; +import org.apache.jackrabbit.webdav.DavServletResponse; +import org.apache.jackrabbit.webdav.jcr.ItemResourceConstants; +import org.apache.jackrabbit.webdav.jcr.JcrDavException; +import org.apache.jackrabbit.webdav.jcr.nodetype.NodeDefinitionImpl; +import org.apache.jackrabbit.webdav.jcr.nodetype.PropertyDefinitionImpl; +import org.apache.jackrabbit.webdav.version.report.Report; +import org.apache.jackrabbit.webdav.version.report.ReportInfo; +import org.apache.jackrabbit.webdav.version.report.ReportType; +import org.apache.jackrabbit.webdav.xml.DomUtil; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +import javax.jcr.RepositoryException; +import javax.jcr.Session; +import javax.jcr.nodetype.NodeDefinition; +import javax.jcr.nodetype.NodeType; +import javax.jcr.nodetype.NodeTypeIterator; +import javax.jcr.nodetype.NodeTypeManager; +import javax.jcr.nodetype.PropertyDefinition; +import java.util.ArrayList; +import java.util.List; + +/** + * NodeTypesReport allows to retrieve the definition of a single + * or multiple node types. The request body must be a 'dcr:nodetypes' element: + *
+ * <!ELEMENT nodetypes ( nodetype+ | all-nodetypes | mixin-nodetypes | primary-nodetypes ) >
+ *
+ * <!ELEMENT nodetype ( nodetypename ) >
+ * <!ELEMENT nodetypename (#PCDATA) >
+ *
+ * <!ELEMENT all-nodetypes EMPTY >
+ * <!ELEMENT mixin-nodetypes EMPTY >
+ * <!ELEMENT primary-nodetypes EMPTY >
+ * 
+ */ +//todo: currently the nodetype report is not consistent with the general way of representing nodetype names (with NodetypeElement) in order to be compatible with the jackrabbit nodetype registry... +//todo: for the same reason, not the complete nodetype-definition, but only the nodetype def as stored is represented. +//todo: no namespace definition with response (> jackrabbit)... and nodetype element has same name as the one used with dav-properties +public class NodeTypesReport extends AbstractJcrReport implements NodeTypeConstants { + + private static Logger log = LoggerFactory.getLogger(NodeTypesReport.class); + + /** + * The registered type of this report. + */ + public static final ReportType NODETYPES_REPORT = ReportType.register(JcrRemotingConstants.REPORT_NODETYPES, ItemResourceConstants.NAMESPACE, NodeTypesReport.class); + + private NodeTypeIterator ntIter; + + /** + * Returns {@link #NODETYPES_REPORT} type. + * @return {@link #NODETYPES_REPORT} + * @see org.apache.jackrabbit.webdav.version.report.Report#getType() + */ + public ReportType getType() { + return NODETYPES_REPORT; + } + + /** + * Always returns false. + * + * @return false + * @see org.apache.jackrabbit.webdav.version.report.Report#isMultiStatusReport() + */ + public boolean isMultiStatusReport() { + return false; + } + + /** + * @see Report#init(DavResource, ReportInfo) + */ + @Override + public void init(DavResource resource, ReportInfo info) throws DavException { + // delegate basic validation to super class + super.init(resource, info); + // report specific validation and preparation for xml serialization + try { + ntIter = getNodeTypes(getRepositorySession(), info); + } catch (RepositoryException e) { + throw new JcrDavException(e); + } + if (ntIter == null) { + throw new DavException(DavServletResponse.SC_INTERNAL_SERVER_ERROR); + } + } + + /** + * Returns a Xml representation of the node type definition(s) according + * to the info object. + * + * @param document + * @return Xml representation of the node type definition(s) + * @see org.apache.jackrabbit.webdav.xml.XmlSerializable#toXml(Document) + */ + public Element toXml(Document document) { + Element report = document.createElement(NODETYPES_ELEMENT); + // loop over the nodetypes to be returned in the report + while (ntIter.hasNext()) { + NodeType nt = ntIter.nextNodeType(); + Element ntDef = document.createElement(NODETYPE_ELEMENT); + ntDef.setAttribute(NAME_ATTRIBUTE, nt.getName()); + ntDef.setAttribute(ISMIXIN_ATTRIBUTE, Boolean.toString(nt.isMixin())); + ntDef.setAttribute(HASORDERABLECHILDNODES_ATTRIBUTE, Boolean.toString(nt.hasOrderableChildNodes())); + // JCR 2.0 extension + ntDef.setAttribute(ISABSTRACT_ATTRIBUTE, Boolean.toString(nt.isAbstract())); + // JCR 2.0 extension + ntDef.setAttribute(ISQUERYABLE_ATTRIBUTE, Boolean.toString(nt.isQueryable())); + + // declared supertypes + Element supertypes = DomUtil.addChildElement(ntDef, SUPERTYPES_ELEMENT, null); + for (NodeType snt : nt.getDeclaredSupertypes()) { + DomUtil.addChildElement(supertypes, SUPERTYPE_ELEMENT, null, snt.getName()); + } + + // declared child node definitions + for (NodeDefinition aCnd : nt.getChildNodeDefinitions()) { + if (aCnd.getDeclaringNodeType().getName().equals(nt.getName())) { + ntDef.appendChild(NodeDefinitionImpl.create(aCnd).toXml(document)); + } + } + + // declared property definitions + for (PropertyDefinition aPd : nt.getPropertyDefinitions()) { + if (aPd.getDeclaringNodeType().getName().equals(nt.getName())) { + ntDef.appendChild(PropertyDefinitionImpl.create(aPd).toXml(document)); + } + } + + String primaryItemName = nt.getPrimaryItemName(); + if (primaryItemName != null) { + ntDef.setAttribute(PRIMARYITEMNAME_ATTRIBUTE, primaryItemName); + } + report.appendChild(ntDef); + } + return report; + } + + /** + * Parse the Xml element in the info object an return an interator over + * the specified node types. + * + * @return + * @throws RepositoryException + * @throws DavException + */ + private static NodeTypeIterator getNodeTypes(Session session, ReportInfo info) throws RepositoryException, DavException { + NodeTypeManager ntMgr = session.getWorkspace().getNodeTypeManager(); + + // check the simple types first... + if (info.containsContentElement(XML_REPORT_ALLNODETYPES, ItemResourceConstants.NAMESPACE)) { + return ntMgr.getAllNodeTypes(); + } else if (info.containsContentElement(XML_REPORT_MIXINNODETYPES, ItemResourceConstants.NAMESPACE)) { + return ntMgr.getMixinNodeTypes(); + } else if (info.containsContentElement(XML_REPORT_PRIMARYNODETYPES, ItemResourceConstants.NAMESPACE)) { + return ntMgr.getPrimaryNodeTypes(); + } else { + // None of the simple types. test if a report for individual + // nodetype was request. If not, the request body is not valid. + List elemList = info.getContentElements(XML_NODETYPE, ItemResourceConstants.NAMESPACE); + if (elemList.isEmpty()) { + // throw exception if the request body does not contain a single nodetype element + throw new DavException(DavServletResponse.SC_BAD_REQUEST, "NodeTypes report: request body has invalid format."); + } + + // todo: find better solution... + List ntList = new ArrayList(); + for (Element el : elemList) { + String nodetypeName = DomUtil.getChildTextTrim(el, XML_NODETYPENAME, ItemResourceConstants.NAMESPACE); + if (nodetypeName != null) { + ntList.add(ntMgr.getNodeType(nodetypeName)); + } + } + return new NodeTypeIteratorAdapter(ntList); + } + } +} Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/version/report/NodeTypesReport.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/webdav/jcr/version/report/RegisteredNamespacesReport.java =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/version/report/RegisteredNamespacesReport.java (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/version/report/RegisteredNamespacesReport.java (working copy) @@ -0,0 +1,121 @@ +/* + * 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.webdav.jcr.version.report; + +import org.apache.jackrabbit.webdav.DavException; +import org.apache.jackrabbit.webdav.DavResource; +import org.apache.jackrabbit.webdav.DavServletResponse; +import org.apache.jackrabbit.webdav.jcr.ItemResourceConstants; +import org.apache.jackrabbit.webdav.version.report.Report; +import org.apache.jackrabbit.webdav.version.report.ReportInfo; +import org.apache.jackrabbit.webdav.version.report.ReportType; +import org.apache.jackrabbit.webdav.xml.DomUtil; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +import javax.jcr.NamespaceRegistry; +import javax.jcr.RepositoryException; + +/** + * RegisteredNamespacesReport let the client retrieve the namespaces + * registered on the repository. + *

+ * Request body: + *

+ * <!ELEMENT registerednamespaces EMPTY >
+ * 
+ * + * Response body: + *
+ * <!ELEMENT registerednamespaces-report (namespace)* >
+ * <!ELEMENT namespace (prefix, uri) >
+ * <!ELEMENT prefix (#PCDATA) >
+ * <!ELEMENT uri (#PCDATA) >
+ * 
+ * + * @see javax.jcr.Workspace#getNamespaceRegistry() + */ +public class RegisteredNamespacesReport extends AbstractJcrReport implements ItemResourceConstants { + + private static Logger log = LoggerFactory.getLogger(RegisteredNamespacesReport.class); + + /** + * The registered type of this report. + */ + public static final ReportType REGISTERED_NAMESPACES_REPORT = ReportType.register(REPORT_REGISTERED_NAMESPACES, ItemResourceConstants.NAMESPACE, RegisteredNamespacesReport.class); + + private NamespaceRegistry nsReg; + + /** + * Returns {@link #REGISTERED_NAMESPACES_REPORT} type. + * @return {@link #REGISTERED_NAMESPACES_REPORT} + * @see org.apache.jackrabbit.webdav.version.report.Report#getType() + */ + public ReportType getType() { + return REGISTERED_NAMESPACES_REPORT; + } + + /** + * Always returns false. + * + * @return false + * @see org.apache.jackrabbit.webdav.version.report.Report#isMultiStatusReport() + */ + public boolean isMultiStatusReport() { + return false; + } + + /** + * @see Report#init(DavResource, ReportInfo) + */ + @Override + public void init(DavResource resource, ReportInfo info) throws DavException { + // delegate validation to abstract super class + super.init(resource, info); + try { + nsReg = getRepositorySession().getWorkspace().getNamespaceRegistry(); + } catch (RepositoryException e) { + throw new DavException(DavServletResponse.SC_INTERNAL_SERVER_ERROR); + } + } + + /** + * Returns a Xml representation of the registered namespace(s). + * + * @return Xml representation of the registered namespace(s) + * error occurs while retrieving the namespaces. + * @see org.apache.jackrabbit.webdav.xml.XmlSerializable#toXml(Document) + * @param document + */ + public Element toXml(Document document) { + Element report = DomUtil.createElement(document, "registerednamespaces-report", NAMESPACE); + try { + for (String prefix : nsReg.getPrefixes()) { + Element elem = DomUtil.addChildElement(report, XML_NAMESPACE, NAMESPACE); + DomUtil.addChildElement(elem, XML_PREFIX, NAMESPACE, prefix); + DomUtil.addChildElement(elem, XML_URI, NAMESPACE, nsReg.getURI(prefix)); + } + } catch (RepositoryException e) { + // should not occur. + log.error(e.getMessage()); + } + return report; + } + +} Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/version/report/RegisteredNamespacesReport.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/webdav/jcr/version/report/RepositoryDescriptorsReport.java =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/version/report/RepositoryDescriptorsReport.java (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/version/report/RepositoryDescriptorsReport.java (working copy) @@ -0,0 +1,128 @@ +/* + * 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.webdav.jcr.version.report; + +import org.apache.jackrabbit.webdav.DavException; +import org.apache.jackrabbit.webdav.DavResource; +import org.apache.jackrabbit.webdav.jcr.ItemResourceConstants; +import org.apache.jackrabbit.webdav.version.report.Report; +import org.apache.jackrabbit.webdav.version.report.ReportInfo; +import org.apache.jackrabbit.webdav.version.report.ReportType; +import org.apache.jackrabbit.webdav.xml.DomUtil; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +import javax.jcr.Repository; +import javax.jcr.Value; +import javax.jcr.RepositoryException; +import javax.jcr.PropertyType; + +/** + * RepositoryDescriptorsReport allows to retrieve the repository + * descriptors. The request body must be an empty 'dcr:repositorydescriptors' element: + *
+ * <!ELEMENT repositorydescriptors EMPTY >
+ * 
+ *
+ * The response body must match the following format + * + *
+ * <!ELEMENT repositorydescriptors-report ( descriptor )* >
+ * <!ELEMENT descriptor ( descriptorkey, descriptorvalue+ ) >
+ * <!ELEMENT descriptorkey (#PCDATA) >
+ * <!ELEMENT descriptorvalue (#PCDATA) >
+ * <!ATTLIST descriptorvalue
+ *      type ( Reference | Path | Name | Boolean | String | Date | Double |
+               Long | Binary | WeakReference | URI | Decimal )
+   >
+ * 
+ * + * @see javax.jcr.Repository#getDescriptorKeys() + * @see javax.jcr.Repository#getDescriptor(String) + * @see javax.jcr.Repository#getDescriptorValue(String) + * @see javax.jcr.Repository#getDescriptorValues(String) + */ +public class RepositoryDescriptorsReport extends AbstractJcrReport implements ItemResourceConstants { + + private static Logger log = LoggerFactory.getLogger(RepositoryDescriptorsReport.class); + + /** + * The registered type of this report. + */ + public static final ReportType REPOSITORY_DESCRIPTORS_REPORT = ReportType.register(REPORT_REPOSITORY_DESCRIPTORS, ItemResourceConstants.NAMESPACE, RepositoryDescriptorsReport.class); + + /** + * Returns {@link #REPOSITORY_DESCRIPTORS_REPORT} type. + * @return {@link #REPOSITORY_DESCRIPTORS_REPORT} + * @see org.apache.jackrabbit.webdav.version.report.Report#getType() + */ + public ReportType getType() { + return REPOSITORY_DESCRIPTORS_REPORT; + } + + /** + * Always returns false. + * + * @return false + * @see org.apache.jackrabbit.webdav.version.report.Report#isMultiStatusReport() + */ + public boolean isMultiStatusReport() { + return false; + } + + /** + * @see Report#init(DavResource, ReportInfo) + */ + @Override + public void init(DavResource resource, ReportInfo info) throws DavException { + // delegate validation to abstract super class + super.init(resource, info); + } + + /** + * Returns a Xml representation of the repository descriptors according + * to the info object. + * + * @return Xml representation of the repository descriptors + * @see org.apache.jackrabbit.webdav.xml.XmlSerializable#toXml(Document) + * @param document + */ + public Element toXml(Document document) { + Repository repository = getRepositorySession().getRepository(); + Element report = DomUtil.createElement(document, "repositorydescriptors-report", NAMESPACE); + for (String key : repository.getDescriptorKeys()) { + Element elem = DomUtil.addChildElement(report, XML_DESCRIPTOR, NAMESPACE); + DomUtil.addChildElement(elem, XML_DESCRIPTORKEY, NAMESPACE, key); + for (Value v : repository.getDescriptorValues(key)) { + String value; + try { + value = v.getString(); + } catch (RepositoryException e) { + log.error("Internal error while reading descriptor value: ", e); + value = repository.getDescriptor(key); + } + Element child = DomUtil.addChildElement(elem, XML_DESCRIPTORVALUE, NAMESPACE, value); + if (PropertyType.STRING != v.getType()) { + child.setAttribute(ATTR_VALUE_TYPE, PropertyType.nameFromValue(v.getType())); + } + } + } + return report; + } +} Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/version/report/RepositoryDescriptorsReport.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/webdav/simple/DavResourceImpl.java =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/simple/DavResourceImpl.java (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/simple/DavResourceImpl.java (working copy) @@ -0,0 +1,1128 @@ +/* + * 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.webdav.simple; + +import org.apache.jackrabbit.JcrConstants; +import org.apache.jackrabbit.server.io.AbstractExportContext; +import org.apache.jackrabbit.server.io.CopyMoveContextImpl; +import org.apache.jackrabbit.server.io.DefaultIOListener; +import org.apache.jackrabbit.server.io.DeleteContextImpl; +import org.apache.jackrabbit.server.io.DeleteManager; +import org.apache.jackrabbit.server.io.ExportContext; +import org.apache.jackrabbit.server.io.ExportContextImpl; +import org.apache.jackrabbit.server.io.IOListener; +import org.apache.jackrabbit.server.io.IOManager; +import org.apache.jackrabbit.server.io.IOUtil; +import org.apache.jackrabbit.server.io.ImportContext; +import org.apache.jackrabbit.server.io.ImportContextImpl; +import org.apache.jackrabbit.server.io.PropertyExportContext; +import org.apache.jackrabbit.server.io.PropertyImportContext; +import org.apache.jackrabbit.util.Text; +import org.apache.jackrabbit.webdav.DavCompliance; +import org.apache.jackrabbit.webdav.DavException; +import org.apache.jackrabbit.webdav.DavResource; +import org.apache.jackrabbit.webdav.DavResourceFactory; +import org.apache.jackrabbit.webdav.DavResourceIterator; +import org.apache.jackrabbit.webdav.DavResourceIteratorImpl; +import org.apache.jackrabbit.webdav.DavResourceLocator; +import org.apache.jackrabbit.webdav.DavServletResponse; +import org.apache.jackrabbit.webdav.DavSession; +import org.apache.jackrabbit.webdav.MultiStatusResponse; +import org.apache.jackrabbit.webdav.bind.BindConstants; +import org.apache.jackrabbit.webdav.bind.BindableResource; +import org.apache.jackrabbit.webdav.bind.ParentElement; +import org.apache.jackrabbit.webdav.bind.ParentSet; +import org.apache.jackrabbit.webdav.io.InputContext; +import org.apache.jackrabbit.webdav.io.OutputContext; +import org.apache.jackrabbit.webdav.jcr.JcrDavException; +import org.apache.jackrabbit.webdav.jcr.JcrDavSession; +import org.apache.jackrabbit.webdav.jcr.lock.JcrActiveLock; +import org.apache.jackrabbit.webdav.lock.ActiveLock; +import org.apache.jackrabbit.webdav.lock.LockDiscovery; +import org.apache.jackrabbit.webdav.lock.LockInfo; +import org.apache.jackrabbit.webdav.lock.LockManager; +import org.apache.jackrabbit.webdav.lock.Scope; +import org.apache.jackrabbit.webdav.lock.SupportedLock; +import org.apache.jackrabbit.webdav.lock.Type; +import org.apache.jackrabbit.webdav.property.DavProperty; +import org.apache.jackrabbit.webdav.property.DavPropertyName; +import org.apache.jackrabbit.webdav.property.DavPropertySet; +import org.apache.jackrabbit.webdav.property.DefaultDavProperty; +import org.apache.jackrabbit.webdav.property.HrefProperty; +import org.apache.jackrabbit.webdav.property.ResourceType; +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.RepositoryException; +import javax.jcr.Session; +import javax.jcr.UnsupportedRepositoryOperationException; +import javax.jcr.Workspace; +import javax.jcr.lock.Lock; +import java.io.IOException; +import java.io.OutputStream; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Date; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.UUID; + +/** + * DavResourceImpl implements a DavResource. + */ +public class DavResourceImpl implements DavResource, BindableResource, JcrConstants { + + /** + * the default logger + */ + private static final Logger log = LoggerFactory.getLogger(DavResourceImpl.class); + + public static final String METHODS = DavResource.METHODS + ", " + BindConstants.METHODS; + + public static final String COMPLIANCE_CLASSES = DavCompliance.concatComplianceClasses( + new String[] { + DavCompliance._1_, + DavCompliance._2_, + DavCompliance._3_, + DavCompliance.BIND + } + ); + + private DavResourceFactory factory; + private LockManager lockManager; + private JcrDavSession session; + private Node node; + private DavResourceLocator locator; + + protected DavPropertySet properties = new DavPropertySet(); + protected boolean propsInitialized = false; + private boolean isCollection = true; + private String rfc4122Uri; + + private ResourceConfig config; + private long modificationTime = IOUtil.UNDEFINED_TIME; + + /** + * Create a new {@link DavResource}. + * + * @param locator + * @param factory + * @param session + * @param config + * @param isCollection + * @throws DavException + */ + public DavResourceImpl(DavResourceLocator locator, DavResourceFactory factory, + DavSession session, ResourceConfig config, + boolean isCollection) throws DavException { + this(locator, factory, session, config, null); + this.isCollection = isCollection; + } + + /** + * Create a new {@link DavResource}. + * + * @param locator + * @param factory + * @param session + * @param config + * @param node + * @throws DavException + */ + public DavResourceImpl(DavResourceLocator locator, DavResourceFactory factory, + DavSession session, ResourceConfig config, Node node) throws DavException { + if (locator == null || session == null || config == null) { + throw new IllegalArgumentException(); + } + JcrDavSession.checkImplementation(session); + this.session = (JcrDavSession)session; + this.factory = factory; + this.locator = locator; + this.config = config; + + if (locator.getResourcePath() != null) { + if (node != null) { + this.node = node; + // define what is a collection in webdav + isCollection = config.isCollectionResource(node); + initRfc4122Uri(); + } + } else { + throw new DavException(DavServletResponse.SC_NOT_FOUND); + } + } + + /** + * If the Node associated with this DavResource has a UUID that allows for the creation of a rfc4122 compliant + * URI, we use it as the value of the protected DAV property DAV:resource-id, which is defined by the BIND + * specification. + */ + private void initRfc4122Uri() { + try { + if (node.isNodeType(MIX_REFERENCEABLE)) { + String uuid = node.getUUID(); + try { + UUID.fromString(uuid); + rfc4122Uri = "urn:uuid:" + uuid; + } catch (IllegalArgumentException e) { + //no, this is not a UUID + } + } + } catch (RepositoryException e) { + log.warn("Error while detecting UUID", e); + } + } + + /** + * @see org.apache.jackrabbit.webdav.DavResource#getComplianceClass() + */ + public String getComplianceClass() { + return COMPLIANCE_CLASSES; + } + + /** + * @return DavResource#METHODS + * @see org.apache.jackrabbit.webdav.DavResource#getSupportedMethods() + */ + public String getSupportedMethods() { + return METHODS; + } + + /** + * @see DavResource#exists() ) + */ + public boolean exists() { + return node != null; + } + + /** + * @see DavResource#isCollection() + */ + public boolean isCollection() { + return isCollection; + } + + /** + * @see org.apache.jackrabbit.webdav.DavResource#getLocator() + */ + public DavResourceLocator getLocator() { + return locator; + } + + /** + * @see DavResource#getResourcePath() + */ + public String getResourcePath() { + return locator.getResourcePath(); + } + + /** + * @see DavResource#getHref() + */ + public String getHref() { + return locator.getHref(isCollection()); + } + + /** + * Returns the the last segment of the resource path.

+ * Note that this must not correspond to the name of the underlying + * repository item for two reasons:

    + *
  • SameNameSiblings have an index appended to their item name.
  • + *
  • the resource path may differ from the item path.
  • + *
+ * Using the item name as DAV:displayname caused problems with XP built-in + * client in case of resources representing SameNameSibling nodes. + * + * @see DavResource#getDisplayName() + */ + public String getDisplayName() { + String resPath = getResourcePath(); + return (resPath != null) ? Text.getName(resPath) : resPath; + } + + /** + * @see org.apache.jackrabbit.webdav.DavResource#getModificationTime() + */ + public long getModificationTime() { + initProperties(); + return modificationTime; + } + + /** + * If this resource exists and the specified context is not null + * this implementation build a new {@link ExportContext} based on the specified + * context and forwards the export to its IOManager. If the + * {@link IOManager#exportContent(ExportContext, DavResource)} fails, + * an IOException is thrown. + * + * @see DavResource#spool(OutputContext) + * @see ResourceConfig#getIOManager() + * @throws IOException if the export fails. + */ + public void spool(OutputContext outputContext) throws IOException { + if (exists() && outputContext != null) { + ExportContext exportCtx = getExportContext(outputContext); + if (!config.getIOManager().exportContent(exportCtx, this)) { + throw new IOException("Unexpected Error while spooling resource."); + } + } + } + + /** + * @see DavResource#getProperty(org.apache.jackrabbit.webdav.property.DavPropertyName) + */ + public DavProperty getProperty(DavPropertyName name) { + initProperties(); + return properties.get(name); + } + + /** + * @see DavResource#getProperties() + */ + public DavPropertySet getProperties() { + initProperties(); + return properties; + } + + /** + * @see DavResource#getPropertyNames() + */ + public DavPropertyName[] getPropertyNames() { + return getProperties().getPropertyNames(); + } + + /** + * Fill the set of properties + */ + protected void initProperties() { + if (!exists() || propsInitialized) { + return; + } + + try { + config.getPropertyManager().exportProperties(getPropertyExportContext(), isCollection()); + } catch (RepositoryException e) { + log.warn("Error while accessing resource properties", e); + } + + // set (or reset) fundamental properties + if (getDisplayName() != null) { + properties.add(new DefaultDavProperty(DavPropertyName.DISPLAYNAME, getDisplayName())); + } + if (isCollection()) { + properties.add(new ResourceType(ResourceType.COLLECTION)); + // Windows XP support + properties.add(new DefaultDavProperty(DavPropertyName.ISCOLLECTION, "1")); + } else { + properties.add(new ResourceType(ResourceType.DEFAULT_RESOURCE)); + // Windows XP support + properties.add(new DefaultDavProperty(DavPropertyName.ISCOLLECTION, "0")); + } + + if (rfc4122Uri != null) { + properties.add(new HrefProperty(BindConstants.RESOURCEID, rfc4122Uri, true)); + } + + Set parentElements = getParentElements(); + if (!parentElements.isEmpty()) { + properties.add(new ParentSet(parentElements)); + } + + /* set current lock information. If no lock is set to this resource, + an empty lock discovery will be returned in the response. */ + properties.add(new LockDiscovery(getLock(Type.WRITE, Scope.EXCLUSIVE))); + + /* lock support information: all locks are lockable. */ + SupportedLock supportedLock = new SupportedLock(); + supportedLock.addEntry(Type.WRITE, Scope.EXCLUSIVE); + properties.add(supportedLock); + + propsInitialized = true; + } + + /** + * @param property + * @throws DavException + * @see DavResource#setProperty(org.apache.jackrabbit.webdav.property.DavProperty) + */ + public void setProperty(DavProperty property) throws DavException { + alterProperty(property); + } + + /** + * @param propertyName + * @throws DavException + * @see DavResource#removeProperty(org.apache.jackrabbit.webdav.property.DavPropertyName) + */ + public void removeProperty(DavPropertyName propertyName) throws DavException { + alterProperty(propertyName); + } + + private void alterProperty(PropEntry prop) throws DavException { + if (isLocked(this)) { + throw new DavException(DavServletResponse.SC_LOCKED); + } + if (!exists()) { + throw new DavException(DavServletResponse.SC_NOT_FOUND); + } + try { + List list = Collections.singletonList(prop); + alterProperties(list); + Map failure = config.getPropertyManager().alterProperties(getPropertyImportContext(list), isCollection()); + if (failure.isEmpty()) { + node.save(); + } else { + node.refresh(false); + // TODO: retrieve specific error from failure-map + throw new DavException(DavServletResponse.SC_INTERNAL_SERVER_ERROR); + } + } catch (RepositoryException e) { + // revert any changes made so far + JcrDavException je = new JcrDavException(e); + try { + node.refresh(false); + } catch (RepositoryException re) { + // should not happen... + } + throw je; + } + } + + public MultiStatusResponse alterProperties(List changeList) throws DavException { + if (isLocked(this)) { + throw new DavException(DavServletResponse.SC_LOCKED); + } + if (!exists()) { + throw new DavException(DavServletResponse.SC_NOT_FOUND); + } + MultiStatusResponse msr = new MultiStatusResponse(getHref(), null); + try { + Map failures = config.getPropertyManager().alterProperties(getPropertyImportContext(changeList), isCollection()); + if (failures.isEmpty()) { + // save all changes together (reverted in case this fails) + node.save(); + } else { + // set/remove of at least a single prop failed: undo modifications. + node.refresh(false); + } + /* loop over list of properties/names that were successfully altered + and them to the multistatus response respecting the result of the + complete action. in case of failure set the status to 'failed-dependency' + in order to indicate, that altering those names/properties would + have succeeded, if no other error occured.*/ + for (PropEntry propEntry : changeList) { + int statusCode; + if (failures.containsKey(propEntry)) { + Object error = failures.get(propEntry); + statusCode = (error instanceof RepositoryException) + ? new JcrDavException((RepositoryException) error).getErrorCode() + : DavServletResponse.SC_INTERNAL_SERVER_ERROR; + } else { + statusCode = (failures.isEmpty()) ? DavServletResponse.SC_OK : DavServletResponse.SC_FAILED_DEPENDENCY; + } + if (propEntry instanceof DavProperty) { + msr.add(((DavProperty) propEntry).getName(), statusCode); + } else { + msr.add((DavPropertyName) propEntry, statusCode); + } + } + return msr; + } catch (RepositoryException e) { + // revert any changes made so far an throw exception + try { + node.refresh(false); + } catch (RepositoryException re) { + // should not happen + } + throw new JcrDavException(e); + } + } + + /** + * @see DavResource#getCollection() + */ + public DavResource getCollection() { + DavResource parent = null; + if (getResourcePath() != null && !getResourcePath().equals("/")) { + String parentPath = Text.getRelativeParent(getResourcePath(), 1); + if (parentPath.equals("")) { + parentPath = "/"; + } + DavResourceLocator parentloc = locator.getFactory().createResourceLocator(locator.getPrefix(), locator.getWorkspacePath(), parentPath); + try { + parent = factory.createResource(parentloc, session); + } catch (DavException e) { + // should not occur + } + } + return parent; + } + + /** + * @see DavResource#getMembers() + */ + public DavResourceIterator getMembers() { + ArrayList list = new ArrayList(); + if (exists() && isCollection()) { + try { + NodeIterator it = node.getNodes(); + while (it.hasNext()) { + Node n = it.nextNode(); + if (!isFilteredItem(n)) { + DavResourceLocator resourceLocator = locator.getFactory().createResourceLocator(locator.getPrefix(), locator.getWorkspacePath(), n.getPath(), false); + DavResource childRes = factory.createResource(resourceLocator, session); + list.add(childRes); + } else { + log.debug("Filtered resource '" + n.getName() + "'."); + } + } + } catch (RepositoryException e) { + // should not occur + } catch (DavException e) { + // should not occur + } + } + return new DavResourceIteratorImpl(list); + } + + /** + * Adds a new member to this resource. + * + * @see DavResource#addMember(DavResource, org.apache.jackrabbit.webdav.io.InputContext) + */ + public void addMember(DavResource member, InputContext inputContext) throws DavException { + if (!exists()) { + throw new DavException(DavServletResponse.SC_CONFLICT); + } + if (isLocked(this) || isLocked(member)) { + throw new DavException(DavServletResponse.SC_LOCKED); + } + try { + // don't allow creation of nodes if this resource represents a protected + // item or if the new resource would be filtered out + if (isFilteredResource(member) || node.getDefinition().isProtected()) { + log.debug("Forbidden to add member: " + member.getDisplayName()); + throw new DavException(DavServletResponse.SC_FORBIDDEN); + } + + String memberName = Text.getName(member.getLocator().getRepositoryPath()); + ImportContext ctx = getImportContext(inputContext, memberName); + if (!config.getIOManager().importContent(ctx, member)) { + // any changes should have been reverted in the importer + throw new DavException(DavServletResponse.SC_UNSUPPORTED_MEDIA_TYPE); + } + // persist changes after successful import + node.save(); + } catch (RepositoryException e) { + log.error("Error while importing resource: " + e.toString()); + throw new JcrDavException(e); + } catch (IOException e) { + log.error("Error while importing resource: " + e.toString()); + throw new DavException(DavServletResponse.SC_INTERNAL_SERVER_ERROR, e.getMessage()); + } + } + + /** + * @see DavResource#removeMember(DavResource) + */ + public void removeMember(DavResource member) throws DavException { + if (!exists() || !member.exists()) { + throw new DavException(DavServletResponse.SC_NOT_FOUND); + } + if (isLocked(this) || isLocked(member)) { + throw new DavException(DavServletResponse.SC_LOCKED); + } + + // don't allow removal of nodes, that would be filtered out + if (isFilteredResource(member)) { + log.debug("Avoid removal of filtered resource: " + member.getDisplayName()); + throw new DavException(DavServletResponse.SC_FORBIDDEN); + } + + DeleteManager dm = config.getDeleteManager(); + dm.delete(new DeleteContextImpl(getJcrSession()), member); + + // make sure, non-jcr locks are removed, once the removal is completed + try { + if (!isJcrLockable()) { + ActiveLock lock = getLock(Type.WRITE, Scope.EXCLUSIVE); + if (lock != null) { + lockManager.releaseLock(lock.getToken(), member); + } + } + } catch (DavException e) { + // since check for 'locked' exception has been performed before + // ignore any error here + } + } + + /** + * @see DavResource#move(DavResource) + */ + public void move(DavResource destination) throws DavException { + if (!exists()) { + throw new DavException(DavServletResponse.SC_NOT_FOUND); + } + if (isLocked(this)) { + throw new DavException(DavServletResponse.SC_LOCKED); + } + if (isFilteredResource(destination)) { + throw new DavException(DavServletResponse.SC_FORBIDDEN); + } + // make sure, that src and destination belong to the same workspace + checkSameWorkspace(destination.getLocator()); + if (!config.getCopyMoveManager().move(new CopyMoveContextImpl(getJcrSession()), this, destination)) { + throw new DavException(DavServletResponse.SC_UNSUPPORTED_MEDIA_TYPE); + } + } + + /** + * @see DavResource#copy(DavResource, boolean) + */ + public void copy(DavResource destination, boolean shallow) throws DavException { + if (!exists()) { + throw new DavException(DavServletResponse.SC_NOT_FOUND); + } + if (isLocked(destination)) { + throw new DavException(DavServletResponse.SC_LOCKED); + } + if (isFilteredResource(destination)) { + throw new DavException(DavServletResponse.SC_FORBIDDEN); + } + // make sure, that src and destination belong to the same workspace + checkSameWorkspace(destination.getLocator()); + if (!config.getCopyMoveManager().copy(new CopyMoveContextImpl(getJcrSession(), shallow), this, destination)) { + throw new DavException(DavServletResponse.SC_UNSUPPORTED_MEDIA_TYPE); + } + } + + /** + * @param type + * @param scope + * @return true if type is {@link Type#WRITE} and scope is {@link Scope#EXCLUSIVE} + * @see DavResource#isLockable(org.apache.jackrabbit.webdav.lock.Type, org.apache.jackrabbit.webdav.lock.Scope) + */ + public boolean isLockable(Type type, Scope scope) { + return Type.WRITE.equals(type) && Scope.EXCLUSIVE.equals(scope); + } + + /** + * @see DavResource#hasLock(org.apache.jackrabbit.webdav.lock.Type, org.apache.jackrabbit.webdav.lock.Scope) + */ + public boolean hasLock(Type type, Scope scope) { + return getLock(type, scope) != null; + } + + /** + * @see DavResource#getLock(Type, Scope) + */ + public ActiveLock getLock(Type type, Scope scope) { + ActiveLock lock = null; + if (exists() && Type.WRITE.equals(type) && Scope.EXCLUSIVE.equals(scope)) { + // try to retrieve the repository lock information first + try { + if (node.isLocked()) { + Lock jcrLock = node.getLock(); + if (jcrLock != null && jcrLock.isLive()) { + lock = new JcrActiveLock(jcrLock); + String lockroot = locator + .getFactory() + .createResourceLocator(locator.getPrefix(), locator.getWorkspacePath(), + jcrLock.getNode().getPath(), false).getHref(false); + lock.setLockroot(lockroot); + } + } + } catch (RepositoryException e) { + // LockException (no lock applies) >> should never occur + // RepositoryException, AccessDeniedException or another error >> ignore + } + + // could not retrieve a jcr-lock. test if a simple webdav lock is present. + if (lock == null) { + lock = lockManager.getLock(type, scope, this); + } + } + return lock; + } + + /** + * @see org.apache.jackrabbit.webdav.DavResource#getLocks() + */ + public ActiveLock[] getLocks() { + ActiveLock writeLock = getLock(Type.WRITE, Scope.EXCLUSIVE); + return (writeLock != null) ? new ActiveLock[]{writeLock} : new ActiveLock[0]; + } + + /** + * @see DavResource#lock(LockInfo) + */ + public ActiveLock lock(LockInfo lockInfo) throws DavException { + ActiveLock lock = null; + if (isLockable(lockInfo.getType(), lockInfo.getScope())) { + // TODO: deal with existing locks, that may have been created, before the node was jcr-lockable... + if (isJcrLockable()) { + try { + javax.jcr.lock.LockManager lockMgr = node.getSession().getWorkspace().getLockManager(); + long timeout = lockInfo.getTimeout(); + if (timeout == LockInfo.INFINITE_TIMEOUT) { + timeout = Long.MAX_VALUE; + } else { + timeout = timeout / 1000; + } + // try to execute the lock operation + Lock jcrLock = lockMgr.lock(node.getPath(), lockInfo.isDeep(), false, timeout, lockInfo.getOwner()); + if (jcrLock != null) { + lock = new JcrActiveLock(jcrLock); + } + } catch (RepositoryException e) { + throw new JcrDavException(e); + } + } else { + // create a new webdav lock + lock = lockManager.createLock(lockInfo, this); + } + } else { + throw new DavException(DavServletResponse.SC_PRECONDITION_FAILED, "Unsupported lock type or scope."); + } + return lock; + } + + /** + * @see DavResource#refreshLock(LockInfo, String) + */ + public ActiveLock refreshLock(LockInfo lockInfo, String lockToken) throws DavException { + if (!exists()) { + throw new DavException(DavServletResponse.SC_NOT_FOUND); + } + ActiveLock lock = getLock(lockInfo.getType(), lockInfo.getScope()); + if (lock == null) { + throw new DavException(DavServletResponse.SC_PRECONDITION_FAILED, "No lock with the given type/scope present on resource " + getResourcePath()); + } + + if (lock instanceof JcrActiveLock) { + try { + // refresh JCR lock and return the original lock object. + node.getLock().refresh(); + } catch (RepositoryException e) { + throw new JcrDavException(e); + } + } else { + lock = lockManager.refreshLock(lockInfo, lockToken, this); + } + /* since lock has infinite lock (simple) or undefined timeout (jcr) + return the lock as retrieved from getLock. */ + return lock; + } + + /** + * @see DavResource#unlock(String) + */ + public void unlock(String lockToken) throws DavException { + ActiveLock lock = getLock(Type.WRITE, Scope.EXCLUSIVE); + if (lock == null) { + throw new DavException(DavServletResponse.SC_PRECONDITION_FAILED); + } else if (lock.isLockedByToken(lockToken)) { + if (lock instanceof JcrActiveLock) { + try { + node.unlock(); + } catch (RepositoryException e) { + throw new JcrDavException(e); + } + } else { + lockManager.releaseLock(lockToken, this); + } + } else { + throw new DavException(DavServletResponse.SC_LOCKED); + } + } + + /** + * @see DavResource#addLockManager(org.apache.jackrabbit.webdav.lock.LockManager) + */ + public void addLockManager(LockManager lockMgr) { + this.lockManager = lockMgr; + } + + /** + * @see org.apache.jackrabbit.webdav.DavResource#getFactory() + */ + public DavResourceFactory getFactory() { + return factory; + } + + /** + * @see org.apache.jackrabbit.webdav.DavResource#getSession() + */ + public DavSession getSession() { + return session; + } + + + /** + * @see BindableResource#rebind(DavResource, DavResource) + */ + public void bind(DavResource collection, DavResource newBinding) throws DavException { + if (!exists()) { + //DAV:bind-source-exists + throw new DavException(DavServletResponse.SC_PRECONDITION_FAILED); + } + if (isLocked(collection)) { + //DAV:locked-update-allowed? + throw new DavException(DavServletResponse.SC_LOCKED); + } + if (isFilteredResource(newBinding)) { + throw new DavException(DavServletResponse.SC_FORBIDDEN); + } + checkSameWorkspace(collection.getLocator()); + try { + if (!node.isNodeType(MIX_SHAREABLE)) { + if (!node.canAddMixin(MIX_SHAREABLE)) { + //DAV:binding-allowed + throw new DavException(DavServletResponse.SC_PRECONDITION_FAILED); + } + node.addMixin(MIX_SHAREABLE); + node.save(); + } + Workspace workspace = session.getRepositorySession().getWorkspace(); + workspace.clone(workspace.getName(), node.getPath(), newBinding.getLocator().getRepositoryPath(), false); + + } catch (RepositoryException e) { + throw new JcrDavException(e); + } + + } + + /** + * @see BindableResource#rebind(DavResource, DavResource) + */ + public void rebind(DavResource collection, DavResource newBinding) throws DavException { + if (!exists()) { + //DAV:rebind-source-exists + throw new DavException(DavServletResponse.SC_PRECONDITION_FAILED); + } + if (isLocked(this)) { + //DAV:protected-source-url-deletion.allowed + throw new DavException(DavServletResponse.SC_PRECONDITION_FAILED); + } + if (isLocked(collection)) { + //DAV:locked-update-allowed? + throw new DavException(DavServletResponse.SC_LOCKED); + } + if (isFilteredResource(newBinding)) { + throw new DavException(DavServletResponse.SC_FORBIDDEN); + } + checkSameWorkspace(collection.getLocator()); + try { + if (!node.isNodeType(MIX_REFERENCEABLE)) { + throw new DavException(node.canAddMixin(MIX_REFERENCEABLE)? + DavServletResponse.SC_CONFLICT : DavServletResponse.SC_METHOD_NOT_ALLOWED); + } + getJcrSession().getWorkspace().move(locator.getRepositoryPath(), newBinding.getLocator().getRepositoryPath()); + } catch (RepositoryException e) { + throw new JcrDavException(e); + } + } + + /** + * @see org.apache.jackrabbit.webdav.bind.BindableResource#getParentElements() + */ + public Set getParentElements() { + try { + if (node.getDepth() > 0) { + Set ps = new HashSet(); + NodeIterator sharedSetIterator = node.getSharedSet(); + while (sharedSetIterator.hasNext()) { + Node sharednode = sharedSetIterator.nextNode(); + DavResourceLocator loc = locator.getFactory().createResourceLocator( + locator.getPrefix(), locator.getWorkspacePath(), sharednode.getParent().getPath(), false); + ps.add(new ParentElement(loc.getHref(true), sharednode.getName())); + } + return ps; + } + } catch (UnsupportedRepositoryOperationException e) { + log.debug("unable to calculate parent set", e); + } catch (RepositoryException e) { + log.warn("unable to calculate parent set", e); + } + return Collections.emptySet(); + } + + /** + * Returns the node that is wrapped by this resource. + * + * @return The underlying JCR node instance. + */ + protected Node getNode() { + return node; + } + + /** + * Returns a new ImportContext + * + * @param inputCtx + * @param systemId + * @return a new ImportContext + * @throws IOException + */ + protected ImportContext getImportContext(InputContext inputCtx, String systemId) throws IOException { + return new ImportContextImpl( + node, systemId, inputCtx, + (inputCtx != null) ? inputCtx.getInputStream() : null, + new DefaultIOListener(log), config.getDetector()); + } + + /** + * Returns a new ExportContext + * + * @param outputCtx + * @return a new ExportContext + * @throws IOException + */ + protected ExportContext getExportContext(OutputContext outputCtx) throws IOException { + return new ExportContextImpl(node, outputCtx); + } + + /** + * Returns a new PropertyImportContext. + * + * @param changeList + * @return a new PropertyImportContext. + */ + protected PropertyImportContext getPropertyImportContext(List changeList) { + return new PropertyImportCtx(changeList); + } + + /** + * Returns a new PropertyExportContext. + * + * @return a new PropertyExportContext + */ + protected PropertyExportContext getPropertyExportContext() { + return new PropertyExportCtx(); + } + + /** + * Returns true, if the underlying node is nodetype jcr:lockable, + * without checking its current lock status. If the node is not jcr-lockable + * an attempt is made to add the mix:lockable mixin type. + * + * @return true if this resource is lockable. + */ + private boolean isJcrLockable() { + boolean lockable = false; + if (exists()) { + try { + lockable = node.isNodeType(MIX_LOCKABLE); + // not jcr-lockable: try to make the node jcr-lockable + if (!lockable && node.canAddMixin(MIX_LOCKABLE)) { + node.addMixin(MIX_LOCKABLE); + node.save(); + lockable = true; + } + } catch (RepositoryException e) { + // -> node is definitely not jcr-lockable. + } + } + return lockable; + } + + /** + * Return true if this resource cannot be modified due to a write lock + * that is not owned by the given session. + * + * @return true if this resource cannot be modified due to a write lock + */ + private boolean isLocked(DavResource res) { + ActiveLock lock = res.getLock(Type.WRITE, Scope.EXCLUSIVE); + if (lock == null) { + return false; + } else { + for (String sLockToken : session.getLockTokens()) { + if (sLockToken.equals(lock.getToken())) { + return false; + } + } + return true; + } + } + + private Session getJcrSession() { + return session.getRepositorySession(); + } + + private boolean isFilteredResource(DavResource resource) { + // TODO: filtered nodetypes should be checked as well in order to prevent problems. + ItemFilter filter = config.getItemFilter(); + return filter != null && filter.isFilteredItem(resource.getDisplayName(), getJcrSession()); + } + + private boolean isFilteredItem(Item item) { + ItemFilter filter = config.getItemFilter(); + return filter != null && filter.isFilteredItem(item); + } + + private void checkSameWorkspace(DavResourceLocator otherLoc) throws DavException { + String wspname = getJcrSession().getWorkspace().getName(); + if (!wspname.equals(otherLoc.getWorkspaceName())) { + throw new DavException(DavServletResponse.SC_FORBIDDEN, "Workspace mismatch: expected '" + wspname + "'; found: '" + otherLoc.getWorkspaceName() + "'"); + } + } + + //--------------------------------------------------------< inner class >--- + /** + * ExportContext that writes the properties of this DavResource + * and provides not stream. + */ + private class PropertyExportCtx extends AbstractExportContext implements PropertyExportContext { + + private PropertyExportCtx() { + super(node, false, null); + // set defaults: + setCreationTime(IOUtil.UNDEFINED_TIME); + setModificationTime(IOUtil.UNDEFINED_TIME); + } + + public OutputStream getOutputStream() { + return null; + } + + public void setContentLanguage(String contentLanguage) { + if (contentLanguage != null) { + properties.add(new DefaultDavProperty(DavPropertyName.GETCONTENTLANGUAGE, contentLanguage)); + } + } + + public void setContentLength(long contentLength) { + if (contentLength > IOUtil.UNDEFINED_LENGTH) { + properties.add(new DefaultDavProperty(DavPropertyName.GETCONTENTLENGTH, contentLength + "")); + } + } + + public void setContentType(String mimeType, String encoding) { + String contentType = IOUtil.buildContentType(mimeType, encoding); + if (contentType != null) { + properties.add(new DefaultDavProperty(DavPropertyName.GETCONTENTTYPE, contentType)); + } + } + + public void setCreationTime(long creationTime) { + String created = IOUtil.getCreated(creationTime); + properties.add(new DefaultDavProperty(DavPropertyName.CREATIONDATE, created)); + } + + public void setModificationTime(long modTime) { + if (modTime <= IOUtil.UNDEFINED_TIME) { + modificationTime = new Date().getTime(); + } else { + modificationTime = modTime; + } + String lastModified = IOUtil.getLastModified(modificationTime); + properties.add(new DefaultDavProperty(DavPropertyName.GETLASTMODIFIED, lastModified)); + } + + public void setETag(String etag) { + if (etag != null) { + properties.add(new DefaultDavProperty(DavPropertyName.GETETAG, etag)); + } + } + + public void setProperty(Object propertyName, Object propertyValue) { + if (propertyValue == null) { + log.warn("Ignore 'setProperty' for " + propertyName + "with null value."); + return; + } + + if (propertyValue instanceof DavProperty) { + properties.add((DavProperty)propertyValue); + } else { + DavPropertyName pName; + if (propertyName instanceof DavPropertyName) { + pName = (DavPropertyName)propertyName; + } else { + // create property name with default DAV: namespace + pName = DavPropertyName.create(propertyName.toString()); + } + properties.add(new DefaultDavProperty(pName, propertyValue)); + } + } + } + + private class PropertyImportCtx implements PropertyImportContext { + + private final IOListener ioListener = new DefaultIOListener(log); + private final List changeList; + private boolean completed; + + private PropertyImportCtx(List changeList) { + this.changeList = changeList; + } + + /** + * @see PropertyImportContext#getImportRoot() + */ + public Item getImportRoot() { + return node; + } + + /** + * @see PropertyImportContext#getChangeList() + */ + public List getChangeList() { + return Collections.unmodifiableList(changeList); + } + + public IOListener getIOListener() { + return ioListener; + } + + public boolean hasStream() { + return false; + } + + /** + * @see PropertyImportContext#informCompleted(boolean) + */ + public void informCompleted(boolean success) { + checkCompleted(); + completed = true; + } + + /** + * @see PropertyImportContext#isCompleted() + */ + public boolean isCompleted() { + return completed; + } + + /** + * @throws IllegalStateException if the context is already completed. + * @see #isCompleted() + * @see #informCompleted(boolean) + */ + private void checkCompleted() { + if (completed) { + throw new IllegalStateException("PropertyImportContext has already been consumed."); + } + } + } +} Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/simple/DavResourceImpl.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/webdav/simple/DavSessionImpl.java =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/simple/DavSessionImpl.java (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/simple/DavSessionImpl.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.webdav.simple; + +import org.apache.jackrabbit.webdav.DavSession; +import org.apache.jackrabbit.webdav.jcr.JcrDavSession; + +import javax.jcr.Session; +import java.util.HashSet; + +/** + * Simple implementation of the {@link DavSession} interface. Stores + * lock tokens but does not yet store references. + */ +public class DavSessionImpl extends JcrDavSession { + + /** the lock tokens of this session */ + private final HashSet lockTokens = new HashSet(); + + /** + * Creates a new DavSession based on a jcr session + * @param session + */ + public DavSessionImpl(Session session) { + super(session); + } + + /** + * @see DavSession#addReference(Object) + */ + public void addReference(Object reference) { + throw new UnsupportedOperationException("No yet implemented."); + } + + /** + * @see DavSession#removeReference(Object) + */ + public void removeReference(Object reference) { + throw new UnsupportedOperationException("No yet implemented."); + } + + /** + * @see DavSession#addLockToken(String) + */ + @Override + public void addLockToken(String token) { + super.addLockToken(token); + lockTokens.add(token); + } + + /** + * @see DavSession#getLockTokens() + */ + @Override + public String[] getLockTokens() { + return lockTokens.toArray(new String[lockTokens.size()]); + } + + /** + * @see DavSession#removeLockToken(String) + */ + @Override + public void removeLockToken(String token) { + super.removeLockToken(token); + lockTokens.remove(token); + } +} Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/simple/DavSessionImpl.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/webdav/simple/DavSessionProviderImpl.java =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/simple/DavSessionProviderImpl.java (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/simple/DavSessionProviderImpl.java (working copy) @@ -0,0 +1,127 @@ +/* + * 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.webdav.simple; + +import org.apache.jackrabbit.server.CredentialsProvider; +import org.apache.jackrabbit.server.SessionProvider; +import org.apache.jackrabbit.webdav.DavException; +import org.apache.jackrabbit.webdav.DavServletResponse; +import org.apache.jackrabbit.webdav.DavSession; +import org.apache.jackrabbit.webdav.DavSessionProvider; +import org.apache.jackrabbit.webdav.WebdavRequest; +import org.apache.jackrabbit.webdav.jcr.JcrDavException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.jcr.NoSuchWorkspaceException; +import javax.jcr.Repository; +import javax.jcr.RepositoryException; +import javax.jcr.Session; +import javax.servlet.ServletException; + +/** + * Simple implementation of the {@link org.apache.jackrabbit.webdav.DavSessionProvider} + * interface that uses a {@link CredentialsProvider} to locate + * credentials in the request, log into the respository, and provide + * a {@link org.apache.jackrabbit.webdav.DavSession} to the request. + */ +public class DavSessionProviderImpl implements DavSessionProvider { + + private static Logger log = LoggerFactory.getLogger(DavSessionProviderImpl.class); + + /** + * the repository + */ + private final Repository repository; + + /** + * the credentials provider + */ + private final SessionProvider sesProvider; + + /** + * Creates a new DavSessionProviderImpl + * @param rep + * @param sesProvider + */ + public DavSessionProviderImpl(Repository rep, SessionProvider sesProvider) { + this.repository = rep; + this.sesProvider = sesProvider; + } + + /** + * Acquires a DavSession. Upon success, the WebdavRequest will + * reference that session. + * + * A session will not be available if an exception is thrown. + * + * @param request + * @throws org.apache.jackrabbit.webdav.DavException if a problem occurred while obtaining the session + * @see DavSessionProvider#attachSession(org.apache.jackrabbit.webdav.WebdavRequest) + */ + public boolean attachSession(WebdavRequest request) throws DavException { + try { + // retrieve the workspace name + String workspaceName = request.getRequestLocator().getWorkspaceName(); + // empty workspaceName rather means default -> must be 'null' + if (workspaceName != null && "".equals(workspaceName)) { + workspaceName = null; + } + // login to repository + Session repSession = sesProvider.getSession(request, repository, workspaceName); + if (repSession == null) { + log.debug("Could not to retrieve a repository session."); + return false; + } + DavSession ds = new DavSessionImpl(repSession); + log.debug("Attaching session '"+ ds + "' to request '" + request + "'"); + request.setDavSession(ds); + return true; + } catch (NoSuchWorkspaceException e) { + // the default error-code for NoSuchWorkspaceException is 409 conflict + // which seems not appropriate here + throw new JcrDavException(e, DavServletResponse.SC_NOT_FOUND); + } catch (RepositoryException e) { + throw new JcrDavException(e); + } catch (ServletException e) { + throw new DavException(DavServletResponse.SC_INTERNAL_SERVER_ERROR, e.getMessage()); + } + } + + /** + * Only removes the DavSession object from the given request object. + * and remove all the lock tokens from the underlying repository session + * in order make sure they can be reset when attaching a session to the + * next request. Finally the session provider is informed, that the + * session is no longer used. + * + * @param request + * @see DavSessionProvider#releaseSession(org.apache.jackrabbit.webdav.WebdavRequest) + */ + public void releaseSession(WebdavRequest request) { + DavSession ds = request.getDavSession(); + if (ds != null && ds instanceof DavSessionImpl) { + Session repSession = ((DavSessionImpl)ds).getRepositorySession(); + for (String lockToken : repSession.getLockTokens()) { + repSession.removeLockToken(lockToken); + } + sesProvider.releaseSession(repSession); + log.debug("Releasing session '"+ ds + "' from request '" + request + "'"); + } // else : session is null. nothing to be done. + request.setDavSession(null); + } +} Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/simple/DavSessionProviderImpl.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/webdav/simple/DefaultItemFilter.java =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/simple/DefaultItemFilter.java (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/simple/DefaultItemFilter.java (working copy) @@ -0,0 +1,158 @@ +/* + * 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.webdav.simple; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.jcr.Item; +import javax.jcr.Node; +import javax.jcr.Property; +import javax.jcr.RepositoryException; +import javax.jcr.Session; +import java.util.ArrayList; +import java.util.List; + +/** + * DefaultItemFilter... + */ +public class DefaultItemFilter implements ItemFilter { + + private static Logger log = LoggerFactory.getLogger(DefaultItemFilter.class); + + private List prefixFilter = new ArrayList(); + private List uriFilter = new ArrayList(); + private List nodetypeFilter = new ArrayList(); + + public DefaultItemFilter() { + } + + /** + * @see ItemFilter#setFilteredURIs(String[]) + */ + public void setFilteredURIs(String[] uris) { + if (uris != null) { + for (String uri : uris) { + uriFilter.add(uri); + } + } + } + + /** + * @see ItemFilter#setFilteredPrefixes(String[]) + */ + public void setFilteredPrefixes(String[] prefixes) { + if (prefixes != null) { + for (String prefix : prefixes) { + prefixFilter.add(prefix); + } + } + } + + /** + * @see ItemFilter#setFilteredNodetypes(String[]) + */ + public void setFilteredNodetypes(String[] nodetypeNames) { + if (nodetypeNames != null) { + for (String nodetypeName : nodetypeNames) { + nodetypeFilter.add(nodetypeName); + } + } + } + + /** + * Returns true if the given item matches either one of the namespace or + * of the the nodetype filters specified. + * + * @see ItemFilter#isFilteredItem(Item) + */ + public boolean isFilteredItem(Item item) { + return isFilteredNamespace(item) || isFilteredNodeType(item); + } + + /** + * @see ItemFilter#isFilteredItem(String, Session) + */ + public boolean isFilteredItem(String displayName, Session session) { + return isFilteredNamespace(displayName, session); + } + + /** + * + * @param name + * @param session + * @return + */ + private boolean isFilteredNamespace(String name, Session session) { + // shortcut + if (prefixFilter.isEmpty() && uriFilter.isEmpty()) { + return false; + } + int pos = name.indexOf(':'); + if (pos < 0) { + // no namespace info present + return false; + } + try { + String prefix = name.substring(0, pos); + String uri = session.getNamespaceURI(prefix); + return prefixFilter.contains(prefix) || uriFilter.contains(uri); + } catch (RepositoryException e) { + log.warn(e.getMessage()); + } + return false; + } + + /** + * + * @param item + * @return + */ + private boolean isFilteredNamespace(Item item) { + try { + return isFilteredNamespace(item.getName(), item.getSession()); + } catch (RepositoryException e) { + log.warn(e.getMessage()); + } + return false; + } + + /** + * + * @param item + * @return + */ + private boolean isFilteredNodeType(Item item) { + // shortcut + if (nodetypeFilter.isEmpty()) { + return false; + } + try { + String ntName; + if (item.isNode()) { + ntName = ((Node) item).getDefinition().getDeclaringNodeType().getName(); + } else { + ntName = ((Property) item).getDefinition().getDeclaringNodeType().getName(); + } + return nodetypeFilter.contains(ntName); + } catch (RepositoryException e) { + log.warn(e.getMessage()); + } + // nodetype info could not be retrieved + return false; + } +} Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/simple/DefaultItemFilter.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/webdav/simple/DeltaVResourceImpl.java =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/simple/DeltaVResourceImpl.java (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/simple/DeltaVResourceImpl.java (working copy) @@ -0,0 +1,274 @@ +/* + * 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.webdav.simple; + +import java.util.ArrayList; +import java.util.List; + +import javax.jcr.Item; +import javax.jcr.Node; +import javax.jcr.RepositoryException; +import javax.jcr.Property; +import javax.xml.parsers.ParserConfigurationException; + +import org.apache.jackrabbit.JcrConstants; +import org.apache.jackrabbit.webdav.DavCompliance; +import org.apache.jackrabbit.webdav.DavException; +import org.apache.jackrabbit.webdav.DavLocatorFactory; +import org.apache.jackrabbit.webdav.DavResource; +import org.apache.jackrabbit.webdav.DavResourceFactory; +import org.apache.jackrabbit.webdav.DavResourceLocator; +import org.apache.jackrabbit.webdav.DavServletResponse; +import org.apache.jackrabbit.webdav.DavSession; +import org.apache.jackrabbit.webdav.property.DavProperty; +import org.apache.jackrabbit.webdav.property.DavPropertyName; +import org.apache.jackrabbit.webdav.property.HrefProperty; +import org.apache.jackrabbit.webdav.property.DefaultDavProperty; +import org.apache.jackrabbit.webdav.version.DeltaVConstants; +import org.apache.jackrabbit.webdav.version.DeltaVResource; +import org.apache.jackrabbit.webdav.version.OptionsInfo; +import org.apache.jackrabbit.webdav.version.OptionsResponse; +import org.apache.jackrabbit.webdav.version.report.Report; +import org.apache.jackrabbit.webdav.version.report.ReportInfo; +import org.apache.jackrabbit.webdav.version.report.ReportType; +import org.apache.jackrabbit.webdav.version.report.SupportedReportSetProperty; +import org.apache.jackrabbit.webdav.xml.DomUtil; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.w3c.dom.Element; + +/** + * The DeltaVResourceImpl encapsulates the functionality common to all + * DeltaV compliant resources. + */ +public class DeltaVResourceImpl extends DavResourceImpl implements DeltaVResource { + + protected SupportedReportSetProperty supportedReports = new SupportedReportSetProperty(); + private static final Logger log = LoggerFactory.getLogger(DeltaVResourceImpl.class); + + private static final String DELTAV_COMPLIANCE_CLASSES = DavCompliance.concatComplianceClasses( + new String[] { + DavResourceImpl.COMPLIANCE_CLASSES, + DavCompliance.BIND, + } + ); + + public DeltaVResourceImpl(DavResourceLocator locator, DavResourceFactory factory, DavSession session, ResourceConfig config, Item item) throws DavException { + super(locator, factory, session, config, (Node)item); + initSupportedReports(); + } + + public DeltaVResourceImpl(DavResourceLocator locator, DavResourceFactory factory, DavSession session, ResourceConfig config, boolean isCollection) throws DavException { + super(locator, factory, session, config, isCollection); + initSupportedReports(); + } + + //---------------------------------------------------------< DavResource>--- + /** + * @see org.apache.jackrabbit.webdav.DavResource#getComplianceClass() + */ + @Override + public String getComplianceClass() { + return DELTAV_COMPLIANCE_CLASSES; + } + + //------------------------------------------------------< DeltaVResource>--- + /** + * @param optionsInfo + * @return object to be used in the OPTIONS response body or null + * @see DeltaVResource#getOptionResponse(org.apache.jackrabbit.webdav.version.OptionsInfo) + */ + public OptionsResponse getOptionResponse(OptionsInfo optionsInfo) { + OptionsResponse oR = null; + if (optionsInfo != null) { + oR = new OptionsResponse(); + // currently only DAV:version-history-collection-set is supported + if (optionsInfo.containsElement(DeltaVConstants.XML_VH_COLLECTION_SET, DeltaVConstants.NAMESPACE)) { + String[] hrefs = new String[] { + getLocatorFromNodePath("/"+JcrConstants.JCR_SYSTEM+"/"+JcrConstants.JCR_VERSIONSTORAGE).getHref(true) + }; + oR.addEntry(DeltaVConstants.XML_VH_COLLECTION_SET, DeltaVConstants.NAMESPACE, hrefs); + } + } + return oR; + } + + /** + * @param reportInfo + * @return the requested report + * @throws DavException + * @see DeltaVResource#getReport(org.apache.jackrabbit.webdav.version.report.ReportInfo) + */ + public Report getReport(ReportInfo reportInfo) throws DavException { + if (reportInfo == null) { + throw new DavException(DavServletResponse.SC_BAD_REQUEST, "A REPORT request must provide a valid XML request body."); + } + if (!exists()) { + throw new DavException(DavServletResponse.SC_NOT_FOUND); + } + + if (!supportedReports.isSupportedReport(reportInfo)) { + Element condition = null; + try { + condition = DomUtil.createDocument().createElementNS("DAV:", "supported-report"); + } catch (ParserConfigurationException ex) { + // we don't care THAT much + } + throw new DavException(DavServletResponse.SC_CONFLICT, + "Unknown report '" + reportInfo.getReportName() + "' requested.", null, condition); + } + return ReportType.getType(reportInfo).createReport(this, reportInfo); + } + + /** + * The JCR api does not provide methods to create new workspaces. Calling + * addWorkspace on this resource will always fail. + * + * @param workspace + * @throws DavException Always throws. + * @see DeltaVResource#addWorkspace(org.apache.jackrabbit.webdav.DavResource) + */ + public void addWorkspace(DavResource workspace) throws DavException { + throw new DavException(DavServletResponse.SC_FORBIDDEN); + } + + /** + * Return an array of DavResource objects that are referenced + * by the property with the specified name. + * + * @param hrefPropertyName + * @return array of DavResources + * @throws DavException + * @see DeltaVResource#getReferenceResources(org.apache.jackrabbit.webdav.property.DavPropertyName) + */ + public DavResource[] getReferenceResources(DavPropertyName hrefPropertyName) throws DavException { + DavProperty prop = getProperty(hrefPropertyName); + List resources = new ArrayList(); + if (prop != null && prop instanceof HrefProperty) { + HrefProperty hp = (HrefProperty)prop; + // process list of hrefs + for (String href : hp.getHrefs()) { + DavResourceLocator locator = getLocator().getFactory().createResourceLocator(getLocator().getPrefix(), href); + resources.add(createResourceFromLocator(locator)); + } + } else { + throw new DavException(DavServletResponse.SC_INTERNAL_SERVER_ERROR); + } + return resources.toArray(new DavResource[resources.size()]); + } + + /** + * Build a DavResourceLocator from the given nodePath path. + * + * @param nodePath + * @return a new DavResourceLocator + * @see DavLocatorFactory#createResourceLocator(String, String, String) + */ + protected DavResourceLocator getLocatorFromNodePath(String nodePath) { + DavResourceLocator loc = getLocator().getFactory().createResourceLocator(getLocator().getPrefix(), getLocator().getWorkspacePath(), nodePath, false); + return loc; + } + + + /** + * Build a new {@link DavResourceLocator} from the given repository node. + * + * @param repositoryNode + * @return a new locator for the specified node. + * @see #getLocatorFromNodePath(String) + */ + protected DavResourceLocator getLocatorFromNode(Node repositoryNode) { + String nodePath = null; + try { + if (repositoryNode != null) { + nodePath = repositoryNode.getPath(); + } + } catch (RepositoryException e) { + // ignore: should not occur + log.warn(e.getMessage()); + } + return getLocatorFromNodePath(nodePath); + } + + /** + * Create a new DavResource from the given locator. + * @param loc + * @return new DavResource + */ + protected DavResource createResourceFromLocator(DavResourceLocator loc) + throws DavException { + DavResource res = getFactory().createResource(loc, getSession()); + return res; + } + + /** + * Returns a {@link org.apache.jackrabbit.webdav.property.HrefProperty} with the + * specified property name and values. Each node present in the specified + * array is referenced in the resulting property. + * + * @param name + * @param values + * @param isProtected + * @return HrefProperty + */ + protected HrefProperty getHrefProperty(DavPropertyName name, Node[] values, + boolean isProtected, boolean isCollection) { + if (values == null) { + return null; + } + String[] pHref = new String[values.length]; + for (int i = 0; i < values.length; i++) { + pHref[i] = getLocatorFromNode(values[i]).getHref(isCollection); + } + return new HrefProperty(name, pHref, isProtected); + } + + /** + * Initialize the supported reports field + */ + protected void initSupportedReports() { + if (exists()) { + supportedReports.addReportType(ReportType.EXPAND_PROPERTY); + if (isCollection()) { + supportedReports.addReportType(ReportType.LOCATE_BY_HISTORY); + } + } + } + + /** + * Fill the property set for this resource. + */ + @Override + protected void initProperties() { + if (!propsInitialized) { + super.initProperties(); + if (exists()) { + properties.add(supportedReports); + + // DAV:creator-displayname -> use jcr:createBy if present. + Node n = getNode(); + try { + if (n.hasProperty(Property.JCR_CREATED_BY)) { + String createdBy = n.getProperty(Property.JCR_CREATED_BY).getString(); + properties.add(new DefaultDavProperty(DeltaVConstants.CREATOR_DISPLAYNAME, createdBy, true)); + } + } catch (RepositoryException e) { + log.debug("Error while accessing jcr:createdBy property"); + } + } + } + } +} Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/simple/DeltaVResourceImpl.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/webdav/simple/ItemFilter.java =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/simple/ItemFilter.java (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/simple/ItemFilter.java (working copy) @@ -0,0 +1,68 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.jackrabbit.webdav.simple; + +import javax.jcr.Item; +import javax.jcr.Session; + +/** + * ItemFilter + */ +public interface ItemFilter { + + /** + * Define the URIs that should be filtered out if present in the prefix + * of an items name. + * + * @param uris + */ + public void setFilteredURIs(String[] uris); + + /** + * Define the namespace prefixes that should be filtered if present in + * the prefix of an items name. + * + * @param prefixes + */ + public void setFilteredPrefixes(String[] prefixes); + + /** + * Set the nodetype names that should be used if a given item should be + * filtered. Note that not the nodetype(s) defined for a given item + * is relevant but rather the nodetype that defined the definition of the item. + * + * @param nodetypeNames + */ + public void setFilteredNodetypes(String[] nodetypeNames); + + /** + * Returns true if the given item should be filtered. + * + * @param item to be tested + * @return true if the given item should be filtered. + */ + public boolean isFilteredItem(Item item); + + /** + * Returns true if the resouce with the given name should be filtered. + * + * @param name to be tested for a filtered namespace prefix + * @param session used for looking up namespace mappings + * @return true if the given resource should be filtered. + */ + public boolean isFilteredItem(String name, Session session); +} \ No newline at end of file Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/simple/ItemFilter.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/webdav/simple/LocatorFactoryImpl.java =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/simple/LocatorFactoryImpl.java (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/simple/LocatorFactoryImpl.java (working copy) @@ -0,0 +1,165 @@ +/* + * 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.webdav.simple; + +import org.apache.jackrabbit.util.Text; +import org.apache.jackrabbit.webdav.DavLocatorFactory; +import org.apache.jackrabbit.webdav.DavResourceLocator; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * ResourceFactoryImpl implements a simple DavLocatorFactory + */ +// todo improve special handling of root item.... +public class LocatorFactoryImpl implements DavLocatorFactory { + + /** the default logger */ + private static final Logger log = LoggerFactory.getLogger(LocatorFactoryImpl.class); + + private final String repositoryPrefix; + + public LocatorFactoryImpl(String repositoryPrefix) { + this.repositoryPrefix = repositoryPrefix; + } + + public DavResourceLocator createResourceLocator(String prefix, String href) { + // build prefix string and remove all prefixes from the given href. + StringBuffer b = new StringBuffer(""); + if (prefix != null && prefix.length() > 0) { + b.append(prefix); + if (href.startsWith(prefix)) { + href = href.substring(prefix.length()); + } + } + if (repositoryPrefix != null && repositoryPrefix.length() > 0 && !prefix.endsWith(repositoryPrefix)) { + b.append(repositoryPrefix); + if (href.startsWith(repositoryPrefix)) { + href = href.substring(repositoryPrefix.length()); + } + } + + // special treatment for root item, that has no name but '/' path. + if (href == null || "".equals(href)) { + href = "/"; + } + return new Locator(b.toString(), Text.unescape(href), this); + } + + public DavResourceLocator createResourceLocator(String prefix, String workspacePath, String resourcePath) { + return createResourceLocator(prefix, workspacePath, resourcePath, true); + } + + public DavResourceLocator createResourceLocator(String prefix, String workspacePath, String path, boolean isResourcePath) { + return new Locator(prefix, path, this); + } + + //-------------------------------------------------------------------------- + private static class Locator implements DavResourceLocator { + + private final String prefix; + private final String resourcePath; + private final DavLocatorFactory factory; + private final String href; + + private Locator(String prefix, String resourcePath, DavLocatorFactory factory) { + this.prefix = prefix; + this.factory = factory; + // remove trailing '/' that is not part of the resourcePath except for the root item. + if (resourcePath.endsWith("/") && !"/".equals(resourcePath)) { + resourcePath = resourcePath.substring(0, resourcePath.length()-1); + } + this.resourcePath = resourcePath; + href = prefix + Text.escapePath(resourcePath); + } + + public String getPrefix() { + return prefix; + } + + public String getResourcePath() { + return resourcePath; + } + + public String getWorkspacePath() { + return ""; + } + + public String getWorkspaceName() { + return ""; + } + + public boolean isSameWorkspace(DavResourceLocator locator) { + return isSameWorkspace(locator.getWorkspaceName()); + } + + public boolean isSameWorkspace(String workspaceName) { + return getWorkspaceName().equals(workspaceName); + } + + public String getHref(boolean isCollection) { + // avoid doubled trailing '/' for the root item + String suffix = (isCollection && !isRootLocation()) ? "/" : ""; + return href + suffix; + } + + public boolean isRootLocation() { + return "/".equals(resourcePath); + } + + public DavLocatorFactory getFactory() { + return factory; + } + + /** + * Returns the same as {@link #getResourcePath()}. No encoding is performed + * at all. + * @see DavResourceLocator#getRepositoryPath() + */ + public String getRepositoryPath() { + return getResourcePath(); + } + + /** + * Computes the hash code from the href, which is built using the final + * fields prefix and resourcePath. + * + * @return the hash code + */ + @Override + public int hashCode() { + return href.hashCode(); + } + + /** + * Equality of path is achieved if the specified object is a DavResourceLocator + * object with the same hash code. + * + * @param obj the object to compare to + * @return true if the 2 objects are equal; + * false otherwise + */ + @Override + public boolean equals(Object obj) { + if (obj instanceof DavResourceLocator) { + DavResourceLocator other = (DavResourceLocator) obj; + return hashCode() == other.hashCode(); + } + return false; + } + } +} Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/simple/LocatorFactoryImpl.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/webdav/simple/LocatorFactoryImplEx.java =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/simple/LocatorFactoryImplEx.java (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/simple/LocatorFactoryImplEx.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.webdav.simple; + +import org.apache.jackrabbit.webdav.AbstractLocatorFactory; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * LocatorFactoryImplEx... + */ +public class LocatorFactoryImplEx extends AbstractLocatorFactory { + + private static Logger log = LoggerFactory.getLogger(LocatorFactoryImplEx.class); + + /** + * Create a new factory + * + * @param pathPrefix Prefix, that needs to be removed in order to retrieve + * the path of the repository item from a given DavResourceLocator. + */ + public LocatorFactoryImplEx(String pathPrefix) { + super(pathPrefix); + } + + /** + * + * @see AbstractLocatorFactory#getRepositoryPath(String, String) + */ + @Override + protected String getRepositoryPath(String resourcePath, String wspPath) { + if (resourcePath == null) { + return resourcePath; + } + + if (resourcePath.equals(wspPath) || startsWithWorkspace(resourcePath, wspPath)) { + String repositoryPath = resourcePath.substring(wspPath.length()); + return (repositoryPath.length() == 0) ? "/" : repositoryPath; + } else { + throw new IllegalArgumentException("Unexpected format of resource path: " + resourcePath + " (workspace: " + wspPath + ")"); + } + } + + /** + * + * @see AbstractLocatorFactory#getResourcePath(String, String) + */ + @Override + protected String getResourcePath(String repositoryPath, String wspPath) { + if (repositoryPath == null) { + throw new IllegalArgumentException("Cannot build resource path from 'null' repository path"); + } + return wspPath + repositoryPath; + } + + private boolean startsWithWorkspace(String repositoryPath, String wspPath) { + if (wspPath == null) { + return true; + } else { + return repositoryPath.startsWith(wspPath + "/"); + } + } +} Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/simple/LocatorFactoryImplEx.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/webdav/simple/ResourceConfig.java =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/simple/ResourceConfig.java (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/simple/ResourceConfig.java (working copy) @@ -0,0 +1,543 @@ +/* + * 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.webdav.simple; + +import java.io.IOException; +import java.io.InputStream; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.net.URL; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import javax.jcr.Item; +import javax.jcr.Node; +import javax.jcr.RepositoryException; +import javax.xml.parsers.ParserConfigurationException; + +import org.apache.jackrabbit.server.io.CopyMoveHandler; +import org.apache.jackrabbit.server.io.CopyMoveManager; +import org.apache.jackrabbit.server.io.CopyMoveManagerImpl; +import org.apache.jackrabbit.server.io.DefaultIOManager; +import org.apache.jackrabbit.server.io.DeleteManager; +import org.apache.jackrabbit.server.io.DeleteManagerImpl; +import org.apache.jackrabbit.server.io.IOHandler; +import org.apache.jackrabbit.server.io.IOManager; +import org.apache.jackrabbit.server.io.PropertyHandler; +import org.apache.jackrabbit.server.io.PropertyManager; +import org.apache.jackrabbit.server.io.PropertyManagerImpl; +import org.apache.jackrabbit.webdav.xml.DomUtil; +import org.apache.jackrabbit.webdav.xml.ElementIterator; +import org.apache.jackrabbit.webdav.xml.Namespace; +import org.apache.tika.detect.Detector; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.w3c.dom.Element; +import org.xml.sax.SAXException; + +/** + * ResourceConfig... + */ +public class ResourceConfig { + + private static Logger log = LoggerFactory.getLogger(ResourceConfig.class); + + private static final String ELEMENT_IOMANAGER = "iomanager"; + private static final String ELEMENT_IOHANDLER = "iohandler"; + + private static final String ELEMENT_PROPERTYMANAGER = "propertymanager"; + private static final String ELEMENT_PROPERTYHANDLER = "propertyhandler"; + + private static final String ELEMENT_COPYMOVEMANAGER = "copymovemanager"; + private static final String ELEMENT_COPYMOVEHANDLER = "copymovehandler"; + + private static final String ELEMENT_CLASS = "class"; + + private static final String ELEMENT_PARAM = "param"; + private static final String ATTR_NAME = "name"; + private static final String ATTR_VALUE = "value"; + + /** + * Content type detector. + */ + private final Detector detector; + + private ItemFilter itemFilter; + private IOManager ioManager; + private CopyMoveManager cmManager; + private PropertyManager propManager; + private DeleteManager deleteManager; + private String[] nodetypeNames = new String[0]; + private boolean collectionNames = false; + + public ResourceConfig(Detector detector) { + this.detector = detector; + } + + /** + * Tries to parse the given xml configuration file. + * The xml must match the following structure:
+ *
+     * <!ELEMENT config (iomanager, propertymanager, (collection | noncollection)?, filter?, mimetypeproperties?) >
+     * <!ELEMENT iomanager (class, iohandler*) >
+     * <!ELEMENT iohandler (class) >
+     * <!ELEMENT propertymanager (class, propertyhandler*) >
+     * <!ELEMENT propertyhandler (class) >
+     * <!ELEMENT collection (nodetypes) >
+     * <!ELEMENT noncollection (nodetypes) >
+     * <!ELEMENT filter (class, namespaces?, nodetypes?) >
+     * <!ELEMENT class >
+     *    <!ATTLIST class
+     *      name  CDATA #REQUIRED
+     *    >
+     * <!ELEMENT namespaces (prefix|uri)* >
+     * <!ELEMENT prefix (CDATA) >
+     * <!ELEMENT uri (CDATA) >
+     * <!ELEMENT nodetypes (nodetype)* >
+     * <!ELEMENT nodetype (CDATA) >
+     * <!ELEMENT mimetypeproperties (mimemapping*, defaultmimetype) >
+     * <!ELEMENT mimemapping >
+     *    <!ATTLIST mimemapping
+     *      extension  CDATA #REQUIRED
+     *      mimetype  CDATA #REQUIRED
+     *    >
+     * <!ELEMENT defaultmimetype (CDATA) >
+     * 
+ *

+ * The <mimetypeproperties/> settings have been deprecated and will + * be ignored with a warning. Instead you can use the + * {@link SimpleWebdavServlet#INIT_PARAM_MIME_INFO mime-info} + * servlet initialization parameter to customize the media type settings. + * + * @param configURL + */ + public void parse(URL configURL) { + try { + parse(configURL.openStream()); + } catch (IOException e) { + log.debug("Invalid resource configuration: " + e.getMessage()); + } + } + + /** + * Parses the given input stream into the xml configuration file. + * The xml must match the following structure:
+ *

+     * <!ELEMENT config (iomanager, propertymanager, (collection | noncollection)?, filter?, mimetypeproperties?) >
+     * <!ELEMENT iomanager (class, iohandler*) >
+     * <!ELEMENT iohandler (class) >
+     * <!ELEMENT propertymanager (class, propertyhandler*) >
+     * <!ELEMENT propertyhandler (class) >
+     * <!ELEMENT collection (nodetypes) >
+     * <!ELEMENT noncollection (nodetypes) >
+     * <!ELEMENT filter (class, namespaces?, nodetypes?) >
+     * <!ELEMENT class >
+     *    <!ATTLIST class
+     *      name  CDATA #REQUIRED
+     *    >
+     * <!ELEMENT namespaces (prefix|uri)* >
+     * <!ELEMENT prefix (CDATA) >
+     * <!ELEMENT uri (CDATA) >
+     * <!ELEMENT nodetypes (nodetype)* >
+     * <!ELEMENT nodetype (CDATA) >
+     * <!ELEMENT mimetypeproperties (mimemapping*, defaultmimetype) >
+     * <!ELEMENT mimemapping >
+     *    <!ATTLIST mimemapping
+     *      extension  CDATA #REQUIRED
+     *      mimetype  CDATA #REQUIRED
+     *    >
+     * <!ELEMENT defaultmimetype (CDATA) >
+     * 
+ *

+ * The <mimetypeproperties/> settings have been deprecated and will + * be ignored with a warning. Instead you can use the + * {@link SimpleWebdavServlet#INIT_PARAM_MIME_INFO mime-info} + * servlet initialization parameter to customize the media type settings. + * + * @param stream + */ + public void parse(InputStream stream) { + try { + Element config = DomUtil.parseDocument(stream).getDocumentElement(); + if (config == null) { + log.warn("Mandatory 'config' element is missing."); + return; + } + + // iomanager config entry + Element el = DomUtil.getChildElement(config, ELEMENT_IOMANAGER, null); + if (el != null) { + Object inst = buildClassFromConfig(el); + if (inst != null && inst instanceof IOManager) { + ioManager = (IOManager)inst; + ioManager.setDetector(detector); + // get optional 'iohandler' child elements and populate the + // ioManager with the instances + ElementIterator iohElements = DomUtil.getChildren(el, ELEMENT_IOHANDLER, null); + while (iohElements.hasNext()) { + Element iohEl = iohElements.nextElement(); + inst = buildClassFromConfig(iohEl); + if (inst != null && inst instanceof IOHandler) { + IOHandler handler = (IOHandler) inst; + setParameters(handler, iohEl); + ioManager.addIOHandler(handler); + } else { + log.warn("Not a valid IOHandler : " + getClassName(iohEl)); + } + } + } else { + log.warn("'iomanager' element does not define a valid IOManager."); + } + } else { + log.warn("'iomanager' element is missing."); + } + + // propertymanager config entry + el = DomUtil.getChildElement(config, ELEMENT_PROPERTYMANAGER, null); + if (el != null) { + Object inst = buildClassFromConfig(el); + if (inst != null && inst instanceof PropertyManager) { + propManager = (PropertyManager)inst; + // get optional 'iohandler' child elements and populate the + // ioManager with the instances + ElementIterator iohElements = DomUtil.getChildren(el, ELEMENT_PROPERTYHANDLER, null); + while (iohElements.hasNext()) { + Element iohEl = iohElements.nextElement(); + inst = buildClassFromConfig(iohEl); + if (inst != null && inst instanceof PropertyHandler) { + PropertyHandler handler = (PropertyHandler) inst; + setParameters(handler, iohEl); + propManager.addPropertyHandler(handler); + } else { + log.warn("Not a valid PropertyHandler : " + getClassName(iohEl)); + } + } + } else { + log.warn("'propertymanager' element does not define a valid PropertyManager."); + } + } else { + log.debug("'propertymanager' element is missing."); + } + + // copymovemanager config entry + el = DomUtil.getChildElement(config, ELEMENT_COPYMOVEMANAGER, null); + if (el != null) { + Object inst = buildClassFromConfig(el); + if (inst != null && inst instanceof CopyMoveManager) { + cmManager = (CopyMoveManager) inst; + // get optional 'copymovehandler' child elements and populate + // the copy move manager with the instances + ElementIterator iohElements = DomUtil.getChildren(el, ELEMENT_COPYMOVEHANDLER, null); + while (iohElements.hasNext()) { + Element iohEl = iohElements.nextElement(); + inst = buildClassFromConfig(iohEl); + if (inst != null && inst instanceof CopyMoveHandler) { + CopyMoveHandler handler = (CopyMoveHandler) inst; + setParameters(handler, iohEl); + cmManager.addCopyMoveHandler(handler); + } else { + log.warn("Not a valid CopyMoveHandler : " + getClassName(iohEl)); + } + } + } else { + log.warn("'copymovemanager' element does not define a valid CopyMoveManager."); + } + } else { + log.debug("'copymovemanager' element is missing."); + } + + // collection/non-collection config entry + el = DomUtil.getChildElement(config, "collection", null); + if (el != null) { + nodetypeNames = parseNodeTypesEntry(el); + collectionNames = true; + } else if ((el = DomUtil.getChildElement(config, "noncollection", null)) != null) { + nodetypeNames = parseNodeTypesEntry(el); + collectionNames = false; + } + // todo: should check if both 'noncollection' and 'collection' are present and write a warning + + // filter config entry + el = DomUtil.getChildElement(config, "filter", null); + if (el != null) { + Object inst = buildClassFromConfig(el); + if (inst != null && inst instanceof ItemFilter) { + itemFilter = (ItemFilter)inst; + } + if (itemFilter != null) { + itemFilter.setFilteredNodetypes(parseNodeTypesEntry(el)); + parseNamespacesEntry(el); + } + } else { + log.debug("No 'filter' element specified."); + } + + el = DomUtil.getChildElement(config, "mimetypeproperties", null); + if (el != null) { + log.warn("Ignoring deprecated mimetypeproperties settings"); + } + } catch (IOException e) { + log.debug("Invalid resource configuration: " + e.getMessage()); + } catch (ParserConfigurationException e) { + log.warn("Failed to parse resource configuration: " + e.getMessage()); + } catch (SAXException e) { + log.warn("Failed to parse resource configuration: " + e.getMessage()); + } + } + + private void parseNamespacesEntry(Element parent) { + Element namespaces = DomUtil.getChildElement(parent, "namespaces", null); + if (namespaces != null) { + List l = new ArrayList(); + // retrieve prefix child elements + ElementIterator it = DomUtil.getChildren(namespaces, "prefix", null); + while (it.hasNext()) { + Element e = it.nextElement(); + l.add(DomUtil.getText(e)); + } + String[] prefixes = l.toArray(new String[l.size()]); + l.clear(); + // retrieve uri child elements + it = DomUtil.getChildren(namespaces, "uri", null); + while (it.hasNext()) { + Element e = it.nextElement(); + l.add(DomUtil.getText(e)); + } + String[] uris = l.toArray(new String[l.size()]); + itemFilter.setFilteredPrefixes(prefixes); + itemFilter.setFilteredURIs(uris); + } + } + + private static String[] parseNodeTypesEntry(Element parent) { + String[] ntNames; + Element nodetypes = DomUtil.getChildElement(parent, "nodetypes", null); + if (nodetypes != null) { + List l = new ArrayList(); + ElementIterator it = DomUtil.getChildren(nodetypes, "nodetype", null); + while (it.hasNext()) { + Element e = it.nextElement(); + l.add(DomUtil.getText(e)); + } + ntNames = l.toArray(new String[l.size()]); + } else { + ntNames = new String[0]; + } + return ntNames; + } + + private static Object buildClassFromConfig(Element parent) { + Object instance = null; + Element classElem = DomUtil.getChildElement(parent, "class", null); + if (classElem != null) { + // contains a 'class' child node + try { + String className = DomUtil.getAttribute(classElem, "name", null); + if (className != null) { + Class c = Class.forName(className); + instance = c.newInstance(); + } else { + log.error("Invalid configuration: missing 'class' element"); + } + } catch (Exception e) { + log.error("Error while create class instance: " + e.getMessage()); + } + } + return instance; + } + + private static String getClassName(Element parent) { + String className = null; + Element classElem = DomUtil.getChildElement(parent, "class", null); + if (classElem != null) { + className = DomUtil.getAttribute(classElem, "name", null); + } + return (className == null) ? "" : className; + } + + /** + * Retrieve 'param' elements for the specified xmlElement and + * use the public setter methods of the given instance to set + * the corresponding instance fields. + * + * @param instance + * @param xmlElement + */ + private static void setParameters(Object instance, Element xmlElement) { + ElementIterator paramElems = DomUtil.getChildren(xmlElement, ELEMENT_PARAM, Namespace.EMPTY_NAMESPACE); + if (paramElems.hasNext()) { + Map setters = getSetters(instance.getClass()); + if (!setters.isEmpty()) { + while (paramElems.hasNext()) { + Element parameter = paramElems.next(); + String name = DomUtil.getAttribute(parameter, ATTR_NAME, null); + String value = DomUtil.getAttribute(parameter, ATTR_VALUE, null); + if (name == null || value == null) { + log.error("Parameter name or value missing -> ignore."); + continue; + } + Method setter = setters.get(name); + if (setter != null) { + Class type = setter.getParameterTypes()[0]; + try { + if (type.isAssignableFrom(String.class) + || type.isAssignableFrom(Object.class)) { + setter.invoke(instance, value); + } else if (type.isAssignableFrom(Boolean.TYPE) + || type.isAssignableFrom(Boolean.class)) { + setter.invoke(instance, Boolean.valueOf(value)); + } else if (type.isAssignableFrom(Integer.TYPE) + || type.isAssignableFrom(Integer.class)) { + setter.invoke(instance, Integer.valueOf(value)); + } else if (type.isAssignableFrom(Long.TYPE) + || type.isAssignableFrom(Long.class)) { + setter.invoke(instance, Long.valueOf(value)); + } else if (type.isAssignableFrom(Double.TYPE) + || type.isAssignableFrom(Double.class)) { + setter.invoke(instance, Double.valueOf(value)); + } else { + log.error("Cannot set configuration property " + name); + } + } catch (Exception e) { + log.error("Invalid format (" + value + ") for property " + name + " of class " + instance.getClass().getName(), e); + } + } + } + } + } + } + + private static Map getSetters(Class cl) { + Map methods = new HashMap(); + for (Method method : cl.getMethods()) { + String name = method.getName(); + if (name.startsWith("set") && name.length() > 3 + && Modifier.isPublic(method.getModifiers()) + && !Modifier.isStatic(method.getModifiers()) + && Void.TYPE.equals(method.getReturnType()) + && method.getParameterTypes().length == 1) { + methods.put(name.substring(3, 4).toLowerCase() + name.substring(4), method); + } + } + return methods; + } + + /** + * + * @return + */ + public IOManager getIOManager() { + if (ioManager == null) { + log.debug("Missing io-manager > building DefaultIOManager "); + ioManager = new DefaultIOManager(); + ioManager.setDetector(detector); + } + return ioManager; + } + + /** + * + * @return + */ + public PropertyManager getPropertyManager() { + if (propManager == null) { + log.debug("Missing property-manager > building default."); + propManager = PropertyManagerImpl.getDefaultManager(); + } + return propManager; + } + + /** + * + * @return + */ + public CopyMoveManager getCopyMoveManager() { + if (cmManager == null) { + log.debug("Missing copymove-manager > building default."); + cmManager = CopyMoveManagerImpl.getDefaultManager(); + } + return cmManager; + } + + /** + * Returns the delete manager. + * @return the delete manager + */ + public DeleteManager getDeleteManager() { + if (deleteManager == null) { + log.debug("Missing delete-manager > building default."); + deleteManager = DeleteManagerImpl.getDefaultManager(); + } + return deleteManager; + } + + /** + * Returns true, if the given item represents a {@link Node node} that is + * either any of the nodetypes specified to represent a collection or + * none of the nodetypes specified to represent a non-collection, respectively. + * If no valid configuration entry is present, this method returns true + * for node items. For items which are not a node, this method always + * returns false. + * + * @param item + * @return true if the given item is a node that represents a webdav + * collection, false otherwise. + */ + public boolean isCollectionResource(Item item) { + if (item.isNode()) { + boolean isCollection = true; + Node n = (Node)item; + try { + for (int i = 0; i < nodetypeNames.length && isCollection; i++) { + isCollection = collectionNames ? n.isNodeType(nodetypeNames[i]) : !n.isNodeType(nodetypeNames[i]); + } + } catch (RepositoryException e) { + log.warn(e.getMessage()); + } + return isCollection; + } else { + return false; + } + } + + /** + * Returns the item filter specified with the configuration or {@link DefaultItemFilter} + * if the configuration was missing the corresponding entry or the parser failed + * to build a ItemFilter instance from the configuration. + * + * @return item filter as defined by the config or {@link DefaultItemFilter} + */ + public ItemFilter getItemFilter() { + if (itemFilter == null) { + log.debug("Missing resource filter > building DefaultItemFilter "); + itemFilter = new DefaultItemFilter(); + } + return itemFilter; + } + + /** + * Returns the configured content type detector. + * + * @return content type detector + */ + public Detector getDetector() { + return detector; + } + +} Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/simple/ResourceConfig.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 \ No newline at end of property Index: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/simple/ResourceFactoryImpl.java =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/simple/ResourceFactoryImpl.java (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/simple/ResourceFactoryImpl.java (working copy) @@ -0,0 +1,208 @@ +/* + * 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.webdav.simple; + +import org.apache.jackrabbit.webdav.DavException; +import org.apache.jackrabbit.webdav.DavMethods; +import org.apache.jackrabbit.webdav.DavResource; +import org.apache.jackrabbit.webdav.DavResourceFactory; +import org.apache.jackrabbit.webdav.DavResourceLocator; +import org.apache.jackrabbit.webdav.DavServletRequest; +import org.apache.jackrabbit.webdav.DavServletResponse; +import org.apache.jackrabbit.webdav.DavSession; +import org.apache.jackrabbit.webdav.jcr.JcrDavSession; +import org.apache.jackrabbit.webdav.lock.LockManager; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.jcr.Item; +import javax.jcr.Node; +import javax.jcr.PathNotFoundException; +import javax.jcr.RepositoryException; +import javax.jcr.Repository; +import javax.jcr.Session; +import javax.jcr.version.Version; +import javax.jcr.version.VersionHistory; + +/** + * ResourceFactoryImpl implements a simple DavResourceFactory + */ +public class ResourceFactoryImpl implements DavResourceFactory { + + private static Logger log =LoggerFactory.getLogger(ResourceFactoryImpl.class); + + private final LockManager lockMgr; + private final ResourceConfig resourceConfig; + + /** + * Create a new ResourceFactory that uses the given lock + * manager and resource filter. + * + * @param lockMgr + * @param resourceConfig + */ + public ResourceFactoryImpl(LockManager lockMgr, ResourceConfig resourceConfig) { + this.lockMgr = lockMgr; + this.resourceConfig = resourceConfig; + } + + /** + * Create a new DavResource from the given locator and + * request. + * + * @param locator + * @param request + * @param response + * @return DavResource + * @throws DavException + * @see DavResourceFactory#createResource(DavResourceLocator, + * DavServletRequest, DavServletResponse) + */ + public DavResource createResource(DavResourceLocator locator, DavServletRequest request, + DavServletResponse response) throws DavException { + try { + Node node = getNode(request.getDavSession(), locator); + DavResource resource; + if (node == null) { + log.debug("Creating resource for non-existing repository node."); + boolean isCollection = DavMethods.isCreateCollectionRequest(request); + resource = createNullResource(locator, request.getDavSession(), isCollection); + } else { + resource = createResource(node, locator, request.getDavSession()); + } + resource.addLockManager(lockMgr); + return resource; + } catch (RepositoryException e) { + throw new DavException(DavServletResponse.SC_INTERNAL_SERVER_ERROR, e); + } + } + + /** + * Create a new DavResource from the given locator and webdav + * session. + * + * @param locator + * @param session + * @return + * @throws DavException + * @see DavResourceFactory#createResource(DavResourceLocator, DavSession) + */ + public DavResource createResource(DavResourceLocator locator, DavSession session) throws DavException { + try { + Node node = getNode(session, locator); + DavResource resource = createResource(node, locator, session); + resource.addLockManager(lockMgr); + return resource; + } catch (RepositoryException e) { + throw new DavException(DavServletResponse.SC_INTERNAL_SERVER_ERROR, e); + } + } + + /** + * Returns the Node corresponding to the given locator or + * null if it does not exist or if the existing item represents + * a Property. + * + * @param sessionImpl + * @param locator + * @return + * @throws RepositoryException + */ + private Node getNode(DavSession sessionImpl, DavResourceLocator locator) + throws RepositoryException { + Node node = null; + try { + String repoPath = locator.getRepositoryPath(); + if (repoPath != null) { + Session session = ((JcrDavSession)sessionImpl).getRepositorySession(); + Item item = session.getItem(repoPath); + if (item instanceof Node) { + node = (Node)item; + } // else: item is a property -> return null + } + } catch (PathNotFoundException e) { + // item does not exist (yet). return null -> create null-resource + } + return node; + } + + /** + * Create a 'null resource' + * + * @param locator + * @param session + * @param isCollection + * @return + * @throws DavException + */ + private DavResource createNullResource(DavResourceLocator locator, + DavSession session, + boolean isCollection) throws DavException { + JcrDavSession.checkImplementation(session); + JcrDavSession sessionImpl = (JcrDavSession)session; + + DavResource resource; + if (versioningSupported(sessionImpl.getRepositorySession())) { + resource = new VersionControlledResourceImpl(locator, this, sessionImpl, resourceConfig, isCollection); + } else { + resource = new DavResourceImpl(locator, this, sessionImpl, resourceConfig, isCollection); + } + return resource; + } + + /** + * Tries to retrieve the repository item defined by the locator's resource + * path and build the corresponding WebDAV resource. If the repository + * supports the versioning option different resources are created for + * version, versionhistory and common nodes. + * + * @param node + * @param locator + * @param session + * @return + * @throws DavException + */ + private DavResource createResource(Node node, DavResourceLocator locator, + DavSession session) throws DavException { + JcrDavSession.checkImplementation(session); + JcrDavSession sessionImpl = (JcrDavSession)session; + + DavResource resource; + if (versioningSupported(sessionImpl.getRepositorySession())) { + // create special resources for Version and VersionHistory + if (node instanceof Version) { + resource = new VersionResourceImpl(locator, this, sessionImpl, resourceConfig, node); + } else if (node instanceof VersionHistory) { + resource = new VersionHistoryResourceImpl(locator, this, sessionImpl, resourceConfig, node); + } else { + resource = new VersionControlledResourceImpl(locator, this, sessionImpl, resourceConfig, node); + } + } else { + resource = new DavResourceImpl(locator, this, session, resourceConfig, node); + } + return resource; + } + + /** + * @param repoSession + * @return true if the JCR repository supports versioning. + */ + private static boolean versioningSupported(Session repoSession) { + String desc = repoSession.getRepository().getDescriptor(Repository.OPTION_VERSIONING_SUPPORTED); + return Boolean.valueOf(desc); + } +} Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/simple/ResourceFactoryImpl.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/webdav/simple/SimpleWebdavServlet.java =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/simple/SimpleWebdavServlet.java (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/simple/SimpleWebdavServlet.java (working copy) @@ -0,0 +1,411 @@ +/* + * 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.webdav.simple; + +import org.apache.jackrabbit.server.BasicCredentialsProvider; +import org.apache.jackrabbit.server.CredentialsProvider; +import org.apache.jackrabbit.server.SessionProvider; +import org.apache.jackrabbit.server.SessionProviderImpl; +import org.apache.jackrabbit.webdav.DavLocatorFactory; +import org.apache.jackrabbit.webdav.DavResource; +import org.apache.jackrabbit.webdav.DavResourceFactory; +import org.apache.jackrabbit.webdav.DavSessionProvider; +import org.apache.jackrabbit.webdav.WebdavRequest; +import org.apache.jackrabbit.webdav.lock.LockManager; +import org.apache.jackrabbit.webdav.lock.SimpleLockManager; +import org.apache.jackrabbit.webdav.server.AbstractWebdavServlet; +import org.apache.jackrabbit.webdav.util.HttpDateTimeFormatter; +import org.apache.tika.detect.Detector; +import org.apache.tika.mime.MimeTypeException; +import org.apache.tika.mime.MimeTypesFactory; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.jcr.Repository; +import javax.servlet.ServletContext; +import javax.servlet.ServletException; + +import java.io.IOException; +import java.net.MalformedURLException; +import java.net.URL; +import java.time.format.DateTimeParseException; + +/** + * WebdavServlet provides WebDAV support (level + * {@link org.apache.jackrabbit.webdav.DavCompliance#_1_ 1}, + * {@link org.apache.jackrabbit.webdav.DavCompliance#_2_ 2}, + * {@link org.apache.jackrabbit.webdav.DavCompliance#_3_ 3} and + * {@link org.apache.jackrabbit.webdav.DavCompliance#BIND bind} compliant) for + * repository resources. + *

+ * Implementations of this abstract class must implement the + * {@link #getRepository()} method to access the repository. + */ +public abstract class SimpleWebdavServlet extends AbstractWebdavServlet { + + /** + * the default logger + */ + private static final Logger log = LoggerFactory.getLogger(SimpleWebdavServlet.class); + + /** + * init param name of the repository prefix + */ + public static final String INIT_PARAM_RESOURCE_PATH_PREFIX = "resource-path-prefix"; + + /** + * Name of the init parameter that specify a separate configuration used + * for filtering the resources displayed. + */ + public static final String INIT_PARAM_RESOURCE_CONFIG = "resource-config"; + + /** + * Name of the parameter that specifies the servlet resource path of + * a custom <mime-info/> configuration file. The default setting + * is to use the MIME media type database included in Apache Tika. + */ + public static final String INIT_PARAM_MIME_INFO = "mime-info"; + + /** + * Servlet context attribute used to store the path prefix instead of + * having a static field with this servlet. The latter causes problems + * when running multiple + */ + public static final String CTX_ATTR_RESOURCE_PATH_PREFIX = "jackrabbit.webdav.simple.resourcepath"; + + /** + * the resource path prefix + */ + private String resourcePathPrefix; + + /** + * Map used to remember any webdav lock created without being reflected + * in the underlying repository. + * This is needed because some clients rely on a successful locking + * mechanism in order to perform properly (e.g. mac OSX built-in dav client) + */ + private LockManager lockManager; + + /** + * the resource factory + */ + private DavResourceFactory resourceFactory; + + /** + * the locator factory + */ + private DavLocatorFactory locatorFactory; + + /** + * the webdav session provider + */ + private DavSessionProvider davSessionProvider; + + /** + * the repository session provider + */ + private SessionProvider sessionProvider; + + /** + * The config + */ + private ResourceConfig config; + + /** + * Init this servlet + * + * @throws ServletException + */ + @Override + public void init() throws ServletException { + super.init(); + + resourcePathPrefix = getInitParameter(INIT_PARAM_RESOURCE_PATH_PREFIX); + if (resourcePathPrefix == null) { + log.debug("Missing path prefix > setting to empty string."); + resourcePathPrefix = ""; + } else if (resourcePathPrefix.endsWith("/")) { + log.debug("Path prefix ends with '/' > removing trailing slash."); + resourcePathPrefix = resourcePathPrefix.substring(0, resourcePathPrefix.length() - 1); + } + getServletContext().setAttribute(CTX_ATTR_RESOURCE_PATH_PREFIX, resourcePathPrefix); + log.info(INIT_PARAM_RESOURCE_PATH_PREFIX + " = '" + resourcePathPrefix + "'"); + + config = new ResourceConfig(getDetector()); + String configParam = getInitParameter(INIT_PARAM_RESOURCE_CONFIG); + if (configParam != null) { + try { + config.parse(getServletContext().getResource(configParam)); + } catch (MalformedURLException e) { + log.debug("Unable to build resource filter provider", e); + } + } + } + + /** + * Reads and returns the configured <mime-info/> database. + * + * @see #INIT_PARAM_MIME_INFO + * @return MIME media type database + * @throws ServletException if the database is invalid or can not be read + */ + private Detector getDetector() throws ServletException { + URL url; + + String mimeInfo = getInitParameter(INIT_PARAM_MIME_INFO); + if (mimeInfo != null) { + try { + url = getServletContext().getResource(mimeInfo); + } catch (MalformedURLException e) { + throw new ServletException( + "Invalid " + INIT_PARAM_MIME_INFO + + " configuration setting: " + mimeInfo, e); + } + } else { + url = MimeTypesFactory.class.getResource("tika-mimetypes.xml"); + } + + try { + return MimeTypesFactory.create(url); + } catch (MimeTypeException e) { + throw new ServletException( + "Invalid MIME media type database: " + url, e); + } catch (IOException e) { + throw new ServletException( + "Unable to read MIME media type database: " + url, e); + } + } + + /** + * {@inheritDoc} + */ + @Override + protected boolean isPreconditionValid(WebdavRequest request, + DavResource resource) { + + long ifUnmodifiedSince = UNDEFINED_TIME; + try { + // will throw if multiple field lines present + String value = AbstractWebdavServlet.getSingletonField(request, "If-Unmodified-Since"); + if (value != null) { + ifUnmodifiedSince = HttpDateTimeFormatter.parse(value); + } + } catch (IllegalArgumentException | DateTimeParseException ex) { + log.debug("illegal value for if-unmodified-since ignored: " + ex.getMessage()); + } + + if (ifUnmodifiedSince > UNDEFINED_TIME && resource.exists()) { + if (resource.getModificationTime() / 1000 > ifUnmodifiedSince / 1000) { + return false; + } + } + + return !resource.exists() || request.matchesIfHeader(resource); + } + + /** + * Returns the configured path prefix + * + * @return resourcePathPrefix + * @see #INIT_PARAM_RESOURCE_PATH_PREFIX + */ + public String getPathPrefix() { + return resourcePathPrefix; + } + + /** + * Returns the configured path prefix + * + * @param ctx The servlet context. + * @return resourcePathPrefix + * @see #INIT_PARAM_RESOURCE_PATH_PREFIX + */ + public static String getPathPrefix(ServletContext ctx) { + return (String) ctx.getAttribute(CTX_ATTR_RESOURCE_PATH_PREFIX); + } + + /** + * Returns the DavLocatorFactory. If no locator factory has + * been set or created a new instance of {@link org.apache.jackrabbit.webdav.simple.LocatorFactoryImpl} is + * returned. + * + * @return the locator factory + * @see AbstractWebdavServlet#getLocatorFactory() + */ + @Override + public DavLocatorFactory getLocatorFactory() { + if (locatorFactory == null) { + locatorFactory = new LocatorFactoryImplEx(resourcePathPrefix); + } + return locatorFactory; + } + + /** + * Sets the DavLocatorFactory. + * + * @param locatorFactory The DavLocatorFactory to use. + * @see AbstractWebdavServlet#setLocatorFactory(DavLocatorFactory) + */ + @Override + public void setLocatorFactory(DavLocatorFactory locatorFactory) { + this.locatorFactory = locatorFactory; + } + + /** + * Returns the LockManager. If no lock manager has + * been set or created a new instance of {@link SimpleLockManager} is + * returned. + * + * @return the lock manager + */ + public LockManager getLockManager() { + if (lockManager == null) { + lockManager = new SimpleLockManager(); + } + return lockManager; + } + + /** + * Sets the LockManager. + * + * @param lockManager The LockManager to be used. + */ + public void setLockManager(LockManager lockManager) { + this.lockManager = lockManager; + } + + /** + * Returns the DavResourceFactory. If no request factory has + * been set or created a new instance of {@link ResourceFactoryImpl} is + * returned. + * + * @return the resource factory + * @see AbstractWebdavServlet#getResourceFactory() + */ + @Override + public DavResourceFactory getResourceFactory() { + if (resourceFactory == null) { + resourceFactory = new ResourceFactoryImpl(getLockManager(), getResourceConfig()); + } + return resourceFactory; + } + + /** + * Sets the DavResourceFactory. + * + * @param resourceFactory The DavResourceFactory to use. + * @see AbstractWebdavServlet#setResourceFactory(org.apache.jackrabbit.webdav.DavResourceFactory) + */ + @Override + public void setResourceFactory(DavResourceFactory resourceFactory) { + this.resourceFactory = resourceFactory; + } + + /** + * Returns the SessionProvider. If no session provider has been + * set or created a new instance of {@link SessionProviderImpl} that extracts + * credentials from the Authorization request header is + * returned. + * + * @return the session provider + */ + public synchronized SessionProvider getSessionProvider() { + if (sessionProvider == null) { + sessionProvider = new SessionProviderImpl(getCredentialsProvider()); + } + return sessionProvider; + } + + /** + * Factory method for creating the credentials provider to be used for + * accessing the credentials associated with a request. The default + * implementation returns a {@link BasicCredentialsProvider} instance, + * but subclasses can override this method to add support for other + * types of credentials. + * + * @return the credentials provider + * @since 1.3 + */ + protected CredentialsProvider getCredentialsProvider() { + return new BasicCredentialsProvider(getInitParameter(INIT_PARAM_MISSING_AUTH_MAPPING)); + } + + /** + * Sets the SessionProvider. + * + * @param sessionProvider The SessionProvider to use. + */ + public synchronized void setSessionProvider(SessionProvider sessionProvider) { + this.sessionProvider = sessionProvider; + } + + /** + * Returns the DavSessionProvider. If no session provider has + * been set or created a new instance of {@link DavSessionProviderImpl} + * is returned. + * + * @return the session provider + * @see AbstractWebdavServlet#getDavSessionProvider() + */ + @Override + public synchronized DavSessionProvider getDavSessionProvider() { + if (davSessionProvider == null) { + davSessionProvider = + new DavSessionProviderImpl(getRepository(), getSessionProvider()); + } + return davSessionProvider; + } + + /** + * Sets the DavSessionProvider. + * + * @param sessionProvider The DavSessionProvider to use. + * @see AbstractWebdavServlet#setDavSessionProvider(org.apache.jackrabbit.webdav.DavSessionProvider) + */ + @Override + public synchronized void setDavSessionProvider(DavSessionProvider sessionProvider) { + this.davSessionProvider = sessionProvider; + } + + /** + * Returns the resource configuration to be applied + * + * @return the resource configuration. + */ + public ResourceConfig getResourceConfig() { + return config; + } + + /** + * Set the resource configuration + * + * @param config The resource configuration. + */ + public void setResourceConfig(ResourceConfig config) { + this.config = config; + } + + /** + * Returns the Repository. If no repository has been set or + * created the repository initialized by RepositoryAccessServlet + * is returned. + * + * @return repository + */ + public abstract Repository getRepository(); + +} Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/simple/SimpleWebdavServlet.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/webdav/simple/VersionControlledResourceImpl.java =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/simple/VersionControlledResourceImpl.java (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/simple/VersionControlledResourceImpl.java (working copy) @@ -0,0 +1,379 @@ +/* + * 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.webdav.simple; + +import javax.jcr.Item; +import javax.jcr.Node; +import javax.jcr.RepositoryException; +import javax.jcr.Value; +import javax.jcr.version.Version; +import javax.jcr.version.VersionHistory; + +import org.apache.jackrabbit.JcrConstants; +import org.apache.jackrabbit.webdav.DavException; +import org.apache.jackrabbit.webdav.DavResource; +import org.apache.jackrabbit.webdav.DavResourceFactory; +import org.apache.jackrabbit.webdav.DavResourceLocator; +import org.apache.jackrabbit.webdav.DavServletResponse; +import org.apache.jackrabbit.webdav.DavSession; +import org.apache.jackrabbit.webdav.MultiStatus; +import org.apache.jackrabbit.webdav.DavMethods; +import org.apache.jackrabbit.webdav.jcr.JcrDavException; +import org.apache.jackrabbit.webdav.property.DefaultDavProperty; +import org.apache.jackrabbit.webdav.property.HrefProperty; +import org.apache.jackrabbit.webdav.version.LabelInfo; +import org.apache.jackrabbit.webdav.version.MergeInfo; +import org.apache.jackrabbit.webdav.version.UpdateInfo; +import org.apache.jackrabbit.webdav.version.VersionControlledResource; +import org.apache.jackrabbit.webdav.version.VersionHistoryResource; +import org.apache.jackrabbit.webdav.version.VersionResource; +import org.apache.jackrabbit.webdav.version.VersionableResource; +import org.apache.jackrabbit.webdav.version.report.ReportType; +import org.apache.jackrabbit.webdav.version.report.SupportedReportSetProperty; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + + + +/** + * VersionControlledResourceImpl represents a JCR node item and + * covers all functionality related to versioning of {@link Node}s. + * + * @see Node + */ +public class VersionControlledResourceImpl extends DeltaVResourceImpl + implements VersionControlledResource { + + private static final Logger log = LoggerFactory.getLogger(VersionControlledResourceImpl.class); + + /** + * Create a new {@link org.apache.jackrabbit.webdav.DavResource}. + * + * @param locator + * @param factory + * @param session + * @param config + * @param item + * @throws DavException + */ + public VersionControlledResourceImpl(DavResourceLocator locator, DavResourceFactory factory, DavSession session, ResourceConfig config, Item item) throws DavException { + super(locator, factory, session, config, item); + initSupportedReports(); + } + + /** + * Create a new {@link org.apache.jackrabbit.webdav.DavResource}. + * + * @param locator + * @param factory + * @param session + * @param config + * @param isCollection + * @throws DavException + */ + public VersionControlledResourceImpl(DavResourceLocator locator, DavResourceFactory factory, DavSession session, ResourceConfig config, boolean isCollection) throws DavException { + super(locator, factory, session, config, isCollection); + initSupportedReports(); + } + + //--------------------------------------------------------< DavResource >--- + /** + * Return a comma separated string listing the supported method names. + * + * @return the supported method names. + * @see org.apache.jackrabbit.webdav.DavResource#getSupportedMethods() + */ + @Override + public String getSupportedMethods() { + StringBuffer sb = new StringBuffer(super.getSupportedMethods()); + // Versioning support + sb.append(", ").append(VersionableResource.METHODS); + if (isVersionControlled()) { + try { + if (getNode().isCheckedOut()) { + sb.append(", ").append(DavMethods.METHOD_CHECKIN); + } else { + sb.append(", ").append(DavMethods.METHOD_CHECKOUT); + sb.append(", ").append(DavMethods.METHOD_LABEL); + } + } catch (RepositoryException e) { + // should not occur. + log.error(e.getMessage()); + } + } + return sb.toString(); + } + + //------------------------------------------< VersionControlledResource >--- + /** + * Adds version control to this resource. If the resource is already under + * version control, this method has no effect. If this resource is a Collection + * resource this method fails with {@link DavServletResponse#SC_METHOD_NOT_ALLOWED}. + * + * @throws org.apache.jackrabbit.webdav.DavException if this resource does not + * exist yet, is a collection or if an error occurs while making the + * underlying node versionable. + * @see org.apache.jackrabbit.webdav.version.VersionableResource#addVersionControl() + */ + public void addVersionControl() throws DavException { + if (!exists()) { + throw new DavException(DavServletResponse.SC_NOT_FOUND); + } + if (isCollection()) { + // since the version-controlled-collection feature is not supported + // collections may not be put under dav version control even if + // the underlying node was / could be made jcr versionable. + throw new DavException(DavServletResponse.SC_METHOD_NOT_ALLOWED); + } + if (!isVersionControlled()) { + Node item = getNode(); + try { + item.addMixin(JcrConstants.MIX_VERSIONABLE); + item.save(); + } catch (RepositoryException e) { + throw new JcrDavException(e); + } + } // else: is already version controlled -> ignore + } + + /** + * Calls {@link javax.jcr.Node#checkin()} on the underlying repository node. + * + * @throws org.apache.jackrabbit.webdav.DavException + * @see org.apache.jackrabbit.webdav.version.VersionControlledResource#checkin() + */ + public String checkin() throws DavException { + if (!exists()) { + throw new DavException(DavServletResponse.SC_NOT_FOUND); + } + if (!isVersionControlled()) { + throw new DavException(DavServletResponse.SC_METHOD_NOT_ALLOWED); + } + try { + Version v = getNode().checkin(); + String versionHref = getLocatorFromNode(v).getHref(false); + return versionHref; + } catch (RepositoryException e) { + // UnsupportedRepositoryException should not occur + throw new JcrDavException(e); + } + } + + /** + * Calls {@link javax.jcr.Node#checkout()} on the underlying repository node. + * + * @throws org.apache.jackrabbit.webdav.DavException + * @see org.apache.jackrabbit.webdav.version.VersionControlledResource#checkout() + */ + public void checkout() throws DavException { + if (!exists()) { + throw new DavException(DavServletResponse.SC_NOT_FOUND); + } + if (!isVersionControlled()) { + throw new DavException(DavServletResponse.SC_METHOD_NOT_ALLOWED); + } + try { + getNode().checkout(); + } catch (RepositoryException e) { + // UnsupportedRepositoryException should not occur + throw new JcrDavException(e); + } + } + + + /** + * UNCHECKOUT cannot be implemented on top of JSR 170 repository. + * Therefore this methods always throws a DavException with error code + * {@link org.apache.jackrabbit.webdav.DavServletResponse#SC_NOT_IMPLEMENTED}. + * + * @throws org.apache.jackrabbit.webdav.DavException + * @see org.apache.jackrabbit.webdav.version.VersionControlledResource#uncheckout() + */ + public void uncheckout() throws DavException { + throw new DavException(DavServletResponse.SC_NOT_IMPLEMENTED); + } + + /** + * UPDATE feature is not (yet) supported. This method allows fails with + * {@link DavServletResponse#SC_NOT_IMPLEMENTED}. + * + * @param updateInfo + * @return + * @throws DavException + * @see VersionControlledResource#update(UpdateInfo) + */ + public MultiStatus update(UpdateInfo updateInfo) throws DavException { + throw new DavException(DavServletResponse.SC_NOT_IMPLEMENTED); + } + + /** + * MERGE feature is not (yet) supported. This method allows fails with + * {@link DavServletResponse#SC_NOT_IMPLEMENTED}. + * + * @param mergeInfo + * @return + * @throws DavException + * @see VersionControlledResource#merge(MergeInfo) + */ + public MultiStatus merge(MergeInfo mergeInfo) throws DavException { + throw new DavException(DavServletResponse.SC_NOT_IMPLEMENTED); + } + + /** + * Modify the labels present with the versions of this resource. + * + * @param labelInfo + * @throws DavException + * @see VersionControlledResource#label(LabelInfo) + * @see javax.jcr.version.VersionHistory#addVersionLabel(String, String, boolean) + * @see javax.jcr.version.VersionHistory#removeVersionLabel(String) + */ + public void label(LabelInfo labelInfo) throws DavException { + if (labelInfo == null) { + throw new DavException(DavServletResponse.SC_BAD_REQUEST, "Valid label request body required."); + } + if (!exists()) { + throw new DavException(DavServletResponse.SC_NOT_FOUND); + } + + try { + if (!isVersionControlled() || getNode().isCheckedOut()) { + throw new DavException(DavServletResponse.SC_PRECONDITION_FAILED, "A LABEL request may only be applied to a version-controlled, checked-in resource."); + } + DavResource[] resArr = this.getReferenceResources(CHECKED_IN); + if (resArr.length == 1 && resArr[0] instanceof VersionResource) { + ((VersionResource)resArr[0]).label(labelInfo); + } else { + throw new DavException(DavServletResponse.SC_INTERNAL_SERVER_ERROR, "DAV:checked-in property on '" + getHref() + "' did not point to a single VersionResource."); + } + } catch (RepositoryException e) { + throw new JcrDavException(e); + } + } + + /** + * Returns the {@link javax.jcr.version.VersionHistory} associated with the repository node. + * If the node is not versionable an exception is thrown. + * + * @return the {@link VersionHistoryResource} associated with this resource. + * @throws org.apache.jackrabbit.webdav.DavException + * @see org.apache.jackrabbit.webdav.version.VersionControlledResource#getVersionHistory() + * @see javax.jcr.Node#getVersionHistory() + */ + public VersionHistoryResource getVersionHistory() throws DavException { + if (!exists()) { + throw new DavException(DavServletResponse.SC_NOT_FOUND); + } + if (!isVersionControlled()) { + throw new DavException(DavServletResponse.SC_FORBIDDEN); + } + try { + VersionHistory vh = getNode().getVersionHistory(); + DavResourceLocator loc = getLocatorFromNode(vh); + DavResource vhr = createResourceFromLocator(loc); + if (vhr instanceof VersionHistoryResource) { + return (VersionHistoryResource)vhr; + } else { + // severe error since resource factory doesn't behave correctly. + throw new DavException(DavServletResponse.SC_INTERNAL_SERVER_ERROR); + } + } catch (RepositoryException e) { + throw new JcrDavException(e); + } + } + + //-------------------------------------------------------------------------- + /** + * Define the set of reports supported by this resource. + * + * @see SupportedReportSetProperty + * @see DeltaVResourceImpl#initSupportedReports() + */ + @Override + protected void initSupportedReports() { + super.initSupportedReports(); + if (exists()) { + supportedReports.addReportType(ReportType.LOCATE_BY_HISTORY); + if (isVersionControlled()) { + supportedReports.addReportType(ReportType.VERSION_TREE); + } + } + } + + /** + * Fill the property set for this resource. + * @see DavResourceImpl#initProperties() + */ + @Override + protected void initProperties() { + if (!propsInitialized) { + super.initProperties(); + if (isVersionControlled()) { + Node n = getNode(); + // properties defined by RFC 3253 for version-controlled resources + try { + // DAV:version-history (computed) + String vhHref = getLocatorFromNode(n.getVersionHistory()).getHref(true); + properties.add(new HrefProperty(VERSION_HISTORY, vhHref, true)); + + // DAV:auto-version property: there is no auto version, explicit CHECKOUT is required. + properties.add(new DefaultDavProperty(AUTO_VERSION, null, true)); + + // baseVersion -> used for DAV:checked-out or DAV:checked-in + String baseVHref = getLocatorFromNode(n.getBaseVersion()).getHref(false); + if (n.isCheckedOut()) { + // DAV:predecessors property + if (n.hasProperty(JcrConstants.JCR_PREDECESSORS)) { + Value[] pv = n.getProperty(JcrConstants.JCR_PREDECESSORS).getValues(); + Node[] predecessors = new Node[pv.length]; + for (int i = 0; i < pv.length; i++) { + predecessors[i] = n.getSession().getNodeByIdentifier(pv[i].getString()); + } + properties.add(getHrefProperty(VersionResource.PREDECESSOR_SET, predecessors, true, false)); + } + // DAV:checked-out property (protected) + properties.add(new HrefProperty(CHECKED_OUT, baseVHref, true)); + } else { + // DAV:checked-in property (protected) + properties.add(new HrefProperty(CHECKED_IN, baseVHref, true)); + } + } catch (RepositoryException e) { + log.error(e.getMessage()); + } + } + } + } + + /** + * @return true, if this resource is a non-collection resource and represents + * an existing repository node that has the mixin nodetype 'mix:versionable' set. + */ + private boolean isVersionControlled() { + boolean vc = false; + // since the version-controlled-collection feature is not supported + // all collection are excluded from version-control even if the + // underlying node was JCR versionable. + if (exists() && !isCollection()) { + Node item = getNode(); + try { + vc = item.isNodeType(JcrConstants.MIX_VERSIONABLE); + } catch (RepositoryException e) { + log.warn(e.getMessage()); + } + } + return vc; + } +} Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/simple/VersionControlledResourceImpl.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/webdav/simple/VersionHistoryResourceImpl.java =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/simple/VersionHistoryResourceImpl.java (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/simple/VersionHistoryResourceImpl.java (working copy) @@ -0,0 +1,235 @@ +/* + * 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.webdav.simple; + +import org.apache.jackrabbit.util.Text; +import org.apache.jackrabbit.webdav.DavException; +import org.apache.jackrabbit.webdav.DavResource; +import org.apache.jackrabbit.webdav.DavResourceFactory; +import org.apache.jackrabbit.webdav.DavResourceLocator; +import org.apache.jackrabbit.webdav.DavServletResponse; +import org.apache.jackrabbit.webdav.DavSession; +import org.apache.jackrabbit.webdav.DavResourceIterator; +import org.apache.jackrabbit.webdav.DavResourceIteratorImpl; +import org.apache.jackrabbit.webdav.MultiStatusResponse; +import org.apache.jackrabbit.webdav.io.InputContext; +import org.apache.jackrabbit.webdav.jcr.JcrDavException; +import org.apache.jackrabbit.webdav.property.HrefProperty; +import org.apache.jackrabbit.webdav.property.ResourceType; +import org.apache.jackrabbit.webdav.property.DavProperty; +import org.apache.jackrabbit.webdav.property.DavPropertyName; +import org.apache.jackrabbit.webdav.property.PropEntry; +import org.apache.jackrabbit.webdav.version.VersionHistoryResource; +import org.apache.jackrabbit.webdav.version.VersionResource; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.jcr.Item; +import javax.jcr.RepositoryException; +import javax.jcr.version.VersionHistory; +import javax.jcr.version.VersionIterator; +import javax.jcr.version.Version; + +import java.util.ArrayList; +import java.util.List; + +/** + * VersionHistoryResourceImpl represents a JCR version history. + * + * @see VersionHistory + */ +public class VersionHistoryResourceImpl extends DeltaVResourceImpl implements VersionHistoryResource { + + private static final Logger log = LoggerFactory.getLogger(VersionHistoryResourceImpl.class); + + public VersionHistoryResourceImpl(DavResourceLocator locator, DavResourceFactory factory, DavSession session, ResourceConfig config, Item item) throws DavException { + super(locator, factory, session, config, item); + if (getNode() == null || !(getNode() instanceof VersionHistory)) { + throw new IllegalArgumentException("VersionHistory item expected."); + } + } + + //--------------------------------------------------------< DavResource >--- + /** + * Show all versions of this history as members. + * + * @return + * @see DavResource#getMembers() + */ + @Override + public DavResourceIterator getMembers() { + ArrayList list = new ArrayList(); + if (exists() && isCollection()) { + try { + // only display versions as members of the vh. the jcr:versionLabels + // node is an internal structure. + VersionIterator it = ((VersionHistory) getNode()).getAllVersions(); + while (it.hasNext()) { + // omit item filter here. if the version history is visible + // its versions should be visible as well. + Version v = it.nextVersion(); + DavResourceLocator vhLocator = getLocator(); + DavResourceLocator resourceLocator = vhLocator.getFactory().createResourceLocator(vhLocator.getPrefix(), vhLocator.getWorkspacePath(), v.getPath(), false); + DavResource childRes = getFactory().createResource(resourceLocator, getSession()); + list.add(childRes); + } + } catch (RepositoryException e) { + // should not occur + log.error("Unexpected error",e); + } catch (DavException e) { + // should not occur + log.error("Unexpected error",e); + } + } + return new DavResourceIteratorImpl(list); + } + + /** + * The version storage is read-only -> fails with 403. + * + * @see DavResource#addMember(DavResource, InputContext) + */ + @Override + public void addMember(DavResource member, InputContext inputContext) throws DavException { + throw new DavException(DavServletResponse.SC_FORBIDDEN); + } + + /** + * Removing a version resource is achieved by calling removeVersion + * on the versionhistory item this version belongs to. + * + * @throws DavException if the version does not exist or if an error occurs + * while deleting. + * @see DavResource#removeMember(org.apache.jackrabbit.webdav.DavResource) + */ + @Override + public void removeMember(DavResource member) throws DavException { + if (exists()) { + VersionHistory versionHistory = (VersionHistory) getNode(); + try { + String itemPath = member.getLocator().getRepositoryPath(); + // Retrieve the last segment of the given path and removes the index if present. + if (itemPath == null) { + throw new IllegalArgumentException("Cannot retrieve name from a 'null' item path."); + } + String name = Text.getName(itemPath); + // remove index + if (name.endsWith("]")) { + name = name.substring(0, name.lastIndexOf('[')); + } + versionHistory.removeVersion(name); + } catch (RepositoryException e) { + throw new JcrDavException(e); + } + } else { + throw new DavException(DavServletResponse.SC_NOT_FOUND); + } + } + + /** + * Version storage is read-only -> fails with 403. + * + * @see DavResource#setProperty(DavProperty) + */ + @Override + public void setProperty(DavProperty property) throws DavException { + throw new DavException(DavServletResponse.SC_FORBIDDEN); + } + + /** + * Version storage is read-only -> fails with 403. + * + * @see DavResource#removeProperty(DavPropertyName) + */ + @Override + public void removeProperty(DavPropertyName propertyName) throws DavException { + throw new DavException(DavServletResponse.SC_FORBIDDEN); + } + + /** + * Version storage is read-only -> fails with 403. + * + * @see DavResource#alterProperties(List) + */ + @Override + public MultiStatusResponse alterProperties(List changeList) throws DavException { + throw new DavException(DavServletResponse.SC_FORBIDDEN); + } + + //---------------------------------------------< VersionHistoryResource >--- + /** + * Return an array of {@link org.apache.jackrabbit.webdav.version.VersionResource}s representing all versions + * present in the underlying JCR version history. + * + * @return array of {@link org.apache.jackrabbit.webdav.version.VersionResource}s representing all versions + * present in the underlying JCR version history. + * @throws org.apache.jackrabbit.webdav.DavException + * @see org.apache.jackrabbit.webdav.version.VersionHistoryResource#getVersions() + */ + public VersionResource[] getVersions() throws DavException { + try { + VersionIterator vIter = ((VersionHistory)getNode()).getAllVersions(); + ArrayList l = new ArrayList(); + while (vIter.hasNext()) { + DavResourceLocator versionLoc = getLocatorFromNode(vIter.nextVersion()); + DavResource vr = createResourceFromLocator(versionLoc); + if (vr instanceof VersionResource) { + l.add((VersionResource) vr); + } else { + // severe error since resource factory doesn't behave correctly. + throw new DavException(DavServletResponse.SC_INTERNAL_SERVER_ERROR); + } + } + return l.toArray(new VersionResource[l.size()]); + } catch (RepositoryException e) { + throw new JcrDavException(e); + } + } + + //-------------------------------------------------------------------------- + /** + * Fill the property set for this resource. + */ + @Override + protected void initProperties() { + if (!propsInitialized) { + super.initProperties(); + + // change resource type defined by default item collection + properties.add(new ResourceType(new int[] {ResourceType.COLLECTION, ResourceType.VERSION_HISTORY})); + + // required root-version property for version-history resource + try { + String rootVersionHref = getLocatorFromNode(((VersionHistory)getNode()).getRootVersion()).getHref(false); + properties.add(new HrefProperty(VersionHistoryResource.ROOT_VERSION, rootVersionHref, false)); + } catch (RepositoryException e) { + log.error(e.getMessage()); + } + + // required, protected version-set property for version-history resource + try { + VersionIterator vIter = ((VersionHistory)getNode()).getAllVersions(); + ArrayList l = new ArrayList(); + while (vIter.hasNext()) { + l.add(vIter.nextVersion()); + } + properties.add(getHrefProperty(VersionHistoryResource.VERSION_SET, l.toArray(new Version[l.size()]), true, false)); + } catch (RepositoryException e) { + log.error(e.getMessage()); + } + } + } +} Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/simple/VersionHistoryResourceImpl.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/webdav/simple/VersionResourceImpl.java =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/simple/VersionResourceImpl.java (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/simple/VersionResourceImpl.java (working copy) @@ -0,0 +1,287 @@ +/* + * 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.webdav.simple; + +import org.apache.jackrabbit.JcrConstants; +import org.apache.jackrabbit.webdav.DavException; +import org.apache.jackrabbit.webdav.DavResource; +import org.apache.jackrabbit.webdav.DavResourceFactory; +import org.apache.jackrabbit.webdav.DavResourceLocator; +import org.apache.jackrabbit.webdav.DavServletResponse; +import org.apache.jackrabbit.webdav.DavSession; +import org.apache.jackrabbit.webdav.DavResourceIterator; +import org.apache.jackrabbit.webdav.DavResourceIteratorImpl; +import org.apache.jackrabbit.webdav.MultiStatusResponse; +import org.apache.jackrabbit.webdav.util.HttpDateFormat; +import org.apache.jackrabbit.webdav.io.InputContext; +import org.apache.jackrabbit.webdav.jcr.JcrDavException; +import org.apache.jackrabbit.webdav.property.DavPropertyName; +import org.apache.jackrabbit.webdav.property.DefaultDavProperty; +import org.apache.jackrabbit.webdav.property.HrefProperty; +import org.apache.jackrabbit.webdav.property.DavProperty; +import org.apache.jackrabbit.webdav.property.PropEntry; +import org.apache.jackrabbit.webdav.version.LabelInfo; +import org.apache.jackrabbit.webdav.version.LabelSetProperty; +import org.apache.jackrabbit.webdav.version.VersionHistoryResource; +import org.apache.jackrabbit.webdav.version.VersionResource; +import org.apache.jackrabbit.webdav.version.report.ReportType; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.jcr.Item; +import javax.jcr.Node; +import javax.jcr.Property; +import javax.jcr.PropertyIterator; +import javax.jcr.RepositoryException; +import javax.jcr.version.Version; +import javax.jcr.version.VersionHistory; + +import java.util.ArrayList; +import java.util.List; + +/** + * VersionResourceImpl represents a JCR version. + * + * @see Version + */ +public class VersionResourceImpl extends DeltaVResourceImpl implements VersionResource { + + private static final Logger log = LoggerFactory.getLogger(VersionResourceImpl.class); + + /** + * Create a new {@link org.apache.jackrabbit.webdav.DavResource}. + * @param locator + * @param factory + * @param session + * @param config + * @param item + * @throws DavException + * + */ + public VersionResourceImpl(DavResourceLocator locator, DavResourceFactory factory, DavSession session, ResourceConfig config, Item item) throws DavException { + super(locator, factory, session, config, item); + if (getNode() == null || !(getNode() instanceof Version)) { + throw new IllegalArgumentException("Version item expected."); + } + } + + //--------------------------------------------------------< DavResource >--- + /** + * Since this implementation of VersionResource never is a + * version belonging to a version controlled collection, this method always + * returns false not respecting the configuration. + * + * @return always false + */ + @Override + public boolean isCollection() { + return false; + } + + /** + * @return An empty DavResourceIterator + */ + @Override + public DavResourceIterator getMembers() { + return DavResourceIteratorImpl.EMPTY; + } + + /** + * The version storage is read-only -> fails with 403. + * + * @see DavResource#addMember(DavResource, InputContext) + */ + @Override + public void addMember(DavResource member, InputContext inputContext) throws DavException { + throw new DavException(DavServletResponse.SC_FORBIDDEN); + } + + /** + * The version storage is read-only -> fails with 403. + * + * @see DavResource#removeMember(DavResource) + */ + @Override + public void removeMember(DavResource member) throws DavException { + throw new DavException(DavServletResponse.SC_FORBIDDEN); + } + + /** + * Version storage is read-only -> fails with 403. + * + * @see DavResource#setProperty(DavProperty) + */ + @Override + public void setProperty(DavProperty property) throws DavException { + throw new DavException(DavServletResponse.SC_FORBIDDEN); + } + + /** + * Version storage is read-only -> fails with 403. + * + * @see DavResource#removeProperty(DavPropertyName) + */ + @Override + public void removeProperty(DavPropertyName propertyName) throws DavException { + throw new DavException(DavServletResponse.SC_FORBIDDEN); + } + + /** + * Version storage is read-only -> fails with 403. + * + * @see DavResource#alterProperties(List) + */ + @Override + public MultiStatusResponse alterProperties(List changeList) throws DavException { + throw new DavException(DavServletResponse.SC_FORBIDDEN); + } + + //----------------------------------------------------< VersionResource >--- + /** + * Modify the labels defined for the underlying repository version. + * + * @param labelInfo + * @throws org.apache.jackrabbit.webdav.DavException + * @see VersionResource#label(org.apache.jackrabbit.webdav.version.LabelInfo) + * @see javax.jcr.version.VersionHistory#addVersionLabel(String, String, boolean) + * @see javax.jcr.version.VersionHistory#removeVersionLabel(String) + */ + public void label(LabelInfo labelInfo) throws DavException { + if (labelInfo == null) { + throw new DavException(DavServletResponse.SC_BAD_REQUEST, "Valid label request body required."); + } + if (!exists()) { + throw new DavException(DavServletResponse.SC_NOT_FOUND); + } + try { + VersionHistory vh = getVersionHistoryItem(); + if (labelInfo.getType() == LabelInfo.TYPE_REMOVE) { + vh.removeVersionLabel(labelInfo.getLabelName()); + } else if (labelInfo.getType() == LabelInfo.TYPE_ADD) { + // ADD: only add if not yet existing + vh.addVersionLabel(getNode().getName(), labelInfo.getLabelName(), false); + } else { + // SET: move label if already existing + vh.addVersionLabel(getNode().getName(), labelInfo.getLabelName(), true); + } + } catch (RepositoryException e) { + throw new JcrDavException(e); + } + } + + /** + * Returns the {@link VersionHistory} associated with the repository version. + * Note: in contrast to a versionable node, the version history of a version + * item is always represented by its nearest ancestor. + * + * @return the {@link org.apache.jackrabbit.webdav.version.VersionHistoryResource} associated with this resource. + * @throws org.apache.jackrabbit.webdav.DavException + * @see org.apache.jackrabbit.webdav.version.VersionResource#getVersionHistory() + * @see javax.jcr.Item#getParent() + */ + public VersionHistoryResource getVersionHistory() throws DavException { + if (!exists()) { + throw new DavException(DavServletResponse.SC_NOT_FOUND); + } + + try { + VersionHistory vh = getVersionHistoryItem(); + DavResourceLocator loc = getLocatorFromNode(vh); + DavResource vhr = createResourceFromLocator(loc); + if (vhr instanceof VersionHistoryResource) { + return (VersionHistoryResource)vhr; + } else { + // severe error since resource factory doesn't behave correctly. + throw new DavException(DavServletResponse.SC_INTERNAL_SERVER_ERROR); + } + } catch (RepositoryException e) { + throw new JcrDavException(e); + } + } + + /** + * Return versionhistory that contains this version item + * + * @return versionhistory that contains this version item + * @throws RepositoryException + * @see javax.jcr.version.Version#getContainingHistory() + */ + private VersionHistory getVersionHistoryItem() throws RepositoryException { + return ((Version)getNode()).getContainingHistory(); + } + + //-------------------------------------------------------------------------- + /** + * Define the set of reports supported by this resource. + * + * @see org.apache.jackrabbit.webdav.version.report.SupportedReportSetProperty + */ + @Override + protected void initSupportedReports() { + super.initSupportedReports(); + if (exists()) { + supportedReports.addReportType(ReportType.VERSION_TREE); + } + } + + /** + * Fill the property set for this resource. + */ + @Override + protected void initProperties() { + if (!propsInitialized) { + super.initProperties(); + Version v = (Version) getNode(); + try { + String creationDate = HttpDateFormat.creationDateFormat().format(v.getCreated().getTime()); + // replace dummy creation date from default collection + properties.add(new DefaultDavProperty(DavPropertyName.CREATIONDATE, creationDate)); + + // required, protected DAV:version-name property + properties.add(new DefaultDavProperty(VERSION_NAME, v.getName(), true)); + + // required, protected DAV:label-name-set property + String[] labels = getVersionHistoryItem().getVersionLabels(v); + properties.add(new LabelSetProperty(labels)); + + // required DAV:predecessor-set (protected) and DAV:successor-set (computed) properties + properties.add(getHrefProperty(VersionResource.PREDECESSOR_SET, v.getPredecessors(), true, false)); + properties.add(getHrefProperty(SUCCESSOR_SET, v.getSuccessors(), true, false)); + + // required DAV:version-history (computed) property + String vhHref = getLocatorFromNode(getVersionHistoryItem()).getHref(true); + properties.add(new HrefProperty(VersionResource.VERSION_HISTORY, vhHref, true)); + + // required DAV:checkout-set (computed) property + PropertyIterator it = v.getReferences(); + List nodeList = new ArrayList(); + while (it.hasNext()) { + Property p = it.nextProperty(); + if (JcrConstants.JCR_BASEVERSION.equals(p.getName())) { + Node n = p.getParent(); + if (n.isCheckedOut()) { + nodeList.add(n); + } + } + } + properties.add(getHrefProperty(CHECKOUT_SET, nodeList.toArray(new Node[nodeList.size()]), true, false)); + + } catch (RepositoryException e) { + log.error(e.getMessage()); + } + } + } +} Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/simple/VersionResourceImpl.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/javadoc/org/apache/jackrabbit/server/io/package.html =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/javadoc/org/apache/jackrabbit/server/io/package.html (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/javadoc/org/apache/jackrabbit/server/io/package.html (working copy) @@ -0,0 +1,21 @@ + + +The jackrabbit webdav server uses the classes defined in this package in order +to perform import and export operations in order to respond to PUT, MKCOL, PROPPATCH +and PROPFIND, GET, HEAD requests, respectively. + Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/javadoc/org/apache/jackrabbit/server/io/package.html ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/javadoc/org/apache/jackrabbit/webdav/jcr/package.html =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/javadoc/org/apache/jackrabbit/webdav/jcr/package.html (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/javadoc/org/apache/jackrabbit/webdav/jcr/package.html (working copy) @@ -0,0 +1,19 @@ + + +Contains JCR specific implementations. + Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/javadoc/org/apache/jackrabbit/webdav/jcr/package.html ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/javadoc/org/apache/jackrabbit/webdav/jcr/version/package.html =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/javadoc/org/apache/jackrabbit/webdav/jcr/version/package.html (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/javadoc/org/apache/jackrabbit/webdav/jcr/version/package.html (working copy) @@ -0,0 +1,25 @@ + + +Contains JCR specific implementations for the following interfaces: +

    +
  • VersionableResource
  • +
  • VersionControlledResource
  • +
  • VersionResource
  • +
  • VersionHistoryResource
  • +
+ Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/javadoc/org/apache/jackrabbit/webdav/jcr/version/package.html ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/javadoc/org/apache/jackrabbit/webdav/jcr/version/report/package.html =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/javadoc/org/apache/jackrabbit/webdav/jcr/version/report/package.html (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/javadoc/org/apache/jackrabbit/webdav/jcr/version/report/package.html (working copy) @@ -0,0 +1,19 @@ + + +Contains JCR specific reports. + Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/javadoc/org/apache/jackrabbit/webdav/jcr/version/report/package.html ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/resources/OSGI-INF/l10n/metatype.properties =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/resources/OSGI-INF/l10n/metatype.properties (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/main/resources/OSGI-INF/l10n/metatype.properties (working copy) @@ -0,0 +1,58 @@ +# +# 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. +# + + +# +# This file contains localization strings for configuration labels and +# descriptions as used in the metatype.xml descriptor generated by the +# the SCR plugin + +dav.name = Apache Jackrabbit DavEx Servlet +dav.description = The DavEx Servlet allows direct access to the \ + complete Repository. + +alias.name = Root Path +alias.description = The root path at which the DavEx Servlet is \ + accessible. The default value is "/server". + +missing-auth-mapping.name = Missing Credentials Handling +missing-auth-mapping.description = Defines how a missing authorization \ + header should be handled. If this property is missing, a 401 response \ + is generated. This is suiteable for clients (eg. webdav clients) for \ + which sending a proper authorization header is not possible if the \ + server never sent a 401. If this property is present with an empty \ + value, null-credentials are returned, thus forcing an null login \ + on the repository. If this propert is present with the value \ + 'guestcredentials' java.jcr.GuestCredentials are used to login to the \ + repository. If this property has a 'user:password' value, the \ + respective simple credentials are generated. + +authenticate-header.name = Realm> +authenticate-header.description = Defines the value of the \ + 'WWW-Authenticate' header. Default is 'Basic realm="Jackrabbit Webdav Server"'. + +csrf-protection.name = CSRF Protection +csrf-protection.description = Configuration of referrer based CSRF \ + protection. If config is not configured or empty string the default \ + behaviour is to allow only requests with an empty referrer header or a \ + referrer host equal to the server host. A comma separated list of \ + additional allowed referrer hosts which are valid in addition to default \ + behaviour (see above). The value "disabled" may be used to disable the \ + referrer checking altogether. The default is "disabled" assuming that \ + a site-wide CSRF protection filter is installed. Index: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/server/BasicCredentialsProviderTest.java =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/server/BasicCredentialsProviderTest.java (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/server/BasicCredentialsProviderTest.java (working copy) @@ -0,0 +1,385 @@ +/* + * 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 junit.framework.TestCase; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.servlet.http.Cookie; +import javax.servlet.http.HttpSession; +import javax.servlet.http.HttpUpgradeHandler; +import javax.servlet.http.Part; +import javax.servlet.ServletInputStream; +import javax.servlet.ServletRequest; +import javax.servlet.ServletResponse; +import javax.servlet.AsyncContext; +import javax.servlet.DispatcherType; +import javax.servlet.RequestDispatcher; +import javax.servlet.ServletContext; +import javax.servlet.ServletException; +import javax.jcr.LoginException; +import javax.jcr.Credentials; +import javax.jcr.SimpleCredentials; +import javax.jcr.GuestCredentials; + +import java.util.Collection; +import java.util.Enumeration; +import java.util.Map; +import java.util.Locale; +import java.util.HashMap; +import java.security.Principal; +import java.io.UnsupportedEncodingException; +import java.io.IOException; +import java.io.BufferedReader; + +/** + * BasicCredentialsProviderTest... + */ +public class BasicCredentialsProviderTest extends TestCase { + + public void testMissingDefaultHeader() throws ServletException { + CredentialsProvider cb = new BasicCredentialsProvider(null); + try { + Credentials creds = cb.getCredentials(new RequestImpl(null)); + fail("LoginException expected"); + } catch (LoginException e) { + // ok + } + } + + public void testGuestCredentialsDefaultHeader() throws ServletException, LoginException { + CredentialsProvider cb = new BasicCredentialsProvider(BasicCredentialsProvider.GUEST_DEFAULT_HEADER_VALUE); + Credentials creds = cb.getCredentials(new RequestImpl(null)); + + assertTrue(creds instanceof GuestCredentials); + } + + public void testEmptyDefaultHeader() throws ServletException, LoginException { + CredentialsProvider cb = new BasicCredentialsProvider(BasicCredentialsProvider.EMPTY_DEFAULT_HEADER_VALUE); + Credentials creds = cb.getCredentials(new RequestImpl(null)); + + assertNull(creds); + } + + public void testDefaultPassword() throws ServletException, LoginException { + Map m = new HashMap(); + m.put("userId", new char[0]); + m.put("userId:", new char[0]); + m.put("userId:pw", "pw".toCharArray()); + + for (String uid : m.keySet()) { + char[] pw = m.get(uid); + + CredentialsProvider cb = new BasicCredentialsProvider(uid); + Credentials creds = cb.getCredentials(new RequestImpl(null)); + + assertNotNull(creds); + assertTrue(creds instanceof SimpleCredentials); + assertEquals("userId", ((SimpleCredentials) creds).getUserID()); + if (pw.length == 0) { + assertEquals(0, ((SimpleCredentials) creds).getPassword().length); + } else { + assertEquals(new String(pw), new String(((SimpleCredentials) creds).getPassword())); + } + } + } + + + + + private class RequestImpl implements HttpServletRequest { + + private final String authHeader; + + private RequestImpl(String authHeader) { + this.authHeader = authHeader; + } + + public String getAuthType() { + return null; + } + + public Cookie[] getCookies() { + return new Cookie[0]; + } + + public long getDateHeader(String name) { + return 0; + } + + public String getHeader(String name) { + return authHeader; + } + + public Enumeration getHeaders(String name) { + return null; + } + + public Enumeration getHeaderNames() { + return null; + } + + public int getIntHeader(String name) { + return 0; + } + + public String getMethod() { + return null; + } + + public String getPathInfo() { + return null; + } + + public String getPathTranslated() { + return null; + } + + public String getContextPath() { + return null; + } + + public String getQueryString() { + return null; + } + + public String getRemoteUser() { + return null; + } + + public boolean isUserInRole(String role) { + return false; + } + + public Principal getUserPrincipal() { + return null; + } + + public String getRequestedSessionId() { + return null; + } + + public String getRequestURI() { + return null; + } + + public StringBuffer getRequestURL() { + return null; + } + + public String getServletPath() { + return null; + } + + public HttpSession getSession(boolean create) { + return null; + } + + public HttpSession getSession() { + return null; + } + + public boolean isRequestedSessionIdValid() { + return false; + } + + public boolean isRequestedSessionIdFromCookie() { + return false; + } + + public boolean isRequestedSessionIdFromURL() { + return false; + } + + public boolean isRequestedSessionIdFromUrl() { + return false; + } + + public Object getAttribute(String name) { + return null; + } + + public Enumeration getAttributeNames() { + return null; + } + + public String getCharacterEncoding() { + return null; + } + + public void setCharacterEncoding(String s) throws UnsupportedEncodingException { + } + + public int getContentLength() { + return 0; + } + + public String getContentType() { + return null; + } + + public ServletInputStream getInputStream() throws IOException { + return null; + } + + public String getParameter(String name) { + return null; + } + + public Enumeration getParameterNames() { + return null; + } + + public String[] getParameterValues(String name) { + return new String[0]; + } + + public Map getParameterMap() { + return null; + } + + public String getProtocol() { + return null; + } + + public String getScheme() { + return null; + } + + public String getServerName() { + return null; + } + + public int getServerPort() { + return 0; + } + + public BufferedReader getReader() throws IOException { + return null; + } + + public String getRemoteAddr() { + return null; + } + + public String getRemoteHost() { + return null; + } + + public void setAttribute(String name, Object o) { + } + + public void removeAttribute(String name) { + } + + public Locale getLocale() { + return null; + } + + public Enumeration getLocales() { + return null; + } + + public boolean isSecure() { + return false; + } + + public RequestDispatcher getRequestDispatcher(String path) { + return null; + } + + public String getRealPath(String path) { + return null; + } + + public int getRemotePort() { + return 0; + } + + public String getLocalName() { + return null; + } + + public String getLocalAddr() { + return null; + } + + public int getLocalPort() { + return 0; + } + + public long getContentLengthLong() { + return 0; + } + + public ServletContext getServletContext() { + return null; + } + + public AsyncContext startAsync() throws IllegalStateException { + return null; + } + + public AsyncContext startAsync(ServletRequest servletRequest, ServletResponse servletResponse) + throws IllegalStateException { + return null; + } + + public boolean isAsyncStarted() { + return false; + } + + public boolean isAsyncSupported() { + return false; + } + + public AsyncContext getAsyncContext() { + return null; + } + + public DispatcherType getDispatcherType() { + return null; + } + + public String changeSessionId() { + return null; + } + + public boolean authenticate(HttpServletResponse response) throws IOException, ServletException { + return false; + } + + public void login(String username, String password) throws ServletException { + } + + public void logout() throws ServletException { + } + + public Collection getParts() throws IOException, ServletException { + return null; + } + + public Part getPart(String name) throws IOException, ServletException { + return null; + } + + public T upgrade(Class handlerClass) throws IOException, ServletException { + return null; + } + } +} Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/server/BasicCredentialsProviderTest.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/test/java/org/apache/jackrabbit/server/TestAll.java =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/server/TestAll.java (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/server/TestAll.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 junit.framework.Test; +import junit.framework.TestCase; +import junit.framework.TestSuite; + +/** + * Test suite that includes all testcases for package org.apache.jackrabbit.server. + */ +public class TestAll extends TestCase { + + /** + * Returns a Test suite that executes all tests inside this + * package. + */ + public static Test suite() { + TestSuite suite = new TestSuite("org.apache.jackrabbit.server tests"); + + suite.addTestSuite(BasicCredentialsProviderTest.class); + + return suite; + } +} Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/server/TestAll.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/test/java/org/apache/jackrabbit/server/remoting/davex/BatchReadConfigTest.java =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/server/remoting/davex/BatchReadConfigTest.java (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/server/remoting/davex/BatchReadConfigTest.java (working copy) @@ -0,0 +1,86 @@ +/* + * 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.remoting.davex; + +import junit.framework.TestCase; + +import java.util.Properties; + +/** + * BatchReadConfigTest... + */ +public class BatchReadConfigTest extends TestCase { + + public void testDefaultDepth() { + BatchReadConfig cnf = new BatchReadConfig(); + + assertEquals(BatchReadConfig.DEPTH_DEFAULT, cnf.getDefaultDepth()); + assertEquals(cnf.getDefaultDepth(), cnf.getDepth("nt:base")); + + cnf.setDefaultDepth(5); + assertEquals(5, cnf.getDefaultDepth()); + assertEquals(cnf.getDefaultDepth(), cnf.getDepth("nt:base")); + + cnf.setDefaultDepth(BatchReadConfig.DEPTH_INFINITE); + assertEquals(BatchReadConfig.DEPTH_INFINITE, cnf.getDefaultDepth()); + assertEquals(cnf.getDefaultDepth(), cnf.getDepth("nt:base")); + + try { + cnf.setDefaultDepth(-12); + fail("Invalid depth"); + } catch (IllegalArgumentException e) { + //ok + } + } + + public void testDepth() { + BatchReadConfig cnf = new BatchReadConfig(); + + cnf.setDepth("nt:file", 15); + assertEquals(15, cnf.getDepth("nt:file")); + assertEquals(cnf.getDefaultDepth(), cnf.getDepth("nt:base")); + + cnf.setDepth("nt:file", BatchReadConfig.DEPTH_INFINITE); + assertEquals(BatchReadConfig.DEPTH_INFINITE, cnf.getDepth("nt:file")); + assertEquals(cnf.getDefaultDepth(), cnf.getDepth("nt:base")); + + try { + cnf.setDepth("nt:file",-12); + fail("Invalid depth"); + } catch (IllegalArgumentException e) { + //ok + } + } + + public void testAdd() { + Properties props = new Properties(); + props.setProperty("nt:file", "15"); + props.setProperty("default", "-1"); + + BatchReadConfig cnf = new BatchReadConfig(); + cnf.add(props); + + assertEquals(15, cnf.getDepth("nt:file")); + assertEquals(BatchReadConfig.DEPTH_INFINITE, cnf.getDefaultDepth()); + assertEquals(cnf.getDefaultDepth(), cnf.getDepth("nt:base")); + + cnf.setDefaultDepth(BatchReadConfig.DEPTH_DEFAULT); + assertEquals(15, cnf.getDepth("nt:file")); + assertEquals(BatchReadConfig.DEPTH_DEFAULT, cnf.getDefaultDepth()); + assertEquals(cnf.getDefaultDepth(), cnf.getDepth("nt:base")); + } +} \ No newline at end of file Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/server/remoting/davex/BatchReadConfigTest.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/test/java/org/apache/jackrabbit/server/remoting/davex/DiffParserTest.java =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/server/remoting/davex/DiffParserTest.java (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/server/remoting/davex/DiffParserTest.java (working copy) @@ -0,0 +1,385 @@ +/* + * 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.remoting.davex; + +import junit.framework.TestCase; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +/** DiffParserTest... */ +public class DiffParserTest extends TestCase { + + public void testSetProperty() throws IOException, DiffException { + ArrayList l = new ArrayList(); + l.add("\"simple string\""); + l.add("2345"); + l.add("true"); + l.add("false"); + l.add("234.3455"); + l.add("null"); + + for (final String value : l) { + String diff = "^/a/prop : " + value; + + DummyDiffHandler handler = new DummyDiffHandler() { + @Override + public void setProperty(String targetPath, String diffValue) { + assertEquals(targetPath, "/a/prop"); + assertEquals(value, diffValue); + } + }; + DiffParser parser = new DiffParser(handler); + parser.parse(diff); + } + } + + public void testSetPropertyMissing() throws IOException, + DiffException { + ArrayList l = new ArrayList(); + l.add(""); + l.add(null); + + for (String value : l) { + String diff = "^/a/prop : " + ((value == null) ? "" : value); + + DummyDiffHandler handler = new DummyDiffHandler() { + @Override + public void setProperty(String targetPath, String diffValue) { + assertEquals(targetPath, "/a/prop"); + assertTrue(diffValue == null || "".equals(diffValue)); + } + }; + DiffParser parser = new DiffParser(handler); + parser.parse(diff); + } + } + + public void testSetPropertyWithUnicodeChars() throws IOException, + DiffException { + final String value = "\"String value containing \u2355\u8723 unicode chars.\""; + String diff = "^/a/prop : " + value; + + DiffHandler handler = new DummyDiffHandler() { + @Override + public void setProperty(String targetPath, String diffValue) { + assertEquals(targetPath, "/a/prop"); + assertEquals(value, diffValue); + } + }; + + DiffParser parser = new DiffParser(handler); + parser.parse(diff); + } + + public void testSetPropertyWithTrailingLineSep() throws IOException, + DiffException { + final String value = "\"String value ending with \r\r\n\n\r\n.\""; + String diff = "^/a/prop : " + value; + + DiffHandler handler = new DummyDiffHandler() { + @Override + public void setProperty(String targetPath, String diffValue) { + assertEquals(targetPath, "/a/prop"); + assertEquals(value, diffValue); + } + }; + + DiffParser parser = new DiffParser(handler); + parser.parse(diff); + } + + public void testSetPropertyWithSpecialChar() throws IOException, DiffException { + final String value = "+abc \\r+ \\n-ab >c \r\\r\\n+"; + String diff = "^/a/prop : " + value; + + DiffHandler handler = new DummyDiffHandler() { + @Override + public void setProperty(String targetPath, String diffValue) { + assertEquals(targetPath, "/a/prop"); + assertEquals(value, diffValue); + } + }; + + DiffParser parser = new DiffParser(handler); + parser.parse(diff); + } + + public void testSetPropertyUnterminatedString() throws IOException, + DiffException { + final String value = "\"String value ending with \r\r\n\n\r\n."; + String diff = "^/a/prop : " + value; + + DiffHandler handler = new DummyDiffHandler() { + @Override + public void setProperty(String targetPath, String diffValue) { + assertEquals(targetPath, "/a/prop"); + assertEquals(value, diffValue); + } + }; + DiffParser parser = new DiffParser(handler); + parser.parse(diff); + } + + public void testSetPropertyWithUnescapedAction() throws IOException, + DiffException { + String diff = "^abc : \r+def : \n-ghi : \r\n^jkl : \n\r>mno : \n"; + + DiffHandler handler = new DummyDiffHandler() { + @Override + public void addNode(String targetPath, String diffValue) { + assertEquals("def", targetPath); + assertEquals("", diffValue); + } + @Override + public void setProperty(String targetPath, String diffValue) { + assertTrue("abc".equals(targetPath) || "jkl".equals(targetPath)); + assertEquals("", diffValue); + } + @Override + public void remove(String targetPath, String diffValue) { + assertEquals("ghi", targetPath); + assertEquals("", diffValue); + } + + @Override + public void move(String targetPath, String diffValue) { + assertEquals("mno", targetPath); + assertEquals("\n", diffValue); + } + }; + + DiffParser parser = new DiffParser(handler); + parser.parse(diff); + } + + public void testValidDiffs() throws IOException, DiffException { + List l = new ArrayList(); + // unquoted string value + l.add(new String[] {"+/a/b : 134", "/a/b","134"}); + l.add(new String[] {"+/a/b : 2.3", "/a/b","2.3"}); + l.add(new String[] {"+/a/b : true", "/a/b","true"}); + // quoted string value + l.add(new String[] {"+/a/b : \"true\"", "/a/b","\"true\""}); + l.add(new String[] {"+/a/b : \"string value containing \u3456 unicode char.\"", "/a/b","\"string value containing \u3456unicode char.\""}); + // value consisting of quotes + l.add(new String[] {"+/a/b : \"", "/a/b","\""}); + l.add(new String[] {"+/a/b : \"\"", "/a/b","\"\""}); + // value consisting of single + l.add(new String[] {"+/a/b : '", "/a/b","'"}); + l.add(new String[] {"+/a/b : ''''", "/a/b","''''"}); + // value consisting of space(s) only + l.add(new String[] {"+/a/b : ", "/a/b"," "}); + l.add(new String[] {"+/a/b : ", "/a/b"," "}); + // value consisting of line separators only + l.add(new String[] {"+/a/b : \n", "/a/b","\n"}); + l.add(new String[] {"+/a/b : \r", "/a/b","\r"}); + l.add(new String[] {"+/a/b : \r\n", "/a/b","\r\n"}); + l.add(new String[] {"+/a/b : \r\n\n\r", "/a/b","\r\n\n\r"}); + // path containing white space + l.add(new String[] {"+/a /b : 123", "/a /b","123"}); + l.add(new String[] {"+/a\r\t/b : 123", "/a\r\t/b","123"}); + // path having trailing white space + l.add(new String[] {"+/a/b : 123", "/a/b","123"}); + l.add(new String[] {"+/a/b\r : 123", "/a/b\r","123"}); + l.add(new String[] {"+/a/b\r\n\n\r\n: 123", "/a/b\r\n\n\r\n","123"}); + // path containing reserved characters + l.add(new String[] {"++abc+ : val", "+abc+","val"}); + l.add(new String[] {"++++++ : val", "+++++","val"}); + // value containing reserved characters + l.add(new String[] {"+/a/b : +", "/a/b","+"}); + l.add(new String[] {"+/a/b : +->+-", "/a/b","+->+-"}); + l.add(new String[] {"+/a/b : \"+->+-\"", "/a/b","\"+->+-\""}); + // other white space than ' ' used as key-value separator + l.add(new String[] {"+/a/b :\r123", "/a/b","123"}); + l.add(new String[] {"+/a/b\r: 123", "/a/b","123"}); + l.add(new String[] {"+/a/b\r:\r123", "/a/b","123"}); + l.add(new String[] {"+/a/b\r:\n123", "/a/b","123"}); + l.add(new String[] {"+/a/b\t:\r123", "/a/b","123"}); + l.add(new String[] {"+/a/b\t:\t123", "/a/b","123"}); + // path containing colon + l.add(new String[] {"+/a:b/c:d : 123", "/a:b/c:d","123"}); + // value starting with colon -> ok + l.add(new String[] {"+/a/b : : val", "/a/b",": val"}); + // missing value + l.add(new String[] {"+/a/b : ", "/a/b", ""}); + l.add(new String[] {"+/a/b :\n", "/a/b", ""}); + + for (final String[] strs : l) { + DiffHandler hndl = new DummyDiffHandler() { + @Override + public void setProperty(String targetPath, String diffValue) { + assertEquals(strs[1], targetPath); + assertEquals(strs[2], diffValue); + } + }; + DiffParser parser = new DiffParser(hndl); + parser.parse(strs[0]); + } + + List l2 = new ArrayList(); + // multiple commands + l2.add("+abc :\n\n+def : val"); + l2.add("+abc :\n\n+def : val\n"); + l2.add("+abc : \r+def : val"); + l2.add("+/a/b : val\r+abc : \r "); + l2.add("+/a/b : val\r+abc :\n\n "); + // missing value in the last action. + l2.add("+/a/b : \r+abc :\n"); + l2.add("+/a/b : \\r+abc : abc\r\r+abc :\r"); + l2.add("+abc :\n\n+def : val\r\r>abc : "); + + for (String diff : l2) { + final List li = new ArrayList(); + DiffHandler dh = new DummyDiffHandler() { + @Override + public void addNode(String targetPath, String diffValue) { + li.add(diffValue); + } + }; + + DiffParser parser = new DiffParser(dh); + parser.parse(diff); + assertEquals(2, li.size()); + } + } + + public void testSeparatorLines() throws IOException, DiffException { + String diff = "+abc :\n\n+val : val"; + DiffHandler dh = new DummyDiffHandler() { + @Override + public void addNode(String targetPath, String diffValue) { + if ("abc".equals(targetPath)) { + assertEquals("", diffValue); + } else { + assertEquals("val", diffValue); + } + } + }; + new DiffParser(dh).parse(diff); + + diff = "+abc :\n+val : val"; + dh = new DummyDiffHandler() { + @Override + public void addNode(String targetPath, String diffValue) { + assertEquals("+val : val", diffValue); + } + }; + new DiffParser(dh).parse(diff); + + // TODO: check again: currently all line separation chars before an diff-char are ignored unless they are escaped in way the handler understands (e.g. JSON does: \\r for \r). + diff = "+abc :\r\r\r+def : val"; + dh = new DummyDiffHandler() { + @Override + public void addNode(String targetPath, String diffValue) { + if ("abc".equals(targetPath)) { + assertEquals("", diffValue); + } else { + assertEquals("val", diffValue); + } + } + }; + new DiffParser(dh).parse(diff); + + diff = "+abc : val\r+def :\n\n "; + dh = new DummyDiffHandler() { + @Override + public void addNode(String targetPath, String diffValue) { + if ("abc".equals(targetPath)) { + assertEquals("val", diffValue); + } else { + assertEquals("\n ", diffValue); + } + } + }; + new DiffParser(dh).parse(diff); + } + + public void testUnicodeLineSep() throws IOException, DiffException { + String diff = "+abc : val" + new String(new byte[] {Character.LINE_SEPARATOR}, "utf-8") + "+abc : val"; + DiffHandler dh = new DummyDiffHandler() { + @Override + public void addNode(String targetPath, String diffValue) { + assertEquals("abc", targetPath); + assertEquals("val", diffValue); + } + }; + new DiffParser(dh).parse(diff); + } + + public void testInvalidDiff() throws IOException, DiffException { + List l = new ArrayList(); + l.add(""); + // path, separator and value missing + l.add("+"); + l.add("+/a/b : val\r+"); + // path starting with white space, separator and value missing + l.add("+\n"); + // separator and value missing + l.add("+/a/b"); + l.add("+/a/b : val\r+abc\n"); + l.add("+/a/b :"); + // invalid for separator and value are missing (all : and white space + // is interpreted as part of the path. + l.add("+/a/b:"); + l.add("+/a/b:val"); + l.add("+/a/b: val"); + l.add("+/a/b:\rval"); + l.add("+/a/b :: val"); + // diff starting with white space + l.add(" +/a/b: val"); + l.add("\r\r\r\r\r\r+/a/b: val"); + // key starting with white space + l.add("+\r/a/b : 123"); + l.add("+ /a/b : 123"); + // key starting with colon + l.add("+:/a/b : 123"); + + for (String diff : l) { + try { + DiffParser parser = new DiffParser(new DummyDiffHandler()); + parser.parse(diff); + fail(diff + " is not a valid diff string -> should throw DiffException."); + } catch (DiffException e) { + // ok + } + } + } + + private class DummyDiffHandler implements DiffHandler { + + public void addNode(String targetPath, String diffValue) + throws DiffException { + // does nothing + } + + public void setProperty(String targetPath, String diffValue) + throws DiffException { + // does nothing + } + + public void remove(String targetPath, String diffValue) + throws DiffException { + // does nothing + } + + public void move(String targetPath, String diffValue) throws DiffException { + // does nothing + } + } +} Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/server/remoting/davex/DiffParserTest.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/test/java/org/apache/jackrabbit/server/remoting/davex/JsonDiffHandlerImportTest.java =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/server/remoting/davex/JsonDiffHandlerImportTest.java (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/server/remoting/davex/JsonDiffHandlerImportTest.java (working copy) @@ -0,0 +1,176 @@ +/* + * 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.remoting.davex; + +import java.util.ArrayList; +import java.util.List; +import javax.jcr.Node; +import javax.jcr.RepositoryException; +import javax.jcr.security.AccessControlEntry; +import javax.jcr.security.AccessControlList; +import javax.jcr.security.AccessControlManager; +import javax.jcr.security.AccessControlPolicy; +import javax.jcr.security.Privilege; + +import org.apache.jackrabbit.api.security.JackrabbitAccessControlEntry; +import org.apache.jackrabbit.api.security.JackrabbitAccessControlList; +import org.apache.jackrabbit.commons.jackrabbit.authorization.AccessControlUtils; +import org.apache.jackrabbit.core.security.principal.EveryonePrincipal; +import org.apache.jackrabbit.test.AbstractJCRTest; + +/** + * Tests for {@code JsonDiffHandler} that trigger the import mode. + */ +public class JsonDiffHandlerImportTest extends AbstractJCRTest { + + private static final String JSOP_POLICY_TREE = "+rep:policy : {" + + "\"jcr:primaryType\" : \"rep:ACL\"," + + "\"allow\" : {" + "\"jcr:primaryType\" : \"rep:GrantACE\"," + + "\"rep:principalName\" : \"everyone\"," + + "\"rep:privileges\" : [\"jcr:write\"]" + "}" + "}"; + + private static final List ADD_NODES = new ArrayList(); + static { + ADD_NODES.add( + "+node1 : {" + +"\"jcr:primaryType\" : \"nt:file\"," + + "\"jcr:mixinTypes\" : [\"rep:AccessControllable\"]," + +"\"jcr:uuid\" : \"0a0ca2e9-ab98-4433-a12b-d57283765207\"," + +"\"rep:policy\" : {" + +"\"jcr:primaryType\" : \"rep:ACL\"," + +"\"deny0\" : {" + +"\"jcr:primaryType\" : \"rep:DenyACE\"," + +"\"rep:principalName\" : \"everyone\"," + +"\"rep:privileges\" : [\"jcr:read\"]" + +"}"+"}"+"}"); + ADD_NODES.add( + "+node2 : {" + +"\"jcr:primaryType\" : \"nt:unstructured\"," + + "\"jcr:mixinTypes\" : [\"rep:AccessControllable\"]," + +"\"rep:policy\" : {" + +"\"jcr:primaryType\" : \"rep:ACL\"," + +"\"allow\" : {" + +"\"jcr:primaryType\" : \"rep:GrantACE\"," + +"\"rep:principalName\" : \"everyone\"," + +"\"rep:privileges\" : [\"jcr:read\"]" + +"}," + +"\"deny\" : {" + +"\"jcr:primaryType\" : \"rep:DenyACE\"," + +"\"rep:principalName\" : \"everyone\"," + +"\"rep:privileges\" : [\"jcr:write\"]" + +"}" + +"}"+"}"); + + } + + private AccessControlManager acMgr; + + @Override + protected void setUp() throws Exception { + super.setUp(); + acMgr = superuser.getAccessControlManager(); + } + + private static void assertPolicy(AccessControlManager acMgr, Node targetNode, int noACEs) throws RepositoryException { + AccessControlPolicy[] policies = acMgr.getPolicies(targetNode.getPath()); + assertEquals(policies.length, 1); + + AccessControlPolicy acl = policies[0]; + assertTrue(acl instanceof JackrabbitAccessControlList); + AccessControlEntry[] entries = ((JackrabbitAccessControlList) acl).getAccessControlEntries(); + assertEquals(noACEs, entries.length); + } + + /** + * Test two subsequent DIFF strings with policies, thus multiple addNode operations. + */ + public void testMultipleAddNodeOperations() throws Exception { + for(String jsonString : ADD_NODES) { + JsonDiffHandler h = new JsonDiffHandler(superuser, testRoot, null); + new DiffParser(h).parse(jsonString); + } + + assertPolicy(acMgr, testRootNode.getNode("node1"), 1); + assertPolicy(acMgr, testRootNode.getNode("node2"), 2); + } + + /** + * Test adding 'rep:policy' policy node as a child node of /testroot without + * intermediate node. + */ + public void testAllPolicyNode() throws Exception { + try { + testRootNode.addMixin("rep:AccessControllable"); + + JsonDiffHandler handler = new JsonDiffHandler(superuser, testRoot, null); + new DiffParser(handler).parse(JSOP_POLICY_TREE); + + assertTrue(testRootNode.hasNode("rep:policy")); + assertTrue(testRootNode.getNode("rep:policy").getDefinition().isProtected()); + + assertTrue(testRootNode.getNode("rep:policy").getPrimaryNodeType() + .getName().equals("rep:ACL")); + + assertPolicy(acMgr, testRootNode, 1); + + AccessControlEntry entry = ((AccessControlList) acMgr.getPolicies(testRoot)[0]).getAccessControlEntries()[0]; + assertEquals(EveryonePrincipal.NAME, entry.getPrincipal().getName()); + assertEquals(1, entry.getPrivileges().length); + assertEquals(acMgr.privilegeFromName(Privilege.JCR_WRITE), entry.getPrivileges()[0]); + + if (entry instanceof JackrabbitAccessControlEntry) { + assertTrue(((JackrabbitAccessControlEntry) entry).isAllow()); + } + + } finally { + superuser.refresh(false); + } + } + + /** + * Test adding 'rep:policy' policy node as a child node of /testroot without + * intermediate node. + */ + public void testUpdatePolicyNode() throws Exception { + try { + AccessControlUtils.addAccessControlEntry(superuser, testRoot, EveryonePrincipal.getInstance(), new String[] {Privilege.JCR_READ}, false); + + JsonDiffHandler handler = new JsonDiffHandler(superuser, testRoot, null); + new DiffParser(handler).parse(JSOP_POLICY_TREE); + + assertTrue(testRootNode.hasNode("rep:policy")); + assertTrue(testRootNode.getNode("rep:policy").getDefinition().isProtected()); + + assertTrue(testRootNode.getNode("rep:policy").getPrimaryNodeType() + .getName().equals("rep:ACL")); + + assertPolicy(acMgr, testRootNode, 1); + + AccessControlEntry entry = ((AccessControlList) acMgr.getPolicies(testRoot)[0]).getAccessControlEntries()[0]; + assertEquals(EveryonePrincipal.NAME, entry.getPrincipal().getName()); + assertEquals(1, entry.getPrivileges().length); + assertEquals(acMgr.privilegeFromName(Privilege.JCR_WRITE), entry.getPrivileges()[0]); + + if (entry instanceof JackrabbitAccessControlEntry) { + assertTrue(((JackrabbitAccessControlEntry) entry).isAllow()); + } + + } finally { + superuser.refresh(false); + } + } +} \ No newline at end of file Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/server/remoting/davex/JsonDiffHandlerImportTest.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/server/remoting/davex/JsonDiffHandlerTest.java =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/server/remoting/davex/JsonDiffHandlerTest.java (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/server/remoting/davex/JsonDiffHandlerTest.java (working copy) @@ -0,0 +1,267 @@ +/* + * 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.remoting.davex; + +import junit.framework.TestCase; +import org.xml.sax.ContentHandler; + +import javax.jcr.Credentials; +import javax.jcr.Item; +import javax.jcr.Node; +import javax.jcr.Property; +import javax.jcr.Repository; +import javax.jcr.Session; +import javax.jcr.ValueFactory; +import javax.jcr.Workspace; +import javax.jcr.retention.RetentionManager; +import javax.jcr.security.AccessControlManager; +import java.io.InputStream; +import java.io.OutputStream; +import java.security.AccessControlException; +import java.util.HashMap; +import java.util.Map; + +/** + * JsonDiffHandlerTest... + */ +public class JsonDiffHandlerTest extends TestCase { + + public void testGetItemPath() throws Exception { + Map m = new HashMap(); + m.put("abc", "/reqPath/abc"); + m.put("abc/def/ghi", "/reqPath/abc/def/ghi"); + m.put("/abc", "/abc"); + m.put("/abc/def/ghi", "/abc/def/ghi"); + m.put(".", "/reqPath"); + m.put("./abc", "/reqPath/abc"); + m.put("abc/./def", "/reqPath/abc/def"); + m.put("/abc/./def", "/abc/def"); + m.put("..", "/"); + m.put("../abc/def", "/abc/def"); + m.put("abc/../def/.", "/reqPath/def"); + m.put("abc/../def/..", "/reqPath"); + m.put("abc/../def/..", "/reqPath"); + m.put("abc/../def/..", "/reqPath"); + m.put("abc/../def/..", "/reqPath"); + m.put("abc/../def/..", "/reqPath"); + m.put("abc/../def/..", "/reqPath"); + m.put("./././././", "/reqPath"); + m.put("/./././././", "/"); + m.put("/./abc/def/../ghi", "/abc/ghi"); + + JsonDiffHandler handler = new JsonDiffHandler(new DummySession(), "/reqPath", null); + for (String targetPath : m.keySet()) { + String expItemPath = m.get(targetPath); + assertEquals(expItemPath, handler.getItemPath(targetPath)); + } + } + + private final class DummySession implements Session { + + @Override + public Repository getRepository() { + return null; + } + + @Override + public String getUserID() { + return null; + } + + @Override + public Object getAttribute(String name) { + return null; + } + + @Override + public String[] getAttributeNames() { + return new String[0]; + } + + @Override + public Workspace getWorkspace() { + return null; + } + + @Override + public Session impersonate(Credentials credentials) { + return null; + } + + @Override + public Node getRootNode() { + return null; + } + + @Override + public Node getNodeByUUID(String uuid) { + return null; + } + + @Override + public Item getItem(String absPath) { + return null; + } + + @Override + public boolean itemExists(String absPath) { + return false; + } + + @Override + public void move(String srcAbsPath, String destAbsPath) { + } + + @Override + public void save() { + } + + @Override + public void refresh(boolean keepChanges) { + } + + @Override + public boolean hasPendingChanges() { + return false; + } + + @Override + public ValueFactory getValueFactory() { + return null; + } + + @Override + public void checkPermission(String absPath, String actions) throws AccessControlException { + } + + @Override + public ContentHandler getImportContentHandler(String parentAbsPath, int uuidBehavior) { + return null; + } + + @Override + public void importXML(String parentAbsPath, InputStream in, int uuidBehavior) { + } + + @Override + public void exportSystemView(String absPath, ContentHandler contentHandler, boolean skipBinary, boolean noRecurse) { + } + + @Override + public void exportSystemView(String absPath, OutputStream out, boolean skipBinary, boolean noRecurse) { + } + + @Override + public void exportDocumentView(String absPath, ContentHandler contentHandler, boolean skipBinary, boolean noRecurse) { + } + + @Override + public void exportDocumentView(String absPath, OutputStream out, boolean skipBinary, boolean noRecurse) { + } + + @Override + public void setNamespacePrefix(String prefix, String uri) { + } + + @Override + public String[] getNamespacePrefixes() { + return new String[0]; + } + + @Override + public String getNamespaceURI(String prefix) { + return null; + } + + @Override + public String getNamespacePrefix(String uri) { + return null; + } + + @Override + public void logout() { + } + + @Override + public boolean isLive() { + return false; + } + + @Override + public void addLockToken(String lt) { + } + + @Override + public String[] getLockTokens() { + return new String[0]; + } + + @Override + public void removeLockToken(String lt) { + } + + @Override + public AccessControlManager getAccessControlManager() { + return null; + } + + @Override + public Node getNode(String arg0) { + return null; + } + + @Override + public Node getNodeByIdentifier(String arg0) { + return null; + } + + @Override + public Property getProperty(String arg0) { + return null; + } + + @Override + public RetentionManager getRetentionManager() { + return null; + } + + @Override + public boolean hasCapability(String arg0, Object arg1, Object[] arg2) { + return false; + } + + @Override + public boolean hasPermission(String arg0, String arg1) { + return false; + } + + @Override + public boolean nodeExists(String arg0) { + return false; + } + + @Override + public boolean propertyExists(String arg0) { + return false; + } + + @Override + public void removeItem(String arg0) { + + } + } +} Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/server/remoting/davex/JsonDiffHandlerTest.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/test/java/org/apache/jackrabbit/server/remoting/davex/JsonWriterTest.java =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/server/remoting/davex/JsonWriterTest.java (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/server/remoting/davex/JsonWriterTest.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.remoting.davex; + +import org.apache.jackrabbit.commons.iterator.NodeIteratorAdapter; +import org.apache.jackrabbit.commons.iterator.PropertyIteratorAdapter; +import org.easymock.EasyMockSupport; +import org.easymock.IAnswer; +import org.junit.Test; + +import javax.jcr.Node; +import javax.jcr.NodeIterator; +import javax.jcr.Property; +import javax.jcr.PropertyIterator; +import javax.jcr.PropertyType; +import javax.jcr.Value; +import java.io.StringWriter; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import static org.junit.Assert.*; +import static org.easymock.EasyMock.*; + +public class JsonWriterTest extends EasyMockSupport { + + @Test + public void testDoubleOutput() throws Exception { + StringWriter writer = new StringWriter(); + JsonWriter jsonWriter = new JsonWriter(writer); + + Node parent = createMock(Node.class); + Property doubleProperty = createMock(Property.class); + Value doublePropertyValue = createMock(Value.class); + expect(doubleProperty.getType()).andReturn(PropertyType.DOUBLE).anyTimes(); + expect(doubleProperty.getName()).andReturn("singleValued").anyTimes(); + expect(doubleProperty.isMultiple()).andReturn(false).anyTimes(); + expect(doubleProperty.getValue()).andReturn(doublePropertyValue).anyTimes(); + expect(doublePropertyValue.getType()).andReturn(PropertyType.DOUBLE).anyTimes(); + expect(doublePropertyValue.getDouble()).andReturn(5d).anyTimes(); + expect(doublePropertyValue.getString()).andReturn("5").anyTimes(); + + Property mvDoubleProperty = createMock(Property.class); + Value mvDoublePropertyValue1 = createMock(Value.class); + Value mvDoublePropertyValue2 = createMock(Value.class); + expect(mvDoubleProperty.getType()).andReturn(PropertyType.DOUBLE).anyTimes(); + expect(mvDoubleProperty.getName()).andReturn("multiValued").anyTimes(); + expect(mvDoubleProperty.isMultiple()).andReturn(true).anyTimes(); + expect(mvDoubleProperty.getValues()).andReturn(new Value[] { mvDoublePropertyValue1, mvDoublePropertyValue2}).anyTimes(); + expect(mvDoublePropertyValue1.getType()).andReturn(PropertyType.DOUBLE).anyTimes(); + expect(mvDoublePropertyValue1.getDouble()).andReturn(42d).anyTimes(); + expect(mvDoublePropertyValue1.getString()).andReturn("42").anyTimes(); + expect(mvDoublePropertyValue2.getType()).andReturn(PropertyType.DOUBLE).anyTimes(); + expect(mvDoublePropertyValue2.getDouble()).andReturn(98.6).anyTimes(); + expect(mvDoublePropertyValue2.getString()).andReturn("98.6").anyTimes(); + + final List properties = new ArrayList(); + properties.add(doubleProperty); + properties.add(mvDoubleProperty); + expect(parent.getProperties()).andAnswer(new IAnswer() { + @Override + public PropertyIterator answer() throws Throwable { + return new PropertyIteratorAdapter(properties.iterator()); + } + }); + expect(parent.getNodes()).andAnswer(new IAnswer() { + @Override + public NodeIterator answer() throws Throwable { + return new NodeIteratorAdapter(Collections.emptyIterator()); + } + }); + replayAll(); + + jsonWriter.write(parent, 1); + + assertEquals("{\":singleValued\":\"Double\",\"singleValued\":5,\":multiValued\":\"Double\",\"multiValued\":[42,98.6],\"::NodeIteratorSize\":0}", + writer.toString()); + + verifyAll(); + } + +} \ No newline at end of file Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/server/remoting/davex/JsonWriterTest.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/server/remoting/davex/TestAll.java =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/server/remoting/davex/TestAll.java (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/server/remoting/davex/TestAll.java (working copy) @@ -0,0 +1,42 @@ +/* + * 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.remoting.davex; + +import junit.framework.Test; +import junit.framework.TestCase; +import junit.framework.TestSuite; + +/** + * Test suite that includes all testcases for package org.apache.jackrabbit.server.remoting.davex. + */ +public class TestAll extends TestCase { + + /** + * Returns a Test suite that executes all tests inside this + * package. + */ + public static Test suite() { + TestSuite suite = new TestSuite("org.apache.jackrabbit.server.remoting.davex tests"); + + suite.addTestSuite(DiffParserTest.class); + suite.addTestSuite(JsonDiffHandlerImportTest.class); + suite.addTestSuite(JsonDiffHandlerTest.class); + suite.addTestSuite(BatchReadConfigTest.class); + + return suite; + } +} Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/server/remoting/davex/TestAll.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/test/java/org/apache/jackrabbit/webdav/jcr/JcrDavExceptionTest.java =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/jcr/JcrDavExceptionTest.java (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/jcr/JcrDavExceptionTest.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.webdav.jcr; + +import junit.framework.TestCase; + +import javax.jcr.lock.LockException; +import javax.jcr.RepositoryException; + +/** JcrDavExceptionTest... */ +public class JcrDavExceptionTest extends TestCase { + + public void testDerivedException() { + RepositoryException re = new DerievedRepositoryException(); + + // creating JcrDavException from the derived exception must not throw + // NPE (see issue https://issues.apache.org/jira/browse/JCR-1678) + JcrDavException jde = new JcrDavException(re); + + // error code must be the same as for LockException + assertEquals(new JcrDavException(new LockException()).getErrorCode(), + jde.getErrorCode()); + } + + public void testNullException() { + try { + new JcrDavException(null); + fail("Should throw NPE"); + } catch (NullPointerException e) { + // as documented in the javadoc + } + } + + /** + * Derived exception that does not extend from RepositoryException, which + * returns the 'default' error code. + */ + private static final class DerievedRepositoryException extends LockException { + } +} \ No newline at end of file Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/jcr/JcrDavExceptionTest.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/test/java/org/apache/jackrabbit/webdav/jcr/JcrValueTypeTest.java =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/jcr/JcrValueTypeTest.java (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/jcr/JcrValueTypeTest.java (working copy) @@ -0,0 +1,50 @@ +/* + * 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.webdav.jcr; + +import junit.framework.TestCase; + +import javax.jcr.PropertyType; + +import org.apache.jackrabbit.commons.webdav.JcrValueType; + +/** + * JcrValueTypeTest... + */ +public class JcrValueTypeTest extends TestCase { + + public void testTypeFromContentType() { + for (int i = PropertyType.UNDEFINED; i <= PropertyType.DECIMAL; i++) { + String ct = JcrValueType.contentTypeFromType(i); + assertEquals(i, JcrValueType.typeFromContentType(ct)); + } + } + + public void testTypeFromContentTypeIncludingCharSet() { + for (int i = PropertyType.UNDEFINED; i <= PropertyType.DECIMAL; i++) { + String ct = JcrValueType.contentTypeFromType(i) + "; charset=UTF-8"; + assertEquals(i, JcrValueType.typeFromContentType(ct)); + } + } + public void testTypeFromInvalidContentType() { + String[] invalids = new String[] {null, "", "jcr-value/invalid", "invalid/as-well"}; + + for (String invalid : invalids) { + assertEquals(PropertyType.UNDEFINED, JcrValueType.typeFromContentType(invalid)); + } + } +} \ No newline at end of file Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/jcr/JcrValueTypeTest.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/test/java/org/apache/jackrabbit/webdav/jcr/LockTimeOutFormatTest.java =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/jcr/LockTimeOutFormatTest.java (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/jcr/LockTimeOutFormatTest.java (working copy) @@ -0,0 +1,124 @@ +/* + * 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.webdav.jcr; + +import java.net.URISyntaxException; + +import javax.jcr.Node; +import javax.jcr.RepositoryException; +import javax.jcr.lock.Lock; +import javax.jcr.lock.LockException; +import javax.xml.parsers.ParserConfigurationException; + +import junit.framework.TestCase; + +import org.apache.jackrabbit.webdav.jcr.lock.JcrActiveLock; +import org.apache.jackrabbit.webdav.xml.DomUtil; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.NodeList; + +/** + * LockTimeOutFormatTest... + */ +public class LockTimeOutFormatTest extends TestCase { + + public void testOneSec() throws RepositoryException, URISyntaxException, ParserConfigurationException { + testfmt(1, "Second-1"); + } + + public void testInf() throws RepositoryException, URISyntaxException, ParserConfigurationException { + testfmt(Long.MAX_VALUE, "Infinite"); + } + + public void testTooLong() throws RepositoryException, URISyntaxException, ParserConfigurationException { + testfmt(Integer.MAX_VALUE + 100000L, "Infinite"); + } + + public void testNeg() throws RepositoryException, URISyntaxException, ParserConfigurationException { + // expired + testfmt(-1, null); + } + + private void testfmt(long jcrtimeout, String expectedString) throws RepositoryException, URISyntaxException, ParserConfigurationException { + + Lock l = new TestLock(jcrtimeout); + JcrActiveLock al = new JcrActiveLock(l); + + Document d = DomUtil.createDocument(); + Element activeLock = al.toXml(d); + assertEquals("activelock", activeLock.getLocalName()); + NodeList nl = activeLock.getElementsByTagNameNS("DAV:", "timeout"); + + if (expectedString == null) { + assertEquals(0, nl.getLength()); + } + else { + assertEquals(1, nl.getLength()); + Element timeout = (Element)nl.item(0); + String t = DomUtil.getText(timeout); + assertEquals(expectedString, t); + } + } + + /** + * Minimal Lock impl for tests above + */ + private static class TestLock implements Lock { + + private final long timeout; + + public TestLock(long timeout) { + this.timeout = timeout; + } + + public String getLockOwner() { + return null; + } + + public boolean isDeep() { + return false; + } + + public Node getNode() { + return null; + } + + public String getLockToken() { + return "foo"; + } + + public long getSecondsRemaining() throws RepositoryException { + return timeout; + } + + public boolean isLive() throws RepositoryException { + return timeout >= 0; + } + + public boolean isSessionScoped() { + return false; + } + + public boolean isLockOwningSession() { + return false; + } + + public void refresh() throws LockException, RepositoryException { + } + } +} Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/jcr/LockTimeOutFormatTest.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/jcr/LockTokenMappingTest.java =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/jcr/LockTokenMappingTest.java (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/jcr/LockTokenMappingTest.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.webdav.jcr; + +import java.net.URI; +import java.net.URISyntaxException; +import java.util.UUID; + +import javax.jcr.Node; +import javax.jcr.RepositoryException; +import javax.jcr.lock.Lock; +import javax.jcr.lock.LockException; + +import org.apache.jackrabbit.webdav.jcr.lock.LockTokenMapper; + +import junit.framework.TestCase; + +/** + * LockTokenMappingTest... + */ +public class LockTokenMappingTest extends TestCase { + + // test lock with a lock token similar to the ones assigned by Jackrabbit + public void testOpenScopedJcr() throws RepositoryException, URISyntaxException { + testRoundtrip(UUID.randomUUID().toString() + "-X"); + } + + // test a fancy lock string + public void testOpenScopedFancy() throws RepositoryException, URISyntaxException { + testRoundtrip("\n\u00c4 \u20ac"); + } + + private void testRoundtrip(String token) throws RepositoryException, URISyntaxException { + + Lock l = new TestLock(token); + String davtoken = LockTokenMapper.getDavLocktoken(l); + + // valid URI? + URI u = new URI(davtoken); + assertTrue("lock token must be absolute URI", u.isAbsolute()); + assertEquals("lock token URI must be all-ASCII", u.toASCIIString(), u.toString()); + + String jcrtoken = LockTokenMapper.getJcrLockToken(davtoken); + assertEquals(jcrtoken, l.getLockToken()); + } + + /** + * Minimal Lock impl for tests above + */ + private static class TestLock implements Lock { + + private final String token; + + public TestLock(String token) { + this.token = token; + } + + public String getLockOwner() { + return null; + } + + public boolean isDeep() { + return false; + } + + public Node getNode() { + return null; + } + + public String getLockToken() { + return token; + } + + public long getSecondsRemaining() throws RepositoryException { + return 0; + } + + public boolean isLive() throws RepositoryException { + return false; + } + + public boolean isSessionScoped() { + return false; + } + + public boolean isLockOwningSession() { + return false; + } + + public void refresh() throws LockException, RepositoryException { + } + } +} Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/jcr/LockTokenMappingTest.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/jcr/observation/InfoMapTest.java =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/jcr/observation/InfoMapTest.java (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/jcr/observation/InfoMapTest.java (working copy) @@ -0,0 +1,71 @@ +/* + * 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.webdav.jcr.observation; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; + +import javax.jcr.RepositoryException; +import javax.jcr.Session; +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.transform.TransformerException; + +import org.apache.jackrabbit.webdav.observation.ObservationConstants; +import org.apache.jackrabbit.webdav.xml.DomUtil; +import org.apache.jackrabbit.webdav.xml.Namespace; +import org.mockito.Mockito; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.xml.sax.SAXException; + +import junit.framework.TestCase; + +public class InfoMapTest extends TestCase { + + public void testInfoMap() + throws ParserConfigurationException, TransformerException, SAXException, IOException, RepositoryException { + + Session s = Mockito.mock(Session.class); + Mockito.when(s.getNamespaceURI("jcr")).thenReturn("http://www.jcp.org/jcr/1.0"); + + Map map = new HashMap(); + // mandated by JCR 2.0 + map.put("srcChildRelPath", "/x"); + // OAK extension, see https://issues.apache.org/jira/browse/OAK-1669 + map.put("jcr:primaryType", "nt:unstructured"); + Document doc = DomUtil.createDocument(); + Element container = DomUtil.createElement(doc, "x", null); + doc.appendChild(container); + SubscriptionImpl.serializeInfoMap(container, s, map); + ByteArrayOutputStream xml = new ByteArrayOutputStream(); + DomUtil.transformDocument(doc, xml); + + // reparse + Document tripped = DomUtil.parseDocument(new ByteArrayInputStream(xml.toByteArray())); + Element top = tripped.getDocumentElement(); + assertEquals("x", top.getLocalName()); + Element emap = DomUtil.getChildElement(top, ObservationConstants.N_EVENTINFO); + assertNotNull(emap); + Element path = DomUtil.getChildElement(emap, "srcChildRelPath", null); + assertNotNull(path); + Element type = DomUtil.getChildElement(emap, "primaryType", Namespace.getNamespace("http://www.jcp.org/jcr/1.0")); + assertNotNull(type); + } +} Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/jcr/observation/InfoMapTest.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/jcr/security/AbstractSecurityTest.java =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/jcr/security/AbstractSecurityTest.java (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/jcr/security/AbstractSecurityTest.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.webdav.jcr.security; + +import javax.jcr.Repository; +import javax.jcr.security.AccessControlManager; + +import org.apache.jackrabbit.test.AbstractJCRTest; +import org.apache.jackrabbit.test.NotExecutableException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public abstract class AbstractSecurityTest extends AbstractJCRTest { + + protected AccessControlManager acMgr; + + @Override + protected void setUp() throws Exception { + super.setUp(); + if (isSupported(Repository.OPTION_ACCESS_CONTROL_SUPPORTED)) { + acMgr = superuser.getAccessControlManager(); + } else { + throw new NotExecutableException(); + } + } +} \ No newline at end of file Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/jcr/security/AbstractSecurityTest.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/jcr/security/JcrSupportedPrivilegePropertyTest.java =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/jcr/security/JcrSupportedPrivilegePropertyTest.java (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/jcr/security/JcrSupportedPrivilegePropertyTest.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.webdav.jcr.security; + +import java.util.Arrays; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import javax.jcr.RepositoryException; +import javax.jcr.security.Privilege; + +import org.apache.jackrabbit.webdav.security.SupportedPrivilege; + +public class JcrSupportedPrivilegePropertyTest extends AbstractSecurityTest { + + public void testSupportedPrivileges() throws RepositoryException { + Set privs = new HashSet(Arrays.asList(acMgr.getSupportedPrivileges(testRoot))); + JcrSupportedPrivilegesProperty prop = new JcrSupportedPrivilegesProperty(superuser, testRoot); + List value = prop.asDavProperty().getValue(); + + if (privs.contains(acMgr.privilegeFromName(Privilege.JCR_ALL))) { + assertEquals(1, value.size()); + } + } + + public void testJcrAllPrivilege() throws RepositoryException { + JcrSupportedPrivilegesProperty prop = new JcrSupportedPrivilegesProperty(superuser); + List value = prop.asDavProperty().getValue(); + + assertEquals(1, value.size()); + } +} \ No newline at end of file Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/jcr/security/JcrSupportedPrivilegePropertyTest.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/jcr/security/JcrUserPrivilegesPropertyTest.java =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/jcr/security/JcrUserPrivilegesPropertyTest.java (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/jcr/security/JcrUserPrivilegesPropertyTest.java (working copy) @@ -0,0 +1,69 @@ +/* + * 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.webdav.jcr.security; + +import java.util.Collection; +import java.util.HashSet; +import java.util.Set; +import javax.jcr.RepositoryException; +import javax.jcr.Session; +import javax.jcr.security.AccessControlManager; + +import org.apache.jackrabbit.util.Text; +import org.apache.jackrabbit.webdav.security.Privilege; +import org.apache.jackrabbit.webdav.xml.Namespace; + +public class JcrUserPrivilegesPropertyTest extends AbstractSecurityTest { + + private Set getExpected(AccessControlManager acMgr, Session s) throws RepositoryException { + Set expected = new HashSet(); + for (javax.jcr.security.Privilege p : acMgr.getPrivileges(testRoot)) { + String localName = Text.getLocalName(p.getName()); + String prefix = Text.getNamespacePrefix(p.getName()); + Namespace ns = (prefix.isEmpty()) ? Namespace.EMPTY_NAMESPACE : Namespace.getNamespace(prefix, s.getNamespaceURI(prefix)); + expected.add(Privilege.getPrivilege(localName, ns)); + } + return expected; + } + + public void testAdminPrivileges() throws RepositoryException { + Set expected = getExpected(acMgr, superuser); + + JcrUserPrivilegesProperty upp = new JcrUserPrivilegesProperty(superuser, testRoot); + Collection davPrivs = upp.asDavProperty().getValue(); + + assertEquals(expected.size(), davPrivs.size()); + assertTrue(davPrivs.containsAll(expected)); + } + + public void testReadOnlyPrivileges() throws RepositoryException { + Session readOnly = getHelper().getReadOnlySession(); + try { + Set expected = getExpected(readOnly.getAccessControlManager(), readOnly); + + JcrUserPrivilegesProperty upp = new JcrUserPrivilegesProperty(readOnly, testRoot); + Collection davPrivs = upp.asDavProperty().getValue(); + + assertEquals(expected.size(), davPrivs.size()); + assertTrue(davPrivs.containsAll(expected)); + } finally { + if (readOnly != null) { + readOnly.logout(); + } + } + } +} \ No newline at end of file Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/jcr/security/JcrUserPrivilegesPropertyTest.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/server/BindTest.java =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/server/BindTest.java (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/server/BindTest.java (working copy) @@ -0,0 +1,603 @@ +/* + * 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.webdav.server; + +import java.io.IOException; +import java.net.URI; +import java.net.URISyntaxException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Set; + +import org.apache.http.HttpResponse; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.client.methods.HttpHead; +import org.apache.http.client.methods.HttpPut; +import org.apache.http.entity.ContentType; +import org.apache.http.entity.StringEntity; +import org.apache.http.util.EntityUtils; +import org.apache.jackrabbit.webdav.DavException; +import org.apache.jackrabbit.webdav.MultiStatus; +import org.apache.jackrabbit.webdav.MultiStatusResponse; +import org.apache.jackrabbit.webdav.bind.BindConstants; +import org.apache.jackrabbit.webdav.bind.BindInfo; +import org.apache.jackrabbit.webdav.bind.ParentElement; +import org.apache.jackrabbit.webdav.bind.RebindInfo; +import org.apache.jackrabbit.webdav.bind.UnbindInfo; +import org.apache.jackrabbit.webdav.client.methods.HttpBind; +import org.apache.jackrabbit.webdav.client.methods.HttpMkcol; +import org.apache.jackrabbit.webdav.client.methods.HttpMove; +import org.apache.jackrabbit.webdav.client.methods.HttpOptions; +import org.apache.jackrabbit.webdav.client.methods.HttpPropfind; +import org.apache.jackrabbit.webdav.client.methods.HttpRebind; +import org.apache.jackrabbit.webdav.client.methods.HttpUnbind; +import org.apache.jackrabbit.webdav.client.methods.HttpVersionControl; +import org.apache.jackrabbit.webdav.property.DavProperty; +import org.apache.jackrabbit.webdav.property.DavPropertyNameSet; +import org.w3c.dom.Element; +import org.w3c.dom.Node; + +/** + * Test cases for WebDAV BIND functionality (see RFC 5842 + */ +public class BindTest extends WebDAVTestBase { + + // http://greenbytes.de/tech/webdav/rfc5842.html#rfc.section.8.1 + public void testOptions() throws IOException { + HttpOptions options = new HttpOptions(this.uri); + HttpResponse response = this.client.execute(options, this.context); + int status = response.getStatusLine().getStatusCode(); + assertEquals(200, status); + Set allow = options.getAllowedMethods(response); + Set complianceClasses = options.getDavComplianceClasses(response); + assertTrue("DAV header should include 'bind' feature", complianceClasses.contains("bind")); + assertTrue("Allow header should include BIND method", allow.contains("BIND")); + assertTrue("Allow header should include REBIND method", allow.contains("REBIND")); + assertTrue("Allow header should include UNBIND method", allow.contains("UNBIND")); + } + + // create test resource, make it referenceable, check resource id, move resource, check again + public void testResourceId() throws IOException, DavException, URISyntaxException { + + String testcol = this.root + "testResourceId/"; + String testuri1 = testcol + "bindtest1"; + String testuri2 = testcol + "bindtest2"; + int status; + try { + HttpMkcol mkcol = new HttpMkcol(testcol); + status = this.client.execute(mkcol, this.context).getStatusLine().getStatusCode(); + assertEquals(201, status); + + HttpPut put = new HttpPut(testuri1); + put.setEntity(new StringEntity("foo", ContentType.create("text/plain", "UTF-8"))); + status = this.client.execute(put, this.context).getStatusLine().getStatusCode(); + assertEquals(201, status); + + // enabling version control always makes the resource referenceable + HttpVersionControl versioncontrol = new HttpVersionControl(testuri1); + status = this.client.execute(versioncontrol, this.context).getStatusLine().getStatusCode(); + assertTrue("status: " + status, status == 200 || status == 201); + + URI resourceId = getResourceId(testuri1); + + HttpMove move = new HttpMove(testuri1, testuri2, true); + status = this.client.execute(move, this.context).getStatusLine().getStatusCode(); + assertEquals(201, status); + + URI resourceId2 = getResourceId(testuri2); + assertEquals(resourceId, resourceId2); + } finally { + delete(testcol); + } + } + + // utility methods + + // see http://greenbytes.de/tech/webdav/rfc5842.html#rfc.section.3.1 + private URI getResourceId(String uri) throws IOException, DavException, URISyntaxException { + DavPropertyNameSet names = new DavPropertyNameSet(); + names.add(BindConstants.RESOURCEID); + HttpPropfind propfind = new HttpPropfind(uri, names, 0); + HttpResponse response = this.client.execute(propfind, this.context); + int status = response.getStatusLine().getStatusCode(); + assertEquals(207, status); + MultiStatus multistatus = propfind.getResponseBodyAsMultiStatus(response); + MultiStatusResponse[] responses = multistatus.getResponses(); + assertEquals(1, responses.length); + DavProperty resourceId = responses[0].getProperties(200).get(BindConstants.RESOURCEID); + assertNotNull(resourceId); + assertTrue(resourceId.getValue() instanceof Element); + Element href = (Element)resourceId.getValue(); + assertEquals("href", href.getLocalName()); + String text = getUri(href); + URI resid = new URI(text); + return resid; + } + + private DavProperty getParentSet(String uri) throws IOException, DavException, URISyntaxException { + DavPropertyNameSet names = new DavPropertyNameSet(); + names.add(BindConstants.PARENTSET); + HttpPropfind propfind = new HttpPropfind(uri, names, 0); + HttpResponse response = this.client.execute(propfind, this.context); + int status = response.getStatusLine().getStatusCode(); + assertEquals(207, status); + MultiStatus multistatus = propfind.getResponseBodyAsMultiStatus(response); + MultiStatusResponse[] responses = multistatus.getResponses(); + assertEquals(1, responses.length); + DavProperty parentset = responses[0].getProperties(200).get(BindConstants.PARENTSET); + assertNotNull(parentset); + return parentset; + } + + public void testSimpleBind() throws Exception { + String testcol = this.root + "testSimpleBind/"; + String subcol1 = testcol + "bindtest1/"; + String testres1 = subcol1 + "res1"; + String subcol2 = testcol + "bindtest2/"; + String testres2 = subcol2 + "res2"; + int status; + try { + HttpMkcol mkcol = new HttpMkcol(testcol); + status = this.client.execute(mkcol, this.context).getStatusLine().getStatusCode(); + assertEquals(201, status); + mkcol = new HttpMkcol(subcol1); + status = this.client.execute(mkcol, this.context).getStatusLine().getStatusCode(); + assertEquals(201, status); + mkcol = new HttpMkcol(subcol2); + status = this.client.execute(mkcol, this.context).getStatusLine().getStatusCode(); + assertEquals(201, status); + + //create new resource R with path bindtest1/res1 + HttpPut put = new HttpPut(testres1); + put.setEntity(new StringEntity("foo", ContentType.create("text/plain", "UTF-8"))); + status = this.client.execute(put, this.context).getStatusLine().getStatusCode(); + assertEquals(201, status); + + //create new binding of R with path bindtest2/res2 + HttpBind bind = new HttpBind(subcol2, new BindInfo(testres1, "res2")); + status = this.client.execute(bind, this.context).getStatusLine().getStatusCode(); + assertEquals(201, status); + //check if both bindings report the same DAV:resource-id + assertEquals(this.getResourceId(testres1), this.getResourceId(testres2)); + + //compare representations retrieved with both paths + HttpGet get = new HttpGet(testres1); + HttpResponse resp = this.client.execute(get, this.context); + status = resp.getStatusLine().getStatusCode(); + assertEquals(200, status); + assertEquals("foo", EntityUtils.toString(resp.getEntity())); + resp = this.client.execute(get, this.context); + status = resp.getStatusLine().getStatusCode(); + assertEquals(200, status); + assertEquals("foo", EntityUtils.toString(resp.getEntity())); + + //modify R using the new path + put = new HttpPut(testres2); + put.setEntity(new StringEntity("bar", ContentType.create("text/plain", "UTF-8"))); + status = this.client.execute(put, this.context).getStatusLine().getStatusCode(); + assertTrue("status: " + status, status == 200 || status == 204); + + //compare representations retrieved with both paths + get = new HttpGet(testres1); + resp = this.client.execute(get, this.context); + status = resp.getStatusLine().getStatusCode(); + assertEquals(200, status); + assertEquals("bar", EntityUtils.toString(resp.getEntity())); + get = new HttpGet(testres2); + resp = this.client.execute(get, this.context); + status = resp.getStatusLine().getStatusCode(); + assertEquals(200, status); + assertEquals("bar", EntityUtils.toString(resp.getEntity())); + } finally { + delete(testcol); + } + } + + public void testRebind() throws Exception { + String testcol = this.root + "testRebind/"; + String subcol1 = testcol + "bindtest1/"; + String testres1 = subcol1 + "res1"; + String subcol2 = testcol + "bindtest2/"; + String testres2 = subcol2 + "res2"; + int status; + try { + HttpMkcol mkcol = new HttpMkcol(testcol); + status = this.client.execute(mkcol, this.context).getStatusLine().getStatusCode(); + assertEquals(201, status); + mkcol = new HttpMkcol(subcol1); + status = this.client.execute(mkcol, this.context).getStatusLine().getStatusCode(); + assertEquals(201, status); + mkcol = new HttpMkcol(subcol2); + status = this.client.execute(mkcol, this.context).getStatusLine().getStatusCode(); + assertEquals(201, status); + + //create new resource R with path bindtest1/res1 + HttpPut put = new HttpPut(testres1); + put.setEntity(new StringEntity("foo", ContentType.create("text/plain", "UTF-8"))); + status = this.client.execute(put, this.context).getStatusLine().getStatusCode(); + assertEquals(201, status); + + // enabling version control always makes the resource referenceable + HttpVersionControl versioncontrol = new HttpVersionControl(testres1); + status = this.client.execute(versioncontrol, this.context).getStatusLine().getStatusCode(); + assertTrue("status: " + status, status == 200 || status == 201); + + URI r1 = this.getResourceId(testres1); + + HttpGet get = new HttpGet(testres1); + HttpResponse resp = this.client.execute(get, this.context); + status = resp.getStatusLine().getStatusCode(); + assertEquals(200, status); + assertEquals("foo", EntityUtils.toString(resp.getEntity())); + + //rebind R with path bindtest2/res2 + HttpRebind rebind = new HttpRebind(subcol2, new RebindInfo(testres1, "res2")); + status = this.client.execute(rebind, this.context).getStatusLine().getStatusCode(); + assertEquals(201, status); + + URI r2 = this.getResourceId(testres2); + + get = new HttpGet(testres2); + resp = this.client.execute(get, this.context); + status = resp.getStatusLine().getStatusCode(); + assertEquals(200, status); + assertEquals("foo", EntityUtils.toString(resp.getEntity())); + + //make sure that rebind did not change the resource-id + assertEquals(r1, r2); + + //verify that the initial binding is gone + HttpHead head = new HttpHead(testres1); + status = this.client.execute(head, this.context).getStatusLine().getStatusCode(); + assertEquals(404, status); + } finally { + delete(testcol); + } + } + + public void testBindOverwrite() throws Exception { + String testcol = this.root + "testSimpleBind/"; + String subcol1 = testcol + "bindtest1/"; + String testres1 = subcol1 + "res1"; + String subcol2 = testcol + "bindtest2/"; + String testres2 = subcol2 + "res2"; + int status; + try { + HttpMkcol mkcol = new HttpMkcol(testcol); + status = this.client.execute(mkcol, this.context).getStatusLine().getStatusCode(); + assertEquals(201, status); + mkcol = new HttpMkcol(subcol1); + status = this.client.execute(mkcol, this.context).getStatusLine().getStatusCode(); + assertEquals(201, status); + mkcol = new HttpMkcol(subcol2); + status = this.client.execute(mkcol, this.context).getStatusLine().getStatusCode(); + assertEquals(201, status); + + //create new resource R with path bindtest1/res1 + HttpPut put = new HttpPut(testres1); + put.setEntity(new StringEntity("foo", ContentType.create("text/plain", "UTF-8"))); + status = this.client.execute(put, this.context).getStatusLine().getStatusCode(); + assertEquals(201, status); + + //create new resource R' with path bindtest2/res2 + put = new HttpPut(testres2); + put.setEntity(new StringEntity("bar", ContentType.create("text/plain", "UTF-8"))); + status = this.client.execute(put, this.context).getStatusLine().getStatusCode(); + assertEquals(201, status); + + //try to create new binding of R with path bindtest2/res2 and Overwrite:F + HttpBind bind = new HttpBind(subcol2, new BindInfo(testres1, "res2")); + bind.addHeader("Overwrite", "F"); + status = this.client.execute(bind, this.context).getStatusLine().getStatusCode(); + assertEquals(412, status); + + //verify that bindtest2/res2 still points to R' + HttpGet get = new HttpGet(testres2); + HttpResponse resp = this.client.execute(get, this.context); + status = resp.getStatusLine().getStatusCode(); + assertEquals(200, status); + assertEquals("bar", EntityUtils.toString(resp.getEntity())); + + //create new binding of R with path bindtest2/res2 + bind = new HttpBind(subcol2, new BindInfo(testres1, "res2")); + status = this.client.execute(bind, this.context).getStatusLine().getStatusCode(); + assertTrue("status: " + status, status == 200 || status == 204); + + //verify that bindtest2/res2 now points to R + get = new HttpGet(testres2); + resp = this.client.execute(get, this.context); + status = resp.getStatusLine().getStatusCode(); + assertEquals(200, status); + assertEquals("foo", EntityUtils.toString(resp.getEntity())); + + //verify that the initial binding is still there + HttpHead head = new HttpHead(testres1); + status = this.client.execute(head, this.context).getStatusLine().getStatusCode(); + assertEquals(200, status); + } finally { + delete(testcol); + } + } + + public void testRebindOverwrite() throws Exception { + String testcol = this.root + "testSimpleBind/"; + String subcol1 = testcol + "bindtest1/"; + String testres1 = subcol1 + "res1"; + String subcol2 = testcol + "bindtest2/"; + String testres2 = subcol2 + "res2"; + int status; + try { + HttpMkcol mkcol = new HttpMkcol(testcol); + status = this.client.execute(mkcol, this.context).getStatusLine().getStatusCode(); + assertEquals(201, status); + mkcol = new HttpMkcol(subcol1); + status = this.client.execute(mkcol, this.context).getStatusLine().getStatusCode(); + assertEquals(201, status); + mkcol = new HttpMkcol(subcol2); + status = this.client.execute(mkcol, this.context).getStatusLine().getStatusCode(); + assertEquals(201, status); + + //create new resource R with path testSimpleBind/bindtest1/res1 + HttpPut put = new HttpPut(testres1); + put.setEntity(new StringEntity("foo", ContentType.create("text/plain", "UTF-8"))); + status = this.client.execute(put, this.context).getStatusLine().getStatusCode(); + assertEquals(201, status); + + // enabling version control always makes the resource referenceable + HttpVersionControl versioncontrol = new HttpVersionControl(testres1); + status = this.client.execute(versioncontrol, this.context).getStatusLine().getStatusCode(); + assertTrue("status: " + status, status == 200 || status == 201); + + //create new resource R' with path testSimpleBind/bindtest2/res2 + put = new HttpPut(testres2); + put.setEntity(new StringEntity("bar", ContentType.create("text/plain", "UTF-8"))); + status = this.client.execute(put, this.context).getStatusLine().getStatusCode(); + assertEquals(201, status); + + //try rebind R with path testSimpleBind/bindtest2/res2 and Overwrite:F + HttpRebind rebind = new HttpRebind(subcol2, new RebindInfo(testres1, "res2")); + rebind.addHeader("Overwrite", "F"); + status = this.client.execute(rebind, this.context).getStatusLine().getStatusCode(); + assertEquals(412, status); + + //verify that testSimpleBind/bindtest2/res2 still points to R' + HttpGet get = new HttpGet(testres2); + HttpResponse resp = this.client.execute(get, this.context); + status = resp.getStatusLine().getStatusCode(); + assertEquals(200, status); + assertEquals("bar", EntityUtils.toString(resp.getEntity())); + + //rebind R with path testSimpleBind/bindtest2/res2 + rebind = new HttpRebind(subcol2, new RebindInfo(testres1, "res2")); + status = this.client.execute(rebind, this.context).getStatusLine().getStatusCode(); + assertTrue("status: " + status, status == 200 || status == 204); + + //verify that testSimpleBind/bindtest2/res2 now points to R + get = new HttpGet(testres2); + resp = this.client.execute(get, this.context); + status = resp.getStatusLine().getStatusCode(); + assertEquals(200, status); + assertEquals("foo", EntityUtils.toString(resp.getEntity())); + + //verify that the initial binding is gone + HttpHead head = new HttpHead(testres1); + status = this.client.execute(head, this.context).getStatusLine().getStatusCode(); + assertEquals(404, status); + } finally { + delete(testcol); + } + } + + public void testParentSet() throws Exception { + String testcol = this.root + "testParentSet/"; + String subcol1 = testcol + "bindtest1/"; + String testres1 = subcol1 + "res1"; + String subcol2 = testcol + "bindtest2/"; + String testres2 = subcol2 + "res2"; + int status; + try { + HttpMkcol mkcol = new HttpMkcol(testcol); + status = this.client.execute(mkcol, this.context).getStatusLine().getStatusCode(); + assertEquals(201, status); + mkcol = new HttpMkcol(subcol1); + status = this.client.execute(mkcol, this.context).getStatusLine().getStatusCode(); + assertEquals(201, status); + mkcol = new HttpMkcol(subcol2); + status = this.client.execute(mkcol, this.context).getStatusLine().getStatusCode(); + assertEquals(201, status); + + //create new resource R with path testSimpleBind/bindtest1/res1 + HttpPut put = new HttpPut(testres1); + put.setEntity(new StringEntity("foo", ContentType.create("text/plain", "UTF-8"))); + status = this.client.execute(put, this.context).getStatusLine().getStatusCode(); + assertEquals(201, status); + + //create new binding of R with path testSimpleBind/bindtest2/res2 + HttpBind bind = new HttpBind(subcol2, new BindInfo(testres1, "res2")); + status = this.client.execute(bind, this.context).getStatusLine().getStatusCode(); + assertEquals(201, status); + //check if both bindings report the same DAV:resource-id + assertEquals(this.getResourceId(testres1), this.getResourceId(testres2)); + + //verify values of parent-set properties + List hrefs1 = new ArrayList(); + List segments1 = new ArrayList(); + List hrefs2 = new ArrayList(); + List segments2 = new ArrayList(); + Object ps1 = this.getParentSet(testres1).getValue(); + Object ps2 = this.getParentSet(testres2).getValue(); + assertTrue(ps1 instanceof List); + assertTrue(ps2 instanceof List); + List plist1 = (List) ps1; + List plist2 = (List) ps2; + assertEquals(2, plist1.size()); + assertEquals(2, plist2.size()); + for (int k = 0; k < 2; k++) { + Object pObj1 = plist1.get(k); + Object pObj2 = plist2.get(k); + assertTrue(pObj1 instanceof Element); + assertTrue(pObj2 instanceof Element); + ParentElement p1 = ParentElement.createFromXml((Element) pObj1); + ParentElement p2 = ParentElement.createFromXml((Element) pObj2); + hrefs1.add(p1.getHref()); + hrefs2.add(p2.getHref()); + segments1.add(p1.getSegment()); + segments2.add(p2.getSegment()); + } + Collections.sort(hrefs1); + Collections.sort(hrefs2); + Collections.sort(segments1); + Collections.sort(segments2); + assertEquals(hrefs1, hrefs2); + assertEquals(segments1, segments2); + } finally { + delete(testcol); + } + } + + public void testBindCollections() throws Exception { + String testcol = this.root + "testBindCollections/"; + String a1 = testcol + "a1/"; + String b1 = a1 + "b1/"; + String c1 = b1 + "c1/"; + String x1 = c1 + "x1"; + String a2 = testcol + "a2/"; + String b2 = a2 + "b2/"; + String c2 = b2 + "c2/"; + String x2 = c2 + "x2"; + int status; + try { + HttpMkcol mkcol = new HttpMkcol(testcol); + status = this.client.execute(mkcol, this.context).getStatusLine().getStatusCode(); + assertEquals(201, status); + mkcol = new HttpMkcol(a1); + status = this.client.execute(mkcol, this.context).getStatusLine().getStatusCode(); + assertEquals(201, status); + mkcol = new HttpMkcol(a2); + status = this.client.execute(mkcol, this.context).getStatusLine().getStatusCode(); + assertEquals(201, status); + + //create collection resource C + mkcol = new HttpMkcol(b1); + status = this.client.execute(mkcol, this.context).getStatusLine().getStatusCode(); + assertEquals(201, status); + mkcol = new HttpMkcol(c1); + status = this.client.execute(mkcol, this.context).getStatusLine().getStatusCode(); + assertEquals(201, status); + + //create plain resource R + HttpPut put = new HttpPut(x1); + put.setEntity(new StringEntity("foo", ContentType.create("text/plain", "UTF-8"))); + status = this.client.execute(put, this.context).getStatusLine().getStatusCode(); + assertEquals(201, status); + + //create new binding of C with path a2/b2 + HttpBind bind = new HttpBind(a2, new BindInfo(b1, "b2")); + status = this.client.execute(bind, this.context).getStatusLine().getStatusCode(); + assertEquals(201, status); + //check if both bindings report the same DAV:resource-id + assertEquals(this.getResourceId(b1), this.getResourceId(b2)); + + mkcol = new HttpMkcol(c2); + status = this.client.execute(mkcol, this.context).getStatusLine().getStatusCode(); + assertEquals(201, status); + + //create new binding of R with path a2/b2/c2/r2 + bind = new HttpBind(c2, new BindInfo(x1, "x2")); + status = this.client.execute(bind, this.context).getStatusLine().getStatusCode(); + assertEquals(201, status); + //check if both bindings report the same DAV:resource-id + assertEquals(this.getResourceId(x1), this.getResourceId(x2)); + + //verify different path alternatives + URI rid = this.getResourceId(x1); + assertEquals(rid, this.getResourceId(x2)); + assertEquals(rid, this.getResourceId(testcol + "a2/b2/c1/x1")); + assertEquals(rid, this.getResourceId(testcol + "a1/b1/c2/x2")); + Object ps = this.getParentSet(x1).getValue(); + assertTrue(ps instanceof List); + assertEquals(2, ((List) ps).size()); + ps = this.getParentSet(x2).getValue(); + assertTrue(ps instanceof List); + assertEquals(2, ((List) ps).size()); + } finally { + delete(testcol); + } + } + + //will fail until is fixed + public void testUnbind() throws Exception { + String testcol = this.root + "testUnbind/"; + String subcol1 = testcol + "bindtest1/"; + String testres1 = subcol1 + "res1"; + String subcol2 = testcol + "bindtest2/"; + String testres2 = subcol2 + "res2"; + int status; + try { + HttpMkcol mkcol = new HttpMkcol(testcol); + status = this.client.execute(mkcol, this.context).getStatusLine().getStatusCode(); + assertEquals(201, status); + mkcol = new HttpMkcol(subcol1); + status = this.client.execute(mkcol, this.context).getStatusLine().getStatusCode(); + assertEquals(201, status); + mkcol = new HttpMkcol(subcol2); + status = this.client.execute(mkcol, this.context).getStatusLine().getStatusCode(); + assertEquals(201, status); + + //create new resource R with path testSimpleBind/bindtest1/res1 + HttpPut put = new HttpPut(testres1); + put.setEntity(new StringEntity("foo", ContentType.create("text/plain", "UTF-8"))); + status = this.client.execute(put, this.context).getStatusLine().getStatusCode(); + assertEquals(201, status); + + //create new binding of R with path testSimpleBind/bindtest2/res2 + HttpBind bind = new HttpBind(subcol2, new BindInfo(testres1, "res2")); + status = this.client.execute(bind, this.context).getStatusLine().getStatusCode(); + assertEquals(201, status); + //check if both bindings report the same DAV:resource-id + assertEquals(this.getResourceId(testres1), this.getResourceId(testres2)); + + //remove new path + HttpUnbind unbind = new HttpUnbind(subcol2, new UnbindInfo("res2")); + status = this.client.execute(unbind, this.context).getStatusLine().getStatusCode(); + assertTrue("status: " + status, status == 200 || status == 204); + + //verify that the new binding is gone + HttpHead head = new HttpHead(testres2); + status = this.client.execute(head, this.context).getStatusLine().getStatusCode(); + assertEquals(404, status); + + //verify that the initial binding is still there + head = new HttpHead(testres1); + status = this.client.execute(head, this.context).getStatusLine().getStatusCode(); + assertEquals(200, status); + } finally { + delete(testcol); + } + } + + private String getUri(Element href) { + String s = ""; + for (Node c = href.getFirstChild(); c != null; c = c.getNextSibling()) { + if (c.getNodeType() == Node.TEXT_NODE) { + s += c.getNodeValue(); + } + } + return s; + } +} Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/server/BindTest.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/server/ConditionalsTest.java =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/server/ConditionalsTest.java (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/server/ConditionalsTest.java (working copy) @@ -0,0 +1,177 @@ +/* + * 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.webdav.server; + +import java.io.IOException; +import java.text.ParseException; + +import org.apache.http.Header; +import org.apache.http.HttpResponse; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.client.methods.HttpHead; +import org.apache.http.client.methods.HttpPut; +import org.apache.http.entity.StringEntity; +import org.apache.http.util.EntityUtils; + +public class ConditionalsTest extends WebDAVTestBase { + + // private DateFormat HTTPDATEFORMAT = new SimpleDateFormat("EEE, dd MMM + // yyyy HH:mm:ss ZZZ", Locale.ENGLISH); + + public void testPutCheckLastModified() throws IOException, ParseException { + String testUri = this.uri.toString() + (this.uri.toString().endsWith("/") ? "" : "/") + "testPutCheckLastModified"; + try { + // create test resource + { + HttpPut put = new HttpPut(testUri); + put.setEntity(new StringEntity("foobar")); + HttpResponse response = this.client.execute(put, this.context); + int status = response.getStatusLine().getStatusCode(); + assertEquals(201, status); + } + + long created = System.currentTimeMillis(); + + // get last modified date + Header etag = null; + Header lm = null; + { + HttpHead head = new HttpHead(testUri); + HttpResponse response = this.client.execute(head, this.context); + int status = response.getStatusLine().getStatusCode(); + assertEquals(200, status); + lm = response.getFirstHeader("last-modified"); + assertNotNull(lm); + etag = response.getFirstHeader("etag"); + } + + // Date created = HTTPDATEFORMAT.parse(lm.getValue()); + + // conditional GET + { + HttpGet get = new HttpGet(testUri); + get.setHeader("If-Modified-Since", lm.getValue()); + HttpResponse response = this.client.execute(get, this.context); + int status = response.getStatusLine().getStatusCode(); + assertEquals(304, status); + if (etag != null) { + Header newetag = response.getFirstHeader("etag"); + assertNotNull(newetag); + assertEquals(etag.getValue(), newetag.getValue()); + } + } + + // conditional HEAD + { + HttpHead head = new HttpHead(testUri); + head.setHeader("If-Modified-Since", lm.getValue()); + HttpResponse response = this.client.execute(head, this.context); + int status = response.getStatusLine().getStatusCode(); + assertEquals(304, status); + if (etag != null) { + Header newetag = response.getFirstHeader("etag"); + assertNotNull(newetag); + assertEquals(etag.getValue(), newetag.getValue()); + } + } + + // conditional HEAD with broken date (MUST ignore header field) + { + HttpHead head = new HttpHead(testUri); + head.setHeader("If-Modified-Since", "broken"); + HttpResponse response = this.client.execute(head, this.context); + int status = response.getStatusLine().getStatusCode(); + assertEquals(200, status); + } + + // conditional GET with broken date (MUST ignore header field) + { + HttpGet req = new HttpGet(testUri); + req.addHeader("If-Modified-Since", lm.getValue()); + req.addHeader("If-Modified-Since", "foo"); + HttpResponse response = this.client.execute(req, this.context); + int status = response.getStatusLine().getStatusCode(); + assertEquals(200, status); + EntityUtils.consume(response.getEntity()); + } + + // let one sec elapse + while (System.currentTimeMillis() < created + 1000) { + try { + Thread.sleep(100); + } catch (InterruptedException ignored) { + } + } + + // verify last modified did not change + { + HttpHead head = new HttpHead(testUri); + HttpResponse response = this.client.execute(head, this.context); + int status = response.getStatusLine().getStatusCode(); + assertEquals(200, status); + Header newlm = response.getFirstHeader("last-modified"); + assertNotNull(newlm); + assertEquals(lm.getValue(), newlm.getValue()); + } + + // conditional PUT + { + HttpPut put = new HttpPut(testUri); + put.setHeader("If-Unmodified-Since", lm.getValue()); + put.setEntity(new StringEntity("qux")); + HttpResponse response = this.client.execute(put, this.context); + int status = response.getStatusLine().getStatusCode(); + assertEquals(204, status); + } + + // conditional PUT once more should fail + { + HttpPut put = new HttpPut(testUri); + put.setHeader("If-Unmodified-Since", lm.getValue()); + put.setEntity(new StringEntity("lazydog")); + HttpResponse response = this.client.execute(put, this.context); + int status = response.getStatusLine().getStatusCode(); + assertEquals(412, status); + } + + // conditional PUT with broken If-Unmodified-Since should pass + { + HttpPut put = new HttpPut(testUri); + put.addHeader("If-Unmodified-Since", lm.getValue()); + put.addHeader("If-Unmodified-Since", "foo"); + put.setEntity(new StringEntity("qux")); + HttpResponse response = this.client.execute(put, this.context); + int status = response.getStatusLine().getStatusCode(); + assertEquals(204, status); + } + } finally { + delete(testUri); + } + } + + public void testGetCollectionEtag() throws IOException, ParseException { + String testUri = this.uri.toString() + (this.uri.toString().endsWith("/") ? "" : "/"); + HttpGet get = new HttpGet(testUri); + HttpResponse response = this.client.execute(get, this.context); + int status = response.getStatusLine().getStatusCode(); + assertEquals(200, status); + Header etag = response.getFirstHeader("etag"); + if (etag != null) { + assertFalse("etag must not be empty", "".equals(etag.getValue())); + } + } +} Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/server/ConditionalsTest.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/server/ContentCodingTest.java =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/server/ContentCodingTest.java (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/server/ContentCodingTest.java (working copy) @@ -0,0 +1,232 @@ +/* + * 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.webdav.server; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Locale; +import java.util.zip.DeflaterOutputStream; +import java.util.zip.GZIPOutputStream; + +import org.apache.http.Header; +import org.apache.http.HttpResponse; +import org.apache.http.client.methods.HttpHead; +import org.apache.http.client.methods.HttpPut; +import org.apache.http.entity.ByteArrayEntity; +import org.apache.http.entity.StringEntity; +import org.apache.http.message.BasicHeader; +import org.apache.jackrabbit.webdav.DavConstants; +import org.apache.jackrabbit.webdav.DavException; +import org.apache.jackrabbit.webdav.MultiStatusResponse; +import org.apache.jackrabbit.webdav.client.methods.HttpPropfind; + +public class ContentCodingTest extends WebDAVTestBase { + + public void testPutNoContentCoding() throws IOException { + String testUri = this.uri.toString() + (this.uri.toString().endsWith("/") ? "" : "/") + "testPutNoContentCoding"; + try { + HttpPut put = new HttpPut(testUri); + put.setEntity(new StringEntity("foobar")); + int status = this.client.execute(put, this.context).getStatusLine().getStatusCode(); + assertEquals(201, status); + } finally { + delete(testUri); + } + } + + public void testPutUnknownContentCoding() throws IOException { + String testUri = this.uri.toString() + (this.uri.toString().endsWith("/") ? "" : "/") + "testPutUnkownContentCoding"; + int status = -1; + try { + HttpPut put = new HttpPut(testUri); + StringEntity entity = new StringEntity("foobarfoobarfoobar"); + entity.setContentEncoding(new BasicHeader("Content-Encoding", "qux")); + put.setEntity(entity); + status = this.client.execute(put, this.context).getStatusLine().getStatusCode(); + assertTrue("server must signal error for unknown content coding, got: " + status, status == 415); + } finally { + if (status / 2 == 100) { + delete(testUri); + } + } + } + + public void testPutGzipContentCoding() throws IOException { + String testUri = this.uri.toString() + (this.uri.toString().endsWith("/") ? "" : "/") + "testPutGzipContentCoding"; + int status = -1; + try { + byte bytes[] = "foobarfoobarfoobar".getBytes("UTF-8"); + HttpPut put = new HttpPut(testUri); + byte gzbytes[] = asGzipOctets(bytes); + assertTrue(gzbytes.length != bytes.length); + ByteArrayEntity entity = new ByteArrayEntity(gzbytes); + entity.setContentEncoding(new BasicHeader("Content-Encoding", "gzip")); + put.setEntity(entity); + status = this.client.execute(put, this.context).getStatusLine().getStatusCode(); + assertTrue("server create or signal error, got: " + status, status == 201 || status == 415); + if (status / 2 == 100) { + // check length + HttpHead head = new HttpHead(testUri); + HttpResponse response = this.client.execute(head, this.context); + assertEquals(200, response.getStatusLine().getStatusCode()); + assertEquals(bytes.length, Integer.parseInt(response.getFirstHeader("Content-Length").getValue())); + } + } finally { + if (status / 2 == 100) { + delete(testUri); + } + } + } + + public void testPropfindNoContentCoding() throws IOException, DavException { + HttpPropfind propfind = new HttpPropfind(uri, DavConstants.PROPFIND_BY_PROPERTY, 0); + HttpResponse response = this.client.execute(propfind, this.context); + int status = response.getStatusLine().getStatusCode(); + assertEquals(207, status); + List encodings = getContentCodings(response); + assertTrue("Accept should list 'gzip' but did not: " + encodings, encodings.contains("gzip")); + assertTrue("Accept should list 'deflate' but did not: " + encodings, encodings.contains("deflate")); + } + + public void testPropfindAcceptReponseEncoding() throws IOException, DavException { + HttpPropfind propfind = new HttpPropfind(uri, DavConstants.PROPFIND_BY_PROPERTY, 0); + propfind.setHeader(new BasicHeader("Accept-Encoding", "gzip;q=0.555")); + HttpResponse response = this.client.execute(propfind, this.context); + int status = response.getStatusLine().getStatusCode(); + assertEquals(207, status); + MultiStatusResponse[] responses = propfind.getResponseBodyAsMultiStatus(response).getResponses(); + assertEquals(1, responses.length); + } + + private static String PF = ""; + + public void testPropfindUnknownContentCoding() throws IOException { + HttpPropfind propfind = new HttpPropfind(uri, DavConstants.PROPFIND_BY_PROPERTY, 0); + StringEntity entity = new StringEntity(PF); + entity.setContentEncoding(new BasicHeader("Content-Encoding", "qux")); + propfind.setEntity(entity); + HttpResponse response = this.client.execute(propfind, this.context); + int status = response.getStatusLine().getStatusCode(); + assertTrue("server must signal error for unknown content coding, got: " + status, status == 415); + List encodings = getContentCodings(response); + assertTrue("Accept should list 'gzip' but did not: " + encodings, encodings.contains("gzip")); + assertTrue("Accept should list 'deflate' but did not: " + encodings, encodings.contains("deflate")); + } + + public void testPropfindGzipContentCoding() throws IOException { + HttpPropfind propfind = new HttpPropfind(uri, DavConstants.PROPFIND_BY_PROPERTY, 0); + ByteArrayEntity entity = new ByteArrayEntity(asGzipOctets(PF)); + entity.setContentEncoding(new BasicHeader("Content-Encoding", "gzip")); + propfind.setEntity(entity); + int status = this.client.execute(propfind, this.context).getStatusLine().getStatusCode(); + assertEquals(207, status); + } + + // double encoded, empty list member in field value, mixed upper/lower in + // coding name + public void testPropfindGzipContentCodingTwice() throws IOException { + HttpPropfind propfind = new HttpPropfind(uri, DavConstants.PROPFIND_BY_PROPERTY, 0); + ByteArrayEntity entity = new ByteArrayEntity(asGzipOctets(asGzipOctets(PF))); + entity.setContentEncoding(new BasicHeader("Content-Encoding", "gziP,, Gzip")); + propfind.setEntity(entity); + int status = this.client.execute(propfind, this.context).getStatusLine().getStatusCode(); + assertEquals(207, status); + } + + // double encoded, but only when encoding in header field + public void testPropfindGzipContentCodingBadSpec() throws IOException { + HttpPropfind propfind = new HttpPropfind(uri, DavConstants.PROPFIND_BY_PROPERTY, 0); + ByteArrayEntity entity = new ByteArrayEntity(asGzipOctets(asGzipOctets(PF))); + entity.setContentEncoding(new BasicHeader("Content-Encoding", "gzip")); + propfind.setEntity(entity); + int status = this.client.execute(propfind, this.context).getStatusLine().getStatusCode(); + assertEquals(400, status); + } + + public void testPropfindDeflateContentCoding() throws IOException { + HttpPropfind propfind = new HttpPropfind(uri, DavConstants.PROPFIND_BY_PROPERTY, 0); + ByteArrayEntity entity = new ByteArrayEntity(asDeflateOctets(PF)); + entity.setContentEncoding(new BasicHeader("Content-Encoding", "deflate")); + propfind.setEntity(entity); + int status = this.client.execute(propfind, this.context).getStatusLine().getStatusCode(); + assertEquals(207, status); + } + + public void testPropfindGzipDeflateContentCoding() throws IOException { + HttpPropfind propfind = new HttpPropfind(uri, DavConstants.PROPFIND_BY_PROPERTY, 0); + ByteArrayEntity entity = new ByteArrayEntity(asDeflateOctets(asGzipOctets(PF))); + entity.setContentEncoding(new BasicHeader("Content-Encoding", "gzip, deflate")); + propfind.setEntity(entity); + int status = this.client.execute(propfind, this.context).getStatusLine().getStatusCode(); + assertEquals(207, status); + } + + public void testPropfindGzipDeflateContentCodingMislabeled() throws IOException { + HttpPropfind propfind = new HttpPropfind(uri, DavConstants.PROPFIND_BY_PROPERTY, 0); + ByteArrayEntity entity = new ByteArrayEntity(asDeflateOctets(asGzipOctets(PF))); + entity.setContentEncoding(new BasicHeader("Content-Encoding", "deflate, gzip")); + propfind.setEntity(entity); + int status = this.client.execute(propfind, this.context).getStatusLine().getStatusCode(); + assertEquals(400, status); + } + + private static byte[] asGzipOctets(String input) throws IOException { + return asGzipOctets(input.getBytes("UTF-8")); + } + + private static byte[] asGzipOctets(byte[] input) throws IOException { + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + OutputStream gos = new GZIPOutputStream(bos); + gos.write(input); + gos.flush(); + gos.close(); + return bos.toByteArray(); + } + + private static byte[] asDeflateOctets(String input) throws IOException { + return asDeflateOctets(input.getBytes("UTF-8")); + } + + private static byte[] asDeflateOctets(byte[] input) throws IOException { + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + OutputStream gos = new DeflaterOutputStream(bos); + gos.write(input); + gos.flush(); + gos.close(); + return bos.toByteArray(); + } + + private static List getContentCodings(HttpResponse response) { + List result = Collections.emptyList(); + for (Header l : response.getHeaders("Accept-Encoding")) { + for (String h : l.getValue().split(",")) { + if (!h.trim().isEmpty()) { + if (result.isEmpty()) { + result = new ArrayList(); + } + result.add(h.trim().toLowerCase(Locale.ENGLISH)); + } + } + } + + return result; + } +} Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/server/ContentCodingTest.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/server/HttpsSelfSignedTest.java =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/server/HttpsSelfSignedTest.java (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/server/HttpsSelfSignedTest.java (working copy) @@ -0,0 +1,42 @@ +/* + * 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.webdav.server; + +import java.io.IOException; +import java.text.ParseException; + +import javax.net.ssl.SSLHandshakeException; + +import org.apache.http.HttpResponse; +import org.apache.http.client.methods.HttpPut; +import org.apache.http.entity.StringEntity; + +public class HttpsSelfSignedTest extends WebDAVTestBase { + + // check that by default, the client will fail connecting to HTTPS due to + // self-signed certificate + public void testPutCheckLastModified() throws IOException, ParseException { + try { + String testUri = this.httpsUri.toString(); + HttpPut put = new HttpPut(testUri); + put.setEntity(new StringEntity("foobar")); + HttpResponse response = this.client.execute(put, this.context); + fail("should failt with SSLHandshakeException, but got: " + response); + } catch (SSLHandshakeException expected) { + } + } +} Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/server/HttpsSelfSignedTest.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/server/ProppatchTest.java =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/server/ProppatchTest.java (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/server/ProppatchTest.java (working copy) @@ -0,0 +1,79 @@ +/* + * 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.webdav.server; + +import java.io.IOException; + +import org.apache.http.HttpResponse; +import org.apache.http.client.methods.HttpPut; +import org.apache.http.entity.StringEntity; +import org.apache.http.util.EntityUtils; +import org.apache.jackrabbit.webdav.DavException; +import org.apache.jackrabbit.webdav.MultiStatusResponse; +import org.apache.jackrabbit.webdav.client.methods.HttpPropfind; +import org.apache.jackrabbit.webdav.client.methods.HttpProppatch; +import org.apache.jackrabbit.webdav.property.DavProperty; +import org.apache.jackrabbit.webdav.property.DavPropertyName; +import org.apache.jackrabbit.webdav.property.DavPropertyNameSet; +import org.apache.jackrabbit.webdav.property.DavPropertySet; +import org.apache.jackrabbit.webdav.property.DefaultDavProperty; +import org.apache.jackrabbit.webdav.xml.Namespace; + +public class ProppatchTest extends WebDAVTestBase { + + public void testPropPatchSurrogate() throws IOException, DavException { + + String testuri = this.root + "ppsurrogate"; + + try { + int status; + + HttpPut put = new HttpPut(testuri); + put.setEntity(new StringEntity("1")); + status = this.client.execute(put, this.context).getStatusLine().getStatusCode(); + assertEquals("status: " + status, 201, status); + + DavPropertyName name = DavPropertyName.create("foobar", Namespace.EMPTY_NAMESPACE); + DavPropertySet props = new DavPropertySet(); + DavProperty foobar = new DefaultDavProperty<>(name, "\uD83D\uDCA9"); + props.add(foobar); + HttpProppatch proppatch = new HttpProppatch(testuri, props, new DavPropertyNameSet()); + HttpResponse resp = this.client.execute(proppatch, this.context); + status = resp.getStatusLine().getStatusCode(); + assertEquals(207, status); + EntityUtils.consume(resp.getEntity()); + + DavPropertyNameSet names = new DavPropertyNameSet(); + names.add(name); + HttpPropfind propfind = new HttpPropfind(testuri, names, 0); + resp = this.client.execute(propfind, this.context); + status = resp.getStatusLine().getStatusCode(); + assertEquals(207, status); + MultiStatusResponse[] responses = propfind.getResponseBodyAsMultiStatus(resp).getResponses(); + assertEquals(1, responses.length); + + MultiStatusResponse response = responses[0]; + DavPropertySet found = response.getProperties(200); + + DavProperty f = found.get(name); + assertEquals("\uD83D\uDCA9", f.getValue()); + } finally { + delete(testuri); + } + } + +} Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/server/ProppatchTest.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/server/PutTest.java =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/server/PutTest.java (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/server/PutTest.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.webdav.server; + +import java.io.IOException; +import java.text.ParseException; + +import org.apache.http.HttpResponse; +import org.apache.http.client.methods.HttpPut; +import org.apache.http.entity.StringEntity; + +/** + * Test cases for HTTP PUT method + */ +public class PutTest extends WebDAVTestBase { + + public void testPutWithContentRange() throws IOException, ParseException { + String testUri = this.uri.toString() + (this.uri.toString().endsWith("/") ? "" : "/") + "testPutWithContentRange"; + HttpPut put = new HttpPut(testUri); + put.addHeader("Content-Range", "bytes 0-5/6"); + put.setEntity(new StringEntity("foobar")); + HttpResponse response = this.client.execute(put, this.context); + int status = response.getStatusLine().getStatusCode(); + assertEquals(400, status); + } +} Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/server/PutTest.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/server/RFC4918DestinationHeaderTest.java =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/server/RFC4918DestinationHeaderTest.java (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/server/RFC4918DestinationHeaderTest.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.webdav.server; + +import java.io.IOException; +import java.net.URI; +import java.net.URISyntaxException; + +import org.apache.http.client.methods.HttpDelete; +import org.apache.http.client.methods.HttpHead; +import org.apache.http.client.methods.HttpPut; +import org.apache.http.client.methods.HttpRequestBase; +import org.apache.jackrabbit.webdav.client.methods.HttpMove; + +/** + * Test cases for RFC 4918 Destination header functionality + * (see RFC 4918, Section 10.3 + */ +public class RFC4918DestinationHeaderTest extends WebDAVTestBase { + + public void testMove() throws IOException, URISyntaxException { + + String testuri = this.root + "movetest"; + String destinationuri = testuri + "2"; + String destinationpath = new URI(destinationuri).getRawPath(); + // make sure the scheme is removed + assertFalse(destinationpath.contains(":")); + + HttpRequestBase requestBase = null; + try { + requestBase = new HttpPut(testuri); + int status = this.client.execute(requestBase, this.context).getStatusLine().getStatusCode(); + assertTrue("status: " + status, status == 200 || status == 201 || status == 204); + requestBase.releaseConnection(); + + // try to move outside the servlet's name space + requestBase = new HttpMove(testuri, "/foobar", true); + status = this.client.execute(requestBase, this.context).getStatusLine().getStatusCode(); + assertTrue("status: " + status, status == 502); + requestBase.releaseConnection(); + + // try a relative path + requestBase = new HttpMove(testuri, "foobar", true); + status = this.client.execute(requestBase, this.context).getStatusLine().getStatusCode(); + assertTrue("status: " + status, status == 400); + requestBase.releaseConnection(); + + requestBase = new HttpMove(testuri, destinationpath, true); + status = this.client.execute(requestBase, this.context).getStatusLine().getStatusCode(); + assertTrue("status: " + status, status == 200 || status == 201 || status == 204); + requestBase.releaseConnection(); + + requestBase = new HttpHead(destinationuri); + status = this.client.execute(requestBase, this.context).getStatusLine().getStatusCode(); + assertTrue("status: " + status, status == 200); + requestBase.releaseConnection(); + + requestBase = new HttpHead(testuri); + status = this.client.execute(requestBase, this.context).getStatusLine().getStatusCode(); + assertTrue("status: " + status, status == 404); + } finally { + requestBase.releaseConnection(); + requestBase = new HttpDelete(testuri); + int status = this.client.execute(requestBase, this.context).getStatusLine().getStatusCode(); + assertTrue("status: " + status, status == 200 || status == 204 || status == 404); + requestBase.releaseConnection(); + requestBase = new HttpDelete(destinationuri); + status = this.client.execute(requestBase, this.context).getStatusLine().getStatusCode(); + assertTrue("status: " + status, status == 200 || status == 204 || status == 404); + requestBase.releaseConnection(); + } + } +} Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/server/RFC4918DestinationHeaderTest.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/server/RFC4918IfHeaderTest.java =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/server/RFC4918IfHeaderTest.java (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/server/RFC4918IfHeaderTest.java (working copy) @@ -0,0 +1,143 @@ +/* + * 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.webdav.server; + +import java.io.IOException; +import java.net.URI; +import java.net.URISyntaxException; + +import org.apache.http.HttpResponse; +import org.apache.http.client.methods.HttpDelete; +import org.apache.http.client.methods.HttpPut; +import org.apache.http.client.methods.HttpRequestBase; +import org.apache.http.entity.StringEntity; +import org.apache.jackrabbit.webdav.client.methods.HttpLock; +import org.apache.jackrabbit.webdav.lock.LockInfo; +import org.apache.jackrabbit.webdav.lock.Scope; +import org.apache.jackrabbit.webdav.lock.Type; + +/** + * Test cases for RFC 4918 If header functionality + * (see RFC 4918, Section 10.4 + */ + +public class RFC4918IfHeaderTest extends WebDAVTestBase { + + public void testPutIfEtag() throws IOException { + + String testuri = this.root + "iftest"; + HttpPut put = new HttpPut(testuri); + try { + put = new HttpPut(testuri); + String condition = "<" + testuri + "> ([" + "\"an-etag-this-testcase-invented\"" + "])"; + put.setEntity(new StringEntity("1")); + put.setHeader("If", condition); + int status = this.client.execute(put, this.context).getStatusLine().getStatusCode(); + assertEquals("status: " + status, 412, status); + put.releaseConnection(); + + } + finally { + put.releaseConnection(); + HttpDelete delete = new HttpDelete(testuri); + int status = this.client.execute(delete, this.context).getStatusLine().getStatusCode(); + assertTrue("status: " + status, status == 200 || status == 204 || status == 404); + delete.releaseConnection(); + } + } + + public void testPutIfLockToken() throws IOException, URISyntaxException { + + String testuri = this.root + "iflocktest"; + String locktoken = null; + + HttpRequestBase requestBase = null; + try { + requestBase = new HttpPut(testuri); + ((HttpPut)requestBase).setEntity(new StringEntity("1")); + int status = this.client.execute(requestBase, this.context).getStatusLine().getStatusCode(); + assertTrue("status: " + status, status == 200 || status == 201 || status == 204); + requestBase.releaseConnection(); + + requestBase = new HttpLock(testuri, new LockInfo( + Scope.EXCLUSIVE, Type.WRITE, "testcase", 10000, true)); + HttpResponse response = this.client.execute(requestBase, this.context); + status = response.getStatusLine().getStatusCode(); + assertEquals("status", 200, status); + locktoken = ((HttpLock)requestBase).getLockToken(response); + assertNotNull(locktoken); + requestBase.releaseConnection(); + + // try to overwrite without lock token + requestBase = new HttpPut(testuri); + ((HttpPut)requestBase).setEntity(new StringEntity("2")); + status = this.client.execute(requestBase, this.context).getStatusLine().getStatusCode(); + assertEquals("status: " + status, 423, status); + requestBase.releaseConnection(); + + // try to overwrite using bad lock token + requestBase = new HttpPut(testuri); + ((HttpPut)requestBase).setEntity(new StringEntity("2")); + requestBase.setHeader("If", "(<" + "DAV:foobar" + ">)"); + status = this.client.execute(requestBase, this.context).getStatusLine().getStatusCode(); + assertEquals("status: " + status, 412, status); + requestBase.releaseConnection(); + + // try to overwrite using correct lock token, using No-Tag-list format + requestBase = new HttpPut(testuri); + ((HttpPut)requestBase).setEntity(new StringEntity("2")); + requestBase.setHeader("If", "(<" + locktoken + ">)"); + status = this.client.execute(requestBase, this.context).getStatusLine().getStatusCode(); + assertTrue("status: " + status, status == 200 || status == 204); + requestBase.releaseConnection(); + + // try to overwrite using correct lock token, using Tagged-list format + // and full URI + requestBase = new HttpPut(testuri); + ((HttpPut)requestBase).setEntity(new StringEntity("3")); + requestBase.setHeader("If", "<" + testuri + ">" + "(<" + locktoken + ">)"); + status = this.client.execute(requestBase, this.context).getStatusLine().getStatusCode(); + assertTrue("status: " + status, status == 200 || status == 204); + requestBase.releaseConnection(); + + // try to overwrite using correct lock token, using Tagged-list format + // and absolute path only + requestBase = new HttpPut(testuri); + ((HttpPut)requestBase).setEntity(new StringEntity("4")); + requestBase.setHeader("If", "<" + new URI(testuri).getRawPath() + ">" + "(<" + locktoken + ">)"); + status = this.client.execute(requestBase, this.context).getStatusLine().getStatusCode(); + assertTrue("status: " + status, status == 200 || status == 204); + requestBase.releaseConnection(); + + // try to overwrite using correct lock token, using Tagged-list format + // and bad path + requestBase = new HttpPut(testuri); + ((HttpPut)requestBase).setEntity(new StringEntity("5")); + requestBase.setHeader("If", "" + "(<" + locktoken + ">)"); + status = this.client.execute(requestBase, this.context).getStatusLine().getStatusCode(); + assertTrue("status: " + status, status == 404 || status == 412); + } finally { + requestBase.releaseConnection(); + requestBase = new HttpDelete(testuri); + if (locktoken != null) { + requestBase.setHeader("If", "(<" + locktoken + ">)"); + } + int status = this.client.execute(requestBase, this.context).getStatusLine().getStatusCode(); + assertTrue("status: " + status, status == 200 || status == 204 || status == 404); + } + } +} Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/server/RFC4918IfHeaderTest.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/server/RFC4918PropfindTest.java =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/server/RFC4918PropfindTest.java (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/server/RFC4918PropfindTest.java (working copy) @@ -0,0 +1,78 @@ +/* + * 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.webdav.server; + +import java.io.IOException; + +import org.apache.http.HttpResponse; +import org.apache.http.client.methods.HttpPut; +import org.apache.http.entity.StringEntity; +import org.apache.jackrabbit.webdav.DavConstants; +import org.apache.jackrabbit.webdav.DavException; +import org.apache.jackrabbit.webdav.MultiStatus; +import org.apache.jackrabbit.webdav.MultiStatusResponse; +import org.apache.jackrabbit.webdav.client.methods.HttpOptions; +import org.apache.jackrabbit.webdav.client.methods.HttpPropfind; +import org.apache.jackrabbit.webdav.property.DavPropertyNameSet; +import org.apache.jackrabbit.webdav.property.DavPropertySet; +import org.apache.jackrabbit.webdav.version.DeltaVConstants; + +/** + * Test cases for RFC 4918 PROPFIND functionality + * (see RFC 4918, Section 9.1 + */ + +public class RFC4918PropfindTest extends WebDAVTestBase { + + public void testOptions() throws IOException { + HttpOptions options = new HttpOptions(this.root); + HttpResponse response = this.client.execute(options, this.context); + assertTrue(options.getDavComplianceClasses(response).contains("3")); + } + + public void testPropfindInclude() throws IOException, DavException { + + String testuri = this.root + "iftest"; + + int status; + try { + HttpPut put = new HttpPut(testuri); + put.setEntity(new StringEntity("1")); + status = this.client.execute(put, this.context).getStatusLine().getStatusCode(); + assertEquals("status: " + status, 201, status); + + DavPropertyNameSet names = new DavPropertyNameSet(); + names.add(DeltaVConstants.COMMENT); + HttpPropfind propfind = new HttpPropfind(testuri, DavConstants.PROPFIND_ALL_PROP_INCLUDE, names, 0); + HttpResponse resp = this.client.execute(propfind, this.context); + status = resp.getStatusLine().getStatusCode(); + assertEquals(207, status); + + MultiStatus multistatus = propfind.getResponseBodyAsMultiStatus(resp); + MultiStatusResponse[] responses = multistatus.getResponses(); + assertEquals(1, responses.length); + + MultiStatusResponse response = responses[0]; + DavPropertySet found = response.getProperties(200); + DavPropertySet notfound = response.getProperties(404); + + assertTrue(found.contains(DeltaVConstants.COMMENT) || notfound.contains(DeltaVConstants.COMMENT)); + } finally { + delete(testuri); + } + } +} Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/server/RFC4918PropfindTest.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/server/RemotingTest.java =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/server/RemotingTest.java (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/server/RemotingTest.java (working copy) @@ -0,0 +1,60 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.jackrabbit.webdav.server; + +import java.io.IOException; + +import org.apache.http.HttpResponse; +import org.apache.jackrabbit.webdav.DavConstants; +import org.apache.jackrabbit.webdav.DavException; +import org.apache.jackrabbit.webdav.MultiStatus; +import org.apache.jackrabbit.webdav.MultiStatusResponse; +import org.apache.jackrabbit.webdav.client.methods.HttpPropfind; +import org.apache.jackrabbit.webdav.observation.ObservationConstants; +import org.apache.jackrabbit.webdav.property.DavProperty; +import org.apache.jackrabbit.webdav.property.DavPropertyName; +import org.apache.jackrabbit.webdav.property.DavPropertyNameSet; +import org.apache.jackrabbit.webdav.property.DavPropertySet; +import org.apache.jackrabbit.webdav.xml.DomUtil; +import org.w3c.dom.Element; + +public class RemotingTest extends WebDAVTestBase { + + // simple test the verifies that we are indeed talking to the remoting + // servlet + public void testRoot() throws IOException, DavException { + String testuri = this.remotingUri.toASCIIString() + "default/jcr:root"; + DavPropertyName pntn = DavPropertyName.create("primarynodetype", ObservationConstants.NAMESPACE); + DavPropertyNameSet names = new DavPropertyNameSet(); + names.add(pntn); + + HttpPropfind propfind = new HttpPropfind(testuri, DavConstants.PROPFIND_BY_PROPERTY, names, 0); + HttpResponse resp = this.client.execute(propfind, this.context); + int status = resp.getStatusLine().getStatusCode(); + assertEquals(207, status); + + MultiStatus multistatus = propfind.getResponseBodyAsMultiStatus(resp); + MultiStatusResponse[] responses = multistatus.getResponses(); + assertEquals(1, responses.length); + + MultiStatusResponse response = responses[0]; + DavPropertySet found = response.getProperties(200); + DavProperty pnt = found.get(pntn); + Element el = (Element) pnt.getValue(); + assertEquals("rep:root", DomUtil.getText((Element) (el.getFirstChild()))); + } +} Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/server/RemotingTest.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/server/WebDAVTestBase.java =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/server/WebDAVTestBase.java (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/server/WebDAVTestBase.java (working copy) @@ -0,0 +1,238 @@ +/* + * 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.webdav.server; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.URI; + +import javax.jcr.Repository; +import javax.servlet.ServletException; + +import org.apache.commons.io.IOUtils; +import org.apache.http.HttpHost; +import org.apache.http.auth.AuthScope; +import org.apache.http.auth.UsernamePasswordCredentials; +import org.apache.http.client.AuthCache; +import org.apache.http.client.CredentialsProvider; +import org.apache.http.client.HttpClient; +import org.apache.http.client.methods.HttpDelete; +import org.apache.http.client.protocol.HttpClientContext; +import org.apache.http.impl.auth.BasicScheme; +import org.apache.http.impl.client.BasicAuthCache; +import org.apache.http.impl.client.BasicCredentialsProvider; +import org.apache.http.impl.client.HttpClients; +import org.apache.http.impl.conn.PoolingHttpClientConnectionManager; +import org.apache.jackrabbit.core.RepositoryContext; +import org.apache.jackrabbit.core.config.RepositoryConfig; +import org.apache.jackrabbit.server.remoting.davex.JcrRemotingServlet; +import org.apache.jackrabbit.test.AbstractJCRTest; +import org.apache.jackrabbit.test.RepositoryStubException; +import org.apache.jackrabbit.webdav.simple.SimpleWebdavServlet; +import org.eclipse.jetty.http.HttpVersion; +import org.eclipse.jetty.server.HttpConfiguration; +import org.eclipse.jetty.server.HttpConnectionFactory; +import org.eclipse.jetty.server.Server; +import org.eclipse.jetty.server.ServerConnector; +import org.eclipse.jetty.server.SslConnectionFactory; +import org.eclipse.jetty.servlet.ServletContextHandler; +import org.eclipse.jetty.servlet.ServletHolder; +import org.eclipse.jetty.util.resource.Resource; +import org.eclipse.jetty.util.ssl.SslContextFactory; + +import junit.framework.TestResult; + +/** + * Base class for WebDAV tests. + */ +public class WebDAVTestBase extends AbstractJCRTest { + + private static final String SIMPLE_WEBDAV_SERVLET_PATH_MAPPING = "/*"; + private static final String REMOTING_PREFIX = "/remoting"; + private static final String REMOTING_WEBDAV_SERVLET_PATH_MAPPING = REMOTING_PREFIX + "/*"; + + private static ServerConnector httpConnector; + private static ServerConnector httpsConnector; + private static Server server; + private static RepositoryContext repoContext; + + public URI uri; + public URI httpsUri; + public String root; + + // URI for remoting servlet, does not include workspace name + public URI remotingUri; + + public HttpClient client; + public HttpClientContext context; + + private static final String KEYSTORE = "keystore"; + private static final String KEYSTOREPW = "geheimer"; + + protected void setUp() throws Exception { + super.setUp(); + + File home = new File("target/jackrabbit-repository"); + if (!home.exists()) { + home.mkdirs(); + } + + File config = new File(home, "repository.xml"); + if (!config.exists()) { + createDefaultConfiguration(config); + } + + File keystore = new File(home, KEYSTORE); + if (!keystore.exists()) { + createKeystore(keystore); + } + + if (repoContext == null) { + repoContext = RepositoryContext.create(RepositoryConfig.create(config.toURI(), home.getPath())); + } + + if (server == null) { + server = new Server(); + + ServletHolder simple = new ServletHolder(new SimpleWebdavServlet() { + private static final long serialVersionUID = 8638589328461138178L; + + public Repository getRepository() { + return repoContext.getRepository(); + } + }); + simple.setInitParameter(SimpleWebdavServlet.INIT_PARAM_RESOURCE_CONFIG, "/config.xml"); + + ServletHolder remoting = new ServletHolder(new JcrRemotingServlet() { + private static final long serialVersionUID = -2969534124090379387L; + + public Repository getRepository() { + return repoContext.getRepository(); + } + }); + remoting.setInitParameter(JcrRemotingServlet.INIT_PARAM_RESOURCE_PATH_PREFIX, "/remoting"); + + ServletContextHandler schandler = new ServletContextHandler(server, "/"); + schandler.addServlet(simple, SIMPLE_WEBDAV_SERVLET_PATH_MAPPING); + schandler.addServlet(remoting, REMOTING_WEBDAV_SERVLET_PATH_MAPPING); + schandler.setBaseResource(Resource.newClassPathResource("/")); + + server.setHandler(schandler); + } + + if (httpConnector == null) { + httpConnector = new ServerConnector(server); + httpConnector.setHost("localhost"); + httpConnector.setPort(0); + server.addConnector(httpConnector); + } + + if (httpsConnector == null) { + SslContextFactory sslContextFactory = new SslContextFactory(); + sslContextFactory.setKeyStorePath(keystore.getPath()); + sslContextFactory.setKeyStorePassword(KEYSTOREPW); + sslContextFactory.setKeyManagerPassword(KEYSTOREPW); + sslContextFactory.setTrustStorePath(keystore.getPath()); + sslContextFactory.setTrustStorePassword(KEYSTOREPW); + SslConnectionFactory cfac = new SslConnectionFactory(sslContextFactory, HttpVersion.HTTP_1_1.asString()); + httpsConnector = new ServerConnector(server, cfac, new HttpConnectionFactory(new HttpConfiguration())); + httpsConnector.setHost("localhost"); + httpsConnector.setPort(0); + server.addConnector(httpsConnector); + } + + if (!server.isStarted()) { + try { + server.start(); + } catch (Exception e) { + throw new RepositoryStubException(e); + } + } + + this.uri = new URI("http", null, "localhost", httpConnector.getLocalPort(), "/default/", null, null); + this.remotingUri = new URI("http", null, "localhost", httpConnector.getLocalPort(), REMOTING_PREFIX + "/", null, null); + this.httpsUri = new URI("https", null, "localhost", httpsConnector.getLocalPort(), "/default/", null, null); + this.root = this.uri.toASCIIString(); + + PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager(); + //cm.setMaxTotal(100); + HttpHost targetHost = new HttpHost(uri.getHost(), uri.getPort()); + + CredentialsProvider credsProvider = new BasicCredentialsProvider(); + credsProvider.setCredentials( + new AuthScope(targetHost.getHostName(), targetHost.getPort()), + new UsernamePasswordCredentials("admin", "admin")); + + AuthCache authCache = new BasicAuthCache(); + // Generate BASIC scheme object and add it to the local auth cache + BasicScheme basicAuth = new BasicScheme(); + authCache.put(targetHost, basicAuth); + + // Add AuthCache to the execution context + this.context = HttpClientContext.create(); + this.context.setCredentialsProvider(credsProvider); + this.context.setAuthCache(authCache); + + this.client = HttpClients.custom().setConnectionManager(cm).build(); + + super.setUp(); + } + + protected void delete(String uri) throws IOException { + HttpDelete delete = new HttpDelete(uri); + int status = this.client.execute(delete, this.context).getStatusLine().getStatusCode(); + assertTrue("status: " + status, status == 200 || status == 204); + } + + public static Server getServer() { + return server; + } + + /** + * 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); + InputStream input = WebDAVTestBase.class.getResourceAsStream("/repository.xml")) { + IOUtils.copy(input, output); + } catch (IOException e) { + throw new ServletException("Failed to copy default configuration: " + config, e); + } + } + + private void createKeystore(File keystore) throws ServletException { + try (OutputStream output = new FileOutputStream(keystore); + InputStream input = WebDAVTestBase.class.getResourceAsStream("/" + KEYSTORE)) { + IOUtils.copy(input, output); + } catch (IOException e) { + throw new ServletException("Failed to copy keystore: " + keystore, e); + } + } + + @Override + public void run(TestResult testResult) { + if (Boolean.getBoolean("jackrabbit.test.integration")) { + super.run(testResult); + } + } +} Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/server/WebDAVTestBase.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/simple/LitmusTest.java =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/simple/LitmusTest.java (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/simple/LitmusTest.java (working copy) @@ -0,0 +1,130 @@ +/* + * 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.webdav.simple; + +import java.io.ByteArrayOutputStream; +import java.io.File; + +import javax.jcr.Repository; +import javax.jcr.Session; + +import junit.framework.TestCase; + +import org.apache.commons.io.IOUtils; +import org.apache.jackrabbit.commons.JcrUtils; +import org.apache.jackrabbit.util.Text; +import org.eclipse.jetty.server.Server; +import org.eclipse.jetty.server.ServerConnector; +import org.eclipse.jetty.servlet.ServletContextHandler; +import org.eclipse.jetty.servlet.ServletHolder; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class LitmusTest extends TestCase { + + /** + * Logger instance. + */ + private static final Logger log = LoggerFactory.getLogger(LitmusTest.class); + + public void testLitmus() throws Exception { + File dir = new File("target", "litmus"); + String litmus = System.getProperty("litmus", "litmus"); + + if (Boolean.getBoolean("jackrabbit.test.integration") + && isLitmusAvailable(litmus)) { + final Repository repository = JcrUtils.getRepository( + "jcr-jackrabbit://" + Text.escapePath(dir.getCanonicalPath())); + Session session = repository.login(); // for the TransientRepository + try { + Server server = new Server(); + + ServerConnector connector = new ServerConnector(server); + connector.setHost("localhost"); + connector.setPort(Integer.getInteger("litmus.port", 0)); + + server.addConnector(connector); + + ServletHolder holder = new ServletHolder( + new SimpleWebdavServlet() { + @Override + public Repository getRepository() { + return repository; + } + }); + holder.setInitParameter("resource-config", "/config.xml"); + + ServletContextHandler schandler = new ServletContextHandler(server, "/"); + schandler.addServlet(holder, "/*"); + + server.start(); + try { + int port = connector.getLocalPort(); + String url = "http://localhost:" + port + "/default"; + + ProcessBuilder builder = + new ProcessBuilder(litmus, url, "admin", "admin"); + builder.directory(dir); + builder.redirectErrorStream(); + + assertLitmus(builder, "basic", 0); + + assertLitmus(builder, "http", 0); + + assertLitmus(builder, "props", 0); + + // FIXME: JCR-2637: WebDAV shallow copy test failure + assertLitmus(builder, "copymove", 1); + + // FIXME: JCR-2638: Litmus locks test failures + assertLitmus(builder, "locks", 1); + } finally { + server.stop(); + } + } finally { + session.logout(); + } + } + } + + private void assertLitmus( + ProcessBuilder builder, String tests, int exit) throws Exception { + builder.environment().put("TESTS", tests); + Process process = builder.start(); + IOUtils.copy(process.getInputStream(), System.out); + assertEquals(exit, process.waitFor()); + } + + private static boolean isLitmusAvailable(String litmus) { + try { + ProcessBuilder builder = new ProcessBuilder(litmus, "--version"); + builder.redirectErrorStream(); + Process process = builder.start(); + + ByteArrayOutputStream buffer = new ByteArrayOutputStream(); + IOUtils.copy(process.getInputStream(), buffer); + int rv = process.waitFor(); + log.info("litmus version: {}", buffer.toString("US-ASCII").trim()); + + return rv == 0; + } catch (Exception e) { + log.warn("litmus is not available: " + litmus, e); + return false; + } + } + +} Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/simple/LitmusTest.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/simple/LocatorFactoryImplExTest.java =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/simple/LocatorFactoryImplExTest.java (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/simple/LocatorFactoryImplExTest.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.webdav.simple; + +import junit.framework.TestCase; +import org.apache.jackrabbit.webdav.DavLocatorFactory; +import org.apache.jackrabbit.webdav.DavResourceLocator; + +/** LocatorFactoryImplExTest... */ +public class LocatorFactoryImplExTest extends TestCase { + + private DavLocatorFactory factory; + + @Override + protected void setUp() throws Exception { + super.setUp(); + // for simplicity (not yet used) ignore the path prefix. + factory = new LocatorFactoryImplEx(null); + } + + /** + * Test for issue https://issues.apache.org/jira/browse/JCR-1679: An top + * level resource (node directly below the root) whose name equals the + * workspace name results in wrong collection behaviour (garbeled locator + * of child resources). + */ + public void testCollectionNameEqualsWorkspaceName() { + String prefix = "http://localhost:8080/jackrabbit/repository"; + String workspacePath = "/default"; + String nodePath = "/default/another"; + + DavResourceLocator locator = factory.createResourceLocator(prefix, workspacePath, nodePath, false); + assertTrue(locator.getHref(true).indexOf("/default/default") > 0); + + DavResourceLocator locator2 = factory.createResourceLocator(locator.getPrefix(), locator.getWorkspacePath(), locator.getResourcePath()); + assertEquals(locator, locator2); + assertEquals(nodePath, locator2.getRepositoryPath()); + } +} Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/simple/LocatorFactoryImplExTest.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/test/java/org/apache/jackrabbit/webdav/simple/ResourceConfigTest.java =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/simple/ResourceConfigTest.java (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/simple/ResourceConfigTest.java (working copy) @@ -0,0 +1,114 @@ +/* + * 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.webdav.simple; + +import junit.framework.TestCase; +import org.apache.jackrabbit.server.io.DefaultHandler; +import org.apache.jackrabbit.server.io.IOHandler; +import org.apache.jackrabbit.server.io.IOManager; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.ByteArrayInputStream; +import java.io.InputStream; + +/** + * ResourceConfigTest... + */ +public class ResourceConfigTest extends TestCase { + + /** + * logger instance + */ + private static final Logger log = LoggerFactory.getLogger(ResourceConfigTest.class); + + public void testIOManagerConfig() throws Exception { + InputStream in = new ByteArrayInputStream(CONFIG_1.getBytes("UTF-8")); + + ResourceConfig config = new ResourceConfig(null); + config.parse(in); + + IOManager ioMgr = config.getIOManager(); + assertNotNull(ioMgr); + assertEquals("org.apache.jackrabbit.server.io.IOManagerImpl", ioMgr.getClass().getName()); + + IOHandler[] handlers = ioMgr.getIOHandlers(); + assertNotNull(handlers); + assertEquals(1, handlers.length); + assertEquals("org.apache.jackrabbit.server.io.DefaultHandler", handlers[0].getName()); + } + + public void testIOManagerConfigWithParam() throws Exception { + InputStream in = new ByteArrayInputStream(CONFIG_2.getBytes("UTF-8")); + + ResourceConfig config = new ResourceConfig(null); + config.parse(in); + + IOManager ioMgr = config.getIOManager(); + assertNotNull(ioMgr); + assertEquals("org.apache.jackrabbit.server.io.IOManagerImpl", ioMgr.getClass().getName()); + + IOHandler[] handlers = ioMgr.getIOHandlers(); + assertNotNull(handlers); + assertEquals(1, handlers.length); + assertEquals("org.apache.jackrabbit.server.io.DefaultHandler", handlers[0].getName()); + DefaultHandler dh = (DefaultHandler) handlers[0]; + assertEquals("nt:unstructured", dh.getCollectionNodeType()); + assertEquals("nt:unstructured", dh.getNodeType()); + assertEquals("nt:resource", dh.getContentNodeType()); + } + + + private static final String CONFIG_1 = "\n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " " + + ""; + + private static final String CONFIG_2 = "\n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " " + + ""; +} \ No newline at end of file Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/simple/ResourceConfigTest.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/test/resources/config.xml =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/resources/config.xml (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/resources/config.xml (working copy) @@ -0,0 +1,184 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + nt:file + nt:resource + + + + + + + + + + + + + rep + jcr + + + + + + Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/resources/config.xml ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/resources/keystore =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/resources/keystore ___________________________________________________________________ Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/resources/logback-test.xml =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/resources/logback-test.xml (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/resources/logback-test.xml (working copy) @@ -0,0 +1,31 @@ + + + + + + target/jcr.log + + %date{HH:mm:ss.SSS} %-5level %-40([%thread] %F:%L) %msg%n + + + + + + + + Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/resources/logback-test.xml ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/resources/protectedHandlers.properties =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/resources/protectedHandlers.properties (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/resources/protectedHandlers.properties (working copy) @@ -0,0 +1,17 @@ +# 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. + +# ProtectedItemRemoveHandler implementation class +javax.jcr.tck.access.control.list.handler=org.apache.jackrabbit.server.remoting.davex.AclRemoveHandler Index: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/resources/protectedHandlersConfig.xml =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/resources/protectedHandlersConfig.xml (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/resources/protectedHandlersConfig.xml (working copy) @@ -0,0 +1,26 @@ + + + + + + + + Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/resources/protectedHandlersConfig.xml ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/resources/repository.xml =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/resources/repository.xml (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/resources/repository.xml (working copy) @@ -0,0 +1,166 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/resources/repository.xml ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/resources/repositoryStubImpl.properties =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/resources/repositoryStubImpl.properties (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/resources/repositoryStubImpl.properties (working copy) @@ -0,0 +1,23 @@ +# 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. + +# Stub implementation class +javax.jcr.tck.repository_stub_impl=org.apache.jackrabbit.core.JackrabbitRepositoryStub + +# the repository home +org.apache.jackrabbit.repository.home=target/repository + +# the repository configuration +org.apache.jackrabbit.repository.config=target/test-classes/repository.xml Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server/src/test/resources/repositoryStubImpl.properties ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-jcr-server-project/jackrabbit-jcr-server =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server (working copy) Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server ___________________________________________________________________ Added: svn:ignore ## -0,0 +1,5 ## +*.iml +*.ipr +*.iws +target +.* Index: jackrabbit-webdav-project/jackrabbit-webdav-jakarta/pom.xml =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav-jakarta/pom.xml (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav-jakarta/pom.xml (working copy) @@ -0,0 +1,83 @@ + + 4.0.0 + + org.apache.jackrabbit + jackrabbit-webdav-project + 2.21.16-SNAPSHOT + + jackrabbit-webdav-jakarta + + + + org.eclipse.transformer + transformer-maven-plugin + 0.5.0 + true + + + true + + + + + default-jar + + jar + + + + org.apache.jackrabbit + jackrabbit-webdav + ${project.version} + + + + + + + + + + apache-release + + + + org.eclipse.transformer + transformer-maven-plugin + 0.5.0 + true + + + true + + + + + source-jar + + jar + + + + org.apache.jackrabbit + jackrabbit-webdav + ${project.version} + sources + + + + + + + + + + + + jakarta.servlet + jakarta.servlet-api + 5.0.0 + provided + + + \ No newline at end of file Index: jackrabbit-webdav/README.txt =================================================================== --- jackrabbit-webdav/README.txt (revision 1907912) +++ jackrabbit-webdav/README.txt (nonexistent) @@ -1,81 +0,0 @@ -==================================== -Welcome to Jackrabbit WebDAV Library -==================================== - -This is the WebDAV Library component of the Apache Jackrabbit project. -This component provides interfaces and common utility classes used for -building a WebDAV server or client. The following RFC have been integrated: - - * RFC 2518 (WebDAV - HTTP Extensions for Distributed Authoring) - * RFC 3253 (DeltaV - Versioning Extensions to WebDAV) - * RFC 3648 (Ordered Collections Protocol) - * RFC 3744 (Access Control Protocol) - * DAV Searching and Locating (DASL) - * Binding Extensions to Web Distributed Authoring and Versioning (WebDAV) (experimental) - -In addition this library defines (unspecified) - - * Observation - * Bundling multiple request with extensions to locking - -Common Questions -================ - -Q: Which WebDAV features are supported? -A: DAV 1, 2, DeltaV, Ordering, Access Control, Search, Bind - -Q: This this WebDAV library provide a full dav server? -A: This library only defines interfaces, utilities and common - classes used for a dav server/client. - A JCR specific implementation can be found in the 'jcr-server' - and the 'webapp' project. - -Q: How do a get a deployable Jackrabbit installation with WebDAV and - optional RMI support? -A: The 'webdav' project only serves as library. In order to access - a Jackrabbit repository please follow the instructions present - with the 'webapp' project. - -Q: Does the WebDAV library has dependency to JSR170 -A: No, the library can be used as generic webdav library in any - other project. There exists a dependency to the jackrabbit-commons - library for utility classes only. - -Things to do -============ - -------------------------------------------------------------------- -todo webdav/version -------------------------------------------------------------------- - -- review: compliance to deltaV -- reconsider feature-sets (see also JCR-394) -- CHECKOUT may contain request body (working-resource, activity, checkout-in-place) -- CHECKIN may contain request body (working-resource, checkout-in-place) -- VERSION-CONTROL may contain request body (workspace f.) -- BASELINE: creation of Baseline resources is not yet supported - (TODO within AbstractWebDAVServlet) - -------------------------------------------------------------------- -todo webdav/ordering -------------------------------------------------------------------- - -- respect Position header with creation of new collection members by - PUT, COPY, MKCOL requests - -------------------------------------------------------------------- -todo webdav/search -------------------------------------------------------------------- - -- SearchResource should extend DavResource -- Library misses support for the DAV:basicsearch - -------------------------------------------------------------------- -todo webdav/transaction -------------------------------------------------------------------- - -- review naming of the lock scopes. 'global','local' are not correct in - this context. -- j2ee explicitely requires any usertransaction to be completed - upon the end of the servletes service method. - general review necessary. Property changes on: jackrabbit-webdav/README.txt ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Deleted: svn:keywords ## -1 +0,0 ## -author date id revision \ No newline at end of property Index: jackrabbit-webdav/pom.xml =================================================================== --- jackrabbit-webdav/pom.xml (revision 1907912) +++ jackrabbit-webdav/pom.xml (nonexistent) @@ -1,98 +0,0 @@ - - - - - - 4.0.0 - - - - - - org.apache.jackrabbit - jackrabbit-parent - 2.21.16-SNAPSHOT - ../jackrabbit-parent/pom.xml - - jackrabbit-webdav - bundle - Jackrabbit WebDAV Library - Generic WebDAV Library - - - - - org.apache.felix - maven-bundle-plugin - true - - - maven-surefire-plugin - - - **/*TestAll.java - - once - ${test.opts} - - - - - - - - org.osgi - org.osgi.annotation - provided - - - org.slf4j - slf4j-api - - - javax.servlet - javax.servlet-api - provided - - - org.apache.httpcomponents - httpcore - 4.4.16 - - - org.apache.httpcomponents - httpclient - 4.5.14 - - - org.slf4j - jcl-over-slf4j - - - - junit - junit - test - - - ch.qos.logback - logback-classic - test - - - Property changes on: jackrabbit-webdav/pom.xml ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-webdav/src/main/appended-resources/META-INF/NOTICE =================================================================== --- jackrabbit-webdav/src/main/appended-resources/META-INF/NOTICE (revision 1907912) +++ jackrabbit-webdav/src/main/appended-resources/META-INF/NOTICE (nonexistent) @@ -1,2 +0,0 @@ -Based on source code originally developed by -Day Software (http://www.day.com/). Property changes on: jackrabbit-webdav/src/main/appended-resources/META-INF/NOTICE ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Deleted: svn:keywords ## -1 +0,0 ## -author date id revision \ No newline at end of property Index: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/AbstractLocatorFactory.java =================================================================== --- jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/AbstractLocatorFactory.java (revision 1907912) +++ jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/AbstractLocatorFactory.java (nonexistent) @@ -1,403 +0,0 @@ -/* - * 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.webdav; - -import org.apache.jackrabbit.webdav.util.EncodeUtil; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * {@code AbstractLocatorFactory} is an implementation of the DavLocatorFactory - * interface that defines how a given URI is split to workspace path and - * resource path and how it's implementation of {@code DavResourceLocator} - * builds the href. In contrast, the conversion from repository path to - * resource path and vice versa is left to subclasses. - */ -public abstract class AbstractLocatorFactory implements DavLocatorFactory { - - private static Logger log = LoggerFactory.getLogger(AbstractLocatorFactory.class); - - private final String pathPrefix; - - /** - * Create a new factory - * - * @param pathPrefix Prefix, that needs to be removed in order to retrieve - * the path of the repository item from a given {@code DavResourceLocator}. - */ - public AbstractLocatorFactory(String pathPrefix) { - this.pathPrefix = pathPrefix; - } - - //--------------------------------------------------< DavLocatorFactory >--- - /** - * Create a new {@code DavResourceLocator}. Any leading prefix and - * path-prefix (as defined with the constructor) are removed from the - * given request handle. The same applies for trailing '/'. The remaining - * String is called the 'resource handle' and it's first segment is treated - * as workspace name. If resource handle (and therefore workspace name) - * are missing, both values are set to {@code null}. - *

- * Examples: - * - *

-     * http://www.foo.bar/ (path prefix missing)
-     * -> workspace path = null
-     * -> resource path  = null
-     * -> href           = http://www.foo.bar/pathPrefix/
-     *
-     * http://www.foo.bar/pathPrefix/
-     * -> workspace path = null
-     * -> resource path  = null
-     * -> href           = http://www.foo.bar/pathPrefix/
-     *
-     * http://www.foo.bar/pathPrefix/wspName
-     * -> workspace path = /wspName
-     * -> resource path  = /wspName
-     * -> href           = http://www.foo.bar/pathPrefix/wspName
-     *
-     * http://www.foo.bar/pathPrefix/wspName/anypath
-     * -> workspace path = /wspName
-     * -> resource path  = /wspName/anypath
-     * -> href           = http://www.foo.bar/pathPrefix/wspName/anypath
-     * 
- * - * NOTE: If the given href is an absolute URI it must start with the - * specified prefix. - * - * @param prefix - * @param href - * @return a new {@code DavResourceLocator} - * @throws IllegalArgumentException if the given href is {@code null} - */ - public DavResourceLocator createResourceLocator(String prefix, String href) { - if (href == null) { - throw new IllegalArgumentException("Request handle must not be null."); - } - - // build prefix string and remove all prefixes from the given href. - StringBuffer b = new StringBuffer(""); - if (prefix != null && prefix.length() > 0) { - b.append(prefix); - if (href.startsWith(prefix)) { - href = href.substring(prefix.length()); - } - } - if (pathPrefix != null && pathPrefix.length() > 0) { - if (!b.toString().endsWith(pathPrefix)) { - b.append(pathPrefix); - } - if (href.startsWith(pathPrefix)) { - href = href.substring(pathPrefix.length()); - } - } - - // remove trailing "/" that is present with collections - if (href.endsWith("/")) { - href = href.substring(0, href.length() - 1); - } - - String resourcePath; - String workspacePath; - - // an empty requestHandle (after removal of the "/") signifies a request - // to the root that does not represent a repository item. - if ("".equals(href)) { - resourcePath = null; - workspacePath = null; - } else { - resourcePath = EncodeUtil.unescape(href); - // retrieve wspPath: look for the first slash ignoring the leading one - int pos = href.indexOf('/', 1); - if (pos == -1) { - // request to a 'workspace' resource - workspacePath = resourcePath; - } else { - // separate the workspace path from the resource path. - workspacePath = EncodeUtil.unescape(href.substring(0, pos)); - } - } - - log.trace("createResourceLocator: prefix='" + prefix + "' href='" + href + "' -> prefix='" + b.toString() - + "' workspacePath='" + workspacePath + "' resourcePath='" + resourcePath + "'"); - return new DavResourceLocatorImpl(b.toString(), workspacePath, resourcePath, this); - } - - /** - * Like {@link #createResourceLocator(String, String)}, but by setting - * {@code forDestination} to {@code true} any special processing of URI - * suffixes can be disabled. - */ - public DavResourceLocator createResourceLocator(String prefix, String href, boolean forDestination) { - return createResourceLocator(prefix, href); - } - - /** - * Create a new {@code DavResourceLocator} from the specified prefix, - * workspace path and resource path, without modifying the specified Strings. - * Note, that it is expected that the resource path starts with the - * given workspace path unless both values are {@code null}. - * - * @param prefix - * @param workspacePath path or the workspace containing this resource or - * {@code null}. - * @param resourcePath Path of the resource or {@code null}. Any non - * null value must start with the specified workspace path. - * @return a new {@code DavResourceLocator} - * @see DavLocatorFactory#createResourceLocator(String, String, String) - */ - public DavResourceLocator createResourceLocator(String prefix, String workspacePath, String resourcePath) { - return createResourceLocator(prefix, workspacePath, resourcePath, true); - } - - /** - * Create a new {@code DavResourceLocator} from the specified prefix, - * workspace path and resource path. If {@code isResourcePath} is set - * to {@code false}, the given 'resourcePath' is converted by calling - * {@link #getResourcePath(String, String)}. Otherwise the same restriction - * applies as for {@link #createResourceLocator(String, String, String)}. - * - * @param prefix - * @param workspacePath - * @param path - * @param isResourcePath - * @return - * @see DavLocatorFactory#createResourceLocator(String, String, String, boolean) - */ - public DavResourceLocator createResourceLocator(String prefix, String workspacePath, String path, boolean isResourcePath) { - String resourcePath = (isResourcePath) ? path : getResourcePath(path, workspacePath); - return new DavResourceLocatorImpl(prefix, workspacePath, resourcePath, this); - } - - //-------------------------------------------------------------------------- - /** - * Subclasses must defined how the repository path is built from the given - * resource and workspace path. - * - * @param resourcePath - * @param wspPath - * @return - */ - protected abstract String getRepositoryPath(String resourcePath, String wspPath); - - /** - * Subclasses must defined how the resource path is built from the given - * repository and workspace path. - * - * @param repositoryPath - * @param wspPath - * @return - */ - protected abstract String getResourcePath(String repositoryPath, String wspPath); - - //--------------------------------------------------------< DavResource >--- - /** - * Private inner class {@code DavResourceLocatorImpl} implementing - * the {@code DavResourceLocator} interface. - */ - private class DavResourceLocatorImpl implements DavResourceLocator { - - private final String prefix; - private final String workspacePath; - private final String resourcePath; - private final AbstractLocatorFactory factory; - - private final String href; - - /** - * Create a new {@code DavResourceLocatorImpl}. - * - * @param prefix - * @param workspacePath - * @param resourcePath - */ - private DavResourceLocatorImpl(String prefix, String workspacePath, String resourcePath, AbstractLocatorFactory factory) { - - this.prefix = prefix; - this.workspacePath = workspacePath; - this.resourcePath = resourcePath; - this.factory = factory; - - StringBuffer buf = new StringBuffer(prefix); - // NOTE: no need to append the workspace path, since it must - // be part of the resource path. - if (resourcePath != null && resourcePath.length() > 0) { - // check if condition is really met - if (!resourcePath.startsWith(workspacePath)) { - throw new IllegalArgumentException("Resource path '" + resourcePath + "' does not start with workspace path '" + workspacePath + "'."); - } - buf.append(EncodeUtil.escapePath(resourcePath)); - } - int length = buf.length(); - if (length == 0 || (length > 0 && buf.charAt(length - 1) != '/')) { - buf.append("/"); - } - this.href = buf.toString(); - } - - /** - * Return the prefix used to build the href String. This includes the initial - * hrefPrefix as well a the path prefix. - * - * @return prefix String used to build the href. - */ - public String getPrefix() { - return prefix; - } - - /** - * Returns the resource path which always starts with the workspace - * path, if a workspace resource exists. For the top most resource - * (request handle '/'), {@code null} is returned. - * - * @return resource path or {@code null} - * @see org.apache.jackrabbit.webdav.DavResourceLocator#getResourcePath() - */ - public String getResourcePath() { - return resourcePath; - } - - /** - * Return the workspace path or {@code null} if this locator object - * represents the '/' request handle. - * - * @return workspace path or {@code null} - * @see org.apache.jackrabbit.webdav.DavResourceLocator#getWorkspacePath() - */ - public String getWorkspacePath() { - return workspacePath; - } - - /** - * Return the workspace name or {@code null} if this locator object - * represents the '/' request handle, which does not contain a workspace - * path. - * - * @return workspace name or {@code null} - * @see org.apache.jackrabbit.webdav.DavResourceLocator#getWorkspaceName() - */ - public String getWorkspaceName() { - if (workspacePath != null && workspacePath.length() > 0) { - return workspacePath.substring(1); - } - return null; - } - - /** - * Returns true if the specified locator object refers to a resource within - * the same workspace. - * - * @param locator - * @return true if the workspace name obtained from the given locator - * refers to the same workspace as the workspace name of this locator. - * @see DavResourceLocator#isSameWorkspace(org.apache.jackrabbit.webdav.DavResourceLocator) - */ - public boolean isSameWorkspace(DavResourceLocator locator) { - return (locator == null) ? false : isSameWorkspace(locator.getWorkspaceName()); - } - - /** - * Returns true if the specified string equals to this workspace name or - * if both names are null. - * - * @param workspaceName - * @return true if the workspace name is equal to this workspace name. - * @see DavResourceLocator#isSameWorkspace(String) - */ - public boolean isSameWorkspace(String workspaceName) { - String thisWspName = getWorkspaceName(); - return (thisWspName == null) ? workspaceName == null : thisWspName.equals(workspaceName); - } - - /** - * Returns an 'href' consisting of prefix and resource path (which starts - * with the workspace path). It assures a trailing '/' in case the href - * is used for collection. Note, that the resource path is - * {@link org.apache.jackrabbit.webdav.util.EncodeUtil#escapePath(String) escaped}. - * - * @param isCollection - * @return href String representing the text of the href element - * @see org.apache.jackrabbit.webdav.DavConstants#XML_HREF - * @see DavResourceLocator#getHref(boolean) - */ - public String getHref(boolean isCollection) { - return (isCollection) ? href : href.substring(0, href.length() - 1); - } - - /** - * Returns true if the 'workspacePath' field is {@code null}. - * - * @return true if the 'workspacePath' field is {@code null}. - * @see org.apache.jackrabbit.webdav.DavResourceLocator#isRootLocation() - */ - public boolean isRootLocation() { - return getWorkspacePath() == null; - } - - /** - * Return the factory that created this locator. - * - * @return factory - * @see org.apache.jackrabbit.webdav.DavResourceLocator#getFactory() - */ - public DavLocatorFactory getFactory() { - return factory; - } - - /** - * Uses {@link AbstractLocatorFactory#getRepositoryPath(String, String)} - * to build the repository path. - * - * @see DavResourceLocator#getRepositoryPath() - */ - public String getRepositoryPath() { - return factory.getRepositoryPath(getResourcePath(), getWorkspacePath()); - } - - /** - * Computes the hash code from the href, that is built from the prefix, - * the workspace name and the resource path all of them representing - * final instance fields. - * - * @return the hash code - */ - @Override - public int hashCode() { - return href.hashCode(); - } - - /** - * Returns true, if the given object is a {@code DavResourceLocatorImpl} - * with the same hash code. - * - * @param obj the object to compare to - * @return {@code true} if the 2 objects are equal; - * {@code false} otherwise - */ - @Override - public boolean equals(Object obj) { - if (obj == this) { - return true; - } - if (obj instanceof DavResourceLocatorImpl) { - DavResourceLocatorImpl other = (DavResourceLocatorImpl) obj; - return hashCode() == other.hashCode(); - } - return false; - } - } -} Property changes on: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/AbstractLocatorFactory.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Deleted: svn:keywords ## -1 +0,0 ## -author date id revision url \ No newline at end of property Index: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/ContentCodingAwareRequest.java =================================================================== --- jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/ContentCodingAwareRequest.java (revision 1907912) +++ jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/ContentCodingAwareRequest.java (nonexistent) @@ -1,39 +0,0 @@ -/* - * 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.webdav; - -import java.util.List; - -import javax.xml.namespace.QName; - -public interface ContentCodingAwareRequest { - - /** - * Element name for signaling "must be supported content coding" - */ - public final QName PRECONDITION_SUPPORTED = new QName("http://www.day.com/jcr/webdav/1.0", "supported-content-coding", "dcr"); - - /** - * @return value suitable for Accept response field - */ - public String getAcceptableCodings(); - - /** - * @return content codings used in request - */ - public List getRequestContentCodings(); -} Property changes on: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/ContentCodingAwareRequest.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/DavCompliance.java =================================================================== --- jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/DavCompliance.java (revision 1907912) +++ jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/DavCompliance.java (nonexistent) @@ -1,72 +0,0 @@ -/* - * 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.webdav; - -/** - * DavCompliance defines constants for the various compliance - * classes defined RFC 2518, RFC 4918 and it's extensions. - */ -public final class DavCompliance { - - /** - * Avoid instantiation - */ - private DavCompliance() {} - - // RFC 2518 - public static final String _1_ = "1"; - public static final String _2_ = "2"; - - // RFC 4918 - public static final String _3_ = "3"; - - // RFC 3253 - public static final String ACTIVITY = "activity"; - public static final String BASELINE = "baseline"; - public static final String CHECKOUT_IN_PLACE = "checkout-in-place"; - public static final String LABEL = "label"; - public static final String MERGE = "merge"; - public static final String UPDATE = "update"; - public static final String VERSION_CONTROL = "version-control"; - public static final String VERSION_CONTROLLED_COLLECTION = "version-controlled-collection"; - public static final String VERSION_HISTORY = "version-history"; - public static final String WORKING_RESOURCE = "working-resource"; - public static final String WORKSPACE = "workspace"; - - // RFC 3648 - public static final String ORDERED_COLLECTIONS = "ordered-collections"; - - // RFC 3744 - public static final String ACCESS_CONTROL = "access-control"; - - // RFC 5842 - public static final String BIND = "bind"; - - // no RFC - public static final String OBSERVATION = "observation"; - - public static String concatComplianceClasses(String[] complianceClasses) { - StringBuffer b = new StringBuffer(); - for (int i = 0; i < complianceClasses.length; i++) { - if (i > 0) { - b.append(","); - } - b.append(complianceClasses[i]); - } - return b.toString(); - } -} \ No newline at end of file Property changes on: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/DavCompliance.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Deleted: svn:keywords ## -1 +0,0 ## -author date id revision url \ No newline at end of property Index: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/DavConstants.java =================================================================== --- jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/DavConstants.java (revision 1907912) +++ jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/DavConstants.java (nonexistent) @@ -1,154 +0,0 @@ -/* - * 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.webdav; - -import org.apache.jackrabbit.webdav.util.HttpDateFormat; -import org.apache.jackrabbit.webdav.xml.Namespace; - -import java.text.DateFormat; - -/** - * DavConstants provide constants for request and response - * headers, XML elements and property names defined by - * RFC 2518. In addition, - * common date formats (creation date and modification time) are included. - */ -public interface DavConstants { - - /** - * Default Namespace constant - */ - public static final Namespace NAMESPACE = Namespace.getNamespace("D", "DAV:"); - - //--------------------------------< Headers (Names and Value Constants) >--- - public static final String HEADER_DAV = "DAV"; - public static final String HEADER_DESTINATION = "Destination"; - public static final String HEADER_IF = "If"; - public static final String HEADER_AUTHORIZATION = "Authorization"; - public static final String HEADER_CONTENT_TYPE = "Content-Type"; - public static final String HEADER_CONTENT_LENGTH = "Content-Length"; - public static final String HEADER_CONTENT_LANGUAGE = "Content-Language"; - public static final String HEADER_ETAG = "ETag"; - public static final String HEADER_LAST_MODIFIED = "Last-Modified"; - - //--------------------------------------------------< Lock-Token Header >--- - public static final String HEADER_LOCK_TOKEN = "Lock-Token"; - public static final String OPAQUE_LOCK_TOKEN_PREFIX = "opaquelocktoken:"; - - //-----------------------------------------------------< Timeout Header >--- - public static final String HEADER_TIMEOUT = "Timeout"; - public static final String TIMEOUT_INFINITE = "Infinite"; - // RFC 2518: timeout value for TimeType "Second" MUST NOT be greater than 2^32-1 - public static final long INFINITE_TIMEOUT = Integer.MAX_VALUE; - public static final long UNDEFINED_TIMEOUT = Integer.MIN_VALUE; - - //---------------------------------------------------< Overwrite Header >--- - public static final String HEADER_OVERWRITE = "Overwrite"; - - //-------------------------------------------------------< Depth Header >--- - public static final String HEADER_DEPTH = "Depth"; - public static final String DEPTH_INFINITY_S = "infinity"; - public static final int DEPTH_INFINITY = Integer.MAX_VALUE; - public static final int DEPTH_0 = 0; - public static final int DEPTH_1 = 1; - - //---< XML Element, Attribute Names >--------------------------------------- - public static final String XML_ALLPROP = "allprop"; - public static final String XML_COLLECTION = "collection"; - public static final String XML_DST = "dst"; - public static final String XML_HREF = "href"; - public static final String XML_INCLUDE = "include"; - public static final String XML_KEEPALIVE = "keepalive"; - public static final String XML_LINK = "link"; - public static final String XML_MULTISTATUS = "multistatus"; - public static final String XML_OMIT = "omit"; - public static final String XML_PROP = "prop"; - public static final String XML_PROPERTYBEHAVIOR = "propertybehavior"; - public static final String XML_PROPERTYUPDATE = "propertyupdate"; - public static final String XML_PROPFIND = "propfind"; - public static final String XML_PROPNAME = "propname"; - public static final String XML_PROPSTAT = "propstat"; - public static final String XML_REMOVE = "remove"; - public static final String XML_RESPONSE = "response"; - public static final String XML_RESPONSEDESCRIPTION = "responsedescription"; - public static final String XML_SET = "set"; - public static final String XML_SOURCE = "source"; - public static final String XML_STATUS = "status"; - - //------------------------------------------------------------< locking >--- - public static final String XML_ACTIVELOCK = "activelock"; - public static final String XML_DEPTH = "depth"; - public static final String XML_LOCKTOKEN = "locktoken"; - public static final String XML_TIMEOUT = "timeout"; - public static final String XML_LOCKSCOPE = "lockscope"; - public static final String XML_EXCLUSIVE = "exclusive"; - public static final String XML_SHARED = "shared"; - public static final String XML_LOCKENTRY = "lockentry"; - public static final String XML_LOCKINFO = "lockinfo"; - public static final String XML_LOCKTYPE = "locktype"; - public static final String XML_WRITE = "write"; - public static final String XML_OWNER = "owner"; - /** - * The lockroot XML element - * @see RFC 4918 - */ - public static final String XML_LOCKROOT = "lockroot"; - - //-----------------------------------------------------< Property Names >--- - /* - * Webdav property names as defined by RFC 2518
- * Note: Microsoft webdav clients as well as Webdrive request additional - * property (e.g. href, name, owner, isRootLocation, isCollection) within the - * default namespace, which are are ignored by this implementation, except - * for the 'isCollection' property, needed for XP built-in clients. - */ - public static final String PROPERTY_CREATIONDATE = "creationdate"; - public static final String PROPERTY_DISPLAYNAME = "displayname"; - public static final String PROPERTY_GETCONTENTLANGUAGE = "getcontentlanguage"; - public static final String PROPERTY_GETCONTENTLENGTH = "getcontentlength"; - public static final String PROPERTY_GETCONTENTTYPE = "getcontenttype"; - public static final String PROPERTY_GETETAG = "getetag"; - public static final String PROPERTY_GETLASTMODIFIED = "getlastmodified"; - public static final String PROPERTY_LOCKDISCOVERY = "lockdiscovery"; - public static final String PROPERTY_RESOURCETYPE = "resourcetype"; - public static final String PROPERTY_SOURCE = "source"; - public static final String PROPERTY_SUPPORTEDLOCK = "supportedlock"; - - //-------------------------------------------------< PropFind Constants >--- - public static final int PROPFIND_BY_PROPERTY = 0; - public static final int PROPFIND_ALL_PROP = 1; - public static final int PROPFIND_PROPERTY_NAMES = 2; - public static final int PROPFIND_ALL_PROP_INCLUDE = 3; // RFC 4918, Section 9.1 - - //----------------------------------------------< Date Format Constants >--- - /** - * Marker for undefined modification or creation time. - */ - public static long UNDEFINED_TIME = -1; - - /** - * modificationDate date format per RFC 1123.
- * NOTE: Access to DateFormat isn't thread save. - */ - public static DateFormat modificationDateFormat = HttpDateFormat.modificationDateFormat(); - - /** - * Simple date format for the creation date ISO representation (partial).
- * NOTE: Access to DateFormat isn't thread save. - */ - public static DateFormat creationDateFormat = HttpDateFormat.creationDateFormat(); -} Property changes on: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/DavConstants.java ___________________________________________________________________ Deleted: svn Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/DavException.java =================================================================== --- jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/DavException.java (revision 1907912) +++ jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/DavException.java (nonexistent) @@ -1,175 +0,0 @@ -/* - * 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.webdav; - -import org.apache.jackrabbit.webdav.xml.DomUtil; -import org.apache.jackrabbit.webdav.xml.XmlSerializable; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.w3c.dom.Document; -import org.w3c.dom.Element; - -import java.io.IOException; -import java.util.Properties; - -/** - * DavException extends the {@link Exception} class in order - * to simplify handling of exceptional situations occurring during processing - * of WebDAV requests and provides possibility to retrieve an Xml representation - * of the error. - */ -public class DavException extends Exception implements XmlSerializable { - - private static Logger log = LoggerFactory.getLogger(DavException.class); - private static Properties statusPhrases = new Properties(); - static { - try { - statusPhrases.load(DavException.class.getResourceAsStream("statuscode.properties")); - } catch (IOException e) { - log.error("Failed to load status properties: " + e.getMessage()); - } - } - - public static final String XML_ERROR = "error"; - - private int errorCode = DavServletResponse.SC_INTERNAL_SERVER_ERROR; - private Element errorCondition; - - /** - * Create a new DavException. - * - * @param errorCode integer specifying any of the status codes defined by - * {@link DavServletResponse}. - * @param message Human readable error message. - * @see DavException#DavException(int, String, Throwable, Element) - */ - public DavException(int errorCode, String message) { - this(errorCode, message, null, null); - } - - /** - * Create a new DavException. - * - * @param errorCode integer specifying any of the status codes defined by - * {@link DavServletResponse}. - * @param cause Cause of this DavException - * @see DavException#DavException(int, String, Throwable, Element) - */ - public DavException(int errorCode, Throwable cause) { - this(errorCode, null, cause, null); - } - - /** - * Create a new DavException. - * - * @param errorCode integer specifying any of the status codes defined by - * {@link DavServletResponse}. - * @see DavException#DavException(int, String, Throwable, Element) - */ - public DavException(int errorCode) { - this(errorCode, statusPhrases.getProperty(String.valueOf(errorCode)), null, null); - } - - /** - * Create a new DavException. - * - * @param errorCode integer specifying any of the status codes defined by - * {@link DavServletResponse}. - * @param message Human readable error message. - * @param cause Cause of this DavException. - * @param errorCondition Xml element providing detailed information about - * the error. If the condition is not null, {@link #toXml(Document)} - */ - public DavException(int errorCode, String message, Throwable cause, Element errorCondition) { - super(message, cause); - this.errorCode = errorCode; - this.errorCondition = errorCondition; - log.debug("DavException: (" + errorCode + ") " + message); - } - - /** - * Return the error code attached to this DavException. - * - * @return errorCode - */ - public int getErrorCode() { - return errorCode; - } - - /** - * Return the status phrase corresponding to the error code attached to - * this DavException. - * - * @return status phrase corresponding to the error code. - * @see #getErrorCode() - */ - public String getStatusPhrase() { - return getStatusPhrase(errorCode); - } - - /** - * Returns the status phrase for the given error code. - * - * @param errorCode - * @return status phrase corresponding to the given error code. - */ - public static String getStatusPhrase(int errorCode) { - return statusPhrases.getProperty(errorCode + ""); - } - - /** - * @return true if a error condition has been specified, false otherwise. - */ - public boolean hasErrorCondition() { - return errorCondition != null; - } - - /** - * Return the error condition attached to this DavException. - * - * @return errorCondition - */ - public Element getErrorCondition() { - return errorCondition; - } - - /** - * Returns a DAV:error element containing the error condition or - * null if no specific condition is available. See - * RFC 3253 - * Section 1.6 "Method Preconditions and Postconditions" for additional - * information. - * - * @param document - * @return A DAV:error element indicating the error cause or null. - * @see org.apache.jackrabbit.webdav.xml.XmlSerializable#toXml(Document) - */ - public Element toXml(Document document) { - if (hasErrorCondition()) { - Element error; - if (DomUtil.matches(errorCondition, XML_ERROR, DavConstants.NAMESPACE)) { - error = (Element) document.importNode(errorCondition, true); - } else { - error = DomUtil.createElement(document, XML_ERROR, DavConstants.NAMESPACE); - error.appendChild(document.importNode(errorCondition, true)); - } - return error; - } else { - return null; - } - } -} Property changes on: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/DavException.java ___________________________________________________________________ Deleted: svn Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/DavLocatorFactory.java =================================================================== --- jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/DavLocatorFactory.java (revision 1907912) +++ jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/DavLocatorFactory.java (nonexistent) @@ -1,72 +0,0 @@ -/* - * 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.webdav; - -/** - * DavLocatorFactory... - */ -public interface DavLocatorFactory { - - /** - * Create a new DavResourceLocator. - * - * @param prefix String consisting of [scheme:][//authority][path] where - * path defines the (imaginary) path to the {@link DavResourceLocator#isRootLocation root location}. - * @param href of the resource to be created. The given string may start with - * the 'prefix'. Please note, that in contrast to - * {@link DavLocatorFactory#createResourceLocator(String, String, String)} the - * href is expected to be URL encoded. - * @return a new resource locator. - */ - public DavResourceLocator createResourceLocator(String prefix, String href); - - /** - * Create a new DavResourceLocator. This methods corresponds to - * {@link DavLocatorFactory#createResourceLocator(String, String, String, boolean)} - * with the flag set to true. - * - * @param prefix String consisting of [scheme:][//authority][path] where - * path defines the path to the {@link DavResourceLocator#isRootLocation root location}. - * @param workspacePath the first segment of the URIs path indicating the - * workspace. The implementation may allow a empty String if workspaces - * are not supported. - * @param resourcePath the URL decoded resource path. - * @return a new resource locator. - */ - public DavResourceLocator createResourceLocator(String prefix, String workspacePath, String resourcePath); - - /** - * - * @param prefix String consisting of [scheme:][//authority][path] where - * path defines the path to the {@link DavResourceLocator#isRootLocation root location}. - * @param workspacePath the first segment of the URIs path indicating the - * workspace. The implementation may allow a empty String if workspaces - * are not supported. - * @param path the URL decoded path. - * @param isResourcePath If true this method returns the same as - * {@link DavLocatorFactory#createResourceLocator(String, String, String)}, - * otherwise the given path is treated as internal repository path. - * The implementation may choose to implement a conversion of the repository - * path to a valid resource path, e.g. (un)escaping of certain characters, due - * to incompatibility with the URI definition (or vice versa). Note that - * {@link DavResourceLocator#getRepositoryPath()} should in this case implement - * the reverse operation. - * @return a new resource locator. - * @see DavResourceLocator#getRepositoryPath() - */ - public DavResourceLocator createResourceLocator(String prefix, String workspacePath, String path, boolean isResourcePath); -} \ No newline at end of file Property changes on: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/DavLocatorFactory.java ___________________________________________________________________ Deleted: svn Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/DavMethods.java =================================================================== --- jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/DavMethods.java (revision 1907912) +++ jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/DavMethods.java (nonexistent) @@ -1,409 +0,0 @@ -/* - * 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.webdav; - -import java.util.HashMap; -import java.util.Map; - -/** - * DavMethods defines constants for the WebDAV METHODS. - */ -public final class DavMethods { - - /** - * Avoid instantiation - */ - private DavMethods() {} - - /** - * A map of WebDAV METHODS - */ - private static Map methodMap = new HashMap(); - - /** - * An array of method codes that are affected by a Label header - * @see org.apache.jackrabbit.webdav.version.DeltaVConstants#HEADER_LABEL - */ - private static int[] labelMethods; - - /** - * An array of method codes defined by RFC 3253 (deltaV) - */ - private static int[] deltaVMethods; - - /** - * The webdav OPTIONS method and public constant - */ - public static final int DAV_OPTIONS = 1; - public static final String METHOD_OPTIONS = "OPTIONS"; - - /** - * The webdav GET method and public constant - */ - public static final int DAV_GET = DAV_OPTIONS + 1; - public static final String METHOD_GET = "GET"; - - /** - * The webdav HEAD method and public constant - */ - public static final int DAV_HEAD = DAV_GET + 1; - public static final String METHOD_HEAD = "HEAD"; - - - /** - * The webdav POST method and public constant - */ - public static final int DAV_POST = DAV_HEAD + 1; - public static final String METHOD_POST = "POST"; - - - /** The webdav DELETE method and public constant */ - public static final int DAV_DELETE = DAV_POST + 1; - public static final String METHOD_DELETE = "DELETE"; - - - /** The webdav PUT method and public constant */ - public static final int DAV_PUT = DAV_DELETE + 1; - public static final String METHOD_PUT = "PUT"; - - - /** - * The webdav PROPFIND method and public constant as defined by - * RFC 2518. - */ - public static final int DAV_PROPFIND = DAV_PUT + 1; - public static final String METHOD_PROPFIND = "PROPFIND"; - - - /** - * The webdav PROPPATCH method and public constant as defined by - * RFC 2518 - */ - public static final int DAV_PROPPATCH = DAV_PROPFIND + 1; - public static final String METHOD_PROPPATCH = "PROPPATCH"; - - - /** - * The webdav MKCOL (make collection) method and public constant as defined by - * RFC 2518 - */ - public static final int DAV_MKCOL = DAV_PROPPATCH + 1; - public static final String METHOD_MKCOL = "MKCOL"; - - - /** - * The webdav COPY method and public constant as defined by - * RFC 2518 - */ - public static final int DAV_COPY = DAV_MKCOL + 1; - public static final String METHOD_COPY = "COPY"; - - - /** - * The webdav MOVE method and public constant as defined by - * RFC 2518 - */ - public static final int DAV_MOVE = DAV_COPY + 1; - public static final String METHOD_MOVE = "MOVE"; - - - /** - * The webdav LOCK method and public constant as defined by - * RFC 2518 - */ - public static final int DAV_LOCK = DAV_MOVE + 1; - public static final String METHOD_LOCK = "LOCK"; - - - /** - * The webdav UNLOCK method and public constant as defined by - * RFC 2518 - */ - public static final int DAV_UNLOCK = DAV_LOCK + 1; - public static final String METHOD_UNLOCK = "UNLOCK"; - - - /** - * The webdav ORDERPATCH method and public constant - * defined by RFC 3648. - */ - public static final int DAV_ORDERPATCH = DAV_UNLOCK + 1; - public static final String METHOD_ORDERPATCH = "ORDERPATCH"; - - - /** - * The webdav SUBSCRIBE method and public constant.
- * NOTE: This method is not defined by any of the Webdav RFCs - */ - public static final int DAV_SUBSCRIBE = DAV_ORDERPATCH + 1; - public static final String METHOD_SUBSCRIBE = "SUBSCRIBE"; - - - /** - * The webdav UNSUBSCRIBE method and public constant
- * NOTE: This method is not defined by any of the Webdav RFCs - */ - public static final int DAV_UNSUBSCRIBE = DAV_SUBSCRIBE + 1; - public static final String METHOD_UNSUBSCRIBE = "UNSUBSCRIBE"; - - - /** - * The webdav POLL method and public constant
- * NOTE: This method is not defined by any of the Webdav RFCs - */ - public static final int DAV_POLL = DAV_UNSUBSCRIBE + 1; - public static final String METHOD_POLL = "POLL"; - - - /** - * The webdav SEARCH method and public constant as defined by the - * Webdav Search internet draft. - */ - public static final int DAV_SEARCH = DAV_POLL + 1; - public static final String METHOD_SEARCH = "SEARCH"; - - - /** - * The webdav REPORT method and public constant defined by - * RFC 3253 - */ - public static final int DAV_REPORT = DAV_SEARCH + 1; - public static final String METHOD_REPORT = "REPORT"; - - - /** - * The webdav VERSION-CONTROL method and public constant defined by - * RFC 3253 - */ - public static final int DAV_VERSION_CONTROL = DAV_REPORT + 1; - public static final String METHOD_VERSION_CONTROL = "VERSION-CONTROL"; - - /** - * The webdav CHECKIN method and public constant defined by - * RFC 3253 - */ - public static final int DAV_CHECKIN = DAV_VERSION_CONTROL + 1; - public static final String METHOD_CHECKIN = "CHECKIN"; - - /** - * The webdav CHECKOUT method and public constant defined by - * RFC 3253 - */ - public static final int DAV_CHECKOUT = DAV_CHECKIN + 1; - public static final String METHOD_CHECKOUT = "CHECKOUT"; - - /** - * The webdav UNCHECKOUT method and public constant defined by - * RFC 3253 - */ - public static final int DAV_UNCHECKOUT = DAV_CHECKOUT + 1; - public static final String METHOD_UNCHECKOUT = "UNCHECKOUT"; - - /** - * The webdav LABEL method and public constant defined by - * RFC 3253 - */ - public static final int DAV_LABEL = DAV_UNCHECKOUT + 1; - public static final String METHOD_LABEL = "LABEL"; - - /** - * The webdav MERGE method and public constant defined by - * RFC 3253 - */ - public static final int DAV_MERGE = DAV_LABEL + 1; - public static final String METHOD_MERGE = "MERGE"; - - /** - * The webdav UPDATE method and public constant defined by - * RFC 3253 - */ - public static final int DAV_UPDATE = DAV_MERGE + 1; - public static final String METHOD_UPDATE = "UPDATE"; - - /** - * The webdav MKWORKSPACE method and public constant defined by - * RFC 3253 - */ - public static final int DAV_MKWORKSPACE = DAV_UPDATE + 1; - public static final String METHOD_MKWORKSPACE = "MKWORKSPACE"; - - /** - * The webdav BASELINE-CONTROL method and public constant defined by - * RFC 3253 - */ - public static final int DAV_BASELINE_CONTROL = DAV_MKWORKSPACE + 1; - public static final String METHOD_BASELINE_CONTROL = "BASELINE-CONTROL"; - - /** - * The webdav MKACTIVITY method and public constant defined by - * RFC 3253 - */ - public static final int DAV_MKACTIVITY = DAV_BASELINE_CONTROL + 1; - public static final String METHOD_MKACTIVITY = "MKACTIVITY"; - - /** - * The webdav ACL method and public constant defined by - * RFC 3744 - */ - public static final int DAV_ACL = DAV_MKACTIVITY + 1; - public static final String METHOD_ACL = "ACL"; - - /** - * The webdav REBIND method and public constant defined by - * the BIND specification - */ - public static final int DAV_REBIND = DAV_ACL + 1; - public static final String METHOD_REBIND = "REBIND"; - - /** - * The webdav UNBIND method and public constant defined by - * the BIND specification - */ - public static final int DAV_UNBIND = DAV_REBIND + 1; - public static final String METHOD_UNBIND = "UNBIND"; - - /** - * The webdav BIND method and public constant defined by - * the BIND specification - */ - public static final int DAV_BIND = DAV_UNBIND + 1; - public static final String METHOD_BIND = "BIND"; - - /** - * Returns webdav method type code, error result <= 0 - * Valid type codes > 0 - */ - public static int getMethodCode(String method) { - Integer code = methodMap.get(method.toUpperCase()); - if (code != null) { - return code; - } - return 0; - } - - /** - * Static initializer for methodTable map - */ - private static void addMethodCode(String method, int code) { - methodMap.put(method, code); - } - - /** - * Webdav Method table - */ - static { - addMethodCode(METHOD_OPTIONS, DAV_OPTIONS); - addMethodCode(METHOD_GET, DAV_GET); - addMethodCode(METHOD_HEAD, DAV_HEAD); - addMethodCode(METHOD_POST, DAV_POST); - addMethodCode(METHOD_PUT, DAV_PUT); - addMethodCode(METHOD_DELETE, DAV_DELETE); - addMethodCode(METHOD_PROPFIND, DAV_PROPFIND); - addMethodCode(METHOD_PROPPATCH, DAV_PROPPATCH); - addMethodCode(METHOD_MKCOL, DAV_MKCOL); - addMethodCode(METHOD_COPY, DAV_COPY); - addMethodCode(METHOD_MOVE, DAV_MOVE); - addMethodCode(METHOD_LOCK, DAV_LOCK); - addMethodCode(METHOD_UNLOCK, DAV_UNLOCK); - addMethodCode(METHOD_ORDERPATCH, DAV_ORDERPATCH); - addMethodCode(METHOD_SUBSCRIBE, DAV_SUBSCRIBE); - addMethodCode(METHOD_UNSUBSCRIBE, DAV_UNSUBSCRIBE); - addMethodCode(METHOD_POLL, DAV_POLL); - addMethodCode(METHOD_SEARCH, DAV_SEARCH); - addMethodCode(METHOD_REPORT, DAV_REPORT); - addMethodCode(METHOD_VERSION_CONTROL, DAV_VERSION_CONTROL); - addMethodCode(METHOD_CHECKIN, DAV_CHECKIN); - addMethodCode(METHOD_CHECKOUT, DAV_CHECKOUT); - addMethodCode(METHOD_UNCHECKOUT, DAV_UNCHECKOUT); - addMethodCode(METHOD_LABEL, DAV_LABEL); - addMethodCode(METHOD_MERGE, DAV_MERGE); - addMethodCode(METHOD_UPDATE, DAV_UPDATE); - addMethodCode(METHOD_MKWORKSPACE, DAV_MKWORKSPACE); - addMethodCode(METHOD_BASELINE_CONTROL, DAV_BASELINE_CONTROL); - addMethodCode(METHOD_MKACTIVITY, DAV_MKACTIVITY); - addMethodCode(METHOD_ACL, DAV_ACL); - addMethodCode(METHOD_REBIND, DAV_REBIND); - addMethodCode(METHOD_UNBIND, DAV_UNBIND); - addMethodCode(METHOD_BIND, DAV_BIND); - - labelMethods = new int[] { DAV_GET, DAV_HEAD, DAV_OPTIONS, DAV_PROPFIND, - DAV_LABEL, DAV_COPY }; - - deltaVMethods = new int[] { DAV_REPORT, DAV_VERSION_CONTROL, DAV_CHECKIN, - DAV_CHECKOUT, DAV_UNCHECKOUT, DAV_LABEL, - DAV_MERGE, DAV_UPDATE, DAV_MKWORKSPACE, - DAV_BASELINE_CONTROL, DAV_MKACTIVITY }; - } - - /** - * Returns true if the request is to create a resource. - * True for PUT, POST, MKCOL - * and MKWORKSPACE requests. - * - * @return true if request method is to create (or replace) a resource - */ - public static boolean isCreateRequest(DavServletRequest request) { - int methodCode = getMethodCode(request.getMethod()); - return ( methodCode == DAV_PUT || - methodCode == DAV_POST || - methodCode == DAV_MKCOL || - methodCode == DAV_MKWORKSPACE); - } - - /** - * Returns true if the request is to create a collection resource. - * True for MKCOL and MKWORKSPACE requests. - * - * @return true if request method is to create a new collection resource - */ - public static boolean isCreateCollectionRequest(DavServletRequest request) { - int methodCode = getMethodCode(request.getMethod()); - return (methodCode == DAV_MKCOL || methodCode == DAV_MKWORKSPACE); - } - - /** - * Returns true, if the specified method is affected by a Label header - * - * @param request - * @return - */ - public static boolean isMethodAffectedByLabel(DavServletRequest request) { - int code = getMethodCode(request.getMethod()); - for (int labelMethod : labelMethods) { - if (code == labelMethod) { - return true; - } - } - return false; - } - - /** - * Returns true, if the specified method is defined by RFC 3253 - * - * @param request - * @return true, if the specified method is defined by RFC 3253 - */ - public static boolean isDeltaVMethod(DavServletRequest request) { - int code = getMethodCode(request.getMethod()); - for (int deltaVMethod : deltaVMethods) { - if (code == deltaVMethod) { - return true; - } - } - return false; - } -} Property changes on: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/DavMethods.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/DavResource.java =================================================================== --- jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/DavResource.java (revision 1907912) +++ jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/DavResource.java (nonexistent) @@ -1,334 +0,0 @@ -/* - * 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.webdav; - -import org.apache.jackrabbit.webdav.io.InputContext; -import org.apache.jackrabbit.webdav.io.OutputContext; -import org.apache.jackrabbit.webdav.lock.ActiveLock; -import org.apache.jackrabbit.webdav.lock.LockInfo; -import org.apache.jackrabbit.webdav.lock.LockManager; -import org.apache.jackrabbit.webdav.lock.Scope; -import org.apache.jackrabbit.webdav.lock.Type; -import org.apache.jackrabbit.webdav.property.DavProperty; -import org.apache.jackrabbit.webdav.property.DavPropertyName; -import org.apache.jackrabbit.webdav.property.DavPropertySet; -import org.apache.jackrabbit.webdav.property.PropEntry; - -import java.io.IOException; -import java.util.List; - -/** - * DavResource provides standard WebDAV functionality as specified - * by RFC 2518. - */ -public interface DavResource { - - /** - * String constant representing the WebDAV 1 and 2 method set. - */ - public static final String METHODS = "OPTIONS, GET, HEAD, TRACE, PROPFIND, PROPPATCH, MKCOL, COPY, PUT, DELETE, MOVE, LOCK, UNLOCK"; - - /** - * Returns a comma separated list of all compliance classes the given - * resource is fulfilling. - * - * @return compliance classes - */ - public String getComplianceClass(); - - /** - * Returns a comma separated list of all METHODS supported by the given - * resource. - * - * @return METHODS supported by this resource. - */ - public String getSupportedMethods(); - - /** - * Returns true if this webdav resource represents an existing repository item. - * - * @return true, if the resource represents an existing repository item. - */ - public boolean exists(); - - /** - * Returns true if this webdav resource has the resourcetype 'collection'. - * - * @return true if the resource represents a collection resource. - */ - public boolean isCollection(); - - /** - * Returns the display name of this resource. - * - * @return display name. - */ - public String getDisplayName(); - - /** - * Returns the {@link DavResourceLocator locator} object for this webdav resource, - * which encapsulates the information for building the complete 'href'. - * - * @return the locator for this resource. - * @see #getResourcePath() - * @see #getHref() - */ - public DavResourceLocator getLocator(); - - /** - * Returns the path of the hierarchy element defined by this DavResource. - * This method is a shortcut for DavResource.getLocator().getResourcePath(). - * - * @return path of the element defined by this DavResource. - */ - public String getResourcePath(); - - /** - * Returns the absolute href of this resource as returned in the - * multistatus response body. - * - * @return href - */ - public String getHref(); - - /** - * Return the time of the last modification or -1 if the modification time - * could not be retrieved. - * - * @return time of last modification or -1. - */ - public long getModificationTime(); - - /** - * Spools the resource properties and ev. content to the specified context - * (e.g. to respond to a 'GET' or 'HEAD' request). The context could e.g. - * wrap the servlet response. - * - * @param outputContext The output context. - * @throws IOException If an error occurs. - */ - public void spool(OutputContext outputContext) throws IOException; - - /** - * Returns an array of all {@link DavPropertyName property names} available - * on this resource. - * - * @return an array of property names. - */ - public DavPropertyName[] getPropertyNames(); - - /** - * Return the webdav property with the specified name. - * - * @param name name of the webdav property - * @return the {@link DavProperty} with the given name or null - * if the property does not exist. - */ - public DavProperty getProperty(DavPropertyName name); - - /** - * Returns all webdav properties present on this resource that will be - * return upon a {@link DavConstants#PROPFIND_ALL_PROP} request. The - * implementation may in addition expose other (protected or calculated) - * properties which should be marked accordingly (see also - * {@link org.apache.jackrabbit.webdav.property.DavProperty#isInvisibleInAllprop()}. - * - * @return a {@link DavPropertySet} containing at least all properties - * of this resource that are exposed in 'allprop' PROPFIND request. - */ - public DavPropertySet getProperties(); - - /** - * Add/Set the specified property on this resource. - * - * @param property - * @throws DavException if an error occurs - */ - public void setProperty(DavProperty property) throws DavException; - - /** - * Remove the specified property from this resource. - * - * @param propertyName - * @throws DavException if an error occurs - */ - public void removeProperty(DavPropertyName propertyName) throws DavException; - - /** - * Set/add and remove the specified properties from this resource. - * - * @param changeList list containing {@link DavPropertyName} objects (for - * properties to be removed) and {@link DavProperty} objects (for - * properties to be added/set). - * @return multistatus response listing the status resulting from - * setting and/or removing the specified properties, in order to allow a - * detailed multistatus response. - * @throws DavException if an error occurred. This may be the case if the - * general state of the resource prevents any properties to be set or removed - * (e.g. due to a lock). - */ - public MultiStatusResponse alterProperties(List changeList) throws DavException; - - /** - * Retrieve the resource this resource is internal member of. - * - * @return resource this resource is an internal member of. In case this resource - * is the root null is returned. - */ - public DavResource getCollection(); - - /** - * Add the given resource as an internal member to this resource. - * - * @param resource {@link DavResource} to be added as internal member. - * @param inputContext Context providing the properties and content for the - * internal member to be created or replaced. - * @throws DavException - */ - public void addMember(DavResource resource, InputContext inputContext) throws DavException; - - /** - * Returns an iterator over all internal members. - * - * @return a {@link DavResourceIterator} over all internal members. - */ - public DavResourceIterator getMembers(); - - /** - * Removes the specified member from this resource. - * - * @throws DavException - */ - public void removeMember(DavResource member) throws DavException; - - /** - * Move this DavResource to the given destination resource - * - * @param destination - * @throws DavException - */ - public void move(DavResource destination) throws DavException; - - /** - * Copy this DavResource to the given destination resource - * - * @param destination - * @param shallow - * @throws DavException - */ - public void copy(DavResource destination, boolean shallow) throws DavException; - - /** - * Returns true, if the this resource allows locking. NOTE, that this method - * does not define, whether a lock/unlock can be successfully executed. - * - * @return true, if this resource supports any locking. - * @param type - * @param scope - */ - public boolean isLockable(Type type, Scope scope); - - /** - * Returns true if a lock applies to this resource. This may be either a - * lock on this resource itself or a deep lock inherited from a collection - * above this resource.
- * Note, that true is returned whenever a lock applies to that resource even - * if the lock is expired or not effective due to the fact that the request - * provides the proper lock token. - * - * @return true if a lock applies to this resource. - * @param type - */ - public boolean hasLock(Type type, Scope scope); - - /** - * Return the lock present on this webdav resource or null - * if the resource is either not locked or not lockable at all. Note, that - * a resource may have a lock that is inherited by a deep lock enforced on - * one of its 'parent' resources. - * - * @return lock information of this resource or null if this - * resource has no lock applying it. If an error occurs while retrieving the - * lock information null is returned as well. - * @param type - */ - public ActiveLock getLock(Type type, Scope scope) ; - - /** - * Returns an array of all locks applied to the given resource. - * - * @return array of locks. The array is empty if there are no locks applied - * to this resource. - */ - public ActiveLock[] getLocks(); - - /** - * Lock this webdav resource with the information retrieve from the request - * and return the resulting lockdiscovery object. - * - * @param reqLockInfo lock info as retrieved from the request. - * @return lockdiscovery object to be returned in the response. If the lock - * could not be obtained a DavException is thrown. - * @throws DavException if the lock could not be obtained. - */ - public ActiveLock lock(LockInfo reqLockInfo) throws DavException; - - /** - * Refresh an existing lock by resetting the timeout. - * - * @param reqLockInfo lock info as retrieved from the request. - * @param lockToken identifying the lock to be refreshed. - * @return lockdiscovery object to be returned in the response body. If the lock - * could not be refreshed a DavException is thrown. - * @throws DavException if the lock could not be refreshed. - */ - public ActiveLock refreshLock(LockInfo reqLockInfo, String lockToken) throws DavException; - - /** - * Remove the lock identified by the included lock token from this resource. - * This method will return false if the unlocking did not succeed. - * - * @param lockToken identifying the lock to be removed. - * @throws DavException if the lock could not be removed. - */ - public void unlock(String lockToken) throws DavException; - - /** - * Add an external {@link LockManager} to this resource. This method may - * throw {@link UnsupportedOperationException} if the resource does handle - * locking itself. - * - * @param lockmgr - * @see LockManager - */ - public void addLockManager(LockManager lockmgr); - - /** - * Return the DavResourceFactory that created this resource. - * - * @return the factory that created this resource. - */ - public DavResourceFactory getFactory(); - - /** - * Retrieve the DavSession associated with this resource. - * - * @return session object associated with this resource. - */ - public DavSession getSession(); -} - Property changes on: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/DavResource.java ___________________________________________________________________ Deleted: svn Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/DavResourceFactory.java =================================================================== --- jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/DavResourceFactory.java (revision 1907912) +++ jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/DavResourceFactory.java (nonexistent) @@ -1,46 +0,0 @@ -/* - * 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.webdav; - -/** - * DavResourceFactory interface defines a single method for creating - * {@link DavResource} objects. - */ -public interface DavResourceFactory { - - /** - * Create a {@link DavResource} object from the given locator, request and response - * objects. - * - * @param locator locator of the resource - * @param request - * @param response - * @return a new DavResource object. - * @throws DavException - */ - public DavResource createResource(DavResourceLocator locator, DavServletRequest request, DavServletResponse response) throws DavException; - - /** - * Create a new {@link DavResource} object from the given locator and session. - * - * @param locator - * @param session - * @return a new DavResource object. - * @throws DavException - */ - public DavResource createResource(DavResourceLocator locator, DavSession session) throws DavException; -} \ No newline at end of file Property changes on: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/DavResourceFactory.java ___________________________________________________________________ Deleted: svn Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/DavResourceIterator.java =================================================================== --- jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/DavResourceIterator.java (revision 1907912) +++ jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/DavResourceIterator.java (nonexistent) @@ -1,39 +0,0 @@ -/* - * 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.webdav; - -import java.util.Iterator; - -/** - * DavResourceIterator extends the Iterator interface. Additional - * METHODS allow to retrieve the next {@link DavResource} from the iterator - * and the iterators size. - */ -public interface DavResourceIterator extends Iterator { - - /** - * Returns the next {@link DavResource} in the iterator - * @return the next {@link DavResource} - */ - public DavResource nextResource(); - - /** - * Return the number of {@link DavResource}s in the iterator. - * @return number of elements in the iterator. - */ - public int size(); -} Property changes on: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/DavResourceIterator.java ___________________________________________________________________ Deleted: svn Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/DavResourceIteratorImpl.java =================================================================== --- jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/DavResourceIteratorImpl.java (revision 1907912) +++ jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/DavResourceIteratorImpl.java (nonexistent) @@ -1,85 +0,0 @@ -/* - * 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.webdav; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.Iterator; -import java.util.List; -import java.util.Collections; - -/** - * DavResourceIteratorImpl implementation of the {@link DavResourceIterator} - * interface.
- * NOTE: {@link #remove()} is not implemented. - */ -public class DavResourceIteratorImpl implements DavResourceIterator { - - private static Logger log = LoggerFactory.getLogger(DavResourceIteratorImpl.class); - - public static final DavResourceIterator EMPTY = new DavResourceIteratorImpl(Collections.emptyList()); - - private Iterator it; - private int size; - - /** - * Create a new DavResourceIterator from the specified list. - * @param list - */ - public DavResourceIteratorImpl(List list) { - it = list.iterator(); - size = list.size(); - } - - /** - * @see DavResourceIterator#hasNext() - */ - public boolean hasNext() { - return it.hasNext(); - } - - /** - * @see DavResourceIterator#next() - */ - public DavResource next() { - return it.next(); - } - - /** - * @see DavResourceIterator#nextResource() - */ - public DavResource nextResource() { - return next(); - } - - /** - * Returns the size of the initial list. - * - * @see DavResourceIterator#size() - */ - public int size() { - return size; - } - - /** - * @see DavResourceIterator#remove() - */ - public void remove() { - throw new UnsupportedOperationException("Remove not allowed with DavResourceIteratorImpl"); - } -} Property changes on: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/DavResourceIteratorImpl.java ___________________________________________________________________ Deleted: svn Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/DavResourceLocator.java =================================================================== --- jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/DavResourceLocator.java (revision 1907912) +++ jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/DavResourceLocator.java (nonexistent) @@ -1,115 +0,0 @@ -/* - * 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.webdav; - -/** - * DavResourceLocator... - */ -public interface DavResourceLocator { - - /** - * Return the prefix used to build the complete href of the resource as - * required for the {@link DavConstants#XML_HREF href Xml} element. - * This includes scheme and host information as well as constant prefixes. - * However, this must not include workspace prefix. - * - * @return prefix needed in order to build the href from a resource path. - * @see #getResourcePath() - */ - public String getPrefix(); - - /** - * Return the resource path. - * - * @return resource path - */ - public String getResourcePath(); - - /** - * Return the path of the workspace the resource identified by this - * locator is member of. - * - * @return path of the workspace - */ - public String getWorkspacePath(); - - /** - * Return the name of the workspace the resource identified by this - * locator is member of. - * - * @return workspace name - */ - public String getWorkspaceName(); - - /** - * Returns true if the specified locator refers to a resource within the - * same workspace. - * - * @param locator - * @return true if both paths are in the same workspace. - */ - public boolean isSameWorkspace(DavResourceLocator locator); - - /** - * Returns true if the specified workspace name equals to the workspace - * name defined with this locator. - * - * @param workspaceName - * @return true if workspace names are equal. - */ - public boolean isSameWorkspace(String workspaceName); - - /** - * Return the 'href' representation of this locator object. The implementation - * should perform an URL encoding of the resource path. - * - * @param isCollection - * @return 'href' representation of this path - * @see DavConstants#XML_HREF - * @see DavResource#getHref() - */ - public String getHref(boolean isCollection); - - /** - * Returns true if this DavResourceLocator represents the root - * locator that would be requested with 'hrefPrefix'+'pathPrefix' with or - * without a trailing '/'. - * - * @return true if this locator object belongs to the root resource. - */ - public boolean isRootLocation(); - - /** - * Return the locator factory that created this locator. - * - * @return the locator factory - */ - public DavLocatorFactory getFactory(); - - /** - * An implementation may choose to circumvent the incompatibility of a - * repository path with the URI path by applying an appropriate conversion. - * This utility method allows to retrieve this transformed repository path. - * By default this method should return the same as {@link #getResourcePath()} - * - * @return a repository compatible form if the resource path. - * @see DavLocatorFactory#createResourceLocator(String, String, String, boolean) - * that allows to build a valid DavResourceLocator from a given - * repository path. - */ - public String getRepositoryPath(); -} \ No newline at end of file Property changes on: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/DavResourceLocator.java ___________________________________________________________________ Deleted: svn Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/DavServletRequest.java =================================================================== --- jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/DavServletRequest.java (revision 1907912) +++ jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/DavServletRequest.java (nonexistent) @@ -1,199 +0,0 @@ -/* - * 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.webdav; - -import org.apache.jackrabbit.webdav.lock.LockInfo; -import org.apache.jackrabbit.webdav.property.DavPropertyNameSet; -import org.apache.jackrabbit.webdav.property.DavProperty; -import org.apache.jackrabbit.webdav.property.DavPropertyName; -import org.apache.jackrabbit.webdav.property.PropEntry; -import org.w3c.dom.Document; - -import javax.servlet.http.HttpServletRequest; -import java.util.List; - -/** - * DavServletRequest extends the HttpServletRequest by Webdav - * specific METHODS. - */ -public interface DavServletRequest extends HttpServletRequest { - - /** - * Sets the DavSession to this request. - * - * @param session - */ - public void setDavSession(DavSession session); - - /** - * Returns the {@link DavSession} created for this request. - * - * @return session for this resource - */ - public DavSession getDavSession(); - - /** - * Return the locator of the requested {@link DavResource resource}. - * - * @return locator of the requested {@link DavResource resource}. - */ - public DavResourceLocator getRequestLocator(); - - /** - * Parse the {@link DavConstants#HEADER_DESTINATION Destination header} - * and return the locator of the corresponding {@link DavResource resource}. - * - * @return locator of the resource specified with the Destination header. - * @see DavConstants#HEADER_DESTINATION - */ - public DavResourceLocator getDestinationLocator() throws DavException; - - /** - * Returns true if the {@link DavConstants#HEADER_OVERWRITE Overwrite header} - * is set to 'T' thus instructing the server to overwrite the state of a - * non-null destination resource during a COPY or MOVE. A Overwrite header - * value of 'F' will return false. - * - * @return true if the Overwrite header is set to 'T', false if it is set - * to 'F'. - * @see DavConstants#HEADER_OVERWRITE - */ - public boolean isOverwrite(); - - /** - * Return the integer representation of the given {@link DavConstants#HEADER_DEPTH - * Depth header}. 'Infinity' is represented by {@link DavConstants#DEPTH_INFINITY}. - * - * @return integer representation of the {@link DavConstants#HEADER_DEPTH - * Depth header}. - * @see DavConstants#HEADER_DEPTH - */ - public int getDepth(); - - /** - * Returns the integer representation of the {@link DavConstants#HEADER_DEPTH - * Depth header} or the given defaultValue, if the Depth header is missing. - * - * @param defaultValue to be returned if no Depth header is present. - * @return integer representation of the {@link DavConstants#HEADER_DEPTH - * Depth header} or the given defaultValue. - * @see DavConstants#HEADER_DEPTH - */ - public int getDepth(int defaultValue); - - /** - * Returns the token present in the {@link DavConstants#HEADER_LOCK_TOKEN - * Lock-Token Header} or null if no such header is available.
- * Note: The 'Lock-Token' header is sent with UNLOCK requests and with - * lock responses only. For any other request that may be affected by a lock - * the 'If' header field is responsible. - * - * @return the token present in the Lock-Token header. - * @see DavConstants#HEADER_LOCK_TOKEN - */ - public String getLockToken(); - - /** - * Return the timeout requested in the {@link DavConstants#HEADER_TIMEOUT - * Timeout header} as long. The representation of the - * 'Infinite' timeout is left to the implementation. - * - * @return long value representation of the Timeout header. - * @see DavConstants#HEADER_TIMEOUT - * @see DavConstants#TIMEOUT_INFINITE - */ - public long getTimeout(); - - /** - * Parse the Xml request body and return a {@link org.w3c.dom.Document}. - * - * @return Document representing the Xml request body or null - * if no request body is present. - * @throws DavException If the request body cannot be parsed into an Xml - * Document. - */ - public Document getRequestDocument() throws DavException; - - /** - * Return the type of PROPFIND request as indicated by the PROPFIND request - * body. - * - * @return type of PROPFIND request - * @see DavConstants#PROPFIND_ALL_PROP - * @see DavConstants#PROPFIND_BY_PROPERTY - * @see DavConstants#PROPFIND_PROPERTY_NAMES - * @see DavConstants#PROPFIND_ALL_PROP_INCLUDE - * @throws DavException If the propfind type could not be determined due to - * an invalid request body. - */ - public int getPropFindType() throws DavException; - - /** - * Return the set of properties the client requested with a PROPFIND request - * or an empty set if the type of PROPFIND request was {@link DavConstants#PROPFIND_ALL_PROP} - * or {@link DavConstants#PROPFIND_PROPERTY_NAMES}. - * - * @return set of properties the client requested with a PROPFIND request - * @throws DavException In case of invalid request body - */ - public DavPropertyNameSet getPropFindProperties() throws DavException; - - /** - * Return a {@link List} of property change operations. Each entry - * is either of type {@link DavPropertyName}, indicating a <remove> - * operation, or of type {@link DavProperty}, indicating a <set> - * operation. Note that ordering is significant here. - * - * @return {@link List} of property change operations - * @throws DavException In case of invalid request body - */ - public List getPropPatchChangeList() throws DavException; - - /** - * Return the parsed 'lockinfo' request body, the {@link DavConstants#HEADER_TIMEOUT - * Timeout header} and the {@link DavConstants#HEADER_DEPTH Depth header} - * of a LOCK request as LockInfo object. - * - * @return LockInfo object encapsulating the information - * present in the LOCK request. - * @see DavConstants#HEADER_TIMEOUT - * @see DavConstants#HEADER_DEPTH - * @see DavConstants#XML_LOCKINFO - * @throws DavException - */ - public LockInfo getLockInfo() throws DavException; - - /** - * Returns true, if the {@link DavConstants#HEADER_IF If header} present - * with the request matches the given resource. - * - * @param resource - * @return true, if the test is successful, false otherwise. - */ - public boolean matchesIfHeader(DavResource resource); - - /** - * Returns true, if the {@link DavConstants#HEADER_IF If header} present - * with the request matches to the given href, token and eTag. - * - * @param href - * @param token - * @param eTag - * @return true, if the test is successful, false otherwise. - */ - public boolean matchesIfHeader(String href, String token, String eTag); -} Property changes on: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/DavServletRequest.java ___________________________________________________________________ Deleted: svn Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/DavServletResponse.java =================================================================== --- jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/DavServletResponse.java (revision 1907912) +++ jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/DavServletResponse.java (nonexistent) @@ -1,149 +0,0 @@ -/* - * 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.webdav; - -import org.apache.jackrabbit.webdav.lock.ActiveLock; -import org.apache.jackrabbit.webdav.xml.XmlSerializable; - -import javax.servlet.http.HttpServletResponse; -import java.io.IOException; -import java.util.List; - -/** - * WebdavResponse extends the HttpServletResponse by - * Webdav specific status codes and METHODS. - */ -public interface DavServletResponse extends HttpServletResponse { - - /** - * The 102 (Processing) status code is an interim response used to - * inform the client that the server has accepted the complete request, - * but has not yet completed it. - */ - int SC_PROCESSING = 102; - - /** - * Status code (207) indicating that the response requires - * providing status for multiple independent operations. - */ - int SC_MULTI_STATUS = 207; - - /** - * The 422 (Unprocessable Entity) status code means the server understands - * the content type of the request entity (hence a 415(Unsupported Media Type) - * status code is inappropriate), and the syntax of the request entity is - * correct (thus a 400 (Bad Request) status code is inappropriate) but was - * unable to process the contained instructions. For example, this error - * condition may occur if an XML request body contains well-formed (i.e., - * syntactically correct), but semantically erroneous XML instructions. - */ - int SC_UNPROCESSABLE_ENTITY = 422; - - /** - * Status code (423) indicating the destination resource of a - * method is locked, and either the request did not contain a - * valid Lock-Info header, or the Lock-Info header identifies - * a lock held by another principal. - */ - int SC_LOCKED = 423; - - /** - * Status code (424) indicating that the method could not be - * performed on the resource, because the requested action depended - * on another action which failed. - */ - int SC_FAILED_DEPENDENCY = 424; - - /** - * Status code (507) indicating that the resource does not have - * sufficient space to record the state of the resource after the - * execution of this method. - */ - int SC_INSUFFICIENT_SPACE_ON_RESOURCE = 507; - - /** - * Send a response body given more detailed information about the error - * occurred. - * - * @param error - * @throws IOException - */ - public void sendError(DavException error) throws IOException; - - /** - * Send the multistatus response to the client. A multistatus response - * is returned in response to a successful PROPFIND and PROPPATCH request. - * In addition multistatus response is required response in case a COPY, - * MOVE, DELETE, LOCK or PROPPATCH request fails. - * - * @param multistatus - * @throws IOException - * @see #SC_MULTI_STATUS - */ - public void sendMultiStatus(MultiStatus multistatus) throws IOException; - - /** - * Send the multistatus response to the client. A multistatus response - * is returned in response to a successful PROPFIND and PROPPATCH request. - * In addition multistatus response is required response in case a COPY, - * MOVE, DELETE, LOCK or PROPPATCH request fails. - * - * @param multistatus - * @param acceptableContentCodings content codings accepted by the client - * @throws IOException - * @see #SC_MULTI_STATUS - */ - default void sendMultiStatus(MultiStatus multistatus, List acceptableContentCodings) throws IOException { - sendMultiStatus(multistatus); - } - - /** - * Send the lock response for a successful LOCK request, that was intended - * to refresh an existing lock. The locks array must contain at least - * a single element; the ActiveLock objects are then - * included in the lockdiscovery property of the response body as required - * by RFC 2518. - * - * @param locks - * @throws IOException - * @see DavConstants#PROPERTY_LOCKDISCOVERY - */ - public void sendRefreshLockResponse(ActiveLock[] locks) throws IOException; - - /** - * Generic method to return an Xml response body. - * - * @param serializable object that can be converted to the root Xml element - * of the document to be sent as response body. - * @param status Status code to be used with {@link #setStatus(int)}. - * @throws IOException - */ - public void sendXmlResponse(XmlSerializable serializable, int status) throws IOException; - - /** - * Generic method to return an Xml response body. - * - * @param serializable object that can be converted to the root Xml element - * of the document to be sent as response body. - * @param status Status code to be used with {@link #setStatus(int)}. - * @param acceptableContentCodings content codings accepted by the client - * @throws IOException - */ - default void sendXmlResponse(XmlSerializable serializable, int status, List acceptableContentCodings) throws IOException { - sendXmlResponse(serializable, status); - } -} \ No newline at end of file Property changes on: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/DavServletResponse.java ___________________________________________________________________ Deleted: svn Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/DavSession.java =================================================================== --- jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/DavSession.java (revision 1907912) +++ jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/DavSession.java (nonexistent) @@ -1,62 +0,0 @@ -/* - * 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.webdav; - -/** - * DavSession allows to pass session information between request, - * response and resource(s). - */ -public interface DavSession { - - /** - * Adds a reference to this DavSession indicating that this - * session must not be discarded after completion of the current request. - * - * @param reference to be added. - */ - public void addReference(Object reference); - - /** - * Releasing a reference to this DavSession. If no more - * references are present, this session may be discarded. - * - * @param reference to be removed. - */ - public void removeReference(Object reference); - - /** - * Adds a lock token to this DavSession. - * - * @param token - */ - public void addLockToken(String token); - - /** - * Returns the lock tokens of this DavSession. - * - * @return - */ - public String[] getLockTokens(); - - /** - * Removes a lock token from this DavSession. - * - * @param token - */ - public void removeLockToken(String token); - -} \ No newline at end of file Property changes on: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/DavSession.java ___________________________________________________________________ Deleted: svn Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/DavSessionProvider.java =================================================================== --- jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/DavSessionProvider.java (revision 1907912) +++ jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/DavSessionProvider.java (nonexistent) @@ -1,48 +0,0 @@ -/* - * 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.webdav; - -/** - * DavSessionProvider is an interface for components that - * can initiate and complete {@link DavSession}s. A provider is - * responsible for supplying references from a {@link WebdavRequest} - * to a {@link DavSession} when acquired and removing the references - * when released. - - */ -public interface DavSessionProvider { - - /** - * Acquires a DavSession. Upon success, the WebdavRequest will - * reference that session. - * - * A session will not be available if an exception is thrown. - * - * @param request - * @return true if the session was attached to the request; - * false otherwise. - * @throws DavException if a problem occurred while obtaining the session - */ - public boolean attachSession(WebdavRequest request) throws DavException; - - /** - * Releases the reference from the request to the session. - * - * @param request - */ - public void releaseSession(WebdavRequest request); -} Property changes on: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/DavSessionProvider.java ___________________________________________________________________ Deleted: svn Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/MultiStatus.java =================================================================== --- jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/MultiStatus.java (revision 1907912) +++ jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/MultiStatus.java (nonexistent) @@ -1,193 +0,0 @@ -/* - * 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.webdav; - -import org.apache.jackrabbit.webdav.property.DavPropertyNameSet; -import org.apache.jackrabbit.webdav.xml.DomUtil; -import org.apache.jackrabbit.webdav.xml.ElementIterator; -import org.apache.jackrabbit.webdav.xml.XmlSerializable; -import org.w3c.dom.Document; -import org.w3c.dom.Element; - -import java.util.LinkedHashMap; -import java.util.Map; - -/** - * MultiStatus representing the content of a multistatus response body and - * allows to retrieve the Xml representation. - */ -public class MultiStatus implements DavConstants, XmlSerializable { - - /** - * Map collecting the responses for this multistatus, where every href must - * only occur one single time. - */ - private Map responses = new LinkedHashMap(); - - /** - * A general response description at the multistatus top level is used to - * provide a general message describing the overarching nature of the response. - * If this value is available an application may use it instead of - * presenting the individual response descriptions contained within the - * responses. - */ - private String responseDescription; - - /** - * Add response(s) to this multistatus, in order to build a multistatus for - * responding to a PROPFIND request. - * - * @param resource The resource to add property from - * @param propNameSet The requested property names of the PROPFIND request - * @param propFindType - * @param depth - */ - public void addResourceProperties(DavResource resource, DavPropertyNameSet propNameSet, - int propFindType, int depth) { - addResponse(new MultiStatusResponse(resource, propNameSet, propFindType)); - if (depth > 0 && resource.isCollection()) { - DavResourceIterator iter = resource.getMembers(); - while (iter.hasNext()) { - addResourceProperties(iter.nextResource(), propNameSet, propFindType, depth-1); - } - } - } - - /** - * Add response(s) to this multistatus, in order to build a multistatus e.g. - * in order to respond to a PROPFIND request. Please note, that in terms - * of PROPFIND, this method would correspond to a - * {@link DavConstants#PROPFIND_BY_PROPERTY} propfind type. - * - * @param resource The resource to add property from - * @param propNameSet The requested property names of the PROPFIND request - * @param depth - * @see #addResourceProperties(DavResource, DavPropertyNameSet, int, int) for - * the corresponding method that allows to specify the type. - */ - public void addResourceProperties(DavResource resource, DavPropertyNameSet propNameSet, - int depth) { - addResourceProperties(resource, propNameSet, PROPFIND_BY_PROPERTY, depth); - } - - /** - * Add response(s) to this multistatus, in order to build a multistatus - * as returned for COPY, MOVE, LOCK or DELETE requests resulting in an error - * with a resource other than the resource identified in the Request-URI. - * - * @param resource - * @param status - * @param depth - */ - public void addResourceStatus(DavResource resource, int status, int depth) { - addResponse(new MultiStatusResponse(resource.getHref(), status)); - if (depth > 0 && resource.isCollection()) { - DavResourceIterator iter = resource.getMembers(); - while (iter.hasNext()) { - addResourceStatus(iter.nextResource(), status, depth-1); - } - } - } - - /** - * Add a MultiStatusResponse element to this MultiStatus - *

- * This method is synchronized to avoid the problem described in - * JCR-2755. - * - * @param response - */ - public synchronized void addResponse(MultiStatusResponse response) { - responses.put(response.getHref(), response); - } - - /** - * Returns the multistatus responses present as array. - *

- * This method is synchronized to avoid the problem described in - * JCR-2755. - * - * @return array of all {@link MultiStatusResponse responses} present in this - * multistatus. - */ - public synchronized MultiStatusResponse[] getResponses() { - return responses.values().toArray(new MultiStatusResponse[responses.size()]); - } - - /** - * Set the response description. - * - * @param responseDescription - */ - public void setResponseDescription(String responseDescription) { - this.responseDescription = responseDescription; - } - - /** - * Returns the response description. - * - * @return responseDescription - */ - public String getResponseDescription() { - return responseDescription; - } - - /** - * Return the Xml representation of this MultiStatus. - * - * @return Xml document - * @param document - */ - public Element toXml(Document document) { - Element multistatus = DomUtil.createElement(document, XML_MULTISTATUS, NAMESPACE); - for (MultiStatusResponse resp : getResponses()) { - multistatus.appendChild(resp.toXml(document)); - } - if (responseDescription != null) { - Element respDesc = DomUtil.createElement(document, XML_RESPONSEDESCRIPTION, NAMESPACE, responseDescription); - multistatus.appendChild(respDesc); - } - return multistatus; - } - - /** - * Build a MultiStatus from the specified xml element. - * - * @param multistatusElement - * @return new MultiStatus instance. - * @throws IllegalArgumentException if the given document is null - * or does not provide the required element. - */ - public static MultiStatus createFromXml(Element multistatusElement) { - if (!DomUtil.matches(multistatusElement, XML_MULTISTATUS, NAMESPACE)) { - throw new IllegalArgumentException("DAV:multistatus element expected."); - } - - MultiStatus multistatus = new MultiStatus(); - - ElementIterator it = DomUtil.getChildren(multistatusElement, XML_RESPONSE, NAMESPACE); - while (it.hasNext()) { - Element respElem = it.nextElement(); - MultiStatusResponse response = MultiStatusResponse.createFromXml(respElem); - multistatus.addResponse(response); - } - - // optional response description on the multistatus element - multistatus.setResponseDescription(DomUtil.getChildText(multistatusElement, XML_RESPONSEDESCRIPTION, NAMESPACE)); - return multistatus; - } -} Property changes on: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/MultiStatus.java ___________________________________________________________________ Deleted: svn Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/MultiStatusResponse.java =================================================================== --- jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/MultiStatusResponse.java (revision 1907912) +++ jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/MultiStatusResponse.java (nonexistent) @@ -1,486 +0,0 @@ -/* - * 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.webdav; - -import org.apache.jackrabbit.webdav.property.DavProperty; -import org.apache.jackrabbit.webdav.property.DavPropertyName; -import org.apache.jackrabbit.webdav.property.DavPropertyNameSet; -import org.apache.jackrabbit.webdav.property.DavPropertySet; -import org.apache.jackrabbit.webdav.property.DefaultDavProperty; -import org.apache.jackrabbit.webdav.property.PropContainer; -import org.apache.jackrabbit.webdav.xml.DomUtil; -import org.apache.jackrabbit.webdav.xml.ElementIterator; -import org.apache.jackrabbit.webdav.xml.XmlSerializable; -import org.w3c.dom.Document; -import org.w3c.dom.Element; - -import java.util.HashMap; -import java.util.HashSet; -import java.util.Iterator; -import java.util.Set; - -/** - * MultiStatusResponse represents the DAV:multistatus element defined - * by RFC 2518: - *

- * <!ELEMENT response (href, ((href*, status)|(propstat+)), responsedescription?) >
- * <!ELEMENT status (#PCDATA) >
- * <!ELEMENT propstat (prop, status, responsedescription?) >
- * <!ELEMENT responsedescription (#PCDATA) >
- * <!ELEMENT prop ANY >
- * 
- */ -public class MultiStatusResponse implements XmlSerializable, DavConstants { - - private static final int TYPE_PROPSTAT = 0; - private static final int TYPE_HREFSTATUS = 1; - - /** - * The type of MultiStatusResponse - */ - private final int type; - - /** - * The content the 'href' element for this response - */ - private final String href; - - /** - * An optional response description. - */ - private final String responseDescription; - - /** - * Type of MultiStatus response: Href + Status - */ - private Status status; - - /** - * Type of MultiStatus response: PropStat Hashmap containing all status - */ - private HashMap statusMap = new HashMap(); - - private MultiStatusResponse(String href, String responseDescription, int type) { - if (!isValidHref(href)) { - throw new IllegalArgumentException("Invalid href ('" + href + "')"); - } - this.href = href; - this.responseDescription = responseDescription; - this.type = type; - } - - /** - * Constructs an WebDAV multistatus response - * - * @param href - * @param status - * @param responseDescription - */ - public MultiStatusResponse(String href, Status status, String responseDescription) { - this(href, responseDescription, TYPE_HREFSTATUS); - if (status == null) { - throw new IllegalArgumentException("Status must not be null in case of a multistatus reponse that consists of href + status only."); - } - this.status = status; - } - - /** - * Constructs an WebDAV multistatus response for a given resource. This - * would be used by COPY, MOVE, DELETE, LOCK that require a multistatus in - * case of error with a resource other than the resource identified in the - * Request-URI.
- * The response description is set to null. - * - * @param href - * @param statusCode - */ - public MultiStatusResponse(String href, int statusCode) { - this(href, statusCode, null); - } - - /** - * Constructs an WebDAV multistatus response for a given resource. This - * would be used by COPY, MOVE, DELETE, LOCK that require a multistatus in - * case of error with a resource other than the resource identified in the - * Request-URI. - * - * @param href - * @param statusCode - * @param responseDescription - */ - public MultiStatusResponse(String href, int statusCode, String responseDescription) { - this(href, new Status(statusCode), responseDescription); - } - - /** - * Constructs an empty WebDAV multistatus response of type 'PropStat' - */ - public MultiStatusResponse(String href, String responseDescription) { - this(href, responseDescription, TYPE_PROPSTAT); - } - - /** - * Constructs a WebDAV multistatus response and retrieves the resource - * properties according to the given DavPropertyNameSet. - * - * @param resource - * @param propNameSet - */ - public MultiStatusResponse(DavResource resource, DavPropertyNameSet propNameSet) { - this(resource, propNameSet, PROPFIND_BY_PROPERTY); - } - - /** - * Constructs a WebDAV multistatus response and retrieves the resource - * properties according to the given DavPropertyNameSet. It - * adds all known property to the '200' set, while unknown properties are - * added to the '404' set. - *

- * Note, that the set of property names is ignored in case of a {@link - * #PROPFIND_ALL_PROP} and {@link #PROPFIND_PROPERTY_NAMES} propFindType. - * - * @param resource The resource to retrieve the property from - * @param propNameSet The property name set as obtained from the request - * body. - * @param propFindType any of the following values: {@link - * #PROPFIND_ALL_PROP}, {@link #PROPFIND_BY_PROPERTY}, {@link - * #PROPFIND_PROPERTY_NAMES}, {@link #PROPFIND_ALL_PROP_INCLUDE} - */ - public MultiStatusResponse( - DavResource resource, DavPropertyNameSet propNameSet, - int propFindType) { - this(resource.getHref(), null, TYPE_PROPSTAT); - - if (propFindType == PROPFIND_PROPERTY_NAMES) { - // only property names requested - PropContainer status200 = getPropContainer(DavServletResponse.SC_OK, true); - for (DavPropertyName propName : resource.getPropertyNames()) { - status200.addContent(propName); - } - } else { - // all or a specified set of property and their values requested. - PropContainer status200 = getPropContainer(DavServletResponse.SC_OK, false); - - // Collection of missing property names for 404 responses - Set missing = new HashSet(propNameSet.getContent()); - - // Add requested properties or all non-protected properties, - // or non-protected properties plus requested properties (allprop/include) - if (propFindType == PROPFIND_BY_PROPERTY) { - // add explicitly requested properties (proptected or non-protected) - for (DavPropertyName propName : propNameSet) { - DavProperty prop = resource.getProperty(propName); - if (prop != null) { - status200.addContent(prop); - missing.remove(propName); - } - } - } else { - // add all non-protected properties - for (DavProperty property : resource.getProperties()) { - boolean allDeadPlusRfc4918LiveProperties = - propFindType == PROPFIND_ALL_PROP - || propFindType == PROPFIND_ALL_PROP_INCLUDE; - boolean wasRequested = missing.remove(property.getName()); - - if ((allDeadPlusRfc4918LiveProperties - && !property.isInvisibleInAllprop()) - || wasRequested) { - status200.addContent(property); - } - } - - // try if missing properties specified in the include section - // can be obtained using resource.getProperty - if (propFindType == PROPFIND_ALL_PROP_INCLUDE && !missing.isEmpty()) { - for (DavPropertyName propName : new HashSet(missing)) { - DavProperty prop = resource.getProperty(propName); - if (prop != null) { - status200.addContent(prop); - missing.remove(propName); - } - } - } - } - - if (!missing.isEmpty() && propFindType != PROPFIND_ALL_PROP) { - PropContainer status404 = getPropContainer(DavServletResponse.SC_NOT_FOUND, true); - for (DavPropertyName propName : missing) { - status404.addContent(propName); - } - } - } - } - - /** - * Returns the href - * - * @return href - * @see MultiStatusResponse#getHref() - */ - public String getHref() { - return href; - } - - /** - * @return responseDescription - * @see MultiStatusResponse#getResponseDescription() - */ - public String getResponseDescription() { - return responseDescription; - } - - /** - * Return an array listing all 'status' available is this response object. - * Note, that a the array contains a single element if this - * MultiStatusResponse defines an response consisting of - * href and status elements. - * - * @return - */ - public Status[] getStatus() { - Status[] sts; - if (type == TYPE_PROPSTAT) { - sts = new Status[statusMap.size()]; - Iterator iter = statusMap.keySet().iterator(); - for (int i = 0; iter.hasNext(); i++) { - Integer statusKey = iter.next(); - sts[i] = new Status(statusKey); - } - } else { - sts = new Status[] {status}; - } - return sts; - } - - /** - * @return {@code true} if the response is of type "propstat" (containing information about individual properties) - */ - public boolean isPropStat() { - return this.type == TYPE_PROPSTAT; - } - - /** - * @param document - * @see org.apache.jackrabbit.webdav.xml.XmlSerializable#toXml(org.w3c.dom.Document) - */ - public Element toXml(Document document) { - Element response = DomUtil.createElement(document, XML_RESPONSE, NAMESPACE); - // add '' - response.appendChild(DomUtil.hrefToXml(getHref(), document)); - if (type == TYPE_PROPSTAT) { - // add '' elements - for (Integer statusKey : statusMap.keySet()) { - Status st = new Status(statusKey); - PropContainer propCont = statusMap.get(statusKey); - if (!propCont.isEmpty()) { - Element propstat = DomUtil.createElement(document, XML_PROPSTAT, NAMESPACE); - propstat.appendChild(propCont.toXml(document)); - propstat.appendChild(st.toXml(document)); - response.appendChild(propstat); - } - } - } else { - // add a single '' element - // NOTE: a href+status response cannot be created with 'null' status - response.appendChild(status.toXml(document)); - } - // add the optional '' element - String description = getResponseDescription(); - if (description != null) { - Element desc = DomUtil.createElement(document, XML_RESPONSEDESCRIPTION, NAMESPACE); - DomUtil.setText(desc, description); - response.appendChild(desc); - } - return response; - } - //----------------------------------------------< type specific methods >--- - /** - * Adds a property to this response '200' propstat set. - * - * @param property the property to add - */ - public void add(DavProperty property) { - checkType(TYPE_PROPSTAT); - PropContainer status200 = getPropContainer(DavServletResponse.SC_OK, false); - status200.addContent(property); - } - - /** - * Adds a property name to this response '200' propstat set. - * - * @param propertyName the property name to add - */ - public void add(DavPropertyName propertyName) { - checkType(TYPE_PROPSTAT); - PropContainer status200 = getPropContainer(DavServletResponse.SC_OK, true); - status200.addContent(propertyName); - } - - /** - * Adds a property to this response - * - * @param property the property to add - * @param status the status of the response set to select - */ - public void add(DavProperty property, int status) { - checkType(TYPE_PROPSTAT); - PropContainer propCont = getPropContainer(status, false); - propCont.addContent(property); - } - - /** - * Adds a property name to this response - * - * @param propertyName the property name to add - * @param status the status of the response set to select - */ - public void add(DavPropertyName propertyName, int status) { - checkType(TYPE_PROPSTAT); - PropContainer propCont = getPropContainer(status, true); - propCont.addContent(propertyName); - } - - /** - * @param status - * @return - */ - private PropContainer getPropContainer(int status, boolean forNames) { - PropContainer propContainer = statusMap.get(status); - if (propContainer == null) { - if (forNames) { - propContainer = new DavPropertyNameSet(); - } else { - propContainer = new DavPropertySet(); - } - statusMap.put(status, propContainer); - } - return propContainer; - } - - private void checkType(int type) { - if (this.type != type) { - throw new IllegalStateException("The given MultiStatusResponse is not of the required type."); - } - } - - /** - * Get properties present in this response for the given status code. In - * case this MultiStatusResponse does not represent a 'propstat' response, - * always an empty {@link DavPropertySet} will be returned. - * - * @param status - * @return property set - */ - public DavPropertySet getProperties(int status) { - if (statusMap.containsKey(status)) { - PropContainer mapEntry = statusMap.get(status); - if (mapEntry != null && mapEntry instanceof DavPropertySet) { - return (DavPropertySet) mapEntry; - } - } - return new DavPropertySet(); - } - - /** - * Get property names present in this response for the given status code. In - * case this MultiStatusResponse does not represent a 'propstat' response, - * always an empty {@link DavPropertyNameSet} will be returned. - * - * @param status - * @return property names - */ - public DavPropertyNameSet getPropertyNames(int status) { - if (statusMap.containsKey(status)) { - PropContainer mapEntry = statusMap.get(status); - if (mapEntry != null) { - if (mapEntry instanceof DavPropertySet) { - DavPropertyNameSet set = new DavPropertyNameSet(); - for (DavPropertyName name : ((DavPropertySet) mapEntry).getPropertyNames()) { - set.add(name); - } - return set; - } else { - // is already a DavPropertyNameSet - return (DavPropertyNameSet) mapEntry; - } - } - } - return new DavPropertyNameSet(); - } - - /** - * Build a new response object from the given xml element. - * - * @param responseElement - * @return new MultiStatusResponse instance - * @throws IllegalArgumentException if the specified element is - * null or not a DAV:response element or if the mandatory - * DAV:href child is missing. - */ - public static MultiStatusResponse createFromXml(Element responseElement) { - if (!DomUtil.matches(responseElement, XML_RESPONSE, NAMESPACE)) { - throw new IllegalArgumentException("DAV:response element required."); - } - String href = DomUtil.getChildTextTrim(responseElement, XML_HREF, NAMESPACE); - if (href == null) { - throw new IllegalArgumentException("DAV:response element must contain a DAV:href element expected."); - } - String statusLine = DomUtil.getChildText(responseElement, XML_STATUS, NAMESPACE); - String responseDescription = DomUtil.getChildText(responseElement, XML_RESPONSEDESCRIPTION, NAMESPACE); - - MultiStatusResponse response; - if (statusLine != null) { - Status status = Status.parse(statusLine); - response = new MultiStatusResponse(href, status, responseDescription); - } else { - response = new MultiStatusResponse(href, responseDescription, TYPE_PROPSTAT); - // read propstat elements - ElementIterator it = DomUtil.getChildren(responseElement, XML_PROPSTAT, NAMESPACE); - while (it.hasNext()) { - Element propstat = it.nextElement(); - String propstatus = DomUtil.getChildText(propstat, XML_STATUS, NAMESPACE); - Element prop = DomUtil.getChildElement(propstat, XML_PROP, NAMESPACE); - if (propstatus != null && prop != null) { - int statusCode = Status.parse(propstatus).getStatusCode(); - ElementIterator propIt = DomUtil.getChildren(prop); - while (propIt.hasNext()) { - Element el = propIt.nextElement(); - /* - always build dav property from the given element, since - distinction between prop-names and properties not having - a value is not possible. - retrieval of the set of 'property names' is possible from - the given prop-set by calling DavPropertySet#getPropertyNameSet() - */ - DavProperty property = DefaultDavProperty.createFromXml(el); - response.add(property, statusCode); - } - } - } - } - return response; - } - - /** - * @param href - * @return false if the given href is null or empty string. - */ - private static boolean isValidHref(String href) { - return href != null && !"".equals(href); - } -} Property changes on: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/MultiStatusResponse.java ___________________________________________________________________ Deleted: svn Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/Status.java =================================================================== --- jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/Status.java (revision 1907912) +++ jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/Status.java (nonexistent) @@ -1,123 +0,0 @@ -/* - * 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.webdav; - -import org.apache.jackrabbit.webdav.xml.DomUtil; -import org.apache.jackrabbit.webdav.xml.XmlSerializable; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.w3c.dom.Document; -import org.w3c.dom.Element; - -/** - * Status encapsulating the 'status' present in multistatus - * responses. - */ -public class Status implements DavConstants, XmlSerializable{ - - private static Logger log = LoggerFactory.getLogger(Status.class); - - private final String version; - private final int code; - private final String phrase; - - public Status(int code) { - version = "HTTP/1.1"; - this.code = code; - phrase = DavException.getStatusPhrase(code); - } - - public Status(String version, int code, String phrase) { - this.version = version; - this.code = code; - this.phrase = phrase; - } - - public int getStatusCode() { - return code; - } - - /** - * @see XmlSerializable#toXml(Document) - */ - public Element toXml(Document document) { - String statusLine = version + " " + code + " " + phrase; - Element e = DomUtil.createElement(document, XML_STATUS, NAMESPACE); - DomUtil.setText(e, statusLine); - return e; - } - - /** - * Parse the given status line and return a new Status object. - * - * @param statusLine - * @return a new Status - */ - public static Status parse(String statusLine) { - if (statusLine == null) { - throw new IllegalArgumentException("Unable to parse status line from null xml element."); - } - Status status; - - // code copied from org.apache.commons.httpclient.StatusLine - int length = statusLine.length(); - int at = 0; - int start = 0; - try { - while (Character.isWhitespace(statusLine.charAt(at))) { - ++at; - ++start; - } - if (!"HTTP".equals(statusLine.substring(at, at += 4))) { - log.warn("Status-Line '" + statusLine + "' does not start with HTTP"); - } - //handle the HTTP-Version - at = statusLine.indexOf(' ', at); - if (at <= 0) { - log.warn("Unable to parse HTTP-Version from the status line: '" + statusLine + "'"); - } - String version = (statusLine.substring(start, at)).toUpperCase(); - //advance through spaces - while (statusLine.charAt(at) == ' ') { - at++; - } - //handle the Status-Code - int code; - int to = statusLine.indexOf(' ', at); - if (to < 0) { - to = length; - } - try { - code = Integer.parseInt(statusLine.substring(at, to)); - } catch (NumberFormatException e) { - throw new IllegalArgumentException("Unable to parse status code from status line: '" + statusLine + "'"); - } - //handle the Reason-Phrase - String phrase = ""; - at = to + 1; - if (at < length) { - phrase = statusLine.substring(at).trim(); - } - - status = new Status(version, code, phrase); - - } catch (StringIndexOutOfBoundsException e) { - throw new IllegalArgumentException("Status-Line '" + statusLine + "' is not valid"); - } - return status; - } -} \ No newline at end of file Property changes on: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/Status.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Deleted: svn:keywords ## -1 +0,0 ## -author date id revision url \ No newline at end of property Index: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/WebdavRequest.java =================================================================== --- jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/WebdavRequest.java (revision 1907912) +++ jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/WebdavRequest.java (nonexistent) @@ -1,36 +0,0 @@ -/* - * 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.webdav; - -import org.apache.jackrabbit.webdav.observation.ObservationDavServletRequest; -import org.apache.jackrabbit.webdav.ordering.OrderingDavServletRequest; -import org.apache.jackrabbit.webdav.transaction.TransactionDavServletRequest; -import org.apache.jackrabbit.webdav.version.DeltaVServletRequest; -import org.apache.jackrabbit.webdav.bind.BindServletRequest; - -/** - * The empty WebdavRequest interface collects the functionality - * defined by {@link org.apache.jackrabbit.webdav.DavServletRequest} encapsulating - * the core Webdav specification (RFC 2518) as well as the various extensions - * used for observation and transaction support, ordering of collections, search - * and versioning. - */ -public interface WebdavRequest extends DavServletRequest, - ObservationDavServletRequest, OrderingDavServletRequest, - TransactionDavServletRequest, DeltaVServletRequest, - BindServletRequest { -} Property changes on: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/WebdavRequest.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/WebdavRequestContext.java =================================================================== --- jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/WebdavRequestContext.java (revision 1907912) +++ jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/WebdavRequestContext.java (nonexistent) @@ -1,30 +0,0 @@ -/* - * 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.webdav; - -/** - * Interface providing the minimum WebDAV request information associated with the current thread of execution. - */ -public interface WebdavRequestContext { - - /** - * Return the current {@link WebdavRequest} instance associated with the current thread of execution. - * @return the current {@link WebdavRequest} instance associated with the current thread of execution - */ - public WebdavRequest getRequest(); - -} Property changes on: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/WebdavRequestContext.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/WebdavRequestImpl.java =================================================================== --- jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/WebdavRequestImpl.java (revision 1907912) +++ jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/WebdavRequestImpl.java (nonexistent) @@ -1,1312 +0,0 @@ -/* - * 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.webdav; - -import java.io.BufferedInputStream; -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStream; -import java.io.UnsupportedEncodingException; -import java.net.URI; -import java.net.URISyntaxException; -import java.security.Principal; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Enumeration; -import java.util.Iterator; -import java.util.List; -import java.util.Locale; -import java.util.Map; -import java.util.zip.GZIPInputStream; -import java.util.zip.InflaterInputStream; - -import javax.servlet.AsyncContext; -import javax.servlet.DispatcherType; -import javax.servlet.ReadListener; -import javax.servlet.RequestDispatcher; -import javax.servlet.ServletContext; -import javax.servlet.ServletException; -import javax.servlet.ServletInputStream; -import javax.servlet.ServletRequest; -import javax.servlet.ServletResponse; -import javax.servlet.http.Cookie; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import javax.servlet.http.HttpSession; -import javax.servlet.http.HttpUpgradeHandler; -import javax.servlet.http.Part; -import javax.xml.parsers.ParserConfigurationException; - -import org.apache.jackrabbit.webdav.bind.BindInfo; -import org.apache.jackrabbit.webdav.bind.RebindInfo; -import org.apache.jackrabbit.webdav.bind.UnbindInfo; -import org.apache.jackrabbit.webdav.header.CodedUrlHeader; -import org.apache.jackrabbit.webdav.header.DepthHeader; -import org.apache.jackrabbit.webdav.header.IfHeader; -import org.apache.jackrabbit.webdav.header.LabelHeader; -import org.apache.jackrabbit.webdav.header.OverwriteHeader; -import org.apache.jackrabbit.webdav.header.PollTimeoutHeader; -import org.apache.jackrabbit.webdav.header.TimeoutHeader; -import org.apache.jackrabbit.webdav.lock.LockInfo; -import org.apache.jackrabbit.webdav.lock.Scope; -import org.apache.jackrabbit.webdav.lock.Type; -import org.apache.jackrabbit.webdav.observation.ObservationConstants; -import org.apache.jackrabbit.webdav.observation.SubscriptionInfo; -import org.apache.jackrabbit.webdav.ordering.OrderPatch; -import org.apache.jackrabbit.webdav.ordering.OrderingConstants; -import org.apache.jackrabbit.webdav.ordering.Position; -import org.apache.jackrabbit.webdav.property.DavProperty; -import org.apache.jackrabbit.webdav.property.DavPropertyName; -import org.apache.jackrabbit.webdav.property.DavPropertyNameSet; -import org.apache.jackrabbit.webdav.property.DavPropertySet; -import org.apache.jackrabbit.webdav.property.DefaultDavProperty; -import org.apache.jackrabbit.webdav.property.PropEntry; -import org.apache.jackrabbit.webdav.server.AbstractWebdavServlet; -import org.apache.jackrabbit.webdav.transaction.TransactionConstants; -import org.apache.jackrabbit.webdav.transaction.TransactionInfo; -import org.apache.jackrabbit.webdav.version.LabelInfo; -import org.apache.jackrabbit.webdav.version.MergeInfo; -import org.apache.jackrabbit.webdav.version.OptionsInfo; -import org.apache.jackrabbit.webdav.version.UpdateInfo; -import org.apache.jackrabbit.webdav.version.report.ReportInfo; -import org.apache.jackrabbit.webdav.xml.DomUtil; -import org.apache.jackrabbit.webdav.xml.ElementIterator; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.w3c.dom.Document; -import org.w3c.dom.Element; -import org.xml.sax.SAXException; - -/** - * WebdavRequestImpl... - */ -public class WebdavRequestImpl implements WebdavRequest, DavConstants, ContentCodingAwareRequest { - - private static Logger log = LoggerFactory.getLogger(WebdavRequestImpl.class); - - private final HttpServletRequest httpRequest; - private final DavLocatorFactory factory; - private final IfHeader ifHeader; - private final String hrefPrefix; - - private DavSession session; - - private int propfindType = PROPFIND_ALL_PROP; - private DavPropertyNameSet propfindProps; - private DavPropertySet proppatchSet; - private List proppatchList; - - /** - * Creates a new DavServletRequest with the given parameters. - */ - public WebdavRequestImpl(HttpServletRequest httpRequest, DavLocatorFactory factory) { - this(httpRequest, factory, true); - } - - /** - * Creates a new DavServletRequest with the given parameters. - * - * @param httpRequest - * @param factory - * @param createAbsoluteURI defines if we must create a absolute URI. if false a absolute path will be created - */ - public WebdavRequestImpl(HttpServletRequest httpRequest, DavLocatorFactory factory, boolean createAbsoluteURI) { - this.httpRequest = httpRequest; - this.factory = factory; - this.ifHeader = new IfHeader(httpRequest); - - String host = getHeader("Host"); - String scheme = getScheme(); - String uriPrefix = scheme + "://" + host + getContextPath(); - this.hrefPrefix = createAbsoluteURI ? uriPrefix : getContextPath(); - } - - /** - * Sets the session field and adds all lock tokens present with either the - * Lock-Token header or the If header to the given session object. - * - * @param session - * @see DavServletRequest#setDavSession(DavSession) - */ - public void setDavSession(DavSession session) { - this.session = session; - // set lock-tokens from header to the current session - if (session != null) { - String lt = getLockToken(); - if (lt != null) { - session.addLockToken(lt); - } - // add all token present in the the If header to the session as well. - Iterator it = ifHeader.getAllTokens(); - while (it.hasNext()) { - String ifHeaderToken = it.next(); - session.addLockToken(ifHeaderToken); - } - } - } - - /** - * @see DavServletRequest#getDavSession() - */ - public DavSession getDavSession() { - return session; - } - - /** - * Return a DavResourceLocator representing the request handle. - * - * @return locator of the requested resource - * @see DavServletRequest#getRequestLocator() - */ - public DavResourceLocator getRequestLocator() { - String path = getRequestURI(); - String ctx = getContextPath(); - if (path.startsWith(ctx)) { - path = path.substring(ctx.length()); - } - return factory.createResourceLocator(hrefPrefix, path); - } - - /** - * Parse the destination header field and return the path of the destination - * resource. - * - * @return path of the destination resource. - * @throws DavException - * @see #HEADER_DESTINATION - * @see DavServletRequest#getDestinationLocator - */ - public DavResourceLocator getDestinationLocator() throws DavException { - return getHrefLocator(httpRequest.getHeader(HEADER_DESTINATION), true); - } - - private DavResourceLocator getHrefLocator(String href, boolean forDestination) throws DavException { - String ref = href; - if (ref != null) { - //href should be a Simple-ref production as defined in RFC4918, so it is either an absolute URI - //or an absolute path - try { - URI uri = new URI(ref).normalize(); // normalize path (see JCR-3174) - String auth = uri.getAuthority(); - ref = uri.getRawPath(); - if (auth == null) { - //verify that href is an absolute path - if (ref.startsWith("//") || !ref.startsWith("/")) { - log.warn("expected absolute path but found " + ref); - throw new DavException(DavServletResponse.SC_BAD_REQUEST); - } - } else if (!auth.equals(httpRequest.getHeader("Host"))) { - //this looks like an unsupported cross-server operation, but of course a reverse-proxy - //might have rewritten the Host header. Since we can't find out, we have to reject anyway. - //Better use absolute paths in DAV:href elements! - throw new DavException(DavServletResponse.SC_FORBIDDEN); - } - } catch (URISyntaxException e) { - log.warn("malformed uri: " + href, e); - throw new DavException(DavServletResponse.SC_BAD_REQUEST); - } - // cut off the context path - String contextPath = httpRequest.getContextPath(); - if (ref.startsWith(contextPath)) { - ref = ref.substring(contextPath.length()); - } else { - //absolute path has to start with context path - throw new DavException(DavServletResponse.SC_FORBIDDEN); - } - } - if (factory instanceof AbstractLocatorFactory) { - return ((AbstractLocatorFactory)factory).createResourceLocator(hrefPrefix, ref, forDestination); - } - else { - return factory.createResourceLocator(hrefPrefix, ref); - } - } - - /** - * Parse a href and return the path of the resource. - * - * @return path of the resource identified by the href. - * @see org.apache.jackrabbit.webdav.bind.BindServletRequest#getHrefLocator - */ - public DavResourceLocator getHrefLocator(String href) throws DavException { - return getHrefLocator(href, false); - } - - /** - * Returns the path of the member resource of the request resource which is identified by the segment parameter. - * - * @return path of internal member resource. - */ - public DavResourceLocator getMemberLocator(String segment) { - String path = (this.getRequestLocator().getHref(true) + segment).substring(hrefPrefix.length()); - return factory.createResourceLocator(hrefPrefix, path); - } - - /** - * Return true if the overwrite header does not inhibit overwriting. - * - * @return true if the overwrite header requests 'overwriting' - * @see #HEADER_OVERWRITE - * @see DavServletRequest#isOverwrite() - */ - public boolean isOverwrite() { - return new OverwriteHeader(httpRequest).isOverwrite(); - } - - /** - * @see DavServletRequest#getDepth(int) - */ - public int getDepth(int defaultValue) { - return DepthHeader.parse(httpRequest, defaultValue).getDepth(); - } - - /** - * @see DavServletRequest#getDepth() - */ - public int getDepth() { - return getDepth(DEPTH_INFINITY); - } - - /** - * Parse the Timeout header and return a long representing the value. - * {@link #UNDEFINED_TIMEOUT} is used as default value if no header - * is available or if the parsing fails. - * - * @return milliseconds indicating length of the timeout. - * @see DavServletRequest#getTimeout() - * @see TimeoutHeader#parse(javax.servlet.http.HttpServletRequest, long) - */ - public long getTimeout() { - return TimeoutHeader.parse(httpRequest, UNDEFINED_TIMEOUT).getTimeout(); - } - - /** - * Retrieve the lock token from the 'Lock-Token' header. - * - * @return String representing the lock token sent in the Lock-Token header. - * @throws IllegalArgumentException If the value has not the correct format. - * @see #HEADER_LOCK_TOKEN - * @see DavServletRequest#getLockToken() - */ - public String getLockToken() { - return CodedUrlHeader.parse(httpRequest, HEADER_LOCK_TOKEN).getCodedUrl(); - } - - /** - * @see DavServletRequest#getRequestDocument() - */ - public Document getRequestDocument() throws DavException { - Document requestDocument = null; - /* - Don't attempt to parse the body if the content length header is 0. - NOTE: a value of -1 indicates that the length is unknown, thus we have - to parse the body. Note that http1.1 request using chunked transfer - coding will therefore not be detected here. - */ - if (httpRequest.getContentLength() == 0) { - return requestDocument; - } - // try to parse the request body - try { - InputStream in = getDecodedInputStream(); - if (in != null) { - // use a buffered input stream to find out whether there actually - // is a request body - InputStream bin = new BufferedInputStream(in); - bin.mark(1); - boolean isEmpty = -1 == bin.read(); - bin.reset(); - if (!isEmpty) { - requestDocument = DomUtil.parseDocument(bin); - } - } - } catch (IOException e) { - if (log.isDebugEnabled()) { - log.debug("Unable to build an XML Document from the request body: " + e.getMessage()); - } - Throwable cause = e.getCause(); - throw (cause instanceof DavException) ? (DavException) cause : new DavException(DavServletResponse.SC_BAD_REQUEST); - } catch (ParserConfigurationException e) { - if (log.isDebugEnabled()) { - log.debug("Unable to build an XML Document from the request body: " + e.getMessage()); - } - throw new DavException(DavServletResponse.SC_INTERNAL_SERVER_ERROR); - } catch (SAXException e) { - if (log.isDebugEnabled()) { - log.debug("Unable to build an XML Document from the request body: " + e.getMessage()); - } - throw new DavException(DavServletResponse.SC_BAD_REQUEST); - } - return requestDocument; - } - - /** - * Returns the type of PROPFIND as indicated by the request body. - * - * @return type of the PROPFIND request. Default value is {@link #PROPFIND_ALL_PROP allprops} - * @see DavServletRequest#getPropFindType() - */ - public int getPropFindType() throws DavException { - if (propfindProps == null) { - parsePropFindRequest(); - } - return propfindType; - } - - /** - * Returns the set of properties requested by the PROPFIND body or an - * empty set if the {@link #getPropFindType type} is either 'allprop' or - * 'propname'. - * - * @return set of properties requested by the PROPFIND body or an empty set. - * @see DavServletRequest#getPropFindProperties() - */ - public DavPropertyNameSet getPropFindProperties() throws DavException { - if (propfindProps == null) { - parsePropFindRequest(); - } - return propfindProps; - } - - private InputStream getDecodedInputStream() throws IOException { - List contentCodings = getRequestContentCodings(); - int len = contentCodings.size(); - - log.trace("content codings: " + contentCodings); - InputStream result = httpRequest.getInputStream(); - - for (int i = 1; i <= len; i++) { - String s = contentCodings.get(len - i); - log.trace("decoding: " + s); - if ("gzip".equals(s)) { - result = new GZIPInputStream(result); - } else if ("deflate".equals(s)) { - result = new InflaterInputStream(result); - } else { - String message = "Unsupported content coding: " + s; - try { - Element condition = DomUtil.createElement(DomUtil.createDocument(), PRECONDITION_SUPPORTED); - throw new IOException( - new DavException(HttpServletResponse.SC_UNSUPPORTED_MEDIA_TYPE, message, null, condition)); - } catch (ParserConfigurationException ex) { - throw new IOException(message); - } - } - } - - return result; - } - - private List requestContentCodings = null; - - @Override - public List getRequestContentCodings() { - if (requestContentCodings == null) { - requestContentCodings = AbstractWebdavServlet.getContentCodings(httpRequest); - } - - return requestContentCodings; - } - - @Override - public String getAcceptableCodings() { - return "deflate, gzip"; - } - - /** - * Parse the propfind request body in order to determine the type of the propfind - * and the set of requested property. - * NOTE: An empty 'propfind' request body will be treated as request for all - * property according to the specification. - */ - private void parsePropFindRequest() throws DavException { - propfindProps = new DavPropertyNameSet(); - Document requestDocument = getRequestDocument(); - // propfind httpRequest with empty body >> retrieve all property - if (requestDocument == null) { - return; - } - - // propfind httpRequest with invalid body - Element root = requestDocument.getDocumentElement(); - if (!XML_PROPFIND.equals(root.getLocalName())) { - log.info("PropFind-Request has no tag."); - throw new DavException(DavServletResponse.SC_BAD_REQUEST, "PropFind-Request has no tag."); - } - - DavPropertyNameSet include = null; - - ElementIterator it = DomUtil.getChildren(root); - int propfindTypeFound = 0; - - while (it.hasNext()) { - Element child = it.nextElement(); - String nodeName = child.getLocalName(); - if (NAMESPACE.getURI().equals(child.getNamespaceURI())) { - if (XML_PROP.equals(nodeName)) { - propfindType = PROPFIND_BY_PROPERTY; - propfindProps = new DavPropertyNameSet(child); - propfindTypeFound += 1; - } - else if (XML_PROPNAME.equals(nodeName)) { - propfindType = PROPFIND_PROPERTY_NAMES; - propfindTypeFound += 1; - } - else if (XML_ALLPROP.equals(nodeName)) { - propfindType = PROPFIND_ALL_PROP; - propfindTypeFound += 1; - } - else if (XML_INCLUDE.equals(nodeName)) { - include = new DavPropertyNameSet(); - ElementIterator pit = DomUtil.getChildren(child); - while (pit.hasNext()) { - include.add(DavPropertyName.createFromXml(pit.nextElement())); - } - } - } - } - - if (propfindTypeFound > 1) { - log.info("Multiple top-level propfind instructions"); - throw new DavException(DavServletResponse.SC_BAD_REQUEST, "Multiple top-level propfind instructions"); - } - - if (include != null) { - if (propfindType == PROPFIND_ALL_PROP) { - // special case: allprop with include extension - propfindType = PROPFIND_ALL_PROP_INCLUDE; - propfindProps = include; - } - else { - throw new DavException(DavServletResponse.SC_BAD_REQUEST, " goes only with "); - - } - } - } - - /** - * Return a {@link List} of property change operations. Each entry - * is either of type {@link DavPropertyName}, indicating a <remove> - * operation, or of type {@link DavProperty}, indicating a <set> - * operation. Note that ordering is significant here. - * - * @return the list of change operations entries in the PROPPATCH request body - * @see DavServletRequest#getPropPatchChangeList() - */ - public List getPropPatchChangeList() throws DavException { - if (proppatchList == null) { - parsePropPatchRequest(); - } - return proppatchList; - } - - /** - * Parse the PROPPATCH request body. - */ - private void parsePropPatchRequest() throws DavException { - - proppatchSet = new DavPropertySet(); - proppatchList = new ArrayList(); - - Document requestDocument = getRequestDocument(); - - if (requestDocument == null) { - throw new DavException(DavServletResponse.SC_BAD_REQUEST, "Invalid request body."); - } - - Element root = requestDocument.getDocumentElement(); - if (!DomUtil.matches(root, XML_PROPERTYUPDATE, NAMESPACE)) { - log.warn("PropPatch-Request has no tag."); - throw new DavException(DavServletResponse.SC_BAD_REQUEST, "PropPatch-Request has no tag."); - } - - ElementIterator it = DomUtil.getChildren(root); - while (it.hasNext()) { - Element el = it.nextElement(); - if (DomUtil.matches(el, XML_SET, NAMESPACE)) { - Element propEl = DomUtil.getChildElement(el, XML_PROP, NAMESPACE); - if (propEl != null) { - ElementIterator properties = DomUtil.getChildren(propEl); - while (properties.hasNext()) { - DavProperty davProp = DefaultDavProperty.createFromXml(properties.nextElement()); - proppatchSet.add(davProp); - proppatchList.add(davProp); - } - } - } else if (DomUtil.matches(el, XML_REMOVE, NAMESPACE)) { - Element propEl = DomUtil.getChildElement(el, XML_PROP, NAMESPACE); - if (propEl != null) { - ElementIterator properties = DomUtil.getChildren(propEl); - while (properties.hasNext()) { - DavProperty davProp = DefaultDavProperty.createFromXml(properties.nextElement()); - proppatchSet.add(davProp); - proppatchList.add(davProp.getName()); - } - } - } else { - log.debug("Unknown element in DAV:propertyupdate: " + el.getNodeName()); - // unknown child elements are ignored - } - } - } - - /** - * {@link LockInfo} object encapsulating the information passed with a LOCK - * request if the LOCK request body was valid. If the request body is - * missing a 'refresh lock' request is assumed. The {@link LockInfo} - * then only provides timeout and isDeep property and returns true on - * {@link org.apache.jackrabbit.webdav.lock.LockInfo#isRefreshLock()} - * - * @return lock info object or null if an error occurred while - * parsing the request body. - * @throws DavException throws a 400 (Bad Request) DavException if a request - * body is present but does not start with a DAV:lockinfo element. Note however, - * that a non-existing request body is a valid request used to refresh - * an existing lock. - * @see DavServletRequest#getLockInfo() - */ - public LockInfo getLockInfo() throws DavException { - LockInfo lockInfo; - boolean isDeep = (getDepth(DEPTH_INFINITY) == DEPTH_INFINITY); - Document requestDocument = getRequestDocument(); - // check if XML request body is present. It SHOULD have one for - // 'create Lock' request and missing for a 'refresh Lock' request - if (requestDocument != null) { - Element root = requestDocument.getDocumentElement(); - if (root.getLocalName().equals(XML_LOCKINFO)) { - lockInfo = new LockInfo(root, getTimeout(), isDeep); - } else { - log.debug("Lock request body must start with a DAV:lockinfo element."); - throw new DavException(DavServletResponse.SC_BAD_REQUEST); - } - } else { - lockInfo = new LockInfo(null, getTimeout(), isDeep); - } - return lockInfo; - } - - /** - * Test if the if header matches the given resource. The comparison is - * made with the {@link DavResource#getHref() - * resource href} and the token returned from an exclusive write lock present on - * the resource.
- * NOTE: If either the If header or the resource is null or if - * the resource has not applied an exclusive write lock the preconditions are met. - * If in contrast the lock applied to the given resource returns a - * null lock token (e.g. for security reasons) or a lock token - * that does not match, the method will return false. - * - * @param resource Webdav resources being operated on - * @return true if the test is successful and the preconditions for the - * request processing are fulfilled. - * @see DavServletRequest#matchesIfHeader(DavResource) - * @see IfHeader#matches(String, String, String) - * @see DavResource#hasLock(org.apache.jackrabbit.webdav.lock.Type, org.apache.jackrabbit.webdav.lock.Scope) - * @see org.apache.jackrabbit.webdav.lock.ActiveLock#getToken() - */ - public boolean matchesIfHeader(DavResource resource) { - // no ifheader, no resource or no write lock on resource - // >> preconditions ok so far - if (!ifHeader.hasValue() || resource == null || !resource.hasLock(Type.WRITE, Scope.EXCLUSIVE)) { - return true; - } - - boolean isMatching = false; - String lockToken = resource.getLock(Type.WRITE, Scope.EXCLUSIVE).getToken(); - if (lockToken != null) { - isMatching = matchesIfHeader(resource.getHref(), lockToken, getStrongETag(resource)); - } // else: lockToken is null >> the if-header will not match. - - return isMatching; - } - - /** - * @see DavServletRequest#matchesIfHeader(String, String, String) - * @see IfHeader#matches(String, String, String) - */ - public boolean matchesIfHeader(String href, String token, String eTag) { - return ifHeader.matches(href, token, isStrongETag(eTag) ? eTag : ""); - } - - /** - * Returns the strong etag present on the given resource or empty string - * if either the resource does not provide any etag or if the etag is weak. - * - * @param resource - * @return strong etag or empty string. - */ - private String getStrongETag(DavResource resource) { - DavProperty prop = resource.getProperty(DavPropertyName.GETETAG); - if (prop != null && prop.getValue() != null) { - String etag = prop.getValue().toString(); - if (isStrongETag(etag)) { - return etag; - } - } - // no strong etag available - return ""; - } - - /** - * Returns true if the given string represents a strong etag. - * - * @param eTag - * @return true, if its a strong etag - */ - private static boolean isStrongETag(String eTag) { - return eTag != null && eTag.length() > 0 && !eTag.startsWith("W\\"); - } - - //-----------------------------< TransactionDavServletRequest Interface >--- - /** - * @see org.apache.jackrabbit.webdav.transaction.TransactionDavServletRequest#getTransactionId() - */ - public String getTransactionId() { - return CodedUrlHeader.parse(httpRequest, TransactionConstants.HEADER_TRANSACTIONID).getCodedUrl(); - } - - /** - * @see org.apache.jackrabbit.webdav.transaction.TransactionDavServletRequest#getTransactionInfo() - */ - public TransactionInfo getTransactionInfo() throws DavException { - Document requestDocument = getRequestDocument(); - if (requestDocument != null) { - return new TransactionInfo(requestDocument.getDocumentElement()); - } - return null; - } - - //-----------------------------< ObservationDavServletRequest Interface >--- - /** - * @see org.apache.jackrabbit.webdav.observation.ObservationDavServletRequest#getSubscriptionId() - */ - public String getSubscriptionId() { - return CodedUrlHeader.parse(httpRequest, ObservationConstants.HEADER_SUBSCRIPTIONID).getCodedUrl(); - } - - /** - * @see org.apache.jackrabbit.webdav.observation.ObservationDavServletRequest#getPollTimeout() - */ - public long getPollTimeout() { - return PollTimeoutHeader.parseHeader(httpRequest, 0).getTimeout(); - } - - /** - * @see org.apache.jackrabbit.webdav.observation.ObservationDavServletRequest#getSubscriptionInfo() - */ - public SubscriptionInfo getSubscriptionInfo() throws DavException { - Document requestDocument = getRequestDocument(); - if (requestDocument != null) { - Element root = requestDocument.getDocumentElement(); - if (ObservationConstants.XML_SUBSCRIPTIONINFO.equals(root.getLocalName())) { - int depth = getDepth(DEPTH_0); - return new SubscriptionInfo(root, getTimeout(), depth == DEPTH_INFINITY); - } - } - return null; - } - - //--------------------------------< OrderingDavServletRequest Interface >--- - /** - * @see org.apache.jackrabbit.webdav.ordering.OrderingDavServletRequest#getOrderingType() - */ - public String getOrderingType() { - return getHeader(OrderingConstants.HEADER_ORDERING_TYPE); - } - - /** - * @see org.apache.jackrabbit.webdav.ordering.OrderingDavServletRequest#getPosition() - */ - public Position getPosition() { - String h = getHeader(OrderingConstants.HEADER_POSITION); - Position pos = null; - if (h != null) { - String[] typeNSegment = h.split("\\s"); - if (typeNSegment.length == 2) { - try { - pos = new Position(typeNSegment[0], typeNSegment[1]); - } catch (IllegalArgumentException e) { - log.error("Cannot parse Position header: " + e.getMessage()); - } - } - } - return pos; - } - - /** - * @return OrderPatch object representing the orderpatch request - * body or null if the - * @see org.apache.jackrabbit.webdav.ordering.OrderingDavServletRequest#getOrderPatch() - */ - public OrderPatch getOrderPatch() throws DavException { - OrderPatch op = null; - Document requestDocument = getRequestDocument(); - if (requestDocument != null) { - Element root = requestDocument.getDocumentElement(); - op = OrderPatch.createFromXml(root); - } else { - log.error("Error while building xml document from ORDERPATH request body."); - } - return op; - } - - //-------------------------------------< DeltaVServletRequest interface >--- - /** - * @see org.apache.jackrabbit.webdav.version.DeltaVServletRequest#getLabel() - */ - public String getLabel() { - LabelHeader label = LabelHeader.parse(this); - if (label != null) { - return label.getLabel(); - } - return null; - } - - /** - * @see org.apache.jackrabbit.webdav.version.DeltaVServletRequest#getLabelInfo() - */ - public LabelInfo getLabelInfo() throws DavException { - LabelInfo lInfo = null; - Document requestDocument = getRequestDocument(); - if (requestDocument != null) { - Element root = requestDocument.getDocumentElement(); - int depth = getDepth(DEPTH_0); - lInfo = new LabelInfo(root, depth); - } - return lInfo; - } - - /** - * @see org.apache.jackrabbit.webdav.version.DeltaVServletRequest#getMergeInfo() - */ - public MergeInfo getMergeInfo() throws DavException { - MergeInfo mInfo = null; - Document requestDocument = getRequestDocument(); - if (requestDocument != null) { - mInfo = new MergeInfo(requestDocument.getDocumentElement()); - } - return mInfo; - } - - /** - * @see org.apache.jackrabbit.webdav.version.DeltaVServletRequest#getUpdateInfo() - */ - public UpdateInfo getUpdateInfo() throws DavException { - UpdateInfo uInfo = null; - Document requestDocument = getRequestDocument(); - if (requestDocument != null) { - uInfo = new UpdateInfo(requestDocument.getDocumentElement()); - } - return uInfo; - } - - /** - * @see org.apache.jackrabbit.webdav.version.DeltaVServletRequest#getReportInfo() - */ - public ReportInfo getReportInfo() throws DavException { - ReportInfo rInfo = null; - Document requestDocument = getRequestDocument(); - if (requestDocument != null) { - rInfo = new ReportInfo(requestDocument.getDocumentElement(), getDepth(DEPTH_0)); - } - return rInfo; - } - - /** - * @see org.apache.jackrabbit.webdav.version.DeltaVServletRequest#getOptionsInfo() - */ - public OptionsInfo getOptionsInfo() throws DavException { - OptionsInfo info = null; - Document requestDocument = getRequestDocument(); - if (requestDocument != null) { - info = OptionsInfo.createFromXml(requestDocument.getDocumentElement()); - } - return info; - } - - /** - * @see org.apache.jackrabbit.webdav.bind.BindServletRequest#getRebindInfo() - */ - public RebindInfo getRebindInfo() throws DavException { - RebindInfo info = null; - Document requestDocument = getRequestDocument(); - if (requestDocument != null) { - info = RebindInfo.createFromXml(requestDocument.getDocumentElement()); - } - return info; - } - - /** - * @see org.apache.jackrabbit.webdav.bind.BindServletRequest#getUnbindInfo() - */ - public UnbindInfo getUnbindInfo() throws DavException { - UnbindInfo info = null; - Document requestDocument = getRequestDocument(); - if (requestDocument != null) { - info = UnbindInfo.createFromXml(requestDocument.getDocumentElement()); - } - return info; - } - - /** - * @see org.apache.jackrabbit.webdav.bind.BindServletRequest#getBindInfo() - */ - public BindInfo getBindInfo() throws DavException { - BindInfo info = null; - Document requestDocument = getRequestDocument(); - if (requestDocument != null) { - info = BindInfo.createFromXml(requestDocument.getDocumentElement()); - } - return info; - } - - //---------------------------------------< HttpServletRequest interface >--- - - @Override - public String getAuthType() { - return httpRequest.getAuthType(); - } - - @Override - public Cookie[] getCookies() { - return httpRequest.getCookies(); - } - - @Override - public long getDateHeader(String s) { - return httpRequest.getDateHeader(s); - } - - @Override - public String getHeader(String s) { - return httpRequest.getHeader(s); - } - - @Override - public Enumeration getHeaders(String s) { - return httpRequest.getHeaders(s); - } - - @Override - public Enumeration getHeaderNames() { - return httpRequest.getHeaderNames(); - } - - @Override - public int getIntHeader(String s) { - return httpRequest.getIntHeader(s); - } - - @Override - public String getMethod() { - return httpRequest.getMethod(); - } - - @Override - public String getPathInfo() { - return httpRequest.getPathInfo(); - } - - @Override - public String getPathTranslated() { - return httpRequest.getPathTranslated(); - } - - @Override - public String getContextPath() { - return httpRequest.getContextPath(); - } - - @Override - public String getQueryString() { - return httpRequest.getQueryString(); - } - - @Override - public String getRemoteUser() { - return httpRequest.getRemoteUser(); - } - - @Override - public boolean isUserInRole(String s) { - return httpRequest.isUserInRole(s); - } - - @Override - public Principal getUserPrincipal() { - return httpRequest.getUserPrincipal(); - } - - @Override - public String getRequestedSessionId() { - return httpRequest.getRequestedSessionId(); - } - - @Override - public String getRequestURI() { - return httpRequest.getRequestURI(); - } - - @Override - public StringBuffer getRequestURL() { - return httpRequest.getRequestURL(); - } - - @Override - public String getServletPath() { - return httpRequest.getServletPath(); - } - - @Override - public HttpSession getSession(boolean b) { - return httpRequest.getSession(b); - } - - @Override - public HttpSession getSession() { - return httpRequest.getSession(); - } - - @Override - public boolean isRequestedSessionIdValid() { - return httpRequest.isRequestedSessionIdValid(); - } - - @Override - public boolean isRequestedSessionIdFromCookie() { - return httpRequest.isRequestedSessionIdFromCookie(); - } - - @Override - public boolean isRequestedSessionIdFromURL() { - return httpRequest.isRequestedSessionIdFromURL(); - } - - @Override - public boolean isRequestedSessionIdFromUrl() { - return httpRequest.isRequestedSessionIdFromUrl(); - } - - @Override - public Object getAttribute(String s) { - return httpRequest.getAttribute(s); - } - - @Override - public Enumeration getAttributeNames() { - return httpRequest.getAttributeNames(); - } - - @Override - public String getCharacterEncoding() { - return httpRequest.getCharacterEncoding(); - } - - @Override - public void setCharacterEncoding(String s) throws UnsupportedEncodingException { - httpRequest.setCharacterEncoding(s); - } - - @Override - public int getContentLength() { - return httpRequest.getContentLength(); - } - - @Override - public String getContentType() { - return httpRequest.getContentType(); - } - - @Override - public ServletInputStream getInputStream() throws IOException { - return new MyServletInputStream(getDecodedInputStream()); - } - - @Override - public String getParameter(String s) { - return httpRequest.getParameter(s); - } - - @Override - public Enumeration getParameterNames() { - return httpRequest.getParameterNames(); - } - - @Override - public String[] getParameterValues(String s) { - return httpRequest.getParameterValues(s); - } - - @Override - public Map getParameterMap() { - return httpRequest.getParameterMap(); - } - - @Override - public String getProtocol() { - return httpRequest.getProtocol(); - } - - @Override - public String getScheme() { - return httpRequest.getScheme(); - } - - @Override - public String getServerName() { - return httpRequest.getServerName(); - } - - @Override - public int getServerPort() { - return httpRequest.getServerPort(); - } - - @Override - public BufferedReader getReader() throws IOException { - return httpRequest.getReader(); - } - - @Override - public String getRemoteAddr() { - return httpRequest.getRemoteAddr(); - } - - @Override - public String getRemoteHost() { - return httpRequest.getRemoteHost(); - } - - @Override - public void setAttribute(String s, Object o) { - httpRequest.setAttribute(s, o); - } - - @Override - public void removeAttribute(String s) { - httpRequest.removeAttribute(s); - } - - @Override - public Locale getLocale() { - return httpRequest.getLocale(); - } - - @Override - public Enumeration getLocales() { - return httpRequest.getLocales(); - } - - @Override - public boolean isSecure() { - return httpRequest.isSecure(); - } - - @Override - public RequestDispatcher getRequestDispatcher(String s) { - return httpRequest.getRequestDispatcher(s); - } - - @Override - public String getRealPath(String s) { - return httpRequest.getRealPath(s); - } - - @Override - public int getRemotePort() { - return httpRequest.getRemotePort(); - } - - @Override - public String getLocalName() { - return httpRequest.getLocalName(); - } - - @Override - public String getLocalAddr() { - return httpRequest.getLocalAddr(); - } - - @Override - public int getLocalPort() { - return httpRequest.getLocalPort(); - } - - @Override - public String changeSessionId() { - return httpRequest.changeSessionId(); - } - - @Override - public boolean authenticate(HttpServletResponse response) throws IOException, ServletException { - return httpRequest.authenticate(response); - } - - @Override - public void login(String username, String password) throws ServletException { - httpRequest.login(username, password); - } - - @Override - public void logout() throws ServletException { - httpRequest.logout(); - } - - @Override - public Collection getParts() throws IOException, ServletException { - return httpRequest.getParts(); - } - - @Override - public Part getPart(String name) throws IOException, ServletException { - return httpRequest.getPart(name); - } - - @Override - public T upgrade(Class handlerClass) throws IOException, ServletException { - return httpRequest.upgrade(handlerClass); - } - - @Override - public long getContentLengthLong() { - return httpRequest.getContentLengthLong(); - } - - @Override - public ServletContext getServletContext() { - return httpRequest.getServletContext(); - } - - @Override - public AsyncContext startAsync() throws IllegalStateException { - return httpRequest.startAsync(); - } - - @Override - public AsyncContext startAsync(ServletRequest servletRequest, ServletResponse servletResponse) throws IllegalStateException { - return httpRequest.startAsync(servletRequest, servletResponse); - } - - @Override - public boolean isAsyncStarted() { - return httpRequest.isAsyncStarted(); - } - - @Override - public boolean isAsyncSupported() { - return httpRequest.isAsyncSupported(); - } - - @Override - public AsyncContext getAsyncContext() { - return httpRequest.getAsyncContext(); - } - - @Override - public DispatcherType getDispatcherType() { - return httpRequest.getDispatcherType(); - } - - private static class MyServletInputStream extends ServletInputStream { - - private final InputStream delegate; - - public MyServletInputStream(InputStream delegate) { - this.delegate = delegate; - } - - @Override - public int available() throws IOException { - return delegate.available(); - } - - @Override - public void close() throws IOException { - delegate.close(); - } - - @Override - public boolean equals(Object other) { - return delegate.equals(other); - } - - @Override - public int hashCode() { - return delegate.hashCode(); - } - - @Override - public void mark(int readlimit) { - delegate.mark(readlimit); - } - - @Override - public boolean markSupported() { - return delegate.markSupported(); - } - - @Override - public int read() throws IOException { - return delegate.read(); - } - - @Override - public int read(byte[] b, int off, int len) throws IOException { - return delegate.read(b, off, len); - } - - @Override - public int read(byte[] b) throws IOException { - return delegate.read(b); - } - - @Override - public int readLine(byte[] b, int off, int len) throws IOException { - throw new UnsupportedOperationException(); - } - - @Override - public void reset() throws IOException { - delegate.reset(); - } - - @Override - public long skip(long n) throws IOException { - return delegate.skip(n); - } - - @Override - public String toString() { - return delegate.toString(); - } - - @Override - public boolean isFinished() { - throw new UnsupportedOperationException(); - } - - @Override - public boolean isReady() { - throw new UnsupportedOperationException(); - } - - @Override - public void setReadListener(ReadListener readListener) { - throw new UnsupportedOperationException(); - } - } -} Property changes on: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/WebdavRequestImpl.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/WebdavResponse.java =================================================================== --- jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/WebdavResponse.java (revision 1907912) +++ jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/WebdavResponse.java (nonexistent) @@ -1,42 +0,0 @@ -/* - * 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.webdav; - -import java.util.Map; -import java.util.function.Supplier; - -import org.apache.jackrabbit.webdav.observation.ObservationDavServletResponse; - -/** - * The empty WebdavResponse interface collects the functionality - * defined by {@link org.apache.jackrabbit.webdav.DavServletResponse} - * encapsulating for the core WebDAV specification (RFC 2518) as well as the - * various extensions used for observation and transaction support, ordering of - * collections, search and versioning. - */ -public interface WebdavResponse extends DavServletResponse, ObservationDavServletResponse { - - // can be removed when we move to Servlet API 4.0 - public default void setTrailerFields(Supplier> supplier) { - // nop - } - - // can be removed when we move to Servlet API 4.0 - public default Supplier> getTrailerFields() { - return null; - } -} \ No newline at end of file Property changes on: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/WebdavResponse.java ___________________________________________________________________ Deleted: svn Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/WebdavResponseImpl.java =================================================================== --- jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/WebdavResponseImpl.java (revision 1907912) +++ jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/WebdavResponseImpl.java (nonexistent) @@ -1,407 +0,0 @@ -/* - * 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.webdav; - -import org.apache.jackrabbit.webdav.header.CodedUrlHeader; -import org.apache.jackrabbit.webdav.header.Header; -import org.apache.jackrabbit.webdav.lock.ActiveLock; -import org.apache.jackrabbit.webdav.lock.LockDiscovery; -import org.apache.jackrabbit.webdav.observation.EventDiscovery; -import org.apache.jackrabbit.webdav.observation.ObservationConstants; -import org.apache.jackrabbit.webdav.observation.Subscription; -import org.apache.jackrabbit.webdav.observation.SubscriptionDiscovery; -import org.apache.jackrabbit.webdav.property.DavPropertySet; -import org.apache.jackrabbit.webdav.xml.DomUtil; -import org.apache.jackrabbit.webdav.xml.XmlSerializable; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.w3c.dom.Document; -import org.xml.sax.SAXException; - -import javax.servlet.ServletOutputStream; -import javax.servlet.http.Cookie; -import javax.servlet.http.HttpServletResponse; -import javax.xml.parsers.ParserConfigurationException; -import javax.xml.transform.TransformerException; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.OutputStream; -import java.io.PrintWriter; -import java.util.Collection; -import java.util.Collections; -import java.util.List; -import java.util.Locale; -import java.util.Map; -import java.util.function.Supplier; -import java.util.zip.GZIPOutputStream; - -/** - * WebdavResponseImpl implements the WebdavResponse interface. - */ -public class WebdavResponseImpl implements WebdavResponse { - - private static Logger log = LoggerFactory.getLogger(WebdavResponseImpl.class); - - private HttpServletResponse httpResponse; - - /** - * Create a new WebdavResponse - * - * @param httpResponse - */ - public WebdavResponseImpl(HttpServletResponse httpResponse) { - this(httpResponse, false); - } - - /** - * Create a new WebdavResponse - * - * @param httpResponse - * @param noCache - */ - public WebdavResponseImpl(HttpServletResponse httpResponse, boolean noCache) { - this.httpResponse = httpResponse; - if (noCache) { - /* set cache control headers */ - addHeader("Pragma", "No-cache"); // http1.0 - addHeader("Cache-Control", "no-cache"); // http1.1 - } - } - - /** - * If the specifid exception provides an error condition an Xml response body - * is sent providing more detailed information about the error. Otherwise only - * the error code and status phrase is sent back. - * - * @param exception - * @throws IOException - * @see DavServletResponse#sendError(org.apache.jackrabbit.webdav.DavException) - * @see #sendError(int, String) - * @see #sendXmlResponse(XmlSerializable, int) - */ - public void sendError(DavException exception) throws IOException { - if (!exception.hasErrorCondition()) { - httpResponse.sendError(exception.getErrorCode(), exception.getStatusPhrase()); - } else { - sendXmlResponse(exception, exception.getErrorCode()); - } - } - - @Override - public void sendMultiStatus(MultiStatus multistatus) throws IOException { - sendXmlResponse(multistatus, SC_MULTI_STATUS); - } - - @Override - public void sendMultiStatus(MultiStatus multistatus, List acceptableContentCodings) throws IOException { - sendXmlResponse(multistatus, SC_MULTI_STATUS, acceptableContentCodings); - } - - /** - * Send response body for a lock request that was intended to refresh one - * or several locks. - * - * @param locks - * @throws java.io.IOException - * @see DavServletResponse#sendRefreshLockResponse(org.apache.jackrabbit.webdav.lock.ActiveLock[]) - */ - public void sendRefreshLockResponse(ActiveLock[] locks) throws IOException { - DavPropertySet propSet = new DavPropertySet(); - propSet.add(new LockDiscovery(locks)); - sendXmlResponse(propSet, SC_OK); - } - - @Override - public void sendXmlResponse(XmlSerializable serializable, int status) throws IOException { - sendXmlResponse(serializable, status, Collections.emptyList()); - } - - @Override - public void sendXmlResponse(XmlSerializable serializable, int status, List acceptableContentCodings) throws IOException { - httpResponse.setStatus(status); - - if (serializable != null) { - try { - ByteArrayOutputStream out = new ByteArrayOutputStream(); - Document doc = DomUtil.createDocument(); - doc.appendChild(serializable.toXml(doc)); - DomUtil.transformDocument(doc, out); - out.close(); - - httpResponse.setContentType("text/xml; charset=UTF-8"); - - // use GZIP iff accepted by client and content size >= 256 octets - if (out.size() < 256 || !acceptableContentCodings.contains("gzip")) { - httpResponse.setContentLength(out.size()); - out.writeTo(httpResponse.getOutputStream()); - } else { - httpResponse.setHeader("Content-Encoding", "gzip"); - try (OutputStream os = new GZIPOutputStream(httpResponse.getOutputStream())) { - out.writeTo(os); - } - } - } catch (ParserConfigurationException e) { - log.error(e.getMessage()); - throw new IOException(e.getMessage()); - } catch (TransformerException e) { - log.error(e.getMessage()); - throw new IOException(e.getMessage()); - } catch (SAXException e) { - log.error(e.getMessage()); - throw new IOException(e.getMessage()); - } - } - } - - //----------------------------< ObservationDavServletResponse Interface >--- - /** - * - * @param subscription - * @throws IOException - * @see org.apache.jackrabbit.webdav.observation.ObservationDavServletResponse#sendSubscriptionResponse(org.apache.jackrabbit.webdav.observation.Subscription) - */ - public void sendSubscriptionResponse(Subscription subscription) throws IOException { - String id = subscription.getSubscriptionId(); - if (id != null) { - Header h = new CodedUrlHeader(ObservationConstants.HEADER_SUBSCRIPTIONID, id); - httpResponse.setHeader(h.getHeaderName(), h.getHeaderValue()); - } - DavPropertySet propSet = new DavPropertySet(); - propSet.add(new SubscriptionDiscovery(subscription)); - sendXmlResponse(propSet, SC_OK); - } - - /** - * - * @param eventDiscovery - * @throws IOException - * @see org.apache.jackrabbit.webdav.observation.ObservationDavServletResponse#sendPollResponse(org.apache.jackrabbit.webdav.observation.EventDiscovery) - */ - public void sendPollResponse(EventDiscovery eventDiscovery) throws IOException { - sendXmlResponse(eventDiscovery, SC_OK); - } - - //--------------------------------------< HttpServletResponse interface >--- - - @Override - public void addCookie(Cookie cookie) { - httpResponse.addCookie(cookie); - } - - @Override - public boolean containsHeader(String s) { - return httpResponse.containsHeader(s); - } - - @Override - public String encodeURL(String s) { - return httpResponse.encodeRedirectURL(s); - } - - @Override - public String encodeRedirectURL(String s) { - return httpResponse.encodeRedirectURL(s); - } - - @Override - public String encodeUrl(String s) { - return httpResponse.encodeUrl(s); - } - - @Override - public String encodeRedirectUrl(String s) { - return httpResponse.encodeRedirectURL(s); - } - - @Override - public void sendError(int i, String s) throws IOException { - httpResponse.sendError(i, s); - } - - @Override - public void sendError(int i) throws IOException { - httpResponse.sendError(i); - } - - @Override - public void sendRedirect(String s) throws IOException { - httpResponse.sendRedirect(s); - } - - @Override - public void setDateHeader(String s, long l) { - httpResponse.setDateHeader(s, l); - } - - @Override - public void addDateHeader(String s, long l) { - httpResponse.addDateHeader(s, l); - } - - @Override - public void setHeader(String s, String s1) { - httpResponse.setHeader(s, s1); - } - - @Override - public void addHeader(String s, String s1) { - httpResponse.addHeader(s, s1); - } - - @Override - public void setIntHeader(String s, int i) { - httpResponse.setIntHeader(s, i); - } - - @Override - public void addIntHeader(String s, int i) { - httpResponse.addIntHeader(s, i); - } - - @Override - public void setStatus(int i) { - httpResponse.setStatus(i); - } - - @Override - public void setStatus(int i, String s) { - httpResponse.setStatus(i, s); - } - - @Override - public String getCharacterEncoding() { - return httpResponse.getCharacterEncoding(); - } - - @Override - public ServletOutputStream getOutputStream() throws IOException { - return httpResponse.getOutputStream(); - } - - @Override - public PrintWriter getWriter() throws IOException { - return httpResponse.getWriter(); - } - - @Override - public void setContentLength(int i) { - httpResponse.setContentLength(i); - } - - @Override - public void setContentType(String s) { - httpResponse.setContentType(s); - } - - @Override - public void setBufferSize(int i) { - httpResponse.setBufferSize(i); - } - - @Override - public int getBufferSize() { - return httpResponse.getBufferSize(); - } - - @Override - public void flushBuffer() throws IOException { - httpResponse.flushBuffer(); - } - - @Override - public void resetBuffer() { - httpResponse.resetBuffer(); - } - - @Override - public boolean isCommitted() { - return httpResponse.isCommitted(); - } - - @Override - public void reset() { - httpResponse.reset(); - } - - @Override - public void setLocale(Locale locale) { - httpResponse.setLocale(locale); - } - - @Override - public Locale getLocale() { - return httpResponse.getLocale(); - } - - @Override - public String getContentType() { - return httpResponse.getContentType(); - } - - @Override - public void setCharacterEncoding(String charset) { - httpResponse.setCharacterEncoding(charset); - } - - @Override - public int getStatus() { - return httpResponse.getStatus(); - } - - @Override - public String getHeader(String name) { - return httpResponse.getHeader(name); - } - - @Override - public Collection getHeaders(String name) { - return httpResponse.getHeaders(name); - } - - @Override - public Collection getHeaderNames() { - return httpResponse.getHeaderNames(); - } - - @Override - public void setContentLengthLong(long len) { - httpResponse.setContentLengthLong(len); - } - - // Servlet 4.0 API support for trailers, for now using reflection - - public void setTrailerFields(Supplier> supplier) { - try { - java.lang.reflect.Method stf = httpResponse.getClass().getDeclaredMethod("setTrailerFields", Supplier.class); - stf.invoke(httpResponse, supplier); - } catch (IllegalAccessException | java.lang.reflect.InvocationTargetException | NoSuchMethodException - | SecurityException ex) { - throw new UnsupportedOperationException("no servlet 4.0 support on: " + httpResponse.getClass(), ex); - } - } - - @SuppressWarnings("unchecked") - public Supplier> getTrailerFields() { - try { - java.lang.reflect.Method stf = httpResponse.getClass().getDeclaredMethod("getTrailerFields"); - return (Supplier>) stf.invoke(httpResponse); - } catch (IllegalAccessException | java.lang.reflect.InvocationTargetException | NoSuchMethodException - | SecurityException ex) { - throw new UnsupportedOperationException("no servlet 4.0 support on: " + httpResponse.getClass(), ex); - } - } -} Property changes on: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/WebdavResponseImpl.java ___________________________________________________________________ Deleted: svn Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/bind/BindConstants.java =================================================================== --- jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/bind/BindConstants.java (revision 1907912) +++ jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/bind/BindConstants.java (nonexistent) @@ -1,52 +0,0 @@ -/* - * 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.webdav.bind; - -import org.apache.jackrabbit.webdav.xml.Namespace; -import org.apache.jackrabbit.webdav.DavConstants; -import org.apache.jackrabbit.webdav.property.DavPropertyName; - -/** - * BindConstants provide constants for request and response - * headers, Xml elements and property names defined by - * the BIND specification. - */ -public interface BindConstants { - - /** - * The namespace - */ - public static final Namespace NAMESPACE = DavConstants.NAMESPACE; - - /** - * local names of XML elements used in the request bodies of the methods BIND, REBIND and UNBIND. - */ - public static final String XML_BIND = "bind"; - public static final String XML_REBIND = "rebind"; - public static final String XML_UNBIND = "unbind"; - public static final String XML_SEGMENT = "segment"; - public static final String XML_HREF = "href"; - public static final String XML_PARENT = "parent"; - - public static final String METHODS = "BIND, REBIND, UNBIND"; - - /* - * Webdav properties defined by the BIND specification. - */ - public static final DavPropertyName RESOURCEID = DavPropertyName.create("resource-id"); - public static final DavPropertyName PARENTSET = DavPropertyName.create("parent-set"); -} Property changes on: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/bind/BindConstants.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/bind/BindInfo.java =================================================================== --- jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/bind/BindInfo.java (revision 1907912) +++ jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/bind/BindInfo.java (nonexistent) @@ -1,108 +0,0 @@ -/* - * 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.webdav.bind; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.apache.jackrabbit.webdav.DavServletResponse; -import org.apache.jackrabbit.webdav.DavException; -import org.apache.jackrabbit.webdav.xml.DomUtil; -import org.apache.jackrabbit.webdav.xml.ElementIterator; -import org.apache.jackrabbit.webdav.xml.XmlSerializable; -import org.w3c.dom.Element; -import org.w3c.dom.Document; - -public class BindInfo implements XmlSerializable { - - private static Logger log = LoggerFactory.getLogger(BindInfo.class); - - private String segment; - private String href; - - public BindInfo(String href, String segment) { - this.href = href; - this.segment = segment; - } - - public String getHref() { - return this.href; - } - - public String getSegment() { - return this.segment; - } - - /** - * Build an BindInfo object from the root element present - * in the request body. - * - * @param root the root element of the request body - * @return a BindInfo object containing segment and href - * @throws org.apache.jackrabbit.webdav.DavException if the BIND request is malformed - */ - public static BindInfo createFromXml(Element root) throws DavException { - if (!DomUtil.matches(root, BindConstants.XML_BIND, BindConstants.NAMESPACE)) { - log.warn("DAV:bind element expected"); - throw new DavException(DavServletResponse.SC_BAD_REQUEST); - } - String href = null; - String segment = null; - ElementIterator it = DomUtil.getChildren(root); - while (it.hasNext()) { - Element elt = it.nextElement(); - if (DomUtil.matches(elt, BindConstants.XML_SEGMENT, BindConstants.NAMESPACE)) { - if (segment == null) { - segment = DomUtil.getText(elt); - } else { - log.warn("unexpected multiple occurrence of DAV:segment element"); - throw new DavException(DavServletResponse.SC_BAD_REQUEST); - } - } else if (DomUtil.matches(elt, BindConstants.XML_HREF, BindConstants.NAMESPACE)) { - if (href == null) { - href = DomUtil.getText(elt); - } else { - log.warn("unexpected multiple occurrence of DAV:href element"); - throw new DavException(DavServletResponse.SC_BAD_REQUEST); - } - } else { - log.warn("unexpected element " + elt.getLocalName()); - throw new DavException(DavServletResponse.SC_BAD_REQUEST); - } - } - if (href == null) { - log.warn("DAV:href element expected"); - throw new DavException(DavServletResponse.SC_BAD_REQUEST); - } - if (segment == null) { - log.warn("DAV:segment element expected"); - throw new DavException(DavServletResponse.SC_BAD_REQUEST); - } - return new BindInfo(href, segment); - } - - /** - * @see org.apache.jackrabbit.webdav.xml.XmlSerializable#toXml(org.w3c.dom.Document) - */ - public Element toXml(Document document) { - Element bindElt = DomUtil.createElement(document, BindConstants.XML_BIND, BindConstants.NAMESPACE); - Element hrefElt = DomUtil.createElement(document, BindConstants.XML_HREF, BindConstants.NAMESPACE, this.href); - Element segElt = DomUtil.createElement(document, BindConstants.XML_SEGMENT, BindConstants.NAMESPACE, this.segment); - bindElt.appendChild(hrefElt); - bindElt.appendChild(segElt); - return bindElt; - } -} Property changes on: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/bind/BindInfo.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/bind/BindServletRequest.java =================================================================== --- jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/bind/BindServletRequest.java (revision 1907912) +++ jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/bind/BindServletRequest.java (nonexistent) @@ -1,65 +0,0 @@ -/* - * 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.webdav.bind; - -import org.apache.jackrabbit.webdav.DavException; -import org.apache.jackrabbit.webdav.DavResourceLocator; - -/** - * BindServletRequest provides extension useful for functionality - * related to BIND specification. - */ -public interface BindServletRequest { - - /** - * Returns the {@link RebindInfo} present with the request - * - * @return {@link RebindInfo} object - * @throws org.apache.jackrabbit.webdav.DavException in case of an invalid or missing request body - */ - public RebindInfo getRebindInfo() throws DavException; - - /** - * Returns the {@link UnbindInfo} present with the request - * - * @return {@link UnbindInfo} object - * @throws org.apache.jackrabbit.webdav.DavException in case of an invalid or missing request body - */ - public UnbindInfo getUnbindInfo() throws DavException; - - /** - * Returns the {@link BindInfo} present with the request - * - * @return {@link BindInfo} object - * @throws org.apache.jackrabbit.webdav.DavException in case of an invalid or missing request body - */ - public BindInfo getBindInfo() throws DavException; - - /** - * Parses a href and returns the path of the resource. - * - * @return path of the resource identified by the href. - */ - public DavResourceLocator getHrefLocator(String href) throws DavException; - - /** - * Returns the path of the member resource of the request resource which is identified by the segment parameter. - * - * @return path of internal member resource. - */ - public DavResourceLocator getMemberLocator(String segment); -} Property changes on: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/bind/BindServletRequest.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/bind/BindableResource.java =================================================================== --- jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/bind/BindableResource.java (revision 1907912) +++ jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/bind/BindableResource.java (nonexistent) @@ -1,50 +0,0 @@ -/* - * 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.webdav.bind; - -import java.util.Set; - -import org.apache.jackrabbit.webdav.DavException; -import org.apache.jackrabbit.webdav.DavResource; - -public interface BindableResource { - - /** - * Will add a new binding to the given collection referencing this resource. - * - * @param collection the collection to create the new binding in. - * @param newBinding the new binding - */ - public void bind(DavResource collection, DavResource newBinding) throws DavException; - - /** - * Will rebind the resource to the given collection. By definition, this is - * an atomic move operation. - * - * @param collection the collection to create the new binding in. - * @param newBinding the new binding - */ - public void rebind(DavResource collection, DavResource newBinding) throws DavException; - - /** - * Will retrieve a collection of parent elements of the bindable resource - * representing the parent set. - * - * @return newBinding the new binding - */ - public Set getParentElements(); -} Property changes on: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/bind/BindableResource.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/bind/ParentElement.java =================================================================== --- jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/bind/ParentElement.java (revision 1907912) +++ jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/bind/ParentElement.java (nonexistent) @@ -1,111 +0,0 @@ -/* - * 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.webdav.bind; - -import org.apache.jackrabbit.webdav.xml.XmlSerializable; -import org.apache.jackrabbit.webdav.xml.DomUtil; -import org.apache.jackrabbit.webdav.xml.ElementIterator; -import org.apache.jackrabbit.webdav.DavException; -import org.apache.jackrabbit.webdav.DavServletResponse; -import org.w3c.dom.Element; -import org.w3c.dom.Document; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * ParentElement wraps en element of the parent set of a resource. A java.util.Set of - * ParentElement objects may serve as the value object of the ParentSet DavProperty. - */ -public class ParentElement implements XmlSerializable { - - private static Logger log = LoggerFactory.getLogger(ParentElement.class); - - private final String href; - private final String segment; - - public ParentElement(String href, String segment) { - this.href = href; - this.segment = segment; - } - - public String getHref() { - return this.href; - } - - public String getSegment() { - return this.segment; - } - - /** - * Build an ParentElement object from an XML element DAV:parent - * - * @param root the DAV:parent element - * @return a ParentElement object - * @throws org.apache.jackrabbit.webdav.DavException if the DAV:parent element is malformed - */ - public static ParentElement createFromXml(Element root) throws DavException { - if (!DomUtil.matches(root, BindConstants.XML_PARENT, BindConstants.NAMESPACE)) { - log.warn("DAV:paret element expected"); - throw new DavException(DavServletResponse.SC_BAD_REQUEST); - } - String href = null; - String segment = null; - ElementIterator it = DomUtil.getChildren(root); - while (it.hasNext()) { - Element elt = it.nextElement(); - if (DomUtil.matches(elt, BindConstants.XML_SEGMENT, BindConstants.NAMESPACE)) { - if (segment == null) { - segment = DomUtil.getText(elt); - } else { - log.warn("unexpected multiple occurrence of DAV:segment element"); - throw new DavException(DavServletResponse.SC_BAD_REQUEST); - } - } else if (DomUtil.matches(elt, BindConstants.XML_HREF, BindConstants.NAMESPACE)) { - if (href == null) { - href = DomUtil.getText(elt); - } else { - log.warn("unexpected multiple occurrence of DAV:href element"); - throw new DavException(DavServletResponse.SC_BAD_REQUEST); - } - } else { - log.warn("unexpected element " + elt.getLocalName()); - throw new DavException(DavServletResponse.SC_BAD_REQUEST); - } - } - if (href == null) { - log.warn("DAV:href element expected"); - throw new DavException(DavServletResponse.SC_BAD_REQUEST); - } - if (segment == null) { - log.warn("DAV:segment element expected"); - throw new DavException(DavServletResponse.SC_BAD_REQUEST); - } - return new ParentElement(href, segment); - } - - /** - * @see org.apache.jackrabbit.webdav.xml.XmlSerializable#toXml(org.w3c.dom.Document) - */ - public Element toXml(Document document) { - Element parentElt = DomUtil.createElement(document, BindConstants.XML_PARENT, BindConstants.NAMESPACE); - Element hrefElt = DomUtil.createElement(document, BindConstants.XML_HREF, BindConstants.NAMESPACE, this.href); - Element segElt = DomUtil.createElement(document, BindConstants.XML_SEGMENT, BindConstants.NAMESPACE, this.segment); - parentElt.appendChild(hrefElt); - parentElt.appendChild(segElt); - return parentElt; - } -} Property changes on: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/bind/ParentElement.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/bind/ParentSet.java =================================================================== --- jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/bind/ParentSet.java (revision 1907912) +++ jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/bind/ParentSet.java (nonexistent) @@ -1,45 +0,0 @@ -/* - * 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.webdav.bind; - -import org.apache.jackrabbit.webdav.property.AbstractDavProperty; - -import java.util.Collection; - -/** - * ParentSet represents a DAV:parent-set property. - */ -public class ParentSet extends AbstractDavProperty> { - - private final Collection parents; - - /** - * Creates a new ParentSet from a collection of ParentElement objects. - * @param parents - */ - public ParentSet(Collection parents) { - super(BindConstants.PARENTSET, true); - this.parents = parents; - } - - /** - * @see org.apache.jackrabbit.webdav.property.AbstractDavProperty#getValue() - */ - public Collection getValue() { - return this.parents; - } -} Property changes on: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/bind/ParentSet.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/bind/RebindInfo.java =================================================================== --- jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/bind/RebindInfo.java (revision 1907912) +++ jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/bind/RebindInfo.java (nonexistent) @@ -1,108 +0,0 @@ -/* - * 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.webdav.bind; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.apache.jackrabbit.webdav.DavServletResponse; -import org.apache.jackrabbit.webdav.DavException; -import org.apache.jackrabbit.webdav.xml.DomUtil; -import org.apache.jackrabbit.webdav.xml.ElementIterator; -import org.apache.jackrabbit.webdav.xml.XmlSerializable; -import org.w3c.dom.Element; -import org.w3c.dom.Document; - -public class RebindInfo implements XmlSerializable { - - private static Logger log = LoggerFactory.getLogger(RebindInfo.class); - - private String segment; - private String href; - - public RebindInfo(String href, String segment) { - this.href = href; - this.segment = segment; - } - - public String getHref() { - return this.href; - } - - public String getSegment() { - return this.segment; - } - - /** - * Build an RebindInfo object from the root element present - * in the request body. - * - * @param root the root element of the request body - * @return a RebindInfo object containing segment and href - * @throws org.apache.jackrabbit.webdav.DavException if the REBIND request is malformed - */ - public static RebindInfo createFromXml(Element root) throws DavException { - if (!DomUtil.matches(root, BindConstants.XML_REBIND, BindConstants.NAMESPACE)) { - log.warn("DAV:rebind element expected"); - throw new DavException(DavServletResponse.SC_BAD_REQUEST); - } - String href = null; - String segment = null; - ElementIterator it = DomUtil.getChildren(root); - while (it.hasNext()) { - Element elt = it.nextElement(); - if (DomUtil.matches(elt, BindConstants.XML_SEGMENT, BindConstants.NAMESPACE)) { - if (segment == null) { - segment = DomUtil.getText(elt); - } else { - log.warn("unexpected multiple occurrence of DAV:segment element"); - throw new DavException(DavServletResponse.SC_BAD_REQUEST); - } - } else if (DomUtil.matches(elt, BindConstants.XML_HREF, BindConstants.NAMESPACE)) { - if (href == null) { - href = DomUtil.getText(elt); - } else { - log.warn("unexpected multiple occurrence of DAV:href element"); - throw new DavException(DavServletResponse.SC_BAD_REQUEST); - } - } else { - log.warn("unexpected element " + elt.getLocalName()); - throw new DavException(DavServletResponse.SC_BAD_REQUEST); - } - } - if (href == null) { - log.warn("DAV:href element expected"); - throw new DavException(DavServletResponse.SC_BAD_REQUEST); - } - if (segment == null) { - log.warn("DAV:segment element expected"); - throw new DavException(DavServletResponse.SC_BAD_REQUEST); - } - return new RebindInfo(href, segment); - } - - /** - * @see org.apache.jackrabbit.webdav.xml.XmlSerializable#toXml(org.w3c.dom.Document) - */ - public Element toXml(Document document) { - Element rebindElt = DomUtil.createElement(document, BindConstants.XML_REBIND, BindConstants.NAMESPACE); - Element hrefElt = DomUtil.createElement(document, BindConstants.XML_HREF, BindConstants.NAMESPACE, this.href); - Element segElt = DomUtil.createElement(document, BindConstants.XML_SEGMENT, BindConstants.NAMESPACE, this.segment); - rebindElt.appendChild(hrefElt); - rebindElt.appendChild(segElt); - return rebindElt; - } -} Property changes on: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/bind/RebindInfo.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/bind/UnbindInfo.java =================================================================== --- jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/bind/UnbindInfo.java (revision 1907912) +++ jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/bind/UnbindInfo.java (nonexistent) @@ -1,90 +0,0 @@ -/* - * 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.webdav.bind; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.apache.jackrabbit.webdav.DavServletResponse; -import org.apache.jackrabbit.webdav.DavException; -import org.apache.jackrabbit.webdav.xml.DomUtil; -import org.apache.jackrabbit.webdav.xml.ElementIterator; -import org.apache.jackrabbit.webdav.xml.XmlSerializable; -import org.w3c.dom.Element; -import org.w3c.dom.Document; - -public class UnbindInfo implements XmlSerializable { - - private static Logger log = LoggerFactory.getLogger(UnbindInfo.class); - - private String segment; - - private UnbindInfo() {} - - public UnbindInfo(String segment) { - this.segment = segment; - } - - public String getSegment() { - return this.segment; - } - - /** - * Build an UnbindInfo object from the root element present - * in the request body. - * - * @param root the root element of the request body - * @return a UnbindInfo object containing a segment identifier - * @throws org.apache.jackrabbit.webdav.DavException if the UNBIND request is malformed - */ - public static UnbindInfo createFromXml(Element root) throws DavException { - if (!DomUtil.matches(root, BindConstants.XML_UNBIND, BindConstants.NAMESPACE)) { - log.warn("DAV:unbind element expected"); - throw new DavException(DavServletResponse.SC_BAD_REQUEST); - } - String segment = null; - ElementIterator it = DomUtil.getChildren(root); - while (it.hasNext()) { - Element elt = it.nextElement(); - if (DomUtil.matches(elt, BindConstants.XML_SEGMENT, BindConstants.NAMESPACE)) { - if (segment == null) { - segment = DomUtil.getText(elt); - } else { - log.warn("unexpected multiple occurrence of DAV:segment element"); - throw new DavException(DavServletResponse.SC_BAD_REQUEST); - } - } else { - log.warn("unexpected element " + elt.getLocalName()); - throw new DavException(DavServletResponse.SC_BAD_REQUEST); - } - } - if (segment == null) { - log.warn("DAV:segment element expected"); - throw new DavException(DavServletResponse.SC_BAD_REQUEST); - } - return new UnbindInfo(segment); - } - - /** - * @see org.apache.jackrabbit.webdav.xml.XmlSerializable#toXml(org.w3c.dom.Document) - */ - public Element toXml(Document document) { - Element unbindElt = DomUtil.createElement(document, BindConstants.XML_UNBIND, BindConstants.NAMESPACE); - Element segElt = DomUtil.createElement(document, BindConstants.XML_SEGMENT, BindConstants.NAMESPACE, this.segment); - unbindElt.appendChild(segElt); - return unbindElt; - } -} Property changes on: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/bind/UnbindInfo.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/bind/package-info.java =================================================================== --- jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/bind/package-info.java (revision 1907912) +++ jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/bind/package-info.java (nonexistent) @@ -1,18 +0,0 @@ -/* - * 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. - */ -@org.osgi.annotation.versioning.Version("1.0.0") -package org.apache.jackrabbit.webdav.bind; Property changes on: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/bind/package-info.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/BaseDavRequest.java =================================================================== --- jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/BaseDavRequest.java (revision 1907912) +++ jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/BaseDavRequest.java (nonexistent) @@ -1,219 +0,0 @@ -/* - * 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.webdav.client.methods; - -import java.io.IOException; -import java.io.InputStream; -import java.net.URI; - -import javax.xml.parsers.ParserConfigurationException; - -import org.apache.http.HttpEntity; -import org.apache.http.HttpResponse; -import org.apache.http.StatusLine; -import org.apache.http.client.methods.HttpEntityEnclosingRequestBase; -import org.apache.jackrabbit.webdav.DavConstants; -import org.apache.jackrabbit.webdav.DavException; -import org.apache.jackrabbit.webdav.MultiStatus; -import org.apache.jackrabbit.webdav.lock.LockDiscovery; -import org.apache.jackrabbit.webdav.observation.EventDiscovery; -import org.apache.jackrabbit.webdav.observation.ObservationConstants; -import org.apache.jackrabbit.webdav.observation.Subscription; -import org.apache.jackrabbit.webdav.observation.SubscriptionDiscovery; -import org.apache.jackrabbit.webdav.xml.DomUtil; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.w3c.dom.Document; -import org.w3c.dom.Element; -import org.xml.sax.SAXException; - -/** - * Base class for HTTP request classes defined in this package. - */ -public abstract class BaseDavRequest extends HttpEntityEnclosingRequestBase { - - private static Logger log = LoggerFactory.getLogger(BaseDavRequest.class); - - public BaseDavRequest(URI uri) { - super(); - super.setURI(uri); - } - - /** - * Gets a {@link Document} representing the response body. - * @return document or {@code null} for null entity - * @throws IOException in case of I/O or XMP pasting problems - */ - public Document getResponseBodyAsDocument(HttpEntity entity) throws IOException { - - if (entity == null) { - return null; - } else { - // read response and try to build a xml document - InputStream in = entity.getContent(); - try { - return DomUtil.parseDocument(in); - } catch (ParserConfigurationException ex) { - throw new IOException("XML parser configuration error", ex); - } catch (SAXException ex) { - throw new IOException("XML parsing error", ex); - } finally { - in.close(); - } - } - } - - /** - * Return response body as {@link MultiStatus} object. - * @throws IllegalStateException when response does not represent a {@link MultiStatus} - * @throws DavException for failures in obtaining/parsing the response body - */ - public MultiStatus getResponseBodyAsMultiStatus(HttpResponse response) throws DavException { - try { - Document doc = getResponseBodyAsDocument(response.getEntity()); - if (doc == null) { - throw new DavException(response.getStatusLine().getStatusCode(), "no response body"); - } - return MultiStatus.createFromXml(doc.getDocumentElement()); - } catch (IOException ex) { - throw new DavException(response.getStatusLine().getStatusCode(), ex); - } - } - - /** - * Return response body as {@link LockDiscovery} object. - * @throws IllegalStateException when response does not represent a {@link LockDiscovery} - * @throws DavException for failures in obtaining/parsing the response body - */ - public LockDiscovery getResponseBodyAsLockDiscovery(HttpResponse response) throws DavException { - try { - Document doc = getResponseBodyAsDocument(response.getEntity()); - if (doc == null) { - throw new DavException(response.getStatusLine().getStatusCode(), "no response body"); - } - Element root = doc.getDocumentElement(); - - if (!DomUtil.matches(root, DavConstants.XML_PROP, DavConstants.NAMESPACE) - && DomUtil.hasChildElement(root, DavConstants.PROPERTY_LOCKDISCOVERY, DavConstants.NAMESPACE)) { - throw new DavException(response.getStatusLine().getStatusCode(), - "Missing DAV:prop response body in LOCK response."); - } - - Element lde = DomUtil.getChildElement(root, DavConstants.PROPERTY_LOCKDISCOVERY, DavConstants.NAMESPACE); - if (!DomUtil.hasChildElement(lde, DavConstants.XML_ACTIVELOCK, DavConstants.NAMESPACE)) { - throw new DavException(response.getStatusLine().getStatusCode(), - "The DAV:lockdiscovery must contain a least a single DAV:activelock in response to a successful LOCK request."); - } - - return LockDiscovery.createFromXml(lde); - } catch (IOException ex) { - throw new DavException(response.getStatusLine().getStatusCode(), ex); - } - } - - /** - * Return response body as {@link SubscriptionDiscovery} object. - * @throws IllegalStateException when response does not represent a {@link SubscriptionDiscovery} - * @throws DavException for failures in obtaining/parsing the response body - */ - public SubscriptionDiscovery getResponseBodyAsSubscriptionDiscovery(HttpResponse response) throws DavException { - try { - Document doc = getResponseBodyAsDocument(response.getEntity()); - if (doc == null) { - throw new DavException(response.getStatusLine().getStatusCode(), "no response body"); - } - Element root = doc.getDocumentElement(); - - if (!DomUtil.matches(root, DavConstants.XML_PROP, DavConstants.NAMESPACE) - && DomUtil.hasChildElement(root, ObservationConstants.SUBSCRIPTIONDISCOVERY.getName(), - ObservationConstants.SUBSCRIPTIONDISCOVERY.getNamespace())) { - throw new DavException(response.getStatusLine().getStatusCode(), - "Missing DAV:prop response body in SUBSCRIBE response."); - } - - Element sde = DomUtil.getChildElement(root, ObservationConstants.SUBSCRIPTIONDISCOVERY.getName(), - ObservationConstants.SUBSCRIPTIONDISCOVERY.getNamespace()); - SubscriptionDiscovery sd = SubscriptionDiscovery.createFromXml(sde); - if (((Subscription[]) sd.getValue()).length > 0) { - return sd; - } else { - throw new DavException(response.getStatusLine().getStatusCode(), - "Missing 'subscription' elements in SUBSCRIBE response body. At least a single subscription must be present if SUBSCRIBE was successful."); - } - } catch (IOException ex) { - throw new DavException(response.getStatusLine().getStatusCode(), ex); - } - } - - /** - * Return response body as {@link EventDiscovery} object. - * @throws IllegalStateException when response does not represent a {@link EventDiscovery} - * @throws DavException for failures in obtaining/parsing the response body - */ - public EventDiscovery getResponseBodyAsEventDiscovery(HttpResponse response) throws DavException { - try { - Document doc = getResponseBodyAsDocument(response.getEntity()); - if (doc == null) { - throw new DavException(response.getStatusLine().getStatusCode(), "no response body"); - } - return EventDiscovery.createFromXml(doc.getDocumentElement()); - } catch (IOException ex) { - throw new DavException(response.getStatusLine().getStatusCode(), ex); - } - } - - /** - * Check the response and throw when it is considered to represent a failure. - */ - public void checkSuccess(HttpResponse response) throws DavException { - if (!succeeded(response)) { - throw getResponseException(response); - } - } - - /** - * Obtain a {@link DavException} representing the response. - * @throws IllegalStateException when the response is considered to be successful - */ - public DavException getResponseException(HttpResponse response) { - if (succeeded(response)) { - String msg = "Cannot retrieve exception from successful response."; - log.warn(msg); - throw new IllegalStateException(msg); - } - - StatusLine st = response.getStatusLine(); - Element responseRoot = null; - try { - responseRoot = getResponseBodyAsDocument(response.getEntity()).getDocumentElement(); - } catch (IOException e) { - // non-parseable body -> use null element - } - - return new DavException(st.getStatusCode(), st.getReasonPhrase(), null, responseRoot); - } - - /** - * Check the provided {@link HttpResponse} for successful execution. The default implementation treats all - * 2xx status codes (RFC 7231, Section 6.3). - * Implementations can further restrict the accepted range of responses (or even check the response body). - */ - public boolean succeeded(HttpResponse response) { - int status = response.getStatusLine().getStatusCode(); - return status >= 200 && status <= 299; - } -} Property changes on: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/BaseDavRequest.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpBind.java =================================================================== --- jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpBind.java (revision 1907912) +++ jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpBind.java (nonexistent) @@ -1,54 +0,0 @@ -/* - * 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.webdav.client.methods; - -import java.io.IOException; -import java.net.URI; - -import org.apache.http.HttpResponse; -import org.apache.jackrabbit.webdav.DavMethods; -import org.apache.jackrabbit.webdav.DavServletResponse; -import org.apache.jackrabbit.webdav.bind.BindInfo; - -/** - * Represents an HTTP BIND request. - * - * @see RFC 5842, Section 4 - * @since 2.13.6 - */ -public class HttpBind extends BaseDavRequest { - - public HttpBind(URI uri, BindInfo info) throws IOException { - super(uri); - super.setEntity(XmlEntity.create(info)); - } - - public HttpBind(String uri, BindInfo info) throws IOException { - this(URI.create(uri), info); - } - - @Override - public String getMethod() { - return DavMethods.METHOD_BIND; - } - - @Override - public boolean succeeded(HttpResponse response) { - int statusCode = response.getStatusLine().getStatusCode(); - return statusCode == DavServletResponse.SC_OK || statusCode == DavServletResponse.SC_CREATED; - } -} \ No newline at end of file Property changes on: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpBind.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpCheckin.java =================================================================== --- jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpCheckin.java (revision 1907912) +++ jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpCheckin.java (nonexistent) @@ -1,51 +0,0 @@ -/* - * 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.webdav.client.methods; - -import java.net.URI; - -import org.apache.http.HttpResponse; -import org.apache.jackrabbit.webdav.DavMethods; -import org.apache.jackrabbit.webdav.DavServletResponse; - -/** - * Represents an HTTP CHECKIN request. - * - * @see RFC 3253, Section 4.4 - * @since 2.13.6 - */ -public class HttpCheckin extends BaseDavRequest { - - public HttpCheckin(URI uri) { - super(uri); - } - - public HttpCheckin(String uri) { - this(URI.create(uri)); - } - - @Override - public String getMethod() { - return DavMethods.METHOD_CHECKIN; - } - - @Override - public boolean succeeded(HttpResponse response) { - int statusCode = response.getStatusLine().getStatusCode(); - return statusCode == DavServletResponse.SC_CREATED; - } -} Property changes on: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpCheckin.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpCheckout.java =================================================================== --- jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpCheckout.java (revision 1907912) +++ jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpCheckout.java (nonexistent) @@ -1,51 +0,0 @@ -/* - * 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.webdav.client.methods; - -import java.net.URI; - -import org.apache.http.HttpResponse; -import org.apache.jackrabbit.webdav.DavMethods; -import org.apache.jackrabbit.webdav.DavServletResponse; - -/** - * Represents an HTTP CHECKOUT request. - * - * @see RFC 3253, Section 4.3 - * @since 2.13.6 - */ -public class HttpCheckout extends BaseDavRequest { - - public HttpCheckout(URI uri) { - super(uri); - } - - public HttpCheckout(String uri) { - this(URI.create(uri)); - } - - @Override - public String getMethod() { - return DavMethods.METHOD_CHECKOUT; - } - - @Override - public boolean succeeded(HttpResponse response) { - int statusCode = response.getStatusLine().getStatusCode(); - return statusCode == DavServletResponse.SC_OK; - } -} Property changes on: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpCheckout.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpCopy.java =================================================================== --- jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpCopy.java (revision 1907912) +++ jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpCopy.java (nonexistent) @@ -1,59 +0,0 @@ -/* - * 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.webdav.client.methods; - -import java.net.URI; - -import org.apache.http.HttpResponse; -import org.apache.jackrabbit.webdav.DavConstants; -import org.apache.jackrabbit.webdav.DavMethods; -import org.apache.jackrabbit.webdav.DavServletResponse; - -/** - * Represents an HTTP COPY request. - * - * @see RFC 4918, Section 9.8 - * @since 2.13.6 - */ -public class HttpCopy extends BaseDavRequest { - - public HttpCopy(URI uri, URI dest, boolean overwrite, boolean shallow) { - super(uri); - super.setHeader(DavConstants.HEADER_DESTINATION, dest.toASCIIString()); - if (!overwrite) { - super.setHeader(DavConstants.HEADER_OVERWRITE, "F"); - } - if (shallow) { - super.setHeader("Depth", "0"); - } - } - - public HttpCopy(String uri, String dest, boolean overwrite, boolean shallow) { - this(URI.create(uri), URI.create(dest), overwrite, shallow); - } - - @Override - public String getMethod() { - return DavMethods.METHOD_COPY; - } - - @Override - public boolean succeeded(HttpResponse response) { - int statusCode = response.getStatusLine().getStatusCode(); - return statusCode == DavServletResponse.SC_CREATED || statusCode == DavServletResponse.SC_NO_CONTENT; - } -} Property changes on: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpCopy.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpDelete.java =================================================================== --- jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpDelete.java (revision 1907912) +++ jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpDelete.java (nonexistent) @@ -1,43 +0,0 @@ -/* - * 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.webdav.client.methods; - -import java.net.URI; - -import org.apache.jackrabbit.webdav.DavMethods; - -/** - * Represents an HTTP DELETE request. - * - * @see RFC 7231, Section 4.3.5 - * @since 2.13.6 - */ -public class HttpDelete extends BaseDavRequest { - - public HttpDelete(URI uri){ - super(uri); - } - - public HttpDelete(String uri) { - this(URI.create(uri)); - } - - @Override - public String getMethod() { - return DavMethods.METHOD_DELETE; - } -} \ No newline at end of file Property changes on: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpDelete.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpLabel.java =================================================================== --- jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpLabel.java (revision 1907912) +++ jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpLabel.java (nonexistent) @@ -1,57 +0,0 @@ -/* - * 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.webdav.client.methods; - -import java.io.IOException; -import java.net.URI; - -import org.apache.http.HttpResponse; -import org.apache.jackrabbit.webdav.DavMethods; -import org.apache.jackrabbit.webdav.DavServletResponse; -import org.apache.jackrabbit.webdav.header.DepthHeader; -import org.apache.jackrabbit.webdav.version.LabelInfo; - -/** - * Represents an HTTP LABEL request. - * - * @see RFC 3253, Section 8.2 - * @since 2.13.6 - */ -public class HttpLabel extends BaseDavRequest { - - public HttpLabel(URI uri, LabelInfo labelInfo) throws IOException { - super(uri); - DepthHeader dh = new DepthHeader(labelInfo.getDepth()); - super.setHeader(dh.getHeaderName(), dh.getHeaderValue()); - super.setEntity(XmlEntity.create(labelInfo)); - } - - public HttpLabel(String uri, LabelInfo labelInfo) throws IOException { - this(URI.create(uri), labelInfo); - } - - @Override - public String getMethod() { - return DavMethods.METHOD_LABEL; - } - - @Override - public boolean succeeded(HttpResponse response) { - int statusCode = response.getStatusLine().getStatusCode(); - return statusCode == DavServletResponse.SC_OK; - } -} Property changes on: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpLabel.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpLock.java =================================================================== --- jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpLock.java (revision 1907912) +++ jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpLock.java (nonexistent) @@ -1,107 +0,0 @@ -/* - * 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.webdav.client.methods; - -import java.io.IOException; -import java.net.URI; -import java.util.Arrays; - -import org.apache.http.Header; -import org.apache.http.HttpResponse; -import org.apache.jackrabbit.webdav.DavConstants; -import org.apache.jackrabbit.webdav.DavMethods; -import org.apache.jackrabbit.webdav.DavServletResponse; -import org.apache.jackrabbit.webdav.header.DepthHeader; -import org.apache.jackrabbit.webdav.header.IfHeader; -import org.apache.jackrabbit.webdav.header.TimeoutHeader; -import org.apache.jackrabbit.webdav.lock.LockInfo; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * Represents an HTTP LOCK request. - * - * @see RFC 4918, Section 9.10 - * @since 2.13.6 - */ -public class HttpLock extends BaseDavRequest { - - private static final Logger LOG = LoggerFactory.getLogger(HttpLock.class); - - private final boolean isRefresh; - - public HttpLock(URI uri, LockInfo lockInfo) throws IOException { - super(uri); - - TimeoutHeader th = new TimeoutHeader(lockInfo.getTimeout()); - super.setHeader(th.getHeaderName(), th.getHeaderValue()); - DepthHeader dh = new DepthHeader(lockInfo.isDeep()); - super.setHeader(dh.getHeaderName(), dh.getHeaderValue()); - - super.setEntity(XmlEntity.create(lockInfo)); - - isRefresh = false; - } - - public HttpLock(String uri, LockInfo lockInfo) throws IOException { - this(URI.create(uri), lockInfo); - } - - public HttpLock(URI uri, long timeout, String[] lockTokens) { - super(uri); - - TimeoutHeader th = new TimeoutHeader(timeout); - super.setHeader(th.getHeaderName(), th.getHeaderValue()); - IfHeader ifh = new IfHeader(lockTokens); - super.setHeader(ifh.getHeaderName(), ifh.getHeaderValue()); - isRefresh = true; - } - - public HttpLock(String uri, long timeout, String[] lockTokens) { - this(URI.create(uri), timeout, lockTokens); - } - - @Override - public String getMethod() { - return DavMethods.METHOD_LOCK; - } - - public String getLockToken(HttpResponse response) { - Header[] ltHeader = response.getHeaders(DavConstants.HEADER_LOCK_TOKEN); - if (ltHeader == null || ltHeader.length == 0) { - return null; - } else if (ltHeader.length != 1) { - LOG.debug("Multiple 'Lock-Token' header fields in response for " + getURI() + ": " + Arrays.asList(ltHeader)); - return null; - } else { - String v = ltHeader[0].getValue().trim(); - if (!v.startsWith("<") || !v.endsWith(">")) { - LOG.debug("Invalid 'Lock-Token' header field in response for " + getURI() + ": " + Arrays.asList(ltHeader)); - return null; - } else { - return v.substring(1, v.length() - 1); - } - } - } - - @Override - public boolean succeeded(HttpResponse response) { - int statusCode = response.getStatusLine().getStatusCode(); - boolean lockTokenHeaderOk = isRefresh || null != getLockToken(response); - return lockTokenHeaderOk && (statusCode == DavServletResponse.SC_OK || statusCode == DavServletResponse.SC_CREATED); - } -} \ No newline at end of file Property changes on: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpLock.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpMerge.java =================================================================== --- jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpMerge.java (revision 1907912) +++ jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpMerge.java (nonexistent) @@ -1,55 +0,0 @@ -/* - * 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.webdav.client.methods; - -import java.io.IOException; -import java.net.URI; - -import org.apache.http.HttpResponse; -import org.apache.jackrabbit.webdav.DavMethods; -import org.apache.jackrabbit.webdav.DavServletResponse; -import org.apache.jackrabbit.webdav.version.MergeInfo; - -/** - * Represents an HTTP MERGE request. - * - * @see RFC 3253, Section 11.2 - * @since 2.13.6 - */ -public class HttpMerge extends BaseDavRequest { - - public HttpMerge(URI uri, MergeInfo mergeInfo) throws IOException { - super(uri); - super.setEntity(XmlEntity.create(mergeInfo)); - } - - public HttpMerge(String uri, MergeInfo mergeInfo) throws IOException { - this(URI.create(uri), mergeInfo); - } - - @Override - public String getMethod() { - return DavMethods.METHOD_MERGE; - } - - @Override - public boolean succeeded(HttpResponse response) { - int statusCode = response.getStatusLine().getStatusCode(); - // TODO: is this correct? - return statusCode == DavServletResponse.SC_MULTI_STATUS; - } -} Property changes on: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpMerge.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpMkcol.java =================================================================== --- jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpMkcol.java (revision 1907912) +++ jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpMkcol.java (nonexistent) @@ -1,51 +0,0 @@ -/* - * 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.webdav.client.methods; - -import java.net.URI; - -import org.apache.http.HttpResponse; -import org.apache.jackrabbit.webdav.DavMethods; -import org.apache.jackrabbit.webdav.DavServletResponse; - -/** - * Represents an HTTP MKCOL request. - * - * @see RFC 4918, Section 9.3 - * @since 2.13.6 - */ -public class HttpMkcol extends BaseDavRequest { - - public HttpMkcol(URI uri) { - super(uri); - } - - public HttpMkcol(String uri) { - this(URI.create(uri)); - } - - @Override - public String getMethod() { - return DavMethods.METHOD_MKCOL; - } - - @Override - public boolean succeeded(HttpResponse response) { - int statusCode = response.getStatusLine().getStatusCode(); - return statusCode == DavServletResponse.SC_CREATED; - } -} Property changes on: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpMkcol.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpMkworkspace.java =================================================================== --- jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpMkworkspace.java (revision 1907912) +++ jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpMkworkspace.java (nonexistent) @@ -1,51 +0,0 @@ -/* - * 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.webdav.client.methods; - -import java.net.URI; - -import org.apache.http.HttpResponse; -import org.apache.jackrabbit.webdav.DavMethods; -import org.apache.jackrabbit.webdav.DavServletResponse; - -/** - * Represents an HTTP MKWORKSPACE request. - * - * @see RFC 3253, Section 6.3 - * @since 2.13.6 - */ -public class HttpMkworkspace extends BaseDavRequest { - - public HttpMkworkspace(URI uri) { - super(uri); - } - - public HttpMkworkspace(String uri) { - this(URI.create(uri)); - } - - @Override - public String getMethod() { - return DavMethods.METHOD_MKWORKSPACE; - } - - @Override - public boolean succeeded(HttpResponse response) { - int statusCode = response.getStatusLine().getStatusCode(); - return statusCode == DavServletResponse.SC_CREATED; - } -} Property changes on: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpMkworkspace.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpMove.java =================================================================== --- jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpMove.java (revision 1907912) +++ jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpMove.java (nonexistent) @@ -1,56 +0,0 @@ -/* - * 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.webdav.client.methods; - -import java.net.URI; - -import org.apache.http.HttpResponse; -import org.apache.jackrabbit.webdav.DavConstants; -import org.apache.jackrabbit.webdav.DavMethods; -import org.apache.jackrabbit.webdav.DavServletResponse; - -/** - * Represents an HTTP MOVE request. - * - * @see RFC 4918, Section 9.9 - * @since 2.13.6 - */ -public class HttpMove extends BaseDavRequest { - - public HttpMove(URI uri, URI dest, boolean overwrite) { - super(uri); - super.setHeader(DavConstants.HEADER_DESTINATION, dest.toASCIIString()); - if (!overwrite) { - super.setHeader(DavConstants.HEADER_OVERWRITE, "F"); - } - } - - public HttpMove(String uri, String dest, boolean overwrite) { - this(URI.create(uri), URI.create(dest), overwrite); - } - - @Override - public String getMethod() { - return DavMethods.METHOD_MOVE; - } - - @Override - public boolean succeeded(HttpResponse response) { - int statusCode = response.getStatusLine().getStatusCode(); - return statusCode == DavServletResponse.SC_CREATED || statusCode == DavServletResponse.SC_NO_CONTENT; - } -} Property changes on: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpMove.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpOptions.java =================================================================== --- jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpOptions.java (revision 1907912) +++ jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpOptions.java (nonexistent) @@ -1,79 +0,0 @@ -/* - * 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.webdav.client.methods; - -import java.net.URI; -import java.util.Collections; -import java.util.HashSet; -import java.util.Set; - -import org.apache.http.Header; -import org.apache.http.HttpResponse; -import org.apache.jackrabbit.webdav.DavConstants; -import org.apache.jackrabbit.webdav.header.FieldValueParser; -import org.apache.jackrabbit.webdav.search.SearchConstants; - -/** - * Represents an HTTP OPTIONS request. - * - * @see RFC 7231, Section 4.3.7 - * @since 2.13.6 - */ -public class HttpOptions extends org.apache.http.client.methods.HttpOptions { - - public HttpOptions(URI uri) { - super(uri); - } - - public HttpOptions(String uri) { - super(URI.create(uri)); - } - - /** - * Compute the set of compliance classes returned in the "dav" header field - */ - public Set getDavComplianceClasses(HttpResponse response) { - Header[] headers = response.getHeaders(DavConstants.HEADER_DAV); - return parseTokenOrCodedUrlheaderField(headers, false); - } - - /** - * Compute set of search grammars returned in the "dasl" header field - */ - public Set getSearchGrammars(HttpResponse response) { - Header[] headers = response.getHeaders(SearchConstants.HEADER_DASL); - return parseTokenOrCodedUrlheaderField(headers, true); - } - - private Set parseTokenOrCodedUrlheaderField(Header[] headers, boolean removeBrackets) { - if (headers == null) { - return Collections.emptySet(); - } - else { - Set result = new HashSet(); - for (Header h : headers) { - for (String s : FieldValueParser.tokenizeList(h.getValue())) { - if (removeBrackets && s.startsWith("<") && s.endsWith(">")) { - s = s.substring(1, s.length() - 1); - } - result.add(s.trim()); - } - } - return Collections.unmodifiableSet(result); - } - } -} Property changes on: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpOptions.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpOrderpatch.java =================================================================== --- jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpOrderpatch.java (revision 1907912) +++ jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpOrderpatch.java (nonexistent) @@ -1,53 +0,0 @@ -/* - * 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.webdav.client.methods; - -import java.io.IOException; -import java.net.URI; - -import org.apache.http.HttpResponse; -import org.apache.jackrabbit.webdav.DavMethods; -import org.apache.jackrabbit.webdav.DavServletResponse; -import org.apache.jackrabbit.webdav.ordering.OrderPatch; - -/** - * Represents an HTTP ORDERPATCH request. - * - * @see RFC 3648, Section 5 - * @since 2.13.6 - */ -public class HttpOrderpatch extends BaseDavRequest { - - public HttpOrderpatch(URI uri, OrderPatch info) throws IOException { - super(uri); - super.setEntity(XmlEntity.create(info)); - } - - public HttpOrderpatch(String uri, OrderPatch info) throws IOException { - this(URI.create(uri), info); - } - - @Override - public String getMethod() { - return DavMethods.METHOD_ORDERPATCH; - } - - @Override - public boolean succeeded(HttpResponse response) { - return response.getStatusLine().getStatusCode() == DavServletResponse.SC_OK; - } -} \ No newline at end of file Property changes on: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpOrderpatch.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpPoll.java =================================================================== --- jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpPoll.java (revision 1907912) +++ jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpPoll.java (nonexistent) @@ -1,58 +0,0 @@ -/* - * 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.webdav.client.methods; - -import java.net.URI; - -import org.apache.http.HttpResponse; -import org.apache.jackrabbit.webdav.DavMethods; -import org.apache.jackrabbit.webdav.DavServletResponse; -import org.apache.jackrabbit.webdav.header.PollTimeoutHeader; -import org.apache.jackrabbit.webdav.observation.ObservationConstants; - -/** - * Represents an HTTP POLL request. - *

- * Note that "POLL" is a custom HTTP extension, not defined in a standards paper. - * @since 2.13.6 - */ -public class HttpPoll extends BaseDavRequest { - - public HttpPoll(URI uri, String subscriptionId, long timeout) { - super(uri); - super.setHeader(ObservationConstants.HEADER_SUBSCRIPTIONID, subscriptionId); - if (timeout > 0) { - PollTimeoutHeader th = new PollTimeoutHeader(timeout); - super.setHeader(th.getHeaderName(), th.getHeaderValue()); - } - } - - public HttpPoll(String uri, String subscriptionId, long timeout) { - this(URI.create(uri), subscriptionId, timeout); - } - - @Override - public String getMethod() { - return DavMethods.METHOD_POLL; - } - - @Override - public boolean succeeded(HttpResponse response) { - int statusCode = response.getStatusLine().getStatusCode(); - return statusCode == DavServletResponse.SC_OK; - } -} \ No newline at end of file Property changes on: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpPoll.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpPropfind.java =================================================================== --- jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpPropfind.java (revision 1907912) +++ jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpPropfind.java (nonexistent) @@ -1,77 +0,0 @@ -/* - * 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.webdav.client.methods; - -import java.io.IOException; -import java.net.URI; - -import org.apache.http.HttpResponse; -import org.apache.jackrabbit.webdav.DavConstants; -import org.apache.jackrabbit.webdav.DavMethods; -import org.apache.jackrabbit.webdav.DavServletResponse; -import org.apache.jackrabbit.webdav.header.DepthHeader; -import org.apache.jackrabbit.webdav.property.DavPropertyNameSet; -import org.apache.jackrabbit.webdav.property.PropfindInfo; - -/** - * Represents an HTTP PROPFIND request. - * - * @see RFC 4918, Section 9.1 - * @since 2.13.6 - */ -public class HttpPropfind extends BaseDavRequest { - - public HttpPropfind(URI uri, int propfindType, DavPropertyNameSet names, int depth) throws IOException { - super(uri); - - DepthHeader dh = new DepthHeader(depth); - super.setHeader(dh.getHeaderName(), dh.getHeaderValue()); - - PropfindInfo info = new PropfindInfo(propfindType, names); - super.setEntity(XmlEntity.create(info)); - } - - public HttpPropfind(URI uri, DavPropertyNameSet names, int depth) throws IOException { - this(uri, DavConstants.PROPFIND_BY_PROPERTY, names, depth); - } - - public HttpPropfind(URI uri, int propfindType, int depth) throws IOException { - this(uri, propfindType, new DavPropertyNameSet(), depth); - } - - public HttpPropfind(String uri, int propfindType, int depth) throws IOException { - this(URI.create(uri), propfindType, depth); - } - - public HttpPropfind(String uri, int propfindType, DavPropertyNameSet names, int depth) throws IOException { - this(URI.create(uri), propfindType, names, depth); - } - - public HttpPropfind(String uri, DavPropertyNameSet names, int depth) throws IOException { - this(URI.create(uri), names, depth); - } - - @Override - public String getMethod() { - return DavMethods.METHOD_PROPFIND; - } - - @Override - public boolean succeeded(HttpResponse response) { - return response.getStatusLine().getStatusCode() == DavServletResponse.SC_MULTI_STATUS; - } -} \ No newline at end of file Property changes on: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpPropfind.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpProppatch.java =================================================================== --- jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpProppatch.java (revision 1907912) +++ jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpProppatch.java (nonexistent) @@ -1,104 +0,0 @@ -/* - * 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.webdav.client.methods; - -import java.io.IOException; -import java.net.URI; -import java.util.List; - -import org.apache.http.HttpResponse; -import org.apache.jackrabbit.webdav.DavMethods; -import org.apache.jackrabbit.webdav.DavServletResponse; -import org.apache.jackrabbit.webdav.property.DavPropertyNameSet; -import org.apache.jackrabbit.webdav.property.DavPropertySet; -import org.apache.jackrabbit.webdav.property.PropEntry; -import org.apache.jackrabbit.webdav.property.ProppatchInfo; - -/** - * Represents an HTTP PROPPATCH request. - * - * @see RFC 4918, Section 9.2 - * @since 2.13.6 - */ -public class HttpProppatch extends BaseDavRequest { - - // private DavPropertyNameSet propertyNames; - - public HttpProppatch(URI uri, ProppatchInfo info) throws IOException { - super(uri); - super.setEntity(XmlEntity.create(info)); - // this.propertyNames = info.getAffectedProperties(); - } - - public HttpProppatch(URI uri, List changeList) throws IOException { - this(uri, new ProppatchInfo(changeList)); - } - - public HttpProppatch(URI uri, DavPropertySet setProperties, DavPropertyNameSet removeProperties) throws IOException { - this(uri, new ProppatchInfo(setProperties, removeProperties)); - } - - public HttpProppatch(String uri, List changeList) throws IOException { - this(URI.create(uri), new ProppatchInfo(changeList)); - } - - public HttpProppatch(String uri, DavPropertySet setProperties, DavPropertyNameSet removeProperties) throws IOException { - this(URI.create(uri), new ProppatchInfo(setProperties, removeProperties)); - } - - @Override - public String getMethod() { - return DavMethods.METHOD_PROPPATCH; - } - - @Override - public boolean succeeded(HttpResponse response) { - return response.getStatusLine().getStatusCode() == DavServletResponse.SC_MULTI_STATUS; - - // disabled code that fails for current PROPPATCH behavior of Jackrabbit -// MultiStatusResponse responses[] = super.getResponseBodyAsMultiStatus(response).getResponses(); -// if (responses.length != 1) { -// throw new DavException(DavServletResponse.SC_MULTI_STATUS, -// "PROPPATCH failed: Expected exactly one multistatus response element, but got " + responses.length); -// } -// DavPropertyNameSet okSet = responses[0].getPropertyNames(DavServletResponse.SC_OK); -// if (okSet.isEmpty()) { -// throw new DavException(DavServletResponse.SC_MULTI_STATUS, -// "PROPPATCH failed: No 'OK' response found for resource " + responses[0].getHref()); -// } else { -// DavPropertyNameIterator it = propertyNames.iterator(); -// while (it.hasNext()) { -// DavPropertyName pn = it.nextPropertyName(); -// boolean success = okSet.remove(pn); -// if (!success) { -// throw new DavException(DavServletResponse.SC_MULTI_STATUS, -// "PROPPATCH failed: Property name not present in multistatus response: " + pn); -// } -// } -// } -// if (!okSet.isEmpty()) { -// StringBuilder b = new StringBuilder(); -// DavPropertyNameIterator it = okSet.iterator(); -// while (it.hasNext()) { -// b.append(it.nextPropertyName().toString()).append("; "); -// } -// throw new DavException(DavServletResponse.SC_MULTI_STATUS, -// "PROPPATCH failed: The following properties outside of the original request where set or removed: " + b.toString()); -// } -// return true; - } -} \ No newline at end of file Property changes on: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpProppatch.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpRebind.java =================================================================== --- jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpRebind.java (revision 1907912) +++ jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpRebind.java (nonexistent) @@ -1,54 +0,0 @@ -/* - * 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.webdav.client.methods; - -import java.io.IOException; -import java.net.URI; - -import org.apache.http.HttpResponse; -import org.apache.jackrabbit.webdav.DavMethods; -import org.apache.jackrabbit.webdav.DavServletResponse; -import org.apache.jackrabbit.webdav.bind.RebindInfo; - -/** - * Represents an HTTP REBIND request. - * - * @see RFC 5842, Section 6 - * @since 2.13.6 - */ -public class HttpRebind extends BaseDavRequest { - - public HttpRebind(URI uri, RebindInfo info) throws IOException { - super(uri); - super.setEntity(XmlEntity.create(info)); - } - - public HttpRebind(String uri, RebindInfo info) throws IOException { - this(URI.create(uri), info); - } - - @Override - public String getMethod() { - return DavMethods.METHOD_REBIND; - } - - @Override - public boolean succeeded(HttpResponse response) { - int statusCode = response.getStatusLine().getStatusCode(); - return statusCode == DavServletResponse.SC_OK || statusCode == DavServletResponse.SC_CREATED; - } -} \ No newline at end of file Property changes on: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpRebind.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpReport.java =================================================================== --- jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpReport.java (revision 1907912) +++ jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpReport.java (nonexistent) @@ -1,66 +0,0 @@ -/* - * 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.webdav.client.methods; - -import java.io.IOException; -import java.net.URI; - -import org.apache.http.HttpResponse; -import org.apache.jackrabbit.webdav.DavConstants; -import org.apache.jackrabbit.webdav.DavMethods; -import org.apache.jackrabbit.webdav.DavServletResponse; -import org.apache.jackrabbit.webdav.header.DepthHeader; -import org.apache.jackrabbit.webdav.version.report.ReportInfo; - -/** - * Represents an HTTP REPORT request. - * - * @see RFC 3253, Section 3.6 - * @since 2.13.6 - */ -public class HttpReport extends BaseDavRequest { - - private final boolean isDeep; - - public HttpReport(URI uri, ReportInfo reportInfo) throws IOException { - super(uri); - DepthHeader dh = new DepthHeader(reportInfo.getDepth()); - isDeep = reportInfo.getDepth() > DavConstants.DEPTH_0; - super.setHeader(dh.getHeaderName(), dh.getHeaderValue()); - super.setEntity(XmlEntity.create(reportInfo)); - } - - public HttpReport(String uri, ReportInfo reportInfo) throws IOException { - this(URI.create(uri), reportInfo); - } - - @Override - public String getMethod() { - return DavMethods.METHOD_REPORT; - } - - @Override - public boolean succeeded(HttpResponse response) { - int statusCode = response.getStatusLine().getStatusCode(); - if (isDeep) { - return statusCode == DavServletResponse.SC_MULTI_STATUS; - } else { - return statusCode == DavServletResponse.SC_OK || statusCode == DavServletResponse.SC_MULTI_STATUS; - } - - } -} \ No newline at end of file Property changes on: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpReport.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpSearch.java =================================================================== --- jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpSearch.java (revision 1907912) +++ jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpSearch.java (nonexistent) @@ -1,54 +0,0 @@ -/* - * 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.webdav.client.methods; - -import java.io.IOException; -import java.net.URI; - -import org.apache.http.HttpResponse; -import org.apache.jackrabbit.webdav.DavMethods; -import org.apache.jackrabbit.webdav.DavServletResponse; -import org.apache.jackrabbit.webdav.search.SearchInfo; - -/** - * Represents an HTTP SEARCH request. - * - * @see RFC 5323, Section 2 - * @since 2.13.6 - */ -public class HttpSearch extends BaseDavRequest { - - public HttpSearch(URI uri, SearchInfo searchInfo) throws IOException { - super(uri); - super.setEntity(XmlEntity.create(searchInfo)); - } - - public HttpSearch(String uri, SearchInfo searchInfo) throws IOException { - this(URI.create(uri), searchInfo); - } - - @Override - public String getMethod() { - return DavMethods.METHOD_SEARCH; - } - - @Override - public boolean succeeded(HttpResponse response) { - int statusCode = response.getStatusLine().getStatusCode(); - return statusCode == DavServletResponse.SC_MULTI_STATUS; - } -} \ No newline at end of file Property changes on: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpSearch.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpSubscribe.java =================================================================== --- jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpSubscribe.java (revision 1907912) +++ jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpSubscribe.java (nonexistent) @@ -1,88 +0,0 @@ -/* - * 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.webdav.client.methods; - -import java.io.IOException; -import java.net.URI; - -import org.apache.http.HttpResponse; -import org.apache.jackrabbit.webdav.DavConstants; -import org.apache.jackrabbit.webdav.DavMethods; -import org.apache.jackrabbit.webdav.DavServletResponse; -import org.apache.jackrabbit.webdav.header.CodedUrlHeader; -import org.apache.jackrabbit.webdav.header.DepthHeader; -import org.apache.jackrabbit.webdav.header.TimeoutHeader; -import org.apache.jackrabbit.webdav.observation.ObservationConstants; -import org.apache.jackrabbit.webdav.observation.SubscriptionInfo; - -/** - * Represents an HTTP SUBSCRIBE request. - *

- * Note that "SUBSCRIBE" is a custom HTTP extension, not defined in a standards paper. - * @since 2.13.6 - */ -public class HttpSubscribe extends BaseDavRequest { - - public HttpSubscribe(URI uri, SubscriptionInfo info, String subscriptionId) throws IOException { - super(uri); - if (info == null) { - throw new IllegalArgumentException("SubscriptionInfo must not be null."); - } - // optional subscriptionId (only required to modify an existing - // subscription) - if (subscriptionId != null) { - CodedUrlHeader h = new CodedUrlHeader(ObservationConstants.HEADER_SUBSCRIPTIONID, subscriptionId); - super.setHeader(h.getHeaderName(), h.getHeaderValue()); - } - // optional timeout header - long to = info.getTimeOut(); - if (to != DavConstants.UNDEFINED_TIMEOUT) { - TimeoutHeader h = new TimeoutHeader(info.getTimeOut()); - super.setHeader(h.getHeaderName(), h.getHeaderValue()); - } - // always set depth header since value is boolean flag - DepthHeader dh = new DepthHeader(info.isDeep()); - super.setHeader(dh.getHeaderName(), dh.getHeaderValue()); - super.setEntity(XmlEntity.create(info)); - } - - public HttpSubscribe(String uri, SubscriptionInfo info, String subscriptionId) throws IOException { - this(URI.create(uri), info, subscriptionId); - } - - public String getSubscriptionId(HttpResponse response) { - org.apache.http.Header sbHeader = response.getFirstHeader(ObservationConstants.HEADER_SUBSCRIPTIONID); - if (sbHeader != null) { - CodedUrlHeader cuh = new CodedUrlHeader(ObservationConstants.HEADER_SUBSCRIPTIONID, sbHeader.getValue()); - return cuh.getCodedUrl(); - } - else { - return null; - } - } - - @Override - public String getMethod() { - return DavMethods.METHOD_SUBSCRIBE; - } - - @Override - public boolean succeeded(HttpResponse response) { - int statusCode = response.getStatusLine().getStatusCode(); - return statusCode == DavServletResponse.SC_OK; - } -} \ No newline at end of file Property changes on: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpSubscribe.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpUnbind.java =================================================================== --- jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpUnbind.java (revision 1907912) +++ jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpUnbind.java (nonexistent) @@ -1,54 +0,0 @@ -/* - * 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.webdav.client.methods; - -import java.io.IOException; -import java.net.URI; - -import org.apache.http.HttpResponse; -import org.apache.jackrabbit.webdav.DavMethods; -import org.apache.jackrabbit.webdav.DavServletResponse; -import org.apache.jackrabbit.webdav.bind.UnbindInfo; - -/** - * Represents an HTTP UNBIND request. - * - * @see RFC 5842, Section 5 - * @since 2.13.6 - */ -public class HttpUnbind extends BaseDavRequest { - - public HttpUnbind(URI uri, UnbindInfo info) throws IOException { - super(uri); - super.setEntity(XmlEntity.create(info)); - } - - public HttpUnbind(String uri, UnbindInfo info) throws IOException { - this(URI.create(uri), info); - } - - @Override - public String getMethod() { - return DavMethods.METHOD_UNBIND; - } - - @Override - public boolean succeeded(HttpResponse response) { - int statusCode = response.getStatusLine().getStatusCode(); - return statusCode == DavServletResponse.SC_OK || statusCode == DavServletResponse.SC_NO_CONTENT; - } -} \ No newline at end of file Property changes on: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpUnbind.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpUnlock.java =================================================================== --- jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpUnlock.java (revision 1907912) +++ jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpUnlock.java (nonexistent) @@ -1,55 +0,0 @@ -/* - * 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.webdav.client.methods; - -import java.net.URI; - -import org.apache.http.HttpResponse; -import org.apache.jackrabbit.webdav.DavConstants; -import org.apache.jackrabbit.webdav.DavMethods; -import org.apache.jackrabbit.webdav.DavServletResponse; -import org.apache.jackrabbit.webdav.header.CodedUrlHeader; - -/** - * Represents an HTTP UNLOCK request. - * - * @see RFC 4918, Section 9.11 - * @since 2.13.6 - */ -public class HttpUnlock extends BaseDavRequest { - - public HttpUnlock(URI uri, String lockToken) { - super(uri); - CodedUrlHeader lth = new CodedUrlHeader(DavConstants.HEADER_LOCK_TOKEN, lockToken); - super.setHeader(lth.getHeaderName(), lth.getHeaderValue()); - } - - public HttpUnlock(String uri, String lockToken) { - this(URI.create(uri), lockToken); - } - - @Override - public String getMethod() { - return DavMethods.METHOD_UNLOCK; - } - - @Override - public boolean succeeded(HttpResponse response) { - int statusCode = response.getStatusLine().getStatusCode(); - return statusCode == DavServletResponse.SC_OK || statusCode == DavServletResponse.SC_NO_CONTENT; - } -} \ No newline at end of file Property changes on: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpUnlock.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpUnsubscribe.java =================================================================== --- jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpUnsubscribe.java (revision 1907912) +++ jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpUnsubscribe.java (nonexistent) @@ -1,53 +0,0 @@ -/* - * 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.webdav.client.methods; - -import java.net.URI; - -import org.apache.http.HttpResponse; -import org.apache.jackrabbit.webdav.DavMethods; -import org.apache.jackrabbit.webdav.DavServletResponse; -import org.apache.jackrabbit.webdav.observation.ObservationConstants; - -/** - * Represents an HTTP UNSUBSCRIBE request. - *

- * Note that "UNSUBSCRIBE" is a custom HTTP extension, not defined in a standards paper. - * @since 2.13.6 - */ -public class HttpUnsubscribe extends BaseDavRequest { - - public HttpUnsubscribe(URI uri, String subscriptionId) { - super(uri); - super.setHeader(ObservationConstants.HEADER_SUBSCRIPTIONID, subscriptionId); - } - - public HttpUnsubscribe(String uri, String subscriptionId) { - this(URI.create(uri), subscriptionId); - } - - @Override - public String getMethod() { - return DavMethods.METHOD_UNSUBSCRIBE; - } - - @Override - public boolean succeeded(HttpResponse response) { - int statusCode = response.getStatusLine().getStatusCode(); - return statusCode == DavServletResponse.SC_NO_CONTENT; - } -} \ No newline at end of file Property changes on: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpUnsubscribe.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpUpdate.java =================================================================== --- jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpUpdate.java (revision 1907912) +++ jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpUpdate.java (nonexistent) @@ -1,54 +0,0 @@ -/* - * 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.webdav.client.methods; - -import java.io.IOException; -import java.net.URI; - -import org.apache.http.HttpResponse; -import org.apache.jackrabbit.webdav.DavMethods; -import org.apache.jackrabbit.webdav.DavServletResponse; -import org.apache.jackrabbit.webdav.version.UpdateInfo; - -/** - * Represents an HTTP UPDATE request. - * - * @see RFC 3253, Section 7.1 - * @since 2.13.6 - */ -public class HttpUpdate extends BaseDavRequest { - - public HttpUpdate(URI uri, UpdateInfo updateInfo) throws IOException { - super(uri); - super.setEntity(XmlEntity.create(updateInfo)); - } - - public HttpUpdate(String uri, UpdateInfo updateInfo) throws IOException { - this(URI.create(uri), updateInfo); - } - - @Override - public String getMethod() { - return DavMethods.METHOD_UPDATE; - } - - @Override - public boolean succeeded(HttpResponse response) { - int statusCode = response.getStatusLine().getStatusCode(); - return statusCode == DavServletResponse.SC_MULTI_STATUS; - } -} Property changes on: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpUpdate.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpVersionControl.java =================================================================== --- jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpVersionControl.java (revision 1907912) +++ jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpVersionControl.java (nonexistent) @@ -1,51 +0,0 @@ -/* - * 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.webdav.client.methods; - -import java.net.URI; - -import org.apache.http.HttpResponse; -import org.apache.jackrabbit.webdav.DavMethods; -import org.apache.jackrabbit.webdav.DavServletResponse; - -/** - * Represents an HTTP VERSION-CONTROL request. - * - * @see RFC 3253, Section 3.5 - * @since 2.13.6 - */ -public class HttpVersionControl extends BaseDavRequest { - - public HttpVersionControl(URI uri) { - super(uri); - } - - public HttpVersionControl(String uri) { - this(URI.create(uri)); - } - - @Override - public String getMethod() { - return DavMethods.METHOD_VERSION_CONTROL; - } - - @Override - public boolean succeeded(HttpResponse response) { - int statusCode = response.getStatusLine().getStatusCode(); - return statusCode == DavServletResponse.SC_OK; - } -} Property changes on: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpVersionControl.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/XmlEntity.java =================================================================== --- jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/XmlEntity.java (revision 1907912) +++ jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/XmlEntity.java (nonexistent) @@ -1,68 +0,0 @@ -/* - * 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.webdav.client.methods; - -import java.io.ByteArrayOutputStream; -import java.io.IOException; - -import javax.xml.parsers.ParserConfigurationException; -import javax.xml.transform.TransformerException; - -import org.apache.http.HttpEntity; -import org.apache.http.entity.ByteArrayEntity; -import org.apache.http.entity.ContentType; -import org.apache.jackrabbit.webdav.xml.DomUtil; -import org.apache.jackrabbit.webdav.xml.XmlSerializable; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.w3c.dom.Document; -import org.xml.sax.SAXException; - -/** - * Utility methods for creating request entities from {@link Document}s or {@link XmlSerializable}s. - */ -public class XmlEntity { - - private static Logger LOG = LoggerFactory.getLogger(XmlEntity.class); - - private static ContentType CT = ContentType.create("application/xml", "UTF-8"); - - public static HttpEntity create(Document doc) throws IOException { - try { - ByteArrayOutputStream xml = new ByteArrayOutputStream(); - DomUtil.transformDocument(doc, xml); - return new ByteArrayEntity(xml.toByteArray(), CT); - } catch (TransformerException ex) { - LOG.error(ex.getMessage()); - throw new IOException(ex); - } catch (SAXException ex) { - LOG.error(ex.getMessage()); - throw new IOException(ex); - } - } - - public static HttpEntity create(XmlSerializable payload) throws IOException { - try { - Document doc = DomUtil.createDocument(); - doc.appendChild(payload.toXml(doc)); - return create(doc); - } catch (ParserConfigurationException ex) { - LOG.error(ex.getMessage()); - throw new IOException(ex); - } - } -} Property changes on: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/XmlEntity.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/package-info.java =================================================================== --- jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/package-info.java (revision 1907912) +++ jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/package-info.java (nonexistent) @@ -1,31 +0,0 @@ -/* - * 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. - */ - -/** - * Provides classes for use with the Apache HttpClient, supporting WebDAV - * request methods. - *

- * This version also contains classes for use with the obsolete "Commons - * HttpClient"; they have been marked "deprecated" and will be removed in the - * next major release. - * - * @see JCR-2406 - * @see https://hc.apache.org/httpcomponents-client-4.5.x/ - */ -@org.osgi.annotation.versioning.Version("2.0.0") -package org.apache.jackrabbit.webdav.client.methods; Property changes on: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/package-info.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/header/CodedUrlHeader.java =================================================================== --- jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/header/CodedUrlHeader.java (revision 1907912) +++ jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/header/CodedUrlHeader.java (nonexistent) @@ -1,113 +0,0 @@ -/* - * 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.webdav.header; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import javax.servlet.http.HttpServletRequest; - -/** - * CodedUrlHeader... - */ -public class CodedUrlHeader implements Header { - - private static Logger log = LoggerFactory.getLogger(CodedUrlHeader.class); - - private final String headerName; - private final String headerValue; - - public CodedUrlHeader(String headerName, String headerValue) { - this.headerName = headerName; - if (headerValue != null && !(headerValue.startsWith("<") && headerValue.endsWith(">"))) { - headerValue = "<" + headerValue + ">"; - } - this.headerValue = headerValue; - } - - /** - * Return the name of the header - * - * @return header name - * @see Header#getHeaderName() - */ - public String getHeaderName() { - return headerName; - } - - /** - * Return the value of the header - * - * @return value - * @see Header#getHeaderValue() - */ - public String getHeaderValue() { - return headerValue; - } - - /** - * Returns the token present in the header value or null. - * If the header contained multiple tokens separated by ',' the first value - * is returned. - * - * @return token present in the CodedURL header or null if - * the header is not present. - * @see #getCodedUrls() - */ - public String getCodedUrl() { - String[] codedUrls = getCodedUrls(); - return (codedUrls != null) ? codedUrls[0] : null; - } - - /** - * Return an array of coded urls as present in the header value or null if - * no value is present. - * - * @return array of coded urls - */ - public String[] getCodedUrls() { - String[] codedUrls = null; - if (headerValue != null) { - String[] values = headerValue.split(","); - codedUrls = new String[values.length]; - for (int i = 0; i < values.length; i++) { - int p1 = values[i].indexOf('<'); - if (p1<0) { - throw new IllegalArgumentException("Invalid CodedURL header value:" + values[i]); - } - int p2 = values[i].indexOf('>', p1); - if (p2<0) { - throw new IllegalArgumentException("Invalid CodedURL header value:" + values[i]); - } - codedUrls[i] = values[i].substring(p1+1, p2); - } - } - return codedUrls; - } - - /** - * Retrieves the header with the given name and builds a new CodedUrlHeader. - * - * @param request - * @param headerName - * @return new CodedUrlHeader instance - */ - public static CodedUrlHeader parse(HttpServletRequest request, String headerName) { - String headerValue = request.getHeader(headerName); - return new CodedUrlHeader(headerName, headerValue); - } -} \ No newline at end of file Property changes on: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/header/CodedUrlHeader.java ___________________________________________________________________ Deleted: svn Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/header/DepthHeader.java =================================================================== --- jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/header/DepthHeader.java (revision 1907912) +++ jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/header/DepthHeader.java (nonexistent) @@ -1,128 +0,0 @@ -/* - * 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.webdav.header; - -import org.apache.jackrabbit.webdav.DavConstants; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import javax.servlet.http.HttpServletRequest; - -/** - * DepthHeader... - */ -public class DepthHeader implements Header, DavConstants { - - private static Logger log = LoggerFactory.getLogger(DepthHeader.class); - - private final int depth; - - /** - * Create a new DepthHeader from the given integer. - * - * @param depth - */ - public DepthHeader(int depth) { - if (depth == DEPTH_0 || depth == DEPTH_1 || depth == DEPTH_INFINITY) { - this.depth = depth; - } else { - throw new IllegalArgumentException("Invalid depth: " + depth); - } - } - - /** - * Create a new DepthHeader with either value {@link #DEPTH_0 0} - * or {@link #DEPTH_INFINITY infinity}. - * - * @param isDeep - */ - public DepthHeader(boolean isDeep) { - this.depth = (isDeep) ? DEPTH_INFINITY : DEPTH_0; - } - - /** - * @return integer representation of the depth indicated by the given header. - */ - public int getDepth() { - return depth; - } - - /** - * Return {@link DavConstants#HEADER_DEPTH Depth} - * - * @return {@link DavConstants#HEADER_DEPTH Depth} - * @see DavConstants#HEADER_DEPTH - * @see Header#getHeaderName() - */ - public String getHeaderName() { - return DavConstants.HEADER_DEPTH; - } - - /** - * Returns the header value. - * - * @return header value - * @see Header#getHeaderValue() - */ - public String getHeaderValue() { - if (depth == DavConstants.DEPTH_0 || depth == DavConstants.DEPTH_1) { - return String.valueOf(depth); - } else { - return DavConstants.DEPTH_INFINITY_S; - } - } - - /** - * Retrieve the Depth header from the given request object and parse the - * value. If no header is present or the value is empty String, the - * defaultValue is used ot build a new DepthHeader instance. - * - * @param request - * @param defaultValue - * @return a new DepthHeader instance - */ - public static DepthHeader parse(HttpServletRequest request, int defaultValue) { - String headerValue = request.getHeader(HEADER_DEPTH); - if (headerValue == null || "".equals(headerValue)) { - return new DepthHeader(defaultValue); - } else { - return new DepthHeader(depthToInt(headerValue)); - } - } - - /** - * Convert the String depth value to an integer. - * - * @param depth - * @return integer representation of the given depth String - * @throws IllegalArgumentException if the String does not represent a valid - * depth. - */ - private static int depthToInt(String depth) { - int d; - if (depth.equalsIgnoreCase(DavConstants.DEPTH_INFINITY_S)) { - d = DavConstants.DEPTH_INFINITY; - } else if (depth.equals(DavConstants.DEPTH_0+"")) { - d = DavConstants.DEPTH_0; - } else if (depth.equals(DavConstants.DEPTH_1+"")) { - d = DavConstants.DEPTH_1; - } else { - throw new IllegalArgumentException("Invalid depth value: " + depth); - } - return d; - } -} \ No newline at end of file Property changes on: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/header/DepthHeader.java ___________________________________________________________________ Deleted: svn Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/header/FieldValueParser.java =================================================================== --- jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/header/FieldValueParser.java (revision 1907912) +++ jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/header/FieldValueParser.java (nonexistent) @@ -1,55 +0,0 @@ -/* - * 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.webdav.header; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - -public class FieldValueParser { - - /** - * Tokenize lists of token and quoted-url - * @param list field value - */ - public static List tokenizeList(String list) { - - String[] split = list.split(","); - if (split.length == 1) { - return Collections.singletonList(split[0].trim()); - } else { - List result = new ArrayList(); - String inCodedUrl = null; - for (String t : split) { - String trimmed = t.trim(); - // handle quoted-url containing "," - if (trimmed.startsWith("<") && !trimmed.endsWith(">")) { - inCodedUrl = trimmed + ","; - } else if (inCodedUrl != null && trimmed.endsWith(">")) { - inCodedUrl += trimmed; - result.add(inCodedUrl); - inCodedUrl = null; - } else { - if (trimmed.length() != 0) { - result.add(trimmed); - } - } - } - return Collections.unmodifiableList(result); - } - } -} Property changes on: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/header/FieldValueParser.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/header/Header.java =================================================================== --- jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/header/Header.java (revision 1907912) +++ jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/header/Header.java (nonexistent) @@ -1,27 +0,0 @@ -/* - * 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.webdav.header; - -/** - * Header... - */ -public interface Header { - - public String getHeaderName(); - - public String getHeaderValue(); -} \ No newline at end of file Property changes on: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/header/Header.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Deleted: svn:keywords ## -1 +0,0 ## -author date id revision url \ No newline at end of property Index: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/header/IfHeader.java =================================================================== --- jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/header/IfHeader.java (revision 1907912) +++ jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/header/IfHeader.java (nonexistent) @@ -1,888 +0,0 @@ -/* - * 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.webdav.header; - -import org.apache.jackrabbit.webdav.DavConstants; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import javax.servlet.http.HttpServletRequest; -import java.io.IOException; -import java.io.Reader; -import java.io.StringReader; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; - -/** - * The IfHeader class represents the state lists defined - * through the HTTP If header, which is specified in RFC 2518 as - * follows : - *

-     If = "If" ":" ( 1*No-tag-list | 1*Tagged-list)
-     No-tag-list = List
-     Tagged-list = Resource 1*List
-     Resource = Coded-URL
-     List = "(" 1*(["Not"](State-etag | "[" entity-tag "]")) ")"
-     State-etag = Coded-URL
-     Coded-URL = "<" absoluteURI ">"
- * 
- *

- * Reformulating this specification into proper EBNF as specified by N. Wirth - * we get the following productions, which map to the parse METHODS of this - * class. Any whitespace is ignored except for white space surrounding and - * within words which is considered significant. - *

-     If = "If:" ( Tagged | Untagged ).
-     Tagged = { "<" Word ">" Untagged } .
-     Untagged = { "(" IfList ")" } .
-     IfList = { [ "Not" ] ( ("<" Word ">" ) | ( "[" Word "]" ) ) } .
-     Word = characters .
- * 
- *

- * An If header either contains untagged IfList entries or - * tagged IfList entries but not a mixture of both. An If - * header containing tagged entries is said to be of tagged type while - * an If header containing untagged entries is said to be of - * untagged type. - *

- * An IfList is a list of tokens - words enclosed in < > - * - and etags - words enclosed in [ ]. An IfList matches a - * (token, etag) tuple if all entries in the list match. If an entry in the list - * is prefixed with the word Not (parsed case insensitively) the entry - * must not match the concrete token or etag. - *

- * Example: The ifList (<token> [etag]) only matches - * if the concret token has the value token and the conrete etag - * has the value etag. On the other hand, the ifList - * (Not <notoken>) matches any token which is not - * notoken (in this case the concrete value of the etag is - * not taken into consideration). - * - * @author Felix Meschberger - */ -public class IfHeader implements Header { - - /** - * default logger - */ - private static final Logger log = LoggerFactory.getLogger(IfHeader.class); - - /** - * The string representation of the header value - */ - private final String headerValue; - - /** - * The list of untagged state entries - */ - private final IfHeaderInterface ifHeader; - - /** - * The list of all positive tokens present in the If header. - */ - private List allTokens = new ArrayList(); - /** - * The list of all NOT tokens present in the If header. - */ - private List allNotTokens = new ArrayList(); - - /** - * Create a Untagged IfHeader if the given lock tokens. - * - * @param tokens - */ - public IfHeader(String[] tokens) { - allTokens.addAll(Arrays.asList(tokens)); - StringBuffer b = new StringBuffer(); - for (String token : tokens) { - b.append("(").append("<"); - b.append(token); - b.append(">").append(")"); - } - headerValue = b.toString(); - ifHeader = parse(); - } - - /** - * Parses the If header and creates and internal representation - * which is easy to query. - * - * @param req The request object - */ - public IfHeader(HttpServletRequest req) { - headerValue = req.getHeader(DavConstants.HEADER_IF); - ifHeader = parse(); - } - - /** - * Return {@link DavConstants#HEADER_IF If} - * - * @return {@link DavConstants#HEADER_IF If} - * @see DavConstants#HEADER_IF - */ - public String getHeaderName() { - return DavConstants.HEADER_IF; - } - - /** - * Return the String representation of the If header present on - * the given request or null. - * - * @return If header value as String or null. - */ - public String getHeaderValue() { - return headerValue; - } - - /** - * Returns true if an If header was present in the given request. False otherwise. - * - * @return true if an If header was present. - */ - public boolean hasValue() { - return ifHeader != null; - } - - /** - * Tries to match the contents of the If header with the given - * token and etag values with the restriction to only check for the tag. - *

- * If the If header is of untagged type, the untagged IfList - * is matched against the token and etag given: A match of the token and - * etag is found if at least one of the IfList entries match the - * token and etag tuple. - * - * @param tag The tag to identify the IfList to match the token - * and etag against. - * @param token The token to compare. - * @param etag The ETag value to compare. - * - * @return If the If header is of untagged type the result is - * true if any of the IfList entries matches - * the token and etag values. For tagged type If header the - * result is true if either no entry for the given tag - * exists in the If header or if the IfList for the - * given tag matches the token and etag given. - */ - public boolean matches(String tag, String token, String etag) { - if (ifHeader == null) { - log.debug("matches: No If header, assume match"); - return true; - } else { - return ifHeader.matches(tag, token, etag); - } - } - - /** - * @return an iterator over all tokens present in the if header, that were - * not denied by a leading NOT statement. - */ - public Iterator getAllTokens() { - return allTokens.iterator(); - } - - /** - * @return an iterator over all NOT tokens present in the if header, that - * were explicitly denied. - */ - public Iterator getAllNotTokens() { - return allNotTokens.iterator(); - } - - /** - * Parse the original header value and build the internal IfHeaderInterface - * object that is easy to query. - */ - private IfHeaderInterface parse() { - IfHeaderInterface ifHeader; - if (headerValue != null && headerValue.length() > 0) { - StringReader reader = null; - int firstChar = 0; - - try { - reader = new StringReader(headerValue); - // get the first character to decide - expect '(' or '<' - try { - reader.mark(1); - firstChar = readWhiteSpace(reader); - reader.reset(); - } catch (IOException ignore) { - // may be thrown according to API but is only thrown by the - // StringReader class if the reader is already closed. - } - - if (firstChar == '(') { - ifHeader = parseUntagged(reader); - } else if (firstChar == '<') { - ifHeader = parseTagged(reader); - } else { - logIllegalState("If", firstChar, "(<", null); - ifHeader = null; - } - - } finally { - if (reader != null) { - reader.close(); - } - } - - } else { - log.debug("IfHeader: No If header in request"); - ifHeader = null; - } - return ifHeader; - } - - //---------- internal IF header parser ------------------------------------- - /** - * Parses a tagged type If header. This method implements the - * Tagged production given in the class comment : - *

-         Tagged = { "<" Word ">" Untagged } .
-     * 
- * - * @param reader - * @return - */ - private IfHeaderMap parseTagged(StringReader reader) { - IfHeaderMap map = new IfHeaderMap(); - try { - while (true) { - // read next non-white space - int c = readWhiteSpace(reader); - if (c < 0) { - // end of input, no more entries - break; - } else if (c == '<') { - // start a tag with an IfList - String resource = readWord(reader, '>'); - if (resource != null) { - // go to untagged after reading the resource - map.put(resource, parseUntagged(reader)); - } else { - break; - } - } else { - // unexpected character - // catchup to end of input or start of a tag - logIllegalState("Tagged", c, "<", reader); - } - } - } catch (IOException ioe) { - log.error("parseTagged: Problem parsing If header: "+ioe.toString()); - } - - return map; - } - - /** - * Parses an untagged type If header. This method implements the - * Untagged production given in the class comment : - *
-         Untagged = { "(" IfList ")" } .
-     * 
- * - * @param reader The StringReader to read from for parsing - * - * @return An ArrayList of {@link IfList} entries. - */ - private IfHeaderList parseUntagged(StringReader reader) { - IfHeaderList list = new IfHeaderList(); - try { - while (true) { - // read next non white space - reader.mark(1); - int c = readWhiteSpace(reader); - if (c < 0) { - // end of input, no more IfLists - break; - - } else if (c == '(') { - // start of an IfList, parse - list.add(parseIfList(reader)); - - } else if (c == '<') { - // start of a tag, return current list - reader.reset(); - break; - - } else { - // unexpected character - // catchup to end of input or start of an IfList - logIllegalState("Untagged", c, "(", reader); - } - } - } catch (IOException ioe) { - log.error("parseUntagged: Problem parsing If header: "+ioe.toString()); - } - return list; - } - - /** - * Parses an IfList in the If header. This method - * implements the Tagged production given in the class comment : - *
-         IfList = { [ "Not" ] ( ("<" Word ">" ) | ( "[" Word "]" ) ) } .
-     * 
- * - * @param reader The StringReader to read from for parsing - * - * @return The {@link IfList} for the input IfList. - * - * @throws IOException if a problem occurs during reading. - */ - private IfList parseIfList(StringReader reader) throws IOException { - IfList res = new IfList(); - boolean positive = true; - String word; - - ReadLoop: - while (true) { - int nextChar = readWhiteSpace(reader); - switch (nextChar) { - case 'N': - case 'n': - // read not - - // check whether o or O - int not = reader.read(); - if (not != 'o' && not != 'O') { - logIllegalState("IfList-Not", not, "o", null); - break; - } - - // check whether t or T - not = reader.read(); - if (not !='t' && not != 'T') { - logIllegalState("IfList-Not", not, "t", null); - break; - } - - // read Not ok - positive = false; - break; - - case '<': - // state token - word = readWord(reader, '>'); - if (word != null) { - res.add(new IfListEntryToken(word, positive)); - // also add the token to the list of all tokens - if (positive) { - allTokens.add(word); - } else { - allNotTokens.add(word); - } - positive = true; - } - break; - - case '[': - // etag - word = readWord(reader, ']'); - if (word != null) { - res.add(new IfListEntryEtag(word, positive)); - positive = true; - } - break; - - case ')': - // correct end of list, end the loop - log.debug("parseIfList: End of If list, terminating loop"); - break ReadLoop; - - default: - logIllegalState("IfList", nextChar, "nN<[)", reader); - - // abort loop if EOF - if (nextChar < 0) { - break ReadLoop; - } - - break; - } - } - - // return the current list anyway - return res; - } - - /** - * Returns the first non-whitespace character from the reader or -1 if - * the end of the reader is encountered. - * - * @param reader The Reader to read from - * - * @return The first non-whitespace character or -1 in case of EOF. - * - * @throws IOException if a problem occurs during reading. - */ - private int readWhiteSpace(Reader reader) throws IOException { - int c = reader.read(); - while (c >= 0 && Character.isWhitespace((char) c)) { - c = reader.read(); - } - return c; - } - - /** - * Reads from the input until the end character is encountered and returns - * the string up to but not including this end character. If the end of input - * is reached before reading the end character null is - * returned. - *

- * Note that this method does not support any escaping. - * - * @param reader The Reader to read from - * @param end The ending character limiting the word. - * - * @return The string read up to but not including the ending character or - * null if the end of input is reached before the ending - * character has been read. - * - * @throws IOException if a problem occurs during reading. - */ - private String readWord(Reader reader, char end) throws IOException { - StringBuffer buf = new StringBuffer(); - - // read the word value - int c = reader.read(); - for (; c >= 0 && c != end; c=reader.read()) { - buf.append((char) c); - } - - // check whether we succeeded - if (c < 0) { - log.error("readWord: Unexpected end of input reading word"); - return null; - } - - // build the string and return it - return buf.toString(); - } - - /** - * Logs an unexpected character with the corresponding state and list of - * expected characters. If the reader parameter is not null, characters - * are read until either the end of the input is reached or any of the - * characters in the expChar string is read. - * - * @param state The name of the current parse state. This method logs this - * name in the message. The intended value would probably be the - * name of the EBNF production during which the error occurs. - * @param effChar The effective character read. - * @param expChar The list of characters acceptable in the current state. - * @param reader The reader to be caught up to any of the expected - * characters. If null the input is not caught up to - * any of the expected characters (of course ;-). - */ - private void logIllegalState(String state, int effChar, String expChar, - StringReader reader) { - - // format the effective character to be logged - String effString = (effChar < 0) ? "" : String.valueOf((char) effChar); - - // log the error - log.error("logIllegalState: Unexpected character '"+effString+"' in state "+state+", expected any of "+expChar); - - // catch up if a reader is given - if (reader != null && effChar >= 0) { - try { - log.debug("logIllegalState: Catch up to any of "+expChar); - do { - reader.mark(1); - effChar = reader.read(); - } while (effChar >= 0 && expChar.indexOf(effChar) < 0); - if (effChar >= 0) { - reader.reset(); - } - } catch (IOException ioe) { - log.error("logIllegalState: IO Problem catching up to any of "+expChar); - } - } - } - - //---------- internal If header structure ---------------------------------- - - /** - * The IfListEntry abstract class is the base class for - * entries in an IfList production. This abstract base class - * provides common functionality to both types of entries, namely tokens - * enclosed in angle brackets (< >) and etags enclosed - * in square brackets ([ ]). - */ - private static abstract class IfListEntry { - - /** - * The entry string value - the semantics of this value depends on the - * implementing class. - */ - protected final String value; - - /** Flag to indicate, whether this is a positive match or not */ - protected final boolean positive; - - /** The cached result of the {@link #toString} method. */ - protected String stringValue; - - /** - * Sets up the final fields of this abstract class. The meaning of - * value parameter depends solely on the implementing class. From the - * point of view of this abstract class, it is simply a string value. - * - * @param value The string value of this instance - * @param positive true if matches are positive - */ - protected IfListEntry(String value, boolean positive) { - this.value = value; - this.positive = positive; - } - - /** - * Matches the value from the parameter to the internal string value. - * If the parameter and the {@link #value} field match, the method - * returns true for positive matches and false - * for negative matches. - *

- * This helper method can be called by implementations to evaluate the - * concrete match on the correct value parameter. See - * {@link #match(String, String)} for the external API method. - * - * @param value The string value to compare to the {@link #value} - * field. - * - * @return true if the value parameter and the - * {@link #value} field match and the {@link #positive} field is - * true or if the values do not match and the - * {@link #positive} field is false. - */ - protected boolean match(String value) { - return positive == this.value.equals(value); - } - - /** - * Matches the entry's value to the the token or etag. Depending on the - * concrete implementation, only one of the parameters may be evaluated - * while the other may be ignored. - *

- * Implementing METHODS may call the helper method {@link #match(String)} - * for the actual matching. - * - * @param token The token value to compare - * @param etag The etag value to compare - * - * @return true if the token/etag matches the IfList - * entry. - */ - public abstract boolean match(String token, String etag); - - /** - * Returns a short type name for the implementation. This method is - * used by the {@link #toString} method to build the string representation - * if the instance. - * - * @return The type name of the implementation. - */ - protected abstract String getType(); - - /** - * Returns the value of this entry. - * - * @return the value - */ - protected String getValue() { - return value; - } - - /** - * Returns the String representation of this entry. This method uses the - * {@link #getType} to build the string representation. - * - * @return the String representation of this entry. - */ - @Override - public String toString() { - if (stringValue == null) { - stringValue = getType() + ": " + (positive?"":"!") + value; - } - return stringValue; - } - } - - /** - * The IfListEntryToken extends the {@link IfListEntry} - * abstract class to represent an entry for token matching. - */ - private static class IfListEntryToken extends IfListEntry { - - /** - * Creates a token matching entry. - * - * @param token The token value pertinent to this instance. - * @param positive true if this is a positive match entry. - */ - IfListEntryToken(String token, boolean positive) { - super(token, positive); - } - - /** - * Matches the token parameter to the stored token value and returns - * true if the values match and if the match is positive. - * true is also returned for negative matches if the values - * do not match. - * - * @param token The token value to compare - * @param etag The etag value to compare, which is ignored in this - * implementation. - * - * @return true if the token matches the IfList - * entry's token value. - */ - @Override - public boolean match(String token, String etag) { - return super.match(token); - } - - /** - * Returns the type name of this implementation, which is fixed to - * be Token. - * - * @return The fixed string Token as the type name. - */ - @Override - protected String getType() { - return "Token"; - } - } - - /** - * The IfListEntryToken extends the {@link IfListEntry} - * abstract class to represent an entry for etag matching. - */ - private static class IfListEntryEtag extends IfListEntry { - - /** - * Creates an etag matching entry. - * - * @param etag The etag value pertinent to this instance. - * @param positive true if this is a positive match entry. - */ - IfListEntryEtag(String etag, boolean positive) { - super(etag, positive); - } - - /** - * Matches the etag parameter to the stored etag value and returns - * true if the values match and if the match is positive. - * true is also returned for negative matches if the values - * do not match. - * - * @param token The token value to compare, which is ignored in this - * implementation. - * @param etag The etag value to compare - * - * @return true if the etag matches the IfList - * entry's etag value. - */ - @Override - public boolean match(String token, String etag) { - return super.match(etag); - } - - /** - * Returns the type name of this implementation, which is fixed to - * be ETag. - * - * @return The fixed string ETag as the type name. - */ - @Override - protected String getType() { - return "ETag"; - } - } - - /** - * The IfList class extends the ArrayList class - * with the limitation to only support adding {@link IfListEntry} objects - * and adding a {@link #match} method. - *

- * This class is a container for data contained in the If - * production IfList - *

-         IfList = { [ "Not" ] ( ("<" Word ">" ) | ( "[" Word "]" ) ) } .
-     * 
- *

- */ - private static class IfList extends ArrayList { - - /** - * Adds the {@link IfListEntry} at the end of the list. - * - * @param entry The {@link IfListEntry} to add to the list - * - * @return true (as per the general contract of Collection.add). - */ - @Override - public boolean add(IfListEntry entry) { - return super.add(entry); - } - - /** - * Adds the {@link IfListEntry} at the indicated position of the list. - * - * @param index - * @param entry - * - * @throws IndexOutOfBoundsException if index is out of range - * (index < 0 || index > size()). - */ - @Override - public void add(int index, IfListEntry entry) { - super.add(index, entry); - } - - /** - * Returns true if all {@link IfListEntry} objects in the - * list match the given token and etag. If the list is entry, it is - * considered to match the token and etag. - * - * @param token The token to compare. - * @param etag The etag to compare. - * - * @return true if all entries in the list match the - * given tag and token. - */ - public boolean match(String token, String etag) { - log.debug("match: Trying to match token="+token+", etag="+etag); - for (int i=0; i < size(); i++) { - IfListEntry ile = get(i); - if (!ile.match(token, etag)) { - log.debug("match: Entry "+i+"-"+ile+" does not match"); - return false; - } - } - // invariant: all entries matched - - return true; - } - } - - /** - * The IfHeaderInterface interface abstracts away the difference of - * tagged and untagged If header lists. The single method provided - * by this interface is to check whether a request may be applied to a - * resource with given token and etag. - */ - private static interface IfHeaderInterface { - - /** - * Matches the resource, token, and etag against this - * IfHeaderInterface instance. - * - * @param resource The resource to match this instance against. This - * must be absolute URI of the resource as defined in Section 3 - * (URI Syntactic Components) of RFC 2396 Uniform Resource - * Identifiers (URI): Generic Syntax. - * @param token The resource's lock token to match - * @param etag The resource's etag to match - * - * @return true if the header matches the resource with - * token and etag, which means that the request is applicable - * to the resource according to the If header. - */ - public boolean matches(String resource, String token, String etag); - } - - /** - * The IfHeaderList class implements the {@link IfHeaderInterface} - * interface to support untagged lists of {@link IfList}s. This class - * implements the data container for the production : - *

-         Untagged = { "(" IfList ")" } .
-     * 
- */ - private static class IfHeaderList extends ArrayList implements IfHeaderInterface { - - /** - * Matches a list of {@link IfList}s against the token and etag. If any of - * the {@link IfList}s matches, the method returns true. - * On the other hand false is only returned if non of the - * {@link IfList}s match. - * - * @param resource The resource to match, which is ignored by this - * implementation. A value of null is therefor - * acceptable. - * @param token The token to compare. - * @param etag The ETag value to compare. - * - * @return True if any of the {@link IfList}s matches the token - * and etag, else false is returned. - */ - public boolean matches(String resource, String token, String etag) { - log.debug("matches: Trying to match token="+token+", etag="+etag); - - for (IfList il : this) { - if (il.match(token, etag)) { - log.debug("matches: Found match with " + il); - return true; - } - } - // invariant: no match found - - return false; - } - } - - /** - * The IfHeaderMap class implements the {@link IfHeaderInterface} - * interface to support tagged lists of {@link IfList}s. This class - * implements the data container for the production : - *
-         Tagged = { "<" Word ">" "(" IfList ")" } .
-     * 
- */ - private static class IfHeaderMap extends HashMap implements IfHeaderInterface { - - /** - * Matches the token and etag for the given resource. If the resource is - * not mentioned in the header, a match is assumed and true - * is returned in this case. - * - * @param resource The absolute URI of the resource for which to find - * a match. - * @param token The token to compare. - * @param etag The etag to compare. - * - * @return true if either no entry exists for the resource - * or if the entry for the resource matches the token and etag. - */ - public boolean matches(String resource, String token, String etag) { - log.debug("matches: Trying to match resource="+resource+", token="+token+","+etag); - - IfHeaderList list = get(resource); - if (list == null) { - log.debug("matches: No entry for tag "+resource+", assuming match"); - return true; - } else { - return list.matches(resource, token, etag); - } - } - } -} Property changes on: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/header/IfHeader.java ___________________________________________________________________ Deleted: svn Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/header/LabelHeader.java =================================================================== --- jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/header/LabelHeader.java (revision 1907912) +++ jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/header/LabelHeader.java (nonexistent) @@ -1,61 +0,0 @@ -/* - * 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.webdav.header; - -import org.apache.jackrabbit.webdav.WebdavRequest; -import org.apache.jackrabbit.webdav.util.EncodeUtil; -import org.apache.jackrabbit.webdav.version.DeltaVConstants; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * LabelHeader... - */ -public class LabelHeader implements Header { - - private static Logger log = LoggerFactory.getLogger(LabelHeader.class); - - private final String label; - - public LabelHeader(String label) { - if (label == null) { - throw new IllegalArgumentException("null is not a valid label."); - } - this.label = label; - } - - public String getLabel() { - return label; - } - - public String getHeaderName() { - return DeltaVConstants.HEADER_LABEL; - } - - public String getHeaderValue() { - return EncodeUtil.escape(label); - } - - public static LabelHeader parse(WebdavRequest request) { - String hv = request.getHeader(DeltaVConstants.HEADER_LABEL); - if (hv == null) { - return null; - } else { - return new LabelHeader(EncodeUtil.unescape(hv)); - } - } -} \ No newline at end of file Property changes on: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/header/LabelHeader.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Deleted: svn:keywords ## -1 +0,0 ## -author date id revision url \ No newline at end of property Index: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/header/OverwriteHeader.java =================================================================== --- jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/header/OverwriteHeader.java (revision 1907912) +++ jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/header/OverwriteHeader.java (nonexistent) @@ -1,75 +0,0 @@ -/* - * 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.webdav.header; - -import org.apache.jackrabbit.webdav.DavConstants; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import javax.servlet.http.HttpServletRequest; - -/** - * OverwriteHeader... - */ -public class OverwriteHeader implements Header { - - private static Logger log = LoggerFactory.getLogger(OverwriteHeader.class); - - public static final String OVERWRITE_TRUE = "T"; - public static final String OVERWRITE_FALSE = "F"; - - /** - * Set 'doOverwrite' to true by default. See RFC 2518: - * "If the overwrite header is not included in a COPY or MOVE request then - * the resource MUST treat the request as if it has an overwrite header of - * value {@link #OVERWRITE_TRUE}". - */ - private final boolean doOverwrite; - - public OverwriteHeader(boolean doOverwrite) { - this.doOverwrite = doOverwrite; - } - - /** - * Create a new OverwriteHeader for the given request object. - * If the latter does not contain an "Overwrite" header field, the default - * applies, which is {@link #OVERWRITE_TRUE} according to RFC 2518. - * - * @param request - */ - public OverwriteHeader(HttpServletRequest request) { - String overwriteHeader = request.getHeader(DavConstants.HEADER_OVERWRITE); - if (overwriteHeader != null) { - doOverwrite = overwriteHeader.equalsIgnoreCase(OVERWRITE_TRUE); - } else { - // no Overwrite header -> default is 'true' - doOverwrite = true; - } - } - - public String getHeaderName() { - return DavConstants.HEADER_OVERWRITE; - } - - public String getHeaderValue() { - return (doOverwrite) ? OVERWRITE_TRUE : OVERWRITE_FALSE; - } - - public boolean isOverwrite() { - return doOverwrite; - } -} \ No newline at end of file Property changes on: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/header/OverwriteHeader.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Deleted: svn:keywords ## -1 +0,0 ## -author date id revision url \ No newline at end of property Index: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/header/PollTimeoutHeader.java =================================================================== --- jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/header/PollTimeoutHeader.java (revision 1907912) +++ jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/header/PollTimeoutHeader.java (nonexistent) @@ -1,52 +0,0 @@ -/* - * 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.webdav.header; - -import org.apache.jackrabbit.webdav.observation.ObservationConstants; - -import javax.servlet.http.HttpServletRequest; - -/** - * PollTimeoutHeader implements a timeout header for subscription - * polling. - */ -public class PollTimeoutHeader extends TimeoutHeader { - - public PollTimeoutHeader(long timeout) { - super(timeout); - } - - @Override - public String getHeaderName() { - return ObservationConstants.HEADER_POLL_TIMEOUT; - } - - /** - * Parses the request timeout header and converts it into a new - * PollTimeoutHeader object.
The default value is used as - * fallback if the String is not parseable. - * - * @param request - * @param defaultValue - * @return a new PollTimeoutHeader object. - */ - public static PollTimeoutHeader parseHeader(HttpServletRequest request, long defaultValue) { - String timeoutStr = request.getHeader(ObservationConstants.HEADER_POLL_TIMEOUT); - long timeout = parse(timeoutStr, defaultValue); - return new PollTimeoutHeader(timeout); - } -} Property changes on: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/header/PollTimeoutHeader.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/header/TimeoutHeader.java =================================================================== --- jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/header/TimeoutHeader.java (revision 1907912) +++ jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/header/TimeoutHeader.java (nonexistent) @@ -1,104 +0,0 @@ -/* - * 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.webdav.header; - -import org.apache.jackrabbit.webdav.DavConstants; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import javax.servlet.http.HttpServletRequest; - -/** - * TimeoutHeader... - */ -public class TimeoutHeader implements Header, DavConstants { - - private static Logger log = LoggerFactory.getLogger(TimeoutHeader.class); - - private final long timeout; - - public TimeoutHeader(long timeout) { - this.timeout = timeout; - } - - public String getHeaderName() { - return DavConstants.HEADER_TIMEOUT; - } - - public String getHeaderValue() { - if (timeout == INFINITE_TIMEOUT) { - return TIMEOUT_INFINITE; - } else { - return "Second-" + (timeout / 1000); - } - } - - public long getTimeout() { - return timeout; - } - - /** - * Parses the request timeout header and converts it into a new - * TimeoutHeader object.
The default value is used as - * fallback if the String is not parseable. - * - * @param request - * @param defaultValue - * @return a new TimeoutHeader object. - */ - public static TimeoutHeader parse(HttpServletRequest request, long defaultValue) { - String timeoutStr = request.getHeader(HEADER_TIMEOUT); - long timeout = parse(timeoutStr, defaultValue); - return new TimeoutHeader(timeout); - } - - /** - * Parses the given timeout String and converts the timeout value - * into a long indicating the number of milliseconds until expiration time - * is reached.
- * NOTE: If the timeout String equals to {@link #TIMEOUT_INFINITE 'infinite'} - * {@link Integer#MAX_VALUE} is returned. If the Sting is invalid or is in an - * invalid format that cannot be parsed, the default value is returned. - * - * @param timeoutStr - * @param defaultValue - * @return long representing the timeout present in the header or the default - * value if the header is missing or could not be parsed. - */ - public static long parse(String timeoutStr, long defaultValue) { - long timeout = defaultValue; - if (timeoutStr != null && timeoutStr.length() > 0) { - int secondsInd = timeoutStr.indexOf("Second-"); - if (secondsInd >= 0) { - secondsInd += 7; // read over "Second-" - int i = secondsInd; - while (i < timeoutStr.length() && Character.isDigit(timeoutStr.charAt(i))) { - i++; - } - try { - timeout = 1000L * Long.parseLong(timeoutStr.substring(secondsInd, i)); - } catch (NumberFormatException ignore) { - // ignore and return 'undefined' timeout - log.error("Invalid timeout format: " + timeoutStr); - } - } else if (timeoutStr.equalsIgnoreCase(TIMEOUT_INFINITE)) { - timeout = INFINITE_TIMEOUT; - } - } - return timeout; - } -} \ No newline at end of file Property changes on: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/header/TimeoutHeader.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Deleted: svn:keywords ## -1 +0,0 ## -author date id revision url \ No newline at end of property Index: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/header/package-info.java =================================================================== --- jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/header/package-info.java (revision 1907912) +++ jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/header/package-info.java (nonexistent) @@ -1,18 +0,0 @@ -/* - * 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. - */ -@org.osgi.annotation.versioning.Version("1.1.0") -package org.apache.jackrabbit.webdav.header; Property changes on: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/header/package-info.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/io/InputContext.java =================================================================== --- jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/io/InputContext.java (revision 1907912) +++ jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/io/InputContext.java (nonexistent) @@ -1,78 +0,0 @@ -/* - * 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.webdav.io; - -import java.io.InputStream; - -/** - * InputContext... - */ -public interface InputContext { - - /** - * Return true, if there are any data to be imported (and not only properties) - * - * @return - */ - public boolean hasStream(); - - /** - * Returns the input stream of the resource to import. - * - * @return the input stream. - */ - 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 -1 if the contentlength could not be - * determined. - * - * @return the content length - */ - public long getContentLength(); - - /** - * Return the content type or null - * - * @return - */ - public String getContentType(); - - /** - * Returns the value of the given property or null if this property does - * not exist. - * - * @param propertyName - * @return String property value or null - */ - public String getProperty(String propertyName); -} Property changes on: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/io/InputContext.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Deleted: svn:keywords ## -1 +0,0 ## -author date id revision \ No newline at end of property Index: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/io/InputContextImpl.java =================================================================== --- jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/io/InputContextImpl.java (revision 1907912) +++ jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/io/InputContextImpl.java (nonexistent) @@ -1,98 +0,0 @@ -/* - * 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.webdav.io; - -import org.apache.jackrabbit.webdav.DavConstants; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import javax.servlet.http.HttpServletRequest; -import java.io.InputStream; -import java.util.Date; - -/** - * InputContextImpl class encapsulates the InputStream - * and some header values as present in the POST, PUT or MKCOL request. - */ -public class InputContextImpl implements InputContext { - - private static Logger log = LoggerFactory.getLogger(InputContextImpl.class); - - private final HttpServletRequest request; - private final InputStream in; - - public InputContextImpl(HttpServletRequest request, InputStream in) { - if (request == null) { - throw new IllegalArgumentException("DavResource and Request must not be null."); - } - - this.request = request; - this.in = in; - } - - public boolean hasStream() { - return in != null; - } - - /** - * Returns the input stream of the resource to import. - * - * @return the input stream. - */ - public InputStream getInputStream() { - return in; - } - - public long getModificationTime() { - return new Date().getTime(); - } - - /** - * Returns the content language or null. - * - * @return contentLanguage - */ - public String getContentLanguage() { - return request.getHeader(DavConstants.HEADER_CONTENT_LANGUAGE); - } - - /** - * @return content length or -1 when unknown - */ - public long getContentLength() { - String length = request.getHeader(DavConstants.HEADER_CONTENT_LENGTH); - if (length == null) { - // header not present - return -1; - } else { - try { - return Long.parseLong(length); - } catch (NumberFormatException ex) { - log.error("broken Content-Length header: " + length); - return -1; - } - } - } - - public String getContentType() { - return request.getHeader(DavConstants.HEADER_CONTENT_TYPE); - } - - public String getProperty(String propertyName) { - return request.getHeader(propertyName); - } -} Property changes on: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/io/InputContextImpl.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Deleted: svn:keywords ## -1 +0,0 ## -author date id revision url \ No newline at end of property Index: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/io/OutputContext.java =================================================================== --- jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/io/OutputContext.java (revision 1907912) +++ jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/io/OutputContext.java (nonexistent) @@ -1,82 +0,0 @@ -/* - * 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.webdav.io; - -import java.io.OutputStream; - -/** - * OutputContext... - */ -public interface OutputContext { - - /** - * Return true if the given export context can provide an output stream - */ - public boolean hasStream(); - - /** - * Return the output stream to be used for the export or null - * - * @return - */ - public OutputStream getOutputStream(); - - /** - * Sets the content language. - * - * @param contentLanguage - */ - public void setContentLanguage(String contentLanguage); - - /** - * Sets the length of the data. - * - * @param contentLength the content length - */ - public void setContentLength(long contentLength); - - /** - * Set the content type for the resource content - * - * @param contentType - */ - public void setContentType(String contentType); - - /** - * 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); - - /** - * Allows to set additional properties that are not covered by an extra setter - * method. - * - * @param propertyName - * @param propertyValue - */ - public void setProperty(String propertyName, String propertyValue); -} Property changes on: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/io/OutputContext.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Deleted: svn:keywords ## -1 +0,0 ## -author date id revision url \ No newline at end of property Index: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/io/OutputContextImpl.java =================================================================== --- jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/io/OutputContextImpl.java (revision 1907912) +++ jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/io/OutputContextImpl.java (nonexistent) @@ -1,88 +0,0 @@ -/* - * 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.webdav.io; - -import org.apache.jackrabbit.webdav.DavConstants; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import javax.servlet.http.HttpServletResponse; -import java.io.OutputStream; - -/** - * OutputContextImpl... - */ -public class OutputContextImpl implements OutputContext { - - private static Logger log = LoggerFactory.getLogger(OutputContextImpl.class); - - private final HttpServletResponse response; - private final OutputStream out; - - public OutputContextImpl(HttpServletResponse response, OutputStream out) { - if (response == null) { - throw new IllegalArgumentException("Response must not be null."); - } - - this.response = response; - this.out = out; - } - - public boolean hasStream() { - return out != null; - } - - public OutputStream getOutputStream() { - return out; - } - - public void setContentLanguage(String contentLanguage) { - if (contentLanguage != null) { - response.setHeader(DavConstants.HEADER_CONTENT_LANGUAGE, contentLanguage); - } - } - - public void setContentLength(long contentLength) { - if (contentLength >= 0) { - response.setContentLengthLong(contentLength); - } // else: negative content length -> ignore. - } - - public void setContentType(String contentType) { - if (contentType != null) { - response.setContentType(contentType); - } - } - - public void setModificationTime(long modificationTime) { - if (modificationTime >= 0) { - response.addDateHeader(DavConstants.HEADER_LAST_MODIFIED, modificationTime); - } - } - - public void setETag(String etag) { - if (etag != null) { - response.setHeader(DavConstants.HEADER_ETAG, etag); - } - } - - public void setProperty(String propertyName, String propertyValue) { - if (propertyName != null && propertyValue != null) { - response.setHeader(propertyName, propertyValue); - } - } -} \ No newline at end of file Property changes on: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/io/OutputContextImpl.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Deleted: svn:keywords ## -1 +0,0 ## -author date id revision url \ No newline at end of property Index: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/io/package-info.java =================================================================== --- jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/io/package-info.java (revision 1907912) +++ jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/io/package-info.java (nonexistent) @@ -1,18 +0,0 @@ -/* - * 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. - */ -@org.osgi.annotation.versioning.Version("1.0.1") -package org.apache.jackrabbit.webdav.io; Property changes on: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/io/package-info.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/lock/AbstractActiveLock.java =================================================================== --- jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/lock/AbstractActiveLock.java (revision 1907912) +++ jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/lock/AbstractActiveLock.java (nonexistent) @@ -1,86 +0,0 @@ -/* - * 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.webdav.lock; - -import org.apache.jackrabbit.webdav.DavConstants; -import org.apache.jackrabbit.webdav.xml.DomUtil; -import org.w3c.dom.Document; -import org.w3c.dom.Element; - -/** - * AbstractActiveLock... - */ -public abstract class AbstractActiveLock implements ActiveLock, DavConstants { - - private String lockroot; - - /** - * @see ActiveLock#getLockroot() - */ - public String getLockroot() { - return lockroot; - } - - /** - * @see ActiveLock#setLockroot(String) - */ - public void setLockroot(String lockroot) { - this.lockroot = lockroot; - } - - /** - * Returns the default Xml representation of the 'activelock' element - * as defined by RFC 4918. - * - * @return Xml representation - * @param document - */ - public Element toXml(Document document) { - Element activeLock = DomUtil.createElement(document, XML_ACTIVELOCK, NAMESPACE); - - // lockscope property - activeLock.appendChild(getScope().toXml(document)); - // locktype property - activeLock.appendChild(getType().toXml(document)); - // depth - activeLock.appendChild(DomUtil.depthToXml(isDeep(), document)); - // timeout - long timeout = getTimeout(); - if (!isExpired() && timeout != UNDEFINED_TIMEOUT) { - activeLock.appendChild(DomUtil.timeoutToXml(timeout, document)); - } - - // owner - if (getOwner() != null) { - DomUtil.addChildElement(activeLock, XML_OWNER, NAMESPACE, getOwner()); - } - - // locktoken - if (getToken() != null) { - Element lToken = DomUtil.addChildElement(activeLock, XML_LOCKTOKEN, NAMESPACE); - lToken.appendChild(DomUtil.hrefToXml(getToken(), document)); - } - - // lock root - if (getLockroot() != null) { - Element lroot = DomUtil.addChildElement(activeLock, XML_LOCKROOT, NAMESPACE); - lroot.appendChild(DomUtil.hrefToXml(getLockroot(), document)); - } - return activeLock; - } - -} \ No newline at end of file Property changes on: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/lock/AbstractActiveLock.java ___________________________________________________________________ Deleted: svn Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/lock/AbstractLockEntry.java =================================================================== --- jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/lock/AbstractLockEntry.java (revision 1907912) +++ jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/lock/AbstractLockEntry.java (nonexistent) @@ -1,47 +0,0 @@ -/* - * 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.webdav.lock; - -import org.apache.jackrabbit.webdav.DavConstants; -import org.apache.jackrabbit.webdav.xml.DomUtil; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.w3c.dom.Document; -import org.w3c.dom.Element; - -/** - * AbstractLockEntry provides the generic {@link org.apache.jackrabbit.webdav.xml.XmlSerializable#toXml} method. - */ -public abstract class AbstractLockEntry implements LockEntry, DavConstants { - - private static Logger log = LoggerFactory.getLogger(AbstractLockEntry.class); - - /** - * Returns the Xml representation of this LockEntry. - * - * @return Xml representation - * @see org.apache.jackrabbit.webdav.xml.XmlSerializable#toXml(Document) - * @param document - */ - public Element toXml(Document document) { - Element entry = DomUtil.createElement(document, XML_LOCKENTRY, NAMESPACE); - entry.appendChild(getScope().toXml(document)); - entry.appendChild(getType().toXml(document)); - return entry; - } - -} \ No newline at end of file Property changes on: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/lock/AbstractLockEntry.java ___________________________________________________________________ Deleted: svn Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/lock/ActiveLock.java =================================================================== --- jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/lock/ActiveLock.java (revision 1907912) +++ jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/lock/ActiveLock.java (nonexistent) @@ -1,124 +0,0 @@ -/* - * 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.webdav.lock; - -import org.apache.jackrabbit.webdav.xml.XmlSerializable; - -/** - * ActiveLock encapsulates the lock information for a - * {@link org.apache.jackrabbit.webdav.DavResource}. - */ -public interface ActiveLock extends XmlSerializable { - - /** - * Return true, if the given token matches the lock token present in this - * lock thus indicating that any lock relevant operation should not fail - * due to a lock. - * - * @param lockToken to be checked - * @return true if the given lock token matches. - */ - public boolean isLockedByToken(String lockToken); - - /** - * Returns true, if this lock is already expired. - * - * @return true if the lock is expired - */ - public boolean isExpired(); - - /** - * Return the lock token. - * - * @return token string representing the lock token. - */ - public String getToken(); - - /** - * Return the name (or id) of the lock owner. - * - * @return name (or id) of the lock owner. - */ - public String getOwner(); - - /** - * Set the name (or id) of the lock owner - * - * @param owner - */ - public void setOwner(String owner); - - /** - * Return the number of milliseconds the lock will live until it is expired - * or -1 if the timeout is not available (or the client is not allowed - * to retrieve it). - * - * @return number of milliseconds. - */ - public long getTimeout(); - - /** - * Defines the number of milliseconds until the timeout is reached. - * - * @param timeout - */ - public void setTimeout(long timeout); - - /** - * Return true if the lock is deep. - * - * @return true if the lock is deep. - */ - public boolean isDeep(); - - /** - * Set the lock deepness. - * - * @param isDeep - */ - public void setIsDeep(boolean isDeep); - - /** - * Returns the lockroot. - * - * @return lockroot - * @see RFC 4918 - */ - public String getLockroot(); - - /** - * Set the lockroot. - * - * @param lockroot - * @see RFC 4918 - */ - public void setLockroot(String lockroot); - - /** - * Return the type of this lock. - * - * @return type - */ - public Type getType(); - - /** - * Return the scope of this lock. - * - * @return scope - */ - public Scope getScope(); -} Property changes on: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/lock/ActiveLock.java ___________________________________________________________________ Deleted: svn Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/lock/DefaultActiveLock.java =================================================================== --- jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/lock/DefaultActiveLock.java (revision 1907912) +++ jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/lock/DefaultActiveLock.java (nonexistent) @@ -1,147 +0,0 @@ -/* - * 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.webdav.lock; - -import java.util.UUID; - -import org.apache.jackrabbit.webdav.DavConstants; - -/** - * DefaultActiveLock implements the ActiveLock interface - * and represents an exclusive write lock with a random uuid lock token. - * Lock owner, timeout and depth is retrieved from the {@link LockInfo} object - * passed in the constructor. If the lockinfo is null, the following default - * values are set:
- * - timeout is set to infinity.
- * - isDeep is set to true.
- * 
- */ -public class DefaultActiveLock extends AbstractActiveLock { - - private final String token = DavConstants.OPAQUE_LOCK_TOKEN_PREFIX + UUID.randomUUID(); - private String owner; - private boolean isDeep = true; // deep by default - private long expirationTime = DavConstants.INFINITE_TIMEOUT; // never expires by default; - - /** - * Create a new DefaultActiveLock with default values. - */ - public DefaultActiveLock() { - } - - /** - * Create a new lock - * - * @param lockInfo - * @throws IllegalArgumentException if either scope or type is invalid. - */ - public DefaultActiveLock(LockInfo lockInfo) { - if (lockInfo != null) { - if (!(Type.WRITE.equals(lockInfo.getType()) && Scope.EXCLUSIVE.equals(lockInfo.getScope()))) { - throw new IllegalArgumentException("Only 'exclusive write' lock is allowed scope/type pair."); - } - owner = lockInfo.getOwner(); - isDeep = lockInfo.isDeep(); - setTimeout(lockInfo.getTimeout()); - } - } - - /** - * @see ActiveLock#isLockedByToken(String) - */ - public boolean isLockedByToken(String lockToken) { - return (token != null) && token.equals(lockToken); - } - - /** - * @see ActiveLock#isExpired() - */ - public boolean isExpired() { - return System.currentTimeMillis() > expirationTime; - } - - /** - * @see ActiveLock#getToken() - */ - public String getToken() { - return token; - } - - /** - * @see ActiveLock#getOwner() - */ - public String getOwner() { - return owner; - } - - /** - * @see ActiveLock#setOwner(String) - */ - public void setOwner(String owner) { - this.owner = owner; - } - - /** - * @see ActiveLock#getTimeout() - */ - public long getTimeout() { - return expirationTime - System.currentTimeMillis(); - } - - /** - * @see ActiveLock#setTimeout(long) - */ - public void setTimeout(long timeout) { - if (timeout > 0) { - expirationTime = System.currentTimeMillis() + timeout; - } - } - - /** - * @see ActiveLock#isDeep() - */ - public boolean isDeep() { - return isDeep; - } - - /** - * @see ActiveLock#setIsDeep(boolean) - */ - public void setIsDeep(boolean isDeep) { - this.isDeep = isDeep; - } - - /** - * This is always a write lock. - * - * @return the lock type - * @see Type#WRITE - */ - public Type getType() { - return Type.WRITE; - } - - /** - * This is always an exclusive lock. - * - * @return the lock scope. - * @see Scope#EXCLUSIVE - */ - public Scope getScope() { - return Scope.EXCLUSIVE; - } -} Property changes on: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/lock/DefaultActiveLock.java ___________________________________________________________________ Deleted: svn Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/lock/LockDiscovery.java =================================================================== --- jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/lock/LockDiscovery.java (revision 1907912) +++ jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/lock/LockDiscovery.java (nonexistent) @@ -1,233 +0,0 @@ -/* - * 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.webdav.lock; - -import org.apache.jackrabbit.webdav.property.AbstractDavProperty; -import org.apache.jackrabbit.webdav.property.DavPropertyName; -import org.apache.jackrabbit.webdav.xml.DomUtil; -import org.apache.jackrabbit.webdav.xml.ElementIterator; -import org.apache.jackrabbit.webdav.header.TimeoutHeader; -import org.w3c.dom.Document; -import org.w3c.dom.Element; - -import java.util.ArrayList; -import java.util.List; - -/** - * The LockDiscovery class encapsulates the webdav lock discovery - * property that is sent in the request body (PROPFIND and LOCK) and received - * in a LOCK response body. - */ -public class LockDiscovery extends AbstractDavProperty> { - - /** - * Listing of existing locks applied to the resource this discovery was - * requested for. Each entry reveals, who has a lock, what type of lock he has, - * the timeout type and the time remaining on the timeout, and the lock-type. - * NOTE, that any of the information listed may be not available for the - * server is free to withhold any or all of this information. - */ - private List activeLocks = new ArrayList(); - - /** - * Creates a new empty LockDiscovery property - */ - public LockDiscovery() { - super(DavPropertyName.LOCKDISCOVERY, false); - } - - /** - * Create a new LockDiscovery property - * - * @param lock - */ - public LockDiscovery(ActiveLock lock) { - super(DavPropertyName.LOCKDISCOVERY, false); - addActiveLock(lock); - } - - /** - * Create a new LockDiscovery property - * - * @param locks - */ - public LockDiscovery(ActiveLock[] locks) { - super(DavPropertyName.LOCKDISCOVERY, false); - for (ActiveLock lock : locks) { - addActiveLock(lock); - } - } - - private void addActiveLock(ActiveLock lock) { - if (lock != null) { - activeLocks.add(lock); - } - } - - /** - * Returns the list of active locks. - * - * @return list of active locks - * @see org.apache.jackrabbit.webdav.property.DavProperty#getValue() - */ - public List getValue() { - return activeLocks; - } - - /** - * Creates a <lockdiscovery> element in response - * to a LOCK request or to the lockdiscovery property of a PROPFIND request.
- * NOTE: if the {@link #activeLocks} list is empty an empty lockdiscovery - * property is created ( <lockdiscovery/>) - * @return A <lockdiscovery> element. - * @param document - */ - @Override - public Element toXml(Document document) { - Element lockdiscovery = getName().toXml(document); - for (ActiveLock lock : activeLocks) { - lockdiscovery.appendChild(lock.toXml(document)); - } - return lockdiscovery; - } - - //---------------------------------------------------< factory from xml >--- - /** - * Builds a new LockDiscovery object from the given xml element. - * - * @param lockDiscoveryElement - * @return - * @throws IllegalArgumentException if the given xml element is not a - * DAV:lockdiscovery element. - */ - public static LockDiscovery createFromXml(Element lockDiscoveryElement) { - if (!DomUtil.matches(lockDiscoveryElement, PROPERTY_LOCKDISCOVERY, NAMESPACE)) { - throw new IllegalArgumentException("DAV:lockdiscovery element expected."); - } - - List activeLocks = new ArrayList(); - ElementIterator it = DomUtil.getChildren(lockDiscoveryElement, XML_ACTIVELOCK, NAMESPACE); - while (it.hasNext()) { - Element al = it.nextElement(); - activeLocks.add(new ALockImpl(al)); - } - - return new LockDiscovery(activeLocks.toArray(new ActiveLock[activeLocks.size()])); - } - - //------< inner class >----------------------------------------------------- - /** - * Simple implementation of ActiveLock interface, that retrieves - * the values from the DAV:activelock XML element.
- * Note, that all set-methods as well as {@link #isExpired()} are not - * implemented. - */ - private static class ALockImpl implements ActiveLock { - - private final Element alElement; - - private ALockImpl(Element alElement) { - if (!DomUtil.matches(alElement, XML_ACTIVELOCK, NAMESPACE)) { - throw new IllegalArgumentException("DAV:activelock element expected."); - } - this.alElement = alElement; - } - - public boolean isLockedByToken(String lockToken) { - String lt = getToken(); - if (lt == null) { - return false; - } else { - return lt.equals(lockToken); - } - } - - public boolean isExpired() { - throw new UnsupportedOperationException("Not implemented"); - } - - public String getToken() { - Element ltEl = DomUtil.getChildElement(alElement, XML_LOCKTOKEN, NAMESPACE); - if (ltEl != null) { - return DomUtil.getChildText(ltEl, XML_HREF, NAMESPACE); - } - return null; - } - - public String getOwner() { - String owner = null; - Element ow = DomUtil.getChildElement(alElement, XML_OWNER, NAMESPACE); - if (ow != null) { - if (DomUtil.hasChildElement(ow, XML_HREF, NAMESPACE)) { - owner = DomUtil.getChildTextTrim(ow, XML_HREF, NAMESPACE); - } else { - owner = DomUtil.getTextTrim(ow); - } - } - return owner; - } - - public void setOwner(String owner) { - throw new UnsupportedOperationException("Not implemented"); - } - - public long getTimeout() { - // get timeout string. if no DAV:timeout element is present, - // 't' will be 'null' and the undefined timeout will be returned. - String t = DomUtil.getChildTextTrim(alElement, XML_TIMEOUT, NAMESPACE); - return TimeoutHeader.parse(t, UNDEFINED_TIMEOUT); - } - - public void setTimeout(long timeout) { - throw new UnsupportedOperationException("Not implemented"); - } - - public boolean isDeep() { - String depth = DomUtil.getChildTextTrim(alElement, XML_DEPTH, NAMESPACE); - return DEPTH_INFINITY_S.equalsIgnoreCase(depth); - } - - public void setIsDeep(boolean isDeep) { - throw new UnsupportedOperationException("Not implemented"); - } - - public String getLockroot() { - Element root = DomUtil.getChildElement(alElement, XML_LOCKROOT, NAMESPACE); - if (root != null) { - return DomUtil.getChildTextTrim(root, XML_HREF, NAMESPACE); - } - // no lockroot element - return null; - } - - public void setLockroot(String lockroot) { - throw new UnsupportedOperationException("Not implemented"); - } - - public Type getType() { - return Type.createFromXml(DomUtil.getChildElement(alElement, XML_LOCKTYPE, NAMESPACE)); - } - - public Scope getScope() { - return Scope.createFromXml(DomUtil.getChildElement(alElement, XML_LOCKSCOPE, NAMESPACE)); - } - - public Element toXml(Document document) { - return (Element) document.importNode(alElement, true); - } - } -} Property changes on: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/lock/LockDiscovery.java ___________________________________________________________________ Deleted: svn Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/lock/LockEntry.java =================================================================== --- jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/lock/LockEntry.java (revision 1907912) +++ jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/lock/LockEntry.java (nonexistent) @@ -1,39 +0,0 @@ -/* - * 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.webdav.lock; - -import org.apache.jackrabbit.webdav.xml.XmlSerializable; - -/** - * LockEntry... - */ -public interface LockEntry extends XmlSerializable { - - /** - * Returns the type of this lock entry - * - * @return type of this lock entry. - */ - public Type getType(); - - /** - * Returns the scope of this lock entry. - * - * @return scope of this lock entry. - */ - public Scope getScope(); -} \ No newline at end of file Property changes on: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/lock/LockEntry.java ___________________________________________________________________ Deleted: svn Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/lock/LockInfo.java =================================================================== --- jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/lock/LockInfo.java (revision 1907912) +++ jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/lock/LockInfo.java (nonexistent) @@ -1,237 +0,0 @@ -/* - * 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.webdav.lock; - -import org.apache.jackrabbit.webdav.DavConstants; -import org.apache.jackrabbit.webdav.DavException; -import org.apache.jackrabbit.webdav.DavServletResponse; -import org.apache.jackrabbit.webdav.xml.DomUtil; -import org.apache.jackrabbit.webdav.xml.ElementIterator; -import org.apache.jackrabbit.webdav.xml.XmlSerializable; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.w3c.dom.Document; -import org.w3c.dom.Element; - -/** - * LockInfo is a simple utility class encapsulating the information - * passed with a LOCK request. It combines both the request body (which if present - * is required to by a 'lockinfo' Xml element) and the lock relevant request - * headers '{@link DavConstants#HEADER_TIMEOUT Timeout}' and - * '{@link DavConstants#HEADER_DEPTH Depth}'.
- * Note that is class is not intended to perform any validation of the information - * given, since this left to those objects responsible for the lock creation - * on the requested resource. - */ -public class LockInfo implements DavConstants, XmlSerializable { - - private static Logger log = LoggerFactory.getLogger(LockInfo.class); - - private Type type; - private Scope scope; - private String owner; - private boolean isDeep; - private long timeout; - - private boolean isRefreshLock; - - /** - * Create a new LockInfo used for refreshing an existing lock. - * - * @param timeout - */ - public LockInfo(long timeout) { - this.timeout = (timeout > 0) ? timeout : INFINITE_TIMEOUT; - this.isRefreshLock = true; - } - - /** - * Create a new LockInfo - * - * @param scope - * @param type - * @param owner - * @param timeout - * @param isDeep - */ - public LockInfo(Scope scope, Type type, String owner, long timeout, boolean isDeep) { - this.timeout = (timeout > 0) ? timeout : INFINITE_TIMEOUT; - this.isDeep = isDeep; - - if (scope == null || type == null) { - this.isRefreshLock = true; - } else { - this.scope = scope; - this.type = type; - this.owner = owner; - } - } - - /** - * Create a new LockInfo object from the given information. If - * liElement is null this lockinfo is assumed to - * be issued from a 'Refresh Lock' request. - * - * @param liElement 'lockinfo' element present in the request body of a LOCK request - * or null if the request was intended to refresh an existing lock. - * @param timeout Requested timespan until the lock should expire. A LOCK - * request MUST contain a '{@link DavConstants#HEADER_TIMEOUT Timeout}' - * according to RFC 2518. - * @param isDeep boolean value indicating whether the lock should be applied - * with depth infinity or only to the requested resource. - * @throws DavException if the liElement is not - * null but does not start with an 'lockinfo' element. - */ - public LockInfo(Element liElement, long timeout, boolean isDeep) throws DavException { - this.timeout = (timeout > 0) ? timeout : INFINITE_TIMEOUT; - this.isDeep = isDeep; - - if (liElement != null) { - if (!DomUtil.matches(liElement, XML_LOCKINFO, NAMESPACE)) { - log.warn("'DAV:lockinfo' element expected."); - throw new DavException(DavServletResponse.SC_BAD_REQUEST); - } - - ElementIterator it = DomUtil.getChildren(liElement); - while (it.hasNext()) { - Element child = it.nextElement(); - String childName = child.getLocalName(); - if (XML_LOCKTYPE.equals(childName)) { - type = Type.createFromXml(child); - } else if (XML_LOCKSCOPE.equals(childName)) { - scope = Scope.createFromXml(child); - } else if (XML_OWNER.equals(childName)) { - // first try if 'owner' is inside a href element - owner = DomUtil.getChildTextTrim(child, XML_HREF, NAMESPACE); - if (owner==null) { - // otherwise: assume owner is a simple text element - owner = DomUtil.getTextTrim(child); - } - } - } - isRefreshLock = false; - } else { - isRefreshLock = true; - } - } - - /** - * Returns the lock type or null if no 'lockinfo' element was - * passed to the constructor or did not contain an 'type' element and the - * type has not been set otherwise. - * - * @return type or null - */ - public Type getType() { - return type; - } - - /** - * Set the lock type. - * - * @param type - */ - public void setType(Type type) { - this.type = type; - } - - /** - * Return the lock scope or null if no 'lockinfo' element was - * passed to the constructor or did not contain an 'scope' element and the - * scope has not been set otherwise. - * - * @return scope or null - */ - public Scope getScope() { - return scope; - } - - /** - * Set the lock scope. - * - * @param scope - */ - public void setScope(Scope scope) { - this.scope = scope; - } - - /** - * Return the owner indicated by the corresponding child element from the - * 'lockinfo' element or null if no 'lockinfo' element was - * passed to the constructor or did not contain an 'owner' element. - * - * @return owner or null - */ - public String getOwner() { - return owner; - } - - /** - * Returns true if the lock must be applied with depth infinity. - * - * @return true if a deep lock must be created. - */ - public boolean isDeep() { - return isDeep; - } - - /** - * Returns the time until the lock is requested to expire. - * - * @return time until the lock should expire. - */ - public long getTimeout() { - return timeout; - } - - /** - * Returns true if this LockInfo was created for a LOCK - * request intended to refresh an existing lock rather than creating a - * new one. - * - * @return true if the corresponding LOCK request was intended to refresh - * an existing lock. - */ - public boolean isRefreshLock() { - return isRefreshLock; - } - - /** - * Returns the xml representation of this lock info.
- * NOTE however, that the depth and the timeout are not included - * in the xml. They will be passed to the server using the corresponding - * request headers. - * - * @param document - * @return xml representation of this lock info. - * @see org.apache.jackrabbit.webdav.xml.XmlSerializable#toXml(Document) - */ - public Element toXml(Document document) { - if (isRefreshLock) { - return null; - } else { - Element lockInfo = DomUtil.createElement(document, XML_LOCKINFO, NAMESPACE); - lockInfo.appendChild(scope.toXml(document)); - lockInfo.appendChild(type.toXml(document)); - if (owner != null) { - DomUtil.addChildElement(lockInfo, XML_OWNER, NAMESPACE, owner); - } - return lockInfo; - } - } - -} \ No newline at end of file Property changes on: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/lock/LockInfo.java ___________________________________________________________________ Deleted: svn Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/lock/LockManager.java =================================================================== --- jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/lock/LockManager.java (revision 1907912) +++ jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/lock/LockManager.java (nonexistent) @@ -1,87 +0,0 @@ -/* - * 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.webdav.lock; - -import org.apache.jackrabbit.webdav.DavException; -import org.apache.jackrabbit.webdav.DavResource; - -/** - * The LockManager interface. - */ -public interface LockManager { - - /** - * Create a new lock for the given {@link org.apache.jackrabbit.webdav.DavResource resource}. - * - * @param lockInfo - * @param resource - * @return - * @throws DavException - */ - public ActiveLock createLock(LockInfo lockInfo, DavResource resource) - throws DavException; - - /** - * Refresh the lock identified by the given lockToken and initially created - * on the specified resource. The update information can be retrieved from - * the lockInfo object passes. - * - * @param lockInfo - * @param lockToken - * @param resource - * @return - * @throws DavException - */ - public ActiveLock refreshLock(LockInfo lockInfo, String lockToken, DavResource resource) - throws DavException; - - /** - * Release the lock identified by the given lockToken and initially created - * on the specified resource. - * - * @param lockToken - * @param resource - * @throws DavException - */ - public void releaseLock(String lockToken, DavResource resource) - throws DavException; - - /** - * Retrieve the lock with the given type and scope that is applied to the - * given resource. The lock may be either initially created on this resource - * or might be inherited from an ancestor resource that hold a deep lock. - * If no such lock applies to the given resource null must be - * returned. - * - * @param type - * @param scope - * @param resource - * @return lock with the given type and scope applied to the resource or - * null if no lock applies. - */ - public ActiveLock getLock(Type type, Scope scope, DavResource resource); - - /** - * Returns true, if the the manager contains a lock for the given - * resource, that is hold by the specified token. - * - * @param lockToken - * @param resource - * @return true if the resource is locked by the specified token. - */ - public boolean hasLock(String lockToken, DavResource resource); -} \ No newline at end of file Property changes on: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/lock/LockManager.java ___________________________________________________________________ Deleted: svn Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/lock/Scope.java =================================================================== --- jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/lock/Scope.java (revision 1907912) +++ jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/lock/Scope.java (nonexistent) @@ -1,122 +0,0 @@ -/* - * 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.webdav.lock; - -import org.apache.jackrabbit.webdav.DavConstants; -import org.apache.jackrabbit.webdav.xml.DomUtil; -import org.apache.jackrabbit.webdav.xml.Namespace; -import org.apache.jackrabbit.webdav.xml.XmlSerializable; -import org.w3c.dom.Document; -import org.w3c.dom.Element; - -import java.util.HashMap; -import java.util.Map; - -/** - * The Scope class abstracts the lock scope as defined by RFC 2518. - */ -public class Scope implements XmlSerializable { - - private static final Map scopes = new HashMap(); - - public static final Scope EXCLUSIVE = Scope.create(DavConstants.XML_EXCLUSIVE, DavConstants.NAMESPACE); - public static final Scope SHARED = Scope.create(DavConstants.XML_SHARED, DavConstants.NAMESPACE); - - private final String localName; - private final Namespace namespace; - - /** - * Private constructor - * - * @param localName - * @param namespace - */ - private Scope(String localName, Namespace namespace) { - this.localName = localName; - this.namespace = namespace; - } - - /** - * Return the Xml representation of the lock scope object as present in - * the LOCK request and response body and in the {@link LockDiscovery}. - * - * @return Xml representation - * @see org.apache.jackrabbit.webdav.xml.XmlSerializable#toXml(Document) - */ - public Element toXml(Document document) { - Element lockScope = DomUtil.createElement(document, DavConstants.XML_LOCKSCOPE, DavConstants.NAMESPACE); - DomUtil.addChildElement(lockScope, localName, namespace); - return lockScope; - } - - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + localName.hashCode(); - result = prime * result + namespace.hashCode(); - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } else if (obj instanceof Scope) { - Scope other = (Scope) obj; - return localName.equals(other.localName) && namespace.equals(other.namespace); - } else { - return false; - } - } - - /** - * Create a Scope object from the given Xml element. - * - * @param lockScope - * @return Scope object. - */ - public static Scope createFromXml(Element lockScope) { - if (lockScope != null && DavConstants.XML_LOCKSCOPE.equals(lockScope.getLocalName())) { - // we have the parent element and must retrieve the scope first - lockScope = DomUtil.getFirstChildElement(lockScope); - } - if (lockScope == null) { - throw new IllegalArgumentException("'null' is not a valid lock scope entry."); - } - Namespace namespace = Namespace.getNamespace(lockScope.getPrefix(), lockScope.getNamespaceURI()); - return create(lockScope.getLocalName(), namespace); - } - - /** - * Create a Scope object from the given name and namespace. - * - * @param localName - * @param namespace - * @return Scope object. - */ - public static Scope create(String localName, Namespace namespace) { - String key = DomUtil.getExpandedName(localName, namespace); - if (scopes.containsKey(key)) { - return scopes.get(key); - } else { - Scope scope = new Scope(localName, namespace); - scopes.put(key, scope); - return scope; - } - } -} Property changes on: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/lock/Scope.java ___________________________________________________________________ Deleted: svn Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/lock/SimpleLockManager.java =================================================================== --- jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/lock/SimpleLockManager.java (revision 1907912) +++ jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/lock/SimpleLockManager.java (nonexistent) @@ -1,233 +0,0 @@ -/* - * 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.webdav.lock; - -import org.apache.jackrabbit.webdav.DavException; -import org.apache.jackrabbit.webdav.DavResource; -import org.apache.jackrabbit.webdav.DavResourceIterator; -import org.apache.jackrabbit.webdav.DavServletResponse; - -import java.util.HashMap; -import java.util.Map; - -/** - * Simple manager for webdav locks.
- */ -public class SimpleLockManager implements LockManager { - - /** map of locks */ - private Map locks = new HashMap(); - - /** - * - * @param lockToken - * @param resource - * @return - * @see LockManager#hasLock(String, org.apache.jackrabbit.webdav.DavResource) - */ - public boolean hasLock(String lockToken, DavResource resource) { - ActiveLock lock = locks.get(resource.getResourcePath()); - if (lock != null && lock.getToken().equals(lockToken)) { - return true; - } - return false; - } - - /** - * Returns the lock applying to the given resource or null if - * no lock can be found. - * - * @param type - * @param scope - * @param resource - * @return lock that applies to the given resource or null. - */ - public synchronized ActiveLock getLock(Type type, Scope scope, DavResource resource) { - if (!(Type.WRITE.equals(type) && Scope.EXCLUSIVE.equals(scope))) { - return null; - } - return getLock(resource.getResourcePath()); - } - - /** - * Looks for a valid lock at the given path or a deep lock present with - * a parent path. - * - * @param path - * @return - */ - private ActiveLock getLock(String path) { - ActiveLock lock = locks.get(path); - if (lock != null) { - // check if not expired - if (lock.isExpired()) { - lock = null; - } - } - if (lock == null) { - // check, if child of deep locked parent - if (!path.equals("/")) { - ActiveLock parentLock = getLock(getParentPath(path)); - if (parentLock != null && parentLock.isDeep()) { - lock = parentLock; - } - } - } - return lock; - } - - /** - * Adds the lock for the given resource, replacing any existing lock. - * - * @param lockInfo - * @param resource being the lock holder - */ - public synchronized ActiveLock createLock(LockInfo lockInfo, - DavResource resource) - throws DavException { - if (lockInfo == null || resource == null) { - throw new IllegalArgumentException("Neither lockInfo nor resource must be null."); - } - - String resourcePath = resource.getResourcePath(); - // test if there is already a lock present on this resource - ActiveLock lock = locks.get(resourcePath); - if (lock != null && lock.isExpired()) { - locks.remove(resourcePath); - lock = null; - } - if (lock != null) { - throw new DavException(DavServletResponse.SC_LOCKED, "Resource '" + resource.getResourcePath() + "' already holds a lock."); - } - // test if the new lock would conflict with any lock inherited from the - // collection or with a lock present on any member resource. - for (String key : locks.keySet()) { - // TODO: is check for lock on internal-member correct? - if (isDescendant(key, resourcePath)) { - ActiveLock l = locks.get(key); - if (l.isDeep() || (key.equals(getParentPath(resourcePath)) && !resource.isCollection())) { - throw new DavException(DavServletResponse.SC_LOCKED, "Resource '" + resource.getResourcePath() + "' already inherits a lock by its collection."); - } - } else if (isDescendant(resourcePath, key)) { - if (lockInfo.isDeep() || isInternalMember(resource, key)) { - throw new DavException(DavServletResponse.SC_CONFLICT, "Resource '" + resource.getResourcePath() + "' cannot be locked due to a lock present on the member resource '" + key + "'."); - } - - } - } - lock = new DefaultActiveLock(lockInfo); - locks.put(resource.getResourcePath(), lock); - return lock; - } - - /** - * - * @param lockInfo - * @param lockToken - * @param resource - * @return - * @throws DavException - * @see DavResource#refreshLock(org.apache.jackrabbit.webdav.lock.LockInfo, String) - */ - public ActiveLock refreshLock(LockInfo lockInfo, String lockToken, DavResource resource) - throws DavException { - ActiveLock lock = getLock(lockInfo.getType(), lockInfo.getScope(), resource); - if (lock == null) { - throw new DavException(DavServletResponse.SC_PRECONDITION_FAILED); - } else if (!lock.getToken().equals(lockToken)) { - throw new DavException(DavServletResponse.SC_LOCKED); - } - lock.setTimeout(lockInfo.getTimeout()); - return lock; - } - - /** - * Remove the lock hold by the given resource. - * - * @param lockToken - * @param resource that is the lock holder - */ - public synchronized void releaseLock(String lockToken, DavResource resource) - throws DavException { - if (!locks.containsKey(resource.getResourcePath())) { - throw new DavException(DavServletResponse.SC_PRECONDITION_FAILED); - } - ActiveLock lock = locks.get(resource.getResourcePath()); - if (lock.getToken().equals(lockToken)) { - locks.remove(resource.getResourcePath()); - } else { - throw new DavException(DavServletResponse.SC_LOCKED); - } - } - - /** - * Return true, if the resource with the given memberPath is a internal - * non-collection member of the given resource, thus affected by a - * non-deep lock present on the resource. - * - * @param resource - * @param memberPath - * @return - */ - private static boolean isInternalMember(DavResource resource, String memberPath) { - if (resource.getResourcePath().equals(getParentPath(memberPath))) { - // find the member with the given path - DavResourceIterator it = resource.getMembers(); - while (it.hasNext()) { - DavResource member = it.nextResource(); - if (member.getResourcePath().equals(memberPath)) { - // return true if that member is not a collection - return !member.isCollection(); - } - } - } - return false; - } - - /** - * @param path Path to retrieve the parent path for. - * @return empty string if the specified path contains no '/', "/" if the - * last index of '/' is zero. Otherwise the last segment is cut off the - * specified path. - */ - private static String getParentPath(String path) { - int idx = path.lastIndexOf('/'); - switch (idx) { - case -1: - return ""; - case 0: - return "/"; - default: - return path.substring(0, idx); - } - } - - /** - * Determines if the descendant path is hierarchical a - * descendant of path. - * - * @param path the current path - * @param descendant the potential descendant - * @return true if the descendant is a descendant; - * false otherwise. - */ - private static boolean isDescendant(String path, String descendant) { - String pattern = path.endsWith("/") ? path : path + "/"; - return !pattern.equals(descendant) && descendant.startsWith(pattern); - } -} - Property changes on: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/lock/SimpleLockManager.java ___________________________________________________________________ Deleted: svn Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/lock/SupportedLock.java =================================================================== --- jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/lock/SupportedLock.java (revision 1907912) +++ jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/lock/SupportedLock.java (nonexistent) @@ -1,166 +0,0 @@ -/* - * 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.webdav.lock; - -import org.apache.jackrabbit.webdav.property.AbstractDavProperty; -import org.apache.jackrabbit.webdav.property.DavPropertyName; -import org.w3c.dom.Document; -import org.w3c.dom.Element; - -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; - -/** - * The SupportedLock class encapsulates the lock capabilities - * of a resource. It is mainly responsible for generating the <supportedlock> - * property. - */ -public class SupportedLock extends AbstractDavProperty> { - - /** the list of lock entries */ - private final List entries = new ArrayList(); - - /** - * Creates a new empty SupportedLock property. - */ - public SupportedLock() { - super(DavPropertyName.SUPPORTEDLOCK, false); - } - - /** - * Adds a capability to this lock support. - * - * @param type Can currently only be 'write' - * @param scope Can currently only be 'exclusive' or 'shared' - * - * @throws IllegalArgumentException If an argument contains invalid string - */ - public void addEntry(Type type, Scope scope) { - entries.add(new WriteLockEntry(type, scope)); - } - - /** - * Adds a capability to this lock support. - * - * @param entry specifying the type of lock that is supported by this entry. - * @see LockEntry - */ - public void addEntry(LockEntry entry) { - if (entry == null) { - throw new IllegalArgumentException("The lock entry cannot be null."); - } - entries.add(entry); - } - - /** - * Returns true if this a lock with the given type and scope is supported. - * - * @param type - * @param scope - * @return true if applying a lock with the given type and scope is basically - * supported. - */ - public boolean isSupportedLock(Type type, Scope scope) { - for (LockEntry le : entries) { - if (le.getType().equals(type) && le.getScope().equals(scope)) { - return true; - } - } - return false; - } - - /** - * Returns an iterator over all supported locks. - * - * @return an iterator over all supported locks - */ - public Iterator getSupportedLocks() { - return entries.iterator(); - } - - /** - * Creates an XML element that represents the <supportedlock> tag. - * - * @return An XML element of this lock support. - * @param document - */ - @Override - public Element toXml(Document document) { - Element support = getName().toXml(document); - for (LockEntry le : entries) { - support.appendChild(le.toXml(document)); - } - return support; - } - - /** - * Returns the list of supported lock entries. - * - * @return list of supported lock. - * @see org.apache.jackrabbit.webdav.property.DavProperty#getValue() - */ - public List getValue() { - return entries; - } - - /** - * Class representing the default lock entries defined by - * RFC 2518. - */ - private final static class WriteLockEntry extends AbstractLockEntry { - - /** the lock scope */ - private final Scope scope; - - /** - * Creates a new WriteLockEntry - * - * @param type Can currently only be - * {@link Type#WRITE write} - * @param scope Can currently only be {@link Scope#EXCLUSIVE exclusive} - * or {@link Scope#SHARED shared}. - * - * @throws IllegalArgumentException If an argument contains invalid string - */ - WriteLockEntry(Type type, Scope scope) { - if (!Type.WRITE.equals(type)) { - throw new IllegalArgumentException("Invalid Type:" + type); - } - if (!Scope.EXCLUSIVE.equals(scope) && !Scope.SHARED.equals(scope)) { - throw new IllegalArgumentException("Invalid scope:" +scope); - } - this.scope = scope; - } - - /** - * @return always returns {@link Type#WRITE write}. - * @see LockEntry#getType() - */ - public Type getType() { - return Type.WRITE; - } - - /** - * @return returns {@link Scope#EXCLUSIVE} or {@link Scope#SHARED}. - * @see LockEntry#getScope() - */ - public Scope getScope() { - return scope; - } - } -} Property changes on: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/lock/SupportedLock.java ___________________________________________________________________ Deleted: svn Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/lock/Type.java =================================================================== --- jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/lock/Type.java (revision 1907912) +++ jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/lock/Type.java (nonexistent) @@ -1,129 +0,0 @@ -/* - * 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.webdav.lock; - -import org.apache.jackrabbit.webdav.DavConstants; -import org.apache.jackrabbit.webdav.xml.DomUtil; -import org.apache.jackrabbit.webdav.xml.Namespace; -import org.apache.jackrabbit.webdav.xml.XmlSerializable; -import org.w3c.dom.Document; -import org.w3c.dom.Element; - -import java.util.HashMap; -import java.util.Map; - -/** - * The Type class encapsulates the lock type as defined by RFC 2518. - */ -public class Type implements XmlSerializable { - - private static Map types = new HashMap(); - - public static final Type WRITE = Type.create(DavConstants.XML_WRITE, DavConstants.NAMESPACE); - - private final String localName; - private final Namespace namespace; - - private int hashCode = -1; - - /** - * Private constructor. - * - * @param name - * @param namespace - */ - private Type(String name, Namespace namespace) { - this.localName = name; - this.namespace = namespace; - } - - /** - * Returns the Xml representation of this lock Type. - * - * @return Xml representation - * @see org.apache.jackrabbit.webdav.xml.XmlSerializable#toXml(Document) - */ - public Element toXml(Document document) { - Element lockType = DomUtil.createElement(document, DavConstants.XML_LOCKTYPE, DavConstants.NAMESPACE); - DomUtil.addChildElement(lockType, localName, namespace); - return lockType; - } - - @Override - public int hashCode() { - if (hashCode == -1) { - StringBuilder b = new StringBuilder(); - b.append("LockType : {").append(namespace).append("}").append(localName); - hashCode = b.toString().hashCode(); - } - return hashCode; - } - - /** - * Returns true if this Type is equal to the given one. - * - * @param obj - * @return - */ - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (obj instanceof Type) { - Type other = (Type) obj; - return localName.equals(other.localName) && namespace.equals(other.namespace); - } - return false; - } - - /** - * Create a Type object from the given Xml element. - * - * @param lockType - * @return Type object. - */ - public static Type createFromXml(Element lockType) { - if (lockType != null && DavConstants.XML_LOCKTYPE.equals(lockType.getLocalName())) { - // we have the parent element and must retrieve the type first - lockType = DomUtil.getFirstChildElement(lockType); - } - if (lockType == null) { - throw new IllegalArgumentException("'null' is not valid lock type entry."); - } - Namespace namespace = Namespace.getNamespace(lockType.getPrefix(), lockType.getNamespaceURI()); - return create(lockType.getLocalName(), namespace); - } - - /** - * Create a Type object from the given localName and namespace. - * - * @param localName - * @param namespace - * @return Type object. - */ - public static Type create(String localName, Namespace namespace) { - String key = DomUtil.getExpandedName(localName, namespace); - if (types.containsKey(key)) { - return types.get(key); - } else { - Type type = new Type(localName, namespace); - types.put(key, type); - return type; - } - } -} Property changes on: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/lock/Type.java ___________________________________________________________________ Deleted: svn Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/lock/package-info.java =================================================================== --- jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/lock/package-info.java (revision 1907912) +++ jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/lock/package-info.java (nonexistent) @@ -1,18 +0,0 @@ -/* - * 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. - */ -@org.osgi.annotation.versioning.Version("1.0.1") -package org.apache.jackrabbit.webdav.lock; Property changes on: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/lock/package-info.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/observation/DefaultEventType.java =================================================================== --- jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/observation/DefaultEventType.java (revision 1907912) +++ jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/observation/DefaultEventType.java (nonexistent) @@ -1,148 +0,0 @@ -/* - * 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.webdav.observation; - -import org.apache.jackrabbit.webdav.xml.Namespace; -import org.apache.jackrabbit.webdav.xml.DomUtil; -import org.apache.jackrabbit.webdav.xml.XmlSerializable; -import org.apache.jackrabbit.webdav.xml.ElementIterator; -import org.w3c.dom.Element; -import org.w3c.dom.Document; - -import java.util.Map; -import java.util.HashMap; -import java.util.List; -import java.util.ArrayList; - -/** - * DefaultEventType defines a simple EventType implementation that - * only consists of a qualified event name consisting of namespace plus local - * name. - */ -public class DefaultEventType implements EventType { - - private static final Map eventTypes = new HashMap(); - - private final String localName; - private final Namespace namespace; - - /** - * Avoid instantiation of DefaultEventType. Since the amount - * of available (and registered) events is considered to be limited, the - * static {@link #create(String, Namespace) method is defined. - * - * @param localName - * @param namespace - */ - private DefaultEventType(String localName, Namespace namespace) { - this.localName = localName; - this.namespace = namespace; - } - - /** - * Factory method to create a new EventType. - * - * @param localName - * @param namespace - * @return - */ - public static EventType create(String localName, Namespace namespace) { - if (localName == null || "".equals(localName)) { - throw new IllegalArgumentException("null and '' are not valid local names of an event type."); - } - String key = DomUtil.getExpandedName(localName, namespace); - if (eventTypes.containsKey(key)) { - return eventTypes.get(key); - } else { - EventType type = new DefaultEventType(localName, namespace); - eventTypes.put(key, type); - return type; - } - } - - /** - * Factory method to create an array of new EventType for the - * specified localNames and the specified namespace. - * - * @param localNames - * @param namespace - * @return An array of event types. - */ - public static EventType[] create(String[] localNames, Namespace namespace) { - EventType[] types = new EventType[localNames.length]; - for (int i = 0; i < localNames.length; i++) { - types[i] = create(localNames[i], namespace); - } - return types; - } - - /** - * Retrieves one or multiple EventTypes from the 'eventtype' - * Xml element. While a subscription may register multiple types (thus - * the 'eventtype' contains multiple child elements), a single event may only - * refer to one single type. - * - * @param eventType - * @return - */ - public static EventType[] createFromXml(Element eventType) { - if (!DomUtil.matches(eventType, ObservationConstants.XML_EVENTTYPE, ObservationConstants.NAMESPACE)) { - throw new IllegalArgumentException("'eventtype' element expected which contains a least a single child element."); - } - - List etypes = new ArrayList(); - ElementIterator it = DomUtil.getChildren(eventType); - while (it.hasNext()) { - Element el = it.nextElement(); - etypes.add(create(el.getLocalName(), DomUtil.getNamespace(el))); - } - return etypes.toArray(new EventType[etypes.size()]); - } - - //----------------------------------------------------------< EventType >--- - /** - * @see EventType#getName() - */ - public String getName() { - return localName; - } - - /** - * @see EventType#getNamespace() - */ - public Namespace getNamespace() { - return namespace; - } - - //----------------------------------------------------< XmlSerializable >--- - /** - * Returns a single empty Xml element where namespace and local name of this - * event type define the elements name. - *
-     * EventType.create("someevent", Namespace.getNamespace("F", "http://www.foo.bar/eventtypes"));
-     *
-     * returns the following element upon call of toXml:
-     *
-     * <F:someevent xmlns:F="http://www.foo.bar/eventtypes" />
-     * 
- * - * @see XmlSerializable#toXml(Document) - */ - public Element toXml(Document document) { - return DomUtil.createElement(document, localName, namespace); - } -} Property changes on: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/observation/DefaultEventType.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Deleted: svn:keywords ## -1 +0,0 ## -author date id revision url \ No newline at end of property Index: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/observation/EventBundle.java =================================================================== --- jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/observation/EventBundle.java (revision 1907912) +++ jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/observation/EventBundle.java (nonexistent) @@ -1,29 +0,0 @@ -/* - * 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.webdav.observation; - -import org.apache.jackrabbit.webdav.xml.XmlSerializable; - -/** - * EventBundle defines an empty interface used to represent a bundle - * of events. - * - * @see EventDiscovery#addEventBundle(EventBundle) - */ -public interface EventBundle extends XmlSerializable { - -} \ No newline at end of file Property changes on: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/observation/EventBundle.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Deleted: svn:keywords ## -1 +0,0 ## -author date id revision url \ No newline at end of property Index: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/observation/EventDiscovery.java =================================================================== --- jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/observation/EventDiscovery.java (revision 1907912) +++ jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/observation/EventDiscovery.java (nonexistent) @@ -1,121 +0,0 @@ -/* - * 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.webdav.observation; - -import org.apache.jackrabbit.webdav.xml.DomUtil; -import org.apache.jackrabbit.webdav.xml.ElementIterator; -import org.apache.jackrabbit.webdav.xml.XmlSerializable; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.w3c.dom.Document; -import org.w3c.dom.Element; - -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; - -/** - * EventDiscovery represents the request body of a successful - * POLL request. It reveals all events that occurred since the last POLL. The - * definition what events that particular subscription is interested in was - * specified with the initial SUBSCRIPTION that started the event listening. - */ -public class EventDiscovery implements ObservationConstants, XmlSerializable { - - private static Logger log = LoggerFactory.getLogger(EventDiscovery.class); - - private final List bundles = new ArrayList(); - - /** - * Add the Xml representation of an single 'eventBundle' listing the - * events that resulted from a change in the server, filtered by the - * restrictions present in the corresponding subscription. - * - * @param eventBundle - * @see Subscription - */ - public void addEventBundle(EventBundle eventBundle) { - if (eventBundle != null) { - bundles.add(eventBundle); - } - } - - /** - * Returns an iterator over the {@link EventBundle event bundles} currently - * present on this discovery. - * - * @return iterator over event bundles present. - */ - public Iterator getEventBundles() { - return bundles.iterator(); - } - - /** - * Returns true, if this event discovery does not report any events (thus - * {@link #getEventBundles()} would return an empty iterator. - * - * @return true if {@link #getEventBundles()} would return an empty iterator, - * false otherwise. - */ - public boolean isEmpty() { - return bundles.isEmpty(); - } - - /** - * Returns the Xml representation of this EventDiscovery as - * being present in the POLL response body. - * - * @return Xml representation - * @see org.apache.jackrabbit.webdav.xml.XmlSerializable#toXml(Document) - * @param document - */ - public Element toXml(Document document) { - Element ed = DomUtil.createElement(document, XML_EVENTDISCOVERY, NAMESPACE); - for (EventBundle bundle : bundles) { - ed.appendChild(bundle.toXml(document)); - } - return ed; - } - - /** - * Build a EventDiscovery from the specified xml element. - * - * @param eventDiscoveryElement - * @return new EventDiscovery instance. - * @throws IllegalArgumentException if the given document is null - * or does not provide the required element. - */ - public static EventDiscovery createFromXml(Element eventDiscoveryElement) { - if (!DomUtil.matches(eventDiscoveryElement, XML_EVENTDISCOVERY, ObservationConstants.NAMESPACE)) { - throw new IllegalArgumentException( - "{" + ObservationConstants.NAMESPACE + "}" + XML_EVENTDISCOVERY + " element expected, but got: {" - + eventDiscoveryElement.getNamespaceURI() + "}" + eventDiscoveryElement.getLocalName()); - } - EventDiscovery eventDiscovery = new EventDiscovery(); - ElementIterator it = DomUtil.getChildren(eventDiscoveryElement, XML_EVENTBUNDLE, ObservationConstants.NAMESPACE); - while (it.hasNext()) { - final Element ebElement = it.nextElement(); - EventBundle eb = new EventBundle() { - public Element toXml(Document document) { - return (Element) document.importNode(ebElement, true); - } - }; - eventDiscovery.addEventBundle(eb); - } - return eventDiscovery; - } -} Property changes on: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/observation/EventDiscovery.java ___________________________________________________________________ Deleted: svn Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/observation/EventType.java =================================================================== --- jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/observation/EventType.java (revision 1907912) +++ jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/observation/EventType.java (nonexistent) @@ -1,30 +0,0 @@ -/* - * 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.webdav.observation; - -import org.apache.jackrabbit.webdav.xml.Namespace; -import org.apache.jackrabbit.webdav.xml.XmlSerializable; - -/** - * EventType... - */ -public interface EventType extends XmlSerializable { - - public String getName(); - - public Namespace getNamespace(); -} \ No newline at end of file Property changes on: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/observation/EventType.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Deleted: svn:keywords ## -1 +0,0 ## -author date id revision url \ No newline at end of property Index: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/observation/Filter.java =================================================================== --- jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/observation/Filter.java (revision 1907912) +++ jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/observation/Filter.java (nonexistent) @@ -1,74 +0,0 @@ -/* - * 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.webdav.observation; - -import org.apache.jackrabbit.webdav.xml.DomUtil; -import org.apache.jackrabbit.webdav.xml.Namespace; -import org.apache.jackrabbit.webdav.xml.XmlSerializable; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.w3c.dom.Document; -import org.w3c.dom.Element; - -/** - * Filter... - */ -public class Filter implements XmlSerializable { - - private static Logger log = LoggerFactory.getLogger(Filter.class); - - private final String filterName; - private final Namespace filterNamespace; - private final String filterValue; - - public Filter(String filterName, Namespace filterNamespace, String filterValue) { - if (filterName == null) { - throw new IllegalArgumentException("filterName must not be null."); - } - this.filterName = filterName; - this.filterNamespace = filterNamespace; - this.filterValue = filterValue; - } - - public Filter(Element filterElem) { - filterName = filterElem.getLocalName(); - filterNamespace = DomUtil.getNamespace(filterElem); - filterValue = DomUtil.getTextTrim(filterElem); - } - - public String getName() { - return filterName; - } - - public Namespace getNamespace() { - return filterNamespace; - } - - public String getValue() { - return filterValue; - } - - public boolean isMatchingFilter(String localName, Namespace namespace) { - boolean matchingNsp = (filterNamespace == null) ? namespace == null : filterNamespace.equals(namespace); - return filterName.equals(localName) && matchingNsp; - } - - public Element toXml(Document document) { - return DomUtil.createElement(document, filterName, filterNamespace, filterValue); - } - -} \ No newline at end of file Property changes on: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/observation/Filter.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Deleted: svn:keywords ## -1 +0,0 ## -author date id revision url \ No newline at end of property Index: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/observation/ObservationConstants.java =================================================================== --- jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/observation/ObservationConstants.java (revision 1907912) +++ jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/observation/ObservationConstants.java (nonexistent) @@ -1,101 +0,0 @@ -/* - * 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.webdav.observation; - -import javax.xml.namespace.QName; - -import org.apache.jackrabbit.webdav.property.DavPropertyName; -import org.apache.jackrabbit.webdav.xml.Namespace; - -/** - * ObservationConstants interface provide constants for request - * and response headers, Xml elements and property names used for handling - * observation over WebDAV. There exists no public standard for this - * functionality. - */ -public interface ObservationConstants { - - /** - * The namespace - */ - public static final Namespace NAMESPACE = Namespace.getNamespace("dcr", "http://www.day.com/jcr/webdav/1.0"); - - //---< Headers >------------------------------------------------------------ - /** - * The SubscriptionId request header
- */ - public static final String HEADER_SUBSCRIPTIONID = "SubscriptionId"; - - /** - * The PollTimeout request header. - */ - public static final String HEADER_POLL_TIMEOUT = "PollTimeout"; - - //---< XML Element, Attribute Names >--------------------------------------- - /** - * subscription Xml element
- * Mandatory element inside the {@link #SUBSCRIPTIONDISCOVERY subscriptiondiscovery} - * property indicating the event listeners present for this session.
- * NOTE, that this will not reveal any subscription made by another session. - */ - public static final String XML_SUBSCRIPTION = "subscription"; - - /** - * Xml elements - */ - public static final String XML_SUBSCRIPTIONINFO = "subscriptioninfo"; - - public static final String XML_EVENTTYPE = "eventtype"; - public static final String XML_NOLOCAL = "nolocal"; - public static final String XML_FILTER = "filter"; - public static final String XML_SUBSCRIPTIONID = "subscriptionid"; - public static final String XML_EVENTSWITHTYPES = "eventswithnodetypes"; - public static final String XML_EVENTSWITHLOCALFLAG = "eventswithlocalflag"; - public static final String XML_UUID = "uuid"; - public static final String XML_NODETYPE_NAME = "nodetype-name"; - - public static final String XML_EVENTDISCOVERY = "eventdiscovery"; - public static final String XML_EVENTBUNDLE = "eventbundle"; - public static final String XML_EVENT_TRANSACTION_ID = "transactionid"; - public static final String XML_EVENT_LOCAL = "local"; - public static final String XML_EVENT = "event"; - public static final String XML_EVENTUSERID = "eventuserid"; - public static final String XML_EVENTUSERDATA = "eventuserdata"; - public static final String XML_EVENTDATE = "eventdate"; - public static final String XML_EVENTIDENTIFIER = "eventidentifier"; - public static final String XML_EVENTINFO = "eventinfo"; - public static final String XML_EVENTPRIMARNODETYPE = "eventprimarynodetype"; - public static final String XML_EVENTMIXINNODETYPE = "eventmixinnodetype"; - - public static final QName N_EVENT = new QName(NAMESPACE.getURI(), XML_EVENT); - public static final QName N_EVENTBUNDLE = new QName(NAMESPACE.getURI(), XML_EVENTBUNDLE); - public static final QName N_EVENTDATE = new QName(NAMESPACE.getURI(), XML_EVENTDATE); - public static final QName N_EVENTDISCOVERY = new QName(NAMESPACE.getURI(), XML_EVENTDISCOVERY); - public static final QName N_EVENTINFO = new QName(NAMESPACE.getURI(), XML_EVENTINFO); - public static final QName N_EVENTMIXINNODETYPE = new QName(NAMESPACE.getURI(), XML_EVENTMIXINNODETYPE); - public static final QName N_EVENTPRIMARYNODETYPE = new QName(NAMESPACE.getURI(), XML_EVENTPRIMARNODETYPE); - public static final QName N_EVENTTYPE = new QName(NAMESPACE.getURI(), XML_EVENTTYPE); - public static final QName N_EVENTUSERDATA = new QName(NAMESPACE.getURI(), XML_EVENTUSERDATA); - public static final QName N_EVENTUSERID = new QName(NAMESPACE.getURI(), XML_EVENTUSERID); - - //---< Property Names >----------------------------------------------------- - /** - * The protected subscription discovery property is used to find out about - * existing subscriptions present on the specified resource. - */ - public static final DavPropertyName SUBSCRIPTIONDISCOVERY = DavPropertyName.create("subscriptiondiscovery", NAMESPACE); -} Property changes on: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/observation/ObservationConstants.java ___________________________________________________________________ Deleted: svn Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/observation/ObservationDavServletRequest.java =================================================================== --- jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/observation/ObservationDavServletRequest.java (revision 1907912) +++ jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/observation/ObservationDavServletRequest.java (nonexistent) @@ -1,54 +0,0 @@ -/* - * 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.webdav.observation; - -import org.apache.jackrabbit.webdav.DavException; -import org.apache.jackrabbit.webdav.DavServletRequest; - -/** - * ObservationDavServletRequest provides extensions to the - * {@link DavServletRequest} interface used for dealing with observation. - */ -public interface ObservationDavServletRequest extends DavServletRequest { - - /** - * Return the {@link ObservationConstants#HEADER_SUBSCRIPTIONID SubscriptionId header} - * or null if no such header is present. - * - * @return the {@link ObservationConstants#HEADER_SUBSCRIPTIONID SubscriptionId header} - */ - public String getSubscriptionId(); - - /** - * Returns the {@link ObservationConstants#HEADER_POLL_TIMEOUT PollTimeout header} - * or 0 (zero) if no such header is present. - * - * @return milliseconds indicating length of the poll timeout. - */ - public long getPollTimeout(); - - /** - * Return a {@link SubscriptionInfo} object representing the subscription - * info present in the SUBSCRIBE request body or null if - * retrieving the subscription info fails. - * - * @return subscription info object encapsulating the SUBSCRIBE request body - * or null if the subscription info cannot be built. - * @throws DavException if an invalid request body was encountered. - */ - public SubscriptionInfo getSubscriptionInfo() throws DavException; -} \ No newline at end of file Property changes on: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/observation/ObservationDavServletRequest.java ___________________________________________________________________ Deleted: svn Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/observation/ObservationDavServletResponse.java =================================================================== --- jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/observation/ObservationDavServletResponse.java (revision 1907912) +++ jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/observation/ObservationDavServletResponse.java (nonexistent) @@ -1,45 +0,0 @@ -/* - * 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.webdav.observation; - -import org.apache.jackrabbit.webdav.DavServletResponse; - -import java.io.IOException; - -/** - * ObservationDavServletResponse provides extensions to the - * {@link DavServletResponse} interface used for dealing with observation. - */ -public interface ObservationDavServletResponse extends DavServletResponse { - - /** - * Send the response to a successful SUBSCRIBE request. - * - * @param subscription that needs to be represented in the response body. - * @throws IOException - */ - public void sendSubscriptionResponse(Subscription subscription) throws IOException; - - /** - * Send the response to a successful POLL request. - * - * @param eventDiscovery {@link EventDiscovery} object to be returned in - * the response body. - * @throws IOException - */ - public void sendPollResponse(EventDiscovery eventDiscovery) throws IOException; -} \ No newline at end of file Property changes on: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/observation/ObservationDavServletResponse.java ___________________________________________________________________ Deleted: svn Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/observation/ObservationResource.java =================================================================== --- jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/observation/ObservationResource.java (revision 1907912) +++ jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/observation/ObservationResource.java (nonexistent) @@ -1,72 +0,0 @@ -/* - * 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.webdav.observation; - -import org.apache.jackrabbit.webdav.DavException; -import org.apache.jackrabbit.webdav.DavResource; - -/** - * ObservationResource extends the {@link DavResource} interface by - * observation relevant METHODS. - */ -public interface ObservationResource extends DavResource { - - public String METHODS = "SUBSCRIBE, UNSUBSCRIBE, POLL"; - - /** - * Initializes this resource. - * - * @param subsMgr subscription manager object - */ - public void init(SubscriptionManager subsMgr); - - /** - * Subscribe this resource for event listening defined by the specified - * subscription info. A subscriptionId may be specified in case an existing - * subscription should be modified. - * - * @param info SubscriptionInfo object as defined by the - * request body and headers. - * @param subscriptionId or null if the - * {@link ObservationConstants#HEADER_SUBSCRIPTIONID SubscriptionId} header - * is missing. - * @return Subscription object in case the subscription was - * successful. - */ - public Subscription subscribe(SubscriptionInfo info, String subscriptionId) throws DavException; - - /** - * Unsubscribe the event listener with the given SubscriptionId. - * - * @param subscriptionId as present in the {@link ObservationConstants#HEADER_SUBSCRIPTIONID - * SubscriptionId} header. - */ - public void unsubscribe(String subscriptionId) throws DavException; - - /** - * Retrieve the list of events that where recorded for the event listener - * with the given SubscriptionId. - * - * @param subscriptionId as present in the - * {@link ObservationConstants#HEADER_SUBSCRIPTIONID SubscriptionId} header. - * @param timeout as present in the - * {@link ObservationConstants#HEADER_POLL_TIMEOUT} header or 0 (zero) if - * none is present. - * @return EventDiscovery object - */ - public EventDiscovery poll(String subscriptionId, long timeout) throws DavException; -} \ No newline at end of file Property changes on: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/observation/ObservationResource.java ___________________________________________________________________ Deleted: svn Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/observation/Subscription.java =================================================================== --- jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/observation/Subscription.java (revision 1907912) +++ jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/observation/Subscription.java (nonexistent) @@ -1,49 +0,0 @@ -/* - * 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.webdav.observation; - -import org.apache.jackrabbit.webdav.xml.XmlSerializable; - -/** - * Subscription represents public representation of the event - * listener created (or modified) by a successful SUBSCRIBE request.
- * Please note that this interface extends the XmlSerializable - * interface. The Xml representation of a Subscription is - * returned in the response to a successful SUBSCRIBE request as well - * as in a PROPFIND request. In both cases the subscription is packed into - * a {@link SubscriptionDiscovery} property object. - */ -public interface Subscription extends XmlSerializable { - - /** - * Returns the id of this subscription, that must be used for un-subscribing - * as well as for event discovery later on. - * - * @return subscriptionId - */ - public String getSubscriptionId(); - - /** - * @return whether events will be returned with node type information - */ - public boolean eventsProvideNodeTypeInformation(); - - /** - * @return whether events will be returned with the "noLocal" flag - */ - public boolean eventsProvideNoLocalFlag(); -} \ No newline at end of file Property changes on: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/observation/Subscription.java ___________________________________________________________________ Deleted: svn Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/observation/SubscriptionDiscovery.java =================================================================== --- jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/observation/SubscriptionDiscovery.java (revision 1907912) +++ jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/observation/SubscriptionDiscovery.java (nonexistent) @@ -1,139 +0,0 @@ -/* - * 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.webdav.observation; - -import org.apache.jackrabbit.webdav.property.AbstractDavProperty; -import org.apache.jackrabbit.webdav.xml.DomUtil; -import org.apache.jackrabbit.webdav.xml.ElementIterator; -import org.apache.jackrabbit.webdav.xml.XmlSerializable; -import org.apache.jackrabbit.webdav.DavConstants; -import org.w3c.dom.Document; -import org.w3c.dom.Element; - -import java.util.List; -import java.util.ArrayList; - -/** - * SubscriptionDiscovery encapsulates the 'subscriptiondiscovery' - * property of a webdav resource. - */ -public class SubscriptionDiscovery extends AbstractDavProperty { - - private final Subscription[] subscriptions; - - /** - * Create a new SubscriptionDiscovery that lists the given - * subscriptions. - * - * @param subscriptions - */ - public SubscriptionDiscovery(Subscription[] subscriptions) { - super(ObservationConstants.SUBSCRIPTIONDISCOVERY, true); - if (subscriptions != null) { - this.subscriptions = subscriptions; - } else { - this.subscriptions = new Subscription[0]; - } - } - - /** - * Create a new SubscriptionDiscovery that contains a single - * subscription entry. - * - * @param subscription - */ - public SubscriptionDiscovery(Subscription subscription) { - super(ObservationConstants.SUBSCRIPTIONDISCOVERY, true); - if (subscription != null) { - this.subscriptions = new Subscription[]{subscription}; - } else { - this.subscriptions = new Subscription[0]; - } - } - - /** - * Returns an array of {@link Subscription}s. - * - * @return an array of {@link Subscription}s - * @see org.apache.jackrabbit.webdav.property.DavProperty#getValue() - */ - public Subscription[] getValue() { - return subscriptions; - } - - /** - * Returns the Xml representation of the subscription discovery. - * - * @return Xml representation - * @see org.apache.jackrabbit.webdav.xml.XmlSerializable#toXml(Document) - * @param document - */ - @Override - public Element toXml(Document document) { - Element elem = getName().toXml(document); - for (Subscription subscription : subscriptions) { - elem.appendChild(subscription.toXml(document)); - } - return elem; - } - - //-----------------------------------------------------< static Factory >--- - public static SubscriptionDiscovery createFromXml(Element sDiscoveryElement) { - if (!DomUtil.matches(sDiscoveryElement, ObservationConstants.SUBSCRIPTIONDISCOVERY.getName(), ObservationConstants.SUBSCRIPTIONDISCOVERY.getNamespace())) { - throw new IllegalArgumentException("'subscriptiondiscovery' element expected."); - } - - List subscriptions = new ArrayList(); - ElementIterator it = DomUtil.getChildren(sDiscoveryElement, ObservationConstants.XML_SUBSCRIPTION, ObservationConstants.NAMESPACE); - while (it.hasNext()) { - final Element sb = it.nextElement(); - // anonymous inner class: Subscription interface - Subscription s = new Subscription() { - /** - * @see Subscription#getSubscriptionId() - */ - public String getSubscriptionId() { - Element ltEl = DomUtil.getChildElement(sb, ObservationConstants.XML_SUBSCRIPTIONID, ObservationConstants.NAMESPACE); - if (ltEl != null) { - return DomUtil.getChildText(sb, DavConstants.XML_HREF, DavConstants.NAMESPACE); - } - return null; - } - - public boolean eventsProvideNodeTypeInformation() { - String t = DomUtil.getChildText(sb, ObservationConstants.XML_EVENTSWITHTYPES, ObservationConstants.NAMESPACE); - return t == null ? false : Boolean.parseBoolean(t); - } - - public boolean eventsProvideNoLocalFlag() { - String t = DomUtil.getChildText(sb, ObservationConstants.XML_EVENTSWITHLOCALFLAG, ObservationConstants.NAMESPACE); - return t == null ? false : Boolean.parseBoolean(t); - } - - /** - * @see XmlSerializable#toXml(Document) - */ - public Element toXml(Document document) { - return (Element) document.importNode(sb, true); - } - }; - subscriptions.add(s); - } - - return new SubscriptionDiscovery(subscriptions.toArray(new Subscription[subscriptions.size()])); - } -} \ No newline at end of file Property changes on: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/observation/SubscriptionDiscovery.java ___________________________________________________________________ Deleted: svn Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/observation/SubscriptionInfo.java =================================================================== --- jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/observation/SubscriptionInfo.java (revision 1907912) +++ jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/observation/SubscriptionInfo.java (nonexistent) @@ -1,242 +0,0 @@ -/* - * 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.webdav.observation; - -import org.apache.jackrabbit.webdav.DavException; -import org.apache.jackrabbit.webdav.DavServletResponse; -import org.apache.jackrabbit.webdav.header.TimeoutHeader; -import org.apache.jackrabbit.webdav.header.DepthHeader; -import org.apache.jackrabbit.webdav.xml.DomUtil; -import org.apache.jackrabbit.webdav.xml.ElementIterator; -import org.apache.jackrabbit.webdav.xml.Namespace; -import org.apache.jackrabbit.webdav.xml.XmlSerializable; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.w3c.dom.Document; -import org.w3c.dom.Element; - -import java.util.ArrayList; -import java.util.List; - -/** - * SubscriptionInfo class encapsulates the subscription info - * that forms the request body of a SUBSCRIBE request.
- * The following xml layout is defined for the subscription info: - *
- * <!ELEMENT subscriptioninfo ( eventtype, nolocal?, filter? ) >
- * <!ELEMENT eventtype ANY >
- *
- * ANY defines any sequence of elements where at least one defines a valid
- * eventtype. Note that a single eventtype must not occur multiple times.
-
- * <!ELEMENT nolocal EMPTY >
- * <!ELEMENT filter ANY >
- *
- * ANY: any sequence of elements identifying a filter for event listening but
- * at least a single element.
- * 
- * @see ObservationConstants#XML_SUBSCRIPTIONINFO - */ -public class SubscriptionInfo implements ObservationConstants, XmlSerializable { - - private static Logger log = LoggerFactory.getLogger(SubscriptionInfo.class); - - private final EventType[] eventTypes; - private final Filter[] filters; - private final boolean noLocal; - private final boolean isDeep; - private final long timeout; - - /** - * Create a new SubscriptionInfo - * - * @param eventTypes - * @param isDeep - * @param timeout - */ - public SubscriptionInfo(EventType[] eventTypes, boolean isDeep, long timeout) { - this(eventTypes, null, false, isDeep, timeout); - } - - /** - * Create a new SubscriptionInfo - * - * @param eventTypes - * @param filters - * @param noLocal - * @param isDeep - * @param timeout - */ - public SubscriptionInfo(EventType[] eventTypes, Filter[] filters, boolean noLocal, boolean isDeep, long timeout) { - if (eventTypes == null || eventTypes.length == 0) { - throw new IllegalArgumentException("'subscriptioninfo' must at least indicate a single event type."); - } - - this.eventTypes = eventTypes; - this.noLocal = noLocal; - - if (filters != null) { - this.filters = filters; - } else { - this.filters = new Filter[0]; - } - - this.isDeep = isDeep; - this.timeout = timeout; - } - - /** - * Create a new SubscriptionInfo from the given Xml element - * and from additional information that is transported within the request - * header: - *
    - *
  • {@link TimeoutHeader timeout},
  • - *
  • {@link DepthHeader isDeep}
  • - *
- * @param reqInfo Xml element present in the request body. - * @param timeout as defined in the {@link org.apache.jackrabbit.webdav.DavConstants#HEADER_TIMEOUT timeout header}. - * @param isDeep as defined in the {@link org.apache.jackrabbit.webdav.DavConstants#HEADER_DEPTH depth header}. - * @throws IllegalArgumentException if the reqInfo element does not contain the mandatory elements. - */ - public SubscriptionInfo(Element reqInfo, long timeout, boolean isDeep) throws DavException { - if (!DomUtil.matches(reqInfo, XML_SUBSCRIPTIONINFO, NAMESPACE)) { - log.warn("Element with name 'subscriptioninfo' expected"); - throw new DavException(DavServletResponse.SC_BAD_REQUEST); - } - Element el = DomUtil.getChildElement(reqInfo, XML_EVENTTYPE, NAMESPACE); - if (el != null) { - eventTypes = DefaultEventType.createFromXml(el); - if (eventTypes.length == 0) { - log.warn("'subscriptioninfo' must at least indicate a single, valid event type."); - throw new DavException(DavServletResponse.SC_BAD_REQUEST); - } - } else { - log.warn("'subscriptioninfo' must contain an 'eventtype' child element."); - throw new DavException(DavServletResponse.SC_BAD_REQUEST); - } - - List filters = new ArrayList(); - el = DomUtil.getChildElement(reqInfo, XML_FILTER, NAMESPACE); - if (el != null) { - ElementIterator it = DomUtil.getChildren(el); - while (it.hasNext()) { - Filter f = new Filter(it.nextElement()); - filters.add(f); - } - } - this.filters = filters.toArray(new Filter[filters.size()]); - - this.noLocal = DomUtil.hasChildElement(reqInfo, XML_NOLOCAL, NAMESPACE); - this.isDeep = isDeep; - this.timeout = timeout; - } - - /** - * Return array of event type names present in the subscription info. - * - * @return array of String defining the names of the events this subscription - * should listen to. - * - */ - public EventType[] getEventTypes() { - return eventTypes; - } - - /** - * Return all filters defined for this SubscriptionInfo - * - * @return all filters or an empty Filter array. - */ - public Filter[] getFilters() { - return filters; - } - - /** - * Return array of filters with the specified name. - * - * @param localName the filter elements must provide. - * @param namespace - * @return array containing the text of the filter elements with the given - * name. - */ - public Filter[] getFilters(String localName, Namespace namespace) { - List l = new ArrayList(); - for (Filter filter : filters) { - if (filter.isMatchingFilter(localName, namespace)) { - l.add(filter); - } - } - return l.toArray(new Filter[l.size()]); - } - - /** - * Returns true if the {@link #XML_NOLOCAL} element is present in this - * subscription info. - * - * @return if {@link #XML_NOLOCAL} element is present. - */ - public boolean isNoLocal() { - return noLocal; - } - - /** - * Returns true if the {@link org.apache.jackrabbit.webdav.DavConstants#HEADER_DEPTH - * depths header} defined a depth other than '0'. - * - * @return true if this subscription info was created with isDeep - * true. - */ - public boolean isDeep() { - return isDeep; - } - - /** - * Return the timeout as retrieved from the request. - * - * @return timeout. - */ - public long getTimeOut() { - return timeout; - } - - /** - * Xml representation of this SubscriptionInfo. - * - * @return Xml representation - * @see org.apache.jackrabbit.webdav.xml.XmlSerializable#toXml(Document) - * @param document - */ - public Element toXml(Document document) { - Element subscrInfo = DomUtil.createElement(document, XML_SUBSCRIPTIONINFO, NAMESPACE); - Element eventType = DomUtil.addChildElement(subscrInfo, XML_EVENTTYPE, NAMESPACE); - for (EventType et : eventTypes) { - eventType.appendChild(et.toXml(document)); - } - - if (filters.length > 0) { - Element filter = DomUtil.addChildElement(subscrInfo, XML_FILTER, NAMESPACE); - for (Filter f : filters) { - filter.appendChild(f.toXml(document)); - } - } - - if (noLocal) { - DomUtil.addChildElement(subscrInfo, XML_NOLOCAL, NAMESPACE); - } - return subscrInfo; - } -} Property changes on: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/observation/SubscriptionInfo.java ___________________________________________________________________ Deleted: svn Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/observation/SubscriptionManager.java =================================================================== --- jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/observation/SubscriptionManager.java (revision 1907912) +++ jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/observation/SubscriptionManager.java (nonexistent) @@ -1,69 +0,0 @@ -/* - * 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.webdav.observation; - -import org.apache.jackrabbit.webdav.DavException; - -/** - * SubscriptionManager interface. - */ -public interface SubscriptionManager { - - /** - * Retrieve the {@link org.apache.jackrabbit.webdav.observation.SubscriptionDiscovery} object for the given - * resource. Note, that the discovery object will be empty if there are - * no subscriptions present. - * - * @param resource - */ - public SubscriptionDiscovery getSubscriptionDiscovery(ObservationResource resource); - - /** - * Create a new Subscription or update an existing Subscription.. - * - * @param info - * @param subscriptionId - * @param resource - * @return Subscription that has been created or updated - * @throws DavException if the subscription fails - */ - public Subscription subscribe(SubscriptionInfo info, String subscriptionId, - ObservationResource resource) - throws DavException; - - /** - * Unsubscribe the Subscription with the given id. - * - * @param subscriptionId - * @param resource - * @throws DavException - */ - public void unsubscribe(String subscriptionId, ObservationResource resource) - throws DavException; - - /** - * Retrieve the list of events that occurred since the last poll. - * - * @param subscriptionId identifier for the subscription - * @param timeout the time in milliseconds to wait at most for events - * if none is present currently. - * @param resource - * @return - */ - public EventDiscovery poll(String subscriptionId, long timeout, ObservationResource resource) - throws DavException; -} \ No newline at end of file Property changes on: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/observation/SubscriptionManager.java ___________________________________________________________________ Deleted: svn Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/observation/package-info.java =================================================================== --- jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/observation/package-info.java (revision 1907912) +++ jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/observation/package-info.java (nonexistent) @@ -1,18 +0,0 @@ -/* - * 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. - */ -@org.osgi.annotation.versioning.Version("1.1.0") -package org.apache.jackrabbit.webdav.observation; Property changes on: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/observation/package-info.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/ordering/OrderPatch.java =================================================================== --- jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/ordering/OrderPatch.java (revision 1907912) +++ jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/ordering/OrderPatch.java (nonexistent) @@ -1,212 +0,0 @@ -/* - * 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.webdav.ordering; - -import org.apache.jackrabbit.webdav.DavConstants; -import org.apache.jackrabbit.webdav.DavException; -import org.apache.jackrabbit.webdav.DavServletResponse; -import org.apache.jackrabbit.webdav.xml.DomUtil; -import org.apache.jackrabbit.webdav.xml.ElementIterator; -import org.apache.jackrabbit.webdav.xml.XmlSerializable; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.w3c.dom.Document; -import org.w3c.dom.Element; - -import java.util.ArrayList; -import java.util.List; - -/** - * OrderPatch represents the mandatory request body of an - * ORDERPATCH request. RFC 3648 defines the following structure for it:
- *
- * <!ELEMENT orderpatch (ordering-type?, order-member*) >
- * <!ELEMENT order-member (segment, position) >
- * <!ELEMENT position (first | last | before | after) >
- * <!ELEMENT segment (#PCDATA) >
- * <!ELEMENT first EMPTY >
- * <!ELEMENT last EMPTY >
- * <!ELEMENT before segment >
- * <!ELEMENT after segment >
- * 
- */ -public class OrderPatch implements OrderingConstants, XmlSerializable { - - private static Logger log = LoggerFactory.getLogger(OrderPatch.class); - - private Member[] instructions; - private String orderingType; - - /** - * Create a new OrderPath object. - * - * @param orderingType - * @param instruction - */ - public OrderPatch(String orderingType, Member instruction) { - this(orderingType, new Member[] {instruction}); - } - - /** - * Create a new OrderPath object. - * - * @param orderingType - * @param instructions - */ - public OrderPatch(String orderingType, Member[] instructions) { - if (orderingType == null || instructions == null) { - throw new IllegalArgumentException("ordering type and instructions cannot be null."); - } - this.orderingType = orderingType; - this.instructions = instructions; - } - - /** - * Return the ordering type. - * - * @return ordering type - */ - public String getOrderingType() { - return orderingType; - } - - /** - * Return an array of {@link Member} objects defining the re-ordering - * instructions to be applied to the requested resource. - * - * @return ordering instructions. - */ - public Member[] getOrderInstructions() { - return instructions; - } - - //------------------------------------------< XmlSerializable interface >--- - /** - * - * @return - * @param document - */ - public Element toXml(Document document) { - Element orderPatch = DomUtil.createElement(document, XML_ORDERPATCH, NAMESPACE); - // add DAV:ordering-type below DAV:orderpatch - Element otype = DomUtil.addChildElement(orderPatch, XML_ORDERING_TYPE, NAMESPACE); - otype.appendChild(DomUtil.hrefToXml(orderingType, document)); - // add DAV:member elements below DAV:orderpatch - for (Member instruction : instructions) { - orderPatch.appendChild(instruction.toXml(document)); - } - return orderPatch; - } - - //------------------------------------------------------< static method >--- - /** - * Create a new OrderPath object. - * - * @param orderPatchElement - * @throws IllegalArgumentException if the specified Xml element was not valid. - */ - public static OrderPatch createFromXml(Element orderPatchElement) throws DavException { - if (!DomUtil.matches(orderPatchElement, XML_ORDERPATCH, NAMESPACE)) { - log.warn("ORDERPATH request body must start with an 'orderpatch' element."); - throw new DavException(DavServletResponse.SC_BAD_REQUEST); - } - - // retrieve the href of the orderingtype element - String orderingType; - Element otype = DomUtil.getChildElement(orderPatchElement, XML_ORDERING_TYPE, NAMESPACE); - if (otype != null) { - orderingType = DomUtil.getChildText(otype, DavConstants.XML_HREF, DavConstants.NAMESPACE); - } else { - log.warn("ORDERPATH request body must contain an 'ordering-type' child element."); - throw new DavException(DavServletResponse.SC_BAD_REQUEST); - } - - // set build the list of ordering instructions - List tmpList = new ArrayList(); - ElementIterator it = DomUtil.getChildren(orderPatchElement, XML_ORDER_MEMBER, NAMESPACE); - while (it.hasNext()) { - Element el = it.nextElement(); - try { - // retrieve text 'DAV:segment' child of this DAV:order-member element - String segment = DomUtil.getChildText(el, XML_SEGMENT, NAMESPACE); - // retrieve the 'DAV:position' child element - Position pos = Position.createFromXml(DomUtil.getChildElement(el, XML_POSITION, NAMESPACE)); - Member om = new Member(segment, pos); - tmpList.add(om); - } catch (IllegalArgumentException e) { - log.warn("Invalid element in 'orderpatch' request body: " + e.getMessage()); - throw new DavException(DavServletResponse.SC_BAD_REQUEST); - } - } - Member[] instructions = tmpList.toArray(new Member[tmpList.size()]); - return new OrderPatch(orderingType, instructions); - } - - //-------------------------------------------------------------------------- - /** - * Internal class Member represents the 'Order-Member' children - * elements of an 'OrderPatch' request body present in the ORDERPATCH request. - */ - public static class Member implements XmlSerializable { - - private String memberHandle; - private Position position; - - /** - * Create a new Member object. - * - * @param memberHandle - * @param position - */ - public Member(String memberHandle, Position position) { - this.memberHandle = memberHandle; - this.position = position; - } - - /** - * Return the handle of the internal member to be reordered. - * - * @return handle of the internal member. - */ - public String getMemberHandle() { - return memberHandle; - } - - /** - * Return the position where the internal member identified by the - * member handle should be placed. - * - * @return position for the member after the request. - * @see #getMemberHandle() - */ - public Position getPosition() { - return position; - } - - //--------------------------------------< XmlSerializable interface >--- - /** - * @see org.apache.jackrabbit.webdav.xml.XmlSerializable#toXml(Document) - */ - public Element toXml(Document document) { - Element memberElem = DomUtil.createElement(document, XML_ORDER_MEMBER, NAMESPACE); - DomUtil.addChildElement(memberElem, XML_SEGMENT, NAMESPACE, memberHandle); - memberElem.appendChild(position.toXml(document)); - return memberElem; - } - - } -} Property changes on: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/ordering/OrderPatch.java ___________________________________________________________________ Deleted: svn Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/ordering/OrderingConstants.java =================================================================== --- jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/ordering/OrderingConstants.java (revision 1907912) +++ jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/ordering/OrderingConstants.java (nonexistent) @@ -1,106 +0,0 @@ -/* - * 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.webdav.ordering; - -import org.apache.jackrabbit.webdav.DavConstants; -import org.apache.jackrabbit.webdav.property.DavPropertyName; -import org.apache.jackrabbit.webdav.xml.Namespace; - -/** - * OrderingConstants provide constants for request and response - * headers, Xml elements and property names defined by - * RFC 3648. - */ -public interface OrderingConstants { - - /** - * The namespace - */ - public static final Namespace NAMESPACE = DavConstants.NAMESPACE; - - /** - * Constant representing the DAV:custom ordering type URI, which indicates - * that the collection is not ordered. - */ - public static final String ORDERING_TYPE_CUSTOM = "DAV:custom"; - - /** - * Constant representing the DAV:unordered ordering type URI, which indicates - * that the collection is to be ordered, but the semantics of the ordering - * is not being advertised. - */ - public static final String ORDERING_TYPE_UNORDERED = "DAV:unordered"; - - //---< Headers >------------------------------------------------------------ - /** - * The "Ordering-Type" request header. - */ - public static final String HEADER_ORDERING_TYPE = "Ordering-Type"; - - /** - * When a new member is added to a collection with a client-maintained - * ordering (for example, with PUT, COPY, or MKCOL), its position in the - * ordering can be set with the new Position header.

- * - * Position = "Position" ":" ("first" | "last" | (("before" | "after") segment)) - * - *

NOTE: segment is defined in section 3.3 of RFC2396. - */ - public static final String HEADER_POSITION = "Position"; - - //---< XML Element, Attribute Names >--------------------------------------- - /** - * Xml elements used for reordering internal members of a collection. - */ - public static final String XML_ORDERPATCH = "orderpatch"; - public static final String XML_ORDERING_TYPE = "ordering-type"; - public static final String XML_ORDER_MEMBER = "order-member"; - public static final String XML_POSITION = "position"; - public static final String XML_SEGMENT = "segment"; - - public static final String XML_FIRST = "first"; - public static final String XML_LAST = "last"; - public static final String XML_BEFORE = "before"; - public static final String XML_AFTER = "after"; - - //---< XML Element, Attribute Names >--------------------------------------- - /** - * The DAV:ordering-type property indicates whether the collection is - * ordered and, if so, uniquely identifies the semantics of the ordering. - * - * @see OrderingType - */ - public static final DavPropertyName ORDERING_TYPE = DavPropertyName.create("ordering-type", DavConstants.NAMESPACE); - - /** - * Required live property for resources that honor the 'ordered-collections' - * compliance class defined by RFC 3648.
- * The supported-method-set property has been introduced with RFC 3253. - * - * @see org.apache.jackrabbit.webdav.version.DeltaVConstants#SUPPORTED_METHOD_SET - */ - public static final DavPropertyName SUPPORTED_METHOD_SET = DavPropertyName.create("supported-method-set", DavConstants.NAMESPACE); - - /** - * Required live property for resources that honor the 'ordered-collections' - * compliance class defined by RFC 3648.
- * The supported-live-property-set property has been introduced with RFC 3253. - * - * @see org.apache.jackrabbit.webdav.version.DeltaVConstants#SUPPORTED_LIVE_PROPERTY_SET - */ - public static final DavPropertyName SUPPORTED_LIVE_PROPERTY_SET = DavPropertyName.create("supported-live-property-set", DavConstants.NAMESPACE); -} \ No newline at end of file Property changes on: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/ordering/OrderingConstants.java ___________________________________________________________________ Deleted: svn Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/ordering/OrderingDavServletRequest.java =================================================================== --- jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/ordering/OrderingDavServletRequest.java (revision 1907912) +++ jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/ordering/OrderingDavServletRequest.java (nonexistent) @@ -1,55 +0,0 @@ -/* - * 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.webdav.ordering; - -import org.apache.jackrabbit.webdav.DavException; -import org.apache.jackrabbit.webdav.DavServletRequest; - -/** - * OrderingDavServletRequest provides extensions to the - * {@link DavServletRequest} interface used for ordering members of orderable - * collections. - */ -public interface OrderingDavServletRequest extends DavServletRequest { - - /** - * Returns the {@link OrderingConstants#HEADER_ORDERING_TYPE Ordering-Type header}. - * - * @return the String value of the {@link OrderingConstants#HEADER_ORDERING_TYPE Ordering-Type header}. - */ - public String getOrderingType(); - - /** - * Return a Position object encapsulating the {@link OrderingConstants#HEADER_POSITION - * Position header} field or null if no Position header is present - * or does not contain a valid format. - * - * @return Position object encapsulating the {@link OrderingConstants#HEADER_POSITION - * Position header} - */ - public Position getPosition(); - - /** - * Return a OrderPatch object encapsulating the request body - * of an ORDERPATCH request or null if the request body was - * either missing or could not be parsed. - * - * @return OrderPatch object encapsulating the request body. - */ - public OrderPatch getOrderPatch() throws DavException; - -} \ No newline at end of file Property changes on: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/ordering/OrderingDavServletRequest.java ___________________________________________________________________ Deleted: svn Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/ordering/OrderingResource.java =================================================================== --- jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/ordering/OrderingResource.java (revision 1907912) +++ jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/ordering/OrderingResource.java (nonexistent) @@ -1,47 +0,0 @@ -/* - * 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.webdav.ordering; - -import org.apache.jackrabbit.webdav.DavException; -import org.apache.jackrabbit.webdav.DavResource; - -/** - * OrderingResource extends the {@link DavResource} interface by - * METHODS relating to ordering functionality defined by - * RFC 3648. - */ -public interface OrderingResource extends DavResource { - - public String METHODS = "ORDERPATCH"; - - /** - * Returns true if this resources allows ordering of its internal members. - * - * @return true if internal members are orderable. - */ - public boolean isOrderable(); - - /** - * Reorders the internal members of this resource according to the - * instructions present in the specified {@link OrderPatch} object. - * - * @param orderPatch as present in the ORDERPATCH request body. - * @throws DavException - */ - public void orderMembers(OrderPatch orderPatch) throws DavException; - -} \ No newline at end of file Property changes on: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/ordering/OrderingResource.java ___________________________________________________________________ Deleted: svn Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/ordering/OrderingType.java =================================================================== --- jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/ordering/OrderingType.java (revision 1907912) +++ jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/ordering/OrderingType.java (nonexistent) @@ -1,52 +0,0 @@ -/* - * 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.webdav.ordering; - -import org.apache.jackrabbit.webdav.property.HrefProperty; - -/** - * OrderingType represents the {@link #ORDERING_TYPE - * DAV:ordering-type} property as defined by - * RFC 3648. This property is - * protected cannot be set using PROPPATCH. Its value may only be set by - * including the Ordering-Type header with a MKCOL request or by submitting an - * ORDERPATCH request. - * - * @see org.apache.jackrabbit.webdav.property.DavProperty#isInvisibleInAllprop() - */ -public class OrderingType extends HrefProperty implements OrderingConstants { - - /** - * Creates a OrderingType with the default type (e.g. default - * value). The default value is specified to be {@link #ORDERING_TYPE_UNORDERED}. - */ - public OrderingType() { - this(null); - } - - /** - * Create an OrderingType with the given ordering.
- * NOTE: the ordering-type property is defined to be protected. - * - * @param href - * @see org.apache.jackrabbit.webdav.property.DavProperty#isInvisibleInAllprop() - */ - public OrderingType(String href) { - // spec requires that the default value is 'DAV:unordered' - super(ORDERING_TYPE, (href != null) ? href : ORDERING_TYPE_UNORDERED, true); - } -} Property changes on: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/ordering/OrderingType.java ___________________________________________________________________ Deleted: svn Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/ordering/Position.java =================================================================== --- jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/ordering/Position.java (revision 1907912) +++ jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/ordering/Position.java (nonexistent) @@ -1,164 +0,0 @@ -/* - * 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.webdav.ordering; - -import org.apache.jackrabbit.webdav.xml.DomUtil; -import org.apache.jackrabbit.webdav.xml.ElementIterator; -import org.apache.jackrabbit.webdav.xml.XmlSerializable; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.w3c.dom.Document; -import org.w3c.dom.Element; - -import java.util.HashSet; -import java.util.Set; - -/** - * Position encapsulates the position in ordering information - * contained in a Webdav request. This includes both the - * {@link OrderingConstants#HEADER_POSITION Position header} and the position - * Xml element present in the request body of an ORDERPATCH request. - * - * @see OrderingConstants#HEADER_POSITION - * @see OrderingConstants#XML_POSITION - * @see OrderPatch - */ -public class Position implements OrderingConstants, XmlSerializable { - - private static Logger log = LoggerFactory.getLogger(Position.class); - - private static final Set VALID_TYPES = new HashSet(); - static { - VALID_TYPES.add(XML_FIRST); - VALID_TYPES.add(XML_LAST); - VALID_TYPES.add(XML_AFTER); - VALID_TYPES.add(XML_BEFORE); - } - - private final String type; - private final String segment; - - /** - * Create a new Position object with the specified type. - * Since any type except for {@link #XML_FIRST first} and {@link #XML_LAST last} - * must be combined with a segment, only the mentioned types are valid - * arguments. - * - * @param type {@link #XML_FIRST first} or {@link #XML_LAST last} - * @throws IllegalArgumentException if the given type is other than {@link #XML_FIRST} - * or {@link #XML_LAST}. - */ - public Position(String type) { - if (!VALID_TYPES.contains(type)) { - throw new IllegalArgumentException("Invalid type: " + type); - } - if (!(XML_FIRST.equals(type) || XML_LAST.equals(type))) { - throw new IllegalArgumentException("If type is other than 'first' or 'last' a segment must be specified"); - } - this.type = type; - this.segment = null; - } - - /** - * Create a new Position object with the specified type and - * segment. - * - * @param type - * @param segment - * @throws IllegalArgumentException if the specified type and segment do not - * form a valid pair. - */ - public Position(String type, String segment) { - if (!VALID_TYPES.contains(type)) { - throw new IllegalArgumentException("Invalid type: " + type); - } - if ((XML_AFTER.equals(type) || XML_BEFORE.equals(type)) && (segment == null || "".equals(segment))) { - throw new IllegalArgumentException("If type is other than 'first' or 'last' a segment must be specified"); - } - this.type = type; - this.segment = segment; - } - - /** - * Return the type of this Position object, which may be any - * of the following valid types: {@link #XML_FIRST first}, - * {@link #XML_LAST last}, {@link #XML_AFTER after}, {@link #XML_BEFORE before} - * - * @return type - */ - public String getType() { - return type; - } - - /** - * Returns the segment used to create this Position object or - * null if no segment is present with the type. - * - * @return segment or null - * @see #getType() - */ - public String getSegment() { - return segment; - } - - //------------------------------------------< XmlSerializable interface >--- - /** - * @see org.apache.jackrabbit.webdav.xml.XmlSerializable#toXml(Document) - * @param document - */ - public Element toXml(Document document) { - Element positionElement = DomUtil.createElement(document, XML_POSITION, NAMESPACE); - Element typeElement = DomUtil.addChildElement(positionElement, type, NAMESPACE); - if (segment != null) { - DomUtil.addChildElement(typeElement, XML_SEGMENT, NAMESPACE, segment); - } - return positionElement; - } - - //-----------------------------------------------------< static methods >--- - /** - * Create a new Position object from the specified position - * element. The element must fulfill the following structure:
- *
-     * <!ELEMENT position (first | last | before | after) >
-     * <!ELEMENT segment (#PCDATA) >
-     * <!ELEMENT first EMPTY >
-     * <!ELEMENT last EMPTY >
-     * <!ELEMENT before segment >
-     * <!ELEMENT after segment >
-     * 
- * - * @param positionElement Xml element defining the position. - * @throws IllegalArgumentException if the given Xml element is not valid. - */ - public static Position createFromXml(Element positionElement) { - if (!DomUtil.matches(positionElement, XML_POSITION, NAMESPACE)) { - throw new IllegalArgumentException("The 'DAV:position' element required."); - } - ElementIterator it = DomUtil.getChildren(positionElement); - if (it.hasNext()) { - Element el = it.nextElement(); - String type = el.getLocalName(); - // read the text of DAV:segment child element inside the type - String segmentText = DomUtil.getChildText(el, XML_SEGMENT, NAMESPACE); - // stop after the first iteration - return new Position(type, segmentText); - } else { - throw new IllegalArgumentException("The 'DAV:position' element required with exact one child indicating the type."); - } - } -} Property changes on: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/ordering/Position.java ___________________________________________________________________ Deleted: svn Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/ordering/package-info.java =================================================================== --- jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/ordering/package-info.java (revision 1907912) +++ jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/ordering/package-info.java (nonexistent) @@ -1,18 +0,0 @@ -/* - * 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. - */ -@org.osgi.annotation.versioning.Version("1.0.0") -package org.apache.jackrabbit.webdav.ordering; Property changes on: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/ordering/package-info.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/package-info.java =================================================================== --- jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/package-info.java (revision 1907912) +++ jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/package-info.java (nonexistent) @@ -1,18 +0,0 @@ -/* - * 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. - */ -@org.osgi.annotation.versioning.Version("1.4.0") -package org.apache.jackrabbit.webdav; Property changes on: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/package-info.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/property/AbstractDavProperty.java =================================================================== --- jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/property/AbstractDavProperty.java (revision 1907912) +++ jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/property/AbstractDavProperty.java (nonexistent) @@ -1,163 +0,0 @@ -/* - * 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.webdav.property; - -import org.apache.jackrabbit.webdav.DavConstants; -import org.apache.jackrabbit.webdav.xml.DomUtil; -import org.apache.jackrabbit.webdav.xml.XmlSerializable; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.w3c.dom.Document; -import org.w3c.dom.Element; -import org.w3c.dom.Node; - -import java.util.Collection; - -/** - * AbstractDavProperty provides generic METHODS used by various - * implementations of the {@link DavProperty} interface. - */ -public abstract class AbstractDavProperty implements DavProperty { - - private static Logger log = LoggerFactory.getLogger(AbstractDavProperty.class); - - private final DavPropertyName name; - private final boolean isInvisibleInAllprop; - - /** - * Create a new AbstractDavProperty with the given {@link DavPropertyName} - * and a boolean flag indicating whether this property should be suppressed - * in PROPFIND/allprop responses. - */ - public AbstractDavProperty(DavPropertyName name, boolean isInvisibleInAllprop) { - this.name = name; - this.isInvisibleInAllprop = isInvisibleInAllprop; - } - - /** - * Computes the hash code using this property's name and value. - * - * @return the hash code - */ - @Override - public int hashCode() { - int hashCode = getName().hashCode(); - if (getValue() != null) { - hashCode += getValue().hashCode(); - } - return hashCode % Integer.MAX_VALUE; - } - - /** - * Checks if this property has the same {@link DavPropertyName name} - * and value as the given one. - * - * @param obj the object to compare to - * @return true if the 2 objects are equal; - * false otherwise - */ - @Override - public boolean equals(Object obj) { - if (obj instanceof DavProperty) { - DavProperty prop = (DavProperty) obj; - boolean equalName = getName().equals(prop.getName()); - boolean equalValue = (getValue() == null) ? prop.getValue() == null : getValue().equals(prop.getValue()); - return equalName && equalValue; - } - return false; - } - - - /** - * Return a XML element representation of this property. The value of the - * property will be added as text or as child element. - *
-     * new DavProperty("displayname", "WebDAV Directory").toXml
-     * gives a element like:
-     * <D:displayname>WebDAV Directory</D:displayname>
-     *
-     * new DavProperty("resourcetype", new Element("collection")).toXml
-     * gives a element like:
-     * <D:resourcetype><D:collection/></D:resourcetype>
-     *
-     * Element[] customVals = { new Element("bla", customNamespace), new Element("bli", customNamespace) };
-     * new DavProperty("custom-property", customVals, customNamespace).toXml
-     * gives an element like
-     * <Z:custom-property>
-     *    <Z:bla/>
-     *    <Z:bli/>
-     * </Z:custom-property>
-     * 
- * - * @return a XML element of this property - * @see org.apache.jackrabbit.webdav.xml.XmlSerializable#toXml(Document) - * @param document - */ - public Element toXml(Document document) { - Element elem = getName().toXml(document); - T value = getValue(); - // todo: improve.... - if (value != null) { - if (value instanceof XmlSerializable) { - elem.appendChild(((XmlSerializable)value).toXml(document)); - } else if (value instanceof Node) { - Node n = document.importNode((Node)value, true); - elem.appendChild(n); - } else if (value instanceof Node[]) { - for (int i = 0; i < ((Node[])value).length; i++) { - Node n = document.importNode(((Node[])value)[i], true); - elem.appendChild(n); - } - } else if (value instanceof Collection) { - for (Object entry : ((Collection) value)) { - if (entry instanceof XmlSerializable) { - elem.appendChild(((XmlSerializable) entry).toXml(document)); - } else if (entry instanceof Node) { - Node n = document.importNode((Node) entry, true); - elem.appendChild(n); - } else { - DomUtil.setText(elem, entry.toString()); - } - } - } else { - DomUtil.setText(elem, value.toString()); - } - } - return elem; - } - - /** - * Returns the name of this property. - * - * @return name - * @see DavProperty#getName() - */ - public DavPropertyName getName() { - return name; - } - - /** - * Return true if this property should be suppressed - * in a PROPFIND/{@link DavConstants#PROPFIND_ALL_PROP DAV:allprop} - * response. See RFC 4918, Section 9.1. - * - * @see org.apache.jackrabbit.webdav.property.DavProperty#isInvisibleInAllprop() - */ - public boolean isInvisibleInAllprop() { - return isInvisibleInAllprop; - } -} Property changes on: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/property/AbstractDavProperty.java ___________________________________________________________________ Deleted: svn Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/property/DavProperty.java =================================================================== --- jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/property/DavProperty.java (revision 1907912) +++ jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/property/DavProperty.java (nonexistent) @@ -1,71 +0,0 @@ -/* - * 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.webdav.property; - -import org.apache.jackrabbit.webdav.DavConstants; -import org.apache.jackrabbit.webdav.xml.XmlSerializable; - -/** - * The Property class represents a Property of a WebDAV - * resource. The {@link Object#hashCode()} and {@link Object#equals(Object)} methods are - * overridden in a way, such that the name and value of the property are - * respected. This means, a property is equal to another if the names - * and values are equal.
- * The XML representation of a DavProperty: - *
- * new DavProperty("displayname", "WebDAV Directory").toXml
- * gives a element like:
- * <D:displayname>WebDAV Directory</D:displayname>
- *
- * new DavProperty("resourcetype", new Element("collection")).toXml
- * gives a element like:
- * <D:resourcetype><D:collection/></D:resourcetype>
- *
- * Element[] customVals = { new Element("bla", customNamespace), new Element("bli", customNamespace) };
- * new DavProperty("custom-property", customVals, customNamespace).toXml
- * gives an element like
- * <Z:custom-property>
- *    <Z:bla/>
- *    <Z:bli/>
- * </Z:custom-property>
- * 
- */ -public interface DavProperty extends XmlSerializable, DavConstants, PropEntry { - - /** - * Returns the name of this property - * - * @return the name of this property - */ - public DavPropertyName getName(); - - /** - * Returns the value of this property - * - * @return the value of this property - */ - public T getValue(); - - /** - * Return true if this property should be suppressed - * in a PROPFIND/{@link DavConstants#PROPFIND_ALL_PROP DAV:allprop} - * response. See RFC 4918, Section 9.1. - * - * @return true, if this property should be suppressed in a PROPFIND/allprop response - */ - public boolean isInvisibleInAllprop(); -} Property changes on: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/property/DavProperty.java ___________________________________________________________________ Deleted: svn Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/property/DavPropertyIterator.java =================================================================== --- jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/property/DavPropertyIterator.java (revision 1907912) +++ jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/property/DavPropertyIterator.java (nonexistent) @@ -1,34 +0,0 @@ -/* - * 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.webdav.property; - -import java.util.Iterator; -import java.util.NoSuchElementException; - -/** - * The DavPropertyIterator extends the Iterator by - * a property specific next() method. - */ -public interface DavPropertyIterator extends Iterator> { - /** - * Returns the next Property. - * - * @return the next Property in the iteration. - * @throws java.util.NoSuchElementException if iteration has no more elements. - */ - public DavProperty nextProperty() throws NoSuchElementException; -} Property changes on: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/property/DavPropertyIterator.java ___________________________________________________________________ Deleted: svn Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/property/DavPropertyName.java =================================================================== --- jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/property/DavPropertyName.java (revision 1907912) +++ jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/property/DavPropertyName.java (nonexistent) @@ -1,206 +0,0 @@ -/* - * 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.webdav.property; - -import org.apache.jackrabbit.webdav.DavConstants; -import org.apache.jackrabbit.webdav.xml.DomUtil; -import org.apache.jackrabbit.webdav.xml.Namespace; -import org.apache.jackrabbit.webdav.xml.XmlSerializable; -import org.w3c.dom.Document; -import org.w3c.dom.Element; - -import java.util.HashMap; -import java.util.Map; - -/** - * The DavPropertyName class reflects a WebDAV property name. It - * holds together the local name of the property and its namespace. - */ -public class DavPropertyName implements DavConstants, XmlSerializable, PropEntry { - - /** internal 'cache' of created property names */ - private static final Map> cache = new HashMap>(); - - /* some standard webdav property (that have #PCDATA) */ - public static final DavPropertyName CREATIONDATE = DavPropertyName.create(PROPERTY_CREATIONDATE); - public static final DavPropertyName DISPLAYNAME = DavPropertyName.create(PROPERTY_DISPLAYNAME); - public static final DavPropertyName GETCONTENTLANGUAGE = DavPropertyName.create(PROPERTY_GETCONTENTLANGUAGE); - public static final DavPropertyName GETCONTENTLENGTH = DavPropertyName.create(PROPERTY_GETCONTENTLENGTH); - public static final DavPropertyName GETCONTENTTYPE = DavPropertyName.create(PROPERTY_GETCONTENTTYPE); - public static final DavPropertyName GETETAG = DavPropertyName.create(PROPERTY_GETETAG); - public static final DavPropertyName GETLASTMODIFIED = DavPropertyName.create(PROPERTY_GETLASTMODIFIED); - - /* some standard webdav property (that have other elements) */ - public static final DavPropertyName LOCKDISCOVERY = DavPropertyName.create(PROPERTY_LOCKDISCOVERY); - public static final DavPropertyName RESOURCETYPE = DavPropertyName.create(PROPERTY_RESOURCETYPE); - public static final DavPropertyName SOURCE = DavPropertyName.create(PROPERTY_SOURCE); - public static final DavPropertyName SUPPORTEDLOCK = DavPropertyName.create(PROPERTY_SUPPORTEDLOCK); - - /* property use by microsoft that are not specified in the RFC 2518 */ - public static final DavPropertyName ISCOLLECTION = DavPropertyName.create("iscollection"); - - /** the name of the property */ - private final String name; - - /** the namespace of the property */ - private final Namespace namespace; - - /** - * Creates a new DavPropertyName with the given name and - * Namespace. - * - * @param name The local name of the new property name - * @param namespace The namespace of the new property name - * - * @return The WebDAV property name - */ - public synchronized static DavPropertyName create(String name, Namespace namespace) { - - // get (or create) map for the given namespace - Map map = cache.get(namespace); - if (map == null) { - map = new HashMap(); - cache.put(namespace, map); - } - // get (or create) property name object - DavPropertyName ret = map.get(name); - if (ret == null) { - if (namespace.equals(NAMESPACE)) { - // ensure prefix for default 'DAV:' namespace - namespace = NAMESPACE; - } - ret = new DavPropertyName(name, namespace); - map.put(name, ret); - } - return ret; - } - - /** - * Creates a new DavPropertyName with the given local name - * and the default WebDAV {@link DavConstants#NAMESPACE namespace}. - * - * @param name The local name of the new property name - * - * @return The WebDAV property name - */ - public synchronized static DavPropertyName create(String name) { - return create(name, NAMESPACE); - } - - /** - * Create a new DavPropertyName with the name and namespace - * of the given Xml element. - * - * @param nameElement - * @return DavPropertyName instance - */ - public synchronized static DavPropertyName createFromXml(Element nameElement) { - if (nameElement == null) { - throw new IllegalArgumentException("Cannot build DavPropertyName from a 'null' element."); - } - String ns = nameElement.getNamespaceURI(); - if (ns == null) { - return create(nameElement.getLocalName(), Namespace.EMPTY_NAMESPACE); - } else { - return create(nameElement.getLocalName(), Namespace.getNamespace(nameElement.getPrefix(), ns)); - } - } - - /** - * Creates a new DavPropertyName with the given name and - * Namespace. - * - * @param name The local name of the new property name - * @param namespace The namespace of the new property name - */ - private DavPropertyName(String name, Namespace namespace) { - if (name == null || namespace == null) { - throw new IllegalArgumentException("Name and namespace must not be 'null' for a DavPropertyName."); - } - this.name = name; - this.namespace = namespace; - } - - /** - * Return the name of this DavPropertyName. - * - * @return name - */ - public String getName() { - return name; - } - - /** - * Return the namespace of this DavPropertyName. - * - * @return namespace - */ - public Namespace getNamespace() { - return namespace; - } - - /** - * Computes the hash code using this properties name and namespace. - * - * @return the hash code - */ - @Override - public int hashCode() { - return (name.hashCode() + namespace.hashCode()) % Integer.MAX_VALUE; - } - - /** - * Checks if this property has the same name and namespace as the - * given one. - * - * @param obj the object to compare to - * - * @return true if the 2 objects are equal; - * false otherwise - */ - @Override - public boolean equals(Object obj) { - if (obj instanceof DavPropertyName) { - DavPropertyName propName = (DavPropertyName) obj; - return name.equals(propName.name) && namespace.equals(propName.namespace); - } - return false; - } - - /** - * Returns a string representation of this property suitable for debugging - * - * @return a human readable string representation - */ - @Override - public String toString() { - return DomUtil.getExpandedName(name, namespace); - } - - /** - * Creates a element with the name and namespace of this - * DavPropertyName. - * - * @return A element with the name and namespace of this - * DavPropertyName. - * @param document - */ - public Element toXml(Document document) { - return DomUtil.createElement(document, name, namespace); - } -} - Property changes on: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/property/DavPropertyName.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/property/DavPropertyNameIterator.java =================================================================== --- jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/property/DavPropertyNameIterator.java (revision 1907912) +++ jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/property/DavPropertyNameIterator.java (nonexistent) @@ -1,28 +0,0 @@ -/* - * 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.webdav.property; - -import java.util.Iterator; - -/** - * DavPropertyNameIterator... - */ -public interface DavPropertyNameIterator extends Iterator { - - public DavPropertyName nextPropertyName(); - -} Property changes on: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/property/DavPropertyNameIterator.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Deleted: svn:keywords ## -1 +0,0 ## -author date id revision url \ No newline at end of property Index: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/property/DavPropertyNameSet.java =================================================================== --- jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/property/DavPropertyNameSet.java (revision 1907912) +++ jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/property/DavPropertyNameSet.java (nonexistent) @@ -1,203 +0,0 @@ -/* - * 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.webdav.property; - -import org.apache.jackrabbit.webdav.xml.DomUtil; -import org.apache.jackrabbit.webdav.xml.ElementIterator; -import org.apache.jackrabbit.webdav.xml.Namespace; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.w3c.dom.Element; - -import java.util.Collection; -import java.util.HashSet; -import java.util.Iterator; -import java.util.Set; - -/** - * DavPropertyNameSet represents a Set of {@link DavPropertyName} - * objects. - */ -public class DavPropertyNameSet extends PropContainer - implements Iterable { - - private static Logger log = LoggerFactory.getLogger(DavPropertyNameSet.class); - private final Set set = new HashSet(); - - /** - * Create a new empty set. - */ - public DavPropertyNameSet() { - } - - /** - * Create a new DavPropertyNameSet with the given initial values. - * - * @param initialSet - */ - public DavPropertyNameSet(DavPropertyNameSet initialSet) { - addAll(initialSet); - } - - /** - * Create a new DavPropertyNameSet from the given DAV:prop - * element. - * - * @param propElement - * @throws IllegalArgumentException if the specified element is null - * or is not a DAV:prop element. - */ - public DavPropertyNameSet(Element propElement) { - if (!DomUtil.matches(propElement, XML_PROP, NAMESPACE)) { - throw new IllegalArgumentException("'DAV:prop' element expected."); - } - - // fill the set - ElementIterator it = DomUtil.getChildren(propElement); - while (it.hasNext()) { - add(DavPropertyName.createFromXml(it.nextElement())); - } - } - - /** - * Adds the specified {@link DavPropertyName} object to this - * set if it is not already present. - * - * @param propertyName element to be added to this set. - * @return {@code true} if the set did not already contain the specified - * element. - */ - public boolean add(DavPropertyName propertyName) { - return set.add(propertyName); - } - - /** - * Creates a DavPropertyName from the given parameters and add it to this set. - * - * @param localName - * @param namespace - * @return {@code true} if the set did not already contain the specified - * property name. - */ - public boolean add(String localName, Namespace namespace) { - return set.add(DavPropertyName.create(localName, namespace)); - } - - /** - * Add the property names contained in the specified set to this set. - * - * @param propertyNames - * @return true if the set has been modified by this call. - */ - public boolean addAll(DavPropertyNameSet propertyNames) { - return set.addAll(propertyNames.set); - } - - /** - * Removes the specified {@link DavPropertyName} object from this set. - * - * @param propertyName - * @return true if the given property name could be removed. - * @see HashSet#remove(Object) - */ - public boolean remove(DavPropertyName propertyName) { - return set.remove(propertyName); - } - - /** - * @return Iterator over all DavPropertyNames contained in this - * set. - */ - public DavPropertyNameIterator iterator() { - return new PropertyNameIterator(); - } - - //------------------------------------------------------< PropContainer >--- - /** - * @see PropContainer#contains(DavPropertyName) - */ - @Override - public boolean contains(DavPropertyName name) { - return set.contains(name); - } - - /** - * @param contentEntry NOTE that an instance of DavPropertyName - * in order to successfully add the given entry. - * @return true if contentEntry is an instance of DavPropertyName - * that could be added to this set. False otherwise. - * @see PropContainer#addContent(Object) - */ - @Override - public boolean addContent(PropEntry contentEntry) { - if (contentEntry instanceof DavPropertyName) { - return add((DavPropertyName) contentEntry); - } - log.debug("DavPropertyName object expected. Found: " + contentEntry.getClass().toString()); - return false; - } - - /** - * @see PropContainer#isEmpty() - */ - @Override - public boolean isEmpty() { - return set.isEmpty(); - } - - /** - * @see PropContainer#getContentSize() - */ - @Override - public int getContentSize() { - return set.size(); - } - - /** - * @see PropContainer#getContent() - */ - @Override - public Collection getContent() { - return set; - } - - //--------------------------------------------------------< inner class >--- - private class PropertyNameIterator implements DavPropertyNameIterator { - - private Iterator iter; - - private PropertyNameIterator() { - this.iter = set.iterator(); - } - - public DavPropertyName nextPropertyName() { - return iter.next(); - } - - public void remove() { - iter.remove(); - } - - public boolean hasNext() { - return iter.hasNext(); - } - - public DavPropertyName next() { - return iter.next(); - } - } -} Property changes on: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/property/DavPropertyNameSet.java ___________________________________________________________________ Deleted: svn Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/property/DavPropertySet.java =================================================================== --- jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/property/DavPropertySet.java (revision 1907912) +++ jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/property/DavPropertySet.java (nonexistent) @@ -1,300 +0,0 @@ -/* - * 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.webdav.property; - -import org.apache.jackrabbit.webdav.xml.Namespace; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.Collection; -import java.util.HashMap; -import java.util.Iterator; -import java.util.Map; -import java.util.NoSuchElementException; - -/** - * The DavPropertySet class represents a set of WebDAV - * property. - */ -public class DavPropertySet extends PropContainer - implements Iterable> { - - private static Logger log = LoggerFactory.getLogger(DavPropertySet.class); - - /** - * the set of property - */ - private final Map> map = new HashMap>(); - - /** - * Adds a new property to this set. - * - * @param property The property to add - * - * @return The previously assigned property or null. - */ - public DavProperty add(DavProperty property) { - return map.put(property.getName(), property); - } - - /** - * - * @param pset Properties to add - */ - public void addAll(DavPropertySet pset) { - map.putAll(pset.map); - } - - /** - * Retrieves the property with the specified name and the - * default WebDAV {@link org.apache.jackrabbit.webdav.DavConstants#NAMESPACE namespace}. - * - * @param name The name of the property to retrieve - * - * @return The desired property or null - */ - public DavProperty get(String name) { - return get(DavPropertyName.create(name)); - } - - /** - * Retrieves the property with the specified name and - * namespace. - * - * @param name The name of the property to retrieve - * @param namespace The namespace of the property to retrieve - * - * @return The desired property or null - */ - public DavProperty get(String name, Namespace namespace) { - return get(DavPropertyName.create(name, namespace)); - } - - /** - * Retrieves the property with the specified name - * - * @param name The webdav property name of the property to retrieve - * - * @return The desired property or null - */ - public DavProperty get(DavPropertyName name) { - return map.get(name); - } - - - /** - * Removes the indicated property from this set. - * - * @param name The webdav property name to remove - * - * @return The removed property or null - */ - public DavProperty remove(DavPropertyName name) { - return map.remove(name); - } - - /** - * Removes the property with the specified name and the - * default WebDAV {@link org.apache.jackrabbit.webdav.DavConstants#NAMESPACE namespace}. - * - * @param name The name of the property to remove - * - * @return The removed property or null - */ - public DavProperty remove(String name) { - return remove(DavPropertyName.create(name)); - } - - /** - * Removes the property with the specified name and - * namespace from this set. - * - * @param name The name of the property to remove - * @param namespace The namespace of the property to remove - * - * @return The removed property or null - */ - public DavProperty remove(String name, Namespace namespace) { - return remove(DavPropertyName.create(name, namespace)); - } - - /** - * Returns an iterator over all property in this set. - * - * @return An iterator over {@link DavProperty}. - */ - public DavPropertyIterator iterator() { - return new PropIter(); - } - - /** - * Returns an iterator over all those property in this set, that have the - * indicated namespace. - * - * @param namespace The namespace of the property in the iteration. - * - * @return An iterator over {@link DavProperty}. - */ - public DavPropertyIterator iterator(Namespace namespace) { - return new PropIter(namespace); - } - - /** - * Return the names of all properties present in this set. - * - * @return array of {@link DavPropertyName property names} present in this set. - */ - public DavPropertyName[] getPropertyNames() { - return map.keySet().toArray(new DavPropertyName[map.keySet().size()]); - } - - //------------------------------------------------------< PropContainer >--- - /** - * Checks if this set contains the property with the specified name. - * - * @param name The name of the property - * @return true if this set contains the property; - * false otherwise. - * @see PropContainer#contains(DavPropertyName) - */ - @Override - public boolean contains(DavPropertyName name) { - return map.containsKey(name); - } - - /** - * @param contentEntry NOTE, that the given object must be an instance of - * DavProperty in order to be successfully added to this set. - * @return true if the specified object is an instance of DavProperty - * and false otherwise. - * @see PropContainer#addContent(PropEntry) - */ - @Override - public boolean addContent(PropEntry contentEntry) { - if (contentEntry instanceof DavProperty) { - add((DavProperty) contentEntry); - return true; - } - log.debug("DavProperty object expected. Found: " + contentEntry.getClass().toString()); - return false; - } - - /** - * @see PropContainer#isEmpty() - */ - @Override - public boolean isEmpty() { - return map.isEmpty(); - } - - /** - * @see PropContainer#getContentSize() - */ - @Override - public int getContentSize() { - return map.size(); - } - - /** - * @see PropContainer#getContent() - */ - @Override - public Collection getContent() { - return map.values(); - } - - //---------------------------------------------------------- Inner class --- - /** - * Implementation of a DavPropertyIterator that returns webdav property. - * Additionally, it can only return property with the given namespace. - */ - private class PropIter implements DavPropertyIterator { - - /** the namespace to match against */ - private final Namespace namespace; - - /** the internal iterator */ - private final Iterator> iterator; - - /** the next property to return */ - private DavProperty next; - - /** - * Creates a new property iterator. - */ - private PropIter() { - this(null); - } - - /** - * Creates a new iterator with the given namespace - * @param namespace The namespace to match against - */ - private PropIter(Namespace namespace) { - this.namespace = namespace; - iterator = map.values().iterator(); - seek(); - } - - /** - * @see DavPropertyIterator#nextProperty(); - */ - public DavProperty nextProperty() throws NoSuchElementException { - if (next==null) { - throw new NoSuchElementException(); - } - DavProperty ret = next; - seek(); - return ret; - } - - /** - * @see DavPropertyIterator#hasNext(); - */ - public boolean hasNext() { - return next!=null; - } - - /** - * @see DavPropertyIterator#next(); - */ - public DavProperty next() { - return nextProperty(); - } - - /** - * @see DavPropertyIterator#remove(); - */ - public void remove() { - throw new UnsupportedOperationException(); - } - - /** - * Seeks for the next valid property - */ - private void seek() { - while (iterator.hasNext()) { - next = iterator.next(); - if (namespace == null || namespace.equals(next.getName().getNamespace())) { - return; - } - } - next = null; - } - } -} - Property changes on: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/property/DavPropertySet.java ___________________________________________________________________ Deleted: svn Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/property/DefaultDavProperty.java =================================================================== --- jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/property/DefaultDavProperty.java (revision 1907912) +++ jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/property/DefaultDavProperty.java (nonexistent) @@ -1,144 +0,0 @@ -/* - * 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.webdav.property; - -import org.apache.jackrabbit.webdav.xml.DomUtil; -import org.apache.jackrabbit.webdav.xml.Namespace; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.w3c.dom.Element; -import org.w3c.dom.Node; - -import java.util.List; - -/** - * DefaultDavProperty... - */ -public class DefaultDavProperty extends AbstractDavProperty { - - private static Logger log = LoggerFactory.getLogger(DefaultDavProperty.class); - - /** - * the value of the property - */ - private final T value; - - /** - * Creates a new WebDAV property with the given namespace, name and value. - * If the property is intended to be protected the isProtected flag must - * be set to true. - * - * @param name the name of the property - * @param value the value of the property - * @param namespace the namespace of the property - * @param isInvisibleInAllprop A value of true, defines this property to be protected. - * It will not be returned in a {@link org.apache.jackrabbit.webdav.DavConstants#PROPFIND_ALL_PROP DAV:allprop} - * PROPFIND request and cannot be set/removed with a PROPPATCH request. - */ - public DefaultDavProperty(String name, T value, Namespace namespace, boolean isInvisibleInAllprop) { - super(DavPropertyName.create(name, namespace), isInvisibleInAllprop); - this.value = value; - } - - /** - * Creates a new non-protected WebDAV property with the given namespace, name - * and value. - * - * @param name the name of the property - * @param value the value of the property - * @param namespace the namespace of the property - */ - public DefaultDavProperty(String name, T value, Namespace namespace) { - this(name, value, namespace, false); - } - - /** - * Creates a new WebDAV property with the given DavPropertyName - * and value. If the property is meant to be protected the 'isProtected' - * flag must be set to true. - * - * @param name the name of the property - * @param value the value of the property - * @param isInvisibleInAllprop A value of true, defines this property to be protected. - * It will not be returned in a {@link org.apache.jackrabbit.webdav.DavConstants#PROPFIND_ALL_PROP DAV:allprop} - * PROPFIND request and cannot be set/removed with a PROPPATCH request. - */ - public DefaultDavProperty(DavPropertyName name, T value, boolean isInvisibleInAllprop) { - super(name, isInvisibleInAllprop); - this.value = value; - } - - /** - * Creates a new non- protected WebDAV property with the given - * DavPropertyName and value. - * - * @param name the name of the property - * @param value the value of the property - */ - public DefaultDavProperty(DavPropertyName name, T value) { - this(name, value, false); - } - - /** - * Returns the value of this property - * - * @return the value of this property - */ - public T getValue() { - return value; - } - - /** - * Create a new DefaultDavProperty instance from the given Xml - * element. Name and namespace of the element are building the {@link DavPropertyName}, - * while the element's content forms the property value. The following logic - * is applied: - *
-     * - empty Element           -> null value
-     * - single Text content     -> String value
-     * - single non-Text content -> Element.getContent(0) is used as value
-     * - other: List obtained from Element.getContent() is used as value
-     * 
- * - * @param propertyElement - * @return - */ - public static DefaultDavProperty createFromXml(Element propertyElement) { - if (propertyElement == null) { - throw new IllegalArgumentException("Cannot create a new DavProperty from a 'null' element."); - } - DavPropertyName name = DavPropertyName.createFromXml(propertyElement); - DefaultDavProperty prop; - - if (!DomUtil.hasContent(propertyElement)) { - prop = new DefaultDavProperty(name, null, false); - } else { - List c = DomUtil.getContent(propertyElement); - if (c.size() == 1) { - Node n = c.get(0); - if (n instanceof Element) { - prop = new DefaultDavProperty(name, (Element) n, false); - } else { - prop = new DefaultDavProperty(name, n.getNodeValue(), false); - } - } else /* size > 1 */ { - prop = new DefaultDavProperty>(name, c, false); - } - } - return prop; - } -} \ No newline at end of file Property changes on: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/property/DefaultDavProperty.java ___________________________________________________________________ Deleted: svn Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/property/HrefProperty.java =================================================================== --- jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/property/HrefProperty.java (revision 1907912) +++ jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/property/HrefProperty.java (nonexistent) @@ -1,159 +0,0 @@ -/* - * 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.webdav.property; - -import org.apache.jackrabbit.webdav.xml.DomUtil; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.w3c.dom.Document; -import org.w3c.dom.Element; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - -/** - * HrefProperty is an extension to the common {@link DavProperty}. - * The String representation of the property value is always displayed as text - * inside an extra 'href' element. If the value is a String array each array - * element is added as text to a separate 'href' element. - * - * @see org.apache.jackrabbit.webdav.DavConstants#XML_HREF - * @see org.apache.jackrabbit.webdav.property.DavProperty#getValue() - */ -public class HrefProperty extends AbstractDavProperty { - - private static Logger log = LoggerFactory.getLogger(HrefProperty.class); - - private final String[] value; - - /** - * Creates a new WebDAV property with the given DavPropertyName - * - * @param name the name of the property - * @param value the value of the property - * @param isInvisibleInAllprop A value of true, defines this property to be invisible in PROPFIND/allprop - * It will not be returned in a {@link org.apache.jackrabbit.webdav.DavConstants#PROPFIND_ALL_PROP DAV:allprop} - * PROPFIND request. - */ - public HrefProperty(DavPropertyName name, String value, boolean isInvisibleInAllprop) { - super(name, isInvisibleInAllprop); - this.value = new String[]{value}; - } - - /** - * Creates a new WebDAV property with the given DavPropertyName - * - * @param name the name of the property - * @param value the value of the property - * @param isInvisibleInAllprop A value of true, defines this property to be invisible in PROPFIND/allprop - * It will not be returned in a {@link org.apache.jackrabbit.webdav.DavConstants#PROPFIND_ALL_PROP DAV:allprop} - * PROPFIND request. - */ - public HrefProperty(DavPropertyName name, String[] value, boolean isInvisibleInAllprop) { - super(name, isInvisibleInAllprop); - this.value = value; - } - - /** - * Create a new HrefProperty from the specified property. - * Please note, that the property must have a List value - * object, consisting of {@link #XML_HREF href} Element entries. - * - * @param prop - */ - public HrefProperty(DavProperty prop) { - super(prop.getName(), prop.isInvisibleInAllprop()); - if (prop instanceof HrefProperty) { - // already an HrefProperty: no parsing required - this.value = ((HrefProperty)prop).value; - } else { - // assume property has be built from xml - ArrayList hrefList = new ArrayList(); - Object val = prop.getValue(); - if (val instanceof List) { - for (Object entry : ((List) val)) { - if (entry instanceof Element && XML_HREF.equals(((Element) entry).getLocalName())) { - String href = DomUtil.getText((Element) entry); - if (href != null) { - hrefList.add(href); - } else { - log.warn("Valid DAV:href element expected instead of " + entry.toString()); - } - } else { - log.warn("DAV: href element expected in the content of " + getName().toString()); - } - } - } else if (val instanceof Element && XML_HREF.equals(((Element)val).getLocalName())) { - String href = DomUtil.getTextTrim((Element)val); - if (href != null) { - hrefList.add(href); - } else { - log.warn("Valid DAV:href element expected instead of " + val.toString()); - } - } - value = hrefList.toArray(new String[hrefList.size()]); - } - } - - /** - * Returns an Xml element with the following form: - *
-     * <Z:name>
-     *    <DAV:href>value</DAV:href/>
-     * </Z:name>
-     * 
- * where Z: represents the prefix of the namespace defined with the initial - * webdav property name. - * - * @return Xml representation - * @see org.apache.jackrabbit.webdav.xml.DomUtil#hrefToXml(String,org.w3c.dom.Document) - * @param document - */ - @Override - public Element toXml(Document document) { - Element elem = getName().toXml(document); - String[] value = getValue(); - if (value != null) { - for (String href : value) { - elem.appendChild(DomUtil.hrefToXml(href, document)); - } - } - return elem; - } - - /** - * Returns an array of String. - * - * @return an array of String. - * @see DavProperty#getValue() - */ - public String[] getValue() { - return value; - } - - /** - * Return an list of String containing the text of those DAV:href elements - * that would be returned as child elements of this property on - * {@link org.apache.jackrabbit.webdav.xml.XmlSerializable#toXml(Document)} - * - * @return list of href String - */ - public List getHrefs() { - return (value != null) ? Arrays.asList(value) : new ArrayList(); - } -} Property changes on: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/property/HrefProperty.java ___________________________________________________________________ Deleted: svn Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/property/PropContainer.java =================================================================== --- jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/property/PropContainer.java (revision 1907912) +++ jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/property/PropContainer.java (nonexistent) @@ -1,119 +0,0 @@ -/* - * 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.webdav.property; - -import org.apache.jackrabbit.webdav.DavConstants; -import org.apache.jackrabbit.webdav.xml.DomUtil; -import org.apache.jackrabbit.webdav.xml.XmlSerializable; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.w3c.dom.Document; -import org.w3c.dom.Element; - -import java.util.Collection; - -/** - * PropContainer... - */ -public abstract class PropContainer implements XmlSerializable, DavConstants { - - private static Logger log = LoggerFactory.getLogger(PropContainer.class); - - /** - * Tries to add the specified object to the PropContainer and - * returns a boolean indicating whether the content could be added to the - * internal set/map. - * - * @param contentEntry - * @return true if the object could be added; false otherwise - * @deprecated Use {@link #addContent(PropEntry)} instead. - */ - public boolean addContent(Object contentEntry) { - if (contentEntry instanceof PropEntry) { - return addContent((PropEntry) contentEntry); - } else { - return false; - } - } - - /** - * Tries to add the specified entry to the PropContainer and - * returns a boolean indicating whether the content could be added to the - * internal set/map. - * - * @param contentEntry - * @return true if the object could be added; false otherwise - */ - public abstract boolean addContent(PropEntry contentEntry); - - /** - * Returns true if the PropContainer does not yet contain any content elements. - * - * @return true if this container is empty. - */ - public abstract boolean isEmpty(); - - /** - * Returns the number of property related content elements that are present - * in this PropContainer. - * - * @return number of content elements - */ - public abstract int getContentSize(); - - /** - * Returns the collection that contains all the content elements of this - * PropContainer. - * - * @return collection representing the contents of this PropContainer. - */ - public abstract Collection getContent(); - - /** - * Returns true if this PropContainer contains a content element - * that matches the given DavPropertyName. - * - * @param name - * @return true if any of the content elements (be it a DavProperty or a - * DavPropertyName only) matches the given name. - */ - public abstract boolean contains(DavPropertyName name); - - /** - * Returns the xml representation of a property related set with the - * following format: - *
-     * <!ELEMENT prop (ANY) >
-     * where ANY consists of a list of elements each reflecting the xml
-     * representation of the entries returned by {@link #getContent()}.
-     * 
- * - * @see XmlSerializable#toXml(Document) - */ - public Element toXml(Document document) { - Element prop = DomUtil.createElement(document, XML_PROP, NAMESPACE); - for (Object content : getContent()) { - if (content instanceof XmlSerializable) { - prop.appendChild(((XmlSerializable) content).toXml(document)); - } else { - log.debug("Unexpected content in PropContainer: should be XmlSerializable."); - } - } - return prop; - } - -} Property changes on: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/property/PropContainer.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Deleted: svn:keywords ## -1 +0,0 ## -author date id revision url \ No newline at end of property Index: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/property/PropEntry.java =================================================================== --- jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/property/PropEntry.java (revision 1907912) +++ jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/property/PropEntry.java (nonexistent) @@ -1,25 +0,0 @@ -/* - * 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.webdav.property; - -/** - * Marker interface used to flag the different types of entries that form - * part of a PROPPATCH request and define the possible entries for a - * PropContainer. - */ -public interface PropEntry { -} Property changes on: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/property/PropEntry.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Deleted: svn:keywords ## -1 +0,0 ## -Author Date Id Revision Rev URL \ No newline at end of property Index: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/property/PropfindInfo.java =================================================================== --- jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/property/PropfindInfo.java (revision 1907912) +++ jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/property/PropfindInfo.java (nonexistent) @@ -1,84 +0,0 @@ -/* - * 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.webdav.property; - -import org.apache.jackrabbit.webdav.DavConstants; -import org.apache.jackrabbit.webdav.xml.DomUtil; -import org.apache.jackrabbit.webdav.xml.XmlSerializable; -import org.w3c.dom.Document; -import org.w3c.dom.Element; -import org.w3c.dom.Node; - -public class PropfindInfo implements XmlSerializable { - - private final int propfindType; - private final DavPropertyNameSet propNameSet; - - public PropfindInfo(int propfindType, DavPropertyNameSet propNameSet) { - this.propfindType = propfindType; - this.propNameSet = propNameSet; - } - - @Override - public Element toXml(Document document) { - Element propfind = DomUtil.createElement(document, DavConstants.XML_PROPFIND, DavConstants.NAMESPACE); - - // fill the propfind element - switch (propfindType) { - case DavConstants.PROPFIND_ALL_PROP: - propfind.appendChild(DomUtil.createElement(document, DavConstants.XML_ALLPROP, DavConstants.NAMESPACE)); - break; - - case DavConstants.PROPFIND_PROPERTY_NAMES: - propfind.appendChild(DomUtil.createElement(document, DavConstants.XML_PROPNAME, DavConstants.NAMESPACE)); - break; - - case DavConstants.PROPFIND_BY_PROPERTY: - if (propNameSet == null) { - // name set missing, ask for a property that is known to - // exist - Element prop = DomUtil.createElement(document, DavConstants.XML_PROP, DavConstants.NAMESPACE); - Element resourcetype = DomUtil.createElement(document, DavConstants.PROPERTY_RESOURCETYPE, - DavConstants.NAMESPACE); - prop.appendChild(resourcetype); - propfind.appendChild(prop); - } else { - propfind.appendChild(propNameSet.toXml(document)); - } - break; - - case DavConstants.PROPFIND_ALL_PROP_INCLUDE: - propfind.appendChild(DomUtil.createElement(document, DavConstants.XML_ALLPROP, DavConstants.NAMESPACE)); - if (propNameSet != null && !propNameSet.isEmpty()) { - Element include = DomUtil.createElement(document, DavConstants.XML_INCLUDE, DavConstants.NAMESPACE); - Element prop = propNameSet.toXml(document); - for (Node c = prop.getFirstChild(); c != null; c = c.getNextSibling()) { - // copy over the children of to - // element - include.appendChild(c.cloneNode(true)); - } - propfind.appendChild(include); - } - break; - - default: - throw new IllegalArgumentException("unknown propfind type"); - } - - return propfind; - } -} Property changes on: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/property/PropfindInfo.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Deleted: svn:executable ## -1 +0,0 ## -* \ No newline at end of property Index: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/property/ProppatchInfo.java =================================================================== --- jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/property/ProppatchInfo.java (revision 1907912) +++ jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/property/ProppatchInfo.java (nonexistent) @@ -1,128 +0,0 @@ -/* - * 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.webdav.property; - -import java.util.List; - -import org.apache.jackrabbit.webdav.DavConstants; -import org.apache.jackrabbit.webdav.xml.DomUtil; -import org.apache.jackrabbit.webdav.xml.XmlSerializable; -import org.w3c.dom.Document; -import org.w3c.dom.Element; - -public class ProppatchInfo implements XmlSerializable { - - private final List changeList; - private final DavPropertySet setProperties; - private final DavPropertyNameSet removeProperties; - - private final DavPropertyNameSet propertyNames = new DavPropertyNameSet(); - - public ProppatchInfo(List changeList) { - if (changeList == null || changeList.isEmpty()) { - throw new IllegalArgumentException("PROPPATCH cannot be executed without properties to be set or removed."); - } - this.changeList = changeList; - this.setProperties = null; - this.removeProperties = null; - for (PropEntry entry : changeList) { - if (entry instanceof DavPropertyName) { - // DAV:remove - this.propertyNames.add((DavPropertyName) entry); - } else if (entry instanceof DavProperty) { - // DAV:set - DavProperty setProperty = (DavProperty) entry; - this.propertyNames.add(setProperty.getName()); - } else { - throw new IllegalArgumentException("ChangeList may only contain DavPropertyName and DavProperty elements."); - } - } - } - - public ProppatchInfo(DavPropertySet setProperties, DavPropertyNameSet removeProperties) { - if (setProperties == null || removeProperties == null) { - throw new IllegalArgumentException("Neither setProperties nor removeProperties must be null."); - } - if (setProperties.isEmpty() && removeProperties.isEmpty()) { - throw new IllegalArgumentException("Either setProperties or removeProperties can be empty; not both of them."); - } - this.changeList = null; - this.setProperties = setProperties; - this.removeProperties = removeProperties; - this.propertyNames.addAll(removeProperties); - for (DavPropertyName setName : setProperties.getPropertyNames()) { - this.propertyNames.add(setName); - } - } - - public DavPropertyNameSet getAffectedProperties() { - if (this.propertyNames.isEmpty()) { - throw new IllegalStateException("must be called after toXml()"); - } - return this.propertyNames; - } - - @Override - public Element toXml(Document document) { - Element proppatch = DomUtil.createElement(document, DavConstants.XML_PROPERTYUPDATE, DavConstants.NAMESPACE); - - if (changeList != null) { - Element propElement = null; - boolean isSet = false; - for (Object entry : changeList) { - if (entry instanceof DavPropertyName) { - // DAV:remove - DavPropertyName removeName = (DavPropertyName) entry; - if (propElement == null || isSet) { - isSet = false; - propElement = getPropElement(proppatch, false); - } - propElement.appendChild(removeName.toXml(document)); - } else if (entry instanceof DavProperty) { - // DAV:set - DavProperty setProperty = (DavProperty) entry; - if (propElement == null || !isSet) { - isSet = true; - propElement = getPropElement(proppatch, true); - } - propElement.appendChild(setProperty.toXml(document)); - } else { - throw new IllegalArgumentException("ChangeList may only contain DavPropertyName and DavProperty elements."); - } - } - } else { - // DAV:set - if (!setProperties.isEmpty()) { - Element set = DomUtil.addChildElement(proppatch, DavConstants.XML_SET, DavConstants.NAMESPACE); - set.appendChild(setProperties.toXml(document)); - } - // DAV:remove - if (!removeProperties.isEmpty()) { - Element remove = DomUtil.addChildElement(proppatch, DavConstants.XML_REMOVE, DavConstants.NAMESPACE); - remove.appendChild(removeProperties.toXml(document)); - } - } - - return proppatch; - } - - private Element getPropElement(Element propUpdate, boolean isSet) { - Element updateEntry = DomUtil.addChildElement(propUpdate, isSet ? DavConstants.XML_SET : DavConstants.XML_REMOVE, - DavConstants.NAMESPACE); - return DomUtil.addChildElement(updateEntry, DavConstants.XML_PROP, DavConstants.NAMESPACE); - } -} Property changes on: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/property/ProppatchInfo.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/property/ResourceType.java =================================================================== --- jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/property/ResourceType.java (revision 1907912) +++ jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/property/ResourceType.java (nonexistent) @@ -1,205 +0,0 @@ -/* - * 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.webdav.property; - -import org.apache.jackrabbit.webdav.version.DeltaVConstants; -import org.apache.jackrabbit.webdav.xml.DomUtil; -import org.apache.jackrabbit.webdav.xml.Namespace; -import org.apache.jackrabbit.webdav.xml.XmlSerializable; -import org.w3c.dom.Document; -import org.w3c.dom.Element; - -import java.util.ArrayList; -import java.util.HashSet; -import java.util.List; -import java.util.Set; - -/** - * The ResourceType class represents the webdav resource - * type property. The property may contain multiple resource type - * values. Predefined resource types are those defined by RFC2518 and RFC3253: - *
    - *
  • {@link #DEFAULT_RESOURCE the empty default resource type},
  • - *
  • '{@link #COLLECTION DAV:collection}',
  • - *
  • '{@link #VERSION_HISTORY DAV:version-history}',
  • - *
  • '{@link #ACTIVITY DAV:activity}',
  • - *
  • '{@link #BASELINE DAV:baseline}',
  • - *
- */ -public class ResourceType extends AbstractDavProperty> { - - /** - * The default resource type - */ - public static final int DEFAULT_RESOURCE = 0; - - /** - * The collection resource type - */ - public static final int COLLECTION = DEFAULT_RESOURCE + 1; - - /** - * The version-history resource type - */ - public static final int VERSION_HISTORY = COLLECTION + 1; - - /** - * The activity resource type - */ - public static final int ACTIVITY = VERSION_HISTORY + 1; - - /** - * The baseline resource type - */ - public static final int BASELINE = ACTIVITY + 1; - - /** - * Array containing all possible resourcetype elements - */ - private static final List NAMES = new ArrayList(); - static { - NAMES.add(null); - NAMES.add(new TypeName(XML_COLLECTION, NAMESPACE)); - NAMES.add(new TypeName(DeltaVConstants.XML_VERSION_HISTORY, DeltaVConstants.NAMESPACE)); - NAMES.add(new TypeName(DeltaVConstants.XML_ACTIVITY, DeltaVConstants.NAMESPACE)); - NAMES.add(new TypeName(DeltaVConstants.XML_BASELINE, DeltaVConstants.NAMESPACE)); - } - - private final int[] resourceTypes; - - /** - * Create a single-valued resource type property - */ - public ResourceType(int resourceType) { - this(new int[] { resourceType }); - } - - /** - * Create a multi-valued resource type property - */ - public ResourceType(int[] resourceTypes) { - super(DavPropertyName.RESOURCETYPE, false); - for (int resourceType : resourceTypes) { - if (!isValidResourceType(resourceType)) { - throw new IllegalArgumentException("Invalid resource type '" + resourceType + "'."); - } - } - this.resourceTypes = resourceTypes; - } - - /** - * Returns a Set of resource types each implementing the XmlSerializable - * interface. - * - * @return a Set of resource types representing this property. - * @see DavProperty#getValue() - */ - public Set getValue() { - Set rTypes = new HashSet(); - for (int resourceType : resourceTypes) { - TypeName n = NAMES.get(resourceType); - if (n != null) { - rTypes.add(n); - } - } - return rTypes; - } - - /** - * Returns the resource types specified with the constructor. - * - * @return resourceTypes - */ - public int[] getResourceTypes() { - return resourceTypes; - } - - /** - * Returns true if the given integer defines a valid resource type. - * - * @param resourceType to be validated. - * @return true if this is one of the predefined resource types - */ - private static boolean isValidResourceType(int resourceType) { - if (resourceType < DEFAULT_RESOURCE || resourceType > NAMES.size()-1) { - return false; - } - return true; - } - - /** - * Register an additional resource type - * - * @param name - * @param namespace - * @return int to be used for creation of a new ResourceType property - * that contains this type. - * @throws IllegalArgumentException if the given element is null or - * if the registration fails for another reason. - */ - public static int registerResourceType(String name, Namespace namespace) { - if (name == null || namespace == null) { - throw new IllegalArgumentException("Cannot register a resourcetype"); - } - TypeName tn = new TypeName(name, namespace); - // avoid duplicate registrations - if (NAMES.contains(tn)) { - return NAMES.indexOf(tn); - } - // register new type - if (NAMES.add(tn)) { - return NAMES.size() - 1; - } else { - throw new IllegalArgumentException("Could not register resourcetype " + namespace.getPrefix() + name); - } - } - - //--------------------------------------------------------< inner class >--- - /** - * Private inner class used to register predefined and user defined resource - * types. - */ - private static class TypeName implements XmlSerializable { - - private final String localName; - private final Namespace namespace; - private final int hashCode; - - private TypeName(String localName, Namespace namespace) { - this.localName = localName; - this.namespace = namespace; - hashCode = DomUtil.getExpandedName(localName, namespace).hashCode(); - } - - @Override - public int hashCode() { - return hashCode; - } - - @Override - public boolean equals(Object o) { - if (o instanceof TypeName) { - return hashCode == ((TypeName)o).hashCode; - } - return false; - } - - public Element toXml(Document document) { - return DomUtil.createElement(document, localName, namespace); - } - } -} Property changes on: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/property/ResourceType.java ___________________________________________________________________ Deleted: svn Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/property/package-info.java =================================================================== --- jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/property/package-info.java (revision 1907912) +++ jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/property/package-info.java (nonexistent) @@ -1,18 +0,0 @@ -/* - * 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. - */ -@org.osgi.annotation.versioning.Version("1.0.0") -package org.apache.jackrabbit.webdav.property; Property changes on: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/property/package-info.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/search/QueryGrammerSet.java =================================================================== --- jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/search/QueryGrammerSet.java (revision 1907912) +++ jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/search/QueryGrammerSet.java (nonexistent) @@ -1,144 +0,0 @@ -/* - * 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.webdav.search; - -import org.apache.jackrabbit.webdav.property.AbstractDavProperty; -import org.apache.jackrabbit.webdav.property.DavProperty; -import org.apache.jackrabbit.webdav.xml.DomUtil; -import org.apache.jackrabbit.webdav.xml.Namespace; -import org.apache.jackrabbit.webdav.xml.XmlSerializable; -import org.w3c.dom.Document; -import org.w3c.dom.Element; - -import java.util.HashSet; -import java.util.Set; - -/** - * QueryGrammerSet is a {@link DavProperty} that - * encapsulates the 'supported-query-grammer-set' as defined by the - * Webdav SEARCH internet draft. - */ -public class QueryGrammerSet extends AbstractDavProperty> implements SearchConstants { - - private final Set queryGrammers = new HashSet(); - - /** - * Create a new empty QueryGrammerSet. Supported query grammers - * may be added by calling {@link #addQueryLanguage(String, Namespace)}. - */ - public QueryGrammerSet() { - super(QUERY_GRAMMER_SET, true); - } - - /** - * Add another query queryGrammer to this set. - * - * @param grammerName - * @param namespace - */ - public void addQueryLanguage(String grammerName, Namespace namespace) { - queryGrammers.add(new Grammer(grammerName, namespace)); - } - - /** - * Return a String array containing the URIs of the query - * languages supported. - * - * @return names of the supported query languages - */ - public String[] getQueryLanguages() { - int size = queryGrammers.size(); - if (size > 0) { - String[] qLangStr = new String[size]; - Grammer[] grammers = queryGrammers.toArray(new Grammer[size]); - for (int i = 0; i < grammers.length; i++) { - qLangStr[i] = grammers[i].namespace.getURI() + grammers[i].localName; - } - return qLangStr; - } else { - return new String[0]; - } - } - - /** - * Return the Xml representation of this property according to the definition - * of the 'supported-query-grammer-set'. - * - * @return Xml representation - * @see SearchConstants#QUERY_GRAMMER_SET - * @see org.apache.jackrabbit.webdav.xml.XmlSerializable#toXml(Document) - * @param document - */ - @Override - public Element toXml(Document document) { - Element elem = getName().toXml(document); - for (Grammer qGrammer : queryGrammers) { - elem.appendChild(qGrammer.toXml(document)); - } - return elem; - } - - /** - * Returns the set of supported query grammers. - * - * @return list of supported query languages. - * @see org.apache.jackrabbit.webdav.property.DavProperty#getValue() - */ - public Set getValue() { - return queryGrammers; - } - - - private class Grammer implements XmlSerializable { - - private final String localName; - private final Namespace namespace; - private final int hashCode; - - Grammer(String localName, Namespace namespace) { - this.localName = localName; - this.namespace = namespace; - hashCode = DomUtil.getExpandedName(localName, namespace).hashCode(); - } - - @Override - public int hashCode() { - return hashCode; - } - - @Override - public boolean equals(Object obj) { - if (obj == this) { - return true; - } - if (obj instanceof Grammer) { - return obj.hashCode() == hashCode(); - } - return false; - } - - /** - * @see XmlSerializable#toXml(org.w3c.dom.Document) - */ - public Element toXml(Document document) { - Element sqg = DomUtil.createElement(document, XML_QUERY_GRAMMAR, SearchConstants.NAMESPACE); - Element grammer = DomUtil.addChildElement(sqg, XML_GRAMMER, SearchConstants.NAMESPACE); - DomUtil.addChildElement(grammer, localName, namespace); - return sqg; - } - } -} \ No newline at end of file Property changes on: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/search/QueryGrammerSet.java ___________________________________________________________________ Deleted: svn Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/search/SearchConstants.java =================================================================== --- jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/search/SearchConstants.java (revision 1907912) +++ jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/search/SearchConstants.java (nonexistent) @@ -1,91 +0,0 @@ -/* - * 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.webdav.search; - -import org.apache.jackrabbit.webdav.DavConstants; -import org.apache.jackrabbit.webdav.property.DavPropertyName; -import org.apache.jackrabbit.webdav.xml.Namespace; - -/** - * SearchConstants interface provide constants for request - * and response headers, Xml elements and property names used for WebDAV - * search. - */ -public interface SearchConstants { - - /** - * Namespace definition.
- * NOTE: For convenience reasons, the namespace is defined to be the default - * {@link DavConstants#NAMESPACE DAV:} namespace. This is not correct for the - * underlying specification is still in a draft state. See also the editorial - * note inside the - * Internet Draft WebDAV Search - * document. - */ - public static final Namespace NAMESPACE = DavConstants.NAMESPACE; - - /** - * Predefined basic query grammer. - */ - public static final String BASICSEARCH = NAMESPACE.getPrefix()+"basicsearch"; - - //---< Headers >------------------------------------------------------------ - /** - * The DASL response header specifying the query languages supported by - * the requested resource. - */ - public static final String HEADER_DASL = "DASL"; - - //---< XML Element, Attribute Names >--------------------------------------- - /** - * Xml element name for a single query grammar element inside - * the {@link #QUERY_GRAMMER_SET supported-query-grammer-set property}. - */ - public static final String XML_QUERY_GRAMMAR = "supported-query-grammar"; - - /** - * Name constant for the 'DAV:grammar' element, which is used inside the - * {@link #XML_QUERY_GRAMMAR} element. - */ - public static final String XML_GRAMMER = "grammar"; - - /** - * Xml element name for the required request body of a SEARCH request. - * - * @see SearchInfo - * @see SearchResource#search(SearchInfo) - */ - public static final String XML_SEARCHREQUEST = "searchrequest"; - - /** - * Optional Xml element name used in the SEARCH request body instead of {@link #XML_SEARCHREQUEST} - * in order to access a given query schema. - */ - public static final String XML_QUERY_SCHEMA_DISCOVERY = "query-schema-discovery"; - - //---< Property Names >----------------------------------------------------- - /** - * Property indicating the set of query languages the given resource is - * able deal with. The property has the following definition:
- *
-     * <!ELEMENT supported-query-grammar-set (supported-query-grammar*)>
-     * <!ELEMENT supported-query-grammar grammar>
-     * <!ELEMENT grammar ANY>
-     * 
- */ - public static final DavPropertyName QUERY_GRAMMER_SET = DavPropertyName.create("supported-query-grammar-set", NAMESPACE); -} \ No newline at end of file Property changes on: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/search/SearchConstants.java ___________________________________________________________________ Deleted: svn Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/search/SearchInfo.java =================================================================== --- jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/search/SearchInfo.java (revision 1907912) +++ jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/search/SearchInfo.java (nonexistent) @@ -1,271 +0,0 @@ -/* - * 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.webdav.search; - -import org.apache.jackrabbit.webdav.DavException; -import org.apache.jackrabbit.webdav.DavServletResponse; -import org.apache.jackrabbit.webdav.DavConstants; -import org.apache.jackrabbit.webdav.xml.DomUtil; -import org.apache.jackrabbit.webdav.xml.Namespace; -import org.apache.jackrabbit.webdav.xml.XmlSerializable; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.w3c.dom.Document; -import org.w3c.dom.Element; -import org.w3c.dom.Attr; - -import java.util.Map; -import java.util.HashMap; -import java.util.Collections; -import java.util.Set; -import java.util.HashSet; - -/** - * SearchInfo parses the 'searchrequest' element of a SEARCH - * request body and performs basic validation. Both query language and the - * query itself can be access from the resulting object.
- * NOTE: The query is expected to be represented by the text contained in the - * Xml element specifying the query language, thus the 'basicsearch' defined - * by the Webdav Search Internet Draft is not supported by this implementation. - *

- * - * Example of a valid 'searchrequest' body - *

- * <d:searchrequest xmlns:d="DAV:" dcr:="http://www.day.com/jcr/webdav/1.0" >
- *    <dcr:xpath>//sv:node[@sv:name='myapp:paragraph'][1]</dcr:xpath>
- * </d:searchrequest>
- * 
- * - * Would return the following values: - *
- *    getLanguageName() -> xpath
- *    getQuery()        -> //sv:node[@sv:name='myapp:paragraph'][1]
- * 
- * - */ -public class SearchInfo implements SearchConstants, XmlSerializable { - - private static Logger log = LoggerFactory.getLogger(SearchInfo.class); - - public static final long NRESULTS_UNDEFINED = -1; - public static final long OFFSET_UNDEFINED = -1; - - private static final String LIMIT = "limit"; - private static final String NRESULTS = "nresults"; - private static final String OFFSET = "offset"; - - /** - * Set of namespace uri String which are ignored in the search request. - */ - private static final Set IGNORED_NAMESPACES; - - static { - Set s = new HashSet(); - s.add(Namespace.XMLNS_NAMESPACE.getURI()); - s.add(Namespace.XML_NAMESPACE.getURI()); - s.add(DavConstants.NAMESPACE.getURI()); - IGNORED_NAMESPACES = Collections.unmodifiableSet(s); - } - - private final String language; - private final Namespace languageNamespace; - private final String query; - private final Map namespaces; - - private long nresults = NRESULTS_UNDEFINED; - private long offset = OFFSET_UNDEFINED; - - /** - * Create a new SearchInfo instance. - * - * @param language - * @param languageNamespace - * @param query - * @param namespaces the re-mapped namespaces. Key=prefix, value=uri. - */ - public SearchInfo(String language, Namespace languageNamespace, String query, - Map namespaces) { - this.language = language; - this.languageNamespace = languageNamespace; - this.query = query; - this.namespaces = Collections.unmodifiableMap(new HashMap(namespaces)); - } - - /** - * Create a new SearchInfo instance. - * - * @param language - * @param languageNamespace - * @param query - */ - public SearchInfo(String language, Namespace languageNamespace, String query) { - this(language, languageNamespace, query, Collections.emptyMap()); - } - - /** - * Returns the name of the query language to be used. - * - * @return name of the query language - */ - public String getLanguageName() { - return language; - } - - /** - * Returns the namespace of the language specified with the search request element. - * - * @return namespace of the requested language. - */ - public Namespace getLanguageNameSpace() { - return languageNamespace; - } - - /** - * Return the query string. - * - * @return query string - */ - public String getQuery() { - return query; - } - - /** - * Returns the namespaces that have been re-mapped by the user. - * - * @return map of namespace to prefix mappings. Key=prefix, value=uri. - */ - public Map getNamespaces() { - return namespaces; - } - - /** - * Returns the maximal number of search results that should be returned. - * - * @return the maximal number of search results that should be returned. - */ - public long getNumberResults() { - return nresults; - } - - /** - * Sets the maximal number of search results that should be returned. - * - * @param nresults The maximal number of search results - */ - public void setNumberResults(long nresults) { - this.nresults = nresults; - } - - /** - * Returns the desired offset in the total result set. - * - * @return the desired offset in the total result set. - */ - public long getOffset() { - return offset; - } - - /** - * Sets the desired offset in the total result set. - * - * @param offset The desired offset in the total result set. - */ - public void setOffset(long offset) { - this.offset = offset; - } - - /** - * Return the xml representation of this SearchInfo instance. - * - * @return xml representation - * @param document - */ - public Element toXml(Document document) { - Element sRequestElem = DomUtil.createElement(document, XML_SEARCHREQUEST, NAMESPACE); - for (String prefix : namespaces.keySet()) { - String uri = namespaces.get(prefix); - DomUtil.setNamespaceAttribute(sRequestElem, prefix, uri); - } - DomUtil.addChildElement(sRequestElem, language, languageNamespace, query); - if (nresults != NRESULTS_UNDEFINED|| offset != OFFSET_UNDEFINED) { - Element limitE = DomUtil.addChildElement(sRequestElem, LIMIT, NAMESPACE); - if (nresults != NRESULTS_UNDEFINED) { - DomUtil.addChildElement(limitE, NRESULTS, NAMESPACE, nresults + ""); - } - if (offset != OFFSET_UNDEFINED) { - // TODO define reasonable namespace... - DomUtil.addChildElement(limitE, OFFSET, Namespace.EMPTY_NAMESPACE, offset + ""); - } - } - return sRequestElem; - } - - /** - * Create a new SearchInfo from the specifying document - * retrieved from the request body. - * - * @param searchRequest - * @throws DavException if the root element's name is other than - * 'searchrequest' or if it does not contain a single child element specifying - * the query language to be used. - */ - public static SearchInfo createFromXml(Element searchRequest) throws DavException { - if (searchRequest == null || !XML_SEARCHREQUEST.equals(searchRequest.getLocalName())) { - log.warn("The root element must be 'searchrequest'."); - throw new DavException(DavServletResponse.SC_BAD_REQUEST); - } - Element first = DomUtil.getFirstChildElement(searchRequest); - Attr[] nsAttributes = DomUtil.getNamespaceAttributes(searchRequest); - Map namespaces = new HashMap(); - for (Attr nsAttribute : nsAttributes) { - // filter out xmlns namespace and DAV namespace - if (!IGNORED_NAMESPACES.contains(nsAttribute.getValue())) { - namespaces.put(nsAttribute.getLocalName(), nsAttribute.getValue()); - } - } - SearchInfo sInfo; - if (first != null) { - sInfo = new SearchInfo(first.getLocalName(), DomUtil.getNamespace(first), DomUtil.getText(first), namespaces); - } else { - log.warn("A single child element is expected with the 'DAV:searchrequest'."); - throw new DavException(DavServletResponse.SC_BAD_REQUEST); - } - - Element limit = DomUtil.getChildElement(searchRequest, LIMIT, NAMESPACE); - if (limit != null) { - // try to get the value DAV:nresults element - String nresults = DomUtil.getChildTextTrim(limit, NRESULTS, NAMESPACE); - if (nresults != null) { - try { - sInfo.setNumberResults(Long.valueOf(nresults)); - } catch (NumberFormatException e) { - log.error("DAV:nresults cannot be parsed into a long -> ignore."); - } - } - // try of an offset is defined within the DAV:limit element. - String offset = DomUtil.getChildTextTrim(limit, OFFSET, Namespace.EMPTY_NAMESPACE); - if (offset != null) { - try { - sInfo.setOffset(Long.valueOf(offset)); - } catch (NumberFormatException e) { - log.error("'offset' cannot be parsed into a long -> ignore."); - } - } - } - return sInfo; - } -} Property changes on: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/search/SearchInfo.java ___________________________________________________________________ Deleted: svn Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/search/SearchResource.java =================================================================== --- jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/search/SearchResource.java (revision 1907912) +++ jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/search/SearchResource.java (nonexistent) @@ -1,55 +0,0 @@ -/* - * 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.webdav.search; - -import org.apache.jackrabbit.webdav.DavException; -import org.apache.jackrabbit.webdav.MultiStatus; - -/** - * SearchResource defines METHODS required in order to handle - * a SEARCH request. - */ -public interface SearchResource { - - /** - * The 'SEARCH' method - */ - public String METHODS = "SEARCH"; - - - /** - * Returns the protected DAV:supported-method-set property which is defined - * mandatory by RTF 3253. This method call is a shortcut for - * DavResource.getProperty(SearchConstants.QUERY_GRAMMER_SET). - * - * @return the DAV:supported-query-grammer-set - * @see SearchConstants#QUERY_GRAMMER_SET - */ - public QueryGrammerSet getQueryGrammerSet(); - - /** - * Runs a search with the language and query defined in the {@link SearchInfo} - * object specified and returns a {@link MultiStatus} object listing the - * results. - * - * @param sInfo SearchInfo element encapsulating the SEARCH - * request body. - * @return MultiStatus object listing the results. - * @throws DavException - */ - public MultiStatus search(SearchInfo sInfo) throws DavException; -} \ No newline at end of file Property changes on: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/search/SearchResource.java ___________________________________________________________________ Deleted: svn Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/search/package-info.java =================================================================== --- jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/search/package-info.java (revision 1907912) +++ jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/search/package-info.java (nonexistent) @@ -1,18 +0,0 @@ -/* - * 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. - */ -@org.osgi.annotation.versioning.Version("1.0.0") -package org.apache.jackrabbit.webdav.search; Property changes on: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/search/package-info.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/security/AclProperty.java =================================================================== --- jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/security/AclProperty.java (revision 1907912) +++ jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/security/AclProperty.java (nonexistent) @@ -1,262 +0,0 @@ -/* - * 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.webdav.security; - -import org.apache.jackrabbit.webdav.DavConstants; -import org.apache.jackrabbit.webdav.DavException; -import org.apache.jackrabbit.webdav.DavServletResponse; -import org.apache.jackrabbit.webdav.property.AbstractDavProperty; -import org.apache.jackrabbit.webdav.property.DavProperty; -import org.apache.jackrabbit.webdav.xml.DomUtil; -import org.apache.jackrabbit.webdav.xml.ElementIterator; -import org.apache.jackrabbit.webdav.xml.XmlSerializable; -import org.w3c.dom.Document; -import org.w3c.dom.Element; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - -/** - * AclProperty defines a protected property that specifies the list - * of access control entries (ACEs). The set of ACEs define the privileges granted - * or denied to principals on the resource a given property instance belongs to. - *
- * RFC 3744 defines the following format for this property: - *
- * <!ELEMENT acl (ace*) >
- * <!ELEMENT ace ((principal | invert), (grant|deny), protected?, inherited?)>
- * <!ELEMENT principal (href | all | authenticated | unauthenticated | property | self)>
- * <!ELEMENT invert (principal)>
- * <!ELEMENT grant (privilege+)>
- * <!ELEMENT deny (privilege+)>
- * <!ELEMENT protected EMPTY>
- * <!ELEMENT inherited (href)>
- * 
- * - * @see Principal for details regarding DAV:principal - * @see Privilege for details regarding DAV:privilege - */ -public class AclProperty extends AbstractDavProperty> { - - private final List aces; - - /** - * Create a new AclProperty from the given ACEs. - * - * @see AclProperty#createGrantAce(Principal, Privilege[], boolean, boolean, AclResource) for a factory method to create a grant ACE. - * @see AclProperty#createDenyAce(Principal, Privilege[], boolean, boolean, AclResource) for a factory method to create a deny ACE. - */ - public AclProperty(Ace[] accessControlElements) { - this((accessControlElements == null) ? new ArrayList() : Arrays.asList(accessControlElements)); - } - - private AclProperty(List aces) { - super(SecurityConstants.ACL, true); - this.aces = aces; - } - - /** - * @return a List of Ace object. If this property defines no ACEs - * an empty list is returned. - * @see DavProperty#getValue() - */ - public List getValue() { - return aces; - } - - /** - * Build a new AclProperty object from the request body of the - * ACL method call. - * - * @param aclElement - * @return new AclProperty - * @throws DavException - */ - public static AclProperty createFromXml(Element aclElement) throws DavException { - if (!DomUtil.matches(aclElement, SecurityConstants.ACL.getName(), SecurityConstants.ACL.getNamespace())) { - throw new DavException(DavServletResponse.SC_BAD_REQUEST, "ACL request requires a DAV:acl body."); - } - List aces = new ArrayList(); - ElementIterator it = DomUtil.getChildren(aclElement, Ace.XML_ACE, SecurityConstants.NAMESPACE); - while (it.hasNext()) { - Element aceElem = it.nextElement(); - aces.add(Ace.createFromXml(aceElem)); - } - return new AclProperty(aces); - } - - public static Ace createGrantAce(Principal principal, Privilege[] privileges, boolean invert, boolean isProtected, AclResource inheritedFrom) { - return new Ace(principal, invert, privileges, true, isProtected, inheritedFrom); - } - - public static Ace createDenyAce(Principal principal, Privilege[] privileges, boolean invert, boolean isProtected, AclResource inheritedFrom) { - return new Ace(principal, invert, privileges, false, isProtected, inheritedFrom); - } - - //--------------------------------------------------------< inner class >--- - /** - * Simple WebDAV ACE implementation - */ - public static class Ace implements XmlSerializable, SecurityConstants { - - private static final String XML_ACE = "ace"; - private static final String XML_INVERT = "invert"; - private static final String XML_GRANT = "grant"; - private static final String XML_DENY = "deny"; - private static final String XML_PROTECTED = "protected"; - private static final String XML_INHERITED = "inherited"; - - private final Principal principal; - private final boolean invert; - private final Privilege[] privileges; - private final boolean grant; - private final boolean isProtected; - private final String inheritedHref; - - /** - * Private constructor - * - * @param principal - * @param invert - * @param privileges - * @param grant - * @param isProtected - * @param inherited - */ - private Ace(Principal principal, boolean invert, Privilege[] privileges, - boolean grant, boolean isProtected, AclResource inherited) { - this(principal, invert, privileges, grant, isProtected, - ((inherited != null) ? inherited.getHref() : null)); - } - - /** - * Private constructor - * - * @param principal - * @param invert - * @param privileges - * @param grant - * @param isProtected - * @param inheritedHref - */ - private Ace(Principal principal, boolean invert, Privilege[] privileges, - boolean grant, boolean isProtected, String inheritedHref) { - if (principal == null) { - throw new IllegalArgumentException("Cannot create a new ACE with 'null' principal."); - } - if (privileges == null || privileges.length == 0) { - throw new IllegalArgumentException("Cannot create a new ACE: at least a single privilege must be specified."); - } - this.principal = principal; - this.invert = invert; - this.privileges = privileges; - this.grant = grant; - this.isProtected = isProtected; - this.inheritedHref = inheritedHref; - } - - public Principal getPrincipal() { - return principal; - } - - public boolean isInvert() { - return invert; - } - - public Privilege[] getPrivileges() { - return privileges; - } - - public boolean isGrant() { - return grant; - } - - public boolean isDeny() { - return !grant; - } - - public boolean isProtected() { - return isProtected; - } - - public String getInheritedHref() { - return inheritedHref; - } - - /** - * @see XmlSerializable#toXml(Document) - */ - public Element toXml(Document document) { - Element ace = DomUtil.createElement(document, XML_ACE, SecurityConstants.NAMESPACE); - if (invert) { - Element inv = DomUtil.addChildElement(ace, XML_INVERT, SecurityConstants.NAMESPACE); - inv.appendChild(principal.toXml(document)); - } else { - ace.appendChild(principal.toXml(document)); - } - Element gd = DomUtil.addChildElement(ace, ((grant) ? XML_GRANT : XML_DENY), SecurityConstants.NAMESPACE); - for (Privilege privilege : privileges) { - gd.appendChild(privilege.toXml(document)); - } - if (isProtected) { - DomUtil.addChildElement(ace, XML_PROTECTED, SecurityConstants.NAMESPACE); - } - if (inheritedHref != null) { - Element inh = DomUtil.addChildElement(ace, XML_INHERITED, SecurityConstants.NAMESPACE); - inh.appendChild(DomUtil.hrefToXml(inheritedHref, document)); - } - return ace; - } - - private static Ace createFromXml(Element aceElement) throws DavException { - boolean invert = DomUtil.hasChildElement(aceElement, XML_INVERT, NAMESPACE); - Element pe; - if (invert) { - Element invertE = DomUtil.getChildElement(aceElement, XML_INVERT, NAMESPACE); - pe = DomUtil.getChildElement(invertE, Principal.XML_PRINCIPAL, NAMESPACE); - } else { - pe = DomUtil.getChildElement(aceElement, Principal.XML_PRINCIPAL, SecurityConstants.NAMESPACE); - } - Principal principal = Principal.createFromXml(pe); - - boolean grant = DomUtil.hasChildElement(aceElement, Ace.XML_GRANT, SecurityConstants.NAMESPACE); - Element gdElem; - if (grant) { - gdElem = DomUtil.getChildElement(aceElement, XML_GRANT, NAMESPACE); - } else { - gdElem = DomUtil.getChildElement(aceElement, XML_DENY, NAMESPACE); - } - List privilegeList = new ArrayList(); - ElementIterator privIt = DomUtil.getChildren(gdElem, Privilege.XML_PRIVILEGE, NAMESPACE); - while (privIt.hasNext()) { - Privilege pv = Privilege.getPrivilege(privIt.nextElement()); - privilegeList.add(pv); - } - Privilege[] privileges = privilegeList.toArray(new Privilege[privilegeList.size()]); - - boolean isProtected = DomUtil.hasChildElement(aceElement, XML_PROTECTED, NAMESPACE); - String inheritedHref = null; - if (DomUtil.hasChildElement(aceElement, XML_INHERITED, NAMESPACE)) { - Element inhE = DomUtil.getChildElement(aceElement, XML_INHERITED, NAMESPACE); - inheritedHref = DomUtil.getChildText(inhE, DavConstants.XML_HREF, DavConstants.NAMESPACE); - } - - return new Ace(principal, invert, privileges, grant, isProtected, inheritedHref); - } - } -} Property changes on: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/security/AclProperty.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Deleted: svn:keywords ## -1 +0,0 ## -author date id revision url \ No newline at end of property Index: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/security/AclResource.java =================================================================== --- jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/security/AclResource.java (revision 1907912) +++ jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/security/AclResource.java (nonexistent) @@ -1,70 +0,0 @@ -/* - * 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.webdav.security; - -import org.apache.jackrabbit.webdav.DavException; -import org.apache.jackrabbit.webdav.DavResource; -import org.apache.jackrabbit.webdav.DavServletResponse; -import org.apache.jackrabbit.webdav.version.DeltaVResource; -import org.apache.jackrabbit.webdav.version.report.Report; -import org.apache.jackrabbit.webdav.version.report.ReportInfo; - -/** - * AclResource... - */ -public interface AclResource extends DavResource { - - /** - * The AclResource must support the ACL method and the REPORT method in order - * to retrieve various security related reports. - * - * @see DeltaVResource#METHODS - * @see org.apache.jackrabbit.webdav.DavResource#METHODS - */ - public String METHODS = "ACL, REPORT"; - - /** - * Modify the DAV:acl property of this resource object.
- * Note: RFC 3744 limits modification of access control elements (ACEs) to - * elements that are neither inherited nor protected. - * - * @param aclProperty DAV:acl property listing the set of ACEs to be modified - * by this call. This may be a subset of all access control elements - * present on this resource object only. - * @throws DavException If the request fails. RFC 3744 defines a set of - * preconditions which must be met for a successful ACL request. - * If these conditions are violated, this method must fail with - * {@link DavServletResponse#SC_FORBIDDEN 403 (Forbidden)} or - * {@link DavServletResponse#SC_CONFLICT 409 (Conflict)} and should provide - * a detailed error condition in the response body. See - * RFC 3744 Section 8.1.1 - * (ACL Preconditions) for further details. - */ - public void alterAcl(AclProperty aclProperty) throws DavException; - - /** - * Same as {@link DeltaVResource#getReport(ReportInfo)}. - * - * @param reportInfo specifying the report details retrieved from the REPORT - * request. - * @return the requested report. - * @throws DavException in case an error occurred or if the specified - * ReportInfo is either not valid or cannot be run by this - * resource. - */ - public Report getReport(ReportInfo reportInfo) throws DavException; -} Property changes on: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/security/AclResource.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Deleted: svn:keywords ## -1 +0,0 ## -author date id revision url \ No newline at end of property Index: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/security/AclRestrictionsProperty.java =================================================================== --- jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/security/AclRestrictionsProperty.java (revision 1907912) +++ jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/security/AclRestrictionsProperty.java (nonexistent) @@ -1,107 +0,0 @@ -/* - * 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.webdav.security; - -import org.apache.jackrabbit.webdav.property.AbstractDavProperty; -import org.apache.jackrabbit.webdav.property.DavProperty; -import org.apache.jackrabbit.webdav.xml.DomUtil; -import org.w3c.dom.Document; -import org.w3c.dom.Element; - -/** - * AclRestrictionsProperty as defined by RFC 3744 Section 5.6. - * DAV:acl-restrictions: - *
- * <!ELEMENT acl-restrictions (grant-only?, no-invert?, deny-before-grant?, required-principal?)>
- * <!ELEMENT grant-only EMPTY>
- * <!ELEMENT no-invert EMPTY>
- * <!ELEMENT deny-before-grant EMPTY>
- * <!ELEMENT required-principal (all? | authenticated? | unauthenticated? | self? | href* | property*)>
- * 
- * - * @see Principal - * @see AclProperty - */ -public class AclRestrictionsProperty extends AbstractDavProperty { - - // TODO: RFC 3744 defines a distinct structure for required-principal - // than for principal. Current 'normal' principal is used instead. - - private static final String XML_GRANT_ONLY = "grant-only"; - private static final String XML_NO_INVERT = "no-invert"; - private static final String XML_DENY_BEFORE_GRANT = "deny-before-grant"; - - private final boolean grantOnly; - private final boolean noInvert; - private final boolean denyBeforeGrant; - private final Principal requiredPrincipal; - - public AclRestrictionsProperty(boolean grantOnly, boolean noInvert, boolean denyBeforeGrant, Principal requiredPrincipal) { - super(SecurityConstants.ACL_RESTRICTIONS, true); - this.grantOnly = grantOnly; - this.noInvert = noInvert; - this.denyBeforeGrant = denyBeforeGrant; - this.requiredPrincipal = requiredPrincipal; - } - - /** - * Not implemented. - * - * @throws UnsupportedOperationException - */ - public Object getValue() { - throw new UnsupportedOperationException("Not implemented. Use the property specific methods instead."); - } - - /** - * @see DavProperty#toXml(Document) - */ - @Override - public Element toXml(Document document) { - Element elem = getName().toXml(document); - if (grantOnly) { - DomUtil.addChildElement(elem, XML_GRANT_ONLY, SecurityConstants.NAMESPACE); - } - if (noInvert) { - DomUtil.addChildElement(elem, XML_NO_INVERT, SecurityConstants.NAMESPACE); - } - if (denyBeforeGrant) { - DomUtil.addChildElement(elem, XML_DENY_BEFORE_GRANT, SecurityConstants.NAMESPACE); - } - if (requiredPrincipal != null) { - elem.appendChild(requiredPrincipal.toXml(document)); - } - return elem; - } - - public boolean isGrantOnly() { - return grantOnly; - } - - public boolean isNoInvert() { - return noInvert; - } - - public boolean isDenyBeforeGrant() { - return denyBeforeGrant; - } - - public Principal getRequiredPrincipal() { - // TODO: check of should be replaced by specific required-principal... - return requiredPrincipal; - } -} Property changes on: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/security/AclRestrictionsProperty.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Deleted: svn:keywords ## -1 +0,0 ## -author date id revision url \ No newline at end of property Index: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/security/CurrentUserPrivilegeSetProperty.java =================================================================== --- jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/security/CurrentUserPrivilegeSetProperty.java (revision 1907912) +++ jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/security/CurrentUserPrivilegeSetProperty.java (nonexistent) @@ -1,90 +0,0 @@ -/* - * 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.webdav.security; - -import org.apache.jackrabbit.webdav.DavException; -import org.apache.jackrabbit.webdav.DavServletResponse; -import org.apache.jackrabbit.webdav.property.AbstractDavProperty; -import org.apache.jackrabbit.webdav.property.DavProperty; -import org.w3c.dom.Document; -import org.w3c.dom.Element; - -import java.util.Collection; -import java.util.HashSet; -import java.util.Set; - -/** - * CurrentUserPrivilegeSetProperty... - */ -public class CurrentUserPrivilegeSetProperty extends AbstractDavProperty> { - - private final Set privileges; - - /** - * Create a new instance of this property. - * - * @param privileges array privileges. - */ - public CurrentUserPrivilegeSetProperty(Privilege[] privileges) { - super(SecurityConstants.CURRENT_USER_PRIVILEGE_SET, true); - - this.privileges = new HashSet(); - for (Privilege privilege : privileges) { - if (privilege != null) { - this.privileges.add(privilege); - } - } - } - - /** - * Create a new CurrentUserPrivilegeSetProperty from a DavProperty - * as obtained from a MultiStatusResponse. - * - * @param xmlDavProperty - * @throws DavException - */ - public CurrentUserPrivilegeSetProperty(DavProperty xmlDavProperty) throws DavException { - super(xmlDavProperty.getName(), true); - if (!SecurityConstants.CURRENT_USER_PRIVILEGE_SET.equals(getName())) { - throw new DavException(DavServletResponse.SC_BAD_REQUEST, "DAV:current-user-privilege-set expected."); - } - privileges = new HashSet(); - - // parse property value - Object value = xmlDavProperty.getValue(); - if (value != null) { - if (value instanceof Element) { - privileges.add(Privilege.getPrivilege((Element)value)); - } else if (value instanceof Collection) { - for (Object entry : ((Collection) value)) { - if (entry instanceof Element) { - privileges.add(Privilege.getPrivilege((Element) entry)); - } - } - } - } - } - - /** - * @return a Collection of Privilege objects use for xml serialization. - * @see DavProperty#getValue() - * @see AbstractDavProperty#toXml(Document) - */ - public Collection getValue() { - return privileges; - } -} \ No newline at end of file Property changes on: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/security/CurrentUserPrivilegeSetProperty.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Deleted: svn:keywords ## -1 +0,0 ## -author date id revision url \ No newline at end of property Index: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/security/Principal.java =================================================================== --- jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/security/Principal.java (revision 1907912) +++ jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/security/Principal.java (nonexistent) @@ -1,189 +0,0 @@ -/* - * 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.webdav.security; - -import org.apache.jackrabbit.webdav.DavConstants; -import org.apache.jackrabbit.webdav.DavException; -import org.apache.jackrabbit.webdav.DavServletResponse; -import org.apache.jackrabbit.webdav.property.DavPropertyName; -import org.apache.jackrabbit.webdav.xml.DomUtil; -import org.apache.jackrabbit.webdav.xml.XmlSerializable; -import org.w3c.dom.Document; -import org.w3c.dom.Element; - -import java.util.HashMap; -import java.util.Map; - -/** - * Principal encapsulates the DAV:principal element which identifies - * the principal to which this ACE applies. - * RFC 3744 defines the following structure for this element: - *
- * <!ELEMENT principal (href | all | authenticated | unauthenticated | property | self)>
- * 
- */ -public class Principal implements XmlSerializable, SecurityConstants { - - public static final String XML_PRINCIPAL = "principal"; - - private static final String XML_ALL = "all"; - private static final String XML_AUTHENTICATED = "authenticated"; - private static final String XML_UNAUTHENTICATED = "unauthenticated"; - private static final String XML_SELF = "self"; - private static final String XML_PROPERTY = "property"; - - private static final int TYPE_ALL = 0; - private static final int TYPE_AUTHENTICATED = 1; - private static final int TYPE_UNAUTHENTICATED = 2; - private static final int TYPE_SELF = 3; - private static final int TYPE_PROPERTY = 4; - private static final int TYPE_HREF = 5; - - private static final Principal ALL_PRINCIPAL = new Principal(TYPE_ALL); - private static final Principal AUTHENTICATED_PRINCIPAL = new Principal(TYPE_AUTHENTICATED); - private static final Principal UNAUTHENTICATED_PRINCIPAL = new Principal(TYPE_UNAUTHENTICATED); - private static final Principal SELF_PRINCIPAL = new Principal(TYPE_SELF); - - private static final Map PROP_PRINCIPALS = new HashMap(); - - private final int type; - private DavPropertyName propertyName; - private String href; - - private Principal(int type) { - this.type = type; - } - - private Principal(DavPropertyName propertyName) { - this.type = TYPE_PROPERTY; - this.propertyName = propertyName; - } - - private Principal(String href) { - this.type = TYPE_HREF; - this.href = href; - } - - /** - * @return href if this Principal is a href-typed principal, null - * otherwise. - */ - public String getHref() { - return href; - } - - /** - * @return propertyName if this Principal is a property-principal, - * null otherwise. - */ - public DavPropertyName getPropertyName() { - return propertyName; - } - - /** - * @see XmlSerializable#toXml(Document) - */ - public Element toXml(Document document) { - Element pEl = DomUtil.createElement(document, XML_PRINCIPAL, NAMESPACE); - switch (type) { - case TYPE_ALL: - DomUtil.addChildElement(pEl, XML_ALL, NAMESPACE); - break; - case TYPE_AUTHENTICATED: - DomUtil.addChildElement(pEl, XML_AUTHENTICATED, NAMESPACE); - break; - case TYPE_UNAUTHENTICATED: - DomUtil.addChildElement(pEl, XML_UNAUTHENTICATED, NAMESPACE); - break; - case TYPE_SELF: - DomUtil.addChildElement(pEl, XML_SELF, NAMESPACE); - break; - case TYPE_PROPERTY: - Element prop = DomUtil.addChildElement(pEl, XML_PROPERTY, NAMESPACE); - prop.appendChild(propertyName.toXml(document)); - break; - case TYPE_HREF: - Element hrefEl = DomUtil.hrefToXml(href, document); - pEl.appendChild(hrefEl); - break; - // no default - } - return pEl; - } - - public static Principal getAllPrincipal() { - return ALL_PRINCIPAL; - } - - public static Principal getAuthenticatedPrincipal() { - return AUTHENTICATED_PRINCIPAL; - } - - public static Principal getUnauthenticatedPrincipal() { - return UNAUTHENTICATED_PRINCIPAL; - } - - public static Principal getSelfPrincipal() { - return SELF_PRINCIPAL; - } - - public static Principal getPropertyPrincipal(DavPropertyName propertyName) { - if (propertyName == null) { - throw new IllegalArgumentException("Property-Principal must contain a valid property name."); - } - // there is a limited amount of properties, that can be used - // for a Property-Principal - if (PROP_PRINCIPALS.containsKey(propertyName)) { - return PROP_PRINCIPALS.get(propertyName); - } else { - Principal p = new Principal(propertyName); - PROP_PRINCIPALS.put(propertyName, p); - return p; - } - } - - public static Principal getHrefPrincipal(String href) { - if (href == null) { - throw new IllegalArgumentException("Href-Principal must contain a valid href."); - } - return new Principal(href); - } - - public static Principal createFromXml(Element principalElement) throws DavException { - if (!DomUtil.matches(principalElement, XML_PRINCIPAL, NAMESPACE)) { - throw new DavException(DavServletResponse.SC_BAD_REQUEST, "DAV:principal element expected."); - } - if (DomUtil.hasChildElement(principalElement, XML_ALL, NAMESPACE)) { - return ALL_PRINCIPAL; - } else if (DomUtil.hasChildElement(principalElement, XML_SELF, NAMESPACE)) { - return SELF_PRINCIPAL; - } else if (DomUtil.hasChildElement(principalElement, XML_AUTHENTICATED, NAMESPACE)) { - return AUTHENTICATED_PRINCIPAL; - } else if (DomUtil.hasChildElement(principalElement, XML_UNAUTHENTICATED, NAMESPACE)) { - return UNAUTHENTICATED_PRINCIPAL; - } else if (DomUtil.hasChildElement(principalElement, DavConstants.XML_HREF, DavConstants.NAMESPACE)) { - String href = DomUtil.getChildText(principalElement, DavConstants.XML_HREF, DavConstants.NAMESPACE); - return getHrefPrincipal(href); - } else if (DomUtil.hasChildElement(principalElement, XML_PROPERTY, NAMESPACE)) { - Element propEl = DomUtil.getChildElement(principalElement, XML_PROPERTY, NAMESPACE); - DavPropertyName pn = DavPropertyName.createFromXml(DomUtil.getFirstChildElement(propEl)); - return getPropertyPrincipal(pn); - } else { - throw new DavException(DavServletResponse.SC_BAD_REQUEST, "Invalid structure inside DAV:principal element."); - } - } -} Property changes on: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/security/Principal.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Deleted: svn:keywords ## -1 +0,0 ## -author date id revision url \ No newline at end of property Index: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/security/Privilege.java =================================================================== --- jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/security/Privilege.java (revision 1907912) +++ jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/security/Privilege.java (nonexistent) @@ -1,204 +0,0 @@ -/* - * 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.webdav.security; - -import org.apache.jackrabbit.webdav.DavException; -import org.apache.jackrabbit.webdav.DavServletResponse; -import org.apache.jackrabbit.webdav.xml.DomUtil; -import org.apache.jackrabbit.webdav.xml.Namespace; -import org.apache.jackrabbit.webdav.xml.XmlSerializable; -import org.w3c.dom.Document; -import org.w3c.dom.Element; - -import java.util.HashMap; -import java.util.Map; - -/** - * Privilege - */ -public class Privilege implements XmlSerializable { - - public static final String XML_PRIVILEGE = "privilege"; - - /** - * Map for registered privileges - */ - private static final Map REGISTERED_PRIVILEGES = new HashMap(); - - //-------------------------------------< Privileges defined by RFC 3744 >--- - /** - * The read privilege controls methods that return information about the - * state of the resource, including the resource's properties. Affected - * methods include GET and PROPFIND and OPTIONS. - * - * @see RFC 3744 Section 3.1. DAV:read Privilege - */ - public static final Privilege PRIVILEGE_READ = getPrivilege("read", SecurityConstants.NAMESPACE); - /** - * The write privilege controls methods that lock a resource or modify the - * content, dead properties, or (in the case of a collection) membership of - * the resource, such as PUT and PROPPATCH. - * - * @see RFC 3744 Section 3.2. DAV:write Privilege - */ - public static final Privilege PRIVILEGE_WRITE = getPrivilege("write", SecurityConstants.NAMESPACE); - /** - * The DAV:write-properties privilege controls methods that modify the dead - * properties of the resource, such as PROPPATCH. Whether this privilege may - * be used to control access to any live properties is determined by the - * implementation. - * - * @see RFC 3744 Section 3.3. DAV:write-properties Privilege - */ - public static final Privilege PRIVILEGE_WRITE_PROPERTIES = getPrivilege("write-properties", SecurityConstants.NAMESPACE); - /** - * The DAV:write-content privilege controls methods that modify the content - * of an existing resource, such as PUT. - * - * @see RFC 3744 Section 3.4. DAV:write-content Privilege - */ - public static final Privilege PRIVILEGE_WRITE_CONTENT = getPrivilege("write-content", SecurityConstants.NAMESPACE); - /** - * The DAV:unlock privilege controls the use of the UNLOCK method by a - * principal other than the lock owner (the principal that created a lock - * can always perform an UNLOCK). - * - * @see RFC 3744 Section 3.5. DAV:unlock Privilege - */ - public static final Privilege PRIVILEGE_UNLOCK = getPrivilege("unlock", SecurityConstants.NAMESPACE); - /** - * The DAV:read-acl privilege controls the use of PROPFIND to retrieve the - * DAV:acl property of the resource. - * - * @see RFC 3744 Section 3.6. DAV:read-acl Privilege - */ - public static final Privilege PRIVILEGE_READ_ACL = getPrivilege("read-acl", SecurityConstants.NAMESPACE); - /** - * The DAV:read-current-user-privilege-set privilege controls the use of - * PROPFIND to retrieve the DAV:current-user-privilege-set property of the - * resource. - * - * @see RFC 3744 Section 3.7. DAV:"read-current-user-privilege-set Privilege - */ - public static final Privilege PRIVILEGE_READ_CURRENT_USER_PRIVILEGE_SET = getPrivilege("read-current-user-privilege-set", SecurityConstants.NAMESPACE); - /** - * The DAV:write-acl privilege controls use of the ACL method to modify the - * DAV:acl property of the resource. - * - * @see RFC 3744 Section 3.8. DAV:write-acl Privilege - */ - public static final Privilege PRIVILEGE_WRITE_ACL = getPrivilege("write-acl", SecurityConstants.NAMESPACE); - /** - * The DAV:bind privilege allows a method to add a new member URL to the - * specified collection (for example via PUT or MKCOL). It is ignored for - * resources that are not collections. - * - * @see RFC 3744 Section 3.9. DAV:bind Privilege - */ - public static final Privilege PRIVILEGE_BIND = getPrivilege("bind", SecurityConstants.NAMESPACE); - /** - * The DAV:unbind privilege allows a method to remove a member URL from the - * specified collection (for example via DELETE or MOVE). It is ignored for - * resources that are not collections. - * - * @see RFC 3744 Section 3.10. DAV:unbind Privilege - */ - public static final Privilege PRIVILEGE_UNBIND = getPrivilege("unbind", SecurityConstants.NAMESPACE); - /** - * DAV:all is an aggregate privilege that contains the entire set of - * privileges that can be applied to the resource. - * - * @see RFC 3744 Section 3.11. DAV:all Privilege - */ - public static final Privilege PRIVILEGE_ALL = getPrivilege("all", SecurityConstants.NAMESPACE); - - private final String privilege; - private final Namespace namespace; - - /** - * Private constructor - * - * @param privilege - * @param namespace - */ - private Privilege(String privilege, Namespace namespace) { - this.privilege = privilege; - this.namespace = namespace; - } - - /** - * @return The local name of this Privilege. - */ - public String getName() { - return privilege; - } - - /** - * @return The namespace of this Privilege. - */ - public Namespace getNamespace() { - return namespace; - } - - /** - * @see XmlSerializable#toXml(Document) - */ - public Element toXml(Document document) { - Element privEl = DomUtil.createElement(document, XML_PRIVILEGE, SecurityConstants.NAMESPACE); - DomUtil.addChildElement(privEl, privilege, namespace); - return privEl; - } - - /** - * Factory method to create/retrieve a Privilege. - * - * @param privilege - * @param namespace - * @return - */ - public static Privilege getPrivilege(String privilege, Namespace namespace) { - if (privilege == null) { - throw new IllegalArgumentException("'null' is not a valid privilege."); - } - if (namespace == null) { - namespace = Namespace.EMPTY_NAMESPACE; - } - String key = "{" + namespace.getURI() + "}" + privilege; - if (REGISTERED_PRIVILEGES.containsKey(key)) { - return REGISTERED_PRIVILEGES.get(key); - } else { - Privilege p = new Privilege(privilege, namespace); - REGISTERED_PRIVILEGES.put(key, p); - return p; - } - } - - /** - * Factory method to create/retrieve a Privilege from the given - * DAV:privilege element. - * - * @param privilege - * @return - */ - public static Privilege getPrivilege(Element privilege) throws DavException { - if (!DomUtil.matches(privilege, XML_PRIVILEGE, SecurityConstants.NAMESPACE)) { - throw new DavException(DavServletResponse.SC_BAD_REQUEST, "DAV:privilege element expected."); - } - Element el = DomUtil.getFirstChildElement(privilege); - return getPrivilege(el.getLocalName(), DomUtil.getNamespace(el)); - } -} Property changes on: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/security/Privilege.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Deleted: svn:keywords ## -1 +0,0 ## -author date id revision url \ No newline at end of property Index: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/security/SecurityConstants.java =================================================================== --- jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/security/SecurityConstants.java (revision 1907912) +++ jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/security/SecurityConstants.java (nonexistent) @@ -1,110 +0,0 @@ -/* - * 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.webdav.security; - -import org.apache.jackrabbit.webdav.DavConstants; -import org.apache.jackrabbit.webdav.DavMethods; -import org.apache.jackrabbit.webdav.property.DavPropertyName; -import org.apache.jackrabbit.webdav.property.HrefProperty; -import org.apache.jackrabbit.webdav.property.ResourceType; -import org.apache.jackrabbit.webdav.xml.Namespace; - -/** - * SecurityConstants interface lists constants defined by - * RFC 3744 (WebDAV Access - * Control Protocol). - */ -public interface SecurityConstants { - - /** - * Default Namespace constant - */ - public static final Namespace NAMESPACE = DavConstants.NAMESPACE; - - /** - * Principal resources must define DAV:principal XML element in the value - * of the DAV:resourcetype property. - */ - public static int PRINCIPAL_RESOURCETYPE = ResourceType.registerResourceType("principal", NAMESPACE); - - //---< Property Names for Principal Resource >------------------------------ - /** - * Protected href property DAV:principal-URL for principal resources. - * @see HrefProperty - */ - public static final DavPropertyName PRINCIPAL_URL = DavPropertyName.create("principal-URL", NAMESPACE); - /** - * Protected href property DAV:alternate-URI-set for principal resources. - * @see HrefProperty - */ - public static final DavPropertyName ALTERNATE_URI_SET = DavPropertyName.create("alternate-URI-set", NAMESPACE); - /** - * Protected href property DAV:group-member-set for principal resources. - * @see HrefProperty - */ - public static final DavPropertyName GROUP_MEMBER_SET = DavPropertyName.create("group-member-set", NAMESPACE); - /** - * Protected href property DAV:group-membership for principal resources. - * @see HrefProperty - */ - public static final DavPropertyName GROUP_MEMBERSHIP = DavPropertyName.create("group-membership", NAMESPACE); - - //---< Property Names for DavResource >------------------------------------- - /** - * Protected href property DAV:owner - * @see HrefProperty - */ - public static final DavPropertyName OWNER = DavPropertyName.create("owner", NAMESPACE); - /** - * Protected href property DAV:group - * @see HrefProperty - */ - public static final DavPropertyName GROUP = DavPropertyName.create("group", NAMESPACE); - /** - * Protected property DAV:supported-privilege-set - * @see CurrentUserPrivilegeSetProperty - */ - public static final DavPropertyName SUPPORTED_PRIVILEGE_SET = DavPropertyName.create("supported-privilege-set", NAMESPACE); - /** - * Protected property DAV:current-user-privilege-set - * @see CurrentUserPrivilegeSetProperty - */ - public static final DavPropertyName CURRENT_USER_PRIVILEGE_SET = DavPropertyName.create("current-user-privilege-set", NAMESPACE); - /** - * Protected property DAV:acl. Note, that DAV:acl property may be altered - * with a ACL request. - * - * @see AclProperty - * @see DavMethods#METHOD_ACL - */ - public static final DavPropertyName ACL = DavPropertyName.create("acl", NAMESPACE); - /** - * Protected property DAV:acl-restrictions - * @see AclRestrictionsProperty - */ - public static final DavPropertyName ACL_RESTRICTIONS = DavPropertyName.create("acl-restrictions", NAMESPACE); - /** - * Protected href property DAV:inherited-acl-set - * @see HrefProperty - */ - public static final DavPropertyName INHERITED_ACL_SET = DavPropertyName.create("inherited-acl-set", NAMESPACE); - /** - * Protected href property DAV:principal-collection-set - * @see HrefProperty - */ - public static final DavPropertyName PRINCIPAL_COLLECTION_SET = DavPropertyName.create("principal-collection-set", NAMESPACE); -} Property changes on: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/security/SecurityConstants.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Deleted: svn:keywords ## -1 +0,0 ## -author date id revision url \ No newline at end of property Index: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/security/SupportedPrivilege.java =================================================================== --- jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/security/SupportedPrivilege.java (revision 1907912) +++ jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/security/SupportedPrivilege.java (nonexistent) @@ -1,139 +0,0 @@ -/* - * 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.webdav.security; - -import java.util.ArrayList; -import java.util.List; - -import org.apache.jackrabbit.webdav.DavException; -import org.apache.jackrabbit.webdav.DavServletResponse; -import org.apache.jackrabbit.webdav.xml.DomUtil; -import org.apache.jackrabbit.webdav.xml.ElementIterator; -import org.apache.jackrabbit.webdav.xml.Namespace; -import org.apache.jackrabbit.webdav.xml.XmlSerializable; -import org.w3c.dom.Document; -import org.w3c.dom.Element; - -/** - * SupportedPrivilege... - */ -public class SupportedPrivilege implements XmlSerializable { - - private static final String XML_SUPPORTED_PRIVILEGE = "supported-privilege"; - private static final String XML_ABSTRACT = "abstract"; - private static final String XML_DESCRIPTION = "description"; - - private final Privilege privilege; - private final boolean isAbstract; - private final String description; - private final String descriptionLanguage; - private final SupportedPrivilege[] supportedPrivileges; - - /** - * - * @param privilege - * @param description - * @param descriptionLanguage - * @param isAbstract - * @param supportedPrivileges - */ - public SupportedPrivilege(Privilege privilege, String description, - String descriptionLanguage, boolean isAbstract, - SupportedPrivilege[] supportedPrivileges) { - if (privilege == null) { - throw new IllegalArgumentException("DAV:supported-privilege element must contain a single privilege."); - } - this.privilege = privilege; - this.description = description; - this.descriptionLanguage = descriptionLanguage; - this.isAbstract = isAbstract; - this.supportedPrivileges = supportedPrivileges; - } - - /** - * @see XmlSerializable#toXml(Document) - */ - public Element toXml(Document document) { - Element spElem = DomUtil.createElement(document, XML_SUPPORTED_PRIVILEGE, SecurityConstants.NAMESPACE); - spElem.appendChild(privilege.toXml(document)); - if (isAbstract) { - DomUtil.addChildElement(spElem, XML_ABSTRACT, SecurityConstants.NAMESPACE); - } - if (description != null) { - Element desc = DomUtil.addChildElement(spElem, XML_DESCRIPTION, SecurityConstants.NAMESPACE, description); - if (descriptionLanguage != null) { - DomUtil.setAttribute(desc, "lang", Namespace.XML_NAMESPACE, descriptionLanguage); - } - } - if (supportedPrivileges != null) { - for (SupportedPrivilege supportedPrivilege : supportedPrivileges) { - spElem.appendChild(supportedPrivilege.toXml(document)); - } - } - return spElem; - } - - public Privilege getPrivilege() { - return privilege; - } - - public boolean isAbstract() { - return isAbstract; - } - - public SupportedPrivilege[] getSupportedPrivileges() { - return supportedPrivileges; - } - - /** - * Factory method to create/retrieve a SupportedPrivilege from the given - * DAV:privilege element. - * - * @param privilege - * @return - */ - static SupportedPrivilege getSupportedPrivilege(Element supportedPrivilege) throws DavException { - if (!DomUtil.matches(supportedPrivilege, XML_SUPPORTED_PRIVILEGE, SecurityConstants.NAMESPACE)) { - throw new DavException(DavServletResponse.SC_BAD_REQUEST, "DAV:supported-privilege element expected."); - } - boolean isAbstract = false; - Privilege privilege = null; - String description = null; - String descriptionLanguage = null; - List sp = new ArrayList(); - - ElementIterator children = DomUtil.getChildren(supportedPrivilege); - while (children.hasNext()) { - Element child = children.next(); - if (child.getLocalName().equals(XML_ABSTRACT)) { - isAbstract = true; - } else if (child.getLocalName().equals(Privilege.XML_PRIVILEGE)) { - privilege = Privilege.getPrivilege(child); - } else if (child.getLocalName().equals(XML_DESCRIPTION)) { - description = child.getLocalName(); - if (child.hasAttribute(descriptionLanguage)) { - descriptionLanguage = child.getAttribute(descriptionLanguage); - } - } else if (child.getLocalName().equals(XML_SUPPORTED_PRIVILEGE)) { - sp.add(getSupportedPrivilege(child)); - } - } - return new SupportedPrivilege(privilege, description, - descriptionLanguage, isAbstract, - sp.toArray(new SupportedPrivilege[sp.size()])); - } -} Property changes on: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/security/SupportedPrivilege.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Deleted: svn:keywords ## -1 +0,0 ## -author date id revision url \ No newline at end of property Index: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/security/SupportedPrivilegeSetProperty.java =================================================================== --- jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/security/SupportedPrivilegeSetProperty.java (revision 1907912) +++ jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/security/SupportedPrivilegeSetProperty.java (nonexistent) @@ -1,95 +0,0 @@ -/* - * 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.webdav.security; - -import org.apache.jackrabbit.webdav.DavException; -import org.apache.jackrabbit.webdav.DavServletResponse; -import org.apache.jackrabbit.webdav.property.AbstractDavProperty; -import org.apache.jackrabbit.webdav.property.DavProperty; -import org.w3c.dom.Element; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.List; -import java.util.Collections; - -/** - * SupportedPrivilegeSetProperty defines the - * {@link SecurityConstants#SUPPORTED_PRIVILEGE_SET} property, used to identify - * the privileges defined for the resource. RFC 3744 defines the the following - * structure for this property: - *
- * <!ELEMENT supported-privilege-set (supported-privilege*)>
- * <!ELEMENT supported-privilege (privilege, abstract?, description, supported-privilege*)>
- * <!ELEMENT privilege ANY>
- * <!ELEMENT abstract EMPTY>
- * <!ELEMENT description #PCDATA>
- * 
- * - * @see SupportedPrivilege - * @see Privilege - */ -public class SupportedPrivilegeSetProperty extends AbstractDavProperty> { - - private final SupportedPrivilege[] supportedPrivileges; - - /** - * Create a new SupportedPrivilegeSetProperty. - * - * @param supportedPrivileges - */ - public SupportedPrivilegeSetProperty(SupportedPrivilege[] supportedPrivileges) { - super(SecurityConstants.SUPPORTED_PRIVILEGE_SET, true); - this.supportedPrivileges = supportedPrivileges; - } - - public SupportedPrivilegeSetProperty(DavProperty p) throws DavException { - super(SecurityConstants.SUPPORTED_PRIVILEGE_SET, true); - if (!SecurityConstants.SUPPORTED_PRIVILEGE_SET.equals(getName())) { - throw new DavException(DavServletResponse.SC_BAD_REQUEST, "DAV:supported-privilege-set expected."); - } - - List supportedPrivs = new ArrayList(); - - for (Object obj : Collections.singletonList(p.getValue())) { - if (obj instanceof Element) { - supportedPrivs.add(SupportedPrivilege.getSupportedPrivilege((Element) obj)); - } else if (obj instanceof Collection) { - for (Object entry : ((Collection) obj)) { - if (entry instanceof Element) { - supportedPrivs.add(SupportedPrivilege.getSupportedPrivilege((Element) entry)); - } - } - } - } - supportedPrivileges = supportedPrivs.toArray(new SupportedPrivilege[supportedPrivs.size()]); - } - - /** - * @return List of {@link SupportedPrivilege}s. - */ - public List getValue() { - List l; - if (supportedPrivileges == null) { - l = Collections.emptyList(); - } else { - l = Arrays.asList(supportedPrivileges); - } - return l; - } -} \ No newline at end of file Property changes on: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/security/SupportedPrivilegeSetProperty.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Deleted: svn:keywords ## -1 +0,0 ## -author date id revision url \ No newline at end of property Index: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/security/package-info.java =================================================================== --- jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/security/package-info.java (revision 1907912) +++ jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/security/package-info.java (nonexistent) @@ -1,18 +0,0 @@ -/* - * 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. - */ -@org.osgi.annotation.versioning.Version("1.0.0") -package org.apache.jackrabbit.webdav.security; Property changes on: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/security/package-info.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/security/report/AbstractSecurityReport.java =================================================================== --- jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/security/report/AbstractSecurityReport.java (revision 1907912) +++ jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/security/report/AbstractSecurityReport.java (nonexistent) @@ -1,82 +0,0 @@ -/* - * 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.webdav.security.report; - -import org.apache.jackrabbit.webdav.DavConstants; -import org.apache.jackrabbit.webdav.DavException; -import org.apache.jackrabbit.webdav.DavResource; -import org.apache.jackrabbit.webdav.DavServletResponse; -import org.apache.jackrabbit.webdav.MultiStatus; -import org.apache.jackrabbit.webdav.MultiStatusResponse; -import org.apache.jackrabbit.webdav.version.report.AbstractReport; -import org.apache.jackrabbit.webdav.version.report.Report; -import org.apache.jackrabbit.webdav.version.report.ReportInfo; -import org.w3c.dom.Document; -import org.w3c.dom.Element; - -/** - * AbstractSecurityReport covers basic validation and utilities - * common to the majority of the reports defined within RFC 3744. - */ -public abstract class AbstractSecurityReport extends AbstractReport { - - protected MultiStatusResponse[] responses; - - /** - * Always returns true. - * - * @return true - */ - public boolean isMultiStatusReport() { - return true; - } - - /** - * Checks if the given resource and report info are not null, - * that the requested report type matches this implementation and that no - * other Depth header than 0 is present. - * - * @param resource - * @param info - * @throws DavException - */ - public void init(DavResource resource, ReportInfo info) throws DavException { - if (resource == null || info == null) { - throw new DavException(DavServletResponse.SC_BAD_REQUEST, "Unable to run report: WebDAV Resource and ReportInfo must not be null."); - } - if (!getType().isRequestedReportType(info)) { - throw new DavException(DavServletResponse.SC_BAD_REQUEST, "Expected report type: '" + getType().getReportName() + "', found: '" + info.getReportName() + ";" + "'."); - } - if (info.getDepth() > DavConstants.DEPTH_0) { - throw new DavException(DavServletResponse.SC_BAD_REQUEST, "Invalid Depth header: " + info.getDepth()); - } - } - - /** - * @return DAV:multistatus element listing the matching resources. - * @see Report#toXml(Document) - */ - public Element toXml(Document document) { - MultiStatus ms = new MultiStatus(); - if (responses != null) { - for (MultiStatusResponse response : responses) { - ms.addResponse(response); - } - } - return ms.toXml(document); - } -} Property changes on: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/security/report/AbstractSecurityReport.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Deleted: svn:keywords ## -1 +0,0 ## -author date id revision url \ No newline at end of property Index: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/security/report/AclPrincipalReport.java =================================================================== --- jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/security/report/AclPrincipalReport.java (revision 1907912) +++ jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/security/report/AclPrincipalReport.java (nonexistent) @@ -1,96 +0,0 @@ -/* - * 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.webdav.security.report; - -import org.apache.jackrabbit.webdav.DavException; -import org.apache.jackrabbit.webdav.DavResource; -import org.apache.jackrabbit.webdav.DavResourceLocator; -import org.apache.jackrabbit.webdav.DavServletResponse; -import org.apache.jackrabbit.webdav.MultiStatusResponse; -import org.apache.jackrabbit.webdav.property.DavProperty; -import org.apache.jackrabbit.webdav.security.AclProperty; -import org.apache.jackrabbit.webdav.security.SecurityConstants; -import org.apache.jackrabbit.webdav.version.report.Report; -import org.apache.jackrabbit.webdav.version.report.ReportInfo; -import org.apache.jackrabbit.webdav.version.report.ReportType; - -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -/** - * The AclPrincipalReport report returns the requested property set - * for all principals in the DAV:acl property, that are identified by http(s) - * URLs or by a DAV:property principal. - *

- * The request body MUST be a DAV:acl-principal-prop-set XML element: - *

- * <!ELEMENT acl-principal-prop-set ANY>
- * ANY value: a sequence of one or more elements, with at most one
- *            DAV:prop element.
- * prop: see RFC 2518, Section 12.11
- * 
- * The response body MUST be a DAV:multistatus element containing a - * DAV:response element for each principal identified by a http(s) URL listed - * in a DAV:principal XML element of an ACE within the DAV:acl property of the - * resource this report is requested for. - */ -public class AclPrincipalReport extends AbstractSecurityReport { - - public static final String REPORT_NAME = "acl-principal-prop-set"; - - /** - * The report type - */ - public static final ReportType REPORT_TYPE = ReportType.register(REPORT_NAME, SecurityConstants.NAMESPACE, AclPrincipalReport.class); - - /** - * @see Report#getType() - */ - public ReportType getType() { - return REPORT_TYPE; - } - - /** - * @see Report#init(DavResource, ReportInfo) - */ - @Override - public void init(DavResource resource, ReportInfo info) throws DavException { - super.init(resource, info); - // build the DAV:responses objects. - DavProperty acl = resource.getProperty(SecurityConstants.ACL); - if (!(acl instanceof AclProperty)) { - throw new DavException(DavServletResponse.SC_INTERNAL_SERVER_ERROR, "DAV:acl property expected."); - } - - DavResourceLocator loc = resource.getLocator(); - Map respMap = new HashMap(); - List list = (List) ((AclProperty)acl).getValue(); - for (AclProperty.Ace ace : list) { - String href = normalizeResourceHref(ace.getPrincipal().getHref()); - if (href == null || respMap.containsKey(href)) { - // ignore non-href principals and principals that have been listed before - continue; - } - // href-principal that has not been found before - DavResourceLocator princLocator = loc.getFactory().createResourceLocator(loc.getPrefix(), href); - DavResource principalResource = resource.getFactory().createResource(princLocator, resource.getSession()); - respMap.put(href, new MultiStatusResponse(principalResource, info.getPropertyNameSet())); - } - this.responses = respMap.values().toArray(new MultiStatusResponse[respMap.size()]); - } -} Property changes on: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/security/report/AclPrincipalReport.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Deleted: svn:keywords ## -1 +0,0 ## -author date id revision url \ No newline at end of property Index: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/security/report/PrincipalMatchReport.java =================================================================== --- jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/security/report/PrincipalMatchReport.java (revision 1907912) +++ jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/security/report/PrincipalMatchReport.java (nonexistent) @@ -1,115 +0,0 @@ -/* - * 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.webdav.security.report; - -import org.apache.jackrabbit.webdav.DavException; -import org.apache.jackrabbit.webdav.DavResource; -import org.apache.jackrabbit.webdav.DavServletResponse; -import org.apache.jackrabbit.webdav.MultiStatusResponse; -import org.apache.jackrabbit.webdav.property.DavPropertyName; -import org.apache.jackrabbit.webdav.security.SecurityConstants; -import org.apache.jackrabbit.webdav.version.report.Report; -import org.apache.jackrabbit.webdav.version.report.ReportInfo; -import org.apache.jackrabbit.webdav.version.report.ReportType; -import org.apache.jackrabbit.webdav.xml.DomUtil; -import org.w3c.dom.Element; - -/** - * PrincipalMatchReport can be request for any collection resources. - * The resulting report identifies member resources that either represent the - * requesting principal ("principal resources") or contain a specified property - * that matches the requesting principal in its value. For the first match - * the request body must contain a DAV:self element, for the latter a - * DAV:principal-property element which in turn specifies the property to - * be examined. - *

- * The request body MUST be a DAV:principal-match XML element: - *

- * <!ELEMENT principal-match ((principal-property | self), prop?)>
- * <!ELEMENT principal-property ANY>
- * ANY value: an element whose value identifies a property. The value of this
- * property typically contains an href element referring to a principal.
- * <!ELEMENT self EMPTY>
- * prop: see RFC 2518, Section 12.11
- * 
- * The response body of a successful report must contain a DAV:multistatus - * element. Each matching member is present with a separate DAV:response element. - */ -public class PrincipalMatchReport extends AbstractSecurityReport { - - public static final String XML_PRINCIPAL_PROPERTY = "principal-property"; - public static final String XML_SELF = "self"; - - /** - * The report name - */ - public static final String REPORT_NAME = "principal-match"; - - /** - * The report type - */ - public static final ReportType REPORT_TYPE = ReportType.register(REPORT_NAME, SecurityConstants.NAMESPACE, PrincipalMatchReport.class); - - private DavPropertyName principalPropertyName; - - /** - * @see Report#getType() - */ - public ReportType getType() { - return REPORT_TYPE; - } - - /** - * @see Report#init(DavResource, ReportInfo) - */ - @Override - public void init(DavResource resource, ReportInfo info) throws DavException { - super.init(resource, info); - if (info.containsContentElement(XML_PRINCIPAL_PROPERTY, SecurityConstants.NAMESPACE)) { - Element pp = info.getContentElement(XML_PRINCIPAL_PROPERTY, SecurityConstants.NAMESPACE); - principalPropertyName = DavPropertyName.createFromXml(DomUtil.getFirstChildElement(pp)); - } else if (info.containsContentElement(XML_SELF, SecurityConstants.NAMESPACE)) { - principalPropertyName = SecurityConstants.PRINCIPAL_URL; - } else { - throw new DavException(DavServletResponse.SC_BAD_REQUEST, "DAV:self or DAV:principal-property element required within report info."); - } - } - - //------------------------------------< implementation specific methods >--- - /** - * Retrieve the property name that indicates which property must be search - * for matching principals.
- * Note, that the search result must be converted to {@link MultiStatusResponse}s - * that must be returned back to this report. - * - * @return property name which should be check for match with the current - * user. - * @see #setResponses(MultiStatusResponse[]) - */ - public DavPropertyName getPrincipalPropertyName() { - return principalPropertyName; - } - - /** - * Write the result(s) of the match back to the report. - * - * @param responses - */ - public void setResponses(MultiStatusResponse[] responses) { - this.responses = responses; - } -} Property changes on: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/security/report/PrincipalMatchReport.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Deleted: svn:keywords ## -1 +0,0 ## -author date id revision url \ No newline at end of property Index: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/security/report/PrincipalSearchReport.java =================================================================== --- jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/security/report/PrincipalSearchReport.java (revision 1907912) +++ jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/security/report/PrincipalSearchReport.java (nonexistent) @@ -1,184 +0,0 @@ -/* - * 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.webdav.security.report; - -import org.apache.jackrabbit.webdav.DavConstants; -import org.apache.jackrabbit.webdav.DavException; -import org.apache.jackrabbit.webdav.DavResource; -import org.apache.jackrabbit.webdav.DavServletResponse; -import org.apache.jackrabbit.webdav.MultiStatusResponse; -import org.apache.jackrabbit.webdav.property.DavPropertyNameSet; -import org.apache.jackrabbit.webdav.property.HrefProperty; -import org.apache.jackrabbit.webdav.security.SecurityConstants; -import org.apache.jackrabbit.webdav.version.report.Report; -import org.apache.jackrabbit.webdav.version.report.ReportInfo; -import org.apache.jackrabbit.webdav.version.report.ReportType; -import org.apache.jackrabbit.webdav.xml.DomUtil; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.w3c.dom.Element; - -import java.util.List; - -/** - * The PrincipalSearchReport performs a search for all principals - * that match the search criteria specified in the request. - *

- * The following XML structure is required in the request body: - *

- * <!ELEMENT principal-property-search ((property-search+), prop?, apply-to-principal-collection-set?) >
- * <!ELEMENT property-search (prop, match) >
- *  prop: see RFC 2518, Section 12.11
- * <!ELEMENT match #PCDATA >
- * <!ELEMENT apply-to-principal-collection-set #EMPTY >
- * 
- * DAV:property-search contains lists the properties to be - * searched inside the DAV:prop element and the query string inside the DAV:match - * element. Multiple DAV:property-search elements or multiple elements within the - * DAV:prop element will be interpreted with a logical AND. - *

- * DAV:prop lists the property names to be reported in the - * response for each of the principle resources found. - *

- * DAV:apply-to-principal-collection-set: Optional empty element. - * If present in the request body the search will be executed over all members - * of the collections that are listed as values in the DAV:principal-collection-set - * property present on the resource the report has been requested for. - * Otherwise the search is limited to all members (at any depth) of that resource - * itself. - *

- * The response body must contain a single DAV:multistatus XML element. - */ -public class PrincipalSearchReport extends AbstractSecurityReport { - - private static Logger log = LoggerFactory.getLogger(PrincipalSearchReport.class); - - public static final String XML_APPLY_TO_PRINCIPAL_COLLECTION_SET = "apply-to-principal-collection-set"; - public static final String XML_PROPERTY_SEARCH = "property-search"; - public static final String XML_MATCH = "match"; - - /** - * The report name - */ - public static final String REPORT_NAME = "principal-property-search"; - - /** - * The report type - */ - public static final ReportType REPORT_TYPE = ReportType.register(REPORT_NAME, SecurityConstants.NAMESPACE, PrincipalSearchReport.class); - - private String[] searchRoots; - private SearchArgument[] searchArguments; - - /** - * @see Report#getType() - */ - public ReportType getType() { - return REPORT_TYPE; - } - - /** - * @see Report#init(DavResource, ReportInfo) - */ - @Override - public void init(DavResource resource, ReportInfo info) throws DavException { - super.init(resource, info); - // make sure the request body contains all mandatory elements - if (!info.containsContentElement(XML_PROPERTY_SEARCH, SecurityConstants.NAMESPACE)) { - throw new DavException(DavServletResponse.SC_BAD_REQUEST, "Request body must contain at least a single DAV:property-search element."); - } - List psElements = info.getContentElements(XML_PROPERTY_SEARCH, SecurityConstants.NAMESPACE); - searchArguments = new SearchArgument[psElements.size()]; - int i = 0; - for (Element psElement : psElements) { - searchArguments[i++] = new SearchArgument(psElement); - } - - if (info.containsContentElement(XML_APPLY_TO_PRINCIPAL_COLLECTION_SET, SecurityConstants.NAMESPACE)) { - HrefProperty p = new HrefProperty(resource.getProperty(SecurityConstants.PRINCIPAL_COLLECTION_SET)); - searchRoots = p.getHrefs().toArray(new String[0]); - } else { - searchRoots = new String[] {resource.getHref()}; - } - } - - //------------------------------------< implementation specific methods >--- - /** - * Retrieve the the locations where the search should be performed.
- * Note, that the search result must be converted to {@link MultiStatusResponse}s - * that must be returned back to this report. - * - * @return href of collections that act as start for the search. - * @see #setResponses(MultiStatusResponse[]) - */ - public String[] getSearchRoots() { - return searchRoots; - } - - /** - * Retrieve the search arguments used to run the search for principals.
- * Note, that the search result must be converted to {@link MultiStatusResponse}s - * that must be returned back to this report. - * - * @return array of SearchArgument used to run the principal - * search. - * @see #setResponses(MultiStatusResponse[]) - */ - public SearchArgument[] getSearchArguments() { - return searchArguments; - } - - /** - * Write the search result back to the report. - * - * @param responses - */ - public void setResponses(MultiStatusResponse[] responses) { - this.responses = responses; - } - - //--------------------------------< implementation specific inner class >--- - /** - * Inner utility class preparing the query arguments present in the - * DAV:property-search element(s). - */ - protected class SearchArgument { - - private final DavPropertyNameSet searchProps; - private final String searchString; - - private SearchArgument(Element propSearch) { - searchProps = new DavPropertyNameSet(DomUtil.getChildElement(propSearch, DavConstants.XML_PROP, DavConstants.NAMESPACE)); - searchString = DomUtil.getChildText(propSearch, XML_MATCH, SecurityConstants.NAMESPACE); - } - - /** - * @return property name set used to restrict the search to a limited - * amount of properties. - */ - protected DavPropertyNameSet getSearchProperties() { - return searchProps; - } - - /** - * @return query string as present in the DAV:match element. - */ - protected String getSearchString() { - return searchString; - } - } -} Property changes on: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/security/report/PrincipalSearchReport.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Deleted: svn:keywords ## -1 +0,0 ## -author date id revision url \ No newline at end of property Index: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/security/report/SearchablePropertyReport.java =================================================================== --- jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/security/report/SearchablePropertyReport.java (revision 1907912) +++ jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/security/report/SearchablePropertyReport.java (nonexistent) @@ -1,204 +0,0 @@ -/* - * 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.webdav.security.report; - -import java.util.HashSet; -import java.util.Set; - -import org.apache.jackrabbit.webdav.DavConstants; -import org.apache.jackrabbit.webdav.DavException; -import org.apache.jackrabbit.webdav.DavResource; -import org.apache.jackrabbit.webdav.DavServletResponse; -import org.apache.jackrabbit.webdav.property.DavPropertyName; -import org.apache.jackrabbit.webdav.property.DavPropertyNameSet; -import org.apache.jackrabbit.webdav.security.SecurityConstants; -import org.apache.jackrabbit.webdav.version.report.AbstractReport; -import org.apache.jackrabbit.webdav.version.report.Report; -import org.apache.jackrabbit.webdav.version.report.ReportInfo; -import org.apache.jackrabbit.webdav.version.report.ReportType; -import org.apache.jackrabbit.webdav.xml.DomUtil; -import org.apache.jackrabbit.webdav.xml.Namespace; -import org.apache.jackrabbit.webdav.xml.XmlSerializable; -import org.w3c.dom.Document; -import org.w3c.dom.Element; - -/** - * SearchablePropertyReport identifies those properties that may be - * searched using the {@link PrincipalSearchReport DAV:principal-property-search REPORT}. - * This report must be supported on all collections identified in the value of - * a DAV:principal-collection-set property. - *

- * The request body MUST be an empty DAV:principal-search-property-set element. - *

- * The response body MUST be a DAV:principal-search-property-set XML element - * with the following structure: - *

- *  <!ELEMENT principal-search-property-set (principal-search-property*) >
- *  <!ELEMENT principal-search-property (prop, description) >
- *  prop: see RFC 2518, Section 12.11
- *  <!ELEMENT description #PCDATA >
- *  Human readable description. Note, that the language of the description must
- *  be indicated by the xml:lang attribute.
- * 
- * - * Note that a DAV:principal-search-property XML element is required for each - * property that may be searched with the DAV:principal-property-search REPORT. - */ -public class SearchablePropertyReport extends AbstractReport { - - /** - * The report name - */ - public static final String REPORT_NAME = "principal-search-property-set"; - - /** - * The report type - */ - public static final ReportType REPORT_TYPE = ReportType.register(REPORT_NAME, SecurityConstants.NAMESPACE, SearchablePropertyReport.class); - - /** - * Constant used for the DAV:principal-search-property-set response element. - */ - public static final String XML_PRINCIPAL_SEARCH_PROPERTY_SET = "principal-search-property-set"; - - /** - * Set collecting the DAV:principal-search-property entries. - */ - private final Set searchPropertySet = new HashSet(); - - /** - * @see Report#getType() - */ - public ReportType getType() { - return REPORT_TYPE; - } - - /** - * @return false Status code of after a successful completion must be - * {@link DavServletResponse#SC_OK 200 (ok)}. - * @see Report#isMultiStatusReport() - */ - public boolean isMultiStatusReport() { - return false; - } - - /** - * @see Report#init(DavResource, ReportInfo) - */ - public void init(DavResource resource, ReportInfo info) throws DavException { - if (resource == null || info == null) { - throw new DavException(DavServletResponse.SC_BAD_REQUEST, "Unable to run report: WebDAV Resource and ReportInfo must not be null."); - } - if (!getType().isRequestedReportType(info)) { - throw new DavException(DavServletResponse.SC_BAD_REQUEST, "Expected report type: '" + getType().getReportName() + "', found: '" + info.getReportName() + ";" + "'."); - } - if (info.getDepth() > DavConstants.DEPTH_0) { - throw new DavException(DavServletResponse.SC_BAD_REQUEST, "Invalid Depth header: " + info.getDepth()); - } - } - - /** - * @see Report#toXml(Document) - */ - public Element toXml(Document document) { - Element rootElem = DomUtil.createElement(document, XML_PRINCIPAL_SEARCH_PROPERTY_SET, SecurityConstants.NAMESPACE); - for (PrincipalSearchProperty psp : searchPropertySet) { - rootElem.appendChild(psp.toXml(document)); - } - return rootElem; - } - - //-----------------------------------------------------< implementation >--- - /** - * Add a property name that should be listed in the DAV:principal-search-property-set. - * - * @param propName a property name that may be searched in the {@link PrincipalSearchReport}. - * @param description Human readable description of the searchable property. - * @param language defines in which language the description is written. - * @throws IllegalArgumentException if propName is null. - */ - public void addPrincipalSearchProperty(DavPropertyName propName, - String description, String language) { - searchPropertySet.add(new PrincipalSearchProperty(propName, description, language)); - } - - //--------------------------------------------------------< inner class >--- - /** - * Inner class encapsulating the DAV:principal-search-property - */ - private class PrincipalSearchProperty implements XmlSerializable { - - private static final String XML_PRINCIPAL_SEARCH_PROPERTY = "principal-search-property"; - private static final String XML_DESCRIPTION = "description"; - private static final String ATTR_LANG = "lang"; - - private final DavPropertyName propName; - private final String description; - private final String language; - private final int hashCode; - - private PrincipalSearchProperty(DavPropertyName propName, - String description, - String language) { - if (propName == null) { - throw new IllegalArgumentException("null is not a valid DavPropertyName for the DAV:principal-search-property."); - } - this.propName = propName; - this.description = description; - this.language = language; - hashCode = propName.hashCode(); - } - - /** - * @see XmlSerializable#toXml(Document) - */ - public Element toXml(Document document) { - Element psElem = DomUtil.createElement(document, XML_PRINCIPAL_SEARCH_PROPERTY, SecurityConstants.NAMESPACE); - // create property set from the single property name - DavPropertyNameSet pnSet = new DavPropertyNameSet(); - pnSet.add(propName); - psElem.appendChild(pnSet.toXml(document)); - // append description if present - if (description != null) { - Element desc = DomUtil.addChildElement(psElem, XML_DESCRIPTION, SecurityConstants.NAMESPACE, description); - if (language != null) { - DomUtil.setAttribute(desc, ATTR_LANG, Namespace.XML_NAMESPACE, language); - } - } - return psElem; - } - - //---------------------------------------------------------< Object >--- - @Override - public boolean equals(Object obj) { - if (obj == this) { - return true; - } - if (obj instanceof PrincipalSearchProperty) { - PrincipalSearchProperty other = (PrincipalSearchProperty)obj; - // ignore the optional description/language - return hashCode == other.hashCode; - } - return false; - } - - @Override - public int hashCode() { - return hashCode; - } - } -} Property changes on: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/security/report/SearchablePropertyReport.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Deleted: svn:keywords ## -1 +0,0 ## -author date id revision url \ No newline at end of property Index: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/security/report/package-info.java =================================================================== --- jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/security/report/package-info.java (revision 1907912) +++ jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/security/report/package-info.java (nonexistent) @@ -1,18 +0,0 @@ -/* - * 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. - */ -@org.osgi.annotation.versioning.Version("1.1.0") -package org.apache.jackrabbit.webdav.security.report; Property changes on: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/security/report/package-info.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/server/AbstractWebdavServlet.java =================================================================== --- jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/server/AbstractWebdavServlet.java (revision 1907912) +++ jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/server/AbstractWebdavServlet.java (nonexistent) @@ -1,1557 +0,0 @@ -/* - * 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.webdav.server; - -import org.apache.jackrabbit.webdav.ContentCodingAwareRequest; -import org.apache.jackrabbit.webdav.DavCompliance; -import org.apache.jackrabbit.webdav.DavConstants; -import org.apache.jackrabbit.webdav.DavException; -import org.apache.jackrabbit.webdav.DavLocatorFactory; -import org.apache.jackrabbit.webdav.DavMethods; -import org.apache.jackrabbit.webdav.DavResource; -import org.apache.jackrabbit.webdav.DavResourceFactory; -import org.apache.jackrabbit.webdav.DavServletRequest; -import org.apache.jackrabbit.webdav.DavServletResponse; -import org.apache.jackrabbit.webdav.DavSessionProvider; -import org.apache.jackrabbit.webdav.MultiStatus; -import org.apache.jackrabbit.webdav.MultiStatusResponse; -import org.apache.jackrabbit.webdav.WebdavRequest; -import org.apache.jackrabbit.webdav.WebdavRequestImpl; -import org.apache.jackrabbit.webdav.WebdavResponse; -import org.apache.jackrabbit.webdav.WebdavResponseImpl; -import org.apache.jackrabbit.webdav.bind.RebindInfo; -import org.apache.jackrabbit.webdav.bind.UnbindInfo; -import org.apache.jackrabbit.webdav.bind.BindableResource; -import org.apache.jackrabbit.webdav.bind.BindInfo; -import org.apache.jackrabbit.webdav.header.CodedUrlHeader; -import org.apache.jackrabbit.webdav.io.InputContext; -import org.apache.jackrabbit.webdav.io.InputContextImpl; -import org.apache.jackrabbit.webdav.io.OutputContext; -import org.apache.jackrabbit.webdav.io.OutputContextImpl; -import org.apache.jackrabbit.webdav.lock.ActiveLock; -import org.apache.jackrabbit.webdav.lock.LockDiscovery; -import org.apache.jackrabbit.webdav.lock.LockInfo; -import org.apache.jackrabbit.webdav.observation.EventDiscovery; -import org.apache.jackrabbit.webdav.observation.ObservationResource; -import org.apache.jackrabbit.webdav.observation.Subscription; -import org.apache.jackrabbit.webdav.observation.SubscriptionInfo; -import org.apache.jackrabbit.webdav.ordering.OrderPatch; -import org.apache.jackrabbit.webdav.ordering.OrderingResource; -import org.apache.jackrabbit.webdav.property.DavProperty; -import org.apache.jackrabbit.webdav.property.DavPropertyName; -import org.apache.jackrabbit.webdav.property.DavPropertyNameSet; -import org.apache.jackrabbit.webdav.property.DavPropertySet; -import org.apache.jackrabbit.webdav.property.PropEntry; -import org.apache.jackrabbit.webdav.search.SearchConstants; -import org.apache.jackrabbit.webdav.search.SearchInfo; -import org.apache.jackrabbit.webdav.search.SearchResource; -import org.apache.jackrabbit.webdav.security.AclProperty; -import org.apache.jackrabbit.webdav.security.AclResource; -import org.apache.jackrabbit.webdav.transaction.TransactionInfo; -import org.apache.jackrabbit.webdav.transaction.TransactionResource; -import org.apache.jackrabbit.webdav.util.CSRFUtil; -import org.apache.jackrabbit.webdav.util.HttpDateTimeFormatter; -import org.apache.jackrabbit.webdav.version.ActivityResource; -import org.apache.jackrabbit.webdav.version.DeltaVConstants; -import org.apache.jackrabbit.webdav.version.DeltaVResource; -import org.apache.jackrabbit.webdav.version.LabelInfo; -import org.apache.jackrabbit.webdav.version.MergeInfo; -import org.apache.jackrabbit.webdav.version.OptionsInfo; -import org.apache.jackrabbit.webdav.version.OptionsResponse; -import org.apache.jackrabbit.webdav.version.UpdateInfo; -import org.apache.jackrabbit.webdav.version.VersionControlledResource; -import org.apache.jackrabbit.webdav.version.VersionResource; -import org.apache.jackrabbit.webdav.version.VersionableResource; -import org.apache.jackrabbit.webdav.version.report.Report; -import org.apache.jackrabbit.webdav.version.report.ReportInfo; -import org.apache.jackrabbit.webdav.xml.DomUtil; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.w3c.dom.Document; -import org.w3c.dom.Element; - -import javax.servlet.ServletException; -import javax.servlet.http.HttpServlet; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.time.format.DateTimeParseException; -import java.util.ArrayList; -import java.util.Collections; -import java.util.Enumeration; -import java.util.List; -import java.util.Locale; - -/** - * AbstractWebdavServlet - *

- */ -abstract public class AbstractWebdavServlet extends HttpServlet implements DavConstants { - - // todo respect Position header - /** - * default logger - */ - private static Logger log = LoggerFactory.getLogger(AbstractWebdavServlet.class); - - /** the 'missing-auth-mapping' init parameter */ - public final static String INIT_PARAM_MISSING_AUTH_MAPPING = "missing-auth-mapping"; - - /** - * Name of the optional init parameter that defines the value of the - * 'WWW-Authenticate' header. - *

- * If the parameter is omitted the default value - * {@link #DEFAULT_AUTHENTICATE_HEADER "Basic Realm=Jackrabbit Webdav Server"} - * is used. - * - * @see #getAuthenticateHeaderValue() - */ - public static final String INIT_PARAM_AUTHENTICATE_HEADER = "authenticate-header"; - - /** - * Default value for the 'WWW-Authenticate' header, that is set, if request - * results in a {@link DavServletResponse#SC_UNAUTHORIZED 401 (Unauthorized)} - * error. - * - * @see #getAuthenticateHeaderValue() - */ - public static final String DEFAULT_AUTHENTICATE_HEADER = "Basic realm=\"Jackrabbit Webdav Server\""; - - /** - * Name of the parameter that specifies the configuration of the CSRF protection. - * May contain a comma-separated list of allowed referrer hosts. - * If the parameter is omitted or left empty the behaviour is to only allow requests which have an empty referrer - * or a referrer host equal to the server host. - * If the parameter is set to 'disabled' no referrer checks will be performed at all. - */ - public static final String INIT_PARAM_CSRF_PROTECTION = "csrf-protection"; - - /** - * Name of the 'createAbsoluteURI' init parameter that defines whether hrefs - * should be created with a absolute URI or as absolute Path (ContextPath). - * The value should be 'true' or 'false'. The default value if not set is true. - */ - public final static String INIT_PARAM_CREATE_ABSOLUTE_URI = "createAbsoluteURI"; - - - /** - * Header value as specified in the {@link #INIT_PARAM_AUTHENTICATE_HEADER} parameter. - */ - private String authenticate_header; - - /** - * CSRF protection utility - */ - private CSRFUtil csrfUtil; - - /** - * Create per default absolute URI hrefs - */ - private boolean createAbsoluteURI = true; - - @Override - public void init() throws ServletException { - super.init(); - - // authenticate header - authenticate_header = getInitParameter(INIT_PARAM_AUTHENTICATE_HEADER); - if (authenticate_header == null) { - authenticate_header = DEFAULT_AUTHENTICATE_HEADER; - } - log.info(INIT_PARAM_AUTHENTICATE_HEADER + " = " + authenticate_header); - - // read csrf protection params - String csrfParam = getInitParameter(INIT_PARAM_CSRF_PROTECTION); - csrfUtil = new CSRFUtil(csrfParam); - log.info(INIT_PARAM_CSRF_PROTECTION + " = " + csrfParam); - - //create absolute URI hrefs.. - String param = getInitParameter(INIT_PARAM_CREATE_ABSOLUTE_URI); - if (param != null) { - createAbsoluteURI = Boolean.parseBoolean(param); - } - log.info(INIT_PARAM_CREATE_ABSOLUTE_URI + " = " + createAbsoluteURI); - } - - /** - * Checks if the precondition for this request and resource is valid. - * - * @param request - * @param resource - * @return - */ - abstract protected boolean isPreconditionValid(WebdavRequest request, DavResource resource); - - /** - * Returns the DavSessionProvider. - * - * @return the session provider - */ - abstract public DavSessionProvider getDavSessionProvider(); - - /** - * Returns the DavSessionProvider. - * - * @param davSessionProvider - */ - abstract public void setDavSessionProvider(DavSessionProvider davSessionProvider); - - /** - * Returns the DavLocatorFactory. - * - * @return the locator factory - */ - abstract public DavLocatorFactory getLocatorFactory(); - - /** - * Sets the DavLocatorFactory. - * - * @param locatorFactory - */ - abstract public void setLocatorFactory(DavLocatorFactory locatorFactory); - - /** - * Returns the DavResourceFactory. - * - * @return the resource factory - */ - abstract public DavResourceFactory getResourceFactory(); - - /** - * Sets the DavResourceFactory. - * - * @param resourceFactory - */ - abstract public void setResourceFactory(DavResourceFactory resourceFactory); - - /** - * Returns the value of the 'WWW-Authenticate' header, that is returned in - * case of 401 error: the value is retrireved from the corresponding init - * param or defaults to {@link #DEFAULT_AUTHENTICATE_HEADER}. - * - * @return corresponding init parameter or {@link #DEFAULT_AUTHENTICATE_HEADER}. - * @see #INIT_PARAM_AUTHENTICATE_HEADER - */ - public String getAuthenticateHeaderValue() { - return authenticate_header; - } - - /** - * Returns if a absolute URI should be created for hrefs. - * - * @return absolute URI hrefs - */ - protected boolean isCreateAbsoluteURI() { - return createAbsoluteURI; - } - - /** - * Service the given request. - * - * @param request - * @param response - * @throws ServletException - * @throws IOException - */ - @Override - protected void service(HttpServletRequest request, HttpServletResponse response) - throws ServletException, IOException { - - WebdavRequest webdavRequest = new WebdavRequestImpl(request, getLocatorFactory(), isCreateAbsoluteURI()); - // DeltaV requires 'Cache-Control' header for all methods except 'VERSION-CONTROL' and 'REPORT'. - int methodCode = DavMethods.getMethodCode(request.getMethod()); - boolean noCache = DavMethods.isDeltaVMethod(webdavRequest) && !(DavMethods.DAV_VERSION_CONTROL == methodCode || DavMethods.DAV_REPORT == methodCode); - WebdavResponse webdavResponse = new WebdavResponseImpl(response, noCache); - - try { - WebdavRequestContextHolder.setContext(new WebdavRequestContextImpl(webdavRequest)); - - // make sure there is a authenticated user - if (!getDavSessionProvider().attachSession(webdavRequest)) { - return; - } - - // perform referrer host checks if CSRF protection is enabled - if (!csrfUtil.isValidRequest(webdavRequest)) { - webdavResponse.sendError(HttpServletResponse.SC_FORBIDDEN); - return; - } - - // JCR-4165: reject any content-coding in request until we can - // support it (see JCR-4166) - if (!(webdavRequest instanceof ContentCodingAwareRequest)) { - List ces = getContentCodings(request); - if (!ces.isEmpty()) { - webdavResponse.setStatus(HttpServletResponse.SC_UNSUPPORTED_MEDIA_TYPE); - webdavResponse.setHeader("Accept-Encoding", "identity"); - webdavResponse.setContentType("text/plain; charset=UTF-8"); - webdavResponse.getWriter().println("Content-Encodings not supported, but received: " + ces); - webdavResponse.getWriter().flush(); - } - } - - // check matching if=header for lock-token relevant operations - DavResource resource = getResourceFactory().createResource(webdavRequest.getRequestLocator(), webdavRequest, webdavResponse); - if (!isPreconditionValid(webdavRequest, resource)) { - webdavResponse.sendError(HttpServletResponse.SC_PRECONDITION_FAILED); - return; - } - if (!execute(webdavRequest, webdavResponse, methodCode, resource)) { - super.service(request, response); - } - } catch (DavException e) { - handleDavException(webdavRequest, webdavResponse, e); - } catch (IOException ex) { - Throwable cause = ex.getCause(); - if (cause instanceof DavException) { - handleDavException(webdavRequest, webdavResponse, (DavException) cause); - } else { - throw ex; - } - } finally { - WebdavRequestContextHolder.clearContext(); - getDavSessionProvider().releaseSession(webdavRequest); - } - } - - private void handleDavException(WebdavRequest webdavRequest, WebdavResponse webdavResponse, DavException ex) - throws IOException { - if (ex.getErrorCode() == HttpServletResponse.SC_UNAUTHORIZED) { - sendUnauthorized(webdavRequest, webdavResponse, ex); - } else { - Element condition = ex.getErrorCondition(); - if (DomUtil.matches(condition, ContentCodingAwareRequest.PRECONDITION_SUPPORTED)) { - if (webdavRequest instanceof ContentCodingAwareRequest) { - webdavResponse.setHeader("Accept-Encoding", ((ContentCodingAwareRequest) webdavRequest).getAcceptableCodings()); - } - } - webdavResponse.sendError(ex); - } - } - - /** - * If request payload was uncompressed, hint about acceptable content codings (RFC 7694) - */ - private void addHintAboutPotentialRequestEncodings(WebdavRequest webdavRequest, WebdavResponse webdavResponse) { - if (webdavRequest instanceof ContentCodingAwareRequest) { - ContentCodingAwareRequest ccr = (ContentCodingAwareRequest)webdavRequest; - List ces = ccr.getRequestContentCodings(); - if (ces.isEmpty()) { - webdavResponse.setHeader("Accept-Encoding", ccr.getAcceptableCodings()); - } - } - } - - /** - * Sets the "WWW-Authenticate" header and writes the appropriate error - * to the given webdav response. - * - * @param request The webdav request. - * @param response The webdav response. - * @param error The DavException that leads to the unauthorized response. - * @throws IOException - */ - protected void sendUnauthorized(WebdavRequest request, - WebdavResponse response, DavException error) throws IOException { - response.setHeader("WWW-Authenticate", getAuthenticateHeaderValue()); - if (error == null || error.getErrorCode() != HttpServletResponse.SC_UNAUTHORIZED) { - response.sendError(HttpServletResponse.SC_UNAUTHORIZED); - } else { - response.sendError(error.getErrorCode(), error.getStatusPhrase()); - } - } - - /** - * Executes the respective method in the given webdav context - * - * @param request - * @param response - * @param method - * @param resource - * @throws ServletException - * @throws IOException - * @throws DavException - */ - protected boolean execute(WebdavRequest request, WebdavResponse response, - int method, DavResource resource) - throws ServletException, IOException, DavException { - - switch (method) { - case DavMethods.DAV_GET: - doGet(request, response, resource); - break; - case DavMethods.DAV_HEAD: - doHead(request, response, resource); - break; - case DavMethods.DAV_PROPFIND: - doPropFind(request, response, resource); - break; - case DavMethods.DAV_PROPPATCH: - doPropPatch(request, response, resource); - break; - case DavMethods.DAV_POST: - doPost(request, response, resource); - break; - case DavMethods.DAV_PUT: - doPut(request, response, resource); - break; - case DavMethods.DAV_DELETE: - doDelete(request, response, resource); - break; - case DavMethods.DAV_COPY: - doCopy(request, response, resource); - break; - case DavMethods.DAV_MOVE: - doMove(request, response, resource); - break; - case DavMethods.DAV_MKCOL: - doMkCol(request, response, resource); - break; - case DavMethods.DAV_OPTIONS: - doOptions(request, response, resource); - break; - case DavMethods.DAV_LOCK: - doLock(request, response, resource); - break; - case DavMethods.DAV_UNLOCK: - doUnlock(request, response, resource); - break; - case DavMethods.DAV_ORDERPATCH: - doOrderPatch(request, response, resource); - break; - case DavMethods.DAV_SUBSCRIBE: - doSubscribe(request, response, resource); - break; - case DavMethods.DAV_UNSUBSCRIBE: - doUnsubscribe(request, response, resource); - break; - case DavMethods.DAV_POLL: - doPoll(request, response, resource); - break; - case DavMethods.DAV_SEARCH: - doSearch(request, response, resource); - break; - case DavMethods.DAV_VERSION_CONTROL: - doVersionControl(request, response, resource); - break; - case DavMethods.DAV_LABEL: - doLabel(request, response, resource); - break; - case DavMethods.DAV_REPORT: - doReport(request, response, resource); - break; - case DavMethods.DAV_CHECKIN: - doCheckin(request, response, resource); - break; - case DavMethods.DAV_CHECKOUT: - doCheckout(request, response, resource); - break; - case DavMethods.DAV_UNCHECKOUT: - doUncheckout(request, response, resource); - break; - case DavMethods.DAV_MERGE: - doMerge(request, response, resource); - break; - case DavMethods.DAV_UPDATE: - doUpdate(request, response, resource); - break; - case DavMethods.DAV_MKWORKSPACE: - doMkWorkspace(request, response, resource); - break; - case DavMethods.DAV_MKACTIVITY: - doMkActivity(request, response, resource); - break; - case DavMethods.DAV_BASELINE_CONTROL: - doBaselineControl(request, response, resource); - break; - case DavMethods.DAV_ACL: - doAcl(request, response, resource); - break; - case DavMethods.DAV_REBIND: - doRebind(request, response, resource); - break; - case DavMethods.DAV_UNBIND: - doUnbind(request, response, resource); - break; - case DavMethods.DAV_BIND: - doBind(request, response, resource); - break; - default: - // any other method - return false; - } - return true; - } - - /** - * The OPTION method - * - * @param request - * @param response - * @param resource - */ - protected void doOptions(WebdavRequest request, WebdavResponse response, - DavResource resource) throws IOException, DavException { - response.addHeader(DavConstants.HEADER_DAV, resource.getComplianceClass()); - response.addHeader("Allow", resource.getSupportedMethods()); - response.addHeader("MS-Author-Via", DavConstants.HEADER_DAV); - if (resource instanceof SearchResource) { - String[] langs = ((SearchResource) resource).getQueryGrammerSet().getQueryLanguages(); - for (String lang : langs) { - response.addHeader(SearchConstants.HEADER_DASL, "<" + lang + ">"); - } - } - // with DeltaV the OPTIONS request may contain a Xml body. - OptionsResponse oR = null; - OptionsInfo oInfo = request.getOptionsInfo(); - if (oInfo != null && resource instanceof DeltaVResource) { - oR = ((DeltaVResource) resource).getOptionResponse(oInfo); - } - if (oR == null) { - response.setStatus(DavServletResponse.SC_OK); - } else { - response.sendXmlResponse(oR, DavServletResponse.SC_OK); - } - } - - /** - * The HEAD method - * - * @param request - * @param response - * @param resource - * @throws IOException - */ - protected void doHead(WebdavRequest request, WebdavResponse response, - DavResource resource) throws IOException { - spoolResource(request, response, resource, false); - } - - /** - * The GET method - * - * @param request - * @param response - * @param resource - * @throws IOException - */ - protected void doGet(WebdavRequest request, WebdavResponse response, - DavResource resource) throws IOException, DavException { - spoolResource(request, response, resource, true); - } - - /** - * @param request - * @param response - * @param resource - * @param sendContent - * @throws IOException - */ - private void spoolResource(WebdavRequest request, WebdavResponse response, - DavResource resource, boolean sendContent) - throws IOException { - - if (!resource.exists()) { - response.sendError(HttpServletResponse.SC_NOT_FOUND); - return; - } - - long modSince = UNDEFINED_TIME; - try { - // will throw if multiple field lines present - String value = getSingletonField(request, "If-Modified-Since"); - if (value != null) { - modSince = HttpDateTimeFormatter.parse(value); - } - } catch (IllegalArgumentException | DateTimeParseException ex) { - log.debug("illegal value for if-modified-since ignored: " + ex.getMessage()); - } - - if (modSince > UNDEFINED_TIME) { - long modTime = resource.getModificationTime(); - // test if resource has been modified. note that formatted modification - // time lost the milli-second precision - if (modTime != UNDEFINED_TIME && (modTime / 1000 * 1000) <= modSince) { - // resource has not been modified since the time indicated in the - // 'If-Modified-Since' header. - - DavProperty etagProp = resource.getProperty(DavPropertyName.GETETAG); - if (etagProp != null) { - // 304 response MUST contain Etag when available - response.setHeader("etag", etagProp.getValue().toString()); - } - response.setStatus(HttpServletResponse.SC_NOT_MODIFIED); - return; - } - } - - // spool resource properties and eventually resource content. - OutputStream out = (sendContent) ? response.getOutputStream() : null; - resource.spool(getOutputContext(response, out)); - response.flushBuffer(); - } - - /** - * The PROPFIND method - * - * @param request - * @param response - * @param resource - * @throws IOException - */ - protected void doPropFind(WebdavRequest request, WebdavResponse response, - DavResource resource) throws IOException, DavException { - - if (!resource.exists()) { - response.sendError(DavServletResponse.SC_NOT_FOUND); - return; - } - - int depth = request.getDepth(DEPTH_INFINITY); - DavPropertyNameSet requestProperties = request.getPropFindProperties(); - int propfindType = request.getPropFindType(); - - MultiStatus mstatus = new MultiStatus(); - mstatus.addResourceProperties(resource, requestProperties, propfindType, depth); - - addHintAboutPotentialRequestEncodings(request, response); - - response.sendMultiStatus(mstatus, - acceptsGzipEncoding(request) ? Collections.singletonList("gzip") : Collections.emptyList()); - } - - /** - * The PROPPATCH method - * - * @param request - * @param response - * @param resource - * @throws IOException - */ - protected void doPropPatch(WebdavRequest request, WebdavResponse response, - DavResource resource) - throws IOException, DavException { - - List changeList = request.getPropPatchChangeList(); - if (changeList.isEmpty()) { - response.sendError(DavServletResponse.SC_BAD_REQUEST); - return; - } - - MultiStatus ms = new MultiStatus(); - MultiStatusResponse msr = resource.alterProperties(changeList); - ms.addResponse(msr); - - addHintAboutPotentialRequestEncodings(request, response); - - response.sendMultiStatus(ms); - } - - /** - * The POST method. Delegate to PUT - * - * @param request - * @param response - * @param resource - * @throws IOException - * @throws DavException - */ - protected void doPost(WebdavRequest request, WebdavResponse response, - DavResource resource) throws IOException, DavException { - response.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED); - } - - /** - * The PUT method - * - * @param request - * @param response - * @param resource - * @throws IOException - * @throws DavException - */ - protected void doPut(WebdavRequest request, WebdavResponse response, - DavResource resource) throws IOException, DavException { - - if (request.getHeader("Content-Range") != null) { - response.sendError(DavServletResponse.SC_BAD_REQUEST, "Content-Range in PUT request not supported"); - return; - } - - DavResource parentResource = resource.getCollection(); - if (parentResource == null || !parentResource.exists()) { - // parent does not exist - response.sendError(DavServletResponse.SC_CONFLICT); - return; - } - - int status; - // test if resource already exists - if (resource.exists()) { - status = DavServletResponse.SC_NO_CONTENT; - } else { - status = DavServletResponse.SC_CREATED; - } - - parentResource.addMember(resource, getInputContext(request, request.getInputStream())); - response.setStatus(status); - } - - /** - * The MKCOL method - * - * @param request - * @param response - * @param resource - * @throws IOException - * @throws DavException - */ - protected void doMkCol(WebdavRequest request, WebdavResponse response, - DavResource resource) throws IOException, DavException { - - DavResource parentResource = resource.getCollection(); - if (parentResource == null || !parentResource.exists() || !parentResource.isCollection()) { - // parent does not exist or is not a collection - response.sendError(DavServletResponse.SC_CONFLICT); - return; - } - // shortcut: mkcol is only allowed on deleted/non-existing resources - if (resource.exists()) { - response.sendError(DavServletResponse.SC_METHOD_NOT_ALLOWED); - return; - } - - if (request.getContentLength() > 0 || request.getHeader("Transfer-Encoding") != null) { - parentResource.addMember(resource, getInputContext(request, request.getInputStream())); - } else { - parentResource.addMember(resource, getInputContext(request, null)); - } - response.setStatus(DavServletResponse.SC_CREATED); - } - - /** - * The DELETE method - * - * @param request - * @param response - * @param resource - * @throws IOException - * @throws DavException - */ - protected void doDelete(WebdavRequest request, WebdavResponse response, - DavResource resource) throws IOException, DavException { - DavResource parent = resource.getCollection(); - if (parent != null) { - parent.removeMember(resource); - response.setStatus(DavServletResponse.SC_NO_CONTENT); - } else { - response.sendError(DavServletResponse.SC_FORBIDDEN, "Cannot remove the root resource."); - } - } - - /** - * The COPY method - * - * @param request - * @param response - * @param resource - * @throws IOException - * @throws DavException - */ - protected void doCopy(WebdavRequest request, WebdavResponse response, - DavResource resource) throws IOException, DavException { - - // only depth 0 and infinity is allowed - int depth = request.getDepth(DEPTH_INFINITY); - if (!(depth == DEPTH_0 || depth == DEPTH_INFINITY)) { - response.sendError(DavServletResponse.SC_BAD_REQUEST); - return; - } - - DavResource destResource = getResourceFactory().createResource(request.getDestinationLocator(), request, response); - int status = validateDestination(destResource, request, true); - if (status > DavServletResponse.SC_NO_CONTENT) { - response.sendError(status); - return; - } - - resource.copy(destResource, depth == DEPTH_0); - response.setStatus(status); - } - - /** - * The MOVE method - * - * @param request - * @param response - * @param resource - * @throws IOException - * @throws DavException - */ - protected void doMove(WebdavRequest request, WebdavResponse response, - DavResource resource) throws IOException, DavException { - - DavResource destResource = getResourceFactory().createResource(request.getDestinationLocator(), request, response); - int status = validateDestination(destResource, request, true); - if (status > DavServletResponse.SC_NO_CONTENT) { - response.sendError(status); - return; - } - - resource.move(destResource); - response.setStatus(status); - } - - /** - * The BIND method - * - * @param request - * @param response - * @param resource the collection resource to which a new member will be added - * @throws IOException - * @throws DavException - */ - protected void doBind(WebdavRequest request, WebdavResponse response, - DavResource resource) throws IOException, DavException { - - if (!resource.exists()) { - response.sendError(DavServletResponse.SC_NOT_FOUND); - } - BindInfo bindInfo = request.getBindInfo(); - DavResource oldBinding = getResourceFactory().createResource(request.getHrefLocator(bindInfo.getHref()), request, response); - if (!(oldBinding instanceof BindableResource)) { - response.sendError(DavServletResponse.SC_METHOD_NOT_ALLOWED); - return; - } - DavResource newBinding = getResourceFactory().createResource(request.getMemberLocator(bindInfo.getSegment()), request, response); - int status = validateDestination(newBinding, request, false); - if (status > DavServletResponse.SC_NO_CONTENT) { - response.sendError(status); - return; - } - ((BindableResource) oldBinding).bind(resource, newBinding); - response.setStatus(status); - } - - /** - * The REBIND method - * - * @param request - * @param response - * @param resource the collection resource to which a new member will be added - * @throws IOException - * @throws DavException - */ - protected void doRebind(WebdavRequest request, WebdavResponse response, - DavResource resource) throws IOException, DavException { - - if (!resource.exists()) { - response.sendError(DavServletResponse.SC_NOT_FOUND); - } - RebindInfo rebindInfo = request.getRebindInfo(); - DavResource oldBinding = getResourceFactory().createResource(request.getHrefLocator(rebindInfo.getHref()), request, response); - if (!(oldBinding instanceof BindableResource)) { - response.sendError(DavServletResponse.SC_METHOD_NOT_ALLOWED); - return; - } - DavResource newBinding = getResourceFactory().createResource(request.getMemberLocator(rebindInfo.getSegment()), request, response); - int status = validateDestination(newBinding, request, false); - if (status > DavServletResponse.SC_NO_CONTENT) { - response.sendError(status); - return; - } - ((BindableResource) oldBinding).rebind(resource, newBinding); - response.setStatus(status); - } - - /** - * The UNBIND method - * - * @param request - * @param response - * @param resource the collection resource from which a member will be removed - * @throws IOException - * @throws DavException - */ - protected void doUnbind(WebdavRequest request, WebdavResponse response, - DavResource resource) throws IOException, DavException { - - UnbindInfo unbindInfo = request.getUnbindInfo(); - DavResource srcResource = getResourceFactory().createResource(request.getMemberLocator(unbindInfo.getSegment()), request, response); - resource.removeMember(srcResource); - } - - /** - * Validate the given destination resource and return the proper status - * code: Any return value greater/equal than {@link DavServletResponse#SC_NO_CONTENT} - * indicates an error. - * - * @param destResource destination resource to be validated. - * @param request - * @param checkHeader flag indicating if the destination header must be present. - * @return status code indicating whether the destination is valid. - */ - protected int validateDestination(DavResource destResource, WebdavRequest request, boolean checkHeader) - throws DavException { - - if (checkHeader) { - String destHeader = request.getHeader(HEADER_DESTINATION); - if (destHeader == null || "".equals(destHeader)) { - return DavServletResponse.SC_BAD_REQUEST; - } - } - if (destResource.getLocator().equals(request.getRequestLocator())) { - return DavServletResponse.SC_FORBIDDEN; - } - - int status; - if (destResource.exists()) { - if (request.isOverwrite()) { - // matching if-header required for existing resources - if (!request.matchesIfHeader(destResource)) { - return DavServletResponse.SC_PRECONDITION_FAILED; - } else { - // overwrite existing resource - DavResource col; - try { - col = destResource.getCollection(); - } - catch (IllegalArgumentException ex) { - return DavServletResponse.SC_BAD_GATEWAY; - } - col.removeMember(destResource); - status = DavServletResponse.SC_NO_CONTENT; - } - } else { - // cannot copy/move to an existing item, if overwrite is not forced - return DavServletResponse.SC_PRECONDITION_FAILED; - } - } else { - // destination does not exist >> copy/move can be performed - status = DavServletResponse.SC_CREATED; - } - return status; - } - - /** - * The LOCK method - * - * @param request - * @param response - * @param resource - * @throws IOException - * @throws DavException - */ - protected void doLock(WebdavRequest request, WebdavResponse response, - DavResource resource) throws IOException, DavException { - - LockInfo lockInfo = request.getLockInfo(); - if (lockInfo.isRefreshLock()) { - // refresh any matching existing locks - ActiveLock[] activeLocks = resource.getLocks(); - List lList = new ArrayList(); - for (ActiveLock activeLock : activeLocks) { - // adjust lockinfo with type/scope retrieved from the lock. - lockInfo.setType(activeLock.getType()); - lockInfo.setScope(activeLock.getScope()); - - DavProperty etagProp = resource.getProperty(DavPropertyName.GETETAG); - String etag = etagProp != null ? String.valueOf(etagProp.getValue()) : ""; - if (request.matchesIfHeader(resource.getHref(), activeLock.getToken(), etag)) { - lList.add(resource.refreshLock(lockInfo, activeLock.getToken())); - } - } - if (lList.isEmpty()) { - throw new DavException(DavServletResponse.SC_PRECONDITION_FAILED); - } - ActiveLock[] refreshedLocks = lList.toArray(new ActiveLock[lList.size()]); - response.sendRefreshLockResponse(refreshedLocks); - } else { - int status = HttpServletResponse.SC_OK; - if (!resource.exists()) { - // lock-empty requires status code 201 (Created) - status = HttpServletResponse.SC_CREATED; - } - - // create a new lock - ActiveLock lock = resource.lock(lockInfo); - - CodedUrlHeader header = new CodedUrlHeader( - DavConstants.HEADER_LOCK_TOKEN, lock.getToken()); - response.setHeader(header.getHeaderName(), header.getHeaderValue()); - - DavPropertySet propSet = new DavPropertySet(); - propSet.add(new LockDiscovery(lock)); - response.sendXmlResponse(propSet, status); - } - } - - /** - * The UNLOCK method - * - * @param request - * @param response - * @param resource - * @throws DavException - */ - protected void doUnlock(WebdavRequest request, WebdavResponse response, - DavResource resource) throws DavException { - // get lock token from header - String lockToken = request.getLockToken(); - TransactionInfo tInfo = request.getTransactionInfo(); - if (tInfo != null) { - ((TransactionResource) resource).unlock(lockToken, tInfo); - } else { - resource.unlock(lockToken); - } - response.setStatus(DavServletResponse.SC_NO_CONTENT); - } - - /** - * The ORDERPATCH method - * - * @param request - * @param response - * @param resource - * @throws IOException - * @throws DavException - */ - protected void doOrderPatch(WebdavRequest request, - WebdavResponse response, - DavResource resource) - throws IOException, DavException { - - if (!(resource instanceof OrderingResource)) { - response.sendError(DavServletResponse.SC_METHOD_NOT_ALLOWED); - return; - } - - OrderPatch op = request.getOrderPatch(); - if (op == null) { - response.sendError(DavServletResponse.SC_BAD_REQUEST); - return; - } - // perform reordering of internal members - ((OrderingResource) resource).orderMembers(op); - response.setStatus(DavServletResponse.SC_OK); - } - - /** - * The SUBSCRIBE method - * - * @param request - * @param response - * @param resource - * @throws IOException - * @throws DavException - */ - protected void doSubscribe(WebdavRequest request, - WebdavResponse response, - DavResource resource) - throws IOException, DavException { - - if (!(resource instanceof ObservationResource)) { - response.sendError(DavServletResponse.SC_METHOD_NOT_ALLOWED); - return; - } - - SubscriptionInfo info = request.getSubscriptionInfo(); - if (info == null) { - response.sendError(DavServletResponse.SC_UNSUPPORTED_MEDIA_TYPE); - return; - } - Subscription subs = ((ObservationResource) resource).subscribe(info, request.getSubscriptionId()); - response.sendSubscriptionResponse(subs); - } - - /** - * The UNSUBSCRIBE method - * - * @param request - * @param response - * @param resource - * @throws IOException - * @throws DavException - */ - protected void doUnsubscribe(WebdavRequest request, - WebdavResponse response, - DavResource resource) - throws IOException, DavException { - - if (!(resource instanceof ObservationResource)) { - response.sendError(DavServletResponse.SC_METHOD_NOT_ALLOWED); - return; - } - ((ObservationResource) resource).unsubscribe(request.getSubscriptionId()); - response.setStatus(DavServletResponse.SC_NO_CONTENT); - } - - /** - * The POLL method - * - * @param request - * @param response - * @param resource - * @throws IOException - * @throws DavException - */ - protected void doPoll(WebdavRequest request, - WebdavResponse response, - DavResource resource) - throws IOException, DavException { - - if (!(resource instanceof ObservationResource)) { - response.sendError(DavServletResponse.SC_METHOD_NOT_ALLOWED); - return; - } - EventDiscovery ed = ((ObservationResource) resource).poll( - request.getSubscriptionId(), request.getPollTimeout()); - response.sendPollResponse(ed); - } - - /** - * The VERSION-CONTROL method - * - * @param request - * @param response - * @param resource - * @throws DavException - * @throws IOException - */ - protected void doVersionControl(WebdavRequest request, WebdavResponse response, - DavResource resource) - throws DavException, IOException { - if (!(resource instanceof VersionableResource)) { - response.sendError(DavServletResponse.SC_METHOD_NOT_ALLOWED); - return; - } - ((VersionableResource) resource).addVersionControl(); - } - - /** - * The LABEL method - * - * @param request - * @param response - * @param resource - * @throws DavException - * @throws IOException - */ - protected void doLabel(WebdavRequest request, WebdavResponse response, - DavResource resource) - throws DavException, IOException { - - LabelInfo labelInfo = request.getLabelInfo(); - if (resource instanceof VersionResource) { - ((VersionResource) resource).label(labelInfo); - } else if (resource instanceof VersionControlledResource) { - ((VersionControlledResource) resource).label(labelInfo); - } else { - // any other resource type that does not support a LABEL request - response.sendError(DavServletResponse.SC_METHOD_NOT_ALLOWED); - } - } - - /** - * The REPORT method - * - * @param request - * @param response - * @param resource - * @throws DavException - * @throws IOException - */ - protected void doReport(WebdavRequest request, WebdavResponse response, - DavResource resource) - throws DavException, IOException { - ReportInfo info = request.getReportInfo(); - Report report; - if (resource instanceof DeltaVResource) { - report = ((DeltaVResource) resource).getReport(info); - } else if (resource instanceof AclResource) { - report = ((AclResource) resource).getReport(info); - } else { - response.sendError(DavServletResponse.SC_METHOD_NOT_ALLOWED); - return; - } - - int statusCode = (report.isMultiStatusReport()) ? DavServletResponse.SC_MULTI_STATUS : DavServletResponse.SC_OK; - addHintAboutPotentialRequestEncodings(request, response); - response.sendXmlResponse(report, statusCode, acceptsGzipEncoding(request) ? Collections.singletonList("gzip") : Collections.emptyList()); - } - - /** - * The CHECKIN method - * - * @param request - * @param response - * @param resource - * @throws DavException - * @throws IOException - */ - protected void doCheckin(WebdavRequest request, WebdavResponse response, - DavResource resource) - throws DavException, IOException { - - if (!(resource instanceof VersionControlledResource)) { - response.sendError(DavServletResponse.SC_METHOD_NOT_ALLOWED); - return; - } - String versionHref = ((VersionControlledResource) resource).checkin(); - response.setHeader(DeltaVConstants.HEADER_LOCATION, versionHref); - response.setStatus(DavServletResponse.SC_CREATED); - } - - /** - * The CHECKOUT method - * - * @param request - * @param response - * @param resource - * @throws DavException - * @throws IOException - */ - protected void doCheckout(WebdavRequest request, WebdavResponse response, - DavResource resource) - throws DavException, IOException { - if (!(resource instanceof VersionControlledResource)) { - response.sendError(DavServletResponse.SC_METHOD_NOT_ALLOWED); - return; - } - ((VersionControlledResource) resource).checkout(); - } - - /** - * The UNCHECKOUT method - * - * @param request - * @param response - * @param resource - * @throws DavException - * @throws IOException - */ - protected void doUncheckout(WebdavRequest request, WebdavResponse response, - DavResource resource) - throws DavException, IOException { - if (!(resource instanceof VersionControlledResource)) { - response.sendError(DavServletResponse.SC_METHOD_NOT_ALLOWED); - return; - } - ((VersionControlledResource) resource).uncheckout(); - } - - /** - * The MERGE method - * - * @param request - * @param response - * @param resource - * @throws DavException - * @throws IOException - */ - protected void doMerge(WebdavRequest request, WebdavResponse response, - DavResource resource) throws DavException, IOException { - - if (!(resource instanceof VersionControlledResource)) { - response.sendError(DavServletResponse.SC_METHOD_NOT_ALLOWED); - return; - } - MergeInfo info = request.getMergeInfo(); - MultiStatus ms = ((VersionControlledResource) resource).merge(info); - response.sendMultiStatus(ms); - } - - /** - * The UPDATE method - * - * @param request - * @param response - * @param resource - * @throws DavException - * @throws IOException - */ - protected void doUpdate(WebdavRequest request, WebdavResponse response, - DavResource resource) throws DavException, IOException { - - if (!(resource instanceof VersionControlledResource)) { - response.sendError(DavServletResponse.SC_METHOD_NOT_ALLOWED); - return; - } - UpdateInfo info = request.getUpdateInfo(); - MultiStatus ms = ((VersionControlledResource) resource).update(info); - response.sendMultiStatus(ms); - } - - /** - * The MKWORKSPACE method - * - * @param request - * @param response - * @param resource - * @throws DavException - * @throws IOException - */ - protected void doMkWorkspace(WebdavRequest request, WebdavResponse response, - DavResource resource) throws DavException, IOException { - if (resource.exists()) { - AbstractWebdavServlet.log.warn("Cannot create a new workspace. Resource already exists."); - response.sendError(DavServletResponse.SC_FORBIDDEN); - return; - } - - DavResource parentResource = resource.getCollection(); - if (parentResource == null || !parentResource.exists() || !parentResource.isCollection()) { - // parent does not exist or is not a collection - response.sendError(DavServletResponse.SC_CONFLICT); - return; - } - if (!(parentResource instanceof DeltaVResource)) { - response.sendError(DavServletResponse.SC_METHOD_NOT_ALLOWED); - return; - } - ((DeltaVResource) parentResource).addWorkspace(resource); - response.setStatus(DavServletResponse.SC_CREATED); - } - - /** - * The MKACTIVITY method - * - * @param request - * @param response - * @param resource - * @throws DavException - * @throws IOException - */ - protected void doMkActivity(WebdavRequest request, WebdavResponse response, - DavResource resource) throws DavException, IOException { - if (resource.exists()) { - AbstractWebdavServlet.log.warn("Unable to create activity: A resource already exists at the request-URL " + request.getRequestURL()); - response.sendError(DavServletResponse.SC_FORBIDDEN); - return; - } - - DavResource parentResource = resource.getCollection(); - if (parentResource == null || !parentResource.exists() || !parentResource.isCollection()) { - // parent does not exist or is not a collection - response.sendError(DavServletResponse.SC_CONFLICT); - return; - } - // TODO: improve. see http://issues.apache.org/jira/browse/JCR-394 - if (!parentResource.getComplianceClass().contains(DavCompliance.ACTIVITY)) { - response.sendError(DavServletResponse.SC_METHOD_NOT_ALLOWED); - return; - } - - if (!(resource instanceof ActivityResource)) { - AbstractWebdavServlet.log.error("Unable to create activity: ActivityResource expected"); - response.sendError(DavServletResponse.SC_INTERNAL_SERVER_ERROR); - return; - } - - // try to add the new activity resource - parentResource.addMember(resource, getInputContext(request, request.getInputStream())); - - // Note: mandatory cache control header has already been set upon response creation. - response.setStatus(DavServletResponse.SC_CREATED); - } - - /** - * The BASELINECONTROL method - * - * @param request - * @param response - * @param resource - * @throws DavException - * @throws IOException - */ - protected void doBaselineControl(WebdavRequest request, WebdavResponse response, - DavResource resource) - throws DavException, IOException { - - if (!resource.exists()) { - AbstractWebdavServlet.log.warn("Unable to add baseline control. Resource does not exist " + resource.getHref()); - response.sendError(DavServletResponse.SC_NOT_FOUND); - return; - } - // TODO: improve. see http://issues.apache.org/jira/browse/JCR-394 - if (!(resource instanceof VersionControlledResource) || !resource.isCollection()) { - AbstractWebdavServlet.log.warn("BaselineControl is not supported by resource " + resource.getHref()); - response.sendError(DavServletResponse.SC_METHOD_NOT_ALLOWED); - return; - } - - // TODO : missing method on VersionControlledResource - throw new DavException(DavServletResponse.SC_NOT_IMPLEMENTED); - /* - ((VersionControlledResource) resource).addBaselineControl(request.getRequestDocument()); - // Note: mandatory cache control header has already been set upon response creation. - response.setStatus(DavServletResponse.SC_OK); - */ - } - - /** - * The SEARCH method - * - * @param request - * @param response - * @param resource - * @throws DavException - * @throws IOException - */ - protected void doSearch(WebdavRequest request, WebdavResponse response, - DavResource resource) throws DavException, IOException { - - if (!(resource instanceof SearchResource)) { - response.sendError(DavServletResponse.SC_METHOD_NOT_ALLOWED); - return; - } - Document doc = request.getRequestDocument(); - if (doc != null) { - SearchInfo sR = SearchInfo.createFromXml(doc.getDocumentElement()); - response.sendMultiStatus(((SearchResource) resource).search(sR)); - } else { - // request without request body is valid if requested resource - // is a 'query' resource. - response.sendMultiStatus(((SearchResource) resource).search(null)); - } - } - - /** - * The ACL method - * - * @param request - * @param response - * @param resource - * @throws DavException - * @throws IOException - */ - protected void doAcl(WebdavRequest request, WebdavResponse response, - DavResource resource) throws DavException, IOException { - if (!(resource instanceof AclResource)) { - response.sendError(DavServletResponse.SC_METHOD_NOT_ALLOWED); - return; - } - Document doc = request.getRequestDocument(); - if (doc == null) { - throw new DavException(DavServletResponse.SC_BAD_REQUEST, "ACL request requires a DAV:acl body."); - } - AclProperty acl = AclProperty.createFromXml(doc.getDocumentElement()); - ((AclResource)resource).alterAcl(acl); - } - - /** - * Return a new InputContext used for adding resource members - * - * @param request - * @param in - * @return - * @see #spoolResource(WebdavRequest, WebdavResponse, DavResource, boolean) - */ - protected InputContext getInputContext(DavServletRequest request, InputStream in) { - return new InputContextImpl(request, in); - } - - /** - * Return a new OutputContext used for spooling resource properties and - * the resource content - * - * @param response - * @param out - * @return - * @see #doPut(WebdavRequest, WebdavResponse, DavResource) - * @see #doMkCol(WebdavRequest, WebdavResponse, DavResource) - */ - protected OutputContext getOutputContext(DavServletResponse response, OutputStream out) { - return new OutputContextImpl(response, out); - } - - /** - * Obtain the (ordered!) list of content codings that have been used in the - * request - */ - public static List getContentCodings(HttpServletRequest request) { - return getListElementsFromHeaderField(request, "Content-Encoding"); - } - - /** - * Check whether recipient accepts GZIP content coding - */ - private static boolean acceptsGzipEncoding(HttpServletRequest request) { - List result = getListElementsFromHeaderField(request, "Accept-Encoding"); - for (String s : result) { - s = s.replace(" ", ""); - int semi = s.indexOf(';'); - if ("gzip".equals(s)) { - return true; - } else if (semi > 0) { - String enc = s.substring(0, semi); - String parm = s.substring(semi + 1); - if ("gzip".equals(enc) && parm.startsWith("q=")) { - float q = Float.valueOf(parm.substring(2)); - return q > 0; - } - } - } - return false; - } - - private static List getListElementsFromHeaderField(HttpServletRequest request, String fieldName) { - List result = Collections.emptyList(); - for (Enumeration ceh = request.getHeaders(fieldName); ceh.hasMoreElements();) { - for (String h : ceh.nextElement().split(",")) { - if (!h.trim().isEmpty()) { - if (result.isEmpty()) { - result = new ArrayList(); - } - result.add(h.trim().toLowerCase(Locale.ENGLISH)); - } - } - } - - return result; - } - - /** - * Get field value of a singleton field - * @param request HTTP request - * @param fieldName field name - * @return the field value (when there is indeed a single field line) or {@code null} when field not present - * @throws IllegalArgumentException when multiple field lines present - */ - protected static String getSingletonField(HttpServletRequest request, String fieldName) { - Enumeration lines = request.getHeaders(fieldName); - if (!lines.hasMoreElements()) { - return null; - } else { - String value = lines.nextElement(); - if (!lines.hasMoreElements()) { - return value; - } else { - List v = new ArrayList<>(); - v.add(value); - while (lines.hasMoreElements()) { - v.add(lines.nextElement()); - } - throw new IllegalArgumentException("Multiple field lines for '" + fieldName + "' header field: " + v); - } - } - } -} - Property changes on: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/server/AbstractWebdavServlet.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Deleted: svn:keywords ## -1 +0,0 ## -author date id revision url \ No newline at end of property Index: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/server/WebdavRequestContextHolder.java =================================================================== --- jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/server/WebdavRequestContextHolder.java (revision 1907912) +++ jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/server/WebdavRequestContextHolder.java (nonexistent) @@ -1,46 +0,0 @@ -/* - * 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.webdav.server; - -import org.apache.jackrabbit.webdav.WebdavRequestContext; - -/** - * Associates a {@link WebdavRequestContext} with the current execution thread. - */ -public final class WebdavRequestContextHolder { - - private static ThreadLocal tlWebdavRequestContext = new ThreadLocal<>(); - - private WebdavRequestContextHolder() { - } - - /** - * Return the {@link WebdavRequestContext} with the current execution thread. - * @return the {@link WebdavRequestContext} with the current execution thread - */ - public static WebdavRequestContext getContext() { - return tlWebdavRequestContext.get(); - } - - static void setContext(WebdavRequestContext context) { - tlWebdavRequestContext.set(context); - } - - static void clearContext() { - tlWebdavRequestContext.remove(); - } -} Property changes on: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/server/WebdavRequestContextHolder.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/server/WebdavRequestContextImpl.java =================================================================== --- jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/server/WebdavRequestContextImpl.java (revision 1907912) +++ jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/server/WebdavRequestContextImpl.java (nonexistent) @@ -1,35 +0,0 @@ -/* - * 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.webdav.server; - -import org.apache.jackrabbit.webdav.WebdavRequest; -import org.apache.jackrabbit.webdav.WebdavRequestContext; - -class WebdavRequestContextImpl implements WebdavRequestContext { - - private final WebdavRequest request; - - WebdavRequestContextImpl(final WebdavRequest request) { - this.request = request; - } - - @Override - public WebdavRequest getRequest() { - return request; - } - -} Property changes on: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/server/WebdavRequestContextImpl.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/server/package-info.java =================================================================== --- jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/server/package-info.java (revision 1907912) +++ jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/server/package-info.java (nonexistent) @@ -1,18 +0,0 @@ -/* - * 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. - */ -@org.osgi.annotation.versioning.Version("1.2.0") -package org.apache.jackrabbit.webdav.server; Property changes on: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/server/package-info.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/transaction/TransactionConstants.java =================================================================== --- jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/transaction/TransactionConstants.java (revision 1907912) +++ jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/transaction/TransactionConstants.java (nonexistent) @@ -1,125 +0,0 @@ -/* - * 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.webdav.transaction; - -import org.apache.jackrabbit.webdav.DavConstants; -import org.apache.jackrabbit.webdav.lock.Scope; -import org.apache.jackrabbit.webdav.lock.Type; -import org.apache.jackrabbit.webdav.xml.Namespace; - -/** - * TransactionConstants interface provide constants for request - * and response headers, Xml elements and property names used for handling - * transactions over WebDAV. There exists no public standard for this functionality. - * - * todo: 'local' and 'global' are not accurate terms in the given context > replace - */ -public interface TransactionConstants { - - /** - * Namespace for transaction related xml elements - */ - public static final Namespace NAMESPACE = Namespace.getNamespace("dcr", "http://www.day.com/jcr/webdav/1.0"); - - //---< Headers >------------------------------------------------------------ - /** - * TransactionId Header - */ - public static final String HEADER_TRANSACTIONID = "TransactionId"; - - //---< XML Element, Attribute Names >--------------------------------------- - /** - * transaction XML element
- * Used as element inside the {@link DavConstants#XML_LOCKTYPE locktype} - * element. - * @see DavConstants#XML_LOCKTYPE - */ - public static final String XML_TRANSACTION = "transaction"; - - /** - * global XML element
- * Used as element inside of the {@link DavConstants#XML_LOCKSCOPE lockscope} element. - * - * @see DavConstants#XML_LOCKSCOPE - */ - public static final String XML_GLOBAL = "global"; - - /** - * local XML element
- * Used as element inside of the {@link DavConstants#XML_LOCKSCOPE lockscope} element. - * It indicates the transaction to be local (e.g. transient changes to - * a repository). - * - * @see DavConstants#XML_LOCKSCOPE - */ - public static final String XML_LOCAL = "local"; - - /** - * transactioninfo XML element
- * Mandatory element of the UNLOCK request body, if the unlock request - * is intended to complete a transaction. - */ - public static final String XML_TRANSACTIONINFO = "transactioninfo"; - - /** - * transactionstatus XML element
- * Mandatory element inside the {@link #XML_TRANSACTIONINFO transactioninfo} - * element indicating how the transaction should be completed. - * @see #XML_TRANSACTIONINFO - */ - public static final String XML_TRANSACTIONSTATUS = "transactionstatus"; - - /** - * commit XML element
- * Used as element inside of the {@link #XML_TRANSACTIONSTATUS transactionstatus} - * element. It indicates a completion by committing the transaction. - * @see #XML_TRANSACTIONSTATUS - */ - public static final String XML_COMMIT = "commit"; - - /** - * rollback XML element
- * Used as element inside of the {@link #XML_TRANSACTIONSTATUS transactionstatus} - * element. It indicates a completion by roll backing the transaction. - * @see #XML_TRANSACTIONSTATUS - */ - public static final String XML_ROLLBACK = "rollback"; - - //---< Lock Type, Lock Scope >---------------------------------------------- - /** - * "transaction" lock type constant. - * @see #XML_TRANSACTION - * @see Type#create(String, Namespace) - */ - public static final Type TRANSACTION = Type.create(XML_TRANSACTION, TransactionConstants.NAMESPACE); - - /** - * "local" lock scope constant. - * - * @see #XML_LOCAL - * @see Scope#create(String, Namespace) - */ - public static final Scope LOCAL = Scope.create(XML_LOCAL, TransactionConstants.NAMESPACE); - - /** - * "global" lock scope constant. - * - * @see #XML_GLOBAL - * @see Scope#create(String, Namespace) - */ - public static final Scope GLOBAL = Scope.create(XML_GLOBAL, TransactionConstants.NAMESPACE); -} \ No newline at end of file Property changes on: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/transaction/TransactionConstants.java ___________________________________________________________________ Deleted: svn Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/transaction/TransactionDavServletRequest.java =================================================================== --- jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/transaction/TransactionDavServletRequest.java (revision 1907912) +++ jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/transaction/TransactionDavServletRequest.java (nonexistent) @@ -1,51 +0,0 @@ -/* - * 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.webdav.transaction; - -import org.apache.jackrabbit.webdav.DavException; -import org.apache.jackrabbit.webdav.DavServletRequest; - -/** - * TransactionDavServletRequest provides extensions to the - * {@link DavServletRequest} interface used for dealing with transaction lock - * requests. - */ -public interface TransactionDavServletRequest extends DavServletRequest { - - /** - * Retrieve the 'transactioninfo' request body that must be included with - * the UNLOCK request of a transaction lock. If the request body is does not - * provide the information required (either because it is missing or the - * Xml is not valid) null is returned. - * - * @return TransactionInfo object encapsulating the 'transactioninfo' - * Xml element present in the request body or null if no - * body is present or if it could not be parsed. - * @throws DavException if an invalid request body is present. - */ - public TransactionInfo getTransactionInfo() throws DavException; - - - /** - * Retrieve the transaction id from the - * {@link TransactionConstants#HEADER_TRANSACTIONID TransactionId header}. - * - * @return transaction id as present in the {@link TransactionConstants#HEADER_TRANSACTIONID TransactionId header} - * or null. - */ - public String getTransactionId(); -} \ No newline at end of file Property changes on: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/transaction/TransactionDavServletRequest.java ___________________________________________________________________ Deleted: svn Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/transaction/TransactionInfo.java =================================================================== --- jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/transaction/TransactionInfo.java (revision 1907912) +++ jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/transaction/TransactionInfo.java (nonexistent) @@ -1,105 +0,0 @@ -/* - * 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.webdav.transaction; - -import org.apache.jackrabbit.webdav.DavException; -import org.apache.jackrabbit.webdav.DavServletResponse; -import org.apache.jackrabbit.webdav.xml.DomUtil; -import org.apache.jackrabbit.webdav.xml.XmlSerializable; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.w3c.dom.Document; -import org.w3c.dom.Element; - -/** - * TransactionInfo class encapsulates the information present - * in the {@link #XML_TRANSACTIONINFO} element that forms the request body of - * the UNLOCk request for a transaction lock. - * - * @see TransactionConstants#XML_TRANSACTIONINFO - * @see TransactionConstants#XML_TRANSACTION - */ -public class TransactionInfo implements TransactionConstants, XmlSerializable { - - private static Logger log = LoggerFactory.getLogger(TransactionInfo.class); - - private final boolean isCommit; - - /** - * Creates a TransactionInfo object - * - * @param isCommit - */ - public TransactionInfo(boolean isCommit) { - this.isCommit = isCommit; - } - - /** - * Creates a TransactionInfo object from the given 'transactionInfo' - * element. The 'transactionInfo' must have the following form: - *

-     *
-     *  <!ELEMENT transactioninfo (transactionstatus) >
-     *  <!ELEMENT transactionstatus ( commit | rollback ) >
-     *  <!ELEMENT commit EMPTY >
-     *  <!ELEMENT rollback EMPTY >
-     * 
- * @param transactionInfo as present in the UNLOCK request body. - * @throws IllegalArgumentException if the given transactionInfo element - * is not valid. - */ - public TransactionInfo(Element transactionInfo) throws DavException { - if (transactionInfo == null || !XML_TRANSACTIONINFO.equals(transactionInfo.getLocalName())) { - log.warn("'transactionInfo' element expected."); - throw new DavException(DavServletResponse.SC_BAD_REQUEST); - } - Element txStatus = DomUtil.getChildElement(transactionInfo, XML_TRANSACTIONSTATUS, NAMESPACE); - if (txStatus != null) { - // retrieve status: commit or rollback - isCommit = DomUtil.hasChildElement(txStatus, XML_COMMIT, NAMESPACE); - } else { - log.warn("transactionInfo must contain a single 'transactionstatus' element."); - throw new DavException(DavServletResponse.SC_BAD_REQUEST); - } - } - - /** - * Returns true, if this info requires a 'commit' action, false otherwise - * (i.e. 'rollback' is requested). - * - * @return true if a 'commit' element was present. false otherwise. - * @see #XML_COMMIT - * @see #XML_ROLLBACK - */ - public boolean isCommit() { - return isCommit; - } - - //------------------------------------------< XmlSerializable interface >--- - /** - * @see org.apache.jackrabbit.webdav.xml.XmlSerializable#toXml(Document) - * @param document - */ - public Element toXml(Document document) { - Element elem = DomUtil.createElement(document, XML_TRANSACTIONINFO, NAMESPACE); - Element st = DomUtil.addChildElement(elem, XML_TRANSACTIONSTATUS, NAMESPACE); - String lName = (isCommit) ? XML_COMMIT : XML_ROLLBACK; - DomUtil.addChildElement(st, lName, NAMESPACE); - return elem; - } - -} \ No newline at end of file Property changes on: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/transaction/TransactionInfo.java ___________________________________________________________________ Deleted: svn Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/transaction/TransactionResource.java =================================================================== --- jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/transaction/TransactionResource.java (revision 1907912) +++ jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/transaction/TransactionResource.java (nonexistent) @@ -1,59 +0,0 @@ -/* - * 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.webdav.transaction; - -import org.apache.jackrabbit.webdav.DavException; -import org.apache.jackrabbit.webdav.DavResource; - -/** - * TransactionResource extends the {@link DavResource} interface by - * transaction relevant METHODS. - */ -public interface TransactionResource extends DavResource { - - public static final String METHODS = ""; - - /** - * Initializes the TransactionResource. - * - * @param txMgr - * @param transactionId - */ - public void init(TxLockManager txMgr, String transactionId); - - /** - * The TransactionId or null according to the value of the - * corresponding request {@link TransactionConstants#HEADER_TRANSACTIONID header} - * field. - * - * @return TransactionId header or null - */ - public String getTransactionId(); - - /** - * Overloads the {@link DavResource#unlock unlock} method of the DavResource - * interface. - * - * @param lockToken lock token as present in the request header. - * @param info transaction info object as present in the UNLOCK request body. - * @throws DavException if an error occurs - * @see DavResource#unlock(String) - * @see TransactionDavServletRequest#getTransactionId() - * @see org.apache.jackrabbit.webdav.DavServletRequest#getLockToken() - */ - public void unlock(String lockToken, TransactionInfo info) throws DavException; -} \ No newline at end of file Property changes on: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/transaction/TransactionResource.java ___________________________________________________________________ Deleted: svn Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/transaction/TxActiveLock.java =================================================================== --- jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/transaction/TxActiveLock.java (revision 1907912) +++ jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/transaction/TxActiveLock.java (nonexistent) @@ -1,93 +0,0 @@ -/* - * 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.webdav.transaction; - -import org.apache.jackrabbit.webdav.lock.DefaultActiveLock; -import org.apache.jackrabbit.webdav.lock.LockInfo; -import org.apache.jackrabbit.webdav.lock.Scope; -import org.apache.jackrabbit.webdav.lock.Type; - -/** - * TxActiveLock represents the transaction lock present on a - * {@link TransactionResource}. - */ -public class TxActiveLock extends DefaultActiveLock implements TransactionConstants { - - public static final long DEFAULT_TIMEOUT = 300000; // 5 minutes - - private final Scope scope; - - /** - * Create a new transaction lock.
- * If the lockInfo element is null the timeout defaults to - * half and hour. The default scope is 'local'. - * - * @param lockInfo - * @throws IllegalArgumentException if either scope or type is invalid or if - * a depth other than infinity is requested. - */ - public TxActiveLock(LockInfo lockInfo) { - if (lockInfo != null) { - if (!TRANSACTION.equals(lockInfo.getType())) { - throw new IllegalArgumentException("Only 'transaction' type is allowed for a transaction-activelock object."); - } - if (!(LOCAL.equals(lockInfo.getScope()) || GLOBAL.equals(lockInfo.getScope()))) { - throw new IllegalArgumentException("Only 'global' or 'local' are valid scopes within a transaction-activelock element."); - } - if (!lockInfo.isDeep()) { - throw new IllegalArgumentException("Only transaction locks can only be deep."); - } - setOwner(lockInfo.getOwner()); - setTimeout(lockInfo.getTimeout()); - scope = lockInfo.getScope(); - } else { - setTimeout(DEFAULT_TIMEOUT); - // local scope by default - scope = LOCAL; - } - } - - /** - * Always returns true. - * - * @return true - */ - @Override - public boolean isDeep() { - return true; - } - - /** - * Always returns the {@link #TRANSACTION} type. - * - * @return {@link #TRANSACTION} - */ - @Override - public Type getType() { - return TRANSACTION; - } - - /** - * Returns the scope of this lock which is either {@link #LOCAL} or {@link #GLOBAL}. - * - * @return {@link #LOCAL} or {@link #GLOBAL} - */ - @Override - public Scope getScope() { - return scope; - } -} Property changes on: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/transaction/TxActiveLock.java ___________________________________________________________________ Deleted: svn Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/transaction/TxLockEntry.java =================================================================== --- jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/transaction/TxLockEntry.java (revision 1907912) +++ jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/transaction/TxLockEntry.java (nonexistent) @@ -1,72 +0,0 @@ -/* - * 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.webdav.transaction; - -import org.apache.jackrabbit.webdav.lock.AbstractLockEntry; -import org.apache.jackrabbit.webdav.lock.Scope; -import org.apache.jackrabbit.webdav.lock.Type; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * TxLockEntry represents the lock entry objects allowed for - * a transaction lock. - */ -public final class TxLockEntry extends AbstractLockEntry implements TransactionConstants { - - private static Logger log = LoggerFactory.getLogger(TxLockEntry.class); - - private final Scope scope; - - /** - * Create a lock entry that identifies transaction lock. - * - * @param isLocal boolean value indicating whether this is a local or a global - * lock entry. - */ - public TxLockEntry(boolean isLocal) { - if (isLocal) { - scope = LOCAL; - } else { - scope = GLOBAL; - } - } - - /** - * Returns the {@link #TRANSACTION 'transaction'} lock type. - * - * @return always returns the 'transaction' type. - * @see org.apache.jackrabbit.webdav.lock.LockEntry#getType() - * @see #TRANSACTION - */ - public Type getType() { - return TRANSACTION; - } - - /** - * Returns either {@link #LOCAL local} or {@link #GLOBAL global} scope - * depending on the initial constructor value. - * - * @return returns 'global' or 'local' scope. - * @see org.apache.jackrabbit.webdav.lock.LockEntry#getScope() - * @see #GLOBAL - * @see #LOCAL - */ - public Scope getScope() { - return scope; - } -} \ No newline at end of file Property changes on: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/transaction/TxLockEntry.java ___________________________________________________________________ Deleted: svn Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/transaction/TxLockManager.java =================================================================== --- jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/transaction/TxLockManager.java (revision 1907912) +++ jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/transaction/TxLockManager.java (nonexistent) @@ -1,65 +0,0 @@ -/* - * 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.webdav.transaction; - -import org.apache.jackrabbit.webdav.DavException; -import org.apache.jackrabbit.webdav.lock.ActiveLock; -import org.apache.jackrabbit.webdav.lock.LockManager; -import org.apache.jackrabbit.webdav.lock.Scope; -import org.apache.jackrabbit.webdav.lock.Type; - -/** - * TxLockManager manages locks with locktype - * '{@link TransactionConstants#TRANSACTION dcr:transaction}'. - * - * todo: removing all expired locks - * todo: 'local' and 'global' are not accurate terms in the given context > replace - * todo: the usage of the 'global' transaction is not according to the JTA specification, - * which explicitly requires any transaction present on a servlet to be completed before - * the service method returns. Starting/completing transactions on the session object, - * which is possible with the jackrabbit implementation is a hack. - * todo: review of this transaction part is therefore required. Is there a use-case - * for those 'global' transactions at all... - */ -public interface TxLockManager extends LockManager { - - - /** - * Release the lock identified by the given lock token. - * - * @param lockInfo - * @param lockToken - * @param resource - * @throws org.apache.jackrabbit.webdav.DavException - */ - public void releaseLock(TransactionInfo lockInfo, String lockToken, - TransactionResource resource) throws DavException; - - - /** - * Return the lock applied to the given resource or null - * - * @param type - * @param scope - * @param resource - * @return lock applied to the given resource or null - * @see org.apache.jackrabbit.webdav.lock.LockManager#getLock(org.apache.jackrabbit.webdav.lock.Type, org.apache.jackrabbit.webdav.lock.Scope, org.apache.jackrabbit.webdav.DavResource) - */ - public ActiveLock getLock(Type type, Scope scope, TransactionResource resource); - - -} Property changes on: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/transaction/TxLockManager.java ___________________________________________________________________ Deleted: svn Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/transaction/package-info.java =================================================================== --- jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/transaction/package-info.java (revision 1907912) +++ jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/transaction/package-info.java (nonexistent) @@ -1,18 +0,0 @@ -/* - * 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. - */ -@org.osgi.annotation.versioning.Version("1.0.0") -package org.apache.jackrabbit.webdav.transaction; Property changes on: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/transaction/package-info.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/util/CSRFUtil.java =================================================================== --- jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/util/CSRFUtil.java (revision 1907912) +++ jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/util/CSRFUtil.java (nonexistent) @@ -1,168 +0,0 @@ -/* - * 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.webdav.util; - -import java.net.URI; -import java.net.URISyntaxException; -import java.util.Arrays; -import java.util.Collections; -import java.util.Enumeration; -import java.util.HashSet; -import java.util.Locale; -import java.util.Set; - -import javax.servlet.http.HttpServletRequest; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * CSRFUtil... - */ -public class CSRFUtil { - - /** - * Constant used to - */ - public static final String DISABLED = "disabled"; - - /** - * Request content types for CSRF checking, see JCR-3909, JCR-4002, and JCR-4009 - */ - public static final Set CONTENT_TYPES = Collections.unmodifiableSet(new HashSet( - Arrays.asList( - new String[] { - "application/x-www-form-urlencoded", - "multipart/form-data", - "text/plain" - } - ) - )); - - /** - * logger instance - */ - private static final Logger log = LoggerFactory.getLogger(CSRFUtil.class); - - /** - * Disable referrer based CSRF protection - */ - private final boolean disabled; - - /** - * Additional allowed referrer hosts for CSRF protection - */ - private final Set allowedReferrerHosts; - - /** - * Creates a new instance from the specified configuration, which defines - * the behaviour of the referrer based CSRF protection as follows: - *
    - *
  1. If config is null or empty string the default - * behaviour is to allow only requests with an empty referrer header or a - * referrer host equal to the server host
  2. - *
  3. A comma separated list of additional allowed referrer hosts which are - * valid in addition to default behaviour (see above).
  4. - *
  5. The value {@link #DISABLED} may be used to disable the referrer checking altogether
  6. - *
- * - * @param config The configuration value which may be any of the following: - *
    - *
  • null or empty string for the default behaviour, which - * only allows requests with an empty referrer header or a - * referrer host equal to the server host
  • - *
  • A comma separated list of additional allowed referrer hosts which are - * valid in addition to default behaviour (see above).
  • - *
  • {@link #DISABLED} in order to disable the referrer checking altogether
  • - *
- */ - public CSRFUtil(String config) { - if (config == null || config.length() == 0) { - disabled = false; - allowedReferrerHosts = Collections.emptySet(); - log.debug("CSRF protection disabled"); - } else { - if (DISABLED.equalsIgnoreCase(config.trim())) { - disabled = true; - allowedReferrerHosts = Collections.emptySet(); - } else { - disabled = false; - String[] allowed = config.split(","); - allowedReferrerHosts = new HashSet(allowed.length); - for (String entry : allowed) { - allowedReferrerHosts.add(entry.trim()); - } - } - log.debug("CSRF protection enabled, allowed referrers: " + allowedReferrerHosts); - } - } - - public boolean isValidRequest(HttpServletRequest request) { - - if (disabled) { - return true; - } else if (!"POST".equals(request.getMethod())) { - // protection only needed for POST - return true; - } else { - Enumeration cts = (Enumeration) request.getHeaders("Content-Type"); - String ct = null; - if (cts != null && cts.hasMoreElements()) { - String t = cts.nextElement(); - // prune parameters - int semicolon = t.indexOf(';'); - if (semicolon >= 0) { - t = t.substring(0, semicolon); - } - ct = t.trim().toLowerCase(Locale.ENGLISH); - } - if (cts != null && cts.hasMoreElements()) { - // reject if there are more header field instances - log.debug("request blocked because there were multiple content-type header fields"); - return false; - } - if (ct != null && !CONTENT_TYPES.contains(ct)) { - // type present and not in blacklist - return true; - } - - String refHeader = request.getHeader("Referer"); - // empty referrer headers are not allowed for POST + relevant - // content types (see JCR-3909) - if (refHeader == null) { - log.debug("POST with content type " + ct + " blocked due to missing referer header field"); - return false; - } - - try { - String host = new URI(refHeader).getHost(); - // test referrer-host equals server or - // if it is contained in the set of explicitly allowed host - // names - boolean ok = host == null || host.equals(request.getServerName()) || allowedReferrerHosts.contains(host); - if (!ok) { - log.debug("POST with content type " + ct + " blocked due to referer header field being: " + refHeader); - } - return ok; - } catch (URISyntaxException ex) { - // referrer malformed -> block access - log.debug("POST with content type " + ct + " blocked due to malformed referer header field: " + refHeader); - return false; - } - } - } -} \ No newline at end of file Property changes on: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/util/CSRFUtil.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Deleted: svn:keywords ## -1 +0,0 ## -Author Date Id Revision Rev URL \ No newline at end of property Index: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/util/EncodeUtil.java =================================================================== --- jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/util/EncodeUtil.java (revision 1907912) +++ jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/util/EncodeUtil.java (nonexistent) @@ -1,220 +0,0 @@ -/* - * 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.webdav.util; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.ByteArrayOutputStream; -import java.io.UnsupportedEncodingException; -import java.nio.charset.StandardCharsets; -import java.util.BitSet; - -/** - * EncodeUtil provides helper methods for URL encoding and decoding - * (copied from jcr-commons jackrabbit.util.Text). - * - * @see JCR-2897. - */ -public final class EncodeUtil { - - /** - * logger instance - */ - private static final Logger log = LoggerFactory.getLogger(EncodeUtil.class); - - /** - * hextable used for {@link #escape(String, char, boolean)} - */ - public static final char[] hexTable = "0123456789abcdef".toCharArray(); - - /** - * The list of characters that are not encoded by the escape() - * and unescape() METHODS. They contains the characters as - * defined 'unreserved' in section 2.3 of the RFC 2396 'URI generic syntax': - *

- *

-     * unreserved  = alphanum | mark
-     * mark        = "-" | "_" | "." | "!" | "~" | "*" | "'" | "(" | ")"
-     * 
- */ - private static BitSet URISave; - - /** - * Same as {@link #URISave} but also contains the '/' - */ - private static BitSet URISaveEx; - - static { - URISave = new BitSet(256); - int i; - for (i = 'a'; i <= 'z'; i++) { - URISave.set(i); - } - for (i = 'A'; i <= 'Z'; i++) { - URISave.set(i); - } - for (i = '0'; i <= '9'; i++) { - URISave.set(i); - } - URISave.set('-'); - URISave.set('_'); - URISave.set('.'); - URISave.set('!'); - URISave.set('~'); - URISave.set('*'); - URISave.set('\''); - URISave.set('('); - URISave.set(')'); - - URISaveEx = (BitSet) URISave.clone(); - URISaveEx.set('/'); - } - - /** - * Does a URL encoding of the string. The characters that - * don't need encoding are those defined 'unreserved' in section 2.3 of - * the 'URI generic syntax' RFC 2396. - * - * @param string the string to encode - * @return the escaped string - * @throws NullPointerException if string is null. - */ - public static String escape(String string) { - return escape(string, '%', false); - } - - /** - * Does a URL encoding of the path. The characters that - * don't need encoding are those defined 'unreserved' in section 2.3 of - * the 'URI generic syntax' RFC 2396. In contrast to the - * {@link #escape(String)} method, not the entire path string is escaped, - * but every individual part (i.e. the slashes are not escaped). - * - * @param path the path to encode - * @return the escaped path - * @throws NullPointerException if path is null. - */ - public static String escapePath(String path) { - return escape(path, '%', true); - } - - /** - * Does an URL encoding of the string using the - * escape character. The characters that don't need encoding - * are those defined 'unreserved' in section 2.3 of the 'URI generic syntax' - * RFC 2396, but without the escape character. If isPath is - * true, additionally the slash '/' is ignored, too. - * - * @param string the string to encode. - * @param escape the escape character. - * @param isPath if true, the string is treated as path - * @return the escaped string - * @throws NullPointerException if string is null. - */ - private static String escape(String string, char escape, boolean isPath) { - BitSet validChars = isPath ? URISaveEx : URISave; - byte[] bytes = string.getBytes(StandardCharsets.UTF_8); - StringBuffer out = new StringBuffer(bytes.length); - for (byte aByte : bytes) { - int c = aByte & 0xff; - if (validChars.get(c) && c != escape) { - out.append((char) c); - } else { - out.append(escape); - out.append(hexTable[(c >> 4) & 0x0f]); - out.append(hexTable[(c) & 0x0f]); - } - } - return out.toString(); - } - - /** - * Does a URL decoding of the string. Please note that in - * opposite to the {@link java.net.URLDecoder} it does not transform the + - * into spaces. - * - * @param string the string to decode - * @return the decoded string - * @throws NullPointerException if string is null. - * @throws ArrayIndexOutOfBoundsException if not enough character follow an - * escape character - * @throws IllegalArgumentException if the 2 characters following the escape - * character do not represent a hex-number. - */ - public static String unescape(String string) { - return unescape(string, '%'); - } - - /** - * Does a URL decoding of the string using the - * escape character. Please note that in opposite to the - * {@link java.net.URLDecoder} it does not transform the + into spaces. - * - * @param string the string to decode - * @param escape the escape character - * @return the decoded string - * @throws NullPointerException if string is null. - * @throws IllegalArgumentException if the 2 characters following the escape - * character do not represent a hex-number - * or if not enough characters follow an - * escape character - */ - private static String unescape(String string, char escape) { - byte[] utf8 = string.getBytes(StandardCharsets.UTF_8); - - // Check whether escape occurs at invalid position - if ((utf8.length >= 1 && utf8[utf8.length - 1] == escape) || - (utf8.length >= 2 && utf8[utf8.length - 2] == escape)) { - throw new IllegalArgumentException("Premature end of escape sequence at end of input"); - } - - ByteArrayOutputStream out = new ByteArrayOutputStream(utf8.length); - for (int k = 0; k < utf8.length; k++) { - byte b = utf8[k]; - if (b == escape) { - out.write((decodeDigit(utf8[++k]) << 4) + decodeDigit(utf8[++k])); - } - else { - out.write(b); - } - } - - return new String(out.toByteArray(), StandardCharsets.UTF_8); - } - - private static byte decodeDigit(byte b) { - if (b >= 0x30 && b <= 0x39) { - return (byte) (b - 0x30); - } - else if (b >= 0x41 && b <= 0x46) { - return (byte) (b - 0x37); - } - else if (b >= 0x61 && b <= 0x66) { - return (byte) (b - 0x57); - } - else { - throw new IllegalArgumentException("Escape sequence is not hexadecimal: " + (char)b); - } - } - - /** - * Private constructor: avoid instantiation. - */ - private EncodeUtil() { - } -} \ No newline at end of file Property changes on: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/util/EncodeUtil.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Deleted: svn:keywords ## -1 +0,0 ## -Author Date Id Revision Rev URL \ No newline at end of property Index: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/util/HttpDateFormat.java =================================================================== --- jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/util/HttpDateFormat.java (revision 1907912) +++ jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/util/HttpDateFormat.java (nonexistent) @@ -1,64 +0,0 @@ -/* - * 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.webdav.util; - -import java.text.SimpleDateFormat; -import java.util.Locale; -import java.util.TimeZone; - -/** - * HttpDateFormat... - */ -public class HttpDateFormat extends SimpleDateFormat { - - private static final TimeZone GMT_TIMEZONE = TimeZone.getTimeZone("GMT"); - - /** - * Pattern for the modification date as defined by RFC 1123 - */ - public static final String MODIFICATION_DATE_PATTERN = "EEE, dd MMM yyyy HH:mm:ss z"; - - /** - * Simple date format pattern for the creation date ISO representation (partial). - */ - public static final String CREATION_DATE_PATTERN = "yyyy-MM-dd'T'HH:mm:ss'Z'"; - - public HttpDateFormat(String pattern) { - super(pattern, Locale.ENGLISH); - super.setTimeZone(GMT_TIMEZONE); - } - - /** - * Creates a new HttpDateFormat using the - * {@link #MODIFICATION_DATE_PATTERN modifcation date pattern}. - * - * @return a new HttpDateFormat. - */ - public static HttpDateFormat modificationDateFormat() { - return new HttpDateFormat(MODIFICATION_DATE_PATTERN); - } - - /** - * Creates a new HttpDateFormat using the - * {@link #CREATION_DATE_PATTERN creation date pattern}. - * - * @return a new HttpDateFormat. - */ - public static HttpDateFormat creationDateFormat() { - return new HttpDateFormat(CREATION_DATE_PATTERN); - } -} \ No newline at end of file Property changes on: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/util/HttpDateFormat.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Deleted: svn:keywords ## -1 +0,0 ## -author date id revision url \ No newline at end of property Index: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/util/HttpDateTimeFormatter.java =================================================================== --- jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/util/HttpDateTimeFormatter.java (revision 1907912) +++ jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/util/HttpDateTimeFormatter.java (nonexistent) @@ -1,152 +0,0 @@ -/* - * 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.webdav.util; - -import java.time.Instant; -import java.time.LocalDate; -import java.time.ZoneOffset; -import java.time.ZonedDateTime; -import java.time.format.DateTimeFormatter; -import java.time.format.DateTimeFormatterBuilder; -import java.time.format.DateTimeParseException; -import java.time.temporal.ChronoField; -import java.util.Locale; - -/** - * Parsers and Serializers for HTTP dates (RFC 7231, Section 7.1.1.1), using - * {@link DateTimeFormatter} (from Java 8). - */ -public class HttpDateTimeFormatter { - - private static DateTimeFormatter IMFFIXDATE = DateTimeFormatter.ofPattern("EEE, dd MMM yyyy HH:mm:ss 'GMT'", Locale.ENGLISH) - .withZone(ZoneOffset.UTC); - - // see - // https://greenbytes.de/tech/webdav/rfc7231.html#rfc.section.7.1.1.1.p.6 - private static DateTimeFormatter RFC850DATE = new DateTimeFormatterBuilder().appendPattern("EEEE, dd-MMM-") - .appendValueReduced(ChronoField.YEAR_OF_ERA, 2, 2, LocalDate.now().minusYears(50)).appendPattern(" HH:mm:ss 'GMT'") - .toFormatter().withLocale(Locale.ENGLISH).withZone(ZoneOffset.UTC); - - private static DateTimeFormatter ASCTIMEDATE = new DateTimeFormatterBuilder().appendPattern("EEE MMM ").padNext(2, ' ') - .appendValue(ChronoField.DAY_OF_MONTH).appendPattern(" HH:mm:ss yyyy").toFormatter().withLocale(Locale.ENGLISH) - .withZone(ZoneOffset.UTC); - - /** - * Parse HTTP "IMF-fixdate" format (see RFC 7231, Section 7.1.1.1) - * - * @param fieldValue - * string value - * @return ms since epoch throws DateTimeParseException on invalid input - */ - public static long parseImfFixedDate(String fieldValue) { - ZonedDateTime d = ZonedDateTime.parse(fieldValue, IMFFIXDATE); - return d.toInstant().toEpochMilli(); - } - - /** - * Parse HTTP "rfc850-date" format (see RFC 7231, Section 7.1.1.1) - * - * @param fieldValue - * string value - * @return ms since epoch throws DateTimeParseException on invalid input - */ - public static long parseRfc850Date(String fieldValue) { - ZonedDateTime d = ZonedDateTime.parse(fieldValue, RFC850DATE); - return d.toInstant().toEpochMilli(); - } - - /** - * Parse HTTP "asctime-date" format (see RFC 7231, Section 7.1.1.1) - * - * @param fieldValue - * string value - * @return ms since epoch throws DateTimeParseException on invalid input - */ - public static long parseAscTimeDate(String fieldValue) { - ZonedDateTime d = ZonedDateTime.parse(fieldValue, ASCTIMEDATE); - return d.toInstant().toEpochMilli(); - } - - /** - * Parse HTTP format, trying the three allowable formats defined in RFC - * 7231, Section 7.1.1.1 - * - * @param fieldValue - * string value - * @return ms since epoch throws DateTimeParseException on invalid input - */ - public static long parse(String fieldValue) { - try { - return parseImfFixedDate(fieldValue); - } catch (DateTimeParseException ex) { - try { - return parseRfc850Date(fieldValue); - } catch (DateTimeParseException ex2) { - try { - return parseAscTimeDate(fieldValue); - } catch (DateTimeParseException ex3) { - // if we get here, throw original exception for IMFFIXDATE - throw ex; - } - } - } - } - - /** - * Format as HTTP default date (IMF-fixdate) (see RFC 7231, Section 7.1.1.1) - * - * @param millisSinceEpoch - * ms since epoch - * @return string representation - */ - public static String format(long millisSinceEpoch) { - return IMFFIXDATE.format(Instant.ofEpochMilli(millisSinceEpoch)); - } - - /** - * Format as HTTP "IMF-fixdate" (see RFC 7231, Section 7.1.1.1) - * - * @param millisSinceEpoch - * ms since epoch - * @return string representation - */ - public static String formatImfFixed(long millisSinceEpoch) { - return IMFFIXDATE.format(Instant.ofEpochMilli(millisSinceEpoch)); - } - - /** - * Format as HTTP "rfc850-date" (see RFC 7231, Section 7.1.1.1) - * - * @param millisSinceEpoch - * ms since epoch - * @return string representation - */ - public static String formatRfc850(long millisSinceEpoch) { - return RFC850DATE.format(Instant.ofEpochMilli(millisSinceEpoch)); - } - - /** - * Format as HTTP "asctime-date" (see RFC 7231, Section 7.1.1.1) - * - * @param millisSinceEpoch - * ms since epoch - * @return string representation - */ - public static String formatAscTime(long millisSinceEpoch) { - return ASCTIMEDATE.format(Instant.ofEpochMilli(millisSinceEpoch)); - } -} Property changes on: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/util/HttpDateTimeFormatter.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/util/LinkHeaderFieldParser.java =================================================================== --- jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/util/LinkHeaderFieldParser.java (revision 1907912) +++ jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/util/LinkHeaderFieldParser.java (nonexistent) @@ -1,197 +0,0 @@ -/* - * 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.webdav.util; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.Enumeration; -import java.util.HashMap; -import java.util.List; -import java.util.Locale; -import java.util.Map; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import org.apache.http.NameValuePair; -import org.apache.http.message.BasicHeaderValueParser; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * Simple parser for HTTP Link header fields, as defined in RFC 5988. - */ -public class LinkHeaderFieldParser { - - /** - * the default logger - */ - private static Logger log = LoggerFactory.getLogger(LinkHeaderFieldParser.class); - - private final List relations; - - public LinkHeaderFieldParser(List fieldValues) { - List tmp = new ArrayList(); - if (fieldValues != null) { - for (String value : fieldValues) { - addFields(tmp, value); - } - } - relations = Collections.unmodifiableList(tmp); - } - - public LinkHeaderFieldParser(Enumeration en) { - if (en != null && en.hasMoreElements()) { - List tmp = new ArrayList(); - - while (en.hasMoreElements()) { - addFields(tmp, en.nextElement().toString()); - } - relations = Collections.unmodifiableList(tmp); - } else { - // optimize case of no Link headers - relations = Collections.emptyList(); - } - } - - public String getFirstTargetForRelation(String relationType) { - - for (LinkRelation lr : relations) { - - String relationNames = lr.getParameters().get("rel"); - if (relationNames != null) { - - // split rel value on whitespace - for (String rn : relationNames.toLowerCase(Locale.ENGLISH) - .split("\\s")) { - if (relationType.equals(rn)) { - return lr.getTarget(); - } - } - } - } - - return null; - } - - // A single header field instance can contain multiple, comma-separated - // fields. - private void addFields(List l, String fieldValue) { - - boolean insideAngleBrackets = false; - boolean insideDoubleQuotes = false; - - for (int i = 0; i < fieldValue.length(); i++) { - - char c = fieldValue.charAt(i); - - if (insideAngleBrackets) { - insideAngleBrackets = c != '>'; - } else if (insideDoubleQuotes) { - insideDoubleQuotes = c != '"'; - if (c == '\\' && i < fieldValue.length() - 1) { - // skip over next character - c = fieldValue.charAt(++i); - } - } else { - insideAngleBrackets = c == '<'; - insideDoubleQuotes = c == '"'; - - if (c == ',') { - String v = fieldValue.substring(0, i); - if (v.length() > 0) { - try { - l.add(new LinkRelation(v)); - } catch (Exception ex) { - log.warn("parse error in Link Header field value", - ex); - } - } - addFields(l, fieldValue.substring(i + 1)); - return; - } - } - } - - if (fieldValue.length() > 0) { - try { - l.add(new LinkRelation(fieldValue)); - } catch (Exception ex) { - log.warn("parse error in Link Header field value", ex); - } - } - } - - private static class LinkRelation { - - private static Pattern P = Pattern.compile("\\s*<(.*)>\\s*(.*)"); - - private String target; - private Map parameters; - - /** - * Parses a single link relation, consisting of and optional - * parameters. - * - * @param field - * field value - * @throws Exception - */ - public LinkRelation(String field) throws Exception { - - // find the link target using a regexp - Matcher m = P.matcher(field); - if (!m.matches()) { - throw new Exception("illegal Link header field value:" + field); - } - - target = m.group(1); - - // pass the remainder to the generic parameter parser - NameValuePair[] params = BasicHeaderValueParser.parseParameters(m.group(2), null); - - if (params.length == 0) { - parameters = Collections.emptyMap(); - } else if (params.length == 1) { - NameValuePair nvp = params[0]; - parameters = Collections.singletonMap(nvp.getName() - .toLowerCase(Locale.ENGLISH), nvp.getValue()); - } else { - parameters = new HashMap(); - for (NameValuePair p : params) { - if (null != parameters.put( - p.getName().toLowerCase(Locale.ENGLISH), - p.getValue())) { - throw new Exception("duplicate parameter + " - + p.getName() + " field ignored"); - } - } - } - } - - public String getTarget() { - return target; - } - - public Map getParameters() { - return parameters; - } - - public String toString() { - return target + " " + parameters; - } - } -} Property changes on: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/util/LinkHeaderFieldParser.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/util/package-info.java =================================================================== --- jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/util/package-info.java (revision 1907912) +++ jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/util/package-info.java (nonexistent) @@ -1,18 +0,0 @@ -/* - * 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. - */ -@org.osgi.annotation.versioning.Version("1.1.0") -package org.apache.jackrabbit.webdav.util; Property changes on: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/util/package-info.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/ActivityResource.java =================================================================== --- jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/ActivityResource.java (revision 1907912) +++ jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/ActivityResource.java (nonexistent) @@ -1,98 +0,0 @@ -/* - * 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.webdav.version; - -import org.apache.jackrabbit.webdav.property.DavPropertyName; - -/** - * An activity is a resource that selects a set of versions that are on a single - * "line of descent", where a line of descent is a sequence of versions connected - * by successor relationships. If an activity selects versions from multiple - * version histories, the versions selected in each version history must be on a - * single line of descent. - *

- * RFC 3253 defines the following required live properties for an Activity - * resource. - *

    - *
  • {@link #ACTIVITY_VERSION_SET DAV:activity-version-set}
  • - *
  • {@link #ACTIVITY_CHECKOUT_SET DAV:activity-checkout-set}
  • - *
  • {@link #SUBACTIVITY_SET DAV:subactivity-set}
  • - *
  • {@link #CURRENT_WORKSPACE_SET DAV:current-workspace-set}
  • - *
  • all DeltaV-compliant resource properties}.
  • - *
  • Note, that the {@link org.apache.jackrabbit.webdav.DavConstants#PROPERTY_RESOURCETYPE DAV:resourcetype} - * property returned by an Activity resource must be - * {@link org.apache.jackrabbit.webdav.property.ResourceType#ACTIVITY DAV:activity}
  • - *
- *

- * The Activity resource must support all methods defined for a - * {@link DeltaVResource DeltaV-compliant resource}. Since no additional methods - * are required for an activity this interface mainly acts as marker. - *

- * Please refer to RFC 3253 - * Section 13 for a complete description of this resource type. - */ -public interface ActivityResource extends DeltaVResource { - - /** - * The computed DAV:activity-version-set property identifies each version - * whose DAV:activity-set property identifies this activity. Multiple - * versions of a single version history can be selected by an activity's - * DAV:activity-version-set property, but all DAV:activity-version-set - * versions from a given version history must be on a single line of descent - * from the root version of that version history. - *

- * Note that the DAV:activity-version-set represents a - * {@link org.apache.jackrabbit.webdav.property.HrefProperty HrefProperty} - */ - public static final DavPropertyName ACTIVITY_VERSION_SET = DavPropertyName.create("activity-version-set", DeltaVConstants.NAMESPACE); - - /** - * The computed DAV:activity-checkout-set property identifies each - * checked-out resource whose DAV:activity-set identifies this activity. - *

- * Note that the DAV:activity-checkout-set represents a - * {@link org.apache.jackrabbit.webdav.property.HrefProperty HrefProperty} - */ - public static final DavPropertyName ACTIVITY_CHECKOUT_SET = DavPropertyName.create("activity-checkout-set", DeltaVConstants.NAMESPACE); - - /** - * The DAV:subactivity-set property identifies each activity that forms a - * part of the logical change being captured by this activity. An activity - * behaves as if its DAV:activity-version-set is extended by the - * DAV:activity-version-set of each activity identified in the - * DAV:subactivity-set. In particular, the versions in this extended set - * MUST be on a single line of descent, and when an activity selects a version - * for merging, the latest version in this extended set is the one that will - * be merged. - *

- * A server MAY reject attempts to modify the DAV:subactivity-set of an activity. - * - * Note that the DAV:subactivity-set represents a - * {@link org.apache.jackrabbit.webdav.property.HrefProperty HrefProperty} - */ - public static final DavPropertyName SUBACTIVITY_SET = DavPropertyName.create("subactivity-set", DeltaVConstants.NAMESPACE); - - /** - * The computed DAV:current-workspace-set property identifies identifies - * each workspace whose DAV:current-activity-set identifies this activity. - *

- * Note that the DAV:current-workspace-set represents a - * {@link org.apache.jackrabbit.webdav.property.HrefProperty HrefProperty} - */ - public static final DavPropertyName CURRENT_WORKSPACE_SET = DavPropertyName.create("current-workspace-set", DeltaVConstants.NAMESPACE); - -} \ No newline at end of file Property changes on: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/ActivityResource.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Deleted: svn:keywords ## -1 +0,0 ## -author date id revision url \ No newline at end of property Index: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/BaselineResource.java =================================================================== --- jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/BaselineResource.java (revision 1907912) +++ jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/BaselineResource.java (nonexistent) @@ -1,81 +0,0 @@ -/* - * 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.webdav.version; - -import org.apache.jackrabbit.webdav.property.DavPropertyName; -import org.apache.jackrabbit.webdav.DavResource; -import org.apache.jackrabbit.webdav.DavException; - -/** - * BaselineResource represents the 'version' of a configuration - * which is represented by a 'version-controlled-configuration' (VCC) resource. - * Such as new versions are created by CHECKIN of a version-controlled - * resource, a new baseline is created, whenever the VCC resource, that - * represents a set of resources rather than a single resource, is checked-in. - *

- * Since the baseline behaves like a VersionResource and only is - * defined to provide additional protected properties, this interface only adds - * a convenience method that allows to retrieve the baseline collection. - *

- * Supported live properties: - *

- * DAV:baseline-collection
- * DAV:subbaseline-set
- * all version properties.
- * 
- * - * Supported methods: - *
- * all version methods.
- * 
- */ -public interface BaselineResource extends VersionResource { - - /** - * The protected DAV:baseline-collection property identifies a distinct - * collection that lists as members all version-controlled resources of - * the configuration this baseline belongs to (the baseline being one - * version of the corresponding vc-configuration-resource). In other words: - * each member in the list must correspond to a member of the baseline-controlled - * collection at the time this baseline (version) was created. - *

- * - * Note that the DAV:baseline-collection represents a - * {@link org.apache.jackrabbit.webdav.property.HrefProperty HrefProperty} - */ - public static final DavPropertyName BASELINE_COLLECTION = DavPropertyName.create("baseline-collection", DeltaVConstants.NAMESPACE); - - /** - * The protected DAV:subbaseline-set property identifies a set of baseline - * resources. Note however, that the subbaselines of this resource are - * not only formed from the baseline resources listed in this property - * but also includes all subbaseline resources of the latter. - * - * Note that the DAV:subbaseline-set represents a - * {@link org.apache.jackrabbit.webdav.property.HrefProperty HrefProperty} - */ - public static final DavPropertyName SUBBASELINE_SET = DavPropertyName.create("subbaseline-set", DeltaVConstants.NAMESPACE); - - /** - * Return the resource that represents the baseline-collection of this - * baseline, which is identified the href present in the {@link #BASELINE_COLLECTION} - * property. - * - * @return baseline collection - */ - public DavResource getBaselineCollection() throws DavException; -} \ No newline at end of file Property changes on: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/BaselineResource.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Deleted: svn:keywords ## -1 +0,0 ## -author date id revision url \ No newline at end of property Index: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/DeltaVConstants.java =================================================================== --- jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/DeltaVConstants.java (revision 1907912) +++ jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/DeltaVConstants.java (nonexistent) @@ -1,374 +0,0 @@ -/* - * 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.webdav.version; - -import org.apache.jackrabbit.webdav.DavConstants; -import org.apache.jackrabbit.webdav.property.DavPropertyName; -import org.apache.jackrabbit.webdav.xml.Namespace; - -/** - * DeltaVConstants defines the following headers and properties - * required for any resource that is compliant to - * RFC 3253:

- * - * Headers: - *

- * Label
- * 
- * - * Properties: - *
- * DAV:comment
- * DAV:creator-displayname
- * DAV:supported-method-set
- * DAV:supported-live-property-set
- * DAV:supported-report-set
- * 
- * - * Some additional resource properties are defined by the various advanced - * version features: - *
- * DAV:workspace (workspace feature)
- * DAV:version-controlled-configuration (baseline)
- * 
- */ -public interface DeltaVConstants { - - /** - * The DAV: namespace. - */ - public static final Namespace NAMESPACE = DavConstants.NAMESPACE; - - //---< Headers >------------------------------------------------------------ - /** - * For certain METHODS, if the request-URL identifies a version-controlled - * resource, a label can be specified in a LabelInfo request header to cause the - * method to be applied to the version selected by that label.
- * LabelInfo header MUST have no effect on a request whose request-URL does not - * identify a version-controlled resource. In particular, it MUST have no - * effect on a request whose request-URL identifies a version or a version - * history. - */ - public static final String HEADER_LABEL = "Label"; - - /** - * Location header as defined by - * RFC 2616. In the versioning - * context it is used to indicate the location of the new version created by a - * successful checkin in the response.

- * From RFC 2616:
- * The Location response-header field is used to redirect the recipient to a - * location other than the Request-URI for completion of the request or - * identification of a new resource.
- * For 201 (Created) responses, the Location is that of the new resource - * which was created by the request. - */ - public static final String HEADER_LOCATION = "Location"; - - //---< Property Names >----------------------------------------------------- - /** - * The "DAV:comment" property is used to track a brief comment about a resource that is - * suitable for presentation to a user. The DAV:comment of a version can be - * used to indicate why that version was created. - */ - public static final DavPropertyName COMMENT = DavPropertyName.create("comment", NAMESPACE); - - /** - * The "DAV:creator-displayname" property contains a description of the creator of - * the resource that is suitable for presentation to a user. The - * DAV:creator-displayname of a version can be used to indicate who created - * that version. - */ - public static final DavPropertyName CREATOR_DISPLAYNAME = DavPropertyName.create("creator-displayname", NAMESPACE); - - /** - * Required protected live property for any resources being compliant with - * RFC 3253. Clients should classify a resource by examine the values of the - * DAV:supported-method-set and DAV:supported-live-property-set - * properties of that resource.
- * Property structure: - *
-     * <!ELEMENT supported-method-set (supported-method*)>
-     * <!ELEMENT supported-method ANY>
-     * <!ATTLIST supported-method name NMTOKEN #REQUIRED>
-     * name value: a method name
-     * 
- * - * @see #SUPPORTED_LIVE_PROPERTY_SET - */ - public static final DavPropertyName SUPPORTED_METHOD_SET = DavPropertyName.create("supported-method-set", NAMESPACE); - - /** - * Required protected live property for any resources being compliant with - * RFC 3253. Clients should classify a resource by examine the values of the - * DAV:supported-method-set and DAV:supported-live-property-set - * properties of that resource.
- * Property structure: - *
-     * <!ELEMENT supported-live-property-set (supported-live-property*)>
-     * <!ELEMENT supported-live-property name>
-     * <!ELEMENT prop ANY>
-     * ANY value: a property element type
-     * 
- * - * @see #SUPPORTED_METHOD_SET - */ - public static final DavPropertyName SUPPORTED_LIVE_PROPERTY_SET = DavPropertyName.create("supported-live-property-set", NAMESPACE); - - /** - * Protected "supported-report-set" property identifies the reports that are - * supported by the resource. - * - * @see #SUPPORTED_REPORT_SET - */ - public static final DavPropertyName SUPPORTED_REPORT_SET = DavPropertyName.create("supported-report-set", NAMESPACE); - - /** - * Protected "workspace" property indicating the workspace of a resource. - * This property is required for all resources if (but only if) the workspace - * feature is supported. - *

- * Note that the DAV:activity-version-set represents a - * {@link org.apache.jackrabbit.webdav.property.HrefProperty HrefProperty}. - * It is defined to have the following format: - *

-     * <!ELEMENT workspace (href)>
-     * 
- * - * @see WorkspaceResource - */ - public static final DavPropertyName WORKSPACE = DavPropertyName.create("workspace", NAMESPACE); - - /** - * The Baseline feature introduces the computed DAV:version-controlled-configuration - * property for all resources that are member of a version-controlled - * configuration. This may be the case if the resource is a collection under - * baseline control or is a member of a collection under baseline control. - *

- * Note that the DAV:activity-version-set represents a - * {@link org.apache.jackrabbit.webdav.property.HrefProperty HrefProperty}. - * It is defined to have the following format: - *

-     * <!ELEMENT version-controlled-configuration (href)>
-     * 
- */ - public static final DavPropertyName VERSION_CONTROLLED_CONFIGURATION = DavPropertyName.create("version-controlled-configuration", NAMESPACE); - - - //---< XML Element, Attribute Names >--------------------------------------- - /** - * Xml elements - */ - public static final String XML_ACTIVITY = "activity"; - public static final String XML_BASELINE = "baseline"; - - public static final String XML_SUPPORTED_METHOD = "supported-method"; - public static final String XML_VERSION_HISTORY = "version-history"; - public static final String XML_VERSION = "version"; - public static final String XML_WORKSPACE = "workspace"; - - // options - /** - * If the OPTIONS request contains a body, i must start with an DAV:options - * element. - * - * @see OptionsInfo - * @see #XML_VH_COLLECTION_SET - * @see #XML_WSP_COLLECTION_SET - * @see #XML_ACTIVITY_COLLECTION_SET - */ - public static final String XML_OPTIONS = "options"; - - /** - * If an XML response body for a successful request is included, it must be - * a DAV:options-response XML element. - * - * @see OptionsResponse - */ - public static final String XML_OPTIONS_RESPONSE = "options-response"; - - /** - * A DAV:version-history-collection-set element may be included in the OPTIONS - * request body to identify collections that may contain version history - * resources.
- * The response body for a successful request must in consequence contain a - * DAV:version-history-collection-set element identifying collections that - * may contain version histories. An identified collection may be the root - * collection of a tree of collections, all of which may contain version - * histories. - * - *
-     * <!ELEMENT version-history-collection-set (href*)>
-     * 
- */ - public static final String XML_VH_COLLECTION_SET = "version-history-collection-set"; - - /** - * A DAV:workspace-collection-set element may be included in the OPTIONS request - * body to identify collections that may contain workspace resources.
- * The response body for a successful request must contain a - * DAV:workspace-collection-set element identifying collections that may - * contain workspaces. An identified collection may be the root collection - * of a tree of collections, all of which may contain workspaces. - * - *
-     * <!ELEMENT workspace-collection-set (href*)>
-     * 
- */ - public static final String XML_WSP_COLLECTION_SET = "workspace-collection-set"; - - /** - * A DAV:workspace-collection-set element may be included in the OPTIONS request - * body to identify collections that may contain activity resources.
- * The response body for a successful request must contain a - * DAV:workspace-collection-set element identifying collections that may - * contain activity resources. An identified collection may be the root collection - * of a tree of collections, all of which may contain activity resources. - * - *
-     * <!ELEMENT activity-collection-set (href*)>
-     * 
- */ - public static final String XML_ACTIVITY_COLLECTION_SET = "activity-collection-set"; - - /** - * Name of Xml element contained in the {@link #SUPPORTED_REPORT_SET} property. - * - * @see #SUPPORTED_REPORT_SET - * @see org.apache.jackrabbit.webdav.version.report.SupportedReportSetProperty - */ - public static final String XML_SUPPORTED_REPORT = "supported-report"; - - /** - * Name of Xml child elements of {@link #XML_SUPPORTED_REPORT}. - * - * @see org.apache.jackrabbit.webdav.version.report.SupportedReportSetProperty - */ - public static final String XML_REPORT = "report"; - - /** - * Top element for the 'DAV:version-tree' report - */ - public static final String XML_VERSION_TREE = "version-tree"; - - /** - * Top element for the 'DAV:expand-property' report - */ - public static final String XML_EXPAND_PROPERTY = "expand-property"; - - /** - * 'DAV:property' element to be used inside the 'DAV:expand-property' element. - * - * @see #XML_EXPAND_PROPERTY - */ - public static final String XML_PROPERTY = "property"; - - /** - * 'DAV:name' attribute for the property element - * - * @see #XML_PROPERTY - */ - public static final String ATTR_NAME = "name"; - - /** - * 'DAV:namespace' attribute for the property element - * - * @see #XML_PROPERTY - */ - public static final String ATTR_NAMESPACE = "namespace"; - - /** - * Top element for the 'DAV:locate-by-history' report - */ - public static final String XML_LOCATE_BY_HISTORY = "locate-by-history"; - - /** - * 'DAV:version-history-set' to be used inside the 'DAV:locate-by-history' - * element - * - * @see #XML_LOCATE_BY_HISTORY - */ - public static final String XML_VERSION_HISTORY_SET = "version-history-set"; - - - /** - * Xml element representing the mandatory root element of a LABEL request - * body. - * - * @see #XML_LABEL_NAME - * @see #XML_LABEL_ADD - * @see #XML_LABEL_REMOVE - * @see #XML_LABEL_SET - * @see LabelInfo - */ - public static final String XML_LABEL = "label"; - public static final String XML_LABEL_NAME = "label-name"; - public static final String XML_LABEL_ADD = "add"; - public static final String XML_LABEL_REMOVE = "remove"; - public static final String XML_LABEL_SET = "set"; - - /** - * Xml element defining the top element in the UPDATE request body. RFC 3253 - * defines the following structure for the 'update' element. - *
-     * <!ELEMENT update ANY>
-     * ANY value: A sequence of elements with at most one DAV:version element
-     * and at most one DAV:prop element.
-     * <!ELEMENT version (href)>
-     * prop: see RFC 2518, Section 12.11
-     * 
- */ - public static final String XML_UPDATE = "update"; - - // auto-version - /** - * Value for the DAV:auto-version property indicating that any modification - * (such as PUT/PROPPATCH) applied to a checked-in version-controlled - * resource will automatically be preceded by a checkout and followed by a - * checkin operation.
- * See also RFC 3253 DAV:auto-version - */ - public static final String XML_CHECKOUT_CHECKIN = "checkout-checkin"; - /** - * Value for the DAV:auto-version property indicating that any modification - * (such as PUT/PROPPATCH) applied to a checked-in version-controlled - * resource will automatically be preceded by a checkout operation. - * If the resource is not write-locked, the request is automatically - * followed by a checkin operation.
- * See also RFC 3253 DAV:auto-version - */ - public static final String XML_CHECKOUT_UNLOCK_CHECKIN = "checkout-unlocked-checkin"; - /** - * Value for the DAV:auto-version property indicating that any modification - * (such as PUT/PROPPATCH) applied to a checked-in version-controlled - * resource will automatically be preceded by a checkout operation.
- * See also RFC 3253 DAV:auto-version - */ - public static final String XML_CHECKOUT = "checkout"; - /** - * Value for the DAV:auto-version property indicating that any modification - * (such as PUT/PROPPATCH) applied to a write-locked checked-in version-controlled - * resource will automatically be preceded by a checkout operation.
- * See also RFC 3253 DAV:auto-version - */ - public static final String XML_LOCKED_CHECKIN = "locked-checkout"; - - // merge - public static final String XML_MERGE = "merge"; - public static final String XML_N0_AUTO_MERGE = "no-auto-merge"; - public static final String XML_N0_CHECKOUT = "no-checkout"; -} \ No newline at end of file Property changes on: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/DeltaVConstants.java ___________________________________________________________________ Deleted: svn Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/DeltaVResource.java =================================================================== --- jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/DeltaVResource.java (revision 1907912) +++ jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/DeltaVResource.java (nonexistent) @@ -1,111 +0,0 @@ -/* - * 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.webdav.version; - -import org.apache.jackrabbit.webdav.DavException; -import org.apache.jackrabbit.webdav.DavResource; -import org.apache.jackrabbit.webdav.property.DavPropertyName; -import org.apache.jackrabbit.webdav.version.report.Report; -import org.apache.jackrabbit.webdav.version.report.ReportInfo; - -/** - * The DeltaVResource encapsulates the functionality common to all - * DeltaV compliant resources. - *

- * RFC 3253 defines the following required properties: - *

    - *
  • {@link DeltaVConstants#COMMENT DAV:comment}
  • - *
  • {@link DeltaVConstants#CREATOR_DISPLAYNAME DAV:creator-displayname}
  • - *
  • {@link DeltaVConstants#SUPPORTED_METHOD_SET DAV:supported-method-set}
  • - *
  • {@link DeltaVConstants#SUPPORTED_LIVE_PROPERTY_SET DAV:supported-live-property-set}
  • - *
  • {@link DeltaVConstants#SUPPORTED_REPORT_SET DAV:supported-report-set}
  • - *
  • all properties defined in WebDAV [RFC2518].
  • - *
- *

- * In addition a DeltaV compliant resource must support the following METHODS: - *

    - *
  • REPORT
  • - *
  • all METHODS defined in WebDAV [RFC2518]
  • - *
  • all METHODS defined in HTTP/1.1 [RFC2616].
  • - *
- * - * @see DavResource - */ -public interface DeltaVResource extends DavResource { - - /** - * The generic deltaV compliant resource defines one additional method REPORT. - * - * @see org.apache.jackrabbit.webdav.DavResource#METHODS - */ - public String METHODS = "REPORT"; - - /** - * If the server support the Workspace featured defined by RFC 3253 certain - * DeltaVResources may also support the MKWORKSPACE method. - * - * @see #addWorkspace(DavResource) - */ - public String METHODS_INCL_MKWORKSPACE = "REPORT, MKWORKSPACE"; - - /** - * Retrieves the information requested in the OPTIONS request body and - * returns the corresponding values. - * - * @param optionsInfo - * @return object to be included to the OPTIONS response body or null - * if the specified optionsInfo was null or empty. - */ - public OptionsResponse getOptionResponse(OptionsInfo optionsInfo); - - /** - * Runs the report specified by the given ReportInfo. - * - * @param reportInfo - * @return the requested report. - * @throws DavException in case an error occurred or if the specified ReportInfo - * is either not valid or cannot be run by the given resource. - */ - public Report getReport(ReportInfo reportInfo) throws DavException; - - /** - * Add a new member to this resource, that represents a workspace.
- * Please note that no resource must exist at the location of the new workspace. - * - * @param workspace resource representing the new workspace to be created as - * member of this resource. - * @throws DavException if creating the new workspace fails. - */ - // TODO: MKWORKSPACE may include an xml request body... - public void addWorkspace(DavResource workspace) throws DavException; - - /** - * Returns an array of DavResource objects that are referenced - * by the {@link org.apache.jackrabbit.webdav.property.HrefProperty} with - * the specified {@link DavPropertyName name}. - * - * @param hrefPropertyName - * @return An array of DavResources - * @throws DavException if the given hrefPropertyName does point to an - * unknown property or does not represent the name of a - * {@link org.apache.jackrabbit.webdav.property.HrefProperty href property}. - * Finally the exception may be caused if the property contains the href - * of a non-existing resource, which cannot be resolved. - * @see org.apache.jackrabbit.webdav.property.HrefProperty - */ - public DavResource[] getReferenceResources(DavPropertyName hrefPropertyName) throws DavException; -} \ No newline at end of file Property changes on: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/DeltaVResource.java ___________________________________________________________________ Deleted: svn Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/DeltaVServletRequest.java =================================================================== --- jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/DeltaVServletRequest.java (revision 1907912) +++ jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/DeltaVServletRequest.java (nonexistent) @@ -1,84 +0,0 @@ -/* - * 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.webdav.version; - -import org.apache.jackrabbit.webdav.DavException; -import org.apache.jackrabbit.webdav.DavServletRequest; -import org.apache.jackrabbit.webdav.version.report.ReportInfo; - -/** - * DeltaVServletRequest provides extension useful for functionality - * related to RFC 3253. - */ -public interface DeltaVServletRequest extends DavServletRequest { - - /** - * Returns the Label header or null - * - * @return label header or null - * @see DeltaVConstants#HEADER_LABEL - */ - public String getLabel(); - - /** - * Return the request body as LabelInfo object or null - * if parsing the request body or the creation of the label info failed. - * - * @return LabelInfo object or null - * @throws DavException in case of an invalid request body - */ - public LabelInfo getLabelInfo() throws DavException; - - /** - * Return the request body as MergeInfo object or null - * if the creation failed due to invalid format. - * - * @return MergeInfo object or null - * @throws DavException in case of an invalid request body - */ - public MergeInfo getMergeInfo() throws DavException; - - /** - * Parses the UPDATE request body a build the corresponding UpdateInfo - * object. If the request body is missing or does not of the required format - * null is returned. - * - * @return the parsed update request body or null - * @throws DavException in case of an invalid request body - */ - public UpdateInfo getUpdateInfo() throws DavException; - - /** - * Returns the request body and the Depth header as ReportInfo - * object. The default depth, if no {@link org.apache.jackrabbit.webdav.DavConstants#HEADER_DEPTH - * Depth header}, is {@link org.apache.jackrabbit.webdav.DavConstants#DEPTH_0}. - * If the request body could not be parsed into an {@link org.w3c.dom.Element} - * null is returned. - * - * @return ReportInfo or null - * @throws DavException in case of an invalid request body - */ - public ReportInfo getReportInfo() throws DavException; - - /** - * Returns the {@link OptionsInfo} present with the request or null. - * - * @return {@link OptionsInfo} or null - * @throws DavException in case of an invalid request body - */ - public OptionsInfo getOptionsInfo() throws DavException; -} \ No newline at end of file Property changes on: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/DeltaVServletRequest.java ___________________________________________________________________ Deleted: svn Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/LabelInfo.java =================================================================== --- jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/LabelInfo.java (revision 1907912) +++ jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/LabelInfo.java (nonexistent) @@ -1,188 +0,0 @@ -/* - * 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.webdav.version; - -import org.apache.jackrabbit.webdav.DavConstants; -import org.apache.jackrabbit.webdav.DavException; -import org.apache.jackrabbit.webdav.DavServletResponse; -import org.apache.jackrabbit.webdav.xml.DomUtil; -import org.apache.jackrabbit.webdav.xml.XmlSerializable; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.w3c.dom.Document; -import org.w3c.dom.Element; - -/** - * LabelInfo encapsulates the request body of a LABEL request - * used to add, set or remove a label from the requested version resource or - * from that version specified with the Label header in case the requested resource - * is a version-controlled resource.

- * The request body (thus the 'labelElement' passed to the constructor must be - * a DAV:label element: - *
- * <!ELEMENT label ANY>
- * ANY value: A sequence of elements with at most one DAV:add,
- * DAV:set, or DAV:remove element.
- * <!ELEMENT add (label-name)>
- * <!ELEMENT set (label-name)>
- * <!ELEMENT remove (label-name)>
- * <!ELEMENT label-name (#PCDATA)>
- * PCDATA value: string
- * 
- * Please note, that the given implementation only recognizes the predefined elements 'add', - * 'set' and 'remove'. - */ -public class LabelInfo implements DeltaVConstants, XmlSerializable { - - private static Logger log = LoggerFactory.getLogger(LabelInfo.class); - - public static final int TYPE_SET = 0; - public static final int TYPE_REMOVE = 1; - public static final int TYPE_ADD = 2; - - public static String[] typeNames = new String[] { XML_LABEL_SET , XML_LABEL_REMOVE, XML_LABEL_ADD}; - - private final int depth; - private final int type; - private final String labelName; - - public LabelInfo(String labelName, String type) { - if (labelName == null) { - throw new IllegalArgumentException("Label name must not be null."); - } - boolean validType = false; - int i = 0; - while (i < typeNames.length) { - if (typeNames[i].equals(type)) { - validType = true; - break; - } - i++; - } - if (!validType) { - throw new IllegalArgumentException("Invalid type: " + type); - } - this.type = i; - this.labelName = labelName; - this.depth = DavConstants.DEPTH_0; - } - - public LabelInfo(String labelName, int type) { - this(labelName, type, DavConstants.DEPTH_0); - } - - public LabelInfo(String labelName, int type, int depth) { - if (labelName == null) { - throw new IllegalArgumentException("Label name must not be null."); - } - if (type < TYPE_SET || type > TYPE_ADD) { - throw new IllegalArgumentException("Invalid type: " + type); - } - this.labelName = labelName; - this.type = type; - this.depth = depth; - } - - /** - * Create a new LabelInfo from the given element and depth - * integer. If the specified Xml element does have a {@link DeltaVConstants#XML_LABEL} - * root element or no label name is specified with the action to perform - * the creation will fail. - * - * @param labelElement - * @param depth - * @throws DavException if the specified element does not - * start with a {@link DeltaVConstants#XML_LABEL} element or if the DAV:label - * element contains illegal instructions e.g. contains multiple DAV:add, DAV:set - * or DAV:remove elements. - */ - public LabelInfo(Element labelElement, int depth) throws DavException { - if (!DomUtil.matches(labelElement, DeltaVConstants.XML_LABEL, DeltaVConstants.NAMESPACE)) { - log.warn("DAV:label element expected"); - throw new DavException(DavServletResponse.SC_BAD_REQUEST); - } - - String label = null; - int type = -1; - for (int i = 0; i < typeNames.length && type == -1; i++) { - if (DomUtil.hasChildElement(labelElement, typeNames[i], NAMESPACE)) { - type = i; - Element el = DomUtil.getChildElement(labelElement, typeNames[i], NAMESPACE); - label = DomUtil.getChildText(el, XML_LABEL_NAME, NAMESPACE); - } - } - if (label == null) { - log.warn("DAV:label element must contain at least one set, add or remove element defining a label-name."); - throw new DavException(DavServletResponse.SC_BAD_REQUEST); - } - this.labelName = label; - this.type = type; - this.depth = depth; - } - - /** - * Create a new LabelInfo from the given element. As depth - * the default value 0 is assumed. - * - * @param labelElement - * @throws DavException - * @see #LabelInfo(org.w3c.dom.Element, int) - */ - public LabelInfo(Element labelElement) throws DavException { - this(labelElement, 0); - } - - /** - * Return the text present inside the 'DAV:label-name' element or null - * - * @return 'label-name' or null - */ - public String getLabelName() { - return labelName; - } - - /** - * Return the type of the LABEL request. This might either be {@link #TYPE_SET}, - * {@link #TYPE_ADD} or {@link #TYPE_REMOVE}. - * - * @return type - */ - public int getType() { - return type; - } - - /** - * Return the depth - * - * @return depth - */ - public int getDepth() { - return depth; - } - - /** - * @see org.apache.jackrabbit.webdav.xml.XmlSerializable#toXml(Document) - * @param document - */ - public Element toXml(Document document) { - Element label = DomUtil.createElement(document, XML_LABEL, NAMESPACE); - Element typeElem = DomUtil.addChildElement(label, typeNames[type], NAMESPACE); - DomUtil.addChildElement(typeElem, XML_LABEL_NAME, NAMESPACE, labelName); - return label; - } - -} \ No newline at end of file Property changes on: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/LabelInfo.java ___________________________________________________________________ Deleted: svn Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/LabelSetProperty.java =================================================================== --- jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/LabelSetProperty.java (revision 1907912) +++ jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/LabelSetProperty.java (nonexistent) @@ -1,63 +0,0 @@ -/* - * 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.webdav.version; - -import org.apache.jackrabbit.webdav.property.AbstractDavProperty; -import org.apache.jackrabbit.webdav.xml.DomUtil; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.w3c.dom.Document; -import org.w3c.dom.Element; - -/** - * LabelSetProperty... - */ -public class LabelSetProperty extends AbstractDavProperty { - - private static Logger log = LoggerFactory.getLogger(LabelSetProperty.class); - - private final String[] value; - - /** - * Create a new LabelSetProperty. - * - * @param labels - */ - public LabelSetProperty(String[] labels) { - super(VersionResource.LABEL_NAME_SET, true); - this.value = labels; - } - - - public String[] getValue() { - return value; - } - - /** - * @see org.apache.jackrabbit.webdav.xml.XmlSerializable#toXml(Document) - * @param document - */ - @Override - public Element toXml(Document document) { - Element elem = getName().toXml(document); - for (String str : value) { - DomUtil.addChildElement(elem, DeltaVConstants.XML_LABEL_NAME, DeltaVConstants.NAMESPACE, str); - } - return elem; - } - -} Property changes on: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/LabelSetProperty.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Deleted: svn:keywords ## -1 +0,0 ## -author date id revision url \ No newline at end of property Index: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/MergeInfo.java =================================================================== --- jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/MergeInfo.java (revision 1907912) +++ jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/MergeInfo.java (nonexistent) @@ -1,182 +0,0 @@ -/* - * 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.webdav.version; - -import org.apache.jackrabbit.webdav.DavConstants; -import org.apache.jackrabbit.webdav.DavException; -import org.apache.jackrabbit.webdav.DavServletResponse; -import org.apache.jackrabbit.webdav.property.DavPropertyNameSet; -import org.apache.jackrabbit.webdav.xml.DomUtil; -import org.apache.jackrabbit.webdav.xml.ElementIterator; -import org.apache.jackrabbit.webdav.xml.XmlSerializable; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.w3c.dom.Document; -import org.w3c.dom.Element; - -import java.util.ArrayList; -import java.util.List; - -/** - * MergeInfo encapsulates the information present in the DAV:merge - * element, that forms the mandatory request body of a MERGE request.
- * The DAV:merge element is specified to have the following form. - *
- * <!ELEMENT merge ANY>
- * ANY value: A sequence of elements with one DAV:source element, at most one
- * DAV:no-auto-merge element, at most one DAV:no-checkout element, at most one
- * DAV:prop element, and any legal set of elements that can occur in a DAV:checkout
- * element.
- * <!ELEMENT source (href+)>
- * <!ELEMENT no-auto-merge EMPTY>
- * <!ELEMENT no-checkout EMPTY>
- * prop: see RFC 2518, Section 12.11
- * 
- */ -public class MergeInfo implements DeltaVConstants, XmlSerializable { - - private static Logger log = LoggerFactory.getLogger(MergeInfo.class); - - private final Element mergeElement; - private final DavPropertyNameSet propertyNameSet; - - /** - * Create a new MergeInfo - * - * @param mergeElement - * @throws DavException if the mergeElement is null - * or not a DAV:merge element. - */ - public MergeInfo(Element mergeElement) throws DavException { - if (!DomUtil.matches(mergeElement, XML_MERGE, NAMESPACE)) { - log.warn("'DAV:merge' element expected"); - throw new DavException(DavServletResponse.SC_BAD_REQUEST); - } - - // if property name set if present - Element propElem = DomUtil.getChildElement(mergeElement, DavConstants.XML_PROP, DavConstants.NAMESPACE); - if (propElem != null) { - propertyNameSet = new DavPropertyNameSet(propElem); - mergeElement.removeChild(propElem); - } else { - propertyNameSet = new DavPropertyNameSet(); - } - this.mergeElement = mergeElement; - } - - /** - * Returns the URL specified with the DAV:source element or null - * if no such child element is present in the DAV:merge element. - * - * @return href present in the DAV:source child element or null. - */ - public String[] getSourceHrefs() { - List sourceHrefs = new ArrayList(); - Element srcElem = DomUtil.getChildElement(mergeElement, DavConstants.XML_SOURCE, DavConstants.NAMESPACE); - if (srcElem != null) { - ElementIterator it = DomUtil.getChildren(srcElem, DavConstants.XML_HREF, DavConstants.NAMESPACE); - while (it.hasNext()) { - String href = DomUtil.getTextTrim(it.nextElement()); - if (href != null) { - sourceHrefs.add(href); - } - } - } - return sourceHrefs.toArray(new String[sourceHrefs.size()]); - } - - /** - * Returns true if the DAV:merge element contains a DAV:no-auto-merge child element. - * - * @return true if the DAV:merge element contains a DAV:no-auto-merge child. - */ - public boolean isNoAutoMerge() { - return DomUtil.hasChildElement(mergeElement, XML_N0_AUTO_MERGE, NAMESPACE); - } - - /** - * Returns true if the DAV:merge element contains a DAV:no-checkout child element. - * - * @return true if the DAV:merge element contains a DAV:no-checkout child - */ - public boolean isNoCheckout() { - return DomUtil.hasChildElement(mergeElement, XML_N0_CHECKOUT, NAMESPACE); - } - - /** - * Returns a {@link DavPropertyNameSet}. If the DAV:merge element contains - * a DAV:prop child element the properties specified therein are included - * in the set. Otherwise an empty set is returned.
- * - * WARNING: modifying the DavPropertyNameSet returned by this method does - * not modify this UpdateInfo. - * - * @return set listing the properties specified in the DAV:prop element indicating - * those properties that must be reported in the response body. - */ - public DavPropertyNameSet getPropertyNameSet() { - return propertyNameSet; - } - - /** - * Returns the DAV:merge element used to create this MergeInfo - * object. - * - * @return DAV:merge element - */ - public Element getMergeElement() { - return mergeElement; - } - - /** - * @see org.apache.jackrabbit.webdav.xml.XmlSerializable#toXml(Document) - * @param document - */ - public Element toXml(Document document) { - Element elem = (Element)document.importNode(mergeElement, true); - if (!propertyNameSet.isEmpty()) { - elem.appendChild(propertyNameSet.toXml(document)); - } - return elem; - } - - - /** - * Factory method to create a minimal DAV:merge element to create a new - * MergeInfo object. - * - * @param mergeSource - * @param isNoAutoMerge - * @param isNoCheckout - * @param factory - * @return - */ - public static Element createMergeElement(String[] mergeSource, boolean isNoAutoMerge, boolean isNoCheckout, Document factory) { - Element mergeElem = DomUtil.createElement(factory, XML_MERGE, NAMESPACE); - Element source = DomUtil.addChildElement(mergeElem, DavConstants.XML_SOURCE, DavConstants.NAMESPACE); - for (String ms : mergeSource) { - source.appendChild(DomUtil.hrefToXml(ms, factory)); - } - if (isNoAutoMerge) { - DomUtil.addChildElement(mergeElem, XML_N0_AUTO_MERGE, NAMESPACE); - } - if (isNoCheckout) { - DomUtil.addChildElement(mergeElem, XML_N0_CHECKOUT, NAMESPACE); - } - return mergeElem; - } -} Property changes on: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/MergeInfo.java ___________________________________________________________________ Deleted: svn Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/OptionsInfo.java =================================================================== --- jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/OptionsInfo.java (revision 1907912) +++ jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/OptionsInfo.java (nonexistent) @@ -1,126 +0,0 @@ -/* - * 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.webdav.version; - -import org.apache.jackrabbit.webdav.DavException; -import org.apache.jackrabbit.webdav.DavServletResponse; -import org.apache.jackrabbit.webdav.xml.DomUtil; -import org.apache.jackrabbit.webdav.xml.ElementIterator; -import org.apache.jackrabbit.webdav.xml.Namespace; -import org.apache.jackrabbit.webdav.xml.XmlSerializable; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.w3c.dom.Document; -import org.w3c.dom.Element; - -import java.util.HashSet; -import java.util.Set; -import java.util.Arrays; - -/** - * OptionsInfo represents the Xml request body, that may be present - * with a OPTIONS request. - *
- * The DAV:options element is specified to have the following form. - * - *
- * <!ELEMENT options ANY>
- * ANY value: A sequence of elements each at most once.
- * 
- * - * Note, that this is a simplified implementation of the very generic - * definition: We assume that the DAV:options element only contains empty child - * elements, such as e.g. {@link DeltaVConstants#XML_VH_COLLECTION_SET DAV:version-history-collection-set} - * or {@link DeltaVConstants#XML_WSP_COLLECTION_SET DAV:workspace-collection-set}. - * - * @see DeltaVConstants#XML_VH_COLLECTION_SET - * @see DeltaVConstants#XML_WSP_COLLECTION_SET - * @see DeltaVConstants#XML_ACTIVITY_COLLECTION_SET - */ -public class OptionsInfo implements XmlSerializable { - - private static Logger log = LoggerFactory.getLogger(OptionsInfo.class); - - private final Set entriesLocalNames = new HashSet(); - - /** - * Create a new OptionsInfo with the specified entries. Each entry will - * be converted to an empty Xml element when calling toXml. - * As namespace {@link DeltaVConstants#NAMESPACE} is used. - * - * @param entriesLocalNames - */ - public OptionsInfo(String[] entriesLocalNames) { - if (entriesLocalNames != null) { - this.entriesLocalNames.addAll(Arrays.asList(entriesLocalNames)); - } - } - - /** - * Private constructor used to create an OptionsInfo from Xml. - */ - private OptionsInfo() {} - - /** - * Returns true if a child element with the given name and namespace is present. - * - * @param localName - * @param namespace - * @return true if such a child element exists in the options element. - */ - public boolean containsElement(String localName, Namespace namespace) { - if (DeltaVConstants.NAMESPACE.equals(namespace)) { - return entriesLocalNames.contains(localName); - } - return false; - } - - /** - * @see org.apache.jackrabbit.webdav.xml.XmlSerializable#toXml(Document) - * @param document - */ - public Element toXml(Document document) { - Element optionsElem = DomUtil.createElement(document, DeltaVConstants.XML_OPTIONS, DeltaVConstants.NAMESPACE); - for (String localName : entriesLocalNames) { - DomUtil.addChildElement(optionsElem, localName, DeltaVConstants.NAMESPACE); - } - return optionsElem; - } - - /** - * Build an OptionsInfo object from the root element present - * in the request body. - * - * @param optionsElement - * @return - * @throws DavException if the optionsElement is null - * or not a DAV:options element. - */ - public static OptionsInfo createFromXml(Element optionsElement) throws DavException { - if (!DomUtil.matches(optionsElement, DeltaVConstants.XML_OPTIONS, DeltaVConstants.NAMESPACE)) { - log.warn("DAV:options element expected"); - throw new DavException(DavServletResponse.SC_BAD_REQUEST); - } - OptionsInfo oInfo = new OptionsInfo(); - ElementIterator it = DomUtil.getChildren(optionsElement); - while (it.hasNext()) { - // todo: not correct since assuming its the deltaV-namespace - oInfo.entriesLocalNames.add(it.nextElement().getLocalName()); - } - return oInfo; - } -} Property changes on: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/OptionsInfo.java ___________________________________________________________________ Deleted: svn Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/OptionsResponse.java =================================================================== --- jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/OptionsResponse.java (revision 1907912) +++ jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/OptionsResponse.java (nonexistent) @@ -1,144 +0,0 @@ -/* - * 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.webdav.version; - -import org.apache.jackrabbit.webdav.DavConstants; -import org.apache.jackrabbit.webdav.xml.DomUtil; -import org.apache.jackrabbit.webdav.xml.ElementIterator; -import org.apache.jackrabbit.webdav.xml.Namespace; -import org.apache.jackrabbit.webdav.xml.XmlSerializable; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.w3c.dom.Document; -import org.w3c.dom.Element; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -/** - * OptionsResponse encapsulates the DAV:options-response element - * present in the response body of a successful OPTIONS request (with body). - *
- * The DAV:options-response element is defined to have the following format. - * - *
- * <!ELEMENT options-response ANY>
- * ANY value: A sequence of elements
- * 
- * - * Please note, that OptionsResponse represents a simplified implementation - * of the given structure. We assume, that there may only entries that consist - * of a qualified name and a set of href child elements. - * - * @see DeltaVConstants#XML_ACTIVITY_COLLECTION_SET - * @see DeltaVConstants#XML_VH_COLLECTION_SET - * @see DeltaVConstants#XML_WSP_COLLECTION_SET - */ -public class OptionsResponse implements DeltaVConstants, XmlSerializable { - - private static Logger log = LoggerFactory.getLogger(OptionsResponse.class); - - private final Map entries = new HashMap(); - - /** - * Add a new entry to this OptionsResponse and make each - * href present in the String array being a separate {@link org.apache.jackrabbit.webdav.DavConstants#XML_HREF DAV:href} - * element within the entry. - * - * @param localName - * @param namespace - * @param hrefs - */ - public void addEntry(String localName, Namespace namespace, String[] hrefs) { - Entry entry = new Entry(localName, namespace, hrefs); - entries.put(DomUtil.getExpandedName(localName, namespace), entry); - } - - /** - * - * @param localName - * @param namespace - * @return - */ - public String[] getHrefs(String localName, Namespace namespace) { - String key = DomUtil.getExpandedName(localName, namespace); - if (entries.containsKey(key)) { - return entries.get(key).hrefs; - } else { - return new String[0]; - } - } - - /** - * Return the Xml representation. - * - * @return Xml representation. - * @see org.apache.jackrabbit.webdav.xml.XmlSerializable#toXml(Document) - * @param document - */ - public Element toXml(Document document) { - Element optionsResponse = DomUtil.createElement(document, XML_OPTIONS_RESPONSE, NAMESPACE); - for (Entry entry : entries.values()) { - Element elem = DomUtil.addChildElement(optionsResponse, entry.localName, entry.namespace); - for (String href : entry.hrefs) { - elem.appendChild(DomUtil.hrefToXml(href, document)); - } - } - return optionsResponse; - } - - /** - * Build a new OptionsResponse object from the given xml element. - * - * @param orElem - * @return a new OptionsResponse object - * @throws IllegalArgumentException if the specified element is null - * or if its name is other than 'DAV:options-response'. - */ - public static OptionsResponse createFromXml(Element orElem) { - if (!DomUtil.matches(orElem, XML_OPTIONS_RESPONSE, NAMESPACE)) { - throw new IllegalArgumentException("DAV:options-response element expected"); - } - OptionsResponse oResponse = new OptionsResponse(); - ElementIterator it = DomUtil.getChildren(orElem); - while (it.hasNext()) { - Element el = it.nextElement(); - List hrefs = new ArrayList(); - ElementIterator hrefIt = DomUtil.getChildren(el, DavConstants.XML_HREF, DavConstants.NAMESPACE); - while (hrefIt.hasNext()) { - hrefs.add(DomUtil.getTextTrim(hrefIt.nextElement())); - } - oResponse.addEntry(el.getLocalName(), DomUtil.getNamespace(el), hrefs.toArray(new String[hrefs.size()])); - } - return oResponse; - } - - private static class Entry { - - private final String localName; - private final Namespace namespace; - private final String[] hrefs; - - private Entry(String localName, Namespace namespace, String[] hrefs) { - this.localName = localName; - this.namespace = namespace; - this.hrefs = hrefs; - } - } -} Property changes on: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/OptionsResponse.java ___________________________________________________________________ Deleted: svn Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/SupportedMethodSetProperty.java =================================================================== --- jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/SupportedMethodSetProperty.java (revision 1907912) +++ jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/SupportedMethodSetProperty.java (nonexistent) @@ -1,63 +0,0 @@ -/* - * 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.webdav.version; - -import org.apache.jackrabbit.webdav.property.AbstractDavProperty; -import org.apache.jackrabbit.webdav.xml.DomUtil; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.w3c.dom.Document; -import org.w3c.dom.Element; - -/** - * The SupportedMethodSetProperty - */ -public class SupportedMethodSetProperty extends AbstractDavProperty implements DeltaVConstants { - - private static Logger log = LoggerFactory.getLogger(SupportedMethodSetProperty.class); - - private final String[] methods; - - /** - * Create a new SupportedMethodSetProperty property. - * - * @param methods that are supported by the resource having this property. - */ - public SupportedMethodSetProperty(String[] methods) { - super(DeltaVConstants.SUPPORTED_METHOD_SET, true); - this.methods = methods; - } - - public String[] getValue() { - return methods; - } - - /** - * @see org.apache.jackrabbit.webdav.xml.XmlSerializable#toXml(Document) - * @param document - */ - @Override - public Element toXml(Document document) { - Element elem = getName().toXml(document); - for (String method : methods) { - Element methodElem = DomUtil.addChildElement(elem, XML_SUPPORTED_METHOD, DeltaVConstants.NAMESPACE); - DomUtil.setAttribute(methodElem, "name", DeltaVConstants.NAMESPACE, method); - } - return elem; - } - -} Property changes on: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/SupportedMethodSetProperty.java ___________________________________________________________________ Deleted: svn Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/UpdateInfo.java =================================================================== --- jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/UpdateInfo.java (revision 1907912) +++ jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/UpdateInfo.java (nonexistent) @@ -1,243 +0,0 @@ -/* - * 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.webdav.version; - -import org.apache.jackrabbit.webdav.DavConstants; -import org.apache.jackrabbit.webdav.DavException; -import org.apache.jackrabbit.webdav.DavServletResponse; -import org.apache.jackrabbit.webdav.property.DavPropertyNameSet; -import org.apache.jackrabbit.webdav.xml.DomUtil; -import org.apache.jackrabbit.webdav.xml.ElementIterator; -import org.apache.jackrabbit.webdav.xml.XmlSerializable; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.w3c.dom.Document; -import org.w3c.dom.Element; - -import java.util.ArrayList; -import java.util.List; - -/** - * UpdateInfo encapsulates the request body of an UPDATE request. - * RFC 3253 defines the request body as follows: - *
- * <!ELEMENT update ANY>
- * ANY value: A sequence of elements with at most one DAV:label-name or
- * DAV:version element (but not both).
- * In addition at one DAV:prop element can be present.
- *
- * <!ELEMENT version (href)>
- * <!ELEMENT label-name (#PCDATA)> PCDATA value: string
- * prop: see RFC 2518, Section 12.11
- * 
- * - * In order to reflect the complete range of version restoring and updating - * of nodes defined by JSR170 the definition has been extended: - *
- * <!ELEMENT update ( (version | label-name | workspace ) , (prop)?, (removeExisting)? ) >
- * <!ELEMENT version (href+) >
- * <!ELEMENT label-name (#PCDATA) >
- * <!ELEMENT workspace (href) >
- * <!ELEMENT prop ANY >
- * <!ELEMENT removeExisting EMPTY >
- * 
- */ -public class UpdateInfo implements DeltaVConstants, XmlSerializable { - - private static Logger log = LoggerFactory.getLogger(UpdateInfo.class); - - public static final int UPDATE_BY_VERSION = 0; - public static final int UPDATE_BY_LABEL = 1; - public static final int UPDATE_BY_WORKSPACE = 2; - - private Element updateElement; - - private DavPropertyNameSet propertyNameSet = new DavPropertyNameSet(); - private String[] source; - private int type; - - public UpdateInfo(String[] updateSource, int updateType, DavPropertyNameSet propertyNameSet) { - if (updateSource == null || updateSource.length == 0) { - throw new IllegalArgumentException("Version href array must not be null and have a minimal length of 1."); - } - if (updateType < UPDATE_BY_VERSION || updateType > UPDATE_BY_WORKSPACE) { - throw new IllegalArgumentException("Illegal type of UpdateInfo."); - } - this.type = updateType; - this.source = (updateType == UPDATE_BY_VERSION) ? updateSource : new String[] {updateSource[0]}; - if (propertyNameSet != null) { - this.propertyNameSet = propertyNameSet; - } - } - - /** - * Create a new UpdateInfo object. - * - * @param updateElement - * @throws DavException if the updateElement is null - * or not a DAV:update element or if the element does not match the required - * structure. - */ - public UpdateInfo(Element updateElement) throws DavException { - if (!DomUtil.matches(updateElement, XML_UPDATE, NAMESPACE)) { - log.warn("DAV:update element expected"); - throw new DavException(DavServletResponse.SC_BAD_REQUEST); - } - - boolean done = false; - if (DomUtil.hasChildElement(updateElement, XML_VERSION, NAMESPACE)) { - Element vEl = DomUtil.getChildElement(updateElement, XML_VERSION, NAMESPACE); - ElementIterator hrefs = DomUtil.getChildren(vEl, DavConstants.XML_HREF, DavConstants.NAMESPACE); - List hrefList = new ArrayList(); - while (hrefs.hasNext()) { - hrefList.add(DomUtil.getText(hrefs.nextElement())); - } - source = hrefList.toArray(new String[hrefList.size()]); - type = UPDATE_BY_VERSION; - done = true; - } - - // alternatively 'DAV:label-name' elements may be present. - if (!done && DomUtil.hasChildElement(updateElement, XML_LABEL_NAME, NAMESPACE)) { - source = new String[] {DomUtil.getChildText(updateElement, XML_LABEL_NAME, NAMESPACE)}; - type = UPDATE_BY_LABEL; - done = true; - } - - // last possibility: a DAV:workspace element - if (!done) { - Element wspElem = DomUtil.getChildElement(updateElement, XML_WORKSPACE, NAMESPACE); - if (wspElem != null) { - source = new String[] {DomUtil.getChildTextTrim(wspElem, DavConstants.XML_HREF, DavConstants.NAMESPACE)}; - type = UPDATE_BY_WORKSPACE; - } else { - log.warn("DAV:update element must contain either DAV:version, DAV:label-name or DAV:workspace child element."); - throw new DavException(DavServletResponse.SC_BAD_REQUEST); - } - } - - // if property name set if present - if (DomUtil.hasChildElement(updateElement, DavConstants.XML_PROP, DavConstants.NAMESPACE)) { - Element propEl = DomUtil.getChildElement(updateElement, DavConstants.XML_PROP, DavConstants.NAMESPACE); - propertyNameSet = new DavPropertyNameSet(propEl); - updateElement.removeChild(propEl); - } else { - propertyNameSet = new DavPropertyNameSet(); - } - this.updateElement = updateElement; - } - - /** - * - * @return - */ - public String[] getVersionHref() { - return (type == UPDATE_BY_VERSION) ? source : null; - } - - /** - * - * @return - */ - public String[] getLabelName() { - return (type == UPDATE_BY_LABEL) ? source : null; - } - - /** - * - * @return - */ - public String getWorkspaceHref() { - return (type == UPDATE_BY_WORKSPACE) ? source[0] : null; - } - - /** - * Returns a {@link DavPropertyNameSet}. If the DAV:update element contains - * a DAV:prop child element the properties specified therein are included - * in the set. Otherwise an empty set is returned. - *

- * WARNING: modifying the DavPropertyNameSet returned by this method does - * not modify this UpdateInfo. - * - * @return set listing the properties specified in the DAV:prop element indicating - * those properties that must be reported in the response body. - */ - public DavPropertyNameSet getPropertyNameSet() { - return propertyNameSet; - } - - /** - * - * @return - */ - public Element getUpdateElement() { - return updateElement; - } - - /** - * @see org.apache.jackrabbit.webdav.xml.XmlSerializable#toXml(Document) - * @param document - */ - public Element toXml(Document document) { - Element elem; - if (updateElement != null) { - elem = (Element)document.importNode(updateElement, true); - } else { - elem = createUpdateElement(source, type, document); - } - if (!propertyNameSet.isEmpty()) { - elem.appendChild(propertyNameSet.toXml(document)); - } - return elem; - } - - /** - * Factory method to create the basic structure of an UpdateInfo - * object. - * - * @param updateSource - * @param updateType - * @param factory - * @return - */ - public static Element createUpdateElement(String[] updateSource, int updateType, Document factory) { - if (updateSource == null || updateSource.length == 0) { - throw new IllegalArgumentException("Update source must specific at least a single resource used to run the update."); - } - - Element elem = DomUtil.createElement(factory, XML_UPDATE, NAMESPACE); - switch (updateType) { - case UPDATE_BY_VERSION: - Element vE = DomUtil.addChildElement(elem, XML_VERSION, NAMESPACE); - for (String source : updateSource) { - vE.appendChild(DomUtil.hrefToXml(source, factory)); - } - break; - case UPDATE_BY_LABEL: - DomUtil.addChildElement(elem, XML_LABEL_NAME, NAMESPACE, updateSource[0]); - break; - case UPDATE_BY_WORKSPACE: - Element wspEl = DomUtil.addChildElement(elem, XML_WORKSPACE, NAMESPACE, updateSource[0]); - wspEl.appendChild(DomUtil.hrefToXml(updateSource[0], factory)); - break; - // no default. - default: - throw new IllegalArgumentException("Invalid update type: " + updateType); - } - return elem; - } -} Property changes on: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/UpdateInfo.java ___________________________________________________________________ Deleted: svn Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/VersionControlledResource.java =================================================================== --- jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/VersionControlledResource.java (revision 1907912) +++ jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/VersionControlledResource.java (nonexistent) @@ -1,363 +0,0 @@ -/* - * 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.webdav.version; - -import org.apache.jackrabbit.webdav.DavException; -import org.apache.jackrabbit.webdav.MultiStatus; -import org.apache.jackrabbit.webdav.property.DavPropertyName; - -/** - * The VersionControlledResource represents in contrast to the - * VersionableResource a resource, that has already been put - * under version-control. This resource can be checked-in, checked-out and - * has its own {@link VersionHistoryResource version history}. - *

- * RFC 3253 defines the following required properties for a - * version-controlled resource (vc-resource): - *

    - *
  • DAV:auto-version
  • - *
  • DAV:version-history (version-history)
  • - *
  • DAV:workspace (workspace)
  • - *
  • DAV:version-controlled-configuration (baseline)
  • - *
  • all DeltaV-compliant resource properties.
  • - *
- * - * checked-in vc-resource: - *
    - *
  • DAV:checked-in
  • - *
- * - * checked-out vc-resource: - *
    - *
  • DAV:checked-out
  • - *
  • DAV:predecessor-set
  • - *
  • DAV:checkout-fork (in-place-checkout or working resource)
  • - *
  • DAV:checkin-fork (in-place-checkout or working resource)
  • - *
  • DAV:merge-set (merge)
  • - *
  • DAV:auto-merge-set (merge)
  • - *
  • DAV:unreserved (activity)
  • - *
  • DAV:activity-set (activity)
  • - *
- * - * If the Version-Controlled-Collection feature is supported (see section 14 - * of RFC 3253) the following computed property is required: - *
    - *
  • DAV:eclipsed-set
  • - *
- * - * If the Baseline feature is supported (see section 12 of RFC 3253), a version- - * controlled resource may represent a 'configuration' rather than a single - * resource. In this case the RFC defines the following required properties: - *
    - *
  • DAV:baseline-controlled-collection
  • - *
  • DAV:subbaseline-set (if the configuration resource is checked-out)
  • - *
- * - *

- * In addition a version-controlled resource must support the following METHODS: - *

    - *
  • VERSION-CONTROL
  • - *
  • MERGE (merge)
  • - *
  • all DeltaV-compliant resource METHODS.
  • - *
- * - * checked-in vc-resource: - *
    - *
  • CHECKOUT (checkout-in-place)
  • - *
  • UPDATE (update)
  • - *
  • all version-controlled resource METHODS.
  • - *
- * - * checked-out vc-resource: - *
    - *
  • CHECKIN (checkout-in-place or working-resource)
  • - *
  • UNCHECKOUT (checkout-in-place)
  • - *
  • all DeltaV-compliant resource METHODS.
  • - *
- * - * @see DeltaVResource - * @see VersionableResource - */ -public interface VersionControlledResource extends VersionableResource { - - /** - * Methods defined for a checked-in version-controlled resource: CHECKOUT, UPDATE, MERGE, LABEL - */ - public String methods_checkedIn = "CHECKOUT, UPDATE, MERGE, LABEL"; - /** - * Methods defined for a checked-out version-controlled resource: CHECKIN, MERGE - */ - public String methods_checkedOut = "CHECKIN, MERGE"; - - /** - * The DAV:auto-version property determines how it responds to a method that - * attempts to modify its content or dead properties. Possible responses - * include various combinations of automated checkout, write lock and checkin - * as well as failure until the resource is explicitly checked-out.
- * See RFC 3253 for a detailed - * description. - */ - public static final DavPropertyName AUTO_VERSION = DavPropertyName.create("auto-version", DeltaVConstants.NAMESPACE); - - /** - * The computed property DAV:version-history identifies the version history - * resource for the DAV:checked-in or DAV:checked-out version of this - * version-controlled resource.
- * The property is defined to have the following format: - *
-     * <!ELEMENT version-history (href)>
-     * 
- */ - public static final DavPropertyName VERSION_HISTORY = DavPropertyName.create("version-history", DeltaVConstants.NAMESPACE); - - /** - * The DAV:checked-in property appears on a checked-in version-controlled - * resource, and identifies the base version of this version-controlled - * resource. This property is removed when the resource is checked out, and - * then added back (identifying a new version) when the resource is checked - * back in.
- * This property is defined to have the following format: - *
-     * <!ELEMENT checked-in (href)>
-     * 
- */ - public static final DavPropertyName CHECKED_IN = DavPropertyName.create("checked-in", DeltaVConstants.NAMESPACE); - - /** - * The DAV:checked-out property identifies the base version of this resource. - * It is the same that was identified by the DAV:checked-in property at the - * time the resource was checked out. This property is removed when the - * resource is checked in.
- * This property is defined to have the following format: - *
-     * <!ELEMENT checked-out (href)>
-     * 
- * - * @see #CHECKED_IN - */ - public static final DavPropertyName CHECKED_OUT = DavPropertyName.create("checked-out", DeltaVConstants.NAMESPACE); - - /** - * The DAV:predecessor-set property of a version-controlled resource points - * to those version resources, that are scheduled to become the predecessors - * of this resource when it is back checked-in. This property is not - * protected, however a server may reject attempts to modify the - * DAV:predecessor-set of a version-controlled resource.
- * This property is defined to have the following format: - *
-     * <!ELEMENT predecessor-set (href+)>
-     * 
- * - * @see #checkin() - * @see VersionResource#PREDECESSOR_SET - */ - public static final DavPropertyName PREDECESSOR_SET = DavPropertyName.create("predecessor-set", DeltaVConstants.NAMESPACE); - - /** - * This property determines the DAV:checkin-fork property of the version - * that results from checking in this resource. - */ - public static final DavPropertyName CHECKIN_FORK = DavPropertyName.create("checkin-fork", DeltaVConstants.NAMESPACE); - - /** - * This property determines the DAV:checkout-fork property of the version - * that results from checking in this resource. - */ - public static final DavPropertyName CHECKOUT_FORK = DavPropertyName.create("checkout-fork", DeltaVConstants.NAMESPACE); - - /** - * This property identifies each version that is to be merged into this - * checked-out resource. This property is set, whenever a MERGE request - * with the DAV:no-auto-merge flag succeeded. The client then must confirm - * each single merge by removing the version from the DAV:merge-set or - * moving it the the versions DAV:predecessor-set.
- * This property is defined to have the following format: - *
-     * <!ELEMENT merge-set (href*)>
-     * 
- * - * @see #merge(MergeInfo) - */ - public static final DavPropertyName MERGE_SET = DavPropertyName.create("merge-set", DeltaVConstants.NAMESPACE); - - /** - * The DAV:auto-merge-set property identifies each version that the server - * has merged into this checked-out resource. The client should confirm that - * the merge has been performed correctly before moving a URL from the - * DAV:auto-merge-set to the DAV:predecessor-set of a checked-out resource.
- * This property is defined to have the following format: - *
-     * <!ELEMENT auto-merge-set (href*)>
-     * 
- * - * @see #merge(MergeInfo) - */ - public static final DavPropertyName AUTO_MERGE_SET = DavPropertyName.create("auto-merge-set", DeltaVConstants.NAMESPACE); - - /** - * DAV:unreserved is a property for a checked-out resource, if the server - * supports the activity feature.
- * It indicates whether the DAV:activity-set of another checked-out resource - * associated with the version history of this version-controlled resource - * can have an activity that is in the DAV:activity-set property of this - * checked-out resource. - *
- * A result of the requirement that an activity must form a single line of - * descent through a given version history is that if multiple checked-out - * resources for a given version history are checked out unreserved into a - * single activity, only the first CHECKIN will succeed. Before another of - * these checked-out resources can be checked in, the user will first have - * to merge into that checked-out resource the latest version selected by - * that activity from that version history, and then modify the - * DAV:predecessor-set of that checked-out resource to identify that version. - *

- * This property is defined to have the following format: - *

-     * <!ELEMENT unreserved (#PCDATA)>
-     * PCDATA value: boolean
-     * 
- * @see VersionResource#ACTIVITY_SET - */ - public static final DavPropertyName UNRESERVED = DavPropertyName.create("activity-set", DeltaVConstants.NAMESPACE); - - /** - * DAV:activity-set is a property for a checked-out resource, if the - * server supports the activity feature.
- * This property determines the DAV:activity-set property of the version that - * results from checking in this resource. - * - * @see VersionResource#ACTIVITY_SET - */ - public static final DavPropertyName ACTIVITY_SET = DavPropertyName.create("activity-set", DeltaVConstants.NAMESPACE); - - /** - * If the 'Version-Controlled-Collection Feature' is supported the - * DAV:eclipsed-set property present on a collection identifies all - * internal members that are not version-controlled and hide a vc internal - * member with the same name. - *

- * This property is defined to have the following format: - *

-     * <!ELEMENT eclipsed-set (binding-name*)>
-     * <!ELEMENT binding-name (#PCDATA)>
-     * PCDATA value: URL segment
-     * 
- * - * @see VersionResource#VERSION_CONTROLLED_BINDING_SET - */ - public static final DavPropertyName ECLIPSED_SET = DavPropertyName.create("eclipsed-set", DeltaVConstants.NAMESPACE); - - /** - * If the 'Baseline' feature is supported, DAV:baseline-controlled-collection - * is a required property of any version-controlled resource, that represents - * a 'configuration'. It identifies the collection that contains the - * version-controlled resources whose versions are tracked by this - * configuration. - *

- * This property is defined to have the following format: - *

-     * <!ELEMENT baseline-controlled-collection (href)>
-     * 
- * Note that the DAV:baseline-controlled-collection represents a - * {@link org.apache.jackrabbit.webdav.property.HrefProperty HrefProperty} - * - * @see DeltaVConstants#VERSION_CONTROLLED_CONFIGURATION for the corresponding - * property, that is required for all resources that are contained in this - * version-controlled-configuration. - */ - public static final DavPropertyName BASELINE_CONTROLLED_COLLECTION = DavPropertyName.create("baseline-controlled-collection", DeltaVConstants.NAMESPACE); - - /** - * This property is mandatory for all checked-out version-controlled-configuration - * resources. It determines the DAV:subbaseline-set property of the baseline - * that results from checking in this resource. - *

- * This property is defined to have the following format: - *

-     * <!ELEMENT subbaseline-set (href*)>
-     * 
- * Note that the DAV:baseline-controlled-collection represents a - * {@link org.apache.jackrabbit.webdav.property.HrefProperty HrefProperty} - * @see BaselineResource#SUBBASELINE_SET - */ - public static final DavPropertyName SUBBASELINE_SET = DavPropertyName.create("subbaseline-set", DeltaVConstants.NAMESPACE); - - /** - * Perform a checkin on the version controlled resource. - * - * @return String representing the location of the version created by the - * checkin. - * @throws DavException if an error occurs. - */ - public String checkin() throws DavException; - - /** - * Perform a checkout on the version controlled resource. - * - * @throws DavException - */ - public void checkout() throws DavException; - - /** - * Perform an uncheckout on the version controlled resource. - * - * @throws DavException - */ - public void uncheckout() throws DavException; - - /** - * Perform an update on this resource using the specified {@link UpdateInfo}. - * - * @param updateInfo - * @return MultiStatus containing the list of resources that - * have been modified by this update call. - * @throws DavException - */ - public MultiStatus update(UpdateInfo updateInfo) throws DavException; - - /** - * Perform a merge on this resource using the specified {@link MergeInfo}. - * - * @param mergeInfo - * @return MultiStatus containing the list of resources that - * have been modified. - * @throws DavException - */ - public MultiStatus merge(MergeInfo mergeInfo) throws DavException; - - /** - * Modify the labels of the version referenced by the DAV:checked-in property - * of this checked-in version-controlled resource. If the resource is not - * checked-in the request must fail. - * - * @param labelInfo - * @throws org.apache.jackrabbit.webdav.DavException - * @see LabelInfo - * @see VersionResource#label(LabelInfo) for the pre- and postcondition of - * a successful LABEL request. - */ - public void label(LabelInfo labelInfo) throws DavException; - - /** - * Returns the VersionHistoryResource, that is referenced in the - * '{@link #VERSION_HISTORY version-history}' property. - * - * @return - * @throws DavException - */ - public VersionHistoryResource getVersionHistory() throws DavException; -} \ No newline at end of file Property changes on: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/VersionControlledResource.java ___________________________________________________________________ Deleted: svn Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/VersionHistoryResource.java =================================================================== --- jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/VersionHistoryResource.java (revision 1907912) +++ jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/VersionHistoryResource.java (nonexistent) @@ -1,73 +0,0 @@ -/* - * 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.webdav.version; - -import org.apache.jackrabbit.webdav.DavException; -import org.apache.jackrabbit.webdav.property.DavPropertyName; -import org.apache.jackrabbit.webdav.property.ResourceType; - -/** - * VersionHistoryResource represents a collection that has - * all versions of a given version-controlled resource as members. - *

- * RFC 3253 defines the following required properties for a version history: - *

    - *
  • DAV:version-set
  • - *
  • DAV:root-version
  • - *
  • all DeltaV-compliant resource properties.
  • - *
- *

- * In addition a version history resource must support the following METHODS: - *

    - *
  • all DeltaV-compliant resource METHODS.
  • - *
- * - * NOTE: the {@link org.apache.jackrabbit.webdav.DavConstants#PROPERTY_RESOURCETYPE DAV:resourcetype} - * property must indicate 'DAV:version-history'. - * - * @see DeltaVResource - * @see ResourceType#VERSION_HISTORY - */ -public interface VersionHistoryResource extends DeltaVResource { - - // supported METHODS: same as DeltaVResource > set to empty string - public static final String METHODS = ""; - - /** - * Computed (protected) property identifying the root version of this version - * history. - */ - public static final DavPropertyName ROOT_VERSION = DavPropertyName.create("root-version", DeltaVConstants.NAMESPACE); - - /** - * The protected property DAV:version-set identifies each version of this - * version history. - * - * @see #getVersions() - */ - public static final DavPropertyName VERSION_SET = DavPropertyName.create("version-set", DeltaVConstants.NAMESPACE); - - /** - * Returns an array of VersionResources containing all versions - * that are a member of this resource. - * - * @return all VersionResources that belong to this version history. - * @throws org.apache.jackrabbit.webdav.DavException - * @see #VERSION_SET - */ - public VersionResource[] getVersions() throws DavException; -} \ No newline at end of file Property changes on: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/VersionHistoryResource.java ___________________________________________________________________ Deleted: svn Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/VersionResource.java =================================================================== --- jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/VersionResource.java (revision 1907912) +++ jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/VersionResource.java (nonexistent) @@ -1,213 +0,0 @@ -/* - * 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.webdav.version; - -import org.apache.jackrabbit.webdav.DavException; -import org.apache.jackrabbit.webdav.property.DavPropertyName; - -/** - * VersionResource is a resource that contains a copy of a particular - * state of a version-controlled resource. A new version resource is created whenever - * a checked-out version-controlled resource is checked-in. The server allocates - * a distinct new URL for each new version, and this URL will never be used to - * identify any resource other than that version. The content and dead properties - * of a version never change. - *

- * RFC 3253 defines the following required properties for a version resource: - *

    - *
  • DAV:predecessor-set (protected)
  • - *
  • DAV:successor-set (computed)
  • - *
  • DAV:checkout-set
  • - *
  • DAV:version-name
  • - *
  • DAV:checkout-fork (in-place-checkout or working resource)
  • - *
  • DAV:checkin-fork (in-place-checkout or working resource)
  • - *
  • DAV:version-history (version-history)
  • - *
  • DAV:label-name-set (label)
  • - *
  • DAV:activity-set (activity)
  • - *
  • all DeltaV-compliant resource properties.
  • - *
- * - * If the 'Version-Controlled-Collection Feature' is supported (see section 14 - * of RFC 3253) the following protected property is defined for a version - * resource associated with a version-controlled collection. - *
    - *
  • DAV:version-controlled-binding-set
  • - *
- * - *

- * In addition a version resource must support the following METHODS: - *

    - *
  • LABEL (label)
  • - *
  • CHECKOUT (working-resource)
  • - *
  • all DeltaV-compliant resource METHODS.
  • - *
- * - * @see DeltaVResource - */ -public interface VersionResource extends DeltaVResource { - - /** - * The version resource defines one additional method LABEL. - * - * @see DeltaVResource#METHODS - * @see org.apache.jackrabbit.webdav.DavResource#METHODS - */ - public String METHODS = "LABEL"; - - /** - * Required protected property 'DAV:label-name-set' for a version of a webdav - * resource introduced with the 'LabelInfo' feature. - * This property contains the labels that currently select this version.
- * Property structure is defined as follows:
- *
-     * <!ELEMENT label-name-set (label-name*)>
-     * <!ELEMENT label-name (#PCDATA)>
-     * PCDATA value: string
-     * 
- */ - public static final DavPropertyName LABEL_NAME_SET = DavPropertyName.create("label-name-set", DeltaVConstants.NAMESPACE); - - /** - * The protected DAV:predecessor property identifies each predecessor of - * this version. Except for the root version, which has no predecessors, - * each version has at least one predecessor.
- * The property is defined to have the following format: - *
-     * <!ELEMENT predecessor-set (href*)>
-     * 
- */ - public static final DavPropertyName PREDECESSOR_SET = DavPropertyName.create("predecessor-set", DeltaVConstants.NAMESPACE); - - /** - * The computed property DAV:successor-set identifies each version whose - * DAV:predecessor-set identifies this version.
- * The property is defined to have the following format: - *
-     * <!ELEMENT successor-set (href*)>
-     * 
- * - */ - public static final DavPropertyName SUCCESSOR_SET = DavPropertyName.create("successor-set", DeltaVConstants.NAMESPACE); - - /** - * The computed property DAV:checkout-set identifies each checked-out - * resource whose DAV:checked-out property identifies this version.
- * The property is defined to have the following format: - *
-     * <!ELEMENT checkout-set (href*)>
-     * 
- * - * @see VersionControlledResource#CHECKED_OUT - */ - public static final DavPropertyName CHECKOUT_SET = DavPropertyName.create("checkout-set", DeltaVConstants.NAMESPACE); - - /** - * The protected property DAV:version-name defines a human readable id for - * this version. The id defined to be unique within the version-history this - * version belongs to.
- * The property is defined to have the following format: - *
-     * <!ELEMENT version-name (#PCDATA)>
-     * PCDATA value: string
-     * 
- */ - public static final DavPropertyName VERSION_NAME = DavPropertyName.create("version-name", DeltaVConstants.NAMESPACE); - - /** - * The computed property DAV:version-history identifies the version history - * that contains this version.
- * The property is defined to have the following format: - *
-     * <!ELEMENT version-history (href)>
-     * 
- */ - public static final DavPropertyName VERSION_HISTORY = DavPropertyName.create("version-history", DeltaVConstants.NAMESPACE); - - /** - * This property controls the behavior of CHECKOUT when a version already - * is checked out or has a successor. - */ - public static final DavPropertyName CHECKOUT_FORK = DavPropertyName.create("checkout-fork", DeltaVConstants.NAMESPACE); - - /** - * This property controls the behavior of CHECKIN when a version already - * has a successor. - */ - public static final DavPropertyName CHECKIN_FORK = DavPropertyName.create("checkin-fork", DeltaVConstants.NAMESPACE); - - /** - * DAV:activity-set is a required property for a version resource, if the - * server supports the activity feature.
- * It identifies the activities that determine to which logical changes this - * version contributes, and on which lines of descent this version appears. - * A server MAY restrict the DAV:activity-set to identify a single activity. - * A server MAY refuse to allow the value of the DAV:activity-set property - * of a version to be modified. - *

- * The property is defined to have the following format: - *

-     * <!ELEMENT activity-set (href*)>
-     * 
- * Note that the DAV:activity-set represents a - * {@link org.apache.jackrabbit.webdav.property.HrefProperty HrefProperty} - */ - public static final DavPropertyName ACTIVITY_SET = DavPropertyName.create("activity-set", DeltaVConstants.NAMESPACE); - - /** - * If the 'Version-Controlled-Collection Feature' is supported the - * DAV:version-controlled-binding-set property identifies the name and the - * version history of all version-controlled internal members of the - * collection this version resource belongs to. - *

- * This property is defined to have the following format: - *

-     * <!ELEMENT version-controlled-binding-set (version-controlled-binding*)>
-     * <!ELEMENT version-controlled-binding (binding-name, version-history)>
-     * <!ELEMENT binding-name (#PCDATA)>
-     * PCDATA value: URL segment
-     * <!ELEMENT version-history (href)>
-     * 
- * - * @see VersionControlledResource#ECLIPSED_SET - */ - public static final DavPropertyName VERSION_CONTROLLED_BINDING_SET = DavPropertyName.create("version-controlled-binding-set", DeltaVConstants.NAMESPACE); - - /** - * Modify the labels of this version resource. The modifications (SET, ADD or - * REMOVE) are listed in the specified LabelInfo object.
- * The case of a label name must be preserved when it is stored and retrieved. - *
If the type of modification is ADD, then the label must not yet occur on - * any other version within the same version history. In contrast a SET - * modification will move the indicated label to this version, if it existed - * with another version before. After a successful LABEL request the label - * must not appear with any other version in the same version history. - * - * @param labelInfo - * @throws org.apache.jackrabbit.webdav.DavException - * @see LabelInfo - */ - public void label(LabelInfo labelInfo) throws DavException; - - /** - * Returns the VersionHistoryResource, that is referenced in the - * {@link #VERSION_HISTORY DAV:version-history} property. - * - * @return - * @throws DavException - */ - public VersionHistoryResource getVersionHistory() throws DavException; -} \ No newline at end of file Property changes on: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/VersionResource.java ___________________________________________________________________ Deleted: svn Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/VersionableResource.java =================================================================== --- jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/VersionableResource.java (revision 1907912) +++ jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/VersionableResource.java (nonexistent) @@ -1,64 +0,0 @@ -/* - * 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.webdav.version; - -import org.apache.jackrabbit.webdav.DavException; - -/** - * VersionableResource represents an extension to the basic - * {@link DeltaVResource}, that allows to adding version-control support. By - * calling {@link #addVersionControl()} resource is put under version control, - * thus the versionable resource turns into a version controlled resource. - *

- * RFC 3253 defines the following required properties for a versionable resource: - *

    - *
  • {@link DeltaVConstants#WORKSPACE DAV:workspace} (workspace feature)
  • - *
  • DAV:version-controlled-configuration (baseline feature)
  • - *
  • all DeltaV-compliant resource properties
  • - *
- *

- * In addition a versionable resource must support the following METHODS: - *

    - *
  • VERSION-CONTROL
  • - *
  • all DeltaV-compliant resource METHODS.
  • - *
- * - * @see DeltaVResource - */ -public interface VersionableResource extends DeltaVResource { - - /** - * The versionable resource defines one additional method VERSION-CONTROL. - * - * @see DeltaVResource#METHODS - * @see org.apache.jackrabbit.webdav.DavResource#METHODS - */ - public String METHODS = "VERSION-CONTROL"; - - /** - * Converts this versionable resource into a version-controlled resource. If - * this resource is already version-controlled this resource is not affected. - * If however, this resource is not versionable an DavException - * (error code: {@link org.apache.jackrabbit.webdav.DavServletResponse#SC_METHOD_NOT_ALLOWED} - * is thrown. The same applies, if this resource is versionable but its - * current state does not allow to made it a version-controlled one or - * if any other error occurs. - * - * @throws org.apache.jackrabbit.webdav.DavException - */ - public void addVersionControl() throws DavException; -} \ No newline at end of file Property changes on: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/VersionableResource.java ___________________________________________________________________ Deleted: svn Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/WorkspaceResource.java =================================================================== --- jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/WorkspaceResource.java (revision 1907912) +++ jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/WorkspaceResource.java (nonexistent) @@ -1,94 +0,0 @@ -/* - * 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.webdav.version; - -import org.apache.jackrabbit.webdav.property.DavPropertyName; - -/** - * A workspace resource is a collection whose members are related - * version-controlled and non-version-controlled resources. - * - *

- * RFC 3253 defines the following required live properties for an Workspace - * resource. - *

    - *
  • all DeltaV-compliant resource properties
  • - *
  • {@link #WORKSPACE_CHECKOUT_SET DAV:workspace-checkout-set}
  • - *
  • {@link #BASELINE_CONTROLLED_COLLECTION_SET DAV:baseline-controlled-collection-set} (baseline)
  • - *
  • {@link #CURRENT_ACTIVITY_SET DAV:current-activity-set} (activity)
  • - *
- * Note, that RFC 3253 doesn't define a separate resource type for a workspace. - *

- * The workspace resource must support all methods defined for a DeltaV-compliant - * collection. Since no additional methods are required for a workspace this - * interface mainly acts as marker. - *

- * Please refer to RFC 3253 - * Section 6 for a complete description of this resource type. - */ -public interface WorkspaceResource extends DeltaVResource { - - /** - * The DAV:workspace-checkout-set property is the only required property - * which is additionally added to a workspace resource.
- * This computed property identifies each checked-out resource whose - * DAV:workspace property identifies this workspace. - *

- * Note that the DAV:workspace-checkout-set represents a - * {@link org.apache.jackrabbit.webdav.property.HrefProperty HrefProperty}. - */ - public static final DavPropertyName WORKSPACE_CHECKOUT_SET = DavPropertyName.create("workspace-checkout-set", DeltaVConstants.NAMESPACE); - - /** - * @deprecated Use {@link #CURRENT_ACTIVITY_SET} instead. - */ - public static final DavPropertyName CUURENT_ACTIVITY_SET = DavPropertyName.create("current-activity-set", DeltaVConstants.NAMESPACE); - - /** - * DAV:current-activity-set is a required property for a workspace resource, - * if the server supports the activity feature.
- * It identifies the activities that currently are being performed in this - * workspace. When a member of this workspace is checked out, if no activity - * is specified in the checkout request, the DAV:current-activity-set will - * be used. This allows an activity-unaware client to update a workspace in - * which activity tracking is required. The DAV:current-activity-set MAY be - * restricted to identify at most one activity. - *

- * The property is defined to have the following format: - *

-     * <!ELEMENT current-activity-set (href*)>
-     * 
- * Note that the DAV:current-activity-set represents a - * {@link org.apache.jackrabbit.webdav.property.HrefProperty HrefProperty} - */ - public static final DavPropertyName CURRENT_ACTIVITY_SET = DavPropertyName.create("current-activity-set", DeltaVConstants.NAMESPACE); - - /** - * The Baseline feature (section 12) defines the following computed property - * for a workspace resource: DAV:baseline-controlled-collection-set lists - * all collections of this workspace, that are under baseline control. This - * list may include the workspace itself. - *

- * The property is defined to have the following format: - *

-     * <!ELEMENT baseline-controlled-collection-set (href*)>
-     * 
- * Note that the DAV:baseline-controlled-collection-set represents a - * {@link org.apache.jackrabbit.webdav.property.HrefProperty HrefProperty} - */ - public static final DavPropertyName BASELINE_CONTROLLED_COLLECTION_SET = DavPropertyName.create("baseline-controlled-collection-set", DeltaVConstants.NAMESPACE); -} \ No newline at end of file Property changes on: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/WorkspaceResource.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Deleted: svn:keywords ## -1 +0,0 ## -author date id revision url \ No newline at end of property Index: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/package-info.java =================================================================== --- jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/package-info.java (revision 1907912) +++ jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/package-info.java (nonexistent) @@ -1,18 +0,0 @@ -/* - * 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. - */ -@org.osgi.annotation.versioning.Version("1.0.0") -package org.apache.jackrabbit.webdav.version; Property changes on: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/package-info.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/report/AbstractReport.java =================================================================== --- jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/report/AbstractReport.java (revision 1907912) +++ jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/report/AbstractReport.java (nonexistent) @@ -1,59 +0,0 @@ -/* - * 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.webdav.version.report; - -import org.apache.jackrabbit.webdav.WebdavRequest; -import org.apache.jackrabbit.webdav.WebdavRequestContext; -import org.apache.jackrabbit.webdav.server.WebdavRequestContextHolder; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * Abstract Report. - */ -public abstract class AbstractReport implements Report { - - private static Logger log = LoggerFactory.getLogger(AbstractReport.class); - - /** - * Normalize the resource {@code href}. For example, remove contextPath prefix if found. - * @param href resource href - * @return normalized resource {@code href} - */ - protected String normalizeResourceHref(final String href) { - if (href == null) { - return href; - } - - final WebdavRequestContext requestContext = WebdavRequestContextHolder.getContext(); - final WebdavRequest request = (requestContext != null) ? requestContext.getRequest() : null; - - if (request == null) { - log.error("WebdavRequest is unavailable in the current execution context."); - return href; - } - - final String contextPath = request.getContextPath(); - - if (!contextPath.isEmpty() && href.startsWith(contextPath)) { - return href.substring(contextPath.length()); - } - - return href; - } - -} \ No newline at end of file Property changes on: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/report/AbstractReport.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/report/CompareBaselineReport.java =================================================================== --- jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/report/CompareBaselineReport.java (revision 1907912) +++ jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/report/CompareBaselineReport.java (nonexistent) @@ -1,188 +0,0 @@ -/* - * 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.webdav.version.report; - -import java.util.ArrayList; -import java.util.List; - -import org.apache.jackrabbit.webdav.DavConstants; -import org.apache.jackrabbit.webdav.DavException; -import org.apache.jackrabbit.webdav.DavResource; -import org.apache.jackrabbit.webdav.DavResourceIterator; -import org.apache.jackrabbit.webdav.DavResourceLocator; -import org.apache.jackrabbit.webdav.DavServletResponse; -import org.apache.jackrabbit.webdav.property.HrefProperty; -import org.apache.jackrabbit.webdav.version.BaselineResource; -import org.apache.jackrabbit.webdav.version.DeltaVConstants; -import org.apache.jackrabbit.webdav.version.VersionControlledResource; -import org.apache.jackrabbit.webdav.version.VersionResource; -import org.apache.jackrabbit.webdav.xml.DomUtil; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.w3c.dom.Document; -import org.w3c.dom.Element; - -/** - * CompareBaselineReport... - */ -public class CompareBaselineReport extends AbstractReport { - - private static Logger log = LoggerFactory.getLogger(CompareBaselineReport.class); - - private static final String XML_COMPARE_BASELINE = "compare-baseline"; - private static final String XML_COMPARE_BASELINE_REPORT = "compare-baseline-report"; - private static final String XML_ADDED_VERSION = "added-version"; - private static final String XML_DELETED_VERSION = "deleted-version"; - private static final String XML_CHANGED_VERSION = "changed-version"; - - public static final ReportType COMPARE_BASELINE = ReportType.register(XML_COMPARE_BASELINE, DeltaVConstants.NAMESPACE, CompareBaselineReport.class); - - private BaselineResource requestBaseline; - private BaselineResource compareBaseline; - - /** - * Returns {@link #COMPARE_BASELINE}. - * - * @see Report#getType() - */ - public ReportType getType() { - return COMPARE_BASELINE; - } - - /** - * Always returns false. - * - * @return false - * @see Report#isMultiStatusReport() - */ - public boolean isMultiStatusReport() { - return false; - } - - /** - * - * @param resource - * @param info - * @throws DavException - * @see Report#init(DavResource, ReportInfo) - */ - public void init(DavResource resource, ReportInfo info) throws DavException { - // validate info - if (!getType().isRequestedReportType(info)) { - throw new DavException(DavServletResponse.SC_BAD_REQUEST, "DAV:compare-baseline element expected."); - } - - // make sure the report is applied to a version history resource - if (resource != null && (resource instanceof BaselineResource)) { - this.requestBaseline = (BaselineResource) resource; - } else { - throw new DavException(DavServletResponse.SC_BAD_REQUEST, "DAV:compare-baseline report can only be created for a baseline resource."); - } - - // make sure the DAV:href element inside the request body points to - // an baseline resource (precondition for this report). - String compareHref = normalizeResourceHref(DomUtil.getText(info.getContentElement(DavConstants.XML_HREF, DavConstants.NAMESPACE))); - DavResourceLocator locator = resource.getLocator(); - DavResourceLocator compareLocator = locator.getFactory().createResourceLocator(locator.getPrefix(), compareHref); - - DavResource compRes = resource.getFactory().createResource(compareLocator, resource.getSession()); - if (compRes instanceof BaselineResource) { - compareBaseline = (BaselineResource) compRes; - } else { - throw new DavException(DavServletResponse.SC_BAD_REQUEST, "DAV:latest-activity-version report: The DAV:href in the request body MUST identify an activity."); - } - - // TODO: eventually add check for 'same-baseline-history' (RFC: "A server MAY require that the baselines being compared be from the same baseline history.") - } - - /** - * @see org.apache.jackrabbit.webdav.xml.XmlSerializable#toXml(Document) - */ - public Element toXml(Document document) { - Element el = DomUtil.createElement(document, XML_COMPARE_BASELINE_REPORT, DeltaVConstants.NAMESPACE); - try { - // TODO: check if correct - List requestVs = new ArrayList(); - getVersions(requestBaseline.getBaselineCollection(), requestVs); - - List compareVs = new ArrayList(); - getVersions(compareBaseline.getBaselineCollection(), compareVs); - - for (VersionResource requestV : requestVs) { - if (!compareVs.remove(requestV)) { - // check if another version of the same vh is present (change) - VersionResource changedV = findChangedVersion(requestV, compareVs); - if (changedV != null) { - // found a 'changed-version' entry - Element cv = DomUtil.addChildElement(el, XML_CHANGED_VERSION, DeltaVConstants.NAMESPACE); - cv.appendChild(DomUtil.hrefToXml(requestV.getHref(), document)); - cv.appendChild(DomUtil.hrefToXml(changedV.getHref(), document)); - } else { - // no corresponding version => 'deleted-version' - Element cv = DomUtil.addChildElement(el, XML_DELETED_VERSION, DeltaVConstants.NAMESPACE); - cv.appendChild(DomUtil.hrefToXml(requestV.getHref(), document)); - } - - } // else: both baseline contain a vc-resource with the same checked-in version - } - - // all remaining versions from the 'compare-baseline' can be considered - // to be added-versions. - for (VersionResource addedV : compareVs) { - Element cv = DomUtil.addChildElement(el, XML_ADDED_VERSION, DeltaVConstants.NAMESPACE); - cv.appendChild(DomUtil.hrefToXml(addedV.getHref(), document)); - } - } catch (DavException e) { - log.error("Internal error while building report", e); - } - return el; - } - - private void getVersions(DavResource collection, List vList) throws DavException { - DavResourceIterator it = collection.getMembers(); - while (it.hasNext()) { - DavResource member = it.nextResource(); - if (member instanceof VersionControlledResource) { - String href = new HrefProperty(member.getProperty(VersionControlledResource.CHECKED_IN)).getHrefs().get(0); - DavResourceLocator locator = member.getLocator(); - DavResourceLocator vLocator = locator.getFactory().createResourceLocator(locator.getPrefix(), href); - - DavResource v = member.getFactory().createResource(vLocator, member.getSession()); - if (v instanceof VersionResource) { - vList.add((VersionResource) v); - } else { - log.error("Internal error: DAV:checked-in property must point to a VersionResource."); - } - } - if (member.isCollection()) { - getVersions(member, vList); - } - } - } - - private VersionResource findChangedVersion(VersionResource requestV, List compareVs) throws DavException { - VersionResource[] vs = requestV.getVersionHistory().getVersions(); - for (VersionResource v : vs) { - if (compareVs.remove(v)) { - // another version of the same versionhistory is present among - // the compare-baseline versions. - return v; - } - } - return null; - } -} Property changes on: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/report/CompareBaselineReport.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Deleted: svn:keywords ## -1 +0,0 ## -author date id revision url \ No newline at end of property Index: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/report/ExpandPropertyReport.java =================================================================== --- jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/report/ExpandPropertyReport.java (revision 1907912) +++ jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/report/ExpandPropertyReport.java (nonexistent) @@ -1,266 +0,0 @@ -/* - * 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.webdav.version.report; - -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; - -import org.apache.jackrabbit.webdav.DavException; -import org.apache.jackrabbit.webdav.DavResource; -import org.apache.jackrabbit.webdav.DavResourceIterator; -import org.apache.jackrabbit.webdav.DavServletResponse; -import org.apache.jackrabbit.webdav.MultiStatus; -import org.apache.jackrabbit.webdav.MultiStatusResponse; -import org.apache.jackrabbit.webdav.property.AbstractDavProperty; -import org.apache.jackrabbit.webdav.property.DavProperty; -import org.apache.jackrabbit.webdav.property.DavPropertyName; -import org.apache.jackrabbit.webdav.property.HrefProperty; -import org.apache.jackrabbit.webdav.version.DeltaVConstants; -import org.apache.jackrabbit.webdav.version.DeltaVResource; -import org.apache.jackrabbit.webdav.xml.DomUtil; -import org.apache.jackrabbit.webdav.xml.ElementIterator; -import org.apache.jackrabbit.webdav.xml.Namespace; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.w3c.dom.Document; -import org.w3c.dom.Element; - -/** - * ExpandPropertyReport encapsulates the DAV:expand-property report, - * that provides a mechanism for retrieving in one request the properties from - * the resources identified by those DAV:href elements. It should be supported by - * all resources that support the REPORT method. - *

- * RFC 3253 specifies the following required format for the request body: - *

- * <!ELEMENT expand-property (property*)>
- * <!ELEMENT property (property*)>
- * <!ATTLIST property name NMTOKEN #REQUIRED>
- * name value: a property element type
- * <!ATTLIST property namespace NMTOKEN "DAV:">
- * namespace value: an XML namespace
- * 
- * NOTE: any DAV:property elements defined in the request body, that does not - * represent {@link HrefProperty} is treated as in a common PROPFIND request. - * - * @see DeltaVConstants#XML_EXPAND_PROPERTY - * @see DeltaVConstants#XML_PROPERTY - */ -public class ExpandPropertyReport extends AbstractReport implements DeltaVConstants { - - private static Logger log = LoggerFactory.getLogger(ExpandPropertyReport.class); - - private DavResource resource; - private ReportInfo info; - private Iterator propertyElements; - - /** - * Returns {@link ReportType#EXPAND_PROPERTY}. - * - * @return - * @see Report#getType() - */ - public ReportType getType() { - return ReportType.EXPAND_PROPERTY; - } - - /** - * Always returns true. - * - * @return true - * @see org.apache.jackrabbit.webdav.version.report.Report#isMultiStatusReport() - */ - public boolean isMultiStatusReport() { - return true; - } - - /** - * @see Report#init(DavResource, ReportInfo) - */ - public void init(DavResource resource, ReportInfo info) throws DavException { - setResource(resource); - setInfo(info); - } - - /** - * Set the target resource. - * - * @param resource - * @throws DavException if the specified resource is null - */ - private void setResource(DavResource resource) throws DavException { - if (resource == null) { - throw new DavException(DavServletResponse.SC_BAD_REQUEST, "The resource specified must not be null."); - } - this.resource = resource; - } - - /** - * Set the ReportInfo. - * - * @param info - * @throws DavException if the given ReportInfo - * does not contain a DAV:expand-property element. - */ - private void setInfo(ReportInfo info) throws DavException { - if (info == null) { - throw new DavException(DavServletResponse.SC_BAD_REQUEST, "The report info specified must not be null."); - } - if (!getType().isRequestedReportType(info)) { - throw new DavException(DavServletResponse.SC_BAD_REQUEST, "DAV:expand-property element expected."); - } - this.info = info; - propertyElements = info.getContentElements(XML_PROPERTY, NAMESPACE).iterator(); - } - - /** - * Run the report - * - * @return Xml Document as defined by - * RFC 2518 - * @see org.apache.jackrabbit.webdav.xml.XmlSerializable#toXml(Document) - * @param document - */ - public Element toXml(Document document) { - return getMultiStatus().toXml(document); - } - - /** - * Retrieve the multistatus object that is returned in response to the - * expand-property report request. - * - * @return - * @throws NullPointerException if info and resource have not been set. - */ - private MultiStatus getMultiStatus() { - MultiStatus ms = new MultiStatus(); - addResponses(resource, info.getDepth(), ms); - return ms; - } - - /** - * Fills the specified MultiStatus object by generating a - * MultiStatusResponse for the given resource (and - * its member according to the depth value). - * - * @param res - * @param depth - * @param ms - * @see #getResponse(DavResource, Iterator) - */ - private void addResponses(DavResource res, int depth, MultiStatus ms) { - MultiStatusResponse response = getResponse(res, propertyElements); - ms.addResponse(response); - if (depth > 0 && res.isCollection()) { - DavResourceIterator it = res.getMembers(); - while (it.hasNext()) { - addResponses(it.nextResource(), depth-1, ms); - } - } - } - - /** - * Builds a MultiStatusResponse for the given resource respecting - * the properties specified. Any property that represents a {@link HrefProperty} - * is expanded: It's name equals the name of a valid {@link HrefProperty}. - * However the value of that given property (consisting of one or multiple DAV:href elements) - * is replaced by the Xml representation of a separate - * {@link MultiStatusResponse multistatus responses} for the - * resource referenced by the given DAV:href elements. The responses may - * themselves have properties, which are defined by the separate list. - * - * @param res - * @param propertyElements - * @return MultiStatusResponse for the given resource. - * @see ExpandProperty - */ - private MultiStatusResponse getResponse(DavResource res, Iterator propertyElements) { - MultiStatusResponse resp = new MultiStatusResponse(res.getHref(), null); - while (propertyElements.hasNext()) { - Element propertyElem = propertyElements.next(); - // retrieve the localName present in the "name" attribute - String nameAttr = propertyElem.getAttribute(ATTR_NAME); - if (nameAttr == null || "".equals(nameAttr)) { - // NOTE: this is not valid according to the DTD - continue; - } - // retrieve the namespace present in the "namespace" attribute - // NOTE: if this attribute is missing the DAV: namespace represents the default. - String namespaceAttr = propertyElem.getAttribute(ATTR_NAMESPACE); - Namespace namespace = (namespaceAttr != null) ? Namespace.getNamespace(namespaceAttr) : NAMESPACE; - - DavPropertyName propName = DavPropertyName.create(nameAttr, namespace); - DavProperty p = res.getProperty(propName); - if (p != null) { - if (p instanceof HrefProperty && res instanceof DeltaVResource) { - ElementIterator it = DomUtil.getChildren(propertyElem, XML_PROPERTY, NAMESPACE); - resp.add(new ExpandProperty((DeltaVResource)res, (HrefProperty)p, it)); - } else { - resp.add(p); - } - } else { - resp.add(propName, DavServletResponse.SC_NOT_FOUND); - } - } - return resp; - } - - //--------------------------------------------------------< inner class >--- - /** - * ExpandProperty extends DavProperty. It's name - * equals the name of a valid {@link HrefProperty}. However the value of - * that given property (consisting of one or multiple DAV:href elements) - * is replaced by the Xml representation of a separate - * {@link MultiStatusResponse multistatus responses} for the - * resource referenced to by the given DAV:href elements. The responses may - * themselves have properties, which are defined by the separate list. - */ - private class ExpandProperty extends AbstractDavProperty> { - - private List valueList = new ArrayList(); - - /** - * Create a new ExpandProperty. - * - * @param hrefProperty - * @param elementIter - */ - private ExpandProperty(DeltaVResource deltaVResource, HrefProperty hrefProperty, ElementIterator elementIter) { - super(hrefProperty.getName(), hrefProperty.isInvisibleInAllprop()); - try { - DavResource[] refResource = deltaVResource.getReferenceResources(hrefProperty.getName()); - for (DavResource res : refResource) { - MultiStatusResponse resp = getResponse(res, elementIter); - valueList.add(resp); - } - } catch (DavException e) { - // invalid references or unknown property - log.error(e.getMessage()); - } - } - - /** - * Returns a List of {@link MultiStatusResponse} objects. - * - * @return - */ - public List getValue() { - return valueList; - } - } -} Property changes on: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/report/ExpandPropertyReport.java ___________________________________________________________________ Deleted: svn Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/report/LatestActivityVersionReport.java =================================================================== --- jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/report/LatestActivityVersionReport.java (revision 1907912) +++ jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/report/LatestActivityVersionReport.java (nonexistent) @@ -1,151 +0,0 @@ -/* - * 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.webdav.version.report; - -import java.util.List; - -import org.apache.jackrabbit.webdav.DavConstants; -import org.apache.jackrabbit.webdav.DavException; -import org.apache.jackrabbit.webdav.DavResource; -import org.apache.jackrabbit.webdav.DavResourceLocator; -import org.apache.jackrabbit.webdav.DavServletResponse; -import org.apache.jackrabbit.webdav.property.HrefProperty; -import org.apache.jackrabbit.webdav.version.ActivityResource; -import org.apache.jackrabbit.webdav.version.DeltaVConstants; -import org.apache.jackrabbit.webdav.version.VersionHistoryResource; -import org.apache.jackrabbit.webdav.version.VersionResource; -import org.apache.jackrabbit.webdav.xml.DomUtil; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.w3c.dom.Document; -import org.w3c.dom.Element; - -/** - * LatestActivityVersionReport is applied to a version history to - * identify the latest version that is selected from that version history by a - * given activity. - */ -public class LatestActivityVersionReport extends AbstractReport { - - private static Logger log = LoggerFactory.getLogger(LatestActivityVersionReport.class); - - private static final String XML_LATEST_ACTIVITY_VERSION = "latest-activity-version"; - private static final String XML_LATEST_ACTIVITY_VERSION_REPORT = "latest-activity-version-report"; - - public static final ReportType LATEST_ACTIVITY_VERSION = ReportType.register(XML_LATEST_ACTIVITY_VERSION, DeltaVConstants.NAMESPACE, LatestActivityVersionReport.class); - - private VersionHistoryResource vhResource; - private DavResource activity; - - /** - * Returns {@link #LATEST_ACTIVITY_VERSION}. - * - * @see Report#getType() - */ - public ReportType getType() { - return LATEST_ACTIVITY_VERSION; - } - - /** - * Always returns false. - * - * @return false - * @see Report#isMultiStatusReport() - */ - public boolean isMultiStatusReport() { - return false; - } - - /** - * Check all the preconditions for this report. - * - * @throws DavException if a precondition is not met. - * @see Report#init(DavResource, ReportInfo) - */ - public void init(DavResource resource, ReportInfo info) throws DavException { - // validate info - if (!getType().isRequestedReportType(info)) { - throw new DavException(DavServletResponse.SC_BAD_REQUEST, "DAV:latest-activity-version element expected."); - } - - // make sure the report is applied to a vh-resource - if (resource != null && (resource instanceof VersionHistoryResource)) { - vhResource = (VersionHistoryResource) resource; - } else { - throw new DavException(DavServletResponse.SC_BAD_REQUEST, "DAV:latest-activity-version report can only be created for a version history resource."); - } - - // make sure the DAV:href element inside the request body points to - // an activity resource (precondition for this report). - String activityHref = normalizeResourceHref(DomUtil.getText(info.getContentElement(DavConstants.XML_HREF, DavConstants.NAMESPACE))); - DavResourceLocator vhLocator = resource.getLocator(); - DavResourceLocator activityLocator = vhLocator.getFactory().createResourceLocator(vhLocator.getPrefix(), activityHref); - - activity = resource.getFactory().createResource(activityLocator, resource.getSession()); - if (!(activity instanceof ActivityResource)) { - throw new DavException(DavServletResponse.SC_BAD_REQUEST, "DAV:latest-activity-version report: The DAV:href in the request body MUST identify an activity."); - } - } - - /** - * - * @see org.apache.jackrabbit.webdav.xml.XmlSerializable#toXml(Document) - */ - public Element toXml(Document document) { - String latestVersionHref = getLatestVersionHref(); - - Element el = DomUtil.createElement(document, XML_LATEST_ACTIVITY_VERSION_REPORT, DeltaVConstants.NAMESPACE); - el.appendChild(DomUtil.hrefToXml(latestVersionHref, document)); - return el; - } - - /** - * The latest-version-href MUST identify the version of the given - * version history that is a member of the DAV:activity-version-set of the - * given activity and has no descendant that is a member of the - * DAV:activity-version-set of that activity. - * - * @return href of the latest version or "" - */ - private String getLatestVersionHref() { - String latestVersionHref = ""; // not found (TODO: check if this valid according to the RFC) - try { - List versionHrefs = new HrefProperty(activity.getProperty(ActivityResource.ACTIVITY_VERSION_SET)).getHrefs(); - - for (VersionResource vr : vhResource.getVersions()) { - String href = vr.getHref(); - if (versionHrefs.contains(href)) { - if ("".equals(latestVersionHref)) { - // shortcut - latestVersionHref = href; - } else { - // if this vr is a descendant of the one already found, set latestVersion again - List predecessors = new HrefProperty(vr.getProperty(VersionResource.PREDECESSOR_SET)).getHrefs(); - if (predecessors.contains(latestVersionHref)) { - // version is a descendant of the vr identified by latestVersionHref - latestVersionHref = href; - } // else: version is predecessor -> nothing to do. - } - } - } - - } catch (DavException e) { - log.error("Unexpected error while retrieving href of latest version.", e); - } - return latestVersionHref; - } -} Property changes on: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/report/LatestActivityVersionReport.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Deleted: svn:keywords ## -1 +0,0 ## -author date id revision url \ No newline at end of property Index: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/report/LocateByHistoryReport.java =================================================================== --- jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/report/LocateByHistoryReport.java (revision 1907912) +++ jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/report/LocateByHistoryReport.java (nonexistent) @@ -1,175 +0,0 @@ -/* - * 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.webdav.version.report; - -import java.util.HashSet; -import java.util.Set; - -import org.apache.jackrabbit.webdav.DavConstants; -import org.apache.jackrabbit.webdav.DavException; -import org.apache.jackrabbit.webdav.DavResource; -import org.apache.jackrabbit.webdav.DavResourceIterator; -import org.apache.jackrabbit.webdav.DavServletResponse; -import org.apache.jackrabbit.webdav.MultiStatus; -import org.apache.jackrabbit.webdav.property.DavPropertyNameSet; -import org.apache.jackrabbit.webdav.version.DeltaVConstants; -import org.apache.jackrabbit.webdav.version.VersionControlledResource; -import org.apache.jackrabbit.webdav.version.VersionHistoryResource; -import org.apache.jackrabbit.webdav.xml.DomUtil; -import org.apache.jackrabbit.webdav.xml.ElementIterator; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.w3c.dom.Document; -import org.w3c.dom.Element; - -/** - * LocateByHistoryReport encapsulates the DAV:locate-by-hisotry - * report, that may be used to locate a version-controlled resource for that - * version history. The DAV:locate-by-history report can be applied to a collection - * to locate the collection member that is a version-controlled resource for a - * specified version history resource. - * - *
- * <!ELEMENT locate-by-history (version-history-set, prop)>
- * <!ELEMENT version-history-set (href+)>
- * 
- */ -public class LocateByHistoryReport extends AbstractReport implements DeltaVConstants { - - private static Logger log = LoggerFactory.getLogger(LocateByHistoryReport.class); - - private ReportInfo info; - private Set vhHrefSet = new HashSet(); - private DavResource resource; - - /** - * Returns {@link ReportType#LOCATE_BY_HISTORY}. - * - * @see Report#getType() - */ - public ReportType getType() { - return ReportType.LOCATE_BY_HISTORY; - } - - /** - * @see Report#init(DavResource, ReportInfo) - */ - public void init(DavResource resource, ReportInfo info) throws DavException { - if (resource == null || !(resource instanceof VersionControlledResource)) { - throw new DavException(DavServletResponse.SC_BAD_REQUEST, "DAV:version-tree report can only be created for version-controlled resources and version resources."); - } - this.resource = resource; - setInfo(info); - } - - /** - * Set the ReportInfo - * - * @param info - * @throws DavException if the given ReportInfo - * does not contain a DAV:version-tree element. - */ - private void setInfo(ReportInfo info) throws DavException { - if (info == null || !getType().isRequestedReportType(info)) { - throw new DavException(DavServletResponse.SC_BAD_REQUEST, "DAV:locate-by-history element expected."); - } - Element versionHistorySet = info.getContentElement(XML_VERSION_HISTORY_SET, NAMESPACE); - if (versionHistorySet == null) { - throw new DavException(DavServletResponse.SC_BAD_REQUEST, "The DAV:locate-by-history element must contain a DAV:version-history-set child."); - } - ElementIterator it = DomUtil.getChildren(versionHistorySet, DavConstants.XML_HREF, DavConstants.NAMESPACE); - while (it.hasNext()) { - String href = DomUtil.getText(it.nextElement()); - if (href != null) { - vhHrefSet.add(href); - } - } - this.info = info; - } - - /** - * Always returns true. - * - * @return true - * @see org.apache.jackrabbit.webdav.version.report.Report#isMultiStatusReport() - */ - public boolean isMultiStatusReport() { - return true; - } - - /** - * Run the report. - * - * @return Xml Document representing the report in the required - * format. - * @see org.apache.jackrabbit.webdav.xml.XmlSerializable#toXml(Document) - * @param document - */ - public Element toXml(Document document) { - return getMultiStatus().toXml(document); - } - - /** - * Retrieve the MultiStatus that is returned in response to a locate-by-history - * report request. - * - * @return - * @throws NullPointerException if info or resource is null. - */ - private MultiStatus getMultiStatus() { - MultiStatus ms = new MultiStatus(); - buildResponse(resource, info.getPropertyNameSet(), info.getDepth(), ms); - return ms; - } - - /** - * Fill the MultiStatus with the MultiStatusResponses - * generated for the specified resource and its members according to the - * depth value. - * - * @param res - * @param propNameSet - * @param depth - * @param ms - */ - private void buildResponse(DavResource res, DavPropertyNameSet propNameSet, - int depth, MultiStatus ms) { - // loop over members first, since this report only list members - DavResourceIterator it = res.getMembers(); - while (!vhHrefSet.isEmpty() && it.hasNext()) { - DavResource childRes = it.nextResource(); - if (childRes instanceof VersionControlledResource) { - try { - VersionHistoryResource vhr = ((VersionControlledResource)childRes).getVersionHistory(); - if (vhHrefSet.remove(vhr.getHref())) { - if (propNameSet.isEmpty()) { - ms.addResourceStatus(childRes, DavServletResponse.SC_OK, 0); - } else { - ms.addResourceProperties(childRes, propNameSet, 0); - } - } - } catch (DavException e) { - log.info(e.getMessage()); - } - } - // traverse subtree - if (depth > 0) { - buildResponse(it.nextResource(), propNameSet, depth-1, ms); - } - } - } -} Property changes on: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/report/LocateByHistoryReport.java ___________________________________________________________________ Deleted: svn Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/report/Report.java =================================================================== --- jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/report/Report.java (revision 1907912) +++ jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/report/Report.java (nonexistent) @@ -1,62 +0,0 @@ -/* - * 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.webdav.version.report; - -import org.apache.jackrabbit.webdav.DavException; -import org.apache.jackrabbit.webdav.DavResource; -import org.apache.jackrabbit.webdav.version.DeltaVResource; -import org.apache.jackrabbit.webdav.xml.XmlSerializable; - -/** - * The Report interface defines METHODS needed in order to respond - * to a REPORT request. The REPORT method is a required feature to all - * DeltaV resources. - * - * @see DeltaVResource#getReport(ReportInfo) - */ -public interface Report extends XmlSerializable { - - /** - * Returns the registered type of this report. - * - * @return the type of this report. - */ - public ReportType getType(); - - /** - * Returns true if this Report will send a MultiStatus - * response.
- * Please note that RFC 3253 that the the response must be a 207 Multi-Status, - * if a Depth request header is present. - * - * @return - */ - public boolean isMultiStatusReport(); - - /** - * Set the DeltaVResource for which this report was requested - * and the ReportInfo as specified by the REPORT request body, - * that defines the details for this report.
- * Please note that this methods should perform basic validation checks - * in order to prevent exceptional situations during the xml serialization. - * - * @param resource - * @param info - * @throws DavException - */ - public void init(DavResource resource, ReportInfo info) throws DavException; -} \ No newline at end of file Property changes on: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/report/Report.java ___________________________________________________________________ Deleted: svn Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/report/ReportInfo.java =================================================================== --- jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/report/ReportInfo.java (revision 1907912) +++ jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/report/ReportInfo.java (nonexistent) @@ -1,263 +0,0 @@ -/* - * 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.webdav.version.report; - -import org.apache.jackrabbit.webdav.DavConstants; -import org.apache.jackrabbit.webdav.DavException; -import org.apache.jackrabbit.webdav.DavServletResponse; -import org.apache.jackrabbit.webdav.property.DavPropertyNameSet; -import org.apache.jackrabbit.webdav.xml.DomUtil; -import org.apache.jackrabbit.webdav.xml.ElementIterator; -import org.apache.jackrabbit.webdav.xml.Namespace; -import org.apache.jackrabbit.webdav.xml.XmlSerializable; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.w3c.dom.Document; -import org.w3c.dom.Element; -import org.w3c.dom.Node; - -import java.util.ArrayList; -import java.util.List; - -/** - * The ReportInfo class encapsulates the body of a REPORT request. - * RFC 3253 the top Xml element - * being the name of the requested report. In addition a Depth header may - * be present (default value: {@link DavConstants#DEPTH_0}). - */ -public class ReportInfo implements XmlSerializable { - - private static Logger log = LoggerFactory.getLogger(ReportInfo.class); - - private final String typeLocalName; - private final Namespace typeNamespace; - private final int depth; - private final DavPropertyNameSet propertyNames; - private final List content = new ArrayList(); - - /** - * Create a new ReportInfo - * - * @param type - */ - public ReportInfo(ReportType type) { - this(type, DavConstants.DEPTH_0, null); - } - - /** - * Create a new ReportInfo - * - * @param type - * @param depth - */ - public ReportInfo(ReportType type, int depth) { - this(type, depth, null); - } - - /** - * Create a new ReportInfo - * - * @param type - * @param depth - * @param propertyNames - */ - public ReportInfo(ReportType type, int depth, DavPropertyNameSet propertyNames) { - this(type.getLocalName(), type.getNamespace(), depth, propertyNames); - } - - /** - * Create a new ReportInfo - * - * @param typeLocalName - * @param typeNamespace - */ - public ReportInfo(String typeLocalName, Namespace typeNamespace) { - this(typeLocalName, typeNamespace, DavConstants.DEPTH_0, null); - } - - /** - * Create a new ReportInfo - * - * @param typelocalName - * @param typeNamespace - * @param depth - * @param propertyNames - */ - public ReportInfo(String typelocalName, Namespace typeNamespace, int depth, DavPropertyNameSet propertyNames) { - this.typeLocalName = typelocalName; - this.typeNamespace = typeNamespace; - this.depth = depth; - if (propertyNames != null) { - this.propertyNames = new DavPropertyNameSet(propertyNames); - } else { - this.propertyNames = new DavPropertyNameSet(); - } - } - - /** - * Create a new ReportInfo object from the given Xml element. - * - * @param reportElement - * @param depth Depth value as retrieved from the {@link DavConstants#HEADER_DEPTH}. - * @throws DavException if the report element is null. - */ - public ReportInfo(Element reportElement, int depth) throws DavException { - if (reportElement == null) { - log.warn("Report request body must not be null."); - throw new DavException(DavServletResponse.SC_BAD_REQUEST); - } - - this.typeLocalName = reportElement.getLocalName(); - this.typeNamespace = DomUtil.getNamespace(reportElement); - this.depth = depth; - Element propElement = DomUtil.getChildElement(reportElement, DavConstants.XML_PROP, DavConstants.NAMESPACE); - if (propElement != null) { - propertyNames = new DavPropertyNameSet(propElement); - reportElement.removeChild(propElement); - } else { - propertyNames = new DavPropertyNameSet(); - } - - ElementIterator it = DomUtil.getChildren(reportElement); - while (it.hasNext()) { - Element el = it.nextElement(); - if (!DavConstants.XML_PROP.equals(el.getLocalName())) { - content.add(el); - } - } - } - - /** - * Returns the depth field. The request must be applied separately to the - * collection itself and to all members of the collection that satisfy the - * depth value. - * - * @return depth - */ - public int getDepth() { - return depth; - } - - /** - * Name of the report type that will be / has been requested. - * - * @return Name of the report type - */ - public String getReportName() { - return DomUtil.getExpandedName(typeLocalName, typeNamespace); - } - - /** - * Indicates whether this info contains an element with the given name/namespace. - * - * @param localName - * @param namespace - * @return true if an element with the given name/namespace is present in the - * body of the request info. - */ - public boolean containsContentElement(String localName, Namespace namespace) { - if (content.isEmpty()) { - return false; - } - for (Element elem : content) { - boolean sameNamespace = (namespace == null) ? elem.getNamespaceURI() == null : namespace.isSame(elem.getNamespaceURI()); - if (sameNamespace && elem.getLocalName().equals(localName)) { - return true; - } - } - return false; - } - - /** - * Retrieves the Xml element with the given name/namespace that is a child - * of this info. If no such child exists null is returned. If - * multiple elements with the same name exist, the first one is returned. - * - * @param localName - * @param namespace - * @return Xml element with the given name/namespace or null - */ - public Element getContentElement(String localName, Namespace namespace) { - List values = getContentElements(localName, namespace); - if (values.isEmpty()) { - return null; - } else { - return values.get(0); - } - } - - /** - * Returns a list containing all child Xml elements of this info that have - * the specified name/namespace. If this info contains no such element, - * an empty list is returned. - * - * @param localName - * @param namespace - * @return List contain all child elements with the given name/namespace - * or an empty list. - */ - public List getContentElements(String localName, Namespace namespace) { - List l = new ArrayList(); - for (Element elem : content) { - if (DomUtil.matches(elem, localName, namespace)) { - l.add(elem); - } - } - return l; - } - - /** - * Add the specified Xml element as child of this info. - * - * @param contentElement - */ - public void setContentElement(Element contentElement) { - content.add(contentElement); - } - - /** - * Returns a DavPropertyNameSet providing the property names present - * in an eventual {@link DavConstants#XML_PROP} child element. If no such - * child element is present an empty set is returned. - * - * @return {@link DavPropertyNameSet} providing the property names present - * in an eventual {@link DavConstants#XML_PROP DAV:prop} child element or an empty set. - */ - public DavPropertyNameSet getPropertyNameSet() { - return propertyNames; - } - - - /** - * @see org.apache.jackrabbit.webdav.xml.XmlSerializable#toXml(Document) - * @param document - */ - public Element toXml(Document document) { - Element reportElement = DomUtil.createElement(document, typeLocalName, typeNamespace); - if (!content.isEmpty()) { - for (Element contentEntry : content) { - Node n = document.importNode(contentEntry, true); - reportElement.appendChild(n); - } - } - if (!propertyNames.isEmpty()) { - reportElement.appendChild(propertyNames.toXml(document)); - } - return reportElement; - } - -} Property changes on: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/report/ReportInfo.java ___________________________________________________________________ Deleted: svn Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/report/ReportType.java =================================================================== --- jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/report/ReportType.java (revision 1907912) +++ jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/report/ReportType.java (nonexistent) @@ -1,190 +0,0 @@ -/* - * 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.webdav.version.report; - -import org.apache.jackrabbit.webdav.DavException; -import org.apache.jackrabbit.webdav.DavServletResponse; -import org.apache.jackrabbit.webdav.version.DeltaVConstants; -import org.apache.jackrabbit.webdav.version.DeltaVResource; -import org.apache.jackrabbit.webdav.xml.DomUtil; -import org.apache.jackrabbit.webdav.xml.Namespace; -import org.apache.jackrabbit.webdav.xml.XmlSerializable; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.w3c.dom.Document; -import org.w3c.dom.Element; - -import java.util.HashMap; - -/** - * ReportType... - */ -public class ReportType implements DeltaVConstants, XmlSerializable { - - private static Logger log = LoggerFactory.getLogger(ReportType.class); - - private static final HashMap types = new HashMap(); - - public static final ReportType VERSION_TREE = register(XML_VERSION_TREE, NAMESPACE, VersionTreeReport.class); - public static final ReportType EXPAND_PROPERTY = register(XML_EXPAND_PROPERTY, NAMESPACE, ExpandPropertyReport.class); - public static final ReportType LOCATE_BY_HISTORY = register(XML_LOCATE_BY_HISTORY, NAMESPACE, LocateByHistoryReport.class); - - private final String key; - private final String localName; - private final Namespace namespace; - private final Class reportClass; - - /** - * Private constructor - * - * @see ReportType#register(String, org.apache.jackrabbit.webdav.xml.Namespace, Class) - */ - private ReportType(String localName, Namespace namespace, String key, Class reportClass) { - this.localName = localName; - this.namespace = namespace; - this.key = key; - this.reportClass = reportClass; - } - - /** - * Creates a new {@link Report} with this type. - * - * @return - * @throws DavException - */ - public Report createReport(DeltaVResource resource, ReportInfo info) throws DavException { - try { - Report report = reportClass.newInstance(); - report.init(resource, info); - return report; - } catch (IllegalAccessException e) { - // should never occur - throw new DavException(DavServletResponse.SC_INTERNAL_SERVER_ERROR, "Failed to create new report (" + reportClass.getName() + ") from class: " + e.getMessage()); - } catch (InstantiationException e) { - // should never occur - throw new DavException(DavServletResponse.SC_INTERNAL_SERVER_ERROR, "Failed to create new report (" + reportClass.getName() + ") from class: " + e.getMessage()); - } - } - - /** - * Returns an Xml element representing this report type. It may be used to - * build the body for a REPORT request. - * - * @param document - * @return Xml representation - * @see XmlSerializable#toXml(org.w3c.dom.Document) - */ - public Element toXml(Document document) { - return DomUtil.createElement(document, localName, namespace); - } - - /** - * Returns true if this ReportType is requested by the given - * ReportInfo - * - * @param reqInfo - * @return - */ - public boolean isRequestedReportType(ReportInfo reqInfo) { - if (reqInfo != null) { - return getReportName().equals(reqInfo.getReportName()); - } - return false; - } - - /** - * Return the qualified name of this ReportType. - * - * @return qualified name - */ - public String getReportName() { - return key; - } - - /** - * - * @return - */ - public String getLocalName() { - return localName; - } - - /** - * - * @return - */ - public Namespace getNamespace() { - return namespace; - } - - /** - * Register the report type with the given name, namespace and class, that can - * run that report. - * - * @param localName - * @param namespace - * @param reportClass - * @return - * @throws IllegalArgumentException if either parameter is null or - * if the given class does not implement the {@link Report} interface or if - * it does not provide an empty constructor. - */ - public static ReportType register(String localName, Namespace namespace, Class reportClass) { - if (localName == null || namespace == null || reportClass == null) { - throw new IllegalArgumentException("A ReportType cannot be registered with a null name, namespace or report class"); - } - String key = DomUtil.getExpandedName(localName, namespace); - if (types.containsKey(key)) { - return types.get(key); - } else { - try { - Object report = reportClass.newInstance(); - if (!(report instanceof Report)) { - throw new IllegalArgumentException("Unable to register Report class: " + reportClass + " does not implement the Report interface."); - } - } catch (IllegalAccessException e) { - throw new IllegalArgumentException("Error while validating Report class: " + e.getMessage()); - } catch (InstantiationException e) { - throw new IllegalArgumentException("Error while validating Report class.: " + e.getMessage()); - } - - ReportType type = new ReportType(localName, namespace, key, reportClass); - types.put(key, type); - return type; - } - } - - /** - * Return the ReportType requested by the given report info object. - * - * @param reportInfo - * @return the requested ReportType - * @throws IllegalArgumentException if the reportInfo is null or - * if the requested report type has not been registered yet. - */ - public static ReportType getType(ReportInfo reportInfo) { - if (reportInfo == null) { - throw new IllegalArgumentException("ReportInfo must not be null."); - } - String key = reportInfo.getReportName(); - if (types.containsKey(key)) { - return types.get(key); - } else { - throw new IllegalArgumentException("The request report '"+key+"' has not been registered yet."); - } - } -} Property changes on: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/report/ReportType.java ___________________________________________________________________ Deleted: svn Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/report/SupportedReportSetProperty.java =================================================================== --- jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/report/SupportedReportSetProperty.java (revision 1907912) +++ jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/report/SupportedReportSetProperty.java (nonexistent) @@ -1,119 +0,0 @@ -/* - * 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.webdav.version.report; - -import org.apache.jackrabbit.webdav.property.AbstractDavProperty; -import org.apache.jackrabbit.webdav.version.DeltaVConstants; -import org.apache.jackrabbit.webdav.xml.DomUtil; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.w3c.dom.Document; -import org.w3c.dom.Element; - -import java.util.HashSet; -import java.util.Set; - -/** - * SupportedReportSetProperty represents the DAV:supported-report-set - * property defined by RFC 3253. It identifies the reports that are supported by - * the given resource. - *
- * <!ELEMENT supported-report-set (supported-report*)>
- * <!ELEMENT supported-report report>
- * <!ELEMENT report ANY>
- * ANY value: a report element type
- * 
- */ -public class SupportedReportSetProperty extends AbstractDavProperty> { - - private static Logger log = LoggerFactory.getLogger(SupportedReportSetProperty.class); - - private final Set reportTypes = new HashSet(); - - /** - * Create a new empty SupportedReportSetProperty. - */ - public SupportedReportSetProperty() { - super(DeltaVConstants.SUPPORTED_REPORT_SET, true); - } - - /** - * Create a new SupportedReportSetProperty property. - * - * @param reportTypes that are supported by the resource having this property. - */ - public SupportedReportSetProperty(ReportType[] reportTypes) { - super(DeltaVConstants.SUPPORTED_REPORT_SET, true); - for (ReportType reportType : reportTypes) { - addReportType(reportType); - } - } - - /** - * Add an additional report type to this property's value. - * - * @param reportType - */ - public void addReportType(ReportType reportType) { - reportTypes.add(reportType); - } - - /** - * Returns true if the report type indicated in the specified RequestInfo - * object is included in the supported reports. - * - * @param reqInfo - * @return true if the requested report is supported. - */ - public boolean isSupportedReport(ReportInfo reqInfo) { - for (ReportType reportType : reportTypes) { - if (reportType.isRequestedReportType(reqInfo)) { - return true; - } - } - return false; - } - - /** - * Returns a set of report types. - * - * @return set of {@link ReportType}. - * @see org.apache.jackrabbit.webdav.property.DavProperty#getValue() - */ - public Set getValue() { - return reportTypes; - } - - /** - * Returns the Xml representation of this property. - * - * @return Xml representation listing all supported reports - * @see org.apache.jackrabbit.webdav.xml.XmlSerializable#toXml(Document) - * @param document - */ - @Override - public Element toXml(Document document) { - Element elem = getName().toXml(document); - for (ReportType rt : reportTypes) { - Element sr = DomUtil.addChildElement(elem, DeltaVConstants.XML_SUPPORTED_REPORT, DeltaVConstants.NAMESPACE); - Element r = DomUtil.addChildElement(sr, DeltaVConstants.XML_REPORT, DeltaVConstants.NAMESPACE); - r.appendChild(rt.toXml(document)); - } - return elem; - } - -} Property changes on: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/report/SupportedReportSetProperty.java ___________________________________________________________________ Deleted: svn Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/report/VersionTreeReport.java =================================================================== --- jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/report/VersionTreeReport.java (revision 1907912) +++ jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/report/VersionTreeReport.java (nonexistent) @@ -1,187 +0,0 @@ -/* - * 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.webdav.version.report; - -import org.apache.jackrabbit.webdav.DavException; -import org.apache.jackrabbit.webdav.DavResource; -import org.apache.jackrabbit.webdav.DavResourceIterator; -import org.apache.jackrabbit.webdav.DavServletResponse; -import org.apache.jackrabbit.webdav.MultiStatus; -import org.apache.jackrabbit.webdav.property.DavPropertyNameSet; -import org.apache.jackrabbit.webdav.version.DeltaVConstants; -import org.apache.jackrabbit.webdav.version.VersionControlledResource; -import org.apache.jackrabbit.webdav.version.VersionResource; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.w3c.dom.Document; -import org.w3c.dom.Element; - -/** - * VersionTreeReport encapsulates the DAV:version-tree report. - * It describes the requested properties of all the versions in the version - * history of a version. The DAV:version-tree report must be supported by all - * version resources and all version-controlled resources. - */ -public class VersionTreeReport extends AbstractReport implements DeltaVConstants { - - private static Logger log = LoggerFactory.getLogger(VersionTreeReport.class); - - private ReportInfo info; - private DavResource resource; - - /** - * Returns {@link ReportType#VERSION_TREE} - * - * @return {@link ReportType#VERSION_TREE} - * @see Report#getType() - */ - public ReportType getType() { - return ReportType.VERSION_TREE; - } - - /** - * Always returns true. - * - * @return true - * @see org.apache.jackrabbit.webdav.version.report.Report#isMultiStatusReport() - */ - public boolean isMultiStatusReport() { - return true; - } - - /** - * Validates the specified resource and info objects. - * - * @param resource - * @param info - * @throws org.apache.jackrabbit.webdav.DavException - * @see Report#init(DavResource, ReportInfo) - */ - public void init(DavResource resource, ReportInfo info) throws DavException { - setResource(resource); - setInfo(info); - } - - /** - * Set the DeltaVResource used to register this report. - * - * @param resource - * @throws DavException if the given resource is neither - * {@link VersionControlledResource} nor {@link VersionResource}. - */ - private void setResource(DavResource resource) throws DavException { - if (resource != null && (resource instanceof VersionControlledResource || resource instanceof VersionResource)) { - this.resource = resource; - } else { - throw new DavException(DavServletResponse.SC_BAD_REQUEST, "DAV:version-tree report can only be created for version-controlled resources and version resources."); - } - } - - /** - * Set the ReportInfo as specified by the REPORT request body, - * that defines the details for this report. - * - * @param info - * @throws DavException if the given ReportInfo - * does not contain a DAV:version-tree element. - */ - private void setInfo(ReportInfo info) throws DavException { - if (!getType().isRequestedReportType(info)) { - throw new DavException(DavServletResponse.SC_BAD_REQUEST, "DAV:version-tree element expected."); - } - this.info = info; - } - - /** - * Runs the DAV:version-tree report. - * - * @return Xml Document representing the report in the required - * format. - * @see org.apache.jackrabbit.webdav.xml.XmlSerializable#toXml(Document) - * @param document - */ - public Element toXml(Document document) { - return getMultiStatus().toXml(document); - } - - /** - * Retrieve the MultiStatus that is returned in response to a locate-by-history - * report request. - * - * @return - * @throws NullPointerException if info or resource is null. - */ - private MultiStatus getMultiStatus() { - if (info == null || resource == null) { - throw new NullPointerException("Error while running DAV:version-tree report"); - } - - MultiStatus ms = new MultiStatus(); - buildResponse(resource, info.getPropertyNameSet(), info.getDepth(), ms); - return ms; - } - - /** - * - * @param res - * @param propNameSet - * @param depth - * @param ms - */ - private void buildResponse(DavResource res, DavPropertyNameSet propNameSet, - int depth, MultiStatus ms) { - try { - for (VersionResource version : getVersions(res)) { - if (propNameSet.isEmpty()) { - ms.addResourceStatus(version, DavServletResponse.SC_OK, 0); - } else { - ms.addResourceProperties(version, propNameSet, 0); - } - } - } catch (DavException e) { - log.error(e.toString()); - } - if (depth > 0 && res.isCollection()) { - DavResourceIterator it = res.getMembers(); - while (it.hasNext()) { - buildResponse(it.nextResource(), propNameSet, depth-1, ms); - } - } - } - - /** - * Retrieve all versions from the version history associated with the given - * resource. If the versions cannot be retrieved from the given resource - * an exception is thrown. - * - * @param res - * @return array of {@link VersionResource}s or an empty array if the versions - * could not be retrieved. - * @throws DavException if the version history could not be retrieved from - * the given resource or if an error occurs while accessing the versions - * from the version history resource. - */ - private static VersionResource[] getVersions(DavResource res) throws DavException { - VersionResource[] versions = new VersionResource[0]; - if (res instanceof VersionControlledResource) { - versions = ((VersionControlledResource)res).getVersionHistory().getVersions(); - } else if (res instanceof VersionResource) { - versions = ((VersionResource)res).getVersionHistory().getVersions(); - } - return versions; - } -} Property changes on: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/report/VersionTreeReport.java ___________________________________________________________________ Deleted: svn Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/report/package-info.java =================================================================== --- jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/report/package-info.java (revision 1907912) +++ jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/report/package-info.java (nonexistent) @@ -1,18 +0,0 @@ -/* - * 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. - */ -@org.osgi.annotation.versioning.Version("1.1.0") -package org.apache.jackrabbit.webdav.version.report; Property changes on: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/report/package-info.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/xml/DavDocumentBuilderFactory.java =================================================================== --- jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/xml/DavDocumentBuilderFactory.java (revision 1907912) +++ jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/xml/DavDocumentBuilderFactory.java (nonexistent) @@ -1,87 +0,0 @@ -/* - * 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.webdav.xml; - -import java.io.IOException; - -import javax.xml.XMLConstants; -import javax.xml.parsers.DocumentBuilder; -import javax.xml.parsers.DocumentBuilderFactory; -import javax.xml.parsers.ParserConfigurationException; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.xml.sax.EntityResolver; -import org.xml.sax.InputSource; -import org.xml.sax.helpers.DefaultHandler; - -/** - * Custom {@link DocumentBuilderFactory} extended for use in WebDAV. - */ -public class DavDocumentBuilderFactory { - - private static final Logger LOG = LoggerFactory.getLogger(DavDocumentBuilderFactory.class); - - private final DocumentBuilderFactory DEFAULT_FACTORY = createFactory(); - - private DocumentBuilderFactory BUILDER_FACTORY = DEFAULT_FACTORY; - - private DocumentBuilderFactory createFactory() { - DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); - factory.setNamespaceAware(true); - factory.setIgnoringComments(true); - factory.setIgnoringElementContentWhitespace(true); - factory.setCoalescing(true); - try { - factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true); - } catch (ParserConfigurationException e) { - LOG.warn("Secure XML processing is not supported", e); - } catch (AbstractMethodError e) { - LOG.warn("Secure XML processing is not supported", e); - } - return factory; - } - - public void setFactory(DocumentBuilderFactory documentBuilderFactory) { - LOG.debug("DocumentBuilderFactory changed to: " + documentBuilderFactory); - BUILDER_FACTORY = documentBuilderFactory != null ? documentBuilderFactory : DEFAULT_FACTORY; - } - - /** - * An entity resolver that does not allow external entity resolution. See - * RFC 4918, Section 20.6 - */ - private static final EntityResolver DEFAULT_ENTITY_RESOLVER = new EntityResolver() { - @Override - public InputSource resolveEntity(String publicId, String systemId) throws IOException { - LOG.debug("Resolution of external entities in XML payload not supported - publicId: " + publicId + ", systemId: " - + systemId); - throw new IOException("This parser does not support resolution of external entities (publicId: " + publicId - + ", systemId: " + systemId + ")"); - } - }; - - public DocumentBuilder newDocumentBuilder() throws ParserConfigurationException { - DocumentBuilder db = BUILDER_FACTORY.newDocumentBuilder(); - if (BUILDER_FACTORY == DEFAULT_FACTORY) { - // if this is the default factory: set the default entity resolver as well - db.setEntityResolver(DEFAULT_ENTITY_RESOLVER); - } - db.setErrorHandler(new DefaultHandler()); - return db; - } -} Property changes on: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/xml/DavDocumentBuilderFactory.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/xml/DomUtil.java =================================================================== --- jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/xml/DomUtil.java (revision 1907912) +++ jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/xml/DomUtil.java (nonexistent) @@ -1,839 +0,0 @@ -/* - * 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.webdav.xml; - -import org.apache.jackrabbit.webdav.DavConstants; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.w3c.dom.Attr; -import org.w3c.dom.CharacterData; -import org.w3c.dom.Document; -import org.w3c.dom.Element; -import org.w3c.dom.Node; -import org.w3c.dom.NodeList; -import org.w3c.dom.Text; -import org.w3c.dom.NamedNodeMap; -import org.xml.sax.SAXException; - -import javax.xml.namespace.QName; -import javax.xml.parsers.DocumentBuilder; -import javax.xml.parsers.DocumentBuilderFactory; -import javax.xml.parsers.ParserConfigurationException; -import javax.xml.transform.Transformer; -import javax.xml.transform.TransformerException; -import javax.xml.transform.TransformerFactory; -import javax.xml.transform.dom.DOMSource; -import javax.xml.transform.stream.StreamResult; - -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.io.Writer; -import java.util.ArrayList; -import java.util.List; - -/** - * DomUtil provides some common utility methods related to w3c-DOM. - */ -public class DomUtil { - - private static Logger log = LoggerFactory.getLogger(DomUtil.class); - - /** - * Constant for DavDocumentBuilderFactory which is used - * to create and parse DOM documents. - */ - private static final DavDocumentBuilderFactory BUILDER_FACTORY = new DavDocumentBuilderFactory(); - - /** - * Support the replacement of {@link #BUILDER_FACTORY}. This is useful - * for injecting a customized BuilderFactory, for example with one that - * uses a local catalog resolver. This is one technique for addressing - * this issue: - * http://www.w3.org/blog/systeam/2008/02/08/w3c_s_excessive_dtd_traffic - * - * @param documentBuilderFactory - */ - public static void setBuilderFactory( - DocumentBuilderFactory documentBuilderFactory) { - BUILDER_FACTORY.setFactory(documentBuilderFactory); - } - - /** - * Transformer factory - */ - private static TransformerFactory TRANSFORMER_FACTORY = TransformerFactory.newInstance(); - - /** - * Creates and returns a new empty DOM document. - * - * @return new DOM document - * @throws ParserConfigurationException if the document can not be created - */ - public static Document createDocument() - throws ParserConfigurationException { - return BUILDER_FACTORY.newDocumentBuilder().newDocument(); - } - - /** - * Parses the given input stream and returns the resulting DOM document. - * - * @param stream XML input stream - * @return parsed DOM document - * @throws ParserConfigurationException if the document can not be created - * @throws SAXException if the document can not be parsed - * @throws IOException if the input stream can not be read - */ - public static Document parseDocument(InputStream stream) - throws ParserConfigurationException, SAXException, IOException { - DocumentBuilder docBuilder = BUILDER_FACTORY.newDocumentBuilder(); - return docBuilder.parse(stream); - } - - /** - * Returns the value of the named attribute of the current element. - * - * @param parent - * @param localName attribute local name or 'nodeName' if no namespace is - * specified. - * @param namespace or null - * @return attribute value, or null if not found - */ - public static String getAttribute(Element parent, String localName, Namespace namespace) { - if (parent == null) { - return null; - } - Attr attribute; - if (namespace == null) { - attribute = parent.getAttributeNode(localName); - } else { - attribute = parent.getAttributeNodeNS(namespace.getURI(), localName); - } - if (attribute != null) { - return attribute.getValue(); - } else { - return null; - } - } - - /** - * Returns the namespace attributes of the given element. - * - * @param element - * @return the namespace attributes. - */ - public static Attr[] getNamespaceAttributes(Element element) { - NamedNodeMap attributes = element.getAttributes(); - List nsAttr = new ArrayList(); - for (int i = 0; i < attributes.getLength(); i++) { - Attr attr = (Attr) attributes.item(i); - if (Namespace.XMLNS_NAMESPACE.getURI().equals(attr.getNamespaceURI())) { - nsAttr.add(attr); - } - } - return nsAttr.toArray(new Attr[nsAttr.size()]); - } - - /** - * Concatenates the values of all child nodes of type 'Text' or 'CDATA'/ - * - * @param element - * @return String representing the value of all Text and CDATA child nodes or - * null if the length of the resulting String is 0. - * @see #isText(Node) - */ - public static String getText(Element element) { - StringBuffer content = new StringBuffer(); - if (element != null) { - NodeList nodes = element.getChildNodes(); - for (int i = 0; i < nodes.getLength(); i++) { - Node child = nodes.item(i); - if (isText(child)) { - // cast to super class that contains Text and CData - content.append(((CharacterData) child).getData()); - } - } - } - return (content.length()==0) ? null : content.toString(); - } - - /** - * Same as {@link #getText(Element)} except that 'defaultValue' is returned - * instead of null, if the element does not contain any text. - * - * @param element - * @param defaultValue - * @return the text contained in the specified element or - * defaultValue if the element does not contain any text. - */ - public static String getText(Element element, String defaultValue) { - String txt = getText(element); - return (txt == null) ? defaultValue : txt; - } - - /** - * Removes leading and trailing whitespace after calling {@link #getText(Element)}. - * - * @param element - * @return Trimmed text or null - */ - public static String getTextTrim(Element element) { - String txt = getText(element); - return (txt == null) ? txt : txt.trim(); - } - - /** - * Calls {@link #getText(Element)} on the first child element that matches - * the given local name and namespace. - * - * @param parent - * @param childLocalName - * @param childNamespace - * @return text contained in the first child that matches the given local name - * and namespace or null. - * @see #getText(Element) - */ - public static String getChildText(Element parent, String childLocalName, Namespace childNamespace) { - Element child = getChildElement(parent, childLocalName, childNamespace); - return (child == null) ? null : getText(child); - } - - /** - * Calls {@link #getTextTrim(Element)} on the first child element that matches - * the given local name and namespace. - * - * @param parent - * @param childLocalName - * @param childNamespace - * @return text contained in the first child that matches the given local name - * and namespace or null. Note, that leading and trailing whitespace - * is removed from the text. - * @see #getTextTrim(Element) - */ - public static String getChildTextTrim(Element parent, String childLocalName, Namespace childNamespace) { - Element child = getChildElement(parent, childLocalName, childNamespace); - return (child == null) ? null : getTextTrim(child); - } - - /** - * Calls {@link #getTextTrim(Element)} on the first child element that matches - * the given name. - * - * @param parent - * @param childName - * @return text contained in the first child that matches the given name - * or null. Note, that leading and trailing whitespace - * is removed from the text. - * @see #getTextTrim(Element) - */ - public static String getChildTextTrim(Element parent, QName childName) { - Element child = getChildElement(parent, childName); - return (child == null) ? null : getTextTrim(child); - } - - /** - * Returns true if the given parent node has a child element that matches - * the specified local name and namespace. - * - * @param parent - * @param childLocalName - * @param childNamespace - * @return returns true if a child element exists that matches the specified - * local name and namespace. - */ - public static boolean hasChildElement(Node parent, String childLocalName, Namespace childNamespace) { - return getChildElement(parent, childLocalName, childNamespace) != null; - } - - /** - * Returns the first child element that matches the given local name and - * namespace. If no child element is present or no child element matches, - * null is returned. - * - * @param parent - * @param childLocalName - * @param childNamespace - * @return first child element matching the specified names or null. - */ - public static Element getChildElement(Node parent, String childLocalName, Namespace childNamespace) { - if (parent != null) { - NodeList children = parent.getChildNodes(); - for (int i = 0; i < children.getLength(); i++) { - Node child = children.item(i); - if (isElement(child) && matches(child, childLocalName, childNamespace)) { - return (Element)child; - } - } - } - return null; - } - - /** - * Returns the first child element that matches the given {@link QName}. - * If no child element is present or no child element matches, - * null is returned. - * - * @param parent - * @param childName - * @return first child element matching the specified name or null. - */ - public static Element getChildElement(Node parent, QName childName) { - if (parent != null) { - NodeList children = parent.getChildNodes(); - for (int i = 0; i < children.getLength(); i++) { - Node child = children.item(i); - if (isElement(child) && matches(child, childName)) { - return (Element)child; - } - } - } - return null; - } - - /** - * Returns a ElementIterator containing all child elements of - * the given parent node that match the given local name and namespace. - * If the namespace is null only the localName is compared. - * - * @param parent the node the children elements should be retrieved from - * @param childLocalName - * @param childNamespace - * @return an ElementIterator giving access to all child elements - * that match the specified localName and namespace. - */ - public static ElementIterator getChildren(Element parent, String childLocalName, Namespace childNamespace) { - return new ElementIterator(parent, childLocalName, childNamespace); - } - - /** - * Returns a ElementIterator containing all child elements of - * the given parent node that match the given {@link QName}. - * - * @param parent - * the node the children elements should be retrieved from - * @param childName - * @return an ElementIterator giving access to all child - * elements that match the specified name. - */ - public static ElementIterator getChildren(Element parent, QName childName) { - return new ElementIterator(parent, childName); - } - - /** - * Return an ElementIterator over all child elements. - * - * @param parent - * @return - * @see #getChildren(Element, String, Namespace) for a method that only - * retrieves child elements that match a specific local name and namespace. - */ - public static ElementIterator getChildren(Element parent) { - return new ElementIterator(parent); - } - - /** - * Return the first child element - * - * @return the first child element or null if the given node has no - * child elements. - */ - public static Element getFirstChildElement(Node parent) { - if (parent != null) { - NodeList children = parent.getChildNodes(); - for (int i = 0; i < children.getLength(); i++) { - Node child = children.item(i); - if (isElement(child)) { - return (Element)child; - } - } - } - return null; - } - - /** - * Return true if the given parent contains any child that is - * either an Element, Text or CDATA. - * - * @param parent - * @return true if the given parent contains any child that is - * either an Element, Text or CDATA. - */ - public static boolean hasContent(Node parent) { - if (parent != null) { - NodeList children = parent.getChildNodes(); - for (int i = 0; i < children.getLength(); i++) { - Node child = children.item(i); - if (isAcceptedNode(child)) { - return true; - } - } - } - return false; - } - - /** - * Return a list of all child nodes that are either Element, Text or CDATA. - * - * @param parent - * @return a list of all child nodes that are either Element, Text or CDATA. - */ - public static List getContent(Node parent) { - List content = new ArrayList(); - if (parent != null) { - NodeList children = parent.getChildNodes(); - for (int i = 0; i < children.getLength(); i++) { - Node child = children.item(i); - if (isAcceptedNode(child)) { - content.add(child); - } - } - } - return content; - } - - /** - * Build a Namespace from the prefix and uri retrieved from the given element. - * - * @return the Namespace of the given element. - */ - public static Namespace getNamespace(Element element) { - String uri = element.getNamespaceURI(); - String prefix = element.getPrefix(); - if (uri == null) { - return Namespace.EMPTY_NAMESPACE; - } else { - return Namespace.getNamespace(prefix, uri); - } - } - - /** - * Returns true if the specified node matches the required names. Note, that - * that tests return true if the required name is null. - * - * @param node - * @param requiredLocalName - * @param requiredNamespace - * @return true if local name and namespace match the corresponding properties - * of the given DOM node. - */ - public static boolean matches(Node node, String requiredLocalName, Namespace requiredNamespace) { - if (node == null) { - return false; - } - boolean matchingNamespace = matchingNamespace(node, requiredNamespace); - return matchingNamespace && matchingLocalName(node, requiredLocalName); - } - - /** - * Returns true if the specified node matches the required {@link QName}. - * - * @param node - * @param requiredName - * @return true if local name and namespace match the corresponding properties - * of the given DOM node. - */ - public static boolean matches(Node node, QName requiredName) { - if (node == null) { - return false; - } else { - String nodens = node.getNamespaceURI() != null ? node.getNamespaceURI() : ""; - return nodens.equals(requiredName.getNamespaceURI()) - && node.getLocalName().equals(requiredName.getLocalPart()); - } - } - - /** - * @param node - * @param requiredNamespace - * @return true if the required namespace is null or matches - * the namespace of the specified node. - */ - private static boolean matchingNamespace(Node node, Namespace requiredNamespace) { - if (requiredNamespace == null) { - return true; - } else { - return requiredNamespace.isSame(node.getNamespaceURI()); - } - } - - /** - * @param node - * @param requiredLocalName - * @return true if the required local name is null or if the - * nodes local name matches. - */ - private static boolean matchingLocalName(Node node, String requiredLocalName) { - if (requiredLocalName == null) { - return true; - } else { - String localName = node.getLocalName(); - return requiredLocalName.equals(localName); - } - } - - /** - * @param node - * @return true if the specified node is either an element or Text or CDATA - */ - private static boolean isAcceptedNode(Node node) { - return isElement(node) || isText(node); - } - - /** - * @param node - * @return true if the given node is of type element. - */ - static boolean isElement(Node node) { - return node.getNodeType() == Node.ELEMENT_NODE; - } - - /** - * @param node - * @return true if the given node is of type text or CDATA. - */ - static boolean isText(Node node) { - int ntype = node.getNodeType(); - return ntype == Node.TEXT_NODE || ntype == Node.CDATA_SECTION_NODE; - } - - //----------------------------------------------------< factory methods >--- - /** - * Create a new DOM element with the specified local name and namespace. - * - * @param factory - * @param localName - * @param namespace - * @return a new DOM element - * @see Document#createElement(String) - * @see Document#createElementNS(String, String) - */ - public static Element createElement(Document factory, String localName, Namespace namespace) { - if (namespace != null) { - return factory.createElementNS(namespace.getURI(), getPrefixedName(localName, namespace)); - } else { - return factory.createElement(localName); - } - } - - /** - * Create a new DOM element with the specified local name and namespace. - * - * @param factory - * @param elementName - * @return a new DOM element - * @see Document#createElement(String) - * @see Document#createElementNS(String, String) - */ - public static Element createElement(Document factory, QName elementName) { - return factory.createElementNS(elementName.getNamespaceURI(), getPrefixedName(elementName)); - } - - /** - * Create a new DOM element with the specified local name and namespace and - * add the specified text as Text node to it. - * - * @param factory - * @param localName - * @param namespace - * @param text - * @return a new DOM element - * @see Document#createElement(String) - * @see Document#createElementNS(String, String) - * @see Document#createTextNode(String) - * @see Node#appendChild(org.w3c.dom.Node) - */ - public static Element createElement(Document factory, String localName, Namespace namespace, String text) { - Element elem = createElement(factory, localName, namespace); - setText(elem, text); - return elem; - } - - /** - * Add a new child element with the given local name and namespace to the - * specified parent. - * - * @param parent - * @param localName - * @param namespace - * @return the new element that was attached to the given parent. - */ - public static Element addChildElement(Element parent, String localName, Namespace namespace) { - Element elem = createElement(parent.getOwnerDocument(), localName, namespace); - parent.appendChild(elem); - return elem; - } - - /** - * Add a new child element with the given local name and namespace to the - * specified parent. - * - * @param parent - * @param localName - * @param namespace - * @return the new element that was attached to the given parent. - */ - public static Element addChildElement(Node parent, String localName, Namespace namespace) { - Document doc = parent.getOwnerDocument(); - if (parent instanceof Document) { - doc = (Document) parent; - } - Element elem = createElement(doc, localName, namespace); - parent.appendChild(elem); - return elem; - } - - /** - * Add a new child element with the given local name and namespace to the - * specified parent. The specified text is added as Text node to the created - * child element. - * - * @param parent - * @param localName - * @param namespace - * @param text - * @return child element that was added to the specified parent - * @see Document#createElement(String) - * @see Document#createElementNS(String, String) - * @see Document#createTextNode(String) - * @see Node#appendChild(org.w3c.dom.Node) - */ - public static Element addChildElement(Element parent, String localName, Namespace namespace, String text) { - Element elem = createElement(parent.getOwnerDocument(), localName, namespace, text); - parent.appendChild(elem); - return elem; - } - - /** - * Create a new text node and add it as child to the given element. - * - * @param element - * @param text - */ - public static void setText(Element element, String text) { - if (text == null || "".equals(text)) { - // ignore null/empty string text - return; - } - Text txt = element.getOwnerDocument().createTextNode(text); - element.appendChild(txt); - } - - /** - * Add an attribute node to the given element. - * - * @param element - * @param attrLocalName - * @param attrNamespace - * @param attrValue - */ - public static void setAttribute(Element element, String attrLocalName, Namespace attrNamespace, String attrValue) { - if (attrNamespace == null) { - Attr attr = element.getOwnerDocument().createAttribute(attrLocalName); - attr.setValue(attrValue); - element.setAttributeNode(attr); - } else { - Attr attr = element.getOwnerDocument().createAttributeNS(attrNamespace.getURI(), getPrefixedName(attrLocalName, attrNamespace)); - attr.setValue(attrValue); - element.setAttributeNodeNS(attr); - } - } - - /** - * Adds a namespace attribute on the given element. - * - * @param element - * @param prefix - * @param uri - */ - public static void setNamespaceAttribute(Element element, String prefix, String uri) { - if (Namespace.EMPTY_NAMESPACE.equals(Namespace.getNamespace(prefix, uri))) { - /** - * don't try to set the empty namespace which will fail - * see {@link org.w3c.dom.DOMException#NAMESPACE_ERR} - * TODO: correct? - */ - log.debug("Empty namespace -> omit attribute setting."); - return; - } - setAttribute(element, prefix, Namespace.XMLNS_NAMESPACE, uri); - } - - /** - * Converts the given timeout (long value defining the number of milli- - * second until timeout is reached) to its Xml representation as defined - * by RFC 4918.
- * - * @param timeout number of milli-seconds until timeout is reached. - * @return 'timeout' Xml element - */ - public static Element timeoutToXml(long timeout, Document factory) { - boolean infinite = timeout / 1000 > Integer.MAX_VALUE || timeout == DavConstants.INFINITE_TIMEOUT; - String expString = infinite ? DavConstants.TIMEOUT_INFINITE : "Second-" + timeout / 1000; - return createElement(factory, DavConstants.XML_TIMEOUT, DavConstants.NAMESPACE, expString); - } - - /** - * Returns the Xml representation of a boolean isDeep, where false - * presents a depth value of '0', true a depth value of 'infinity'. - * - * @param isDeep - * @return Xml representation - */ - public static Element depthToXml(boolean isDeep, Document factory) { - return depthToXml(isDeep? "infinity" : "0", factory); - } - - /** - * Returns the Xml representation of a depth String. Webdav defines the - * following valid values for depths: 0, 1, infinity - * - * @param depth - * @return 'deep' XML element - */ - public static Element depthToXml(String depth, Document factory) { - return createElement(factory, DavConstants.XML_DEPTH, DavConstants.NAMESPACE, depth); - } - - /** - * Builds a 'DAV:href' Xml element from the given href. - *

- * Note that the path present needs to be a valid URI or URI reference. - * - * @param href String representing the text of the 'href' Xml element - * @param factory the Document used as factory - * @return Xml representation of a 'href' according to RFC 2518. - */ - public static Element hrefToXml(String href, Document factory) { - return createElement(factory, DavConstants.XML_HREF, DavConstants.NAMESPACE, href); - } - - /** - * Same as {@link #getExpandedName(String, Namespace)}. - * - * @param localName - * @param namespace - * @return the expanded name of a DOM node consisting of "{" + namespace uri + "}" - * + localName. If the specified namespace is null or represents - * the empty namespace, the local name is returned. - * @deprecated As of 2.0. Please use {@link #getExpandedName(String, Namespace)} - * instead. This method was named according to usage of 'qualified name' in - * JSR 170 that conflicts with the terminology used in XMLNS. As of JCR 2.0 - * the String consisting of "{" + namespace uri + "}" + localName - * is called Expanded Name. - * - */ - public static String getQualifiedName(String localName, Namespace namespace) { - return getExpandedName(localName, namespace); - } - - /** - * Returns a string representation of the name of a DOM node consisting - * of "{" + namespace uri + "}" + localName. If the specified namespace is - * null or represents the empty namespace, the local name is - * returned. - * - * @param localName - * @param namespace - * @return String representation of the name of a DOM node consisting of "{" + namespace uri + "}" - * + localName. If the specified namespace is null or represents - * the empty namespace, the local name is returned. - * @since 2.0 Replaces the deprecated method {@link #getQualifiedName(String, Namespace)}. - */ - public static String getExpandedName(String localName, Namespace namespace) { - if (namespace == null || namespace.equals(Namespace.EMPTY_NAMESPACE)) { - return localName; - } - StringBuffer b = new StringBuffer("{"); - b.append(namespace.getURI()).append("}"); - b.append(localName); - return b.toString(); - } - - /** - * Return the qualified name of a DOM node consisting of - * namespace prefix + ":" + local name. If the specified namespace is null - * or contains an empty prefix, the local name is returned.
- * NOTE, that this is the value to be used for the 'qualified Name' parameter - * expected with the namespace sensitive factory methods. - * - * @param localName - * @param namespace - * @return qualified name consisting of prefix, ':' and local name. - * @see Document#createAttributeNS(String, String) - * @see Document#createElementNS(String, String) - */ - public static String getPrefixedName(String localName, Namespace namespace) { - return getPrefixName(namespace.getURI(), namespace.getPrefix(), localName); - } - - /** - * Return the qualified name of a DOM node consisting of - * namespace prefix + ":" + local name. If the specified namespace is null - * or contains an empty prefix, the local name is returned.
- * NOTE, that this is the value to be used for the 'qualified Name' parameter - * expected with the namespace sensitive factory methods. - * - * @param name - * @return qualified name consisting of prefix, ':' and local name. - * @see Document#createAttributeNS(String, String) - * @see Document#createElementNS(String, String) - */ - public static String getPrefixedName(QName name) { - return getPrefixName(name.getNamespaceURI(), name.getPrefix(), name.getLocalPart()); - } - - private static String getPrefixName(String namespaceURI, String prefix, String localName) { - if (namespaceURI == null || prefix == null || "".equals(namespaceURI) || "".equals(prefix)) { - return localName; - } else { - StringBuffer buf = new StringBuffer(prefix); - buf.append(":"); - buf.append(localName); - return buf.toString(); - } - } - - /** - * Uses a new Transformer instance to transform the specified xml document - * to the specified writer output target. - * - * @param xmlDoc XML document to create the transformation - * Source for. - * @param writer The writer used to create a new transformation - * Result for. - * @throws TransformerException - */ - public static void transformDocument(Document xmlDoc, Writer writer) throws TransformerException, SAXException { - Transformer transformer = TRANSFORMER_FACTORY.newTransformer(); - transformer.transform(new DOMSource(xmlDoc), ResultHelper.getResult(new StreamResult(writer))); - } - - /** - * Uses a new Transformer instance to transform the specified xml document - * to the specified writer output target. - * - * @param xmlDoc XML document to create the transformation - * Source for. - * @param out The stream used to create a new transformation - * Result for. - * @throws TransformerException - */ - public static void transformDocument(Document xmlDoc, OutputStream out) throws TransformerException, SAXException { - Transformer transformer = TRANSFORMER_FACTORY.newTransformer(); - transformer.transform(new DOMSource(xmlDoc), ResultHelper.getResult(new StreamResult(out))); - } -} Property changes on: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/xml/DomUtil.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Deleted: svn:keywords ## -1 +0,0 ## -author date id revision url \ No newline at end of property Index: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/xml/ElementIterator.java =================================================================== --- jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/xml/ElementIterator.java (revision 1907912) +++ jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/xml/ElementIterator.java (nonexistent) @@ -1,170 +0,0 @@ -/* - * 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.webdav.xml; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.w3c.dom.Element; -import org.w3c.dom.Node; -import org.w3c.dom.NodeList; - -import java.util.Iterator; -import java.util.NoSuchElementException; - -import javax.xml.namespace.QName; - -/** - * ElementIterator... - */ -public class ElementIterator implements Iterator { - - private static Logger log = LoggerFactory.getLogger(ElementIterator.class); - - private final Namespace namespace; - private final String localName; - private final QName qName; - - private Element next; - - /** - * Create a new instance of ElementIterator with the given - * parent element. Only child elements that match the given local name - * and namespace will be respected by {@link #hasNext()} and {@link #nextElement()}. - * - * @param parent - * @param localName local name the child elements must match - * @param namespace namespace the child elements must match - */ - public ElementIterator(Element parent, String localName, Namespace namespace) { - this.localName = localName; - this.namespace = namespace; - this.qName = null; - seek(parent); - } - - /** - * Create a new instance of ElementIterator with the given - * parent element. Only child elements that match the given {@link QName} - * will be respected by {@link #hasNext()} and {@link #nextElement()}. - * - * @param parent - * @param qname name to match (exactly) - */ - public ElementIterator(Element parent, QName qname) { - this.localName = null; - this.namespace = null; - this.qName = qname; - seek(parent); - } - - /** - * Create a new instance of ElementIterator with the given - * parent element. No filtering is applied to child elements that are - * iterated. - * - * @param parent - */ - public ElementIterator(Element parent) { - this(parent, null, null); - } - - /** - * Not implemented - * - * @throws UnsupportedOperationException - */ - public void remove() { - throw new UnsupportedOperationException("Remove not implemented."); - } - - /** - * Returns true if there is a next Element - * - * @return true if a next Element is available. - */ - public boolean hasNext() { - return next != null; - } - - /** - * @see java.util.Iterator#next() - * @see #nextElement() - */ - public Element next() { - return nextElement(); - } - - /** - * Returns the next Element in the iterator. - * - * @return the next element - * @throws NoSuchElementException if there is no next element. - */ - public Element nextElement() { - if (next==null) { - throw new NoSuchElementException(); - } - Element ret = next; - seek(); - return ret; - } - - /** - * Seeks for the first matching child element - */ - private void seek(Element parent) { - NodeList nodeList = parent.getChildNodes(); - for (int i = 0; i < nodeList.getLength(); i++) { - Node n = nodeList.item(i); - if (matchesName(n)) { - next = (Element)n; - return; - } - } - } - - /** - * Seeks for the next valid element (i.e. the next valid sibling) - */ - private void seek() { - Node n = next.getNextSibling(); - while (n != null) { - if (matchesName(n)) { - next = (Element)n; - return; - } else { - n = n.getNextSibling(); - } - } - // no next element found -> set to null in order to leave the loop. - next = null; - } - - /** - * Matches the node name according to either {@link #qName} or the pair - * of {@link #localName) and {@link #namespace}. - */ - private boolean matchesName(Node n) { - if (!DomUtil.isElement(n)) { - return false; - } else if (qName != null) { - return DomUtil.matches(n, qName); - } else { - return DomUtil.matches(n, localName, namespace); - } - } -} Property changes on: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/xml/ElementIterator.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Deleted: svn:keywords ## -1 +0,0 ## -author date id revision url \ No newline at end of property Index: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/xml/Namespace.java =================================================================== --- jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/xml/Namespace.java (revision 1907912) +++ jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/xml/Namespace.java (nonexistent) @@ -1,97 +0,0 @@ -/* - * 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.webdav.xml; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * Namespace - */ -public class Namespace { - - private static Logger log = LoggerFactory.getLogger(Namespace.class); - - public static final Namespace EMPTY_NAMESPACE = new Namespace("",""); - public static final Namespace XML_NAMESPACE = new Namespace("xml", "http://www.w3.org/XML/1998/namespace"); - public static final Namespace XMLNS_NAMESPACE = new Namespace("xmlns", "http://www.w3.org/2000/xmlns/"); - - private final String prefix; - private final String uri; - - private Namespace(String prefix, String uri) { - this.prefix = prefix; - this.uri = uri; - } - - //-----------------------------------------------------------< creation >--- - - public static Namespace getNamespace(String prefix, String uri) { - if (prefix == null) { - prefix = EMPTY_NAMESPACE.getPrefix(); - } - if (uri == null) { - uri = EMPTY_NAMESPACE.getURI(); - } - return new Namespace(prefix, uri); - } - - public static Namespace getNamespace(String uri) { - return getNamespace("", uri); - } - - //-------------------------------------------------------------------------- - - public String getPrefix() { - return prefix; - } - - public String getURI() { - return uri; - } - - /** - * Returns true if the a Namespace built from the - * specified namespaceURI is equal to this namespace object. - * - * @param namespaceURI A namespace URI to be compared to this namespace instance. - * @return true if the a Namespace built from the - * specified namespaceURI is equal to this namespace object; - * false otherwise. - */ - public boolean isSame(String namespaceURI) { - Namespace other = getNamespace(namespaceURI); - return this.equals(other); - } - - //-------------------------------------------------------------< Object >--- - @Override - public int hashCode() { - return uri.hashCode(); - } - - @Override - public boolean equals(Object obj) { - if (obj == this) { - return true; - } - if (obj instanceof Namespace) { - return uri.equals(((Namespace)obj).uri); - } - return false; - } -} \ No newline at end of file Property changes on: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/xml/Namespace.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Deleted: svn:keywords ## -1 +0,0 ## -author date id revision url \ No newline at end of property Index: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/xml/ResultHelper.java =================================================================== --- jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/xml/ResultHelper.java (revision 1907912) +++ jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/xml/ResultHelper.java (nonexistent) @@ -1,458 +0,0 @@ -/* - * 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.webdav.xml; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.xml.sax.Attributes; -import org.xml.sax.ContentHandler; -import org.xml.sax.Locator; -import org.xml.sax.SAXException; -import org.xml.sax.helpers.AttributesImpl; -import org.xml.sax.helpers.DefaultHandler; - -import javax.xml.transform.OutputKeys; -import javax.xml.transform.Result; -import javax.xml.transform.Transformer; -import javax.xml.transform.TransformerConfigurationException; -import javax.xml.transform.TransformerFactory; -import javax.xml.transform.sax.SAXResult; -import javax.xml.transform.sax.SAXTransformerFactory; -import javax.xml.transform.sax.TransformerHandler; -import javax.xml.transform.stream.StreamResult; -import java.io.StringWriter; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; - -/** - * ResultHelper is a utility to assert proper namespace handling - * due to misbehavior of certain implementations with respect to xmlns attributes. - * The code is copied and slightly modified from jcr-commons - * SerializingContentHandler - * - * @see JCR-2897. - */ -public final class ResultHelper { - - /** - * logger instance - */ - private static final Logger log = LoggerFactory.getLogger(ResultHelper.class); - - /** The URI for xml namespaces */ - private static final String XML = "http://www.w3.org/XML/1998/namespace"; - - /** - * The factory used to create serializing SAX transformers. - */ - private static final SAXTransformerFactory FACTORY = - // Note that the cast from below is strictly speaking only valid when - // the factory instance supports the SAXTransformerFactory.FEATURE - // feature. But since this class would be useless without this feature, - // it's no problem to fail with a ClassCastException here and prevent - // this class from even being loaded. AFAIK all common JAXP - // implementations do support this feature. - (SAXTransformerFactory) TransformerFactory.newInstance(); - - /** - * Flag that indicates whether we need to work around the issue of - * the serializer not automatically generating the required xmlns - * attributes for the namespaces used in the document. - */ - private static final boolean NEEDS_XMLNS_ATTRIBUTES = - needsXmlnsAttributes(); - - /** - * Probes the available XML serializer for xmlns support. Used to set - * the value of the {@link #NEEDS_XMLNS_ATTRIBUTES} flag. - * - * @return whether the XML serializer needs explicit xmlns attributes - */ - private static boolean needsXmlnsAttributes() { - try { - StringWriter writer = new StringWriter(); - TransformerHandler probe = FACTORY.newTransformerHandler(); - probe.setResult(new StreamResult(writer)); - probe.startDocument(); - probe.startPrefixMapping("p", "uri"); - probe.startElement("uri", "e", "p:e", new AttributesImpl()); - probe.endElement("uri", "e", "p:e"); - probe.endPrefixMapping("p"); - probe.endDocument(); - return writer.toString().indexOf("xmlns") == -1; - } catch (Exception e) { - throw new UnsupportedOperationException("XML serialization fails"); - } - } - - /** - * In case the underlying XML library doesn't properly handle xmlns attributes - * this method creates new content handler dealing with the misbehavior and - * returns an new instance of SAXResult. Otherwise the passed result - * is returned back. - * - * @param result - * @return A instance of Result that properly handles xmlns attributes. - * @throws SAXException - */ - public static Result getResult(Result result) throws SAXException { - try { - TransformerHandler handler = FACTORY.newTransformerHandler(); - handler.setResult(result); - - // Specify the output properties to avoid surprises especially in - // character encoding or the output method (might be html for some - // documents!) - Transformer transformer = handler.getTransformer(); - transformer.setOutputProperty(OutputKeys.METHOD, "xml"); - transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8"); - transformer.setOutputProperty(OutputKeys.INDENT, "no"); - - if (NEEDS_XMLNS_ATTRIBUTES) { - // The serializer does not output xmlns declarations, - // so we need to do it explicitly with this wrapper - return new SAXResult(new SerializingContentHandler(handler)); - } else { - return result; - } - } catch (TransformerConfigurationException e) { - throw new SAXException("Failed to initialize XML serializer", e); - } - } - - /** - * private constructor to avoid instantiation - */ - private ResultHelper() { - } - - /** - * Special content handler fixing issues with xmlns attraibutes handling. - */ - private static final class SerializingContentHandler extends DefaultHandler { - /** - * The prefixes of startPrefixMapping() declarations for the coming element. - */ - private List prefixList = new ArrayList(); - - /** - * The URIs of startPrefixMapping() declarations for the coming element. - */ - private List uriList = new ArrayList(); - - /** - * Maps of URI<->prefix mappings. Used to work around a bug in the Xalan - * serializer. - */ - private Map uriToPrefixMap = new HashMap(); - private Map prefixToUriMap = new HashMap(); - - /** - * True if there has been some startPrefixMapping() for the coming element. - */ - private boolean hasMappings = false; - - /** - * Stack of the prefixes of explicitly generated prefix mapping calls - * per each element level. An entry is appended at the beginning of each - * {@link #startElement(String, String, String, org.xml.sax.Attributes)} call and - * removed at the end of each {@link #endElement(String, String, String)} - * call. By default the entry for each element is null to - * avoid losing performance, but whenever the code detects a new prefix - * mapping that needs to be registered, the null entry is - * replaced with a list of explicitly registered prefixes for that node. - * When that element is closed, the listed prefixes get unmapped. - * - * @see #checkPrefixMapping(String, String) - * @see JCR-1767 - */ - private final List addedPrefixMappings = new ArrayList(); - - /** - * The adapted content handler instance. - */ - private final ContentHandler handler; - - private SerializingContentHandler(ContentHandler handler) { - this.handler = handler; - } - - @Override - public void characters(char[] ch, int start, int length) throws SAXException { - handler.characters(ch, start, length); - } - - @Override - public void startDocument() throws SAXException { - // Cleanup - this.uriToPrefixMap.clear(); - this.prefixToUriMap.clear(); - clearMappings(); - - handler.startDocument(); - } - - /** - * Track mappings to be able to add xmlns: attributes - * in startElement(). - */ - @Override - public void startPrefixMapping(String prefix, String uri) throws SAXException { - // Store the mappings to reconstitute xmlns:attributes - // except prefixes starting with "xml": these are reserved - // VG: (uri != null) fixes NPE in startElement - if (uri != null && !prefix.startsWith("xml")) { - this.hasMappings = true; - this.prefixList.add(prefix); - this.uriList.add(uri); - - // append the prefix colon now, in order to save concatenations later, but - // only for non-empty prefixes. - if (prefix.length() > 0) { - this.uriToPrefixMap.put(uri, prefix + ":"); - } else { - this.uriToPrefixMap.put(uri, prefix); - } - - this.prefixToUriMap.put(prefix, uri); - } - - handler.startPrefixMapping(prefix, uri); - } - - /** - * Checks whether a prefix mapping already exists for the given namespace - * and generates the required {@link #startPrefixMapping(String, String)} - * call if the mapping is not found. By default the registered prefix - * is taken from the given qualified name, but a different prefix is - * automatically selected if that prefix is already used. - * - * @see JCR-1767 - * @param uri namespace URI - * @param qname element name with the prefix, or null - * @throws SAXException if the prefix mapping can not be added - */ - private void checkPrefixMapping(String uri, String qname) - throws SAXException { - // Only add the prefix mapping if the URI is not already known - if (uri != null && uri.length() > 0 && !uri.startsWith("xml") - && !uriToPrefixMap.containsKey(uri)) { - // Get the prefix - String prefix = "ns"; - if (qname != null && qname.length() > 0) { - int colon = qname.indexOf(':'); - if (colon != -1) { - prefix = qname.substring(0, colon); - } - } - - // Make sure that the prefix is unique - String base = prefix; - for (int i = 2; prefixToUriMap.containsKey(prefix); i++) { - prefix = base + i; - } - - int last = addedPrefixMappings.size() - 1; - List prefixes = (List) addedPrefixMappings.get(last); - if (prefixes == null) { - prefixes = new ArrayList(); - addedPrefixMappings.set(last, prefixes); - } - prefixes.add(prefix); - - startPrefixMapping(prefix, uri); - } - } - - /** - * Ensure all namespace declarations are present as xmlns: attributes - * and add those needed before delegating the startElement method on the - * specified handler. This is a workaround for a Xalan bug - * (at least in version 2.0.1) : org.apache.xalan.serialize.SerializerToXML - * ignores start/endPrefixMapping(). - */ - @Override - public void startElement( - String eltUri, String eltLocalName, String eltQName, Attributes attrs) - throws SAXException { - // JCR-1767: Generate extra prefix mapping calls where needed - addedPrefixMappings.add(null); - checkPrefixMapping(eltUri, eltQName); - for (int i = 0; i < attrs.getLength(); i++) { - checkPrefixMapping(attrs.getURI(i), attrs.getQName(i)); - } - - // try to restore the qName. The map already contains the colon - if (null != eltUri && eltUri.length() != 0 && this.uriToPrefixMap.containsKey(eltUri)) { - eltQName = this.uriToPrefixMap.get(eltUri) + eltLocalName; - } - if (this.hasMappings) { - // Add xmlns* attributes where needed - - // New Attributes if we have to add some. - AttributesImpl newAttrs = null; - - int mappingCount = this.prefixList.size(); - int attrCount = attrs.getLength(); - - for (int mapping = 0; mapping < mappingCount; mapping++) { - - // Build infos for this namespace - String uri = (String) this.uriList.get(mapping); - String prefix = (String) this.prefixList.get(mapping); - String qName = prefix.equals("") ? "xmlns" : ("xmlns:" + prefix); - - // Search for the corresponding xmlns* attribute - boolean found = false; - for (int attr = 0; attr < attrCount; attr++) { - if (qName.equals(attrs.getQName(attr))) { - // Check if mapping and attribute URI match - if (!uri.equals(attrs.getValue(attr))) { - throw new SAXException("URI in prefix mapping and attribute do not match"); - } - found = true; - break; - } - } - - if (!found) { - // Need to add this namespace - if (newAttrs == null) { - // Need to test if attrs is empty or we go into an infinite loop... - // Well know SAX bug which I spent 3 hours to remind of :-( - if (attrCount == 0) { - newAttrs = new AttributesImpl(); - } else { - newAttrs = new AttributesImpl(attrs); - } - } - - if (prefix.equals("")) { - newAttrs.addAttribute(XML, qName, qName, "CDATA", uri); - } else { - newAttrs.addAttribute(XML, prefix, qName, "CDATA", uri); - } - } - } // end for mapping - - // Cleanup for the next element - clearMappings(); - - // Start element with new attributes, if any - handler.startElement(eltUri, eltLocalName, eltQName, newAttrs == null ? attrs : newAttrs); - } else { - // Normal job - handler.startElement(eltUri, eltLocalName, eltQName, attrs); - } - } - - - /** - * Receive notification of the end of an element. - * Try to restore the element qName. - */ - @Override - public void endElement(String eltUri, String eltLocalName, String eltQName) throws SAXException { - // try to restore the qName. The map already contains the colon - if (null != eltUri && eltUri.length() != 0 && this.uriToPrefixMap.containsKey(eltUri)) { - eltQName = this.uriToPrefixMap.get(eltUri) + eltLocalName; - } - - handler.endElement(eltUri, eltLocalName, eltQName); - - // JCR-1767: Generate extra prefix un-mapping calls where needed - int last = addedPrefixMappings.size() - 1; - List prefixes = (List) addedPrefixMappings.remove(last); - if (prefixes != null) { - Iterator iterator = prefixes.iterator(); - while (iterator.hasNext()) { - endPrefixMapping((String) iterator.next()); - } - } - } - - /** - * End the scope of a prefix-URI mapping: - * remove entry from mapping tables. - */ - @Override - public void endPrefixMapping(String prefix) throws SAXException { - // remove mappings for xalan-bug-workaround. - // Unfortunately, we're not passed the uri, but the prefix here, - // so we need to maintain maps in both directions. - if (this.prefixToUriMap.containsKey(prefix)) { - this.uriToPrefixMap.remove(this.prefixToUriMap.get(prefix)); - this.prefixToUriMap.remove(prefix); - } - - if (hasMappings) { - // most of the time, start/endPrefixMapping calls have an element event between them, - // which will clear the hasMapping flag and so this code will only be executed in the - // rather rare occasion when there are start/endPrefixMapping calls with no element - // event in between. If we wouldn't remove the items from the prefixList and uriList here, - // the namespace would be incorrectly declared on the next element following the - // endPrefixMapping call. - int pos = prefixList.lastIndexOf(prefix); - if (pos != -1) { - prefixList.remove(pos); - uriList.remove(pos); - } - } - - handler.endPrefixMapping(prefix); - } - - @Override - public void ignorableWhitespace(char[] ch, int start, int length) throws SAXException { - handler.ignorableWhitespace(ch, start, length); - } - - @Override - public void processingInstruction(String target, String data) throws SAXException { - handler.processingInstruction(target, data); - } - - @Override - public void setDocumentLocator(Locator locator) { - handler.setDocumentLocator(locator); - } - - @Override - public void skippedEntity(String name) throws SAXException { - handler.skippedEntity(name); - } - - @Override - public void endDocument() throws SAXException { - // Cleanup - this.uriToPrefixMap.clear(); - this.prefixToUriMap.clear(); - clearMappings(); - - handler.endDocument(); - } - - private void clearMappings() { - this.hasMappings = false; - this.prefixList.clear(); - this.uriList.clear(); - } - } -} \ No newline at end of file Property changes on: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/xml/ResultHelper.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Deleted: svn:keywords ## -1 +0,0 ## -Author Date Id Revision Rev URL \ No newline at end of property Index: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/xml/XmlSerializable.java =================================================================== --- jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/xml/XmlSerializable.java (revision 1907912) +++ jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/xml/XmlSerializable.java (nonexistent) @@ -1,38 +0,0 @@ -/* - * 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.webdav.xml; - -import org.w3c.dom.Document; -import org.w3c.dom.Element; - -/** - * XmlSerializable... - */ -public interface XmlSerializable { - - /** - * Returns the xml representation of the implementing object as - * {@link org.w3c.dom.Element}. The given Document is used - * as factory and represents the {@link org.w3c.dom.Element#getOwnerDocument() - * owner document} of the returned DOM element. - * - * @return a w3c element representing this object - * @param document to be used as factory. - */ - public Element toXml(Document document); - -} \ No newline at end of file Property changes on: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/xml/XmlSerializable.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Deleted: svn:keywords ## -1 +0,0 ## -author date id revision url \ No newline at end of property Index: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/xml/package-info.java =================================================================== --- jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/xml/package-info.java (revision 1907912) +++ jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/xml/package-info.java (nonexistent) @@ -1,18 +0,0 @@ -/* - * 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. - */ -@org.osgi.annotation.versioning.Version("1.2.0") -package org.apache.jackrabbit.webdav.xml; Property changes on: jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/xml/package-info.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-webdav/src/main/javadoc/org/apache/jackrabbit/webdav/client/methods/package.html =================================================================== --- jackrabbit-webdav/src/main/javadoc/org/apache/jackrabbit/webdav/client/methods/package.html (revision 1907912) +++ jackrabbit-webdav/src/main/javadoc/org/apache/jackrabbit/webdav/client/methods/package.html (nonexistent) @@ -1,93 +0,0 @@ - - -

-This package contains classes and utilities used to build a WebDAV client -implementation.
-Currently it consists of DAV-specific extensions to the -Jakarta Commons HttpClient, -namely a set of methods. -

- -

-

How to use Jakarta Commons HttpClient

-Please refer to the - tutorial - present with Jakarta Commons HttpClient for detailed -instructions. -

- -

-

Simple Example

-The following simple example illustrates the additional functionality exposed - by the DavMethod which serves as basic interface for all - WebDAV specific extensions:

- -First you need to create the HostConfiguration which at least - must define the uri pointing to your WebDAV enabled server -
-    String uri = "http://your-webdav-server";
-    HostConfiguration hostConfig = new HostConfiguration();
-    hostConfig.setHost(uri);
-
- -Define a HttpConnectionManager, which also is responsible - for eventual multithreading support: -
-    HttpConnectionManager connectionManager = new MultiThreadedHttpConnectionManager();
-    HttpConnectionManagerParams params = new HttpConnectionManagerParams();
-    int maxHostConnections = 20;
-    params.setMaxConnectionsPerHost(hostConfig, maxHostConnections);
-    connectionManager.setParams(params);
-
- -Create the HttpClient object and eventually pass the Credentials: -
-    HttpClient client = new HttpClient(connectionManager);
-    client.setHostConfiguration(hostConfig);
-    Credentials creds = new UsernamePasswordCredentials("userId", "pw");
-    client.getState().setCredentials(AuthScope.ANY, creds);
-
- -In order to execute a WebDAV request, choose the appropriate DavMethod. - For example, a PROPFIND request could look as follows: -
-    String propfindUri = "http://your-webdav-server/anyresource";
-    DavMethod method = new PropFindMethod(propfindUri, DavConstants.PROPFIND_ALL_PROP, DavConstants.DEPTH_1);
-    client.executeMethod(method);
-
- -The DavMethod interface defines two methods that allows you to determine if the - request was successfully executed without need to evaluate the status line and - knowing about the required status codes: -
    -
  • DavMethod.checkSuccess()
  • -
  • DavMethod.succeeded()
  • -
- -
-    method.checkSuccess();
-
- -In case of success you can retrieve the response body in an appropriate formate - and process it according to you needs,
- For a PROPFIND request use e.g. DavMethod.getResponseBodyAsMultiStatus(): -
-    MultiStatus multiStatus = method.getResponseBodyAsMultiStatus();
-
-

- \ No newline at end of file Property changes on: jackrabbit-webdav/src/main/javadoc/org/apache/jackrabbit/webdav/client/methods/package.html ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-webdav/src/main/javadoc/org/apache/jackrabbit/webdav/lock/package.html =================================================================== --- jackrabbit-webdav/src/main/javadoc/org/apache/jackrabbit/webdav/lock/package.html (revision 1907912) +++ jackrabbit-webdav/src/main/javadoc/org/apache/jackrabbit/webdav/lock/package.html (nonexistent) @@ -1,19 +0,0 @@ - - -Provides interfaces and classes for locking related issues. - Property changes on: jackrabbit-webdav/src/main/javadoc/org/apache/jackrabbit/webdav/lock/package.html ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-webdav/src/main/javadoc/org/apache/jackrabbit/webdav/observation/package.html =================================================================== --- jackrabbit-webdav/src/main/javadoc/org/apache/jackrabbit/webdav/observation/package.html (revision 1907912) +++ jackrabbit-webdav/src/main/javadoc/org/apache/jackrabbit/webdav/observation/package.html (nonexistent) @@ -1,20 +0,0 @@ - - -Contains interfaces and classes related to observation, which is not covered -by the WebDAV protocol. - Property changes on: jackrabbit-webdav/src/main/javadoc/org/apache/jackrabbit/webdav/observation/package.html ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-webdav/src/main/javadoc/org/apache/jackrabbit/webdav/ordering/package.html =================================================================== --- jackrabbit-webdav/src/main/javadoc/org/apache/jackrabbit/webdav/ordering/package.html (revision 1907912) +++ jackrabbit-webdav/src/main/javadoc/org/apache/jackrabbit/webdav/ordering/package.html (nonexistent) @@ -1,21 +0,0 @@ - - -Contains interfaces and classes used to cover the functionality defined by the -RFC 3648: Web Distributed Authoring -and Versioning (WebDAV) Ordered Collections Protocol . - Property changes on: jackrabbit-webdav/src/main/javadoc/org/apache/jackrabbit/webdav/ordering/package.html ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-webdav/src/main/javadoc/org/apache/jackrabbit/webdav/property/package.html =================================================================== --- jackrabbit-webdav/src/main/javadoc/org/apache/jackrabbit/webdav/property/package.html (revision 1907912) +++ jackrabbit-webdav/src/main/javadoc/org/apache/jackrabbit/webdav/property/package.html (nonexistent) @@ -1,19 +0,0 @@ - - -Interfaces and classes related to WebDAV properties. - Property changes on: jackrabbit-webdav/src/main/javadoc/org/apache/jackrabbit/webdav/property/package.html ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-webdav/src/main/javadoc/org/apache/jackrabbit/webdav/search/package.html =================================================================== --- jackrabbit-webdav/src/main/javadoc/org/apache/jackrabbit/webdav/search/package.html (revision 1907912) +++ jackrabbit-webdav/src/main/javadoc/org/apache/jackrabbit/webdav/search/package.html (nonexistent) @@ -1,21 +0,0 @@ - - -Contains interfaces and classes used to cover the functionality defined by the -Internet -Draft WebDAV Search. - Property changes on: jackrabbit-webdav/src/main/javadoc/org/apache/jackrabbit/webdav/search/package.html ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-webdav/src/main/javadoc/org/apache/jackrabbit/webdav/transaction/package.html =================================================================== --- jackrabbit-webdav/src/main/javadoc/org/apache/jackrabbit/webdav/transaction/package.html (revision 1907912) +++ jackrabbit-webdav/src/main/javadoc/org/apache/jackrabbit/webdav/transaction/package.html (nonexistent) @@ -1,19 +0,0 @@ - - -Contains interfaces and classes related to transaction locks. - Property changes on: jackrabbit-webdav/src/main/javadoc/org/apache/jackrabbit/webdav/transaction/package.html ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-webdav/src/main/javadoc/org/apache/jackrabbit/webdav/util/package.html =================================================================== --- jackrabbit-webdav/src/main/javadoc/org/apache/jackrabbit/webdav/util/package.html (revision 1907912) +++ jackrabbit-webdav/src/main/javadoc/org/apache/jackrabbit/webdav/util/package.html (nonexistent) @@ -1,19 +0,0 @@ - - -Common utility classes. - Property changes on: jackrabbit-webdav/src/main/javadoc/org/apache/jackrabbit/webdav/util/package.html ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-webdav/src/main/javadoc/org/apache/jackrabbit/webdav/version/package.html =================================================================== --- jackrabbit-webdav/src/main/javadoc/org/apache/jackrabbit/webdav/version/package.html (revision 1907912) +++ jackrabbit-webdav/src/main/javadoc/org/apache/jackrabbit/webdav/version/package.html (nonexistent) @@ -1,20 +0,0 @@ - - -Interfaces and classes used to cover functionality defined by -RFC 3253: Versioning Extensions to WebDAV. - Property changes on: jackrabbit-webdav/src/main/javadoc/org/apache/jackrabbit/webdav/version/package.html ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-webdav/src/main/javadoc/org/apache/jackrabbit/webdav/version/report/package.html =================================================================== --- jackrabbit-webdav/src/main/javadoc/org/apache/jackrabbit/webdav/version/report/package.html (revision 1907912) +++ jackrabbit-webdav/src/main/javadoc/org/apache/jackrabbit/webdav/version/report/package.html (nonexistent) @@ -1,19 +0,0 @@ - - -Report interface and inplementation for default reports defined by RFC 3253. - Property changes on: jackrabbit-webdav/src/main/javadoc/org/apache/jackrabbit/webdav/version/report/package.html ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-webdav/src/main/javadoc/org/apache/jackrabbit/webdav/xml/package.html =================================================================== --- jackrabbit-webdav/src/main/javadoc/org/apache/jackrabbit/webdav/xml/package.html (revision 1907912) +++ jackrabbit-webdav/src/main/javadoc/org/apache/jackrabbit/webdav/xml/package.html (nonexistent) @@ -1,19 +0,0 @@ - - -Xml utility classes. - Property changes on: jackrabbit-webdav/src/main/javadoc/org/apache/jackrabbit/webdav/xml/package.html ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-webdav/src/main/resources/org/apache/jackrabbit/webdav/statuscode.properties =================================================================== --- jackrabbit-webdav/src/main/resources/org/apache/jackrabbit/webdav/statuscode.properties (revision 1907912) +++ jackrabbit-webdav/src/main/resources/org/apache/jackrabbit/webdav/statuscode.properties (nonexistent) @@ -1,62 +0,0 @@ -# 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. - -100=Continue -101=Switching Protocols -102=Processing -200=OK -201=Created -202=Accepted -203=Non-Authoritative Information -204=No Content -205=Reset Content -206=Partial Content -207=Multi-Status -300=Multiple Choices -301=Moved Permanently -302=Found -303=See Other -304=Not Modified -305=Use Proxy -307=Temporary Redirect -400=Bad Request -401=Unauthorized -402=Payment Required -403=Forbidden -404=Not Found -405=Method Not Allowed -406=Not Acceptable -407=Proxy Authentication Required -408=Request Time-out -409=Conflict -410=Gone -411=Length Required -412=Precondition Failed -413=Request Entity Too Large -414=Request-URI Too Large -415=Unsupported Media Type -416=Requested range not satisfiable -417=Expectation Failed -420=Method Failure -422=Unprocessable Entity -423=Locked -424=Failed Dependency -500=Internal Server Error -501=Not Implemented -502=Bad Gateway -503=Service Unavailable -504=Gateway Time-out -505=HTTP Version not supported -507=Insufficient Storage Property changes on: jackrabbit-webdav/src/main/resources/org/apache/jackrabbit/webdav/statuscode.properties ___________________________________________________________________ Deleted: svn Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-webdav/src/test/java/org/apache/jackrabbit/webdav/header/FieldValueParserTest.java =================================================================== --- jackrabbit-webdav/src/test/java/org/apache/jackrabbit/webdav/header/FieldValueParserTest.java (revision 1907912) +++ jackrabbit-webdav/src/test/java/org/apache/jackrabbit/webdav/header/FieldValueParserTest.java (nonexistent) @@ -1,42 +0,0 @@ -/* - * 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.webdav.header; - -import java.util.List; - -import org.junit.Test; -import static org.junit.Assert.assertArrayEquals; - -import junit.framework.TestCase; - -public class FieldValueParserTest extends TestCase { - - @Test - public void testDavComplianceHeader() { - - List l; - - l = FieldValueParser.tokenizeList("1"); - assertArrayEquals(new String[]{"1"}, l.toArray()); - - l = FieldValueParser.tokenizeList("1,2,,,,,3,,bind,"); - assertArrayEquals(new String[]{"1","2","3","bind"}, l.toArray()); - - l = FieldValueParser.tokenizeList("1,2,"); - assertArrayEquals(new String[]{"1","2",""}, l.toArray()); - } -} Property changes on: jackrabbit-webdav/src/test/java/org/apache/jackrabbit/webdav/header/FieldValueParserTest.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-webdav/src/test/java/org/apache/jackrabbit/webdav/header/TestAll.java =================================================================== --- jackrabbit-webdav/src/test/java/org/apache/jackrabbit/webdav/header/TestAll.java (revision 1907912) +++ jackrabbit-webdav/src/test/java/org/apache/jackrabbit/webdav/header/TestAll.java (nonexistent) @@ -1,32 +0,0 @@ -/* - * 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.webdav.header; - -import junit.framework.Test; -import junit.framework.TestCase; -import junit.framework.TestSuite; - -public class TestAll extends TestCase { - - public static Test suite() { - TestSuite suite = new TestSuite("WebDAV header tests"); - - suite.addTestSuite(FieldValueParserTest.class); - - return suite; - } -} \ No newline at end of file Property changes on: jackrabbit-webdav/src/test/java/org/apache/jackrabbit/webdav/header/TestAll.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-webdav/src/test/java/org/apache/jackrabbit/webdav/io/OutputContextImplTest.java =================================================================== --- jackrabbit-webdav/src/test/java/org/apache/jackrabbit/webdav/io/OutputContextImplTest.java (revision 1907912) +++ jackrabbit-webdav/src/test/java/org/apache/jackrabbit/webdav/io/OutputContextImplTest.java (nonexistent) @@ -1,186 +0,0 @@ -/* - * 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.webdav.io; - -import junit.framework.TestCase; - -import javax.servlet.http.HttpServletResponse; -import javax.servlet.http.Cookie; -import javax.servlet.ServletOutputStream; -import java.io.IOException; -import java.io.PrintWriter; -import java.util.Collection; -import java.util.Locale; - -/** - * OutputContextImplTest... - */ -public class OutputContextImplTest extends TestCase { - - public void testSetContentLength() { - HttpServletResponse response = new DummyResponse() { - @Override - public void setContentLength(int len) { - assertTrue(len >= 0); - } - @Override - public void setHeader(String name, String value) { - assertTrue(Long.parseLong(value) > Integer.MAX_VALUE); - } - @Override - public String getContentType() { - return null; - } - @Override - public void setCharacterEncoding(String charset) { - } - @Override - public int getStatus() { - return 0; - } - @Override - public String getHeader(String name) { - return null; - } - @Override - public Collection getHeaders(String name) { - return null; - } - @Override - public Collection getHeaderNames() { - return null; - } - @Override - public void setContentLengthLong(long len) { - } - }; - - OutputContext ctx = new OutputContextImpl(response, null); - - ctx.setContentLength(Long.MAX_VALUE); - ctx.setContentLength(Long.MIN_VALUE); - ctx.setContentLength(Integer.MAX_VALUE); - ctx.setContentLength((long) Integer.MAX_VALUE + 1); - ctx.setContentLength(0); - ctx.setContentLength(-1); - ctx.setContentLength(12345); - } - - private abstract class DummyResponse implements HttpServletResponse { - - public void addCookie(Cookie cookie) { - } - - public boolean containsHeader(String name) { - return false; - } - - public String encodeURL(String url) { - return null; - } - - public String encodeRedirectURL(String url) { - return null; - } - - public String encodeUrl(String url) { - return null; - } - - public String encodeRedirectUrl(String url) { - return null; - } - - public void sendError(int sc, String msg) throws IOException { - } - - public void sendError(int sc) throws IOException { - } - - public void sendRedirect(String location) throws IOException { - } - - public void setDateHeader(String name, long date) { - } - - public void addDateHeader(String name, long date) { - } - - public void setHeader(String name, String value) { - } - - public void addHeader(String name, String value) { - } - - public void setIntHeader(String name, int value) { - } - - public void addIntHeader(String name, int value) { - } - - public void setStatus(int sc) { - } - - public void setStatus(int sc, String sm) { - } - - public String getCharacterEncoding() { - return null; - } - - public ServletOutputStream getOutputStream() throws IOException { - return null; - } - - public PrintWriter getWriter() throws IOException { - return null; - } - - public void setContentLength(int len) { - } - - public void setContentType(String type) { - } - - public void setBufferSize(int size) { - } - - public int getBufferSize() { - return 0; - } - - public void flushBuffer() throws IOException { - } - - public void resetBuffer() { - } - - public boolean isCommitted() { - return false; - } - - public void reset() { - } - - public void setLocale(Locale loc) { - } - - public Locale getLocale() { - return null; - } - } -} Property changes on: jackrabbit-webdav/src/test/java/org/apache/jackrabbit/webdav/io/OutputContextImplTest.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Deleted: svn:keywords ## -1 +0,0 ## -author date id revision url \ No newline at end of property Index: jackrabbit-webdav/src/test/java/org/apache/jackrabbit/webdav/io/TestAll.java =================================================================== --- jackrabbit-webdav/src/test/java/org/apache/jackrabbit/webdav/io/TestAll.java (revision 1907912) +++ jackrabbit-webdav/src/test/java/org/apache/jackrabbit/webdav/io/TestAll.java (nonexistent) @@ -1,32 +0,0 @@ -/* - * 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.webdav.io; - -import junit.framework.Test; -import junit.framework.TestCase; -import junit.framework.TestSuite; - -public class TestAll extends TestCase { - - public static Test suite() { - TestSuite suite = new TestSuite("WebDAV IO tests"); - - suite.addTestSuite(OutputContextImplTest.class); - - return suite; - } -} \ No newline at end of file Property changes on: jackrabbit-webdav/src/test/java/org/apache/jackrabbit/webdav/io/TestAll.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Deleted: svn:keywords ## -1 +0,0 ## -author date id revision url \ No newline at end of property Index: jackrabbit-webdav/src/test/java/org/apache/jackrabbit/webdav/lock/ActiveLockTest.java =================================================================== --- jackrabbit-webdav/src/test/java/org/apache/jackrabbit/webdav/lock/ActiveLockTest.java (revision 1907912) +++ jackrabbit-webdav/src/test/java/org/apache/jackrabbit/webdav/lock/ActiveLockTest.java (nonexistent) @@ -1,64 +0,0 @@ -/* - * 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.webdav.lock; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.w3c.dom.Document; -import org.apache.jackrabbit.webdav.xml.DomUtil; -import junit.framework.TestCase; - -import javax.xml.parsers.ParserConfigurationException; -import java.util.List; - -/** - * ActiveLockTest... - */ -public class ActiveLockTest extends TestCase { - - /** - * logger instance - */ - private static final Logger log = LoggerFactory.getLogger(ActiveLockTest.class); - - public void testGetLockRoot() { - ActiveLock lock = new DefaultActiveLock(); - lock.setLockroot("lockroot"); - - assertEquals("lockroot", lock.getLockroot()); - } - - public void testParsing() throws ParserConfigurationException { - Document doc = DomUtil.createDocument(); - - ActiveLock lock = new DefaultActiveLock(); - lock.setLockroot("lockroot"); - lock.setOwner("owner"); - lock.setIsDeep(true); - - LockDiscovery disc = LockDiscovery.createFromXml(new LockDiscovery(lock).toXml(doc)); - List l = disc.getValue(); - - assertFalse(l.isEmpty()); - assertEquals(1, l.size()); - ActiveLock al = l.get(0); - - assertEquals("lockroot", al.getLockroot()); - assertEquals("owner", al.getOwner()); - assertTrue(al.isDeep()); - } -} Property changes on: jackrabbit-webdav/src/test/java/org/apache/jackrabbit/webdav/lock/ActiveLockTest.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Deleted: svn:keywords ## -1 +0,0 ## -author date id revision url \ No newline at end of property Index: jackrabbit-webdav/src/test/java/org/apache/jackrabbit/webdav/lock/TestAll.java =================================================================== --- jackrabbit-webdav/src/test/java/org/apache/jackrabbit/webdav/lock/TestAll.java (revision 1907912) +++ jackrabbit-webdav/src/test/java/org/apache/jackrabbit/webdav/lock/TestAll.java (nonexistent) @@ -1,32 +0,0 @@ -/* - * 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.webdav.lock; - -import junit.framework.Test; -import junit.framework.TestCase; -import junit.framework.TestSuite; - -public class TestAll extends TestCase { - - public static Test suite() { - TestSuite suite = new TestSuite("WebDAV lock tests"); - - suite.addTestSuite(ActiveLockTest.class); - - return suite; - } -} \ No newline at end of file Property changes on: jackrabbit-webdav/src/test/java/org/apache/jackrabbit/webdav/lock/TestAll.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Deleted: svn:keywords ## -1 +0,0 ## -author date id revision url \ No newline at end of property Index: jackrabbit-webdav/src/test/java/org/apache/jackrabbit/webdav/util/CSRFUtilTest.java =================================================================== --- jackrabbit-webdav/src/test/java/org/apache/jackrabbit/webdav/util/CSRFUtilTest.java (revision 1907912) +++ jackrabbit-webdav/src/test/java/org/apache/jackrabbit/webdav/util/CSRFUtilTest.java (nonexistent) @@ -1,412 +0,0 @@ -/* - * 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.webdav.util; - -import java.io.BufferedReader; -import java.io.IOException; -import java.io.UnsupportedEncodingException; -import java.security.Principal; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.Enumeration; -import java.util.HashSet; -import java.util.List; -import java.util.Locale; -import java.util.Map; -import java.util.Set; -import java.util.Vector; - -import javax.servlet.AsyncContext; -import javax.servlet.DispatcherType; -import javax.servlet.RequestDispatcher; -import javax.servlet.ServletContext; -import javax.servlet.ServletException; -import javax.servlet.ServletInputStream; -import javax.servlet.ServletRequest; -import javax.servlet.ServletResponse; -import javax.servlet.http.Cookie; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import javax.servlet.http.HttpSession; -import javax.servlet.http.HttpUpgradeHandler; -import javax.servlet.http.Part; - -import junit.framework.TestCase; - -/** - * CSRFUtilTest... - */ -public class CSRFUtilTest extends TestCase { - - private static final String SERVER_NAME = "localhost"; - - private static final String GET = "GET"; - private static final String POST = "POST"; - - private static final List validURLs = new ArrayList(); - private static final List invalidURLs = new ArrayList(); - - static { - validURLs.add("http://localhost:4503/jackrabbit/server"); - validURLs.add("https://localhost:4503/jackrabbit/server"); - validURLs.add("https://localhost/jackrabbit/server"); - validURLs.add("//localhost/jackrabbit/server"); - validURLs.add("/jackrabbit/server"); - - invalidURLs.add("http://invalidHost/test"); - invalidURLs.add("http://host1:8080/test"); - invalidURLs.add("http://user:pw@host2/test"); - } - - static String[] noContentType = new String[0]; - - private static void testValid(CSRFUtil util, Collection validURLs, String method, Set contentTypes) { - if (null == contentTypes) { - for (String url : validURLs) { - assertTrue(url, util.isValidRequest(createRequest(url, method, noContentType))); - } - } else { - for (String contentType : contentTypes) { - for (String url : validURLs) { - assertTrue(url, util.isValidRequest(createRequest(url, method, contentType))); - } - } - } - } - - private static void testInvalid(CSRFUtil util, Collection invalidURLs, String method, Set contentTypes) { - if (null == contentTypes) { - for (String url : validURLs) { - assertFalse(url, util.isValidRequest(createRequest(url, method, noContentType))); - } - } else { - for (String contentType : contentTypes) { - for (String url : invalidURLs) { - assertFalse(url, util.isValidRequest(createRequest(url, method, contentType))); - } - } - } - } - - private static HttpServletRequest createRequest(String url, String method, String[] contentTypes) { - return new DummyRequest(url, SERVER_NAME, method, contentTypes); - } - - private static HttpServletRequest createRequest(String url, String method, String contentType) { - return new DummyRequest(url, SERVER_NAME, method, new String[] { contentType }); - } - - public void testNullConfig() throws Exception { - CSRFUtil util = new CSRFUtil(null); - testValid(util, validURLs, POST, CSRFUtil.CONTENT_TYPES); - testInvalid(util, invalidURLs, POST, CSRFUtil.CONTENT_TYPES); - } - - public void testEmptyConfig() throws Exception { - CSRFUtil util = new CSRFUtil(""); - testValid(util, validURLs, POST, CSRFUtil.CONTENT_TYPES); - testInvalid(util, invalidURLs, POST, CSRFUtil.CONTENT_TYPES); - } - - public void testNoReferrer() throws Exception { - CSRFUtil util = new CSRFUtil(""); - testValid(util, validURLs, POST, CSRFUtil.CONTENT_TYPES); - assertFalse("no referrer", util.isValidRequest(createRequest(null, POST, "text/plain"))); - assertFalse("no referrer", util.isValidRequest(createRequest(null, POST, noContentType))); - assertFalse("no referrer", util.isValidRequest(createRequest(null, POST, "TEXT/PLAIN; foo=bar"))); - assertTrue("no referrer", util.isValidRequest(createRequest(null, POST, "application/json"))); - assertFalse("no referrer", util.isValidRequest(createRequest(null, POST, new String[] { "application/json", "foo/bar" }))); - } - - public void testDisabledConfig() throws Exception { - CSRFUtil util = new CSRFUtil(CSRFUtil.DISABLED); - testValid(util, validURLs, POST, CSRFUtil.CONTENT_TYPES); - // since test is disabled any other referer host must be allowed - testValid(util, invalidURLs, POST, CSRFUtil.CONTENT_TYPES); - } - - public void testConfig() throws Exception { - List configs = new ArrayList(); - configs.add("host1,host2"); - configs.add(" host1 , host2 "); - configs.add("\rhost1,\rhost2\r"); - - // hosts listed in the config must be valid - List otherHosts = new ArrayList(); - otherHosts.add("http://host1:80/test"); - otherHosts.add("http://host1/test"); - otherHosts.add("https://user:pw@host2/test"); - - List invalidURLs = new ArrayList(); - invalidURLs.add("http://invalidHost/test"); - invalidURLs.add("http://host3:8080/test"); - invalidURLs.add("https://user:pw@host4/test"); - - for (String config : configs) { - CSRFUtil util = new CSRFUtil(config); - testValid(util, validURLs, POST, CSRFUtil.CONTENT_TYPES); - testValid(util, otherHosts, POST, CSRFUtil.CONTENT_TYPES); - testInvalid(util, invalidURLs, POST, CSRFUtil.CONTENT_TYPES); - } - } - - public void testMethodsAndMediaType() throws Exception { - CSRFUtil util = new CSRFUtil(""); - testValid(util, invalidURLs, GET, CSRFUtil.CONTENT_TYPES); - testValid(util, invalidURLs, POST, new HashSet(Arrays.asList(new String[] {"application/json"}))); - testInvalid(util, invalidURLs, POST, CSRFUtil.CONTENT_TYPES); - } - - private static final class DummyRequest implements HttpServletRequest { - - private final String referer; - private final String serverName; - private final String method; - private final String[] contentTypes; - - private DummyRequest(String referer, String serverName, String method, String[] contentTypes) { - this.referer = referer; - this.serverName = serverName; - this.method = method; - this.contentTypes = contentTypes; - } - - //---------------------------------------------< HttpServletRequest >--- - - public String getHeader(String name) { - if ("Referer".equalsIgnoreCase(name)) { - return referer; - } else { - return null; - } - } - - public String getServerName() { - return serverName; - } - - public String getContentType() { - return contentTypes.length == 0 ? null : contentTypes[0]; - } - - @SuppressWarnings({ "rawtypes", "unchecked" }) - public Enumeration getHeaders(String name) { - if (name != null && contentTypes.length > 0 && name.toLowerCase(Locale.ENGLISH).equals("content-type")) { - return new Vector(Arrays.asList(contentTypes)).elements(); - } else { - return null; - } - } - - //---------------------------------------------------------< unused >--- - public String getAuthType() { - return null; - } - public Cookie[] getCookies() { - return new Cookie[0]; - } - public long getDateHeader(String name) { - return 0; - } - public Enumeration getHeaderNames() { - return null; - } - public int getIntHeader(String name) { - return 0; - } - public String getMethod() { - return method; - } - public String getPathInfo() { - return null; - } - public String getPathTranslated() { - return null; - } - public String getContextPath() { - return null; - } - public String getQueryString() { - return null; - } - public String getRemoteUser() { - return null; - } - public boolean isUserInRole(String role) { - return false; - } - public Principal getUserPrincipal() { - return null; - } - public String getRequestedSessionId() { - return null; - } - public String getRequestURI() { - return null; - } - public StringBuffer getRequestURL() { - return null; - } - public String getServletPath() { - return null; - } - public HttpSession getSession(boolean create) { - return null; - } - public HttpSession getSession() { - return null; - } - public boolean isRequestedSessionIdValid() { - return false; - } - public boolean isRequestedSessionIdFromCookie() { - return false; - } - public boolean isRequestedSessionIdFromURL() { - return false; - } - public boolean isRequestedSessionIdFromUrl() { - return false; - } - public Object getAttribute(String name) { - return null; - } - public Enumeration getAttributeNames() { - return null; - } - public String getCharacterEncoding() { - return null; - } - public void setCharacterEncoding(String s) throws UnsupportedEncodingException { - - } - public int getContentLength() { - return 0; - } - public ServletInputStream getInputStream() throws IOException { - return null; - } - public String getParameter(String name) { - return null; - } - public Enumeration getParameterNames() { - return null; - } - public String[] getParameterValues(String name) { - return new String[0]; - } - public Map getParameterMap() { - return null; - } - public String getProtocol() { - return null; - } - public String getScheme() { - return null; - } - public int getServerPort() { - return 0; - } - public BufferedReader getReader() throws IOException { - return null; - } - public String getRemoteAddr() { - return null; - } - public String getRemoteHost() { - return null; - } - public void setAttribute(String name, Object o) { - - } - public void removeAttribute(String name) { - - } - public Locale getLocale() { - return null; - } - public Enumeration getLocales() { - return null; - } - public boolean isSecure() { - return false; - } - public RequestDispatcher getRequestDispatcher(String path) { - return null; - } - public String getRealPath(String path) { - return null; - } - public int getRemotePort() { - return 0; - } - public String getLocalName() { - return null; - } - public String getLocalAddr() { - return null; - } - public int getLocalPort() { - return 0; - } - public long getContentLengthLong() { - return 0; - } - public ServletContext getServletContext() { - return null; - } - public AsyncContext startAsync() throws IllegalStateException { - return null; - } - public AsyncContext startAsync(ServletRequest servletRequest, ServletResponse servletResponse) - throws IllegalStateException { - return null; - } - public boolean isAsyncStarted() { - return false; - } - public boolean isAsyncSupported() { - return false; - } - public AsyncContext getAsyncContext() { - return null; - } - public DispatcherType getDispatcherType() { - return null; - } - public String changeSessionId() { - return null; - } - public boolean authenticate(HttpServletResponse response) throws IOException, ServletException { - return false; - } - public void login(String username, String password) throws ServletException { - } - public void logout() throws ServletException { - } - public Collection getParts() throws IOException, ServletException { - return null; - } - public Part getPart(String name) throws IOException, ServletException { - return null; - } - public T upgrade(Class handlerClass) throws IOException, ServletException { - return null; - } - } -} \ No newline at end of file Property changes on: jackrabbit-webdav/src/test/java/org/apache/jackrabbit/webdav/util/CSRFUtilTest.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Deleted: svn:keywords ## -1 +0,0 ## -Author Date Id Revision Rev URL \ No newline at end of property Index: jackrabbit-webdav/src/test/java/org/apache/jackrabbit/webdav/util/HttpDateTimeFormatterTest.java =================================================================== --- jackrabbit-webdav/src/test/java/org/apache/jackrabbit/webdav/util/HttpDateTimeFormatterTest.java (revision 1907912) +++ jackrabbit-webdav/src/test/java/org/apache/jackrabbit/webdav/util/HttpDateTimeFormatterTest.java (nonexistent) @@ -1,65 +0,0 @@ -/* - * 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.webdav.util; - -import java.time.format.DateTimeParseException; - -import junit.framework.TestCase; - -public class HttpDateTimeFormatterTest extends TestCase { - - public void testImfDate() { - long t = HttpDateTimeFormatter.parseImfFixedDate("Sun, 06 Nov 1994 08:49:37 GMT"); - assertEquals(784111777000l, t); - assertEquals("Sun, 06 Nov 1994 08:49:37 GMT", HttpDateTimeFormatter.formatImfFixed(t)); - } - - public void testImfDateWrongTZ() { - try { - HttpDateTimeFormatter.parseImfFixedDate("Sun, 06 Nov 1994 08:49:37 CET"); - fail("should fail for incorrec tz"); - } catch (DateTimeParseException expected) { - } - } - - public void testImfDateWrongWeekday() { - try { - HttpDateTimeFormatter.parseImfFixedDate("Mon, 06 Nov 1994 08:49:37 GMT"); - fail("should fail for incorrec tz"); - } catch (DateTimeParseException expected) { - } - } - - // will fail after 2044 - public void testRFC850Date() { - long t = HttpDateTimeFormatter.parseRfc850Date("Sunday, 06-Nov-94 08:49:37 GMT"); - assertEquals(784111777000l, t); - assertEquals("Sunday, 06-Nov-94 08:49:37 GMT", HttpDateTimeFormatter.formatRfc850(t)); - } - - public void testAscTimeDate() { - long t = HttpDateTimeFormatter.parseAscTimeDate("Sun Nov 6 08:49:37 1994"); - assertEquals(784111777000l, t); - assertEquals("Sun Nov 6 08:49:37 1994", HttpDateTimeFormatter.formatAscTime(t)); - } - - public void testAscTimeDateZeroPad() { - long t = HttpDateTimeFormatter.parseAscTimeDate("Sun Nov 06 08:49:37 1994"); - assertEquals(784111777000l, t); - assertEquals("Sun Nov 6 08:49:37 1994", HttpDateTimeFormatter.formatAscTime(t)); - } -} Property changes on: jackrabbit-webdav/src/test/java/org/apache/jackrabbit/webdav/util/HttpDateTimeFormatterTest.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-webdav/src/test/java/org/apache/jackrabbit/webdav/util/LinkHeaderFieldParserTest.java =================================================================== --- jackrabbit-webdav/src/test/java/org/apache/jackrabbit/webdav/util/LinkHeaderFieldParserTest.java (revision 1907912) +++ jackrabbit-webdav/src/test/java/org/apache/jackrabbit/webdav/util/LinkHeaderFieldParserTest.java (nonexistent) @@ -1,65 +0,0 @@ -/* - * 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.webdav.util; - -import java.util.Collections; - -import junit.framework.TestCase; - -/** - * LinkHeaderFieldParserTest... - */ -public class LinkHeaderFieldParserTest extends TestCase { - - public void testSimple() { - LinkHeaderFieldParser lhfp = new LinkHeaderFieldParser( - Collections.singletonList("; rel=foo")); - assertEquals("a", lhfp.getFirstTargetForRelation("foo")); - } - - public void testMulti() { - LinkHeaderFieldParser lhfp = new LinkHeaderFieldParser( - Collections.singletonList("; rel=foo, ; rel=bar")); - assertEquals("b", lhfp.getFirstTargetForRelation("bar")); - } - - public void testMultiQs() { - LinkHeaderFieldParser lhfp = new LinkHeaderFieldParser( - Collections - .singletonList("; rel=\"fo\\\"o,\", ; rel=bar")); - assertEquals("b,", lhfp.getFirstTargetForRelation("bar")); - } - - // broken by change to httpclient 4 -// public void testTruncated() { -// LinkHeaderFieldParser lhfp = new LinkHeaderFieldParser( -// Collections.singletonList("; rel=\"x\\\"")); -// assertEquals("a,", lhfp.getFirstTargetForRelation("x\\")); -// } - - public void testCommas() { - LinkHeaderFieldParser lhfp = new LinkHeaderFieldParser( - Collections.singletonList(",; rel=\"xy,z\",")); - assertEquals("a", lhfp.getFirstTargetForRelation("xy,z")); - } - - public void testMultiRel() { - LinkHeaderFieldParser lhfp = new LinkHeaderFieldParser( - Collections.singletonList(",; rel=\"a b\"")); - assertEquals("a", lhfp.getFirstTargetForRelation("a")); - } -} Property changes on: jackrabbit-webdav/src/test/java/org/apache/jackrabbit/webdav/util/LinkHeaderFieldParserTest.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-webdav/src/test/java/org/apache/jackrabbit/webdav/util/TestAll.java =================================================================== --- jackrabbit-webdav/src/test/java/org/apache/jackrabbit/webdav/util/TestAll.java (revision 1907912) +++ jackrabbit-webdav/src/test/java/org/apache/jackrabbit/webdav/util/TestAll.java (nonexistent) @@ -1,40 +0,0 @@ -/* - * 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.webdav.util; - -import junit.framework.Test; -import junit.framework.TestCase; -import junit.framework.TestSuite; - -/** - * Test suite that includes all testcases for package org.apache.jackrabbit.webdav.util. - */ -public class TestAll extends TestCase { - - /** - * Returns a Test suite that executes all tests inside this - * package. - */ - public static Test suite() { - TestSuite suite = new TestSuite("org.apache.jackrabbit.webdav.util tests"); - - suite.addTestSuite(CSRFUtilTest.class); - suite.addTestSuite(LinkHeaderFieldParserTest.class); - - return suite; - } -} Property changes on: jackrabbit-webdav/src/test/java/org/apache/jackrabbit/webdav/util/TestAll.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Deleted: svn:keywords ## -1 +0,0 ## -Author Date Id Revision Rev URL \ No newline at end of property Index: jackrabbit-webdav/src/test/java/org/apache/jackrabbit/webdav/xml/NamespaceTest.java =================================================================== --- jackrabbit-webdav/src/test/java/org/apache/jackrabbit/webdav/xml/NamespaceTest.java (revision 1907912) +++ jackrabbit-webdav/src/test/java/org/apache/jackrabbit/webdav/xml/NamespaceTest.java (nonexistent) @@ -1,94 +0,0 @@ -/* - * 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.webdav.xml; - -import junit.framework.TestCase; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.HashMap; -import java.util.Map; - -/** - * NamespaceTest... - */ -public class NamespaceTest extends TestCase { - - /** - * logger instance - */ - private static final Logger log = LoggerFactory.getLogger(NamespaceTest.class); - - public void testGetNamespace() { - assertEquals(Namespace.EMPTY_NAMESPACE, Namespace.getNamespace("", "")); - assertEquals(Namespace.EMPTY_NAMESPACE, Namespace.getNamespace(null, null)); - assertEquals(Namespace.XML_NAMESPACE, Namespace.getNamespace(Namespace.XML_NAMESPACE.getPrefix(), Namespace.XML_NAMESPACE.getURI())); - assertEquals(Namespace.XMLNS_NAMESPACE, Namespace.getNamespace(Namespace.XMLNS_NAMESPACE.getPrefix(), Namespace.XMLNS_NAMESPACE.getURI())); - - Map m = new HashMap(); - m.put("foo", "http://foo.org/ns/foo"); - m.put("", "http://foo.org/ns/foo"); - m.put("off", "http://foo.org/ns/foo"); - m.put("off", ""); - - for (String prefix: m.keySet()) { - String uri = m.get(prefix); - Namespace ns = Namespace.getNamespace(prefix, uri); - assertEquals(prefix, ns.getPrefix()); - assertEquals(uri, ns.getURI()); - assertEquals(ns, Namespace.getNamespace(prefix, uri)); - } - } - - public void testIsSame() { - Map same = new HashMap(); - same.put("http://foo.org/ns/foo", Namespace.getNamespace("foo", "http://foo.org/ns/foo")); - same.put("http://foo.org/ns/foo", Namespace.getNamespace("abc", "http://foo.org/ns/foo")); - same.put("http://foo.org/ns/foo", Namespace.getNamespace("", "http://foo.org/ns/foo")); - same.put("http://foo.org/ns/foo", Namespace.getNamespace(null, "http://foo.org/ns/foo")); - same.put("", Namespace.EMPTY_NAMESPACE); - same.put(null, Namespace.EMPTY_NAMESPACE); - same.put(Namespace.XML_NAMESPACE.getURI(), Namespace.XML_NAMESPACE); - same.put(Namespace.XMLNS_NAMESPACE.getURI(), Namespace.XMLNS_NAMESPACE); - - for (String nsURI : same.keySet()) { - assertTrue(nsURI, same.get(nsURI).isSame(nsURI)); - } - - Map notSame = new HashMap(); - notSame.put("http://foo.org/ns/abc", Namespace.getNamespace("foo", "http://foo.org/ns/foo")); - notSame.put("", Namespace.getNamespace("abc", "http://foo.org/ns/foo")); - notSame.put(null, Namespace.getNamespace("", "http://foo.org/ns/foo")); - notSame.put("http://foo.org/ns/abc", Namespace.EMPTY_NAMESPACE); - notSame.put(Namespace.XML_NAMESPACE.getURI(), Namespace.EMPTY_NAMESPACE); - notSame.put(Namespace.EMPTY_NAMESPACE.getURI(), Namespace.XML_NAMESPACE); - notSame.put(Namespace.XMLNS_NAMESPACE.getURI(), Namespace.XML_NAMESPACE); - notSame.put(Namespace.XML_NAMESPACE.getURI(), Namespace.XMLNS_NAMESPACE); - - for (String nsURI : notSame.keySet()) { - assertFalse(notSame.get(nsURI).isSame(nsURI)); - } - } - - public void testEquals() { - assertEquals(Namespace.EMPTY_NAMESPACE, Namespace.getNamespace("prefix", "")); - assertEquals(Namespace.EMPTY_NAMESPACE, Namespace.getNamespace("prefix", null)); - - assertFalse(Namespace.EMPTY_NAMESPACE.equals(Namespace.getNamespace("", "something"))); - assertFalse(Namespace.EMPTY_NAMESPACE.equals(Namespace.getNamespace(null, "something"))); - } -} \ No newline at end of file Property changes on: jackrabbit-webdav/src/test/java/org/apache/jackrabbit/webdav/xml/NamespaceTest.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Deleted: svn:keywords ## -1 +0,0 ## -Author Date Id Revision Rev URL \ No newline at end of property Index: jackrabbit-webdav/src/test/java/org/apache/jackrabbit/webdav/xml/ParserTest.java =================================================================== --- jackrabbit-webdav/src/test/java/org/apache/jackrabbit/webdav/xml/ParserTest.java (revision 1907912) +++ jackrabbit-webdav/src/test/java/org/apache/jackrabbit/webdav/xml/ParserTest.java (nonexistent) @@ -1,143 +0,0 @@ -/* - * 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.webdav.xml; - -import java.io.ByteArrayInputStream; -import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.io.UnsupportedEncodingException; - -import javax.xml.parsers.DocumentBuilder; -import javax.xml.parsers.DocumentBuilderFactory; -import javax.xml.parsers.ParserConfigurationException; - -import junit.framework.TestCase; - -import org.w3c.dom.Document; -import org.w3c.dom.Element; -import org.xml.sax.EntityResolver; -import org.xml.sax.InputSource; -import org.xml.sax.SAXException; - -public class ParserTest extends TestCase { - - // see - public void testBillionLaughs() throws UnsupportedEncodingException { - - String testBody = "" + "" + " " - + " " - + " " - + " " - + " " - + " " - + " " - + " " - + " " - + " " + "]>" + "&lol9;"; - InputStream is = new ByteArrayInputStream(testBody.getBytes("UTF-8")); - - try { - DomUtil.parseDocument(is); - fail("parsing this document should cause an exception"); - } catch (Exception expected) { - } - } - - public void testExternalEntities() throws IOException { - - String dname = "target"; - String fname = "test.xml"; - - File f = new File(dname, fname); - OutputStream os = new FileOutputStream(f); - os.write("testdata".getBytes()); - os.close(); - - String testBody = "\n" - + "]>\n&test;"; - InputStream is = new ByteArrayInputStream(testBody.getBytes("UTF-8")); - - try { - Document d = DomUtil.parseDocument(is); - Element root = d.getDocumentElement(); - String text = DomUtil.getText(root); - fail("parsing this document should cause an exception, but the following external content was included: " + text); - } catch (Exception expected) { - } - } - - public void testCustomEntityResolver() throws ParserConfigurationException, SAXException, IOException { - - try { - DocumentBuilderFactory dbf = new DocumentBuilderFactory() { - - DocumentBuilderFactory def = DocumentBuilderFactory.newInstance(); - - @Override - public void setFeature(String name, boolean value) throws ParserConfigurationException { - def.setFeature(name, value); - } - - @Override - public void setAttribute(String name, Object value) throws IllegalArgumentException { - def.setAttribute(name, value); - } - - @Override - public DocumentBuilder newDocumentBuilder() throws ParserConfigurationException { - DocumentBuilder db = def.newDocumentBuilder(); - db.setEntityResolver(new EntityResolver() { - @Override - public InputSource resolveEntity(String publicId, String systemId) throws SAXException, IOException { - if ("foo:test".equals(systemId)) { - return new InputSource(new ByteArrayInputStream("foo&bar".getBytes("UTF-8"))); - } else { - return null; - } - } - }); - return db; - } - - @Override - public boolean getFeature(String name) throws ParserConfigurationException { - return def.getFeature(name); - } - - @Override - public Object getAttribute(String name) throws IllegalArgumentException { - return def.getAttribute(name); - } - }; - - DomUtil.setBuilderFactory(dbf); - String testBody = "\n" - + "]>\n&test;"; - InputStream is = new ByteArrayInputStream(testBody.getBytes("UTF-8")); - - Document d = DomUtil.parseDocument(is); - Element root = d.getDocumentElement(); - String text = DomUtil.getText(root); - assertEquals("custom entity resolver apparently not called", "foo&bar", text); - } finally { - DomUtil.setBuilderFactory(null); - } - } -} \ No newline at end of file Property changes on: jackrabbit-webdav/src/test/java/org/apache/jackrabbit/webdav/xml/ParserTest.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-webdav/src/test/java/org/apache/jackrabbit/webdav/xml/TestAll.java =================================================================== --- jackrabbit-webdav/src/test/java/org/apache/jackrabbit/webdav/xml/TestAll.java (revision 1907912) +++ jackrabbit-webdav/src/test/java/org/apache/jackrabbit/webdav/xml/TestAll.java (nonexistent) @@ -1,40 +0,0 @@ -/* - * 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.webdav.xml; - -import junit.framework.Test; -import junit.framework.TestCase; -import junit.framework.TestSuite; - -/** - * Test suite that includes all testcases for package org.apache.jackrabbit.webdav.xml. - */ -public class TestAll extends TestCase { - - /** - * Returns a Test suite that executes all tests inside this - * package. - */ - public static Test suite() { - TestSuite suite = new TestSuite("org.apache.jackrabbit.webdav.xml tests"); - - suite.addTestSuite(NamespaceTest.class); - suite.addTestSuite(ParserTest.class); - - return suite; - } -} Property changes on: jackrabbit-webdav/src/test/java/org/apache/jackrabbit/webdav/xml/TestAll.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Deleted: svn:keywords ## -1 +0,0 ## -Author Date Id Revision Rev URL \ No newline at end of property Index: jackrabbit-webdav/src/test/resources/logback-test.xml =================================================================== --- jackrabbit-webdav/src/test/resources/logback-test.xml (revision 1907912) +++ jackrabbit-webdav/src/test/resources/logback-test.xml (nonexistent) @@ -1,31 +0,0 @@ - - - - - - target/jcr.log - - %date{HH:mm:ss.SSS} %-5level %-40([%thread] %F:%L) %msg%n - - - - - - - - Property changes on: jackrabbit-webdav/src/test/resources/logback-test.xml ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-webdav =================================================================== --- jackrabbit-webdav (revision 1907912) +++ jackrabbit-webdav (nonexistent) Property changes on: jackrabbit-webdav ___________________________________________________________________ Deleted: svn:ignore ## -1,5 +0,0 ## -target -.* -*.iws -*.ipr -*.iml Index: jackrabbit-jcr-server-project/jackrabbit-jcr-server-jakarta/.classpath =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server-jakarta/.classpath (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server-jakarta/.classpath (working copy) @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Index: jackrabbit-jcr-server-project/jackrabbit-jcr-server-jakarta/.project =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server-jakarta/.project (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server-jakarta/.project (working copy) @@ -0,0 +1,23 @@ + + + jackrabbit-jcr-server-jakarta + + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.m2e.core.maven2Builder + + + + + + org.eclipse.jdt.core.javanature + org.eclipse.m2e.core.maven2Nature + + Index: jackrabbit-jcr-server-project/jackrabbit-jcr-server-jakarta/.settings/org.eclipse.core.resources.prefs =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server-jakarta/.settings/org.eclipse.core.resources.prefs (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server-jakarta/.settings/org.eclipse.core.resources.prefs (working copy) @@ -0,0 +1,6 @@ +eclipse.preferences.version=1 +encoding//src/main/java=UTF-8 +encoding//src/main/resources=UTF-8 +encoding//src/test/java=UTF-8 +encoding//src/test/resources=UTF-8 +encoding/=UTF-8 Index: jackrabbit-jcr-server-project/jackrabbit-jcr-server-jakarta/.settings/org.eclipse.jdt.core.prefs =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server-jakarta/.settings/org.eclipse.jdt.core.prefs (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server-jakarta/.settings/org.eclipse.jdt.core.prefs (working copy) @@ -0,0 +1,8 @@ +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 +org.eclipse.jdt.core.compiler.compliance=1.8 +org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled +org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning +org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=ignore +org.eclipse.jdt.core.compiler.release=disabled +org.eclipse.jdt.core.compiler.source=1.8 Index: jackrabbit-jcr-server-project/jackrabbit-jcr-server-jakarta/.settings/org.eclipse.m2e.core.prefs =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server-jakarta/.settings/org.eclipse.m2e.core.prefs (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server-jakarta/.settings/org.eclipse.m2e.core.prefs (working copy) @@ -0,0 +1,4 @@ +activeProfiles= +eclipse.preferences.version=1 +resolveWorkspaceProjects=true +version=1 Index: jackrabbit-jcr-server-project/jackrabbit-jcr-server-jakarta/pom.xml =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server-jakarta/pom.xml (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server-jakarta/pom.xml (working copy) @@ -0,0 +1,88 @@ + + 4.0.0 + + org.apache.jackrabbit + jackrabbit-jcr-server-project + 2.21.16-SNAPSHOT + + jackrabbit-jcr-server-jakarta + + + + org.eclipse.transformer + transformer-maven-plugin + 0.5.0 + true + + + true + + + + + default-jar + + jar + + + + org.apache.jackrabbit + jackrabbit-jcr-server + ${project.version} + + + + + + + + + + apache-release + + + + org.eclipse.transformer + transformer-maven-plugin + 0.5.0 + true + + + true + + + + + source-jar + + jar + + + + org.apache.jackrabbit + jackrabbit-jcr-server + ${project.version} + sources + + + + + + + + + + + + org.apache.jackrabbit + jackrabbit-webdav-jakarta + ${project.version} + + + jakarta.servlet + jakarta.servlet-api + 5.0.0 + provided + + + \ No newline at end of file Index: jackrabbit-jcr-server-project/jackrabbit-jcr-server-jakarta/target/.plxarc =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server-jakarta/target/.plxarc (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server-jakarta/target/.plxarc (working copy) @@ -0,0 +1 @@ +maven-shared-archive-resources \ No newline at end of file Index: jackrabbit-jcr-server-project/jackrabbit-jcr-server-jakarta/target/classes/META-INF/DEPENDENCIES =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server-jakarta/target/classes/META-INF/DEPENDENCIES (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server-jakarta/target/classes/META-INF/DEPENDENCIES (working copy) @@ -0,0 +1,47 @@ +// ------------------------------------------------------------------ +// Transitive dependencies of this project determined from the +// maven pom organized by organization. +// ------------------------------------------------------------------ + +jackrabbit-jcr-server-jakarta + + +From: 'QOS.ch' (http://www.qos.ch) + - JCL 1.2 implemented over SLF4J (http://www.slf4j.org) org.slf4j:jcl-over-slf4j:jar:1.7.36 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - SLF4J API Module (http://www.slf4j.org) org.slf4j:slf4j-api:jar:1.7.36 + License: MIT License (http://www.opensource.org/licenses/mit-license.php) + +From: 'The Apache Software Foundation' (http://www.apache.org) + - Apache Tika core (https://tika.apache.org/) org.apache.tika:tika-core:bundle:2.4.1 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + +From: 'The Apache Software Foundation' (http://www.apache.org/) + - Apache Commons Logging (http://commons.apache.org/proper/commons-logging/) commons-logging:commons-logging:jar:1.2 + License: The Apache Software License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache HttpClient (http://hc.apache.org/httpcomponents-client-ga) org.apache.httpcomponents:httpclient:jar:4.5.14 + License: Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache HttpCore (http://hc.apache.org/httpcomponents-core-ga) org.apache.httpcomponents:httpcore:jar:4.4.16 + License: Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt) + +From: 'The Apache Software Foundation' (https://www.apache.org/) + - Apache Commons Codec (http://commons.apache.org/proper/commons-codec/) commons-codec:commons-codec:jar:1.11 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Commons FileUpload (https://commons.apache.org/proper/commons-fileupload/) commons-fileupload:commons-fileupload:jar:1.5 + License: Apache-2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Commons IO (https://commons.apache.org/proper/commons-io/) commons-io:commons-io:jar:2.11.0 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Commons Collections (https://commons.apache.org/proper/commons-collections/) org.apache.commons:commons-collections4:jar:4.4 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Jackrabbit JCR Commons (http://jackrabbit.apache.org/jackrabbit-jcr-commons/) org.apache.jackrabbit:jackrabbit-jcr-commons:bundle:2.21.16-SNAPSHOT + License: Apache-2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Jackrabbit SPI (http://jackrabbit.apache.org/jackrabbit-spi/) org.apache.jackrabbit:jackrabbit-spi:bundle:2.21.16-SNAPSHOT + License: Apache-2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Jackrabbit SPI Commons (http://jackrabbit.apache.org/jackrabbit-spi-commons/) org.apache.jackrabbit:jackrabbit-spi-commons:bundle:2.21.16-SNAPSHOT + License: Apache-2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - jackrabbit-webdav-jakarta (http://jackrabbit.apache.org/jackrabbit-webdav-project/jackrabbit-webdav-jakarta/) org.apache.jackrabbit:jackrabbit-webdav-jakarta:jar:2.21.16-SNAPSHOT + License: Apache-2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + + + + Index: jackrabbit-jcr-server-project/jackrabbit-jcr-server-jakarta/target/classes/META-INF/LICENSE =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server-jakarta/target/classes/META-INF/LICENSE (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server-jakarta/target/classes/META-INF/LICENSE (working copy) @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed 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. Index: jackrabbit-jcr-server-project/jackrabbit-jcr-server-jakarta/target/classes/META-INF/NOTICE =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server-jakarta/target/classes/META-INF/NOTICE (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server-jakarta/target/classes/META-INF/NOTICE (working copy) @@ -0,0 +1,8 @@ + +jackrabbit-jcr-server-jakarta +Copyright 2004-1970 The Apache Software Foundation + +This product includes software developed at +The Apache Software Foundation (http://www.apache.org/). + + Index: jackrabbit-jcr-server-project/jackrabbit-jcr-server-jakarta/target/classes/META-INF/maven/org.apache.jackrabbit/jackrabbit-jcr-server-jakarta/pom.properties =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server-jakarta/target/classes/META-INF/maven/org.apache.jackrabbit/jackrabbit-jcr-server-jakarta/pom.properties (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server-jakarta/target/classes/META-INF/maven/org.apache.jackrabbit/jackrabbit-jcr-server-jakarta/pom.properties (working copy) @@ -0,0 +1,7 @@ +#Generated by Maven Integration for Eclipse +#Wed Mar 01 12:32:10 CET 2023 +m2e.projectLocation=C\:\\Development\\JackRabbit\\trunk\\jackrabbit-jcr-server-project\\jackrabbit-jcr-server-jakarta +m2e.projectName=jackrabbit-jcr-server-jakarta +groupId=org.apache.jackrabbit +artifactId=jackrabbit-jcr-server-jakarta +version=2.21.16-SNAPSHOT Index: jackrabbit-jcr-server-project/jackrabbit-jcr-server-jakarta/target/classes/META-INF/maven/org.apache.jackrabbit/jackrabbit-jcr-server-jakarta/pom.xml =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server-jakarta/target/classes/META-INF/maven/org.apache.jackrabbit/jackrabbit-jcr-server-jakarta/pom.xml (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server-jakarta/target/classes/META-INF/maven/org.apache.jackrabbit/jackrabbit-jcr-server-jakarta/pom.xml (working copy) @@ -0,0 +1,88 @@ + + 4.0.0 + + org.apache.jackrabbit + jackrabbit-jcr-server-project + 2.21.16-SNAPSHOT + + jackrabbit-jcr-server-jakarta + + + + org.eclipse.transformer + transformer-maven-plugin + 0.5.0 + true + + + true + + + + + default-jar + + jar + + + + org.apache.jackrabbit + jackrabbit-jcr-server + ${project.version} + + + + + + + + + + apache-release + + + + org.eclipse.transformer + transformer-maven-plugin + 0.5.0 + true + + + true + + + + + source-jar + + jar + + + + org.apache.jackrabbit + jackrabbit-jcr-server + ${project.version} + sources + + + + + + + + + + + + org.apache.jackrabbit + jackrabbit-webdav-jakarta + ${project.version} + + + jakarta.servlet + jakarta.servlet-api + 5.0.0 + provided + + + \ No newline at end of file Index: jackrabbit-jcr-server-project/jackrabbit-jcr-server-jakarta/target/jackrabbit-jcr-server-jakarta-2.21.16-SNAPSHOT.jar =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Property changes on: jackrabbit-jcr-server-project/jackrabbit-jcr-server-jakarta/target/jackrabbit-jcr-server-jakarta-2.21.16-SNAPSHOT.jar ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: jackrabbit-jcr-server-project/jackrabbit-jcr-server-jakarta/target/maven-shared-archive-resources/META-INF/DEPENDENCIES =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server-jakarta/target/maven-shared-archive-resources/META-INF/DEPENDENCIES (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server-jakarta/target/maven-shared-archive-resources/META-INF/DEPENDENCIES (working copy) @@ -0,0 +1,47 @@ +// ------------------------------------------------------------------ +// Transitive dependencies of this project determined from the +// maven pom organized by organization. +// ------------------------------------------------------------------ + +jackrabbit-jcr-server-jakarta + + +From: 'QOS.ch' (http://www.qos.ch) + - JCL 1.2 implemented over SLF4J (http://www.slf4j.org) org.slf4j:jcl-over-slf4j:jar:1.7.36 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - SLF4J API Module (http://www.slf4j.org) org.slf4j:slf4j-api:jar:1.7.36 + License: MIT License (http://www.opensource.org/licenses/mit-license.php) + +From: 'The Apache Software Foundation' (http://www.apache.org) + - Apache Tika core (https://tika.apache.org/) org.apache.tika:tika-core:bundle:2.4.1 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + +From: 'The Apache Software Foundation' (http://www.apache.org/) + - Apache Commons Logging (http://commons.apache.org/proper/commons-logging/) commons-logging:commons-logging:jar:1.2 + License: The Apache Software License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache HttpClient (http://hc.apache.org/httpcomponents-client-ga) org.apache.httpcomponents:httpclient:jar:4.5.14 + License: Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache HttpCore (http://hc.apache.org/httpcomponents-core-ga) org.apache.httpcomponents:httpcore:jar:4.4.16 + License: Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt) + +From: 'The Apache Software Foundation' (https://www.apache.org/) + - Apache Commons Codec (http://commons.apache.org/proper/commons-codec/) commons-codec:commons-codec:jar:1.11 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Commons FileUpload (https://commons.apache.org/proper/commons-fileupload/) commons-fileupload:commons-fileupload:jar:1.5 + License: Apache-2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Commons IO (https://commons.apache.org/proper/commons-io/) commons-io:commons-io:jar:2.11.0 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Commons Collections (https://commons.apache.org/proper/commons-collections/) org.apache.commons:commons-collections4:jar:4.4 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Jackrabbit JCR Commons (http://jackrabbit.apache.org/jackrabbit-jcr-commons/) org.apache.jackrabbit:jackrabbit-jcr-commons:bundle:2.21.16-SNAPSHOT + License: Apache-2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Jackrabbit SPI (http://jackrabbit.apache.org/jackrabbit-spi/) org.apache.jackrabbit:jackrabbit-spi:bundle:2.21.16-SNAPSHOT + License: Apache-2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Jackrabbit SPI Commons (http://jackrabbit.apache.org/jackrabbit-spi-commons/) org.apache.jackrabbit:jackrabbit-spi-commons:bundle:2.21.16-SNAPSHOT + License: Apache-2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - jackrabbit-webdav-jakarta (http://jackrabbit.apache.org/jackrabbit-webdav-project/jackrabbit-webdav-jakarta/) org.apache.jackrabbit:jackrabbit-webdav-jakarta:jar:2.21.16-SNAPSHOT + License: Apache-2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + + + + Index: jackrabbit-jcr-server-project/jackrabbit-jcr-server-jakarta/target/maven-shared-archive-resources/META-INF/LICENSE =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server-jakarta/target/maven-shared-archive-resources/META-INF/LICENSE (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server-jakarta/target/maven-shared-archive-resources/META-INF/LICENSE (working copy) @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed 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. Index: jackrabbit-jcr-server-project/jackrabbit-jcr-server-jakarta/target/maven-shared-archive-resources/META-INF/NOTICE =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server-jakarta/target/maven-shared-archive-resources/META-INF/NOTICE (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server-jakarta/target/maven-shared-archive-resources/META-INF/NOTICE (working copy) @@ -0,0 +1,8 @@ + +jackrabbit-jcr-server-jakarta +Copyright 2004-1970 The Apache Software Foundation + +This product includes software developed at +The Apache Software Foundation (http://www.apache.org/). + + Index: jackrabbit-jcr-server-project/jackrabbit-jcr-server-jakarta/target/maven-status/maven-compiler-plugin/compile/default-compile/createdFiles.lst =================================================================== Index: jackrabbit-jcr-server-project/jackrabbit-jcr-server-jakarta/target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst =================================================================== Index: jackrabbit-jcr-server-project/jackrabbit-jcr-server-jakarta/target/maven-status/maven-compiler-plugin/testCompile/default-testCompile/createdFiles.lst =================================================================== Index: jackrabbit-jcr-server-project/jackrabbit-jcr-server-jakarta/target/maven-status/maven-compiler-plugin/testCompile/default-testCompile/inputFiles.lst =================================================================== Index: jackrabbit-jcr-server-project/jackrabbit-jcr-server-jakarta/target/test-classes/META-INF/DEPENDENCIES =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server-jakarta/target/test-classes/META-INF/DEPENDENCIES (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server-jakarta/target/test-classes/META-INF/DEPENDENCIES (working copy) @@ -0,0 +1,47 @@ +// ------------------------------------------------------------------ +// Transitive dependencies of this project determined from the +// maven pom organized by organization. +// ------------------------------------------------------------------ + +jackrabbit-jcr-server-jakarta + + +From: 'QOS.ch' (http://www.qos.ch) + - JCL 1.2 implemented over SLF4J (http://www.slf4j.org) org.slf4j:jcl-over-slf4j:jar:1.7.36 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - SLF4J API Module (http://www.slf4j.org) org.slf4j:slf4j-api:jar:1.7.36 + License: MIT License (http://www.opensource.org/licenses/mit-license.php) + +From: 'The Apache Software Foundation' (http://www.apache.org) + - Apache Tika core (https://tika.apache.org/) org.apache.tika:tika-core:bundle:2.4.1 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + +From: 'The Apache Software Foundation' (http://www.apache.org/) + - Apache Commons Logging (http://commons.apache.org/proper/commons-logging/) commons-logging:commons-logging:jar:1.2 + License: The Apache Software License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache HttpClient (http://hc.apache.org/httpcomponents-client-ga) org.apache.httpcomponents:httpclient:jar:4.5.14 + License: Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache HttpCore (http://hc.apache.org/httpcomponents-core-ga) org.apache.httpcomponents:httpcore:jar:4.4.16 + License: Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt) + +From: 'The Apache Software Foundation' (https://www.apache.org/) + - Apache Commons Codec (http://commons.apache.org/proper/commons-codec/) commons-codec:commons-codec:jar:1.11 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Commons FileUpload (https://commons.apache.org/proper/commons-fileupload/) commons-fileupload:commons-fileupload:jar:1.5 + License: Apache-2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Commons IO (https://commons.apache.org/proper/commons-io/) commons-io:commons-io:jar:2.11.0 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Commons Collections (https://commons.apache.org/proper/commons-collections/) org.apache.commons:commons-collections4:jar:4.4 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Jackrabbit JCR Commons (http://jackrabbit.apache.org/jackrabbit-jcr-commons/) org.apache.jackrabbit:jackrabbit-jcr-commons:bundle:2.21.16-SNAPSHOT + License: Apache-2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Jackrabbit SPI (http://jackrabbit.apache.org/jackrabbit-spi/) org.apache.jackrabbit:jackrabbit-spi:bundle:2.21.16-SNAPSHOT + License: Apache-2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Jackrabbit SPI Commons (http://jackrabbit.apache.org/jackrabbit-spi-commons/) org.apache.jackrabbit:jackrabbit-spi-commons:bundle:2.21.16-SNAPSHOT + License: Apache-2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - jackrabbit-webdav-jakarta (http://jackrabbit.apache.org/jackrabbit-webdav-project/jackrabbit-webdav-jakarta/) org.apache.jackrabbit:jackrabbit-webdav-jakarta:jar:2.21.16-SNAPSHOT + License: Apache-2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + + + + Index: jackrabbit-jcr-server-project/jackrabbit-jcr-server-jakarta/target/test-classes/META-INF/LICENSE =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server-jakarta/target/test-classes/META-INF/LICENSE (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server-jakarta/target/test-classes/META-INF/LICENSE (working copy) @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed 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. Index: jackrabbit-jcr-server-project/jackrabbit-jcr-server-jakarta/target/test-classes/META-INF/NOTICE =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server-jakarta/target/test-classes/META-INF/NOTICE (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server-jakarta/target/test-classes/META-INF/NOTICE (working copy) @@ -0,0 +1,8 @@ + +jackrabbit-jcr-server-jakarta +Copyright 2004-1970 The Apache Software Foundation + +This product includes software developed at +The Apache Software Foundation (http://www.apache.org/). + + 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: + *

+     * <servlet-mapping>
+     *   <servlet-name>Repository</servlet-name>
+     *   <url-pattern>/repository/*</url-pattern>
+     * </servlet-mapping>
+     * 
+ *

+ * 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. + *

+ * A typical way to use this class would be: + *

+ * public class MyServlet extends HttpServlet {
+ *
+ *     private final Repository repository = new ServletRepository(this);
+ *
+ *     protected void doGet(
+ *             HttpServletRequest request, HttpServletResponse response)
+ *             throws ServletException, IOException {
+ *          try {
+ *              Session session = repository.login();
+ *              try {
+ *                  ...;
+ *              } finally {
+ *                  session.logout();
+ *              }
+ *          } catch (RepositoryException e) {
+ *              throw new ServletException(e);
+ *          }
+ *      }
+ *
+ * }
+ * 
+ *

+ * Starting with version 1.6 this class can also be used by a servlet filter: + *

+ * public class MyFilter implements Filter {
+ *
+ *     private Repository repository;
+ *
+ *     public void init(FilterConfig config) {
+ *         repository = new ServletRepository(config);
+ *     }
+ *
+ *     // ...
+ *
+ * }
+ * 
+ + * + * @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". + *
+ *
org.apache.jackrabbit.rmi.server.RemoteAdapterFactory
+ *
+ * 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". + *
+ *
org.apache.jackrabbit.rmi.client.LocalAdapterFactory
+ *
+ * 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". + *
+ *
org.apache.jackrabbit.rmi.server.RemoteAdapterFactory
+ *
+ * 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". + *
+ *
org.apache.jackrabbit.rmi.client.LocalAdapterFactory
+ *
+ * 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". + *
+ *
org.apache.jackrabbit.rmi.server.RemoteAdapterFactory
+ *
+ * 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". + *
+ *
org.apache.jackrabbit.rmi.client.LocalAdapterFactory
+ *
+ * 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". + *
+ *
org.apache.jackrabbit.rmi.server.RemoteAdapterFactory
+ *
+ * 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". + *
+ *
org.apache.jackrabbit.rmi.client.LocalAdapterFactory
+ *
+ * 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/jackrabbit-jcr-servlet-jakarta/.classpath =================================================================== --- jackrabbit-jcr-servlet-project/jackrabbit-jcr-servlet-jakarta/.classpath (nonexistent) +++ jackrabbit-jcr-servlet-project/jackrabbit-jcr-servlet-jakarta/.classpath (working copy) @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Index: jackrabbit-jcr-servlet-project/jackrabbit-jcr-servlet-jakarta/.project =================================================================== --- jackrabbit-jcr-servlet-project/jackrabbit-jcr-servlet-jakarta/.project (nonexistent) +++ jackrabbit-jcr-servlet-project/jackrabbit-jcr-servlet-jakarta/.project (working copy) @@ -0,0 +1,23 @@ + + + jackrabbit-jcr-servlet-jakarta + + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.m2e.core.maven2Builder + + + + + + org.eclipse.jdt.core.javanature + org.eclipse.m2e.core.maven2Nature + + Index: jackrabbit-jcr-servlet-project/jackrabbit-jcr-servlet-jakarta/.settings/org.eclipse.core.resources.prefs =================================================================== --- jackrabbit-jcr-servlet-project/jackrabbit-jcr-servlet-jakarta/.settings/org.eclipse.core.resources.prefs (nonexistent) +++ jackrabbit-jcr-servlet-project/jackrabbit-jcr-servlet-jakarta/.settings/org.eclipse.core.resources.prefs (working copy) @@ -0,0 +1,6 @@ +eclipse.preferences.version=1 +encoding//src/main/java=UTF-8 +encoding//src/main/resources=UTF-8 +encoding//src/test/java=UTF-8 +encoding//src/test/resources=UTF-8 +encoding/=UTF-8 Index: jackrabbit-jcr-servlet-project/jackrabbit-jcr-servlet-jakarta/.settings/org.eclipse.jdt.core.prefs =================================================================== --- jackrabbit-jcr-servlet-project/jackrabbit-jcr-servlet-jakarta/.settings/org.eclipse.jdt.core.prefs (nonexistent) +++ jackrabbit-jcr-servlet-project/jackrabbit-jcr-servlet-jakarta/.settings/org.eclipse.jdt.core.prefs (working copy) @@ -0,0 +1,8 @@ +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 +org.eclipse.jdt.core.compiler.compliance=1.8 +org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled +org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning +org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=ignore +org.eclipse.jdt.core.compiler.release=disabled +org.eclipse.jdt.core.compiler.source=1.8 Index: jackrabbit-jcr-servlet-project/jackrabbit-jcr-servlet-jakarta/.settings/org.eclipse.m2e.core.prefs =================================================================== --- jackrabbit-jcr-servlet-project/jackrabbit-jcr-servlet-jakarta/.settings/org.eclipse.m2e.core.prefs (nonexistent) +++ jackrabbit-jcr-servlet-project/jackrabbit-jcr-servlet-jakarta/.settings/org.eclipse.m2e.core.prefs (working copy) @@ -0,0 +1,4 @@ +activeProfiles= +eclipse.preferences.version=1 +resolveWorkspaceProjects=true +version=1 Index: jackrabbit-jcr-servlet-project/jackrabbit-jcr-servlet-jakarta/pom.xml =================================================================== --- jackrabbit-jcr-servlet-project/jackrabbit-jcr-servlet-jakarta/pom.xml (nonexistent) +++ jackrabbit-jcr-servlet-project/jackrabbit-jcr-servlet-jakarta/pom.xml (working copy) @@ -0,0 +1,83 @@ + + 4.0.0 + + org.apache.jackrabbit + jackrabbit-jcr-servlet-project + 2.21.16-SNAPSHOT + + jackrabbit-jcr-servlet-jakarta + + + + org.eclipse.transformer + transformer-maven-plugin + 0.5.0 + true + + + true + + + + + default-jar + + jar + + + + org.apache.jackrabbit + jackrabbit-jcr-servlet + ${project.version} + + + + + + + + + + apache-release + + + + org.eclipse.transformer + transformer-maven-plugin + 0.5.0 + true + + + true + + + + + source-jar + + jar + + + + org.apache.jackrabbit + jackrabbit-jcr-servlet + ${project.version} + sources + + + + + + + + + + + + jakarta.servlet + jakarta.servlet-api + 5.0.0 + provided + + + \ No newline at end of file Index: jackrabbit-jcr-servlet-project/jackrabbit-jcr-servlet-jakarta/target/.plxarc =================================================================== --- jackrabbit-jcr-servlet-project/jackrabbit-jcr-servlet-jakarta/target/.plxarc (nonexistent) +++ jackrabbit-jcr-servlet-project/jackrabbit-jcr-servlet-jakarta/target/.plxarc (working copy) @@ -0,0 +1 @@ +maven-shared-archive-resources \ No newline at end of file Index: jackrabbit-jcr-servlet-project/jackrabbit-jcr-servlet-jakarta/target/classes/META-INF/DEPENDENCIES =================================================================== --- jackrabbit-jcr-servlet-project/jackrabbit-jcr-servlet-jakarta/target/classes/META-INF/DEPENDENCIES (nonexistent) +++ jackrabbit-jcr-servlet-project/jackrabbit-jcr-servlet-jakarta/target/classes/META-INF/DEPENDENCIES (working copy) @@ -0,0 +1,53 @@ +// ------------------------------------------------------------------ +// Transitive dependencies of this project determined from the +// maven pom organized by organization. +// ------------------------------------------------------------------ + +jackrabbit-jcr-servlet-jakarta + + +From: 'Dough Lea' (http://gee.cs.oswego.edu/dl/classes/EDU/oswego/cs/dl/util/concurrent/intro.html) + - Dough Lea's util.concurrent package concurrent:concurrent:jar:1.3.4 + License: Public domain, Sun Microsoystems (>http://gee.cs.oswego.edu/dl/classes/EDU/oswego/cs/dl/util/concurrent/intro.html) + +From: 'QOS.ch' (http://www.qos.ch) + - JCL 1.2 implemented over SLF4J (http://www.slf4j.org) org.slf4j:jcl-over-slf4j:jar:1.7.36 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - SLF4J API Module (http://www.slf4j.org) org.slf4j:slf4j-api:jar:1.7.36 + License: MIT License (http://www.opensource.org/licenses/mit-license.php) + +From: 'The Apache Software Foundation' (http://www.apache.org) + - Apache Tika core (https://tika.apache.org/) org.apache.tika:tika-core:bundle:2.4.1 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + +From: 'The Apache Software Foundation' (http://www.apache.org/) + - Commons DBCP (http://commons.apache.org/dbcp/) commons-dbcp:commons-dbcp:jar:1.4 + License: The Apache Software License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt) + - Commons Pool (http://commons.apache.org/pool/) commons-pool:commons-pool:jar:1.5.4 + License: The Apache Software License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt) + - Lucene Core (http://lucene.apache.org/java/lucene-parent/lucene-core) org.apache.lucene:lucene-core:jar:3.6.0 + License: Apache 2 (http://www.apache.org/licenses/LICENSE-2.0.txt) + +From: 'The Apache Software Foundation' (https://www.apache.org/) + - Apache Commons IO (https://commons.apache.org/proper/commons-io/) commons-io:commons-io:jar:2.11.0 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Commons Collections (https://commons.apache.org/proper/commons-collections/) org.apache.commons:commons-collections4:jar:4.4 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Jackrabbit Core (http://jackrabbit.apache.org/jackrabbit-core/) org.apache.jackrabbit:jackrabbit-core:jar:2.21.16-SNAPSHOT + License: Apache-2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Jackrabbit Data (http://jackrabbit.apache.org/jackrabbit-data/) org.apache.jackrabbit:jackrabbit-data:bundle:2.21.16-SNAPSHOT + License: Apache-2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Jackrabbit JCR Commons (http://jackrabbit.apache.org/jackrabbit-jcr-commons/) org.apache.jackrabbit:jackrabbit-jcr-commons:bundle:2.21.16-SNAPSHOT + License: Apache-2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Jackrabbit JCR-RMI (http://jackrabbit.apache.org/jackrabbit-jcr-rmi/) org.apache.jackrabbit:jackrabbit-jcr-rmi:bundle:2.21.16-SNAPSHOT + License: Apache-2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Jackrabbit SPI (http://jackrabbit.apache.org/jackrabbit-spi/) org.apache.jackrabbit:jackrabbit-spi:bundle:2.21.16-SNAPSHOT + License: Apache-2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Jackrabbit SPI Commons (http://jackrabbit.apache.org/jackrabbit-spi-commons/) org.apache.jackrabbit:jackrabbit-spi-commons:bundle:2.21.16-SNAPSHOT + License: Apache-2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Jackrabbit API (http://jackrabbit.apache.org/oak-jackrabbit-api/) org.apache.jackrabbit:oak-jackrabbit-api:bundle:1.48.0 + License: Apache-2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + + + + Index: jackrabbit-jcr-servlet-project/jackrabbit-jcr-servlet-jakarta/target/classes/META-INF/LICENSE =================================================================== --- jackrabbit-jcr-servlet-project/jackrabbit-jcr-servlet-jakarta/target/classes/META-INF/LICENSE (nonexistent) +++ jackrabbit-jcr-servlet-project/jackrabbit-jcr-servlet-jakarta/target/classes/META-INF/LICENSE (working copy) @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed 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. Index: jackrabbit-jcr-servlet-project/jackrabbit-jcr-servlet-jakarta/target/classes/META-INF/NOTICE =================================================================== --- jackrabbit-jcr-servlet-project/jackrabbit-jcr-servlet-jakarta/target/classes/META-INF/NOTICE (nonexistent) +++ jackrabbit-jcr-servlet-project/jackrabbit-jcr-servlet-jakarta/target/classes/META-INF/NOTICE (working copy) @@ -0,0 +1,8 @@ + +jackrabbit-jcr-servlet-jakarta +Copyright 2004-1970 The Apache Software Foundation + +This product includes software developed at +The Apache Software Foundation (http://www.apache.org/). + + Index: jackrabbit-jcr-servlet-project/jackrabbit-jcr-servlet-jakarta/target/classes/META-INF/maven/org.apache.jackrabbit/jackrabbit-jcr-servlet-jakarta/pom.properties =================================================================== --- jackrabbit-jcr-servlet-project/jackrabbit-jcr-servlet-jakarta/target/classes/META-INF/maven/org.apache.jackrabbit/jackrabbit-jcr-servlet-jakarta/pom.properties (nonexistent) +++ jackrabbit-jcr-servlet-project/jackrabbit-jcr-servlet-jakarta/target/classes/META-INF/maven/org.apache.jackrabbit/jackrabbit-jcr-servlet-jakarta/pom.properties (working copy) @@ -0,0 +1,7 @@ +#Generated by Maven Integration for Eclipse +#Wed Mar 01 12:32:52 CET 2023 +m2e.projectLocation=C\:\\Development\\JackRabbit\\trunk\\jackrabbit-jcr-servlet-project\\jackrabbit-jcr-servlet-jakarta +m2e.projectName=jackrabbit-jcr-servlet-jakarta +groupId=org.apache.jackrabbit +artifactId=jackrabbit-jcr-servlet-jakarta +version=2.21.16-SNAPSHOT Index: jackrabbit-jcr-servlet-project/jackrabbit-jcr-servlet-jakarta/target/classes/META-INF/maven/org.apache.jackrabbit/jackrabbit-jcr-servlet-jakarta/pom.xml =================================================================== --- jackrabbit-jcr-servlet-project/jackrabbit-jcr-servlet-jakarta/target/classes/META-INF/maven/org.apache.jackrabbit/jackrabbit-jcr-servlet-jakarta/pom.xml (nonexistent) +++ jackrabbit-jcr-servlet-project/jackrabbit-jcr-servlet-jakarta/target/classes/META-INF/maven/org.apache.jackrabbit/jackrabbit-jcr-servlet-jakarta/pom.xml (working copy) @@ -0,0 +1,83 @@ + + 4.0.0 + + org.apache.jackrabbit + jackrabbit-jcr-servlet-project + 2.21.16-SNAPSHOT + + jackrabbit-jcr-servlet-jakarta + + + + org.eclipse.transformer + transformer-maven-plugin + 0.5.0 + true + + + true + + + + + default-jar + + jar + + + + org.apache.jackrabbit + jackrabbit-jcr-servlet + ${project.version} + + + + + + + + + + apache-release + + + + org.eclipse.transformer + transformer-maven-plugin + 0.5.0 + true + + + true + + + + + source-jar + + jar + + + + org.apache.jackrabbit + jackrabbit-jcr-servlet + ${project.version} + sources + + + + + + + + + + + + jakarta.servlet + jakarta.servlet-api + 5.0.0 + provided + + + \ No newline at end of file Index: jackrabbit-jcr-servlet-project/jackrabbit-jcr-servlet-jakarta/target/jackrabbit-jcr-servlet-jakarta-2.21.16-SNAPSHOT.jar =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Property changes on: jackrabbit-jcr-servlet-project/jackrabbit-jcr-servlet-jakarta/target/jackrabbit-jcr-servlet-jakarta-2.21.16-SNAPSHOT.jar ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: jackrabbit-jcr-servlet-project/jackrabbit-jcr-servlet-jakarta/target/maven-shared-archive-resources/META-INF/DEPENDENCIES =================================================================== --- jackrabbit-jcr-servlet-project/jackrabbit-jcr-servlet-jakarta/target/maven-shared-archive-resources/META-INF/DEPENDENCIES (nonexistent) +++ jackrabbit-jcr-servlet-project/jackrabbit-jcr-servlet-jakarta/target/maven-shared-archive-resources/META-INF/DEPENDENCIES (working copy) @@ -0,0 +1,53 @@ +// ------------------------------------------------------------------ +// Transitive dependencies of this project determined from the +// maven pom organized by organization. +// ------------------------------------------------------------------ + +jackrabbit-jcr-servlet-jakarta + + +From: 'Dough Lea' (http://gee.cs.oswego.edu/dl/classes/EDU/oswego/cs/dl/util/concurrent/intro.html) + - Dough Lea's util.concurrent package concurrent:concurrent:jar:1.3.4 + License: Public domain, Sun Microsoystems (>http://gee.cs.oswego.edu/dl/classes/EDU/oswego/cs/dl/util/concurrent/intro.html) + +From: 'QOS.ch' (http://www.qos.ch) + - JCL 1.2 implemented over SLF4J (http://www.slf4j.org) org.slf4j:jcl-over-slf4j:jar:1.7.36 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - SLF4J API Module (http://www.slf4j.org) org.slf4j:slf4j-api:jar:1.7.36 + License: MIT License (http://www.opensource.org/licenses/mit-license.php) + +From: 'The Apache Software Foundation' (http://www.apache.org) + - Apache Tika core (https://tika.apache.org/) org.apache.tika:tika-core:bundle:2.4.1 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + +From: 'The Apache Software Foundation' (http://www.apache.org/) + - Commons DBCP (http://commons.apache.org/dbcp/) commons-dbcp:commons-dbcp:jar:1.4 + License: The Apache Software License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt) + - Commons Pool (http://commons.apache.org/pool/) commons-pool:commons-pool:jar:1.5.4 + License: The Apache Software License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt) + - Lucene Core (http://lucene.apache.org/java/lucene-parent/lucene-core) org.apache.lucene:lucene-core:jar:3.6.0 + License: Apache 2 (http://www.apache.org/licenses/LICENSE-2.0.txt) + +From: 'The Apache Software Foundation' (https://www.apache.org/) + - Apache Commons IO (https://commons.apache.org/proper/commons-io/) commons-io:commons-io:jar:2.11.0 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Commons Collections (https://commons.apache.org/proper/commons-collections/) org.apache.commons:commons-collections4:jar:4.4 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Jackrabbit Core (http://jackrabbit.apache.org/jackrabbit-core/) org.apache.jackrabbit:jackrabbit-core:jar:2.21.16-SNAPSHOT + License: Apache-2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Jackrabbit Data (http://jackrabbit.apache.org/jackrabbit-data/) org.apache.jackrabbit:jackrabbit-data:bundle:2.21.16-SNAPSHOT + License: Apache-2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Jackrabbit JCR Commons (http://jackrabbit.apache.org/jackrabbit-jcr-commons/) org.apache.jackrabbit:jackrabbit-jcr-commons:bundle:2.21.16-SNAPSHOT + License: Apache-2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Jackrabbit JCR-RMI (http://jackrabbit.apache.org/jackrabbit-jcr-rmi/) org.apache.jackrabbit:jackrabbit-jcr-rmi:bundle:2.21.16-SNAPSHOT + License: Apache-2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Jackrabbit SPI (http://jackrabbit.apache.org/jackrabbit-spi/) org.apache.jackrabbit:jackrabbit-spi:bundle:2.21.16-SNAPSHOT + License: Apache-2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Jackrabbit SPI Commons (http://jackrabbit.apache.org/jackrabbit-spi-commons/) org.apache.jackrabbit:jackrabbit-spi-commons:bundle:2.21.16-SNAPSHOT + License: Apache-2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Jackrabbit API (http://jackrabbit.apache.org/oak-jackrabbit-api/) org.apache.jackrabbit:oak-jackrabbit-api:bundle:1.48.0 + License: Apache-2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + + + + Index: jackrabbit-jcr-servlet-project/jackrabbit-jcr-servlet-jakarta/target/maven-shared-archive-resources/META-INF/LICENSE =================================================================== --- jackrabbit-jcr-servlet-project/jackrabbit-jcr-servlet-jakarta/target/maven-shared-archive-resources/META-INF/LICENSE (nonexistent) +++ jackrabbit-jcr-servlet-project/jackrabbit-jcr-servlet-jakarta/target/maven-shared-archive-resources/META-INF/LICENSE (working copy) @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed 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. Index: jackrabbit-jcr-servlet-project/jackrabbit-jcr-servlet-jakarta/target/maven-shared-archive-resources/META-INF/NOTICE =================================================================== --- jackrabbit-jcr-servlet-project/jackrabbit-jcr-servlet-jakarta/target/maven-shared-archive-resources/META-INF/NOTICE (nonexistent) +++ jackrabbit-jcr-servlet-project/jackrabbit-jcr-servlet-jakarta/target/maven-shared-archive-resources/META-INF/NOTICE (working copy) @@ -0,0 +1,8 @@ + +jackrabbit-jcr-servlet-jakarta +Copyright 2004-1970 The Apache Software Foundation + +This product includes software developed at +The Apache Software Foundation (http://www.apache.org/). + + Index: jackrabbit-jcr-servlet-project/jackrabbit-jcr-servlet-jakarta/target/maven-status/maven-compiler-plugin/compile/default-compile/createdFiles.lst =================================================================== Index: jackrabbit-jcr-servlet-project/jackrabbit-jcr-servlet-jakarta/target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst =================================================================== Index: jackrabbit-jcr-servlet-project/jackrabbit-jcr-servlet-jakarta/target/maven-status/maven-compiler-plugin/testCompile/default-testCompile/createdFiles.lst =================================================================== Index: jackrabbit-jcr-servlet-project/jackrabbit-jcr-servlet-jakarta/target/maven-status/maven-compiler-plugin/testCompile/default-testCompile/inputFiles.lst =================================================================== Index: jackrabbit-jcr-servlet-project/jackrabbit-jcr-servlet-jakarta/target/test-classes/META-INF/DEPENDENCIES =================================================================== --- jackrabbit-jcr-servlet-project/jackrabbit-jcr-servlet-jakarta/target/test-classes/META-INF/DEPENDENCIES (nonexistent) +++ jackrabbit-jcr-servlet-project/jackrabbit-jcr-servlet-jakarta/target/test-classes/META-INF/DEPENDENCIES (working copy) @@ -0,0 +1,53 @@ +// ------------------------------------------------------------------ +// Transitive dependencies of this project determined from the +// maven pom organized by organization. +// ------------------------------------------------------------------ + +jackrabbit-jcr-servlet-jakarta + + +From: 'Dough Lea' (http://gee.cs.oswego.edu/dl/classes/EDU/oswego/cs/dl/util/concurrent/intro.html) + - Dough Lea's util.concurrent package concurrent:concurrent:jar:1.3.4 + License: Public domain, Sun Microsoystems (>http://gee.cs.oswego.edu/dl/classes/EDU/oswego/cs/dl/util/concurrent/intro.html) + +From: 'QOS.ch' (http://www.qos.ch) + - JCL 1.2 implemented over SLF4J (http://www.slf4j.org) org.slf4j:jcl-over-slf4j:jar:1.7.36 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - SLF4J API Module (http://www.slf4j.org) org.slf4j:slf4j-api:jar:1.7.36 + License: MIT License (http://www.opensource.org/licenses/mit-license.php) + +From: 'The Apache Software Foundation' (http://www.apache.org) + - Apache Tika core (https://tika.apache.org/) org.apache.tika:tika-core:bundle:2.4.1 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + +From: 'The Apache Software Foundation' (http://www.apache.org/) + - Commons DBCP (http://commons.apache.org/dbcp/) commons-dbcp:commons-dbcp:jar:1.4 + License: The Apache Software License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt) + - Commons Pool (http://commons.apache.org/pool/) commons-pool:commons-pool:jar:1.5.4 + License: The Apache Software License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt) + - Lucene Core (http://lucene.apache.org/java/lucene-parent/lucene-core) org.apache.lucene:lucene-core:jar:3.6.0 + License: Apache 2 (http://www.apache.org/licenses/LICENSE-2.0.txt) + +From: 'The Apache Software Foundation' (https://www.apache.org/) + - Apache Commons IO (https://commons.apache.org/proper/commons-io/) commons-io:commons-io:jar:2.11.0 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Commons Collections (https://commons.apache.org/proper/commons-collections/) org.apache.commons:commons-collections4:jar:4.4 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Jackrabbit Core (http://jackrabbit.apache.org/jackrabbit-core/) org.apache.jackrabbit:jackrabbit-core:jar:2.21.16-SNAPSHOT + License: Apache-2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Jackrabbit Data (http://jackrabbit.apache.org/jackrabbit-data/) org.apache.jackrabbit:jackrabbit-data:bundle:2.21.16-SNAPSHOT + License: Apache-2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Jackrabbit JCR Commons (http://jackrabbit.apache.org/jackrabbit-jcr-commons/) org.apache.jackrabbit:jackrabbit-jcr-commons:bundle:2.21.16-SNAPSHOT + License: Apache-2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Jackrabbit JCR-RMI (http://jackrabbit.apache.org/jackrabbit-jcr-rmi/) org.apache.jackrabbit:jackrabbit-jcr-rmi:bundle:2.21.16-SNAPSHOT + License: Apache-2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Jackrabbit SPI (http://jackrabbit.apache.org/jackrabbit-spi/) org.apache.jackrabbit:jackrabbit-spi:bundle:2.21.16-SNAPSHOT + License: Apache-2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Jackrabbit SPI Commons (http://jackrabbit.apache.org/jackrabbit-spi-commons/) org.apache.jackrabbit:jackrabbit-spi-commons:bundle:2.21.16-SNAPSHOT + License: Apache-2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Jackrabbit API (http://jackrabbit.apache.org/oak-jackrabbit-api/) org.apache.jackrabbit:oak-jackrabbit-api:bundle:1.48.0 + License: Apache-2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + + + + Index: jackrabbit-jcr-servlet-project/jackrabbit-jcr-servlet-jakarta/target/test-classes/META-INF/LICENSE =================================================================== --- jackrabbit-jcr-servlet-project/jackrabbit-jcr-servlet-jakarta/target/test-classes/META-INF/LICENSE (nonexistent) +++ jackrabbit-jcr-servlet-project/jackrabbit-jcr-servlet-jakarta/target/test-classes/META-INF/LICENSE (working copy) @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed 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. Index: jackrabbit-jcr-servlet-project/jackrabbit-jcr-servlet-jakarta/target/test-classes/META-INF/NOTICE =================================================================== --- jackrabbit-jcr-servlet-project/jackrabbit-jcr-servlet-jakarta/target/test-classes/META-INF/NOTICE (nonexistent) +++ jackrabbit-jcr-servlet-project/jackrabbit-jcr-servlet-jakarta/target/test-classes/META-INF/NOTICE (working copy) @@ -0,0 +1,8 @@ + +jackrabbit-jcr-servlet-jakarta +Copyright 2004-1970 The Apache Software Foundation + +This product includes software developed at +The Apache Software Foundation (http://www.apache.org/). + + 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/README.txt =================================================================== --- jackrabbit-webapp-project/jackrabbit-webapp/README.txt (nonexistent) +++ jackrabbit-webapp-project/jackrabbit-webapp/README.txt (working copy) @@ -0,0 +1,22 @@ +===================================== +Welcome to Jackrabbit Web Application +===================================== + +This is the Web Application component of the Apache Jackrabbit project. +This component provides servlets used to access a Jackrabbit repository: + + * RepositoryAccessServlet.java + * LoggingServlet.java + * RepositoryStartupServlet.java + +In addition, the project contains 2 different WebDAV servlets: + + * SimpleWebdavServlet.java + Adds WebDAV support (DAV 1,2) to your jackrabbit repository. + + * JCRWebdavServerServlet.java + A servlet used to remote JSR170 calls via WebDAV. + IMPORTANT: Please note, that this servlet is not intended to provide + common WebDAV support to the repository. Instead the primary goal is to + remote JSR170 calls. + For the corresponding client see -> jackrabbit-jcr2dav (work in progress). Property changes on: jackrabbit-webapp-project/jackrabbit-webapp/README.txt ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +author date id revision \ No newline at end of property Index: jackrabbit-webapp-project/jackrabbit-webapp/pom.xml =================================================================== --- jackrabbit-webapp-project/jackrabbit-webapp/pom.xml (nonexistent) +++ jackrabbit-webapp-project/jackrabbit-webapp/pom.xml (working copy) @@ -0,0 +1,117 @@ + + + + + + 4.0.0 + + + + + + org.apache.jackrabbit + jackrabbit-webapp-project + 2.21.16-SNAPSHOT + + jackrabbit-webapp + war + Jackrabbit Web Application + Web application that hosts and serves a Jackrabbit content repository + + + + org.apache.jackrabbit + jackrabbit-jcr-server + ${project.version} + + + org.apache.jackrabbit + jackrabbit-jcr-servlet + ${project.version} + + + + + + + + maven-antrun-plugin + + + package + + + + + + + run + + + + + + + org.codehaus.mojo + build-helper-maven-plugin + + + attach-artifacts + package + + attach-artifact + + + + + ${project.build.directory}/jackrabbit-webapp-${project.version}.jar + jar + + + + + + + + org.apache.rat + apache-rat-plugin + + + src/main/webapp/WEB-INF/log4j.dtd + + + + + + + + maven-failsafe-plugin + + + + derby.stream.error.file + target/derby.log + + + + + + + + + Property changes on: jackrabbit-webapp-project/jackrabbit-webapp/pom.xml ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webapp-project/jackrabbit-webapp/src/main/java/org/apache/jackrabbit/j2ee/AbstractConfig.java =================================================================== --- jackrabbit-webapp-project/jackrabbit-webapp/src/main/java/org/apache/jackrabbit/j2ee/AbstractConfig.java (nonexistent) +++ jackrabbit-webapp-project/jackrabbit-webapp/src/main/java/org/apache/jackrabbit/j2ee/AbstractConfig.java (working copy) @@ -0,0 +1,110 @@ +/* + * 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.j2ee; + +import org.apache.commons.beanutils.BeanMap; +import org.apache.jackrabbit.util.Text; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.Enumeration; +import java.util.Iterator; +import java.util.Properties; + +import javax.servlet.ServletConfig; +import javax.servlet.ServletException; + +/** + * Abstract configuration class that is based on a bean map. + */ +public abstract class AbstractConfig { + + /** + * default logger + */ + private static final Logger log = LoggerFactory.getLogger(AbstractConfig.class); + + protected boolean valid; + + private BeanMap map = new BeanMap(this); + + /** + * Initializes the configuration with values from the given properties + * @param props the configuration properties + */ + public void init(Properties props) throws ServletException { + Iterator iter = props.keySet().iterator(); + while (iter.hasNext()) { + String name = (String) iter.next(); + String mapName = toMapName(name, '.'); + try { + if (map.containsKey(mapName)) { + map.put(mapName, props.getProperty(name)); + } + } catch (Exception e) { + throw new ServletExceptionWithCause( + "Invalid configuration property: " + name, e); + } + } + } + + public void init(ServletConfig ctx) throws ServletException { + Enumeration names = ctx.getInitParameterNames(); + while (names.hasMoreElements()) { + String name = (String) names.nextElement(); + String mapName = toMapName(name, '-'); + try { + if (map.containsKey(mapName)) { + map.put(mapName, ctx.getInitParameter(name)); + } + } catch (Exception e) { + throw new ServletExceptionWithCause( + "Invalid servlet configuration option: " + name, e); + } + } + } + + public String toMapName(String name, char delim) { + StringBuffer ret = new StringBuffer(); + String[] elems = Text.explode(name, delim); + ret.append(elems[0]); + for (int i=1; i + * +-------------------+-------------------+ + * | Property Name | Init-Param Name | + * +-------------------+-------------------+ + * | repository.home | repository-home | + * | repository.config | repository-config | + * | repository.name | repository-name | + * +-------------------+-------------------+ + * + */ +public class BootstrapConfig extends AbstractConfig { + + private String repositoryHome; + + private String repositoryConfig; + + private String repositoryName; + + private JNDIConfig jndiConfig = new JNDIConfig(this); + + private RMIConfig rmiConfig = new RMIConfig(this); + + public void init(Properties props) throws ServletException { + super.init(props); + jndiConfig.init(props); + rmiConfig.init(props); + } + + public void init(ServletConfig ctx) throws ServletException { + super.init(ctx); + jndiConfig.init(ctx); + rmiConfig.init(ctx); + } + + public String getRepositoryHome() { + return repositoryHome; + } + + public void setRepositoryHome(String repositoryHome) { + this.repositoryHome = repositoryHome; + } + + public String getRepositoryConfig() { + return repositoryConfig; + } + + public void setRepositoryConfig(String repositoryConfig) { + this.repositoryConfig = repositoryConfig; + } + + public String getRepositoryName() { + return repositoryName; + } + + public void setRepositoryName(String repositoryName) { + this.repositoryName = repositoryName; + } + + public JNDIConfig getJndiConfig() { + return jndiConfig; + } + + public RMIConfig getRmiConfig() { + return rmiConfig; + } + + public void validate() { + valid = repositoryName != null; + jndiConfig.validate(); + rmiConfig.validate(); + } + + + public void logInfos() { + super.logInfos(); + if (jndiConfig.isValid()) { + jndiConfig.logInfos(); + } + if (rmiConfig.isValid()) { + rmiConfig.logInfos(); + } + } +} \ No newline at end of file Property changes on: jackrabbit-webapp-project/jackrabbit-webapp/src/main/java/org/apache/jackrabbit/j2ee/BootstrapConfig.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webapp-project/jackrabbit-webapp/src/main/java/org/apache/jackrabbit/j2ee/DerbyShutdown.java =================================================================== --- jackrabbit-webapp-project/jackrabbit-webapp/src/main/java/org/apache/jackrabbit/j2ee/DerbyShutdown.java (nonexistent) +++ jackrabbit-webapp-project/jackrabbit-webapp/src/main/java/org/apache/jackrabbit/j2ee/DerbyShutdown.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.j2ee; + +import java.lang.reflect.Method; +import java.sql.Driver; +import java.sql.DriverManager; +import java.sql.SQLException; +import java.util.Enumeration; + +import javax.servlet.ServletContextEvent; +import javax.servlet.ServletContextListener; + +/** + * Servlet context listener that releases all remaining Derby resources + * when the web application is undeployed. The resources are released only + * if the Derby classes were loaded from within this webapp. + * + * @see JCR-1301 + */ +public class DerbyShutdown implements ServletContextListener { + + public void contextInitialized(ServletContextEvent event) { + } + + public void contextDestroyed(ServletContextEvent event) { + ClassLoader loader = DerbyShutdown.class.getClassLoader(); + + // Deregister all JDBC drivers loaded from this webapp + Enumeration drivers = DriverManager.getDrivers(); + while (drivers.hasMoreElements()) { + Driver driver = drivers.nextElement(); + // Check if this driver comes from this webapp + if (driver.getClass().getClassLoader() == loader) { + try { + DriverManager.deregisterDriver(driver); + } catch (SQLException ignore) { + } + } + } + + // Explicitly tell Derby to release all remaining resources. + // Use reflection to avoid problems when the Derby is not used. + try { + Class monitorClass = + loader.loadClass("org.apache.derby.iapi.services.monitor.Monitor"); + if (monitorClass.getClassLoader() == loader) { + Method getMonitorMethod = + monitorClass.getMethod("getMonitor", new Class[0]); + Object monitor = + getMonitorMethod.invoke(null, new Object[0]); + if (monitor != null) { + Method shutdownMethod = + monitor.getClass().getMethod("shutdown", new Class[0]); + shutdownMethod.invoke(monitor, new Object[0]); + } + } + } catch (Exception ignore) { + } + } + +} \ No newline at end of file Property changes on: jackrabbit-webapp-project/jackrabbit-webapp/src/main/java/org/apache/jackrabbit/j2ee/DerbyShutdown.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webapp-project/jackrabbit-webapp/src/main/java/org/apache/jackrabbit/j2ee/Installer.java =================================================================== --- jackrabbit-webapp-project/jackrabbit-webapp/src/main/java/org/apache/jackrabbit/j2ee/Installer.java (nonexistent) +++ jackrabbit-webapp-project/jackrabbit-webapp/src/main/java/org/apache/jackrabbit/j2ee/Installer.java (working copy) @@ -0,0 +1,234 @@ +/* + * 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.j2ee; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.util.Properties; + +import javax.servlet.ServletContext; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; + +/** + * Provides very basic installation capabilities. + */ +public class Installer { + + /** + * the default logger + */ + private static final Logger log = LoggerFactory.getLogger(Installer.class); + + /** + * Return code for installation succeeded + */ + public static final int C_INSTALL_OK = 0; + + /** + * Return code for invalid input parameter + */ + public static final int C_INVALID_INPUT = 1; + + /** + * Return code for repository home already exists + */ + public static final int C_HOME_EXISTS = 2; + + /** + * Return code for repository home is missing + */ + public static final int C_HOME_MISSING = 3; + + /** + * Return code for repository config already exists + */ + public static final int C_CONFIG_EXISTS = 4; + + /** + * Return code for repository config is missing + */ + public static final int C_CONFIG_MISSING = 5; + + /** + * Return code for bootstrap config already exists + */ + public static final int C_BOOTSTRAP_EXISTS = 6; + + /** + * Return code for a general install error + */ + public static final int C_INSTALL_ERROR = 7; + + /** + * place to store the config file + */ + private final File bootstrapConfigFile; + + /** + * the servlet context + */ + private final ServletContext context; + + /** + * the place for the repository config template + * todo: to be configured + */ + private final String configTemplate = + "/org/apache/jackrabbit/core/repository.xml"; + + /** + * the place for the bootstrap properties template + * todo: to be configured + */ + private final String bootstrapTemplate = "/WEB-INF/templates/bootstrap.properties"; + + /** + * Creates a new installer + * @param bootstrapConfigFile the location for the config file + * @param context the servlet context for accessing resources + */ + public Installer(File bootstrapConfigFile, ServletContext context) { + this.bootstrapConfigFile = bootstrapConfigFile; + this.context = context; + } + + /** + * Handles the installation. + * + * @param req the servlet request with the input parameters + * @return the installation return code + * + * @throws ServletException if a servlet error occurs. + * @throws IOException if an I/O error occurs. + */ + public int installRepository(HttpServletRequest req) + throws ServletException, IOException { + String repHome = req.getParameter("repository_home"); + String repXml = req.getParameter("repository_xml"); + String mode = req.getParameter("mode"); + + if (repHome == null || mode == null) { + return C_INVALID_INPUT; + } + File home = new File(repHome); + + File config; + if (repXml == null || repXml.length() == 0) { + config = new File(home, "repository.xml"); + repXml = config.getPath(); + } else { + config = new File(repXml); + } + + if ("new".equals(mode)) { + // Test internal folder repository existence and not home because home is already created + // by org.apache.jackrabbit.server.remoting.davex.JcrRemotingServlet + if (new File(home, "repository").exists()) { + log.error("Trying to install new repository home '{}' but it already contain a repository", repHome); + return C_HOME_EXISTS; + } + if (config != null && config.exists()) { + log.error("Trying to install new repository config '{}' but already exists", repXml); + return C_CONFIG_EXISTS; + } + log.info("Creating new repository home '{}'", repHome); + home.mkdirs(); + + if (config != null) { + // install repository xml for Jackrabbit Classic + try { + installRepositoryConfig(config); + } catch (IOException e) { + log.error("Error while installing new repository config '{}': {}", repXml, e.toString()); + return C_BOOTSTRAP_EXISTS; + } + } + } else { + if (!home.exists()) { + log.error("Trying to use existing repository home '{}' but does not exists", repHome); + return C_HOME_MISSING; + } + if (config != null && !config.exists()) { + log.error("Trying to use existing repository config '{}' but does not exists", repXml); + return C_CONFIG_MISSING; + } + } + // install bootstrap.properties + try { + installBootstrap(bootstrapConfigFile, repHome, repXml); + } catch (IOException e) { + log.error("Error while installing '{}': {}", bootstrapConfigFile.getPath(), e.toString()); + return C_INSTALL_ERROR; + } + return C_INSTALL_OK; + } + + /** + * Installs the repository config file from the template + * @param dest the destination location + * @throws IOException if an I/O error occurs. + */ + private void installRepositoryConfig(File dest) throws IOException { + log.info("Creating new repository config: {}", dest.getPath()); + InputStream in = context.getResourceAsStream(configTemplate); + if (in == null) { + in = getClass().getResourceAsStream(configTemplate); + } + OutputStream out = new FileOutputStream(dest); + byte[] buffer = new byte[8192]; + int read; + while ((read = in.read(buffer)) >= 0) { + out.write(buffer, 0, read); + } + in.close(); + out.close(); + } + + /** + * Installs the bootstrap config file from the template + * @param dest the destination location + * @param repHome the repository home location + * @param repXml the repository xml location + * @throws IOException if an I/O error occurs + */ + private void installBootstrap(File dest, String repHome, String repXml) + throws IOException { + log.info("Creating new bootstrap properties: {}", dest.getPath()); + InputStream in = context.getResourceAsStream(bootstrapTemplate); + Properties props = new Properties(); + props.load(in); + props.setProperty("repository.home", repHome); + if (repXml != null) { + props.setProperty("repository.config", repXml); + } + in.close(); + if (!dest.getParentFile().exists()) { + dest.getParentFile().mkdirs(); + } + OutputStream out = new FileOutputStream(dest); + props.store(out, "bootstrap properties for the repository startup servlet."); + out.close(); + } + +} Property changes on: jackrabbit-webapp-project/jackrabbit-webapp/src/main/java/org/apache/jackrabbit/j2ee/Installer.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 rev \ No newline at end of property Index: jackrabbit-webapp-project/jackrabbit-webapp/src/main/java/org/apache/jackrabbit/j2ee/JCRWebdavServerServlet.java =================================================================== --- jackrabbit-webapp-project/jackrabbit-webapp/src/main/java/org/apache/jackrabbit/j2ee/JCRWebdavServerServlet.java (nonexistent) +++ jackrabbit-webapp-project/jackrabbit-webapp/src/main/java/org/apache/jackrabbit/j2ee/JCRWebdavServerServlet.java (working copy) @@ -0,0 +1,36 @@ +/* + * 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.j2ee; + +import javax.jcr.Repository; + +/** + * JCRWebdavServerServlet provides request/response handling for the + * JCRWebdavServer. + */ +public class JCRWebdavServerServlet extends + org.apache.jackrabbit.webdav.jcr.JCRWebdavServerServlet { + + /** + * Returns the repository available from the servlet context of this + * servlet. + */ + protected Repository getRepository() { + return RepositoryAccessServlet.getRepository(getServletContext()); + } + +} Property changes on: jackrabbit-webapp-project/jackrabbit-webapp/src/main/java/org/apache/jackrabbit/j2ee/JCRWebdavServerServlet.java ___________________________________________________________________ Added: svn Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webapp-project/jackrabbit-webapp/src/main/java/org/apache/jackrabbit/j2ee/JNDIConfig.java =================================================================== --- jackrabbit-webapp-project/jackrabbit-webapp/src/main/java/org/apache/jackrabbit/j2ee/JNDIConfig.java (nonexistent) +++ jackrabbit-webapp-project/jackrabbit-webapp/src/main/java/org/apache/jackrabbit/j2ee/JNDIConfig.java (working copy) @@ -0,0 +1,112 @@ +/* + * 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.j2ee; + +import java.util.Enumeration; +import java.util.Iterator; +import java.util.Properties; + +import javax.servlet.ServletConfig; +import javax.servlet.ServletException; + +/** + * The JNDI config hold information about JNDI connection details. + * + * It supports the following properties and init parameters: + *

+ * +-------------------+--------------------+
+ * | Property Name     | Init-Param Name    |
+ * +-------------------+--------------------+
+ * | jndi.enable       | {provider spec.}   |
+ * | java.naming.*     | java.naming.*      |
+ * +-------------------+--------------------+
+ * 
+ */ +public class JNDIConfig extends AbstractConfig { + + private boolean jndiEnabled; + + private String jndiName; + + private final BootstrapConfig parentConfig; + + private Properties jndiEnv = new Properties(); + + + public JNDIConfig(BootstrapConfig parentConfig) { + this.parentConfig = parentConfig; + } + + + public String getJndiName() { + return jndiName; + } + + public void setJndiName(String jndiName) { + this.jndiName = jndiName; + } + + public boolean enabled() { + return jndiEnabled; + } + + public String getJndiEnabled() { + return String.valueOf(jndiEnabled); + } + + public void setJndiEnabled(String jndiEnabled) { + this.jndiEnabled = Boolean.valueOf(jndiEnabled).booleanValue(); + } + + public Properties getJndiEnv() { + return jndiEnv; + } + + public void init(Properties props) throws ServletException { + super.init(props); + // add all props whose name starts with 'java.namming.' to the env + Iterator iter = props.keySet().iterator(); + while (iter.hasNext()) { + String name = (String) iter.next(); + if (name.startsWith("java.naming.")) { + jndiEnv.put(name, props.getProperty(name)); + } + } + } + + public void init(ServletConfig ctx) throws ServletException { + super.init(ctx); + // add all params whose name starts with 'java.namming.' to the env + Enumeration names = ctx.getInitParameterNames(); + while (names.hasMoreElements()) { + String name = (String) names.nextElement(); + if (name.startsWith("java.naming.")) { + jndiEnv.put(name, ctx.getInitParameter(name)); + } + } + // enable jndi if url is specified + jndiEnabled = jndiEnv.containsKey("java.naming.provider.url"); + } + + + public void validate() { + if (jndiName == null) { + jndiName = parentConfig.getRepositoryName(); + } + valid = true; + } +} \ No newline at end of file Property changes on: jackrabbit-webapp-project/jackrabbit-webapp/src/main/java/org/apache/jackrabbit/j2ee/JNDIConfig.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 rev \ No newline at end of property Index: jackrabbit-webapp-project/jackrabbit-webapp/src/main/java/org/apache/jackrabbit/j2ee/JcrApiNotFoundException.java =================================================================== --- jackrabbit-webapp-project/jackrabbit-webapp/src/main/java/org/apache/jackrabbit/j2ee/JcrApiNotFoundException.java (nonexistent) +++ jackrabbit-webapp-project/jackrabbit-webapp/src/main/java/org/apache/jackrabbit/j2ee/JcrApiNotFoundException.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.j2ee; + +/** + * Exception for signaling that the JCR API is not available. + */ +public class JcrApiNotFoundException extends ServletExceptionWithCause { + + /** + * Serial version UID + */ + private static final long serialVersionUID = -6439777923943394980L; + + /** + * Creates an exception to signal that the JCR API is not available. + * + * @param e the specific exception that indicates the lack of the JCR API + */ + public JcrApiNotFoundException(ClassNotFoundException e) { + super("JCR API (jcr-1.0.jar) not available in the classpath", e); + } + +} Property changes on: jackrabbit-webapp-project/jackrabbit-webapp/src/main/java/org/apache/jackrabbit/j2ee/JcrApiNotFoundException.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webapp-project/jackrabbit-webapp/src/main/java/org/apache/jackrabbit/j2ee/JcrRemotingServlet.java =================================================================== --- jackrabbit-webapp-project/jackrabbit-webapp/src/main/java/org/apache/jackrabbit/j2ee/JcrRemotingServlet.java (nonexistent) +++ jackrabbit-webapp-project/jackrabbit-webapp/src/main/java/org/apache/jackrabbit/j2ee/JcrRemotingServlet.java (working copy) @@ -0,0 +1,33 @@ +/* + * 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.j2ee; + +import javax.jcr.Repository; + +/** + * JcrRemotingServlet... + */ +public class JcrRemotingServlet extends org.apache.jackrabbit.server.remoting.davex.JcrRemotingServlet { + + /** + * Returns the repository available from the servlet context of this + * servlet. + */ + protected Repository getRepository() { + return RepositoryAccessServlet.getRepository(getServletContext()); + } +} \ No newline at end of file Property changes on: jackrabbit-webapp-project/jackrabbit-webapp/src/main/java/org/apache/jackrabbit/j2ee/JcrRemotingServlet.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-webapp-project/jackrabbit-webapp/src/main/java/org/apache/jackrabbit/j2ee/RMIConfig.java =================================================================== --- jackrabbit-webapp-project/jackrabbit-webapp/src/main/java/org/apache/jackrabbit/j2ee/RMIConfig.java (nonexistent) +++ jackrabbit-webapp-project/jackrabbit-webapp/src/main/java/org/apache/jackrabbit/j2ee/RMIConfig.java (working copy) @@ -0,0 +1,175 @@ +/* + * 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.j2ee; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.net.URI; +import java.net.URISyntaxException; +import java.rmi.registry.Registry; + +import javax.servlet.ServletConfig; +import javax.servlet.ServletException; + +/** + * The RMI config hold information about RMI connection details. + * + * It supports the following properties and init parameters: + *
+ * +-------------------+--------------------+
+ * | Property Name     | Init-Param Name    |
+ * +-------------------+--------------------+
+ * | rmi.enable        | {rmi-port sepc.}   |
+ * | rmi.host          | rmi-host           |
+ * | rmi.port          | rmi-port           |
+ * | rmi.name          | {repository name}  |
+ * | rmi.url           | rmi-url            |
+ * +-------------------+--------------------+
+ * 
+ */ +public class RMIConfig extends AbstractConfig { + + /** + * default logger + */ + private static final Logger log = LoggerFactory.getLogger(RMIConfig.class); + + private boolean rmiEnabled; + + private int rmiPort = -1; + + private String rmiHost; + + private String rmiName; + + private String rmiUri; + + private final BootstrapConfig parentConfig; + + + public RMIConfig(BootstrapConfig parentConfig) { + this.parentConfig = parentConfig; + } + + public void init(ServletConfig ctx) throws ServletException { + super.init(ctx); + // enable RMI if either port or url was defined + rmiEnabled = rmiPort >=0 || rmiUri != null; + } + + public String getRmiName() { + return rmiName; + } + + public void setRmiName(String rmiName) { + this.rmiName = rmiName; + } + + public boolean enabled() { + return rmiEnabled; + } + + public String getRmiEnabled() { + return String.valueOf(rmiEnabled); + } + + public void setRmiEnabled(String rmiEnabled) { + this.rmiEnabled = Boolean.valueOf(rmiEnabled).booleanValue(); + } + + public int rmiPort() { + return rmiPort; + } + + public String getRmiPort() { + return String.valueOf(rmiPort); + } + + public void setRmiPort(String rmiPort) { + this.rmiPort = Integer.decode(rmiPort).intValue(); + } + + public String getRmiHost() { + return rmiHost; + } + + public void setRmiHost(String rmiHost) { + this.rmiHost = rmiHost; + } + + public String getRmiUri() { + return rmiUri; + } + + public void setRmiUri(String rmiUri) { + this.rmiUri = rmiUri; + } + + public void validate() { + if (!rmiEnabled) { + return; + } + + if (rmiUri != null && rmiUri.length() > 0) { + // URI takes precedences, so check whether the configuration has to + // be set from the URI + try { + URI uri = new URI(rmiUri); + + // extract values from the URI, check later + rmiHost = uri.getHost(); + rmiPort = uri.getPort(); + rmiName = uri.getPath(); + + } catch (URISyntaxException e) { + log.warn("Cannot parse RMI URI '" + rmiUri + "'.", e); + rmiUri = null; // clear RMI URI use another one + rmiHost = null; // use default host, ignore rmi-host param + } + + // cut of leading slash from name if defined at all + if (rmiName != null && rmiName.startsWith("/")) { + rmiName = rmiName.substring(1); + } + } + + // check RMI port + if (rmiPort == -1 || rmiPort == 0) { + // accept -1 or 0 as a hint to use the default + rmiPort = Registry.REGISTRY_PORT; + } else if (rmiPort < -1 || rmiPort > 0xFFFF) { + // emit a warning if out of range, use defualt in this case + log.warn("Invalid port in rmi-port param " + rmiPort + ". using default port."); + rmiPort = Registry.REGISTRY_PORT; + } + + // check host - use an empty name if null (i.e. not configured) + if (rmiHost == null) { + rmiHost = ""; + } + + // check name - use repositoryName if empty or null + if (rmiName == null || rmiName.length() ==0) { + rmiName = parentConfig.getRepositoryName(); + } + + // reconstruct the rmiURI now because values might have been changed + rmiUri = "//" + rmiHost + ":" + rmiPort + "/" + rmiName; + valid = true; + } +} \ No newline at end of file Property changes on: jackrabbit-webapp-project/jackrabbit-webapp/src/main/java/org/apache/jackrabbit/j2ee/RMIConfig.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 rev \ No newline at end of property Index: jackrabbit-webapp-project/jackrabbit-webapp/src/main/java/org/apache/jackrabbit/j2ee/RepositoryAccessServlet.java =================================================================== --- jackrabbit-webapp-project/jackrabbit-webapp/src/main/java/org/apache/jackrabbit/j2ee/RepositoryAccessServlet.java (nonexistent) +++ jackrabbit-webapp-project/jackrabbit-webapp/src/main/java/org/apache/jackrabbit/j2ee/RepositoryAccessServlet.java (working copy) @@ -0,0 +1,363 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.jackrabbit.j2ee; + +import org.apache.jackrabbit.rmi.client.ClientRepositoryFactory; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; +import java.net.MalformedURLException; +import java.rmi.NotBoundException; +import java.rmi.RemoteException; +import java.util.Properties; + +import javax.jcr.Repository; +import javax.naming.InitialContext; +import javax.naming.NamingException; +import javax.servlet.ServletContext; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServlet; + +/** + * This Class implements a servlet that is used as unified mechanism to retrieve + * a jcr repository either through JNDI or RMI. + */ +public class RepositoryAccessServlet extends HttpServlet { + + /** + * default logger + */ + private static final Logger log = LoggerFactory.getLogger(RepositoryAccessServlet.class); + + /** + * initial param name for the bootstrap config location + */ + public final static String INIT_PARAM_BOOTSTRAP_CONFIG = "bootstrap-config"; + + /** + * Context parameter name for 'this' instance. + */ + private final static String CTX_PARAM_THIS = "repository.access.servlet"; + + /** + * Ugly hack to override the bootstrap file location in the test cases + */ + static String bootstrapOverride = null; + + /** + * the bootstrap config + */ + private BootstrapConfig config; + + /** + * the initialized initial context + */ + private InitialContext jndiContext; + + /** + * if this is set we try to get a Repository from the ServletContext + */ + private String repositoryContextAttributeName; + + /** + * the repository + */ + private Repository repository; + + /** + * Initializes the servlet.
+ * Please note that only one repository startup servlet may exist per + * webapp. it registers itself as context attribute and acts as singleton. + * + * @throws ServletException if a same servlet is already registered or of + * another initialization error occurs. + */ + public void init() throws ServletException { + // check if servlet is defined twice + if (getServletContext().getAttribute(CTX_PARAM_THIS) != null) { + throw new ServletException("Only one repository access servlet allowed per web-app."); + } + getServletContext().setAttribute(CTX_PARAM_THIS, this); + + repositoryContextAttributeName = getServletConfig().getInitParameter("repository.context.attribute.name"); + + log.info("RepositoryAccessServlet initialized."); + } + + /** + * Returns the instance of this servlet + * @param ctx the servlet context + * @return this servlet + */ + public static RepositoryAccessServlet getInstance(ServletContext ctx) { + final RepositoryAccessServlet instance = (RepositoryAccessServlet) ctx.getAttribute(CTX_PARAM_THIS); + if(instance==null) { + throw new IllegalStateException( + "No RepositoryAccessServlet instance in ServletContext, RepositoryAccessServlet servlet not initialized?" + ); + } + return instance; + } + + /** + * Returns the bootstrap config + * @return the bootstrap config + * @throws ServletException if the config is not valid + */ + private BootstrapConfig getConfig() throws ServletException { + if (config == null) { + // check if there is a loadable bootstrap config + Properties bootstrapProps = new Properties(); + String bstrp = bootstrapOverride; + if (bstrp == null) { + bstrp = getServletConfig().getInitParameter(INIT_PARAM_BOOTSTRAP_CONFIG); + } + if (bstrp != null) { + // check if it's a web-resource + InputStream in = getServletContext().getResourceAsStream(bstrp); + if (in == null) { + // check if it's a file + File file = new File(bstrp); + if (file.canRead()) { + try { + in = new FileInputStream(file); + } catch (FileNotFoundException e) { + throw new ServletExceptionWithCause( + "Bootstrap configuration not found: " + bstrp, e); + } + } + } + if (in != null) { + try { + bootstrapProps.load(in); + } catch (IOException e) { + throw new ServletExceptionWithCause( + "Bootstrap configuration failure: " + bstrp, e); + } finally { + try { + in.close(); + } catch (IOException e) { + // ignore + } + } + } + } + + // read bootstrap config + BootstrapConfig tmpConfig = new BootstrapConfig(); + tmpConfig.init(getServletConfig()); + tmpConfig.init(bootstrapProps); + tmpConfig.validate(); + if (!tmpConfig.isValid()) { + throw new ServletException( + "Repository access configuration is not valid."); + } + tmpConfig.logInfos(); + config = tmpConfig; + } + return config; + } + + /** + * Returns the initial jndi context or null if the jndi access + * is not configured or erroous. + * @return the initial context or null + */ + private InitialContext getInitialContext() { + if (jndiContext == null && config.getJndiConfig().enabled()) { + // retrieve JNDI Context environment + try { + jndiContext = new InitialContext(config.getJndiConfig().getJndiEnv()); + } catch (NamingException e) { + log.error("Create initial context: " + e.toString()); + } + } + return jndiContext; + } + + /** + * Checks if the repository is available via JNDI and returns it. + * @return the repository or null + * @throws ServletException if this servlet is not properly configured. + */ + private Repository getRepositoryByJNDI() throws ServletException { + BootstrapConfig config = getConfig(); + if (!config.getJndiConfig().isValid() || !config.getJndiConfig().enabled()) { + return null; + } + // acquire via JNDI + String repositoryName = config.getRepositoryName(); + InitialContext ctx = getInitialContext(); + if (ctx == null) { + return null; + } + try { + Repository r = (Repository) ctx.lookup(repositoryName); + log.info("Acquired repository via JNDI."); + return r; + } catch (NamingException e) { + log.error("Error while retrieving repository using JNDI (name={})", repositoryName, e); + return null; + } + } + + /** + * Checks if the repository is available via RMI and returns it. + * @return the repository or null + * @throws ServletException if this servlet is not properly configured. + */ + private Repository getRepositoryByRMI() throws ServletException { + BootstrapConfig config = getConfig(); + if (!config.getRmiConfig().isValid() || !config.getRmiConfig().enabled()) { + return null; + } + + // acquire via RMI + String rmiURI = config.getRmiConfig().getRmiUri(); + if (rmiURI == null) { + return null; + } + log.info(" trying to retrieve repository using rmi. uri={}", rmiURI); + ClientFactoryDelegater cfd; + try { + Class clazz = Class.forName(getServerFactoryDelegaterClass()); + cfd = (ClientFactoryDelegater) clazz.newInstance(); + } catch (Throwable e) { + log.error("Unable to locate RMI ClientRepositoryFactory. Is jcr-rmi.jar missing?", e); + return null; + } + + try { + Repository r = cfd.getRepository(rmiURI); + log.info("Acquired repository via RMI."); + return r; + } catch (Exception e) { + log.error("Error while retrieving repository using RMI: {}", rmiURI, e); + return null; + } + } + + /** + * If our config said so, try to retrieve a Repository from the ServletContext + */ + protected Repository getRepositoryByContextAttribute() { + Repository result = null; + if(repositoryContextAttributeName!=null) { + result = (Repository)getServletContext().getAttribute(repositoryContextAttributeName); + + if(log.isDebugEnabled()) { + if(result!=null) { + log.debug("Got Repository from ServletContext attribute '{}'", repositoryContextAttributeName); + } else { + log.debug("ServletContext attribute '{}' does not provide a Repository", repositoryContextAttributeName); + } + } + } + return result; + } + + /** + * Return the fully qualified name of the class providing the client + * repository. The class whose name is returned must implement the + * {@link ClientFactoryDelegater} interface. + * + * @return the qfn of the factory class. + */ + protected String getServerFactoryDelegaterClass() { + return getClass().getName() + "$RMIClientFactoryDelegater"; + } + + /** + * Returns the JCR repository + * + * @return a JCR repository + * @throws IllegalStateException if the repository is not available in the context. + */ + public Repository getRepository() { + try { + if (repository == null) { + // try to get via context attribute + repository = getRepositoryByContextAttribute(); + } + if (repository == null) { + // try to retrieve via jndi + repository = getRepositoryByJNDI(); + } + if (repository == null) { + // try to get via rmi + repository = getRepositoryByRMI(); + } + if (repository == null) { + throw new ServletException("N/A"); + } + return repository; + } catch (ServletException e) { + throw new IllegalStateException( + "The repository is not available. Please check" + + " RepositoryAccessServlet configuration in web.xml.", e); + } + } + + /** + * Returns the JCR repository + * + * @param ctx the servlet context + * @return a JCR repository + * @throws IllegalStateException if the repository is not available in the context. + */ + public static Repository getRepository(ServletContext ctx) { + return getInstance(ctx).getRepository(); + } + + /** + * Returns the config that was used to bootstrap this servlet. + * @return the bootstrap config or null. + */ + public BootstrapConfig getBootstrapConfig() { + return config; + } + + /** + * optional class for RMI, will only be used, if RMI client is present + */ + protected static abstract class ClientFactoryDelegater { + + public abstract Repository getRepository(String uri) + throws RemoteException, MalformedURLException, NotBoundException; + } + + /** + * optional class for RMI, will only be used, if RMI server is present + */ + protected static class RMIClientFactoryDelegater extends ClientFactoryDelegater { + + // only used to enforce linking upon Class.forName() + static String FactoryClassName = ClientRepositoryFactory.class.getName(); + + public Repository getRepository(String uri) + throws MalformedURLException, NotBoundException, RemoteException { + System.setProperty("java.rmi.server.useCodebaseOnly", "true"); + return new ClientRepositoryFactory().getRepository(uri); + } + } +} + Property changes on: jackrabbit-webapp-project/jackrabbit-webapp/src/main/java/org/apache/jackrabbit/j2ee/RepositoryAccessServlet.java ___________________________________________________________________ Added: svn Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webapp-project/jackrabbit-webapp/src/main/java/org/apache/jackrabbit/j2ee/RepositoryStartupServlet.java =================================================================== --- jackrabbit-webapp-project/jackrabbit-webapp/src/main/java/org/apache/jackrabbit/j2ee/RepositoryStartupServlet.java (nonexistent) +++ jackrabbit-webapp-project/jackrabbit-webapp/src/main/java/org/apache/jackrabbit/j2ee/RepositoryStartupServlet.java (working copy) @@ -0,0 +1,767 @@ +/* + * 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.j2ee; + +import org.apache.jackrabbit.api.JackrabbitRepository; +import org.apache.jackrabbit.commons.repository.RepositoryFactory; +import org.apache.jackrabbit.core.RepositoryImpl; +import org.apache.jackrabbit.core.config.RepositoryConfig; +import org.apache.jackrabbit.rmi.server.RemoteAdapterFactory; +import org.apache.jackrabbit.rmi.server.ServerAdapterFactory; +import org.apache.jackrabbit.servlet.AbstractRepositoryServlet; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.xml.sax.InputSource; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; +import java.net.InetAddress; +import java.net.ServerSocket; +import java.net.UnknownHostException; +import java.rmi.AlreadyBoundException; +import java.rmi.Naming; +import java.rmi.NoSuchObjectException; +import java.rmi.Remote; +import java.rmi.RemoteException; +import java.rmi.registry.LocateRegistry; +import java.rmi.registry.Registry; +import java.rmi.server.RMIServerSocketFactory; +import java.rmi.server.UnicastRemoteObject; +import java.util.Properties; + +import javax.jcr.Repository; +import javax.jcr.RepositoryException; +import javax.naming.InitialContext; +import javax.naming.NamingException; +import javax.servlet.ServletContext; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +/** + * The RepositoryStartupServlet starts a jackrabbit repository and registers it + * to the JNDI environment and optional to the RMI registry. + *

+ * Registration with RMI + *

+ * Upon successfull creation of the repository in the {@link #init()} method, + * the repository is registered with an RMI registry if the web application is + * so configured. To register with RMI, the following web application + * init-params are considered: rmi-port designating + * the port on which the RMI registry is listening, rmi-host + * designating the interface on the local host on which the RMI registry is + * active, repository-name designating the name to which the + * repository is to be bound in the registry, and rmi-uri + * designating an RMI URI complete with host, optional port and name to which + * the object is bound. + *

+ * If the rmi-uri parameter is configured with a non-empty value, + * the rmi-port and rmi-host parameters are ignored. + * The repository-name parameter is only considered if a non-empty + * rmi-uri parameter is configured if the latter does not contain + * a name to which to bind the repository. + *

+ * This is the algorithm used to find out the host, port and name for RMI + * registration: + *

    + *
  1. If neither a rmi-uri nor a rmi-host nor a + * rmi-port parameter is configured, the repository is not + * registered with any RMI registry. + *
  2. If a non-empty rmi-uri parameter is configured extract the + * host name (or IP address), port number and name to bind to from the + * URI. If the URI is not valid, host defaults to 0.0.0.0 + * meaning all interfaces on the local host, port defaults to the RMI + * default port (1099) and the name defaults to the value + * of the repository-name parameter. + *
  3. If a non-empty rmi-uri is not configured, the host is taken + * from the rmi-host parameter, the port from the + * rmi-port parameter and the name to bind the repository to + * from the repository-name parameter. If the + * rmi-host parameter is empty or not configured, the host + * defaults to 0.0.0.0 meaning all interfaces on the local + * host. If the rmi-port parameter is empty, not configured, + * zero or a negative value, the default port for the RMI registry + * (1099) is used. + *
+ *

+ * After finding the host and port of the registry, the RMI registry itself + * is acquired. It is assumed, that host and port primarily designate an RMI + * registry, which should be active on the local host but has not been started + * yet. In this case, the LocateRegistry.createRegistry method is + * called to create a registry on the local host listening on the host and port + * configured. If creation fails, the LocateRegistry.getRegistry + * method is called to get a remote instance of the registry. Note, that + * getRegistry does not create an actual registry on the given + * host/port nor does it check, whether an RMI registry is active. + *

+ * When the registry has been retrieved, either by creation or by just creating + * a remote instance, the repository is bound to the configured name in the + * registry. + *

+ * Possible causes for registration failures include: + *

    + *
  • The web application is not configured to register with an RMI registry at + * all. + *
  • The registry is expected to be running on a remote host but does not. + *
  • The registry is expected to be running on the local host but cannot be + * accessed. Reasons include another application which does not act as an + * RMI registry is running on the configured port and thus blocks creation + * of a new RMI registry. + *
  • An object may already be bound to the same name as is configured to be + * used for the repository. + *
+ *

+ * Note: if a bootstrap-config init parameter is specified the + * servlet tries to read the respective resource, either as context resource or + * as file. The properties specified in this file override the init params + * specified in the web.xml. + *

+ *

+ * Setup Wizard Functionality
+ * When using the first time, the configuration can miss the relevant + * repository parameters in the web.xml. if so, it must contain a + * bootstrap-config parameter that refers to a property file. + * This file must exist for proper working. If not, the repository is not + * started.
+ * If the servlet is not configured correctly and accessed via http, it will + * provide a simple wizard for the first time configuration. It prompts for + * a new (or existing) repository home and will copy the templates of the + * repository.xml and bootstrap.properties to the respective location. + */ +public class RepositoryStartupServlet extends AbstractRepositoryServlet { + + /** + * the default logger + */ + private static final Logger log = LoggerFactory.getLogger(RepositoryStartupServlet.class); + + /** + * the context attribute name foe 'this' instance. + */ + private final static String CTX_PARAM_THIS = "repository.startup.servet"; + + /** + * initial param name for the bootstrap config location + */ + public final static String INIT_PARAM_BOOTSTRAP_CONFIG = "bootstrap-config"; + + /** + * Ugly hack to override the bootstrap file location in the test cases + */ + static String bootstrapOverride = null; + + /** + * the registered repository + */ + private Repository repository; + + /** + * the jndi context; created based on configuration + */ + private InitialContext jndiContext; + + private Registry rmiRegistry = null; + + /** + * Keeps a strong reference to the server side RMI repository instance to + * prevent the RMI distributed Garbage Collector from collecting the + * instance making the repository unaccessible though it should still be. + * This field is only set to a non-null value, if registration + * of the repository to an RMI registry succeeded in the + * {@link #registerRMI()} method. + * + * @see #registerRMI() + * @see #unregisterRMI() + */ + private Remote rmiRepository; + + /** + * the file to the bootstrap config + */ + private File bootstrapConfigFile; + + /** + * The bootstrap configuration + */ + private BootstrapConfig config; + + /** + * Initializes the servlet.
+ * Please note that only one repository startup servlet may exist per + * webapp. it registers itself as context attribute and acts as singleton. + * + * @throws ServletException if a same servlet is already registered or of + * another initialization error occurs. + */ + public void init() throws ServletException { + super.init(); + // check if servlet is defined twice + if (getServletContext().getAttribute(CTX_PARAM_THIS) != null) { + throw new ServletException("Only one repository startup servlet allowed per web-app."); + } + getServletContext().setAttribute(CTX_PARAM_THIS, this); + startup(); + } + + /** + * Returns an instance of this servlet. Please note, that only 1 + * repository startup servlet can exist per webapp. + * + * @param context the servlet context + * @return this servlet + */ + public static RepositoryStartupServlet getInstance(ServletContext context) { + return (RepositoryStartupServlet) context.getAttribute(CTX_PARAM_THIS); + } + + /** + * Configures and starts the repository. It registers it then to the + * RMI registry and bind is to the JNDI context if so configured. + * @throws ServletException if an error occurs. + */ + public void startup() throws ServletException { + if (repository != null) { + log.error("Startup: Repository already running."); + throw new ServletException("Repository already running."); + } + log.info("RepositoryStartupServlet initializing..."); + try { + if (configure()) { + initRepository(); + registerRMI(); + registerJNDI(); + } + log.info("RepositoryStartupServlet initialized."); + } catch (ServletException e) { + // shutdown repository + shutdownRepository(); + log.error("RepositoryStartupServlet initializing failed: " + e, e); + } + } + + /** + * Does a shutdown of the repository and deregisters it from the RMI + * registry and unbinds if from the JNDI context if so configured. + */ + public void shutdown() { + if (repository == null) { + log.info("Shutdown: Repository already stopped."); + } else { + log.info("RepositoryStartupServlet shutting down..."); + shutdownRepository(); + unregisterRMI(); + unregisterJNDI(); + log.info("RepositoryStartupServlet shut down."); + } + } + + /** + * Restarts the repository. + * @throws ServletException if an error occurs. + * @see #shutdown() + * @see #startup() + */ + public void restart() throws ServletException { + if (repository != null) { + shutdown(); + } + startup(); + } + + /** + * destroy the servlet + */ + public void destroy() { + super.destroy(); + shutdown(); + } + + /** + * Returns the started repository or null if not started + * yet. + * @return the JCR repository + */ + public Repository getRepository() { + return repository; + } + + /** + * Returns a repository factory that returns the repository if available + * or throws an exception if not. + * + * @return repository factory + */ + public RepositoryFactory getRepositoryFactory() { + return new RepositoryFactory() { + public Repository getRepository() throws RepositoryException { + Repository r = repository; + if (r != null) { + return repository; + } else { + throw new RepositoryException("Repository not available"); + } + } + }; + } + + /** + * Reads the configuration and initializes the {@link #config} field if + * successful. + * @throws ServletException if an error occurs. + */ + private boolean configure() throws ServletException { + // check if there is a loadable bootstrap config + Properties bootstrapProps = new Properties(); + String bstrp = bootstrapOverride; + if (bstrp == null) { + bstrp = getServletConfig().getInitParameter(INIT_PARAM_BOOTSTRAP_CONFIG); + } + if (bstrp != null) { + // check if it's a web-resource + InputStream in = getServletContext().getResourceAsStream(bstrp); + if (in == null) { + // check if it's a file + bootstrapConfigFile = new File(bstrp); + if (bootstrapConfigFile.canRead()) { + try { + in = new FileInputStream(bootstrapConfigFile); + } catch (FileNotFoundException e) { + throw new ServletExceptionWithCause( + "Bootstrap configuration not found: " + bstrp, e); + } + } + } + if (in != null) { + try { + bootstrapProps.load(in); + } catch (IOException e) { + throw new ServletException( + "Bootstrap configuration failure: " + bstrp, e); + } finally { + try { + in.close(); + } catch (IOException e) { + // ignore + } + } + } + } + + // read bootstrap config + config = new BootstrapConfig(); + config.init(getServletConfig()); + config.init(bootstrapProps); + config.validate(); + if (!config.isValid() + || config.getRepositoryHome() == null) { + if (bstrp == null) { + log.error("Repository startup configuration is not valid."); + } else { + log.error("Repository startup configuration is not valid but a bootstrap config is specified."); + log.error("Either create the {} file or", bstrp); + log.error("use the '/config/index.jsp' for easy configuration."); + } + return false; + } else { + config.logInfos(); + return true; + } + } + + /** + * Creates a new Repository based on the configuration and initializes the + * {@link #repository} field if successful. + * + * @throws ServletException if an error occurs + */ + private void initRepository() throws ServletException { + // get repository config + File repHome; + try { + repHome = new File(config.getRepositoryHome()).getCanonicalFile(); + } catch (IOException e) { + throw new ServletExceptionWithCause( + "Repository configuration failure: " + config.getRepositoryHome(), e); + } + String repConfig = config.getRepositoryConfig(); + if (repConfig != null) { + InputStream in = getServletContext().getResourceAsStream(repConfig); + if (in == null) { + try { + in = new FileInputStream(new File(repConfig)); + } catch (FileNotFoundException e) { + // fallback to old config + try { + in = new FileInputStream(new File(repHome, repConfig)); + } catch (FileNotFoundException e1) { + throw new ServletExceptionWithCause( + "Repository configuration not found: " + repConfig, e); + } + } + } + + try { + repository = createRepository(new InputSource(in), repHome); + } catch (RepositoryException e) { + throw new ServletExceptionWithCause("Error while creating repository", e); + } + } else { + throw new ServletException("Missing configuration"); + } + } + + /** + * Shuts down the repository. If the repository is an instanceof + * {@link JackrabbitRepository} it's {@link JackrabbitRepository#shutdown()} + * method is called. in any case, the {@link #repository} field is + * nulled. + */ + private void shutdownRepository() { + if (repository instanceof JackrabbitRepository) { + ((JackrabbitRepository) repository).shutdown(); + } + repository = null; + } + + /** + * Creates the repository instance for the given config and homedir. + * Subclasses may override this method of providing own implementations of + * a {@link Repository}. + * + * @param is input source of the repository config + * @param homedir the repository home directory + * @return a new jcr repository. + * @throws RepositoryException if an error during creation occurs. + */ + protected Repository createRepository(InputSource is, File homedir) + throws RepositoryException { + RepositoryConfig config = RepositoryConfig.create(is, homedir.getAbsolutePath()); + return RepositoryImpl.create(config); + } + + /** + * Binds the repository to the JNDI context + * @throws ServletException if an error occurs. + */ + private void registerJNDI() throws ServletException { + JNDIConfig jc = config.getJndiConfig(); + if (jc.isValid() && jc.enabled()) { + try { + jndiContext = new InitialContext(jc.getJndiEnv()); + jndiContext.bind(jc.getJndiName(), repository); + log.info("Repository bound to JNDI with name: " + jc.getJndiName()); + } catch (NamingException e) { + throw new ServletExceptionWithCause( + "Unable to bind repository using JNDI: " + jc.getJndiName(), e); + } + } + } + + /** + * Unbinds the repository from the JNDI context. + */ + private void unregisterJNDI() { + if (jndiContext != null) { + try { + jndiContext.unbind(config.getJndiConfig().getJndiName()); + } catch (NamingException e) { + log("Error while unbinding repository from JNDI: " + e); + } + } + } + + /** + * Registers the repository to an RMI registry configured in the web + * application. See Registration with RMI in the + * class documentation for a description of the algorithms used to register + * the repository with an RMI registry. + * @throws ServletException if an error occurs. + */ + private void registerRMI() { + RMIConfig rc = config.getRmiConfig(); + if (!rc.isValid() || !rc.enabled()) { + return; + } + + // try to create remote repository + Remote remote; + try { + Class clazz = Class.forName(getRemoteFactoryDelegaterClass()); + RemoteFactoryDelegater rmf = (RemoteFactoryDelegater) clazz.newInstance(); + remote = rmf.createRemoteRepository(repository); + } catch (RemoteException e) { + log.warn("Unable to create RMI repository.", e); + return; + } catch (Throwable t) { + log.warn("Unable to create RMI repository." + + " The jcr-rmi jar might be missing.", t); + return; + } + + try { + System.setProperty("java.rmi.server.useCodebaseOnly", "true"); + Registry reg = null; + + // first try to create the registry, which will fail if another + // application is already running on the configured host/port + // or if the rmiHost is not local + try { + // find the server socket factory: use the default if the + // rmiHost is not configured + RMIServerSocketFactory sf; + if (rc.getRmiHost().length() > 0) { + log.debug("Creating RMIServerSocketFactory for host " + rc.getRmiHost()); + InetAddress hostAddress = InetAddress.getByName(rc.getRmiHost()); + sf = getRMIServerSocketFactory(hostAddress); + } else { + // have the RMI implementation decide which factory is the + // default actually + log.debug("Using default RMIServerSocketFactory"); + sf = null; + } + + // create a registry using the default client socket factory + // and the server socket factory retrieved above. This also + // binds to the server socket to the rmiHost:rmiPort. + reg = LocateRegistry.createRegistry(rc.rmiPort(), null, sf); + rmiRegistry = reg; + } catch (UnknownHostException uhe) { + // thrown if the rmiHost cannot be resolved into an IP-Address + // by getRMIServerSocketFactory + log.info("Cannot create Registry", uhe); + } catch (RemoteException e) { + // thrown by createRegistry if binding to the rmiHost:rmiPort + // fails, for example due to rmiHost being remote or another + // application already being bound to the port + log.info("Cannot create Registry", e); + } + + // if creation of the registry failed, we try to access an + // potentially active registry. We do not check yet, whether the + // registry is actually accessible. + if (reg == null) { + log.debug("Trying to access existing registry at " + rc.getRmiHost() + + ":" + rc.getRmiPort()); + try { + reg = LocateRegistry.getRegistry(rc.getRmiHost(), rc.rmiPort()); + } catch (RemoteException re) { + log.warn("Cannot create the reference to the registry at " + + rc.getRmiHost() + ":" + rc.getRmiPort(), re); + } + } + + // if we finally have a registry, register the repository with the + // rmiName + if (reg != null) { + log.debug("Registering repository as " + rc.getRmiName() + + " to registry " + reg); + reg.bind(rc.getRmiName(), remote); + + // when successfull, keep references + this.rmiRepository = remote; + log.info("Repository bound via RMI with name: " + rc.getRmiUri()); + } else { + log.info("RMI registry missing, cannot bind repository via RMI"); + } + } catch (RemoteException e) { + log.warn("Unable to bind repository via RMI: " + rc.getRmiUri(), e); + } catch (AlreadyBoundException e) { + log.warn("Unable to bind repository via RMI: " + rc.getRmiUri(), e); + } + } + + /** + * Unregisters the repository from the RMI registry, if it has previously + * been registered. + */ + private void unregisterRMI() { + if (rmiRepository != null) { + // Forcibly unexport the repository; + try { + UnicastRemoteObject.unexportObject(rmiRepository, true); + } catch (NoSuchObjectException e) { + log.warn("Odd, the RMI repository was not exported", e); + } + // drop strong reference to remote repository + rmiRepository = null; + + // unregister repository + try { + Naming.unbind(config.getRmiConfig().getRmiUri()); + } catch (Exception e) { + log("Error while unbinding repository from JNDI: " + e); + } + } + + if (rmiRegistry != null) { + try { + UnicastRemoteObject.unexportObject(rmiRegistry, true); + } catch (NoSuchObjectException e) { + log.warn("Odd, the RMI registry was not exported", e); + } + rmiRegistry = null; + } + } + + /** + * Returns the config that was used to bootstrap this servlet. + * @return the bootstrap config or null. + */ + public BootstrapConfig getBootstrapConfig() { + return config; + } + + /** + * Return the fully qualified name of the class providing the remote + * repository. The class whose name is returned must implement the + * {@link RemoteFactoryDelegater} interface. + *

+ * Subclasses may override this method for providing a name of a own + * implementation. + * + * @return getClass().getName() + "$RMIRemoteFactoryDelegater" + */ + protected String getRemoteFactoryDelegaterClass() { + return getClass().getName() + "$RMIRemoteFactoryDelegater"; + } + + /** + * Returns an RMIServerSocketFactory used to create the server + * socket for a locally created RMI registry. + *

+ * This implementation returns a new instance of a simple + * RMIServerSocketFactory which just creates instances of + * the java.net.ServerSocket class bound to the given + * hostAddress. Implementations may overwrite this method to + * provide factory instances, which provide more elaborate server socket + * creation, such as SSL server sockets. + * + * @param hostAddress The InetAddress instance representing the + * the interface on the local host to which the server sockets are + * bound. + * @return A new instance of a simple RMIServerSocketFactory + * creating java.net.ServerSocket instances bound to + * the rmiHost. + */ + protected RMIServerSocketFactory getRMIServerSocketFactory( + final InetAddress hostAddress) { + return new RMIServerSocketFactory() { + public ServerSocket createServerSocket(int port) throws IOException { + return new ServerSocket(port, -1, hostAddress); + } + }; + } + + /** + * optional class for RMI, will only be used, if RMI server is present + */ + protected static abstract class RemoteFactoryDelegater { + + public abstract Remote createRemoteRepository(Repository repository) + throws RemoteException; + } + + /** + * optional class for RMI, will only be used, if RMI server is present + */ + protected static class RMIRemoteFactoryDelegater extends RemoteFactoryDelegater { + + private static final RemoteAdapterFactory FACTORY = + new ServerAdapterFactory(); + + public Remote createRemoteRepository(Repository repository) + throws RemoteException { + return FACTORY.getRemoteRepository(repository); + } + + } + + //-------------------------------------------------< Installer Routines >--- + + /** + * {@inheritDoc} + */ + protected void doGet(HttpServletRequest req, HttpServletResponse resp) + throws ServletException, IOException { + if (repository == null) { + redirect(req, resp, "/bootstrap/missing.jsp"); + } else { + redirect(req, resp, "/bootstrap/running.jsp"); + } + } + + /** + * {@inheritDoc} + */ + protected void doPost(HttpServletRequest req, HttpServletResponse resp) + throws ServletException, IOException { + if (repository != null) { + redirect(req, resp, "/bootstrap/reconfigure.jsp"); + } else { + int rc = new Installer(bootstrapConfigFile, + getServletContext()).installRepository(req); + switch (rc) { + case Installer.C_INSTALL_OK: + // restart rep + restart(); + if (repository == null) { + redirect(req, resp, "/bootstrap/error.jsp"); + } else { + redirect(req, resp, "/bootstrap/success.jsp"); + } + break; + case Installer.C_INVALID_INPUT: + redirect(req, resp, "/bootstrap/missing.jsp"); + break; + case Installer.C_CONFIG_EXISTS: + case Installer.C_BOOTSTRAP_EXISTS: + case Installer.C_HOME_EXISTS: + redirect(req, resp, "/bootstrap/exists.jsp"); + break; + case Installer. C_HOME_MISSING: + case Installer.C_CONFIG_MISSING: + redirect(req, resp, "/bootstrap/notexists.jsp"); + break; + case Installer.C_INSTALL_ERROR: + redirect(req, resp, "/bootstrap/error.jsp"); + break; + } + } + } + + /** + * Helper function to send a redirect response respecting the context path. + * + * @param req the request + * @param resp the response + * @param loc the location for the redirect + * @throws IOException if an I/O error occurs. + */ + private void redirect(HttpServletRequest req, + HttpServletResponse resp, String loc) + throws IOException { + String cp = req.getContextPath(); + if (cp == null || cp.equals("/")) { + cp = ""; + } + resp.sendRedirect(cp + loc); + } +} + Property changes on: jackrabbit-webapp-project/jackrabbit-webapp/src/main/java/org/apache/jackrabbit/j2ee/RepositoryStartupServlet.java ___________________________________________________________________ Added: svn Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webapp-project/jackrabbit-webapp/src/main/java/org/apache/jackrabbit/j2ee/ServletExceptionWithCause.java =================================================================== --- jackrabbit-webapp-project/jackrabbit-webapp/src/main/java/org/apache/jackrabbit/j2ee/ServletExceptionWithCause.java (nonexistent) +++ jackrabbit-webapp-project/jackrabbit-webapp/src/main/java/org/apache/jackrabbit/j2ee/ServletExceptionWithCause.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.j2ee; + +import javax.servlet.ServletException; + +/** + * Utility class that links {@link ServletException} with support for + * the exception chaining mechanism in {@link Throwable}. + * + * @see JCR-1598 + */ +public class ServletExceptionWithCause extends ServletException { + + /** + * Serial version UID + */ + private static final long serialVersionUID = -7201954529718775444L; + + /** + * Creates a servlet exception with the given message and cause. + * + * @param message exception message + * @param cause cause of the exception + */ + public ServletExceptionWithCause(String message, Throwable cause) { + super(message, cause); + if (getCause() == null) { + initCause(cause); + } + } + +} Property changes on: jackrabbit-webapp-project/jackrabbit-webapp/src/main/java/org/apache/jackrabbit/j2ee/ServletExceptionWithCause.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webapp-project/jackrabbit-webapp/src/main/java/org/apache/jackrabbit/j2ee/SimpleWebdavServlet.java =================================================================== --- jackrabbit-webapp-project/jackrabbit-webapp/src/main/java/org/apache/jackrabbit/j2ee/SimpleWebdavServlet.java (nonexistent) +++ jackrabbit-webapp-project/jackrabbit-webapp/src/main/java/org/apache/jackrabbit/j2ee/SimpleWebdavServlet.java (working copy) @@ -0,0 +1,55 @@ +/* + * 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.j2ee; + +import javax.jcr.Repository; + +/** + * WebdavServlet provides webdav support (level 1 and 2 complient) for repository + * resources. + */ +public class SimpleWebdavServlet extends org.apache.jackrabbit.webdav.simple.SimpleWebdavServlet { + + /** + * the jcr repository + */ + private Repository repository; + + /** + * Returns the Repository. If no repository has been set or + * created the repository initialized by RepositoryAccessServlet + * is returned. + * + * @return repository + * @see RepositoryAccessServlet#getRepository(ServletContext) + */ + public Repository getRepository() { + if (repository == null) { + repository = RepositoryAccessServlet.getRepository(getServletContext()); + } + return repository; + } + + /** + * Sets the Repository. + * + * @param repository + */ + public void setRepository(Repository repository) { + this.repository = repository; + } +} Property changes on: jackrabbit-webapp-project/jackrabbit-webapp/src/main/java/org/apache/jackrabbit/j2ee/SimpleWebdavServlet.java ___________________________________________________________________ Added: svn Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webapp-project/jackrabbit-webapp/src/main/resources/logback.xml =================================================================== --- jackrabbit-webapp-project/jackrabbit-webapp/src/main/resources/logback.xml (nonexistent) +++ jackrabbit-webapp-project/jackrabbit-webapp/src/main/resources/logback.xml (working copy) @@ -0,0 +1,30 @@ + + + + + + + %d{yyyy-MM-dd HH:mm:ss.SSS} %-5level %-40([%thread] %F:%L) %msg%n + + + + + + + + Property changes on: jackrabbit-webapp-project/jackrabbit-webapp/src/main/resources/logback.xml ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/META-INF/LICENSE =================================================================== --- jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/META-INF/LICENSE (nonexistent) +++ jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/META-INF/LICENSE (working copy) @@ -0,0 +1,1625 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed 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. + + +APACHE JACKRABBIT SUBCOMPONENTS + +Apache Jackrabbit includes parts with separate copyright notices and license +terms. Your use of these subcomponents is subject to the terms and conditions +of the following licenses: + +XPath parser (jackrabbit-spi-commons) + + XPath 2.0/XQuery 1.0 Parser: + http://www.w3.org/2002/11/xquery-xpath-applets/xgrammar.zip + + Copyright (C) 2002 World Wide Web Consortium, (Massachusetts Institute of + Technology, European Research Consortium for Informatics and Mathematics, + Keio University). All Rights Reserved. + + This work is distributed under the W3C(R) Software License in the hope + that it will be useful, but WITHOUT ANY WARRANTY; without even the + implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + W3C(R) SOFTWARE NOTICE AND LICENSE + http://www.w3.org/Consortium/Legal/2002/copyright-software-20021231 + + This work (and included software, documentation such as READMEs, or + other related items) is being provided by the copyright holders under + the following license. By obtaining, using and/or copying this work, + you (the licensee) agree that you have read, understood, and will comply + with the following terms and conditions. + + Permission to copy, modify, and distribute this software and its + documentation, with or without modification, for any purpose and + without fee or royalty is hereby granted, provided that you include + the following on ALL copies of the software and documentation or + portions thereof, including modifications: + + 1. The full text of this NOTICE in a location viewable to users + of the redistributed or derivative work. + + 2. Any pre-existing intellectual property disclaimers, notices, + or terms and conditions. If none exist, the W3C Software Short + Notice should be included (hypertext is preferred, text is + permitted) within the body of any redistributed or derivative code. + + 3. Notice of any changes or modifications to the files, including + the date changes were made. (We recommend you provide URIs to the + location from which the code is derived.) + + THIS SOFTWARE AND DOCUMENTATION IS PROVIDED "AS IS," AND COPYRIGHT + HOLDERS MAKE NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, + INCLUDING BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS + FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF THE SOFTWARE OR + DOCUMENTATION WILL NOT INFRINGE ANY THIRD PARTY PATENTS, COPYRIGHTS, + TRADEMARKS OR OTHER RIGHTS. + + COPYRIGHT HOLDERS WILL NOT BE LIABLE FOR ANY DIRECT, INDIRECT, SPECIAL + OR CONSEQUENTIAL DAMAGES ARISING OUT OF ANY USE OF THE SOFTWARE OR + DOCUMENTATION. + + The name and trademarks of copyright holders may NOT be used in + advertising or publicity pertaining to the software without specific, + written prior permission. Title to copyright in this software and + any associated documentation will at all times remain with + copyright holders. + +PDFBox libraries (pdfbox, jempbox, fontbox) + + Copyright (c) 2002-2007, www.pdfbox.org + Copyright (c) 2006-2007, www.jempbox.org + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 3. Neither the name of pdfbox; nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. + +Adobe Font Metrics (AFM) for PDF Core 14 Fonts + + This file and the 14 PostScript(R) AFM files it accompanies may be used, + copied, and distributed for any purpose and without charge, with or without + modification, provided that all copyright notices are retained; that the + AFM files are not distributed without this file; that all modifications + to this file or any of the AFM files are prominently noted in the modified + file(s); and that this paragraph is not modified. Adobe Systems has no + responsibility or obligation to support the use of the AFM files. + +CMaps for PDF Fonts (http://www.adobe.com/devnet/font/#pcfi and +ftp://ftp.oreilly.com/pub/examples/nutshell/cjkv/adobe/) + + Copyright 1990-2001 Adobe Systems Incorporated. + All Rights Reserved. + + Patents Pending + + NOTICE: All information contained herein is the property + of Adobe Systems Incorporated. + + Permission is granted for redistribution of this file + provided this copyright notice is maintained intact and + that the contents of this file are not altered in any + way from its original form. + + PostScript and Display PostScript are trademarks of + Adobe Systems Incorporated which may be registered in + certain jurisdictions. + +Glyphlist (http://www.adobe.com/devnet/opentype/archives/glyph.html) + + Copyright (c) 1997,1998,2002,2007 Adobe Systems Incorporated + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this documentation file to use, copy, publish, distribute, + sublicense, and/or sell copies of the documentation, and to permit + others to do the same, provided that: + - No modification, editing or other alteration of this document is + allowed; and + - The above copyright notice and this permission notice shall be + included in all copies of the documentation. + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this documentation file, to create their own derivative works + from the content of this document to use, copy, publish, distribute, + sublicense, and/or sell the derivative works, and to permit others to do + the same, provided that the derived work is not represented as being a + copy or version of this document. + + Adobe shall not be liable to any party for any loss of revenue or profit + or for indirect, incidental, special, consequential, or other similar + damages, whether based on tort (including without limitation negligence + or strict liability), contract or other legal or equitable grounds even + if Adobe has been advised or had reason to know of the possibility of + such damages. The Adobe materials are provided on an "AS IS" basis. + Adobe specifically disclaims all express, statutory, or implied + warranties relating to the Adobe materials, including but not limited to + those concerning merchantability or fitness for a particular purpose or + non-infringement of any third party rights regarding the Adobe + materials. + +The International Components for Unicode (http://site.icu-project.org/) + + Copyright (c) 1995-2009 International Business Machines Corporation + and others + + All rights reserved. + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, and/or sell copies of the Software, and to permit persons + to whom the Software is furnished to do so, provided that the above + copyright notice(s) and this permission notice appear in all copies + of the Software and that both the above copyright notice(s) and this + permission notice appear in supporting documentation. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. + IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN THIS NOTICE + BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, + OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, + WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, + ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + SOFTWARE. + + Except as contained in this notice, the name of a copyright holder shall + not be used in advertising or otherwise to promote the sale, use or other + dealings in this Software without prior written authorization of the + copyright holder. + +MIME type information from file-4.26.tar.gz (http://www.darwinsys.com/file/) + + Copyright (c) Ian F. Darwin 1986, 1987, 1989, 1990, 1991, 1992, 1994, 1995. + Software written by Ian F. Darwin and others; + maintained 1994- Christos Zoulas. + + This software is not subject to any export provision of the United States + Department of Commerce, and may be exported to any country or planet. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice immediately at the beginning of the file, without modification, + this list of conditions, and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR + ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. + +Metadata extractor library (metadata-extractor) + + This is public domain software - that is, you can do whatever you want + with it, and include it software that is licensed under the GNU or the + BSD license, or whatever other licence you choose, including proprietary + closed source licenses. I do ask that you leave this header in tact. + + If you make modifications to this code that you think would benefit the + wider community, please send me a copy and I'll post it on my site. + + If you make use of this code, I'd appreciate hearing about it. + metadata_extractor [at] drewnoakes [dot] com + Latest version of this software kept at + http://drewnoakes.com/ + +ASM bytecode manipulation library (asm) + + Copyright (c) 2000-2005 INRIA, France Telecom + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 3. Neither the name of the copyright holders nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + THE POSSIBILITY OF SUCH DAMAGE. + +SLF4J libraries (slf4j-api, log4j-over-slf4j, jcl-over-slf4j) + + Copyright (c) 2004-2008 QOS.ch + All rights reserved. + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Logback library (logback-core, logback-classic) + + Logback: the reliable, generic, fast and flexible logging framework. + Copyright (C) 1999-2009, QOS.ch. All rights reserved. + + This program and the accompanying materials are dual-licensed under + either the terms of the Eclipse Public License v1.0 as published by + the Eclipse Foundation + + or (per the licensee's choosing) + + under the terms of the GNU Lesser General Public License version 2.1 + as published by the Free Software Foundation. + +XML API library, org.w3c classes (xml-apis) + + DOM Java Language Binding: + http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113/java-binding.html + + W3C IPR SOFTWARE NOTICE + Copyright (C) 2000 World Wide Web Consortium, (Massachusetts Institute of + Technology, Institut National de Recherche en Informatique et en + Automatique, Keio University). All Rights Reserved. + + The DOM bindings are published under the W3C Software Copyright Notice + and License. The software license requires "Notice of any changes or + modifications to the W3C files, including the date changes were made." + Consequently, modified versions of the DOM bindings must document that + they do not conform to the W3C standard; in the case of the IDL binding, + the pragma prefix can no longer be 'w3c.org'; in the case of the Java + binding, the package names can no longer be in the 'org.w3c' package. + + Note: The original version of the W3C Software Copyright Notice and + License could be found at + http://www.w3.org/Consortium/Legal/copyright-software-19980720 + + Copyright (C) 1994-2000 World Wide Web Consortium, (Massachusetts + Institute of Technology, Institut National de Recherche en Informatique + et en Automatique, Keio University). All Rights Reserved. + http://www.w3.org/Consortium/Legal/ + + This W3C work (including software, documents, or other related items) is + being provided by the copyright holders under the following license. By + obtaining, using and/or copying this work, you (the licensee) agree that + you have read, understood, and will comply with the following terms and + conditions: + + Permission to use, copy, and modify this software and its documentation, + with or without modification, for any purpose and without fee or royalty + is hereby granted, provided that you include the following on ALL copies + of the software and documentation or portions thereof, including + modifications, that you make: + + 1. The full text of this NOTICE in a location viewable to users of the + redistributed or derivative work. + + 2. Any pre-existing intellectual property disclaimers, notices, or + terms and conditions. If none exist, a short notice of the following + form (hypertext is preferred, text is permitted) should be used + within the body of any redistributed or derivative code: + "Copyright (C) [$date-of-software] World Wide Web Consortium, + (Massachusetts Institute of Technology, Institut National de + Recherche en Informatique et en Automatique, Keio University). + All Rights Reserved. http://www.w3.org/Consortium/Legal/" + + 3. Notice of any changes or modifications to the W3C files, including + the date changes were made. (We recommend you provide URIs to the + location from which the code is derived.) + + THIS SOFTWARE AND DOCUMENTATION IS PROVIDED "AS IS," AND COPYRIGHT HOLDERS + MAKE NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT + NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR + PURPOSE OR THAT THE USE OF THE SOFTWARE OR DOCUMENTATION WILL NOT INFRINGE + ANY THIRD PARTY PATENTS, COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS. + + COPYRIGHT HOLDERS WILL NOT BE LIABLE FOR ANY DIRECT, INDIRECT, SPECIAL + OR CONSEQUENTIAL DAMAGES ARISING OUT OF ANY USE OF THE SOFTWARE OR + DOCUMENTATION. + + The name and trademarks of copyright holders may NOT be used in + advertising or publicity pertaining to the software without specific, + written prior permission. Title to copyright in this software and any + associated documentation will at all times remain with copyright holders. + +XML API library, org.xml.sax classes (xml-apis) + + SAX2 is Free! + + I hereby abandon any property rights to SAX 2.0 (the Simple API for + XML), and release all of the SAX 2.0 source code, compiled code, and + documentation contained in this distribution into the Public Domain. + SAX comes with NO WARRANTY or guarantee of fitness for any purpose. + + David Megginson, david@megginson.com + 2000-05-05 + +Concurrent library (concurrent-1.3.4.jar) + + http://g.oswego.edu/dl/classes/EDU/oswego/cs/dl/util/concurrent/intro.html + + All classes are released to the public domain and may be used for any + purpose whatsoever without permission or acknowledgment. Portions of + the CopyOnWriteArrayList and ConcurrentReaderHashMap classes are adapted + from Sun JDK source code. These are copyright of Sun Microsystems, Inc, + and are used with their kind permission, as described in this license: + + TECHNOLOGY LICENSE FROM SUN MICROSYSTEMS, INC. TO DOUG LEA + + Whereas Doug Lea desires to utlized certain Java Software technologies + in the util.concurrent technology; and Whereas Sun Microsystems, Inc. + ("Sun") desires that Doug Lea utilize certain Java Software technologies + in the util.concurrent technology; + + Therefore the parties agree as follows, effective May 31, 2002: + + "Java Software technologies" means + + classes/java/util/ArrayList.java, and + classes/java/util/HashMap.java. + + The Java Software technologies are Copyright (c) 1994-2000 Sun + Microsystems, Inc. All rights reserved. + + Sun hereby grants Doug Lea a non-exclusive, worldwide, non-transferrable + license to use, reproduce, create derivate works of, and distribute the + Java Software and derivative works thereof in source and binary forms + as part of a larger work, and to sublicense the right to use, reproduce + and distribute the Java Software and Doug Lea's derivative works as the + part of larger works through multiple tiers of sublicensees provided that + the following conditions are met: + + -Neither the name of or trademarks of Sun may be used to endorse or + promote products including or derived from the Java Software technology + without specific prior written permission; and + -Redistributions of source or binary code must contain the above + copyright notice, this notice and and the following disclaimers: + + This software is provided "AS IS," without a warranty of any kind. + ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + MICROSYSTEMS, INC. AND ITS LICENSORS SHALL NOT BE LIABLE FOR ANY DAMAGES + SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING + THE SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN MICROSYSTEMS, INC. + OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, + HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF + THE USE OF OR INABILITY TO USE SOFTWARE, EVEN IF SUN MICROSYSTEMS, INC. + HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + + You acknowledge that Software is not designed,licensed or intended for + use in the design, construction, operation or maintenance of any nuclear + facility. + +Office Open XML schemas (ooxml-schemas-1.0.jar) + + The Office Open XML schema definitions used by Apache POI are + a part of the Office Open XML ECMA Specification (ECMA-376, [1]). + As defined in section 9.4 of the ECMA bylaws [2], this specification + is available to all interested parties without restriction: + + 9.4 All documents when approved shall be made available to + all interested parties without restriction. + + Furthermore, both Microsoft and Adobe have granted patent licenses + to this work [3,4,5]. + + [1] http://www.ecma-international.org/publications/standards/Ecma-376.htm + [2] http://www.ecma-international.org/memento/Ecmabylaws.htm + [3] http://www.microsoft.com/interop/osp/ + [4] http://www.ecma-international.org/publications/files/ECMA-ST/Ecma%20PATENT/ECMA-376%20Edition%201%20Microsoft%20Patent%20Declaration.pdf + [5] http://www.ecma-international.org/publications/files/ECMA-ST/Ecma%20PATENT/ga-2006-191.pdf + +DOM4J library (dom4j-1.6.1.jar) + + Copyright 2001-2005 (C) MetaStuff, Ltd. All Rights Reserved. + + Redistribution and use of this software and associated documentation + ("Software"), with or without modification, are permitted provided + that the following conditions are met: + + 1. Redistributions of source code must retain copyright + statements and notices. Redistributions must also contain a + copy of this document. + + 2. Redistributions in binary form must reproduce the + above copyright notice, this list of conditions and the + following disclaimer in the documentation and/or other + materials provided with the distribution. + + 3. The name "DOM4J" must not be used to endorse or promote + products derived from this Software without prior written + permission of MetaStuff, Ltd. For written permission, + please contact dom4j-info@metastuff.com. + + 4. Products derived from this Software may not be called "DOM4J" + nor may "DOM4J" appear in their names without prior written + permission of MetaStuff, Ltd. DOM4J is a registered + trademark of MetaStuff, Ltd. + + 5. Due credit should be given to the DOM4J Project - + http://www.dom4j.org + + THIS SOFTWARE IS PROVIDED BY METASTUFF, LTD. AND CONTRIBUTORS + ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT + NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + METASTUFF, LTD. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + OF THE POSSIBILITY OF SUCH DAMAGE. + +Unicode conversion code in Lucene Java (lucene-core) + + Copyright 2001-2004 Unicode, Inc. + + Disclaimer + + This source code is provided as is by Unicode, Inc. No claims are + made as to fitness for any particular purpose. No warranties of any + kind are expressed or implied. The recipient agrees to determine + applicability of information provided. If this file has been + purchased on magnetic or optical media from Unicode, Inc., the + sole remedy for any claim will be exchange of defective media + within 90 days of receipt. + + Limitations on Rights to Redistribute This Code + + Unicode, Inc. hereby grants the right to freely use the information + supplied in this file in the creation of products supporting the + Unicode Standard, and to make copies of this file in any form + for internal or external distribution as long as this notice + remains attached. + +Array utility code in Lucene Java (lucene-core) + + PSF LICENSE AGREEMENT FOR PYTHON 2.4 + ------------------------------------ + + 1. This LICENSE AGREEMENT is between the Python Software Foundation + ("PSF"), and the Individual or Organization ("Licensee") accessing and + otherwise using Python 2.4 software in source or binary form and its + associated documentation. + + 2. Subject to the terms and conditions of this License Agreement, PSF + hereby grants Licensee a nonexclusive, royalty-free, world-wide + license to reproduce, analyze, test, perform and/or display publicly, + prepare derivative works, distribute, and otherwise use Python 2.4 + alone or in any derivative version, provided, however, that PSF's + License Agreement and PSF's notice of copyright, i.e., "Copyright (c) + 2001, 2002, 2003, 2004 Python Software Foundation; All Rights Reserved" + are retained in Python 2.4 alone or in any derivative version prepared + by Licensee. + + 3. In the event Licensee prepares a derivative work that is based on + or incorporates Python 2.4 or any part thereof, and wants to make + the derivative work available to others as provided herein, then + Licensee hereby agrees to include in any such work a brief summary of + the changes made to Python 2.4. + + 4. PSF is making Python 2.4 available to Licensee on an "AS IS" + basis. PSF MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR + IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, PSF MAKES NO AND + DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS + FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF PYTHON 2.4 WILL NOT + INFRINGE ANY THIRD PARTY RIGHTS. + + 5. PSF SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF PYTHON + 2.4 FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS + A RESULT OF MODIFYING, DISTRIBUTING, OR OTHERWISE USING PYTHON 2.4, + OR ANY DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF. + + 6. This License Agreement will automatically terminate upon a material + breach of its terms and conditions. + + 7. Nothing in this License Agreement shall be deemed to create any + relationship of agency, partnership, or joint venture between PSF and + Licensee. This License Agreement does not grant permission to use PSF + trademarks or trade name in a trademark sense to endorse or promote + products or services of Licensee, or any third party. + + 8. By copying, installing or otherwise using Python 2.4, Licensee + agrees to be bound by the terms and conditions of this License + Agreement. + + BEOPEN.COM LICENSE AGREEMENT FOR PYTHON 2.0 + ------------------------------------------- + + BEOPEN PYTHON OPEN SOURCE LICENSE AGREEMENT VERSION 1 + + 1. This LICENSE AGREEMENT is between BeOpen.com ("BeOpen"), having an + office at 160 Saratoga Avenue, Santa Clara, CA 95051, and the + Individual or Organization ("Licensee") accessing and otherwise using + this software in source or binary form and its associated + documentation ("the Software"). + + 2. Subject to the terms and conditions of this BeOpen Python License + Agreement, BeOpen hereby grants Licensee a non-exclusive, + royalty-free, world-wide license to reproduce, analyze, test, perform + and/or display publicly, prepare derivative works, distribute, and + otherwise use the Software alone or in any derivative version, + provided, however, that the BeOpen Python License is retained in the + Software, alone or in any derivative version prepared by Licensee. + + 3. BeOpen is making the Software available to Licensee on an "AS IS" + basis. BEOPEN MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR + IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, BEOPEN MAKES NO AND + DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS + FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF THE SOFTWARE WILL NOT + INFRINGE ANY THIRD PARTY RIGHTS. + + 4. BEOPEN SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF THE + SOFTWARE FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS + AS A RESULT OF USING, MODIFYING OR DISTRIBUTING THE SOFTWARE, OR ANY + DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF. + + 5. This License Agreement will automatically terminate upon a material + breach of its terms and conditions. + + 6. This License Agreement shall be governed by and interpreted in all + respects by the law of the State of California, excluding conflict of + law provisions. Nothing in this License Agreement shall be deemed to + create any relationship of agency, partnership, or joint venture + between BeOpen and Licensee. This License Agreement does not grant + permission to use BeOpen trademarks or trade names in a trademark + sense to endorse or promote products or services of Licensee, or any + third party. As an exception, the "BeOpen Python" logos available at + http://www.pythonlabs.com/logos.html may be used according to the + permissions granted on that web page. + + 7. By copying, installing or otherwise using the software, Licensee + agrees to be bound by the terms and conditions of this License + Agreement. + + CNRI LICENSE AGREEMENT FOR PYTHON 1.6.1 + --------------------------------------- + + 1. This LICENSE AGREEMENT is between the Corporation for National + Research Initiatives, having an office at 1895 Preston White Drive, + Reston, VA 20191 ("CNRI"), and the Individual or Organization + ("Licensee") accessing and otherwise using Python 1.6.1 software in + source or binary form and its associated documentation. + + 2. Subject to the terms and conditions of this License Agreement, CNRI + hereby grants Licensee a nonexclusive, royalty-free, world-wide + license to reproduce, analyze, test, perform and/or display publicly, + prepare derivative works, distribute, and otherwise use Python 1.6.1 + alone or in any derivative version, provided, however, that CNRI's + License Agreement and CNRI's notice of copyright, i.e., "Copyright (c) + 1995-2001 Corporation for National Research Initiatives; All Rights + Reserved" are retained in Python 1.6.1 alone or in any derivative + version prepared by Licensee. Alternately, in lieu of CNRI's License + Agreement, Licensee may substitute the following text (omitting the + quotes): "Python 1.6.1 is made available subject to the terms and + conditions in CNRI's License Agreement. This Agreement together with + Python 1.6.1 may be located on the Internet using the following + unique, persistent identifier (known as a handle): 1895.22/1013. This + Agreement may also be obtained from a proxy server on the Internet + using the following URL: http://hdl.handle.net/1895.22/1013". + + 3. In the event Licensee prepares a derivative work that is based on + or incorporates Python 1.6.1 or any part thereof, and wants to make + the derivative work available to others as provided herein, then + Licensee hereby agrees to include in any such work a brief summary of + the changes made to Python 1.6.1. + + 4. CNRI is making Python 1.6.1 available to Licensee on an "AS IS" + basis. CNRI MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR + IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, CNRI MAKES NO AND + DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS + FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF PYTHON 1.6.1 WILL NOT + INFRINGE ANY THIRD PARTY RIGHTS. + + 5. CNRI SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF PYTHON + 1.6.1 FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS + A RESULT OF MODIFYING, DISTRIBUTING, OR OTHERWISE USING PYTHON 1.6.1, + OR ANY DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF. + + 6. This License Agreement will automatically terminate upon a material + breach of its terms and conditions. + + 7. This License Agreement shall be governed by the federal + intellectual property law of the United States, including without + limitation the federal copyright law, and, to the extent such + U.S. federal law does not apply, by the law of the Commonwealth of + Virginia, excluding Virginia's conflict of law provisions. + Notwithstanding the foregoing, with regard to derivative works based + on Python 1.6.1 that incorporate non-separable material that was + previously distributed under the GNU General Public License (GPL), the + law of the Commonwealth of Virginia shall govern this License + Agreement only as to issues arising under or with respect to + Paragraphs 4, 5, and 7 of this License Agreement. Nothing in this + License Agreement shall be deemed to create any relationship of + agency, partnership, or joint venture between CNRI and Licensee. This + License Agreement does not grant permission to use CNRI trademarks or + trade name in a trademark sense to endorse or promote products or + services of Licensee, or any third party. + + 8. By clicking on the "ACCEPT" button where indicated, or by copying, + installing or otherwise using Python 1.6.1, Licensee agrees to be + bound by the terms and conditions of this License Agreement. + + ACCEPT + + + CWI LICENSE AGREEMENT FOR PYTHON 0.9.0 THROUGH 1.2 + -------------------------------------------------- + + Copyright (c) 1991 - 1995, Stichting Mathematisch Centrum Amsterdam, + The Netherlands. All rights reserved. + + Permission to use, copy, modify, and distribute this software and its + documentation for any purpose and without fee is hereby granted, + provided that the above copyright notice appear in all copies and that + both that copyright notice and this permission notice appear in + supporting documentation, and that the name of Stichting Mathematisch + Centrum or CWI not be used in advertising or publicity pertaining to + distribution of the software without specific, written prior + permission. + + STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO + THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND + FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE + FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT + OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +AspectJ runtime library (aspectjrt) + + Eclipse Public License - v 1.0 + + THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS ECLIPSE + PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF + THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT. + + 1. DEFINITIONS + + "Contribution" means: + + a) in the case of the initial Contributor, the initial code and + documentation distributed under this Agreement, and + + b) in the case of each subsequent Contributor: + + i) changes to the Program, and + + ii) additions to the Program; + + where such changes and/or additions to the Program originate from and + are distributed by that particular Contributor. A Contribution + 'originates' from a Contributor if it was added to the Program by + such Contributor itself or anyone acting on such Contributor's behalf. + Contributions do not include additions to the Program which: (i) are + separate modules of software distributed in conjunction with the + Program under their own license agreement, and (ii) are not derivative + works of the Program. + + "Contributor" means any person or entity that distributes the Program. + + "Licensed Patents " mean patent claims licensable by a Contributor which + are necessarily infringed by the use or sale of its Contribution alone or + when combined with the Program. + + "Program" means the Contributions distributed in accordance with this + Agreement. + + "Recipient" means anyone who receives the Program under this Agreement, + including all Contributors. + + 2. GRANT OF RIGHTS + + a) Subject to the terms of this Agreement, each Contributor hereby grants + Recipient a non-exclusive, worldwide, royalty-free copyright license to + reproduce, prepare derivative works of, publicly display, publicly + perform, distribute and sublicense the Contribution of such + Contributor, if any, and such derivative works, in source code and + object code form. + + b) Subject to the terms of this Agreement, each Contributor hereby grants + Recipient a non-exclusive, worldwide, royalty-free patent license under + Licensed Patents to make, use, sell, offer to sell, import and + otherwise transfer the Contribution of such Contributor, if any, in + source code and object code form. This patent license shall apply to + the combination of the Contribution and the Program if, at the time + the Contribution is added by the Contributor, such addition of the + Contribution causes such combination to be covered by the Licensed + Patents. The patent license shall not apply to any other combinations + which include the Contribution. No hardware per se is licensed hereunder. + + c) Recipient understands that although each Contributor grants the + licenses to its Contributions set forth herein, no assurances are + provided by any Contributor that the Program does not infringe the + patent or other intellectual property rights of any other entity. Each + Contributor disclaims any liability to Recipient for claims brought by + any other entity based on infringement of intellectual property rights + or otherwise. As a condition to exercising the rights and licenses + granted hereunder, each Recipient hereby assumes sole responsibility + to secure any other intellectual property rights needed, if any. For + example, if a third party patent license is required to allow Recipient + to distribute the Program, it is Recipient's responsibility to acquire + that license before distributing the Program. + + d) Each Contributor represents that to its knowledge it has sufficient + copyright rights in its Contribution, if any, to grant the copyright + license set forth in this Agreement. + + 3. REQUIREMENTS + + A Contributor may choose to distribute the Program in object code form + under its own license agreement, provided that: + + a) it complies with the terms and conditions of this Agreement; and + + b) its license agreement: + + i) effectively disclaims on behalf of all Contributors all warranties + and conditions, express and implied, including warranties or + conditions of title and non-infringement, and implied warranties + or conditions of merchantability and fitness for a particular + purpose; + + ii) effectively excludes on behalf of all Contributors all liability + for damages, including direct, indirect, special, incidental and + consequential damages, such as lost profits; + + iii) states that any provisions which differ from this Agreement are + offered by that Contributor alone and not by any other party; and + + iv) states that source code for the Program is available from such + Contributor, and informs licensees how to obtain it in a + reasonable manner on or through a medium customarily used for + software exchange. + + When the Program is made available in source code form: + + a) it must be made available under this Agreement; and + + b) a copy of this Agreement must be included with each copy of the + Program. + + Contributors may not remove or alter any copyright notices contained + within the Program. + + Each Contributor must identify itself as the originator of its + Contribution, if any, in a manner that reasonably allows subsequent + Recipients to identify the originator of the Contribution. + + 4. COMMERCIAL DISTRIBUTION + + Commercial distributors of software may accept certain responsibilities + with respect to end users, business partners and the like. While this + license is intended to facilitate the commercial use of the Program, + the Contributor who includes the Program in a commercial product offering + should do so in a manner which does not create potential liability for + other Contributors. Therefore, if a Contributor includes the Program in + a commercial product offering, such Contributor ("Commercial Contributor") + hereby agrees to defend and indemnify every other Contributor + ("Indemnified Contributor") against any losses, damages and costs + (collectively "Losses") arising from claims, lawsuits and other legal + actions brought by a third party against the Indemnified Contributor to + the extent caused by the acts or omissions of such Commercial Contributor + in connection with its distribution of the Program in a commercial + product offering. The obligations in this section do not apply to any + claims or Losses relating to any actual or alleged intellectual property + infringement. In order to qualify, an Indemnified Contributor must: + a) promptly notify the Commercial Contributor in writing of such claim, + and b) allow the Commercial Contributor to control, and cooperate with + the Commercial Contributor in, the defense and any related settlement + negotiations. The Indemnified Contributor may participate in any such + claim at its own expense. + + For example, a Contributor might include the Program in a commercial + product offering, Product X. That Contributor is then a Commercial + Contributor. If that Commercial Contributor then makes performance claims, + or offers warranties related to Product X, those performance claims and + warranties are such Commercial Contributor's responsibility alone. Under + this section, the Commercial Contributor would have to defend claims + against the other Contributors related to those performance claims and + warranties, and if a court requires any other Contributor to pay any + damages as a result, the Commercial Contributor must pay those damages. + + 5. NO WARRANTY + + EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS PROVIDED + ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER + EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR + CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A + PARTICULAR PURPOSE. Each Recipient is solely responsible for determining + the appropriateness of using and distributing the Program and assumes all + risks associated with its exercise of rights under this Agreement , + including but not limited to the risks and costs of program errors, + compliance with applicable laws, damage to or loss of data, programs or + equipment, and unavailability or interruption of operations. + + 6. DISCLAIMER OF LIABILITY + + EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR + ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING + WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OR + DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED + HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + + 7. GENERAL + + If any provision of this Agreement is invalid or unenforceable under + applicable law, it shall not affect the validity or enforceability of + the remainder of the terms of this Agreement, and without further action + by the parties hereto, such provision shall be reformed to the minimum + extent necessary to make such provision valid and enforceable. + + If Recipient institutes patent litigation against any entity (including + a cross-claim or counterclaim in a lawsuit) alleging that the Program + itself (excluding combinations of the Program with other software or + hardware) infringes such Recipient's patent(s), then such Recipient's + rights granted under Section 2(b) shall terminate as of the date such + litigation is filed. + + All Recipient's rights under this Agreement shall terminate if it fails + to comply with any of the material terms or conditions of this Agreement + and does not cure such failure in a reasonable period of time after + becoming aware of such noncompliance. If all Recipient's rights under + this Agreement terminate, Recipient agrees to cease use and distribution + of the Program as soon as reasonably practicable. However, Recipient's + obligations under this Agreement and any licenses granted by Recipient + relating to the Program shall continue and survive. + + Everyone is permitted to copy and distribute copies of this Agreement, + but in order to avoid inconsistency the Agreement is copyrighted and may + only be modified in the following manner. The Agreement Steward reserves + the right to publish new versions (including revisions) of this Agreement + from time to time. No one other than the Agreement Steward has the right + to modify this Agreement. The Eclipse Foundation is the initial Agreement + Steward. The Eclipse Foundation may assign the responsibility to serve as + the Agreement Steward to a suitable separate entity. Each new version of + the Agreement will be given a distinguishing version number. The Program + (including Contributions) may always be distributed subject to the version + of the Agreement under which it was received. In addition, after a new + version of the Agreement is published, Contributor may elect to distribute + the Program (including its Contributions) under the new version. Except as + expressly stated in Sections 2(a) and 2(b) above, Recipient receives no + rights or licenses to the intellectual property of any Contributor under + this Agreement, whether expressly, by implication, estoppel or otherwise. + All rights in the Program not expressly granted under this Agreement + are reserved. + + This Agreement is governed by the laws of the State of New York and the + intellectual property laws of the United States of America. No party to + this Agreement will bring a legal action under this Agreement more than + one year after the cause of action arose. Each party waives its rights to + a jury trial in any resulting litigation. + +juniversalchardet library (juniversalchardet) + + MOZILLA PUBLIC LICENSE + Version 1.1 + + --------------- + + 1. Definitions. + + 1.0.1. "Commercial Use" means distribution or otherwise making the + Covered Code available to a third party. + + 1.1. "Contributor" means each entity that creates or contributes to + the creation of Modifications. + + 1.2. "Contributor Version" means the combination of the Original + Code, prior Modifications used by a Contributor, and the Modifications + made by that particular Contributor. + + 1.3. "Covered Code" means the Original Code or Modifications or the + combination of the Original Code and Modifications, in each case + including portions thereof. + + 1.4. "Electronic Distribution Mechanism" means a mechanism generally + accepted in the software development community for the electronic + transfer of data. + + 1.5. "Executable" means Covered Code in any form other than Source + Code. + + 1.6. "Initial Developer" means the individual or entity identified + as the Initial Developer in the Source Code notice required by Exhibit + A. + + 1.7. "Larger Work" means a work which combines Covered Code or + portions thereof with code not governed by the terms of this License. + + 1.8. "License" means this document. + + 1.8.1. "Licensable" means having the right to grant, to the maximum + extent possible, whether at the time of the initial grant or + subsequently acquired, any and all of the rights conveyed herein. + + 1.9. "Modifications" means any addition to or deletion from the + substance or structure of either the Original Code or any previous + Modifications. When Covered Code is released as a series of files, a + Modification is: + A. Any addition to or deletion from the contents of a file + containing Original Code or previous Modifications. + + B. Any new file that contains any part of the Original Code or + previous Modifications. + + 1.10. "Original Code" means Source Code of computer software code + which is described in the Source Code notice required by Exhibit A as + Original Code, and which, at the time of its release under this + License is not already Covered Code governed by this License. + + 1.10.1. "Patent Claims" means any patent claim(s), now owned or + hereafter acquired, including without limitation, method, process, + and apparatus claims, in any patent Licensable by grantor. + + 1.11. "Source Code" means the preferred form of the Covered Code for + making modifications to it, including all modules it contains, plus + any associated interface definition files, scripts used to control + compilation and installation of an Executable, or source code + differential comparisons against either the Original Code or another + well known, available Covered Code of the Contributor's choice. The + Source Code can be in a compressed or archival form, provided the + appropriate decompression or de-archiving software is widely available + for no charge. + + 1.12. "You" (or "Your") means an individual or a legal entity + exercising rights under, and complying with all of the terms of, this + License or a future version of this License issued under Section 6.1. + For legal entities, "You" includes any entity which controls, is + controlled by, or is under common control with You. For purposes of + this definition, "control" means (a) the power, direct or indirect, + to cause the direction or management of such entity, whether by + contract or otherwise, or (b) ownership of more than fifty percent + (50%) of the outstanding shares or beneficial ownership of such + entity. + + 2. Source Code License. + + 2.1. The Initial Developer Grant. + The Initial Developer hereby grants You a world-wide, royalty-free, + non-exclusive license, subject to third party intellectual property + claims: + (a) under intellectual property rights (other than patent or + trademark) Licensable by Initial Developer to use, reproduce, + modify, display, perform, sublicense and distribute the Original + Code (or portions thereof) with or without Modifications, and/or + as part of a Larger Work; and + + (b) under Patents Claims infringed by the making, using or + selling of Original Code, to make, have made, use, practice, + sell, and offer for sale, and/or otherwise dispose of the + Original Code (or portions thereof). + + (c) the licenses granted in this Section 2.1(a) and (b) are + effective on the date Initial Developer first distributes + Original Code under the terms of this License. + + (d) Notwithstanding Section 2.1(b) above, no patent license is + granted: 1) for code that You delete from the Original Code; 2) + separate from the Original Code; or 3) for infringements caused + by: i) the modification of the Original Code or ii) the + combination of the Original Code with other software or devices. + + 2.2. Contributor Grant. + Subject to third party intellectual property claims, each Contributor + hereby grants You a world-wide, royalty-free, non-exclusive license + + (a) under intellectual property rights (other than patent or + trademark) Licensable by Contributor, to use, reproduce, modify, + display, perform, sublicense and distribute the Modifications + created by such Contributor (or portions thereof) either on an + unmodified basis, with other Modifications, as Covered Code + and/or as part of a Larger Work; and + + (b) under Patent Claims infringed by the making, using, or + selling of Modifications made by that Contributor either alone + and/or in combination with its Contributor Version (or portions + of such combination), to make, use, sell, offer for sale, have + made, and/or otherwise dispose of: 1) Modifications made by that + Contributor (or portions thereof); and 2) the combination of + Modifications made by that Contributor with its Contributor + Version (or portions of such combination). + + (c) the licenses granted in Sections 2.2(a) and 2.2(b) are + effective on the date Contributor first makes Commercial Use of + the Covered Code. + + (d) Notwithstanding Section 2.2(b) above, no patent license is + granted: 1) for any code that Contributor has deleted from the + Contributor Version; 2) separate from the Contributor Version; + 3) for infringements caused by: i) third party modifications of + Contributor Version or ii) the combination of Modifications made + by that Contributor with other software (except as part of the + Contributor Version) or other devices; or 4) under Patent Claims + infringed by Covered Code in the absence of Modifications made by + that Contributor. + + 3. Distribution Obligations. + + 3.1. Application of License. + The Modifications which You create or to which You contribute are + governed by the terms of this License, including without limitation + Section 2.2. The Source Code version of Covered Code may be + distributed only under the terms of this License or a future version + of this License released under Section 6.1, and You must include a + copy of this License with every copy of the Source Code You + distribute. You may not offer or impose any terms on any Source Code + version that alters or restricts the applicable version of this + License or the recipients' rights hereunder. However, You may include + an additional document offering the additional rights described in + Section 3.5. + + 3.2. Availability of Source Code. + Any Modification which You create or to which You contribute must be + made available in Source Code form under the terms of this License + either on the same media as an Executable version or via an accepted + Electronic Distribution Mechanism to anyone to whom you made an + Executable version available; and if made available via Electronic + Distribution Mechanism, must remain available for at least twelve (12) + months after the date it initially became available, or at least six + (6) months after a subsequent version of that particular Modification + has been made available to such recipients. You are responsible for + ensuring that the Source Code version remains available even if the + Electronic Distribution Mechanism is maintained by a third party. + + 3.3. Description of Modifications. + You must cause all Covered Code to which You contribute to contain a + file documenting the changes You made to create that Covered Code and + the date of any change. You must include a prominent statement that + the Modification is derived, directly or indirectly, from Original + Code provided by the Initial Developer and including the name of the + Initial Developer in (a) the Source Code, and (b) in any notice in an + Executable version or related documentation in which You describe the + origin or ownership of the Covered Code. + + 3.4. Intellectual Property Matters + (a) Third Party Claims. + If Contributor has knowledge that a license under a third party's + intellectual property rights is required to exercise the rights + granted by such Contributor under Sections 2.1 or 2.2, + Contributor must include a text file with the Source Code + distribution titled "LEGAL" which describes the claim and the + party making the claim in sufficient detail that a recipient will + know whom to contact. If Contributor obtains such knowledge after + the Modification is made available as described in Section 3.2, + Contributor shall promptly modify the LEGAL file in all copies + Contributor makes available thereafter and shall take other steps + (such as notifying appropriate mailing lists or newsgroups) + reasonably calculated to inform those who received the Covered + Code that new knowledge has been obtained. + + (b) Contributor APIs. + If Contributor's Modifications include an application programming + interface and Contributor has knowledge of patent licenses which + are reasonably necessary to implement that API, Contributor must + also include this information in the LEGAL file. + + (c) Representations. + Contributor represents that, except as disclosed pursuant to + Section 3.4(a) above, Contributor believes that Contributor's + Modifications are Contributor's original creation(s) and/or + Contributor has sufficient rights to grant the rights conveyed by + this License. + + 3.5. Required Notices. + You must duplicate the notice in Exhibit A in each file of the Source + Code. If it is not possible to put such notice in a particular Source + Code file due to its structure, then You must include such notice in a + location (such as a relevant directory) where a user would be likely + to look for such a notice. If You created one or more Modification(s) + You may add your name as a Contributor to the notice described in + Exhibit A. You must also duplicate this License in any documentation + for the Source Code where You describe recipients' rights or ownership + rights relating to Covered Code. You may choose to offer, and to + charge a fee for, warranty, support, indemnity or liability + obligations to one or more recipients of Covered Code. However, You + may do so only on Your own behalf, and not on behalf of the Initial + Developer or any Contributor. You must make it absolutely clear than + any such warranty, support, indemnity or liability obligation is + offered by You alone, and You hereby agree to indemnify the Initial + Developer and every Contributor for any liability incurred by the + Initial Developer or such Contributor as a result of warranty, + support, indemnity or liability terms You offer. + + 3.6. Distribution of Executable Versions. + You may distribute Covered Code in Executable form only if the + requirements of Section 3.1-3.5 have been met for that Covered Code, + and if You include a notice stating that the Source Code version of + the Covered Code is available under the terms of this License, + including a description of how and where You have fulfilled the + obligations of Section 3.2. The notice must be conspicuously included + in any notice in an Executable version, related documentation or + collateral in which You describe recipients' rights relating to the + Covered Code. You may distribute the Executable version of Covered + Code or ownership rights under a license of Your choice, which may + contain terms different from this License, provided that You are in + compliance with the terms of this License and that the license for the + Executable version does not attempt to limit or alter the recipient's + rights in the Source Code version from the rights set forth in this + License. If You distribute the Executable version under a different + license You must make it absolutely clear that any terms which differ + from this License are offered by You alone, not by the Initial + Developer or any Contributor. You hereby agree to indemnify the + Initial Developer and every Contributor for any liability incurred by + the Initial Developer or such Contributor as a result of any such + terms You offer. + + 3.7. Larger Works. + You may create a Larger Work by combining Covered Code with other code + not governed by the terms of this License and distribute the Larger + Work as a single product. In such a case, You must make sure the + requirements of this License are fulfilled for the Covered Code. + + 4. Inability to Comply Due to Statute or Regulation. + + If it is impossible for You to comply with any of the terms of this + License with respect to some or all of the Covered Code due to + statute, judicial order, or regulation then You must: (a) comply with + the terms of this License to the maximum extent possible; and (b) + describe the limitations and the code they affect. Such description + must be included in the LEGAL file described in Section 3.4 and must + be included with all distributions of the Source Code. Except to the + extent prohibited by statute or regulation, such description must be + sufficiently detailed for a recipient of ordinary skill to be able to + understand it. + + 5. Application of this License. + + This License applies to code to which the Initial Developer has + attached the notice in Exhibit A and to related Covered Code. + + 6. Versions of the License. + + 6.1. New Versions. + Netscape Communications Corporation ("Netscape") may publish revised + and/or new versions of the License from time to time. Each version + will be given a distinguishing version number. + + 6.2. Effect of New Versions. + Once Covered Code has been published under a particular version of the + License, You may always continue to use it under the terms of that + version. You may also choose to use such Covered Code under the terms + of any subsequent version of the License published by Netscape. No one + other than Netscape has the right to modify the terms applicable to + Covered Code created under this License. + + 6.3. Derivative Works. + If You create or use a modified version of this License (which you may + only do in order to apply it to code which is not already Covered Code + governed by this License), You must (a) rename Your license so that + the phrases "Mozilla", "MOZILLAPL", "MOZPL", "Netscape", + "MPL", "NPL" or any confusingly similar phrase do not appear in your + license (except to note that your license differs from this License) + and (b) otherwise make it clear that Your version of the license + contains terms which differ from the Mozilla Public License and + Netscape Public License. (Filling in the name of the Initial + Developer, Original Code or Contributor in the notice described in + Exhibit A shall not of themselves be deemed to be modifications of + this License.) + + 7. DISCLAIMER OF WARRANTY. + + COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, + WITHOUT LIMITATION, WARRANTIES THAT THE COVERED CODE IS FREE OF + DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE OR NON-INFRINGING. + THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED CODE + IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, + YOU (NOT THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE + COST OF ANY NECESSARY SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER + OF WARRANTY CONSTITUTES AN ESSENTIAL PART OF THIS LICENSE. NO USE OF + ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER THIS DISCLAIMER. + + 8. TERMINATION. + + 8.1. This License and the rights granted hereunder will terminate + automatically if You fail to comply with terms herein and fail to cure + such breach within 30 days of becoming aware of the breach. All + sublicenses to the Covered Code which are properly granted shall + survive any termination of this License. Provisions which, by their + nature, must remain in effect beyond the termination of this License + shall survive. + + 8.2. If You initiate litigation by asserting a patent infringement + claim (excluding declatory judgment actions) against Initial Developer + or a Contributor (the Initial Developer or Contributor against whom + You file such action is referred to as "Participant") alleging that: + + (a) such Participant's Contributor Version directly or indirectly + infringes any patent, then any and all rights granted by such + Participant to You under Sections 2.1 and/or 2.2 of this License + shall, upon 60 days notice from Participant terminate prospectively, + unless if within 60 days after receipt of notice You either: (i) + agree in writing to pay Participant a mutually agreeable reasonable + royalty for Your past and future use of Modifications made by such + Participant, or (ii) withdraw Your litigation claim with respect to + the Contributor Version against such Participant. If within 60 days + of notice, a reasonable royalty and payment arrangement are not + mutually agreed upon in writing by the parties or the litigation claim + is not withdrawn, the rights granted by Participant to You under + Sections 2.1 and/or 2.2 automatically terminate at the expiration of + the 60 day notice period specified above. + + (b) any software, hardware, or device, other than such Participant's + Contributor Version, directly or indirectly infringes any patent, then + any rights granted to You by such Participant under Sections 2.1(b) + and 2.2(b) are revoked effective as of the date You first made, used, + sold, distributed, or had made, Modifications made by that + Participant. + + 8.3. If You assert a patent infringement claim against Participant + alleging that such Participant's Contributor Version directly or + indirectly infringes any patent where such claim is resolved (such as + by license or settlement) prior to the initiation of patent + infringement litigation, then the reasonable value of the licenses + granted by such Participant under Sections 2.1 or 2.2 shall be taken + into account in determining the amount or value of any payment or + license. + + 8.4. In the event of termination under Sections 8.1 or 8.2 above, + all end user license agreements (excluding distributors and resellers) + which have been validly granted by You or any distributor hereunder + prior to termination shall survive termination. + + 9. LIMITATION OF LIABILITY. + + UNDER NO CIRCUMSTANCES AND UNDER NO LEGAL THEORY, WHETHER TORT + (INCLUDING NEGLIGENCE), CONTRACT, OR OTHERWISE, SHALL YOU, THE INITIAL + DEVELOPER, ANY OTHER CONTRIBUTOR, OR ANY DISTRIBUTOR OF COVERED CODE, + OR ANY SUPPLIER OF ANY OF SUCH PARTIES, BE LIABLE TO ANY PERSON FOR + ANY INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES OF ANY + CHARACTER INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF GOODWILL, + WORK STOPPAGE, COMPUTER FAILURE OR MALFUNCTION, OR ANY AND ALL OTHER + COMMERCIAL DAMAGES OR LOSSES, EVEN IF SUCH PARTY SHALL HAVE BEEN + INFORMED OF THE POSSIBILITY OF SUCH DAMAGES. THIS LIMITATION OF + LIABILITY SHALL NOT APPLY TO LIABILITY FOR DEATH OR PERSONAL INJURY + RESULTING FROM SUCH PARTY'S NEGLIGENCE TO THE EXTENT APPLICABLE LAW + PROHIBITS SUCH LIMITATION. SOME JURISDICTIONS DO NOT ALLOW THE + EXCLUSION OR LIMITATION OF INCIDENTAL OR CONSEQUENTIAL DAMAGES, SO + THIS EXCLUSION AND LIMITATION MAY NOT APPLY TO YOU. + + 10. U.S. GOVERNMENT END USERS. + + The Covered Code is a "commercial item," as that term is defined in + 48 C.F.R. 2.101 (Oct. 1995), consisting of "commercial computer + software" and "commercial computer software documentation," as such + terms are used in 48 C.F.R. 12.212 (Sept. 1995). Consistent with 48 + C.F.R. 12.212 and 48 C.F.R. 227.7202-1 through 227.7202-4 (June 1995), + all U.S. Government End Users acquire Covered Code with only those + rights set forth herein. + + 11. MISCELLANEOUS. + + This License represents the complete agreement concerning subject + matter hereof. If any provision of this License is held to be + unenforceable, such provision shall be reformed only to the extent + necessary to make it enforceable. This License shall be governed by + California law provisions (except to the extent applicable law, if + any, provides otherwise), excluding its conflict-of-law provisions. + With respect to disputes in which at least one party is a citizen of, + or an entity chartered or registered to do business in the United + States of America, any litigation relating to this License shall be + subject to the jurisdiction of the Federal Courts of the Northern + District of California, with venue lying in Santa Clara County, + California, with the losing party responsible for costs, including + without limitation, court costs and reasonable attorneys' fees and + expenses. The application of the United Nations Convention on + Contracts for the International Sale of Goods is expressly excluded. + Any law or regulation which provides that the language of a contract + shall be construed against the drafter shall not apply to this + License. + + 12. RESPONSIBILITY FOR CLAIMS. + + As between Initial Developer and the Contributors, each party is + responsible for claims and damages arising, directly or indirectly, + out of its utilization of rights under this License and You agree to + work with Initial Developer and Contributors to distribute such + responsibility on an equitable basis. Nothing herein is intended or + shall be deemed to constitute any admission of liability. + + 13. MULTIPLE-LICENSED CODE. + + Initial Developer may designate portions of the Covered Code as + "Multiple-Licensed". "Multiple-Licensed" means that the Initial + Developer permits you to utilize portions of the Covered Code under + Your choice of the NPL or the alternative licenses, if any, specified + by the Initial Developer in the file described in Exhibit A. + + EXHIBIT A -Mozilla Public License. + + ``The contents of this file are subject to the Mozilla Public License + Version 1.1 (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.mozilla.org/MPL/ + + Software distributed under the License is distributed on an "AS IS" + basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the + License for the specific language governing rights and limitations + under the License. + + The Original Code is ______________________________________. + + The Initial Developer of the Original Code is ________________________. + Portions created by ______________________ are Copyright (C) ______ + _______________________. All Rights Reserved. + + Contributor(s): ______________________________________. + + Alternatively, the contents of this file may be used under the terms + of the _____ license (the "[___] License"), in which case the + provisions of [______] License are applicable instead of those + above. If you wish to allow use of your version of this file only + under the terms of the [____] License and not to allow others to use + your version of this file under the MPL, indicate your decision by + deleting the provisions above and replace them with the notice and + other provisions required by the [___] License. If you do not delete + the provisions above, a recipient may use your version of this file + under either the MPL or the [___] License." + + [NOTE: The text of this Exhibit A may differ slightly from the text of + the notices in the Source Code files of the Original Code. You should + use the text of this Exhibit A rather than the text found in the + Original Code Source Code for Your Modifications.] Property changes on: jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/META-INF/LICENSE ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +author date id revision \ No newline at end of property Index: jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/META-INF/NOTICE =================================================================== --- jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/META-INF/NOTICE (nonexistent) +++ jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/META-INF/NOTICE (working copy) @@ -0,0 +1,41 @@ +Apache Jackrabbit +Copyright 2010 The Apache Software Foundation + +This product includes software developed at +The Apache Software Foundation (http://www.apache.org/). + +Based on source code originally developed by +Day Software (http://www.day.com/). + +This product includes software from the following contributions: + +Original BZip2 classes contributed by Keiron Liddle +, Aftex Software to the Apache Ant project + +Original Tar classes from contributors of the Apache Ant project + +Original Zip classes from contributors of the Apache Ant project + +Original CPIO classes contributed by Markus Kuss and the jRPM project +(jrpm.sourceforge.net) + +Portions of Derby were originally developed by International Business +Machines Corporation and are licensed to the Apache Software Foundation +under the "Software Grant and Corporate Contribution License Agreement", +informally known as the "Derby CLA". The following copyright notice(s) +were affixed to portions of the code with which this file is now or was +at one time distributed and are placed here unaltered. + + (C) Copyright 1997,2004 International Business Machines Corporation. + All rights reserved. + + (C) Copyright IBM Corp. 2003. + +The JDBC apis for small devices and JDBC3 (under java/stubs/jsr169 and +java/stubs/jdbc3) were produced by trimming sources supplied by the +Apache Harmony project. The following notice covers the Harmony sources: + + Portions of Harmony were originally developed by + Intel Corporation and are licensed to the Apache Software + Foundation under the "Software Grant and Corporate Contribution + License Agreement", informally known as the "Intel Harmony CLA". Property changes on: jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/META-INF/NOTICE ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +author date id revision \ No newline at end of property Index: jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/WEB-INF/batchread.properties =================================================================== --- jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/WEB-INF/batchread.properties (nonexistent) +++ jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/WEB-INF/batchread.properties (working copy) @@ -0,0 +1,27 @@ +# 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. + +# This file contains an example batch read configuration used by +# JcrRemotingServlet according to the 'batchread-config' init-param. +# +# key = node type name +# value = desired depth for any node having the node type as primary type. +# +# - Use 'default' to set the default depth +# - Depth may be any int >= -1. +# - Depth -1 indicates infinite depth. + +default=5 +nt\:file=-1 \ No newline at end of file Property changes on: jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/WEB-INF/batchread.properties ___________________________________________________________________ Added: svn Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/WEB-INF/config.xml =================================================================== --- jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/WEB-INF/config.xml (nonexistent) +++ jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/WEB-INF/config.xml (working copy) @@ -0,0 +1,184 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + nt:file + nt:resource + + + + + + + + + + + + + rep + jcr + + + + + + Property changes on: jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/WEB-INF/config.xml ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/WEB-INF/protectedHandlers.properties =================================================================== --- jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/WEB-INF/protectedHandlers.properties (nonexistent) +++ jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/WEB-INF/protectedHandlers.properties (working copy) @@ -0,0 +1,17 @@ +# 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. + +# ProtectedItemRemoveHandler implementation class +javax.jcr.tck.access.control.list.handler=org.apache.jackrabbit.server.remoting.davex.AclRemoveHandler Index: jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/WEB-INF/templates/bootstrap.properties =================================================================== --- jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/WEB-INF/templates/bootstrap.properties (nonexistent) +++ jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/WEB-INF/templates/bootstrap.properties (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. + +# This is the template file for the 'bootstrap.properties' that will +# be placed in the repository home directory (or whatever is specified +# in the "bootstrap-config" init parameter. + +# Repository configuration settings (will be adjusted by installer) +repository.config=jackrabbit/repository/repository.xml +repository.home=jackrabbit/repository +repository.name=jackrabbit.repository + +# RMI Settings +rmi.enabled=true +rmi.port=0 +rmi.host=localhost +# If the URI is not specified, it's composed as follows: +#rmi.uri=//${rmi.host}:${rmi.port}/${repository.name} + +# JNDI Settings +# all properties starting with 'java.naming.' will go into the +# environment of the initial context +jndi.enabled=true +# if the name is not specified, it's initialized with the repository.name +#jndi.name=${repository.name} +java.naming.provider.url=http://www.apache.org/jackrabbit +java.naming.factory.initial=org.apache.jackrabbit.core.jndi.provider.DummyInitialContextFactory Property changes on: jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/WEB-INF/templates/bootstrap.properties ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/WEB-INF/web.xml =================================================================== --- jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/WEB-INF/web.xml (nonexistent) +++ jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/WEB-INF/web.xml (working copy) @@ -0,0 +1,407 @@ + + + + + + Jackrabbit JCR Server + + + + + + org.apache.jackrabbit.j2ee.DerbyShutdown + + + + + + + + RepositoryStartup + + Repository servlet that starts the repository and registers it to JNDI ans RMI. + If you already have the repository registered in this appservers JNDI context, + or if its accessible via RMI, you do not need to use this servlet. + + org.apache.jackrabbit.j2ee.RepositoryStartupServlet + + + bootstrap-config + jackrabbit/bootstrap.properties + + Property file that hold the same initialization properties than + the init-params below. If a parameter is specified in both + places the one in the bootstrap-config wins. + + + + + + + + + + 2 + + + + + + + + Repository + + This servlet provides other servlets and jsps a common way to access + the repository. The repository can be accessed via JNDI, RMI or Webdav. + + org.apache.jackrabbit.j2ee.RepositoryAccessServlet + + + bootstrap-config + jackrabbit/bootstrap.properties + + Property file that hold the same initialization properties than + the init-params below. If a parameter is specified in both + places the one in the bootstrap-config wins. + + + + + + + + + + 3 + + + + + + + Webdav + + The webdav servlet that connects HTTP request to the repository. + + org.apache.jackrabbit.j2ee.SimpleWebdavServlet + + + resource-path-prefix + /repository + + defines the prefix for spooling resources out of the repository. + + + + + + + + resource-config + /WEB-INF/config.xml + + Defines various dav-resource configuration parameters. + + + + + 4 + + + + + + + JCRWebdavServer + + The servlet used to remote JCR calls over HTTP. + + org.apache.jackrabbit.j2ee.JcrRemotingServlet + + missing-auth-mapping + + + Defines how a missing authorization header should be handled. + 1) If this init-param is missing, a 401 response is generated. + This is suitable for clients (eg. webdav clients) for which + sending a proper authorization header is not possible if the + server never sent a 401. + 2) If this init-param is present with an empty value, + null-credentials are returned, thus forcing an null login + on the repository. + 3) If this init-param is present with the value 'guestcredentials' + java.jcr.GuestCredentials are used to login to the repository. + 4) If this init-param has a 'user:password' value, the respective + simple credentials are generated. + + + + + + resource-path-prefix + /server + + defines the prefix for spooling resources out of the repository. + + + + + + batchread-config + /WEB-INF/batchread.properties + JcrRemotingServlet: Optional mapping from node type names to default depth. + + + protectedhandlers-config + /WEB-INF/protectedHandlersConfig.xml + JcrRemotingServlet: Handlers for removing protected items. + + + + 5 + + + + + + + RMI + org.apache.jackrabbit.servlet.remote.RemoteBindingServlet + + + + + + + RepositoryStartup + /admin/* + + + Webdav + /repository/* + + + JCRWebdavServer + /server/* + + + RMI + /rmi + + + + + + + index.jsp + + + + org.apache.jackrabbit.j2ee.JcrApiNotFoundException + /error/classpath.jsp + + + javax.jcr.RepositoryException + /error/repository.jsp + + + Property changes on: jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/WEB-INF/web.xml ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/about.jsp =================================================================== --- jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/about.jsp (nonexistent) +++ jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/about.jsp (working copy) @@ -0,0 +1,73 @@ +<%-- + 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. +--%><%@page import="java.io.InputStream, + java.io.InputStreamReader, + java.io.Reader"%><%! + + /** + * Escapes and outputs the contents of a given (UTF-8) text resource. + * TODO: There should be an easier way to do this! + * + * @param path path of the resource to output + * @param out the JSP output writer + * @throws Exception if something goes wrong + */ + private void output(String path, JspWriter out) throws Exception { + InputStream input = getServletContext().getResourceAsStream(path); + try { + Reader reader = new InputStreamReader(input, "UTF-8"); + for (int ch = reader.read(); ch != -1; ch = reader.read()) { + if (ch == '<') { + out.write("<"); + } else if (ch == '>') { + out.write(">"); + } else if (ch == '&') { + out.write("&"); + } else { + out.write((char) ch); + } + } + } finally { + input.close(); + } + } + +%><% request.setAttribute("title", "About Apache Jackrabbit"); +%> +

+ Apache Jackrabbit is a fully + conforming implementation of the Content Repository for Java Technology API + (JCR). A content repository is a hierarchical content store with support for + structured and unstructured content, full text search, versioning, + transactions, observation, and more. Typical applications that use content + repositories include content management, document management, and records + management systems. +

+

+ Version 1.0 of the JCR API was specified by the + Java Specification Request 170 + (JSR 170) and version 2.0 by the + Java Specification Request 283. +

+

+ Apache Jackrabbit is a project of the + Apache Software Foundation. +

+

Copyright Notice

+
<% output("/META-INF/NOTICE", out); %>
+

License Information

+
<% output("/META-INF/LICENSE", out); %>
+ Property changes on: jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/about.jsp ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/bootstrap/error.jsp =================================================================== --- jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/bootstrap/error.jsp (nonexistent) +++ jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/bootstrap/error.jsp (working copy) @@ -0,0 +1,23 @@ +<%-- + 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. +--%><%@page import="org.apache.jackrabbit.util.Text"%><% +request.setAttribute("title", "Content Repository Error"); +%> +

+ Some error occurred during setup. See the log files for details. +

+

back

+ Property changes on: jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/bootstrap/error.jsp ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/bootstrap/exists.jsp =================================================================== --- jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/bootstrap/exists.jsp (nonexistent) +++ jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/bootstrap/exists.jsp (working copy) @@ -0,0 +1,28 @@ +<%-- + 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. +--%><%@page import="org.apache.jackrabbit.util.Text"%><% +request.setAttribute("title", "Content Repository Exists"); +%> +

The repository home directory or configuration already exists.

+

+You have chosen to create a new repository but the specified home +directory or the configuration file already exist. +

+

+Please specify a correct location or choose to reuse an existing repository. +

+

back

+ Property changes on: jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/bootstrap/exists.jsp ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/bootstrap/missing.jsp =================================================================== --- jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/bootstrap/missing.jsp (nonexistent) +++ jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/bootstrap/missing.jsp (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. +--%><%@page import="org.apache.jackrabbit.util.Text"%><% +request.setAttribute("title", "Content Repository Setup"); +%> +

+ Your content repository is not properly configured yet. Please use + the forms below to setup the content repository. +

+

+ Alternatively, you can directly modify the settings in the + WEB-INF/web.xml deployment descriptor and redeploy this + web application. +

+ +

Create a new content repository

+
+ +

+ Use this form to create a new content repository in the given directory. + The directory is created by this web application and should not already + exist. The repository is created using a default configuration file. +

+

+ +

+

+
+ +

Use an existing content repository

+
+ +

+ Use this form to access an existing content repository in the given + directory. The repository configuration file should be available as + repository.xml within the given directory. +

+

+ Note that the repository can not be concurrently accessed by multiple + applications. You must use WebDAV or RMI through this web application + if you want to access the repository remotely. Other web applications + running in the same servlet container can access the repository locally + using JNDI. +

+

+ +

+

+
+ + Property changes on: jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/bootstrap/missing.jsp ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/bootstrap/notexists.jsp =================================================================== --- jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/bootstrap/notexists.jsp (nonexistent) +++ jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/bootstrap/notexists.jsp (working copy) @@ -0,0 +1,28 @@ +<%-- + 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. +--%><%@page import="org.apache.jackrabbit.util.Text"%><% +request.setAttribute("title", "Content Repository Not Found"); +%> +

The repository home directory or configuration do not exists.

+

+You have chosen to reuse an existing repository but the specified home +directory or the configuration file do not exist. +

+

+Please specify a correct location or choose to create a new repository. +

+

back

+ Property changes on: jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/bootstrap/notexists.jsp ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/bootstrap/reconfigure.jsp =================================================================== --- jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/bootstrap/reconfigure.jsp (nonexistent) +++ jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/bootstrap/reconfigure.jsp (working copy) @@ -0,0 +1,25 @@ +<%-- + 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. +--%><%@page import="org.apache.jackrabbit.util.Text"%><% +request.setAttribute("title", "Content Repository Already Running"); +%> +

Your repository is already properly configured an running.

+

+Your changes were discarded. To reconfigure or reinstall the repository modify +the respective configuration files or remove them. +

+

home

+ Property changes on: jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/bootstrap/reconfigure.jsp ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/bootstrap/running.jsp =================================================================== --- jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/bootstrap/running.jsp (nonexistent) +++ jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/bootstrap/running.jsp (working copy) @@ -0,0 +1,25 @@ +<%-- + 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. +--%><%@page import="org.apache.jackrabbit.util.Text"%><% +request.setAttribute("title", "Content Repository Ready"); +%> +

Your repository is properly configured an running.

+

+To reconfigure or reinstall the repository modify the respective configuration +files or remove them. +

+

home

+ Property changes on: jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/bootstrap/running.jsp ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/bootstrap/success.jsp =================================================================== --- jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/bootstrap/success.jsp (nonexistent) +++ jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/bootstrap/success.jsp (working copy) @@ -0,0 +1,25 @@ +<%-- + 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. +--%><%@page import="org.apache.jackrabbit.util.Text"%><% +request.setAttribute("title", "Content Repository Ready"); +%> +

Your repository is now properly configured an running.

+

+To reconfigure or reinstall the repository modify the respective configuration +files or remove them. +

+

home

+ Property changes on: jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/bootstrap/success.jsp ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/css/default.css =================================================================== --- jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/css/default.css (nonexistent) +++ jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/css/default.css (working copy) @@ -0,0 +1,91 @@ +/* + * 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. + */ + +body { font-family: Verdana, Helvetica, Arial, sans-serif; + font-size: small; color: #000000; + background-color: #e0e0e0; + margin: 1em 100px 1em 100px; + padding: 0; } + +#page { background-color: white; } + +a:link { color: #667C00; } +a:visited { color: #7C7C7C; } + +img { border: 0; } + +/* BANNER */ + +#banner { padding: 0 0 113px 0; + border-top: 6px solid black; + border-bottom: 2px solid black; } +#banner p { margin: 0; } +#jcr { float: left; } +#asf { float: right; } +#banner img { margin: 0; + padding: 10px 0 0 0; } +#banner a { text-decoration: none; } + +/* NAVIGATION */ + +#navigation { padding: 18px 0; + width: 180px; + float: left; + font-size: x-small; } + +#navigation ul + { margin: 0; + padding: 1ex 0 1ex 1em; + list-style: none; + font-weight: bold; } + +#navigation ul ul + { font-weight: normal; } + +#navigation a + { text-decoration: none; } + +a.external { font-style: italic; } + +/* CONTENT */ + +#content { margin: 1em 1em 1em 180px; } + +#content p { line-height: 1.3em; } + +h1, h2, h3 { color: #869900; } + +pre { background: #E0E0E0; + padding: 1em; + border: 1px dotted black; + overflow: auto; } + +td { font-size: small; } + +pre.code { font-family: monospace; font-size: small; + padding: 25px; } + +/* FOOTER */ + +#footer { clear: both; + border-top: 1px solid #999; + font-size: x-small; } + +#footer p { margin: 0; + text-align: center; } + +#footer a { text-decoration: none; } Property changes on: jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/css/default.css ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +author date id revision \ No newline at end of property Index: jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/error/classpath.jsp =================================================================== --- jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/error/classpath.jsp (nonexistent) +++ jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/error/classpath.jsp (working copy) @@ -0,0 +1,29 @@ +<%-- + 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. +--%><% +request.setAttribute("title", "JCR API Not Found"); +%> +

+The javax.jcr.Repository interface from the JCR API could not +be loaded. +

+

+To resolve this issue, you need to make the jcr-2.0.jar file +available in the shared classpath of the servlet container. The file is +available for download from the +JSR 283 web page. +

+ Property changes on: jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/error/classpath.jsp ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/error/repository.jsp =================================================================== --- jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/error/repository.jsp (nonexistent) +++ jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/error/repository.jsp (working copy) @@ -0,0 +1,42 @@ +<%-- + 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. +--%><%@ page isErrorPage="true" + import="org.apache.jackrabbit.util.Text, + java.io.StringWriter, + java.io.PrintWriter"%><% +request.setAttribute("title", "Repository Error"); +%> +

+ The content repository operation failed with the following + <%= exception.getClass().getSimpleName() %> error: +

+
<%= Text.encodeIllegalXMLCharacters(exception.getMessage()) %>
+

+ See the + troubleshooting page + for ideas on how to resolve this issue. +

+ +

Exception stack trace

+

+ Below is the full exception stack trace associated with this error: +

+<% +StringWriter buffer = new StringWriter(); +exception.printStackTrace(new PrintWriter(buffer)); +%> +
<%= Text.encodeIllegalXMLCharacters(buffer.toString()) %>
+ Property changes on: jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/error/repository.jsp ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/footer.jsp =================================================================== --- jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/footer.jsp (nonexistent) +++ jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/footer.jsp (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. +--%> + + + + + Property changes on: jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/footer.jsp ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/header.jsp =================================================================== --- jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/header.jsp (nonexistent) +++ jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/header.jsp (working copy) @@ -0,0 +1,88 @@ +<%-- + 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. +--%> +<%@page import="org.apache.jackrabbit.util.Text"%> +<% +String title = + Text.encodeIllegalXMLCharacters(request.getAttribute("title").toString()); +String context = + Text.encodeIllegalXMLCharacters(request.getContextPath()); +%> + + + + <%= title %> + + + + +
+ + +
+

<%= title %>

Property changes on: jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/header.jsp ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/images/0.gif =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Property changes on: jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/images/0.gif ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/images/asf-logo.gif =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Property changes on: jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/images/asf-logo.gif ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/images/asf-logo.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = image/png Property changes on: jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/images/asf-logo.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +image/png \ No newline at end of property Index: jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/images/favicon.ico =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Property changes on: jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/images/favicon.ico ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/images/jackrabbit.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = image/png Property changes on: jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/images/jackrabbit.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +image/png \ No newline at end of property Index: jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/images/jackrabbitlogo.gif =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Property changes on: jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/images/jackrabbitlogo.gif ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/images/jlogo.gif =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Property changes on: jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/images/jlogo.gif ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/index.jsp =================================================================== --- jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/index.jsp (nonexistent) +++ jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/index.jsp (working copy) @@ -0,0 +1,22 @@ +<%-- + 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. +--%><% +try { + Class.forName("javax.jcr.Repository"); +} catch (ClassNotFoundException e) { + throw new org.apache.jackrabbit.j2ee.JcrApiNotFoundException(e); +} +%> \ No newline at end of file Property changes on: jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/index.jsp ___________________________________________________________________ Added: svn Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/local.jsp =================================================================== --- jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/local.jsp (nonexistent) +++ jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/local.jsp (working copy) @@ -0,0 +1,103 @@ +<%-- + 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. +--%><%@page import="org.apache.jackrabbit.util.Text"%><% +request.setAttribute("title", "Local Repository Access"); +%> +

+ The content repository within this web application can be accessed + locally by other web applications within the same servlet container. + Local access is much faster than remote access. +

+

+ The content repository is made available both through JNDI and the + web application context. +

+ +

Accessing the repository through JNDI

+

+ By default the repository is only made available in a dummy JNDI directory + local to this web application. However, you can make the repository globally + available if your servlet container allows a web application to modify the + global JNDI directory or you are using some other JNDI directory that can + manage unserializable Java objects. +

+

+ To bind the the repository to such a JNDI directory, you need to modify + the java.naming parameters in either the /WEB-INF/web.xml + deployment descriptor or the jackrabbit/bootstrap.properties file. You need + to redeploy this web application to activate the changes. +

+

+ Use the following code to access a repository bound in a JNDI directory: +

+
+import javax.jcr.Repository;
+import javax.naming.Context;
+import javax.naming.InitialContext;
+
+Context context = new InitialContext(...);
+Repository repository = (Repository) context.lookup(...);
+
+ +

Accessing the repository through servlet context

+

+ This web application makes the repository available as the + javax.jcr.Repository attribute in the application context. + If your servlet container supports cross-context access, you can + access the repository directly using that attribute. +

+

+ For example in Apache Tomcat + you can enable cross-context access by setting the crossContext + attribute to true in the <Context/> configuration. +

+

+ Use the following code to access a repository through the servlet context: +

+
+import javax.jcr.Repository;
+import javax.servlet.ServletContext;
+
+ServletContext context = ...; // context of your servlet
+ServletContext jackrabbit =
+    context.getContext("<%= Text.encodeIllegalXMLCharacters(request.getContextPath()) %>");
+Repository repository = (Repository)
+    context.getAttribute(Repository.class.getName()).
+
+ +

Using the jackrabbit-jcr-servlet component

+

+ The jackrabbit-jcr-servlet component contains utility classes + for use within JCR web applications. With that component you can hide + both the above and the remote access options + from your code, and use just the following to access a repository: +

+
+import javax.jcr.Repository;
+import org.apache.jackrabbit.servlet.ServletRepository;
+
+public class MyServlet extends HttpServlet {
+
+    private final Repository repository = new ServletRepository(this);
+
+    // ...
+
+}
+
+

+ See the jackrabbit-jcr-servlet documentation for more details. +

+ Property changes on: jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/local.jsp ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/remote.jsp =================================================================== --- jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/remote.jsp (nonexistent) +++ jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/remote.jsp (working copy) @@ -0,0 +1,106 @@ +<%@ page import="java.net.URI"%><%-- + 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. +--%><%@page import="org.apache.jackrabbit.util.Text"%><% +request.setAttribute("title", "Remote Repository Access"); + +URI uri = new URI(request.getRequestURL().toString()); +String base = + uri.getScheme() + "://" + uri.getHost() + ":" + uri.getPort() + + request.getContextPath(); +base = Text.encodeIllegalXMLCharacters(base); +%> +

+ The content repository within this web application is made available + to remote clients through + RMI + and the jackrabbit-jcr-rmi component. +

+

+ The remote repository stub is available both in the RMI registry + (one is started automatically by this web application if not already running) + and as a direct HTTP download. The default URLs for accessing the remote + repository are: +

+
    +
  • RMI registry: //localhost/jackrabbit.repository
  • +
  • HTTP download: <%= base %>/rmi
  • +
+

+ Note that the above URLs are the defaults. You can disable or change them + by modifying the /WEB-INF/web.xml deployment descriptor. +

+ +

Accessing the remote repository

+

+ To access the remote content repository you need to use the + jackrabbit-jcr-rmi component in your application. If you use + Maven 2, you can declare the JCR and jackrabbit-jcr-rmi dependencies + like this: +

+
<dependency>
+  <groupId>javax.jcr</groupId>
+  <artifactId>jcr</artifactId>
+  <version>1.0</version>
+</dependency>
+<dependency>
+  <groupId>org.apache.jackrabbit</groupId>
+  <artifactId>jackrabbit-jcr-rmi</artifactId>
+  <version>1.4</version>
+</dependency>
+
+

+ With that dependency in place, you can use either the RMI registry or + the direct HTTP download to access the repository. +

+

+ The required code for accessing the repository using the RMI registry is: +

+
+import javax.jcr.Repository;
+import org.apache.jackrabbit.rmi.repository.RMIRemoteRepository;
+
+Repository repository =
+    new RMIRemoteRepository("//localhost/jackrabbit.repository");
+
+

+ The required code for accessing the repository using the RMI registry is: +

+
+import javax.jcr.Repository;
+import org.apache.jackrabbit.rmi.repository.URLRemoteRepository;
+
+Repository repository =
+    new URLRemoteRepository("<%= base %>/rmi");
+
+

+ See the JCR specification + and the + Repository + javadoc for details on what to do with the acquired Repository instance. +

+ +

Remote access performance

+

+ Note that the design goal of the current jackrabbit-jcr-rmi component + is correct and complete functionality instead of performance, so you should + not rely on remote access for performance-critical applications. +

+

+ You may want to look at the Jackrabbit clustering feature for best + performance for concurrently accessing the repository on multiple separate + servers. +

+ Property changes on: jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/remote.jsp ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/remoting/footer.jsp =================================================================== --- jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/remoting/footer.jsp (nonexistent) +++ jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/remoting/footer.jsp (working copy) @@ -0,0 +1,25 @@ +<%-- + 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. +--%> + +
+ + Property changes on: jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/remoting/footer.jsp ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +author date id revision \ No newline at end of property Index: jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/remoting/header.jsp =================================================================== --- jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/remoting/header.jsp (nonexistent) +++ jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/remoting/header.jsp (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. +--%> +<%@page import="org.apache.jackrabbit.util.Text"%> +<% +String context = Text.encodeIllegalXMLCharacters(request.getContextPath()); +%> + + + + JCR Remoting Server + + + + +
+ + Property changes on: jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/remoting/header.jsp ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +author date id revision \ No newline at end of property Index: jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/remoting/index.jsp =================================================================== --- jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/remoting/index.jsp (nonexistent) +++ jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/remoting/index.jsp (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. +--%><% +%> +
+

JCR Remoting Server - Introduction

+

Ths section shortly overviews the batch read/write extensions + added to the JCR remoting feature. +

+

+

Some principals are demonstrated in the corresponding example section.

+
+ \ No newline at end of file Property changes on: jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/remoting/index.jsp ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +author date id revision \ No newline at end of property Index: jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/remoting/json.js =================================================================== --- jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/remoting/json.js (nonexistent) +++ jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/remoting/json.js (working copy) @@ -0,0 +1,222 @@ +/* + 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. +*/ + +function getXMLHttpRequest(url, method, headers, params) { + var xmlhttp = null; + if (window.XMLHttpRequest) { + // code for all new browsers + xmlhttp = new XMLHttpRequest(); + } else if (window.ActiveXObject) { + // code for IE + try { + xmlhttp = new ActiveXObject("Msxml2.XMLHTTP"); + } catch (e) { + xmlhttp = new ActiveXObject("Microsoft.XMLHTTP"); + } + } + if (xmlhttp) { + if (!method) { + method = "GET"; + } + xmlhttp.open(method, url, false); + if (headers) { + for (var hdr in headers) { + xmlhttp.setRequestHeader(hdr, headers[hdr]); + } + } + xmlhttp.send(params); + return xmlhttp; + } else { + alert("Your browser does not support XMLHTTP."); + return null; + } +} + +var JsonFormatter = null; +(function() { + + JsonFormatter = new Object(); + JsonFormatter.clear = false; + + JsonFormatter.tree = function(jsonObj, baseHref) { + if (!jsonObj) { + return ""; + } + var indentionLevel = 0; + return JsonFormatter.objectTree("", jsonObj, indentionLevel, baseHref); + } + + JsonFormatter.format = function(jsonObj, clearSpecial) { + if (!jsonObj) { + return ""; + } + var indentionLevel = 0; + clear = clearSpecial; + return JsonFormatter.object(jsonObj, indentionLevel); + } + + JsonFormatter.addLineBreak = function(str) { + return str += "
"; + } + + JsonFormatter.addIndention = function(str, indention, indStr) { + for (var i = 0; i < indention; i++) { + str += indStr; + } + return str; + } + + JsonFormatter.object = function(value, indentionLevel) { + if (value instanceof Array) { + return JsonFormatter.array(value, indentionLevel); + } + + var str = "{"; + str = JsonFormatter.addLineBreak(str); + indentionLevel++; + var delim = false; + + for (var i in value) { + var v = value[i]; + if (clear && i.charAt(0) == ':') { + // skip special prop. + // TODO: evaluate and add to display info. + } else { + var fnctn = JsonFormatter[typeof v]; + if (fnctn) { + v = fnctn(v, indentionLevel); + if (typeof v == 'string') { + if (delim) { + str += ","; + str = JsonFormatter.addLineBreak(str); + } + str = JsonFormatter.addIndention(str, indentionLevel, "\t"); + str += JsonFormatter.string(i) + ' : ' + v; + delim = true; + } + } + } + } + indentionLevel--; + str = JsonFormatter.addLineBreak(str); + str = JsonFormatter.addIndention(str, indentionLevel, "\t"); + str += "}"; + return str; + } + + JsonFormatter.array = function(value, indentionLevel) { + var str = "["; + var delim = false; + for (var i in value) { + var arrVal = value[i]; + var fnctn = JsonFormatter[typeof arrVal]; + if (fnctn) { + arrVal = fnctn(arrVal); + if (delim) { + str += ", "; + } + str += arrVal; + delim = true; + } + } + str += "]"; + return str; + } + + JsonFormatter.boolean = function(value, indentionLevel) { + return String(value); + } + + JsonFormatter.string = function(value, indentionLevel) { + return '"' + value + '"'; + + } + + JsonFormatter.number = function(value, indentionLevel) { + return String(value); + } + + JsonFormatter.extractPropertyType = function(key, value) { + if (key == "::NodeIteratorSize") { + return null; + } else if (key.charAt(0) == ':' && typeof value == 'string') { + return value; + } else { + return null; + } + } + + JsonFormatter.buildKey = function(key, propType, href) { + var keyStr = key; + if (propType) { + var href = "javascript:alert('PropertyType = " + propType + "');"; + keyStr = "" + key + ""; + } else if (key.charAt(0) == ':') { + // binary + var propname = key.substring(1, key.length); + var binHref = href + "/" + propname; + keyStr = "" + propname + ""; + } + return keyStr; + } + + JsonFormatter.objectTree = function(key, value, indentionLevel, href) { + var str = "+ " + key; // + node-name + if (href && href.charAt(href.length - 1) == '/') { + href += key; + } else { + href += "/" + key; + } + + indentionLevel++; + var propType; + var childSize; + var delim = false; + + for (var i in value) { + var v = value[i]; + var pt = JsonFormatter.extractPropertyType(i, v); + if (pt) { + propType = pt; + continue; + } else if (i == "::NodeIteratorSize") { + continue; + } + str = JsonFormatter.addLineBreak(str); + str = JsonFormatter.addIndention(str, indentionLevel, "  "); + if (v instanceof Array) { + // value array - propname + var key = JsonFormatter.buildKey(i, propType, href); + propType = null; + str += "- " + key + ' = ' + JsonFormatter.array(v, indentionLevel); + } else if (v instanceof Object) { + str += JsonFormatter.objectTree(i, v, indentionLevel, href); + } else { + // simple value - propname + var fnctn = JsonFormatter[typeof v]; + if (fnctn) { + v = fnctn(v, indentionLevel); + var key = JsonFormatter.buildKey(i, propType, href); + propType = null; + str += "- " + key + ' = ' + v; + } + } + } + indentionLevel--; + return str; + } +})(); Property changes on: jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/remoting/json.js ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/remoting/read.jsp =================================================================== --- jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/remoting/read.jsp (nonexistent) +++ jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/remoting/read.jsp (working copy) @@ -0,0 +1,65 @@ +<%@ page import="java.net.URI" %> +<%@ page import="org.apache.jackrabbit.j2ee.JcrRemotingServlet" %> +<%@ page import="org.apache.jackrabbit.util.Text" %> +<%-- + 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. +--%><% + +URI uri = new URI(request.getRequestURL().toString()); +String href = + uri.getScheme() + "://" + uri.getHost() + ":" + uri.getPort() + + request.getContextPath() + + JcrRemotingServlet.getPathPrefix(pageContext.getServletContext()); +href = Text.encodeIllegalXMLCharacters(href); +href += "/default/jcr:root"; + +%> +
+

Read

+

Default Reading

+

Reading remotely from the repository generally follows the rules described in + JCR_Webdav_Protocol.zip. +

+

Batch Read

+

Batch read is triggered by adding a '.json' extension to the resource + href. Optionally the client may explicitely specify the desired batch + read depth by appending '.depth.json' extension. If no json extension + is present the GET request is processed by applied the default + remoting rules. +

+

The response to a batch read request contains a plain text representing + a JSON object. Its member either represent nodes or properties. +

    +
  • The name element of the Item path is added as key
  • +
  • The value of a Node entry is a JSON object.
  • +
  • The value of a Property entry is either a JSON array or a simple JSON value.
  • +
+

+

In order to cope with property types that cannot be expressed with JSON + a couple of special rules are defined: +

    +
  • Binary properties: The key gets a leading ":", the value represents the + length of the property. In order to retrieve the binary value, the + client must follow the default rules (see above).
  • +
  • Date, Name, Path and Reference properties: The type information is passed with a separate JSON pair.
  • +
  • The value of a Property entry is either a JSON array or a simple JSON value.
  • +
+

+ See Example: Batch Write for a demostration of + the batch read functionality. +

+
+ \ No newline at end of file Property changes on: jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/remoting/read.jsp ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +author date id revision \ No newline at end of property Index: jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/remoting/read_batch.jsp =================================================================== --- jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/remoting/read_batch.jsp (nonexistent) +++ jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/remoting/read_batch.jsp (working copy) @@ -0,0 +1,104 @@ +<%@ page import="java.net.URI" %> +<%@ page import="org.apache.jackrabbit.j2ee.JcrRemotingServlet" %> +<%@ page import="org.apache.jackrabbit.util.Text" %> +<%-- + 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. +--%><% + +URI uri = new URI(request.getRequestURL().toString()); +String href = + uri.getScheme() + "://" + uri.getHost() + ":" + uri.getPort() + + request.getContextPath() + + JcrRemotingServlet.getPathPrefix(pageContext.getServletContext()); +href = Text.encodeIllegalXMLCharacters(href); +href += "/default/jcr:root"; + +%> + + +
+

Examples: Batch Read

+

+ Enter the path of an existing node and the desired depth. +

+ + + + + + + + + + + + + + +
Node Path
Depth
Result type
+

+


+
+ \ No newline at end of file Property changes on: jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/remoting/read_batch.jsp ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +author date id revision \ No newline at end of property Index: jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/remoting/write.jsp =================================================================== --- jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/remoting/write.jsp (nonexistent) +++ jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/remoting/write.jsp (working copy) @@ -0,0 +1,161 @@ +<%@ page import="java.net.URI" %> +<%@ page import="org.apache.jackrabbit.j2ee.JcrRemotingServlet" %> +<%@ page import="org.apache.jackrabbit.util.Text" %> +<%-- + 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. +--%><% + +URI uri = new URI(request.getRequestURL().toString()); +String href = + uri.getScheme() + "://" + uri.getHost() + ":" + uri.getPort() + + request.getContextPath() + + JcrRemotingServlet.getPathPrefix(pageContext.getServletContext()); +href = Text.encodeIllegalXMLCharacters(href); +href += "/default/jcr:root"; + +%> +
+

Write

+

Default Writing

+

Writing remotely to the repository generally follows the rules described in + JCR_Webdav_Protocol.zip. +

+

Batch Write

+

A set of transient modifications can in addition be sent by using the + extended batch write: A single POST request that contains a custom + :diff parameter describing the changes to be applied. + The expected format is described in the + JavaDoc. +

+ Some cases however can be easily demonstrated. The following examples can + be tested with the form provided at + Example: Batch Write. +

+

Examples

+

The following examples illustrate the basics of the diff format. It does + not cover the special treatment of properties with type Date, + Name, Path, Reference and Binary (see below).

+

Set properties

+
+^prop1  : "stringvalue"
+^prop1  : "changedvalue"
+^prop2  : true
+^prop3  : 100.010
+^prop4  : 1234567890
+^prop5  : ["multi","valued","string prop"]
+^.      : "change existing property at path."
+^/abs/path/to/the/new/prop : "some value."
+

Add new nodes (optionally including child items)

+
++node   : {"title" : "title property of the new node"}
++node2  : {"childN" : {}, "childN2" : {}}
++/abs/path/to/the/new/node : {"text" : "some text"}
+

Move or rename nodes

+
+>node   : rename
+>rename : /moved/to/another/destination
+

Reorder nodes

+
+>childN : childN2#after
+>childN : #first
+>childN : #last
+>childN : childN2#before
+

Remove items

+
+-prop4  :
+-node2  :
+-/moved/to/another/destination :
+

Dealing with Special Property Types

+

Property types that can not be covered unambigously, need some special + handling (see JavaDoc). This affects JCR properties being of type +

    +
  • Date,
  • +
  • Name,
  • +
  • Path,
  • +
  • Reference,
  • +
  • Binary.
  • +
+ In order to set properties of any of the types listed, the value part in the + :diff param must be left empty and a separate request parameter must be + included. Its name equals the corresponding key in the :diff, its value represents + the property value. In addition the desired property type must be specified + using the conversion defined with + JcrValueType#contentTypeFromType(int). +

+

Set a Date property

+
+POST /jackrabbit/server/default/jcr%3aroot/testNode HTTP/1.1
+Content-Type: multipart/form-data; boundary=kTmAb2lkjCtxbMVFzHEplAJjHCUo5aQndaUu
+
+--kTmAb2lkjCtxbMVFzHEplAJjHCUo5aQndaUu
+Content-Disposition: form-data; name="dateProp"
+Content-Type: jcr-value/date
+
+2009-02-12T10:19:40.778+01:00         
+--kTmAb2lkjCtxbMVFzHEplAJjHCUo5aQndaUu
+Content-Disposition: form-data; name=":diff"
+Content-Type: text/plain
+
+^dateProp :  
+--kTmAb2lkjCtxbMVFzHEplAJjHCUo5aQndaUu--
+    
+

Setting Binary, Name, Path or Reference + properties works accordingly. +

+ +

Direct Content Editing

+

The functionality present with batch reading also enables very simplified + content editing using common HTML forms.

+

The :diff parameter is omitted altogether and each request parameter is + treated as property +

    +
  • param name : property name
  • +
  • param value : property value
  • +
+ whereas the form action indicates the path of the parent node. +

+

If no node exists at the specified path an attempt is made to create the + missing intermediate nodes. The primary node type of the new node is + either retrieved from the corresponding jcr:primaryType param or + automatically determined by the implementation.

+

Setting a property can be tested at + Example: Simplified Writing +

+

Examples

+

The following examples illustrate the simplified writing.

+

Set string property +

    +
  • Existing or non-existing node at /testnode
  • +
  • Set property 'propName' with value "any string value"
  • +
+

+
+<form method="POST" action="<%= href %>/testnode">
+    <input type="text" name="propName" value="any string value"/>
+</form>
+

Add node with a defined node type and set a property

+
    +
  • Non-existing node at /testnode/nonexisting
  • +
  • Define its primary type to be "nt:unstructured"
  • +
  • Set property 'propName' with value "any string value"
  • +
+
+<form method="POST" action="<%= href %>/nonexisting">
+    <input type="text" name="jcr:primaryType" value="nt:unstructured"/>
+    <input type="text" name="propName" value="any string value"/>
+</form>
+
+ \ No newline at end of file Property changes on: jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/remoting/write.jsp ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +author date id revision \ No newline at end of property Index: jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/remoting/write_batch.jsp =================================================================== --- jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/remoting/write_batch.jsp (nonexistent) +++ jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/remoting/write_batch.jsp (working copy) @@ -0,0 +1,84 @@ +<%@ page import="java.net.URI" %> +<%@ page import="org.apache.jackrabbit.j2ee.JcrRemotingServlet" %> +<%@ page import="org.apache.jackrabbit.util.Text" %> +<%-- + 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. +--%><% + +URI uri = new URI(request.getRequestURL().toString()); +String href = + uri.getScheme() + "://" + uri.getHost() + ":" + uri.getPort() + + request.getContextPath() + + JcrRemotingServlet.getPathPrefix(pageContext.getServletContext()); +href = Text.encodeIllegalXMLCharacters(href); +href += "/default/jcr:root"; + +%> + + +
+

Examples: Batch Write

+

+ Enter the path of an existing node or property (depending on the desired + actions) and enter the :diff value. +

+

See the introduction to batched writing + for examples. +

+ + + + + + + + + + +
Item Path
Diff
+

+


+
+ \ No newline at end of file Property changes on: jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/remoting/write_batch.jsp ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +author date id revision \ No newline at end of property Index: jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/remoting/write_simple.jsp =================================================================== --- jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/remoting/write_simple.jsp (nonexistent) +++ jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/remoting/write_simple.jsp (working copy) @@ -0,0 +1,101 @@ +<%@ page import="java.net.URI" %> +<%@ page import="org.apache.jackrabbit.j2ee.JcrRemotingServlet" %> +<%@ page import="org.apache.jackrabbit.util.Text" %> +<%-- + 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. +--%><% + +URI uri = new URI(request.getRequestURL().toString()); +String href = + uri.getScheme() + "://" + uri.getHost() + ":" + uri.getPort() + + request.getContextPath() + + JcrRemotingServlet.getPathPrefix(pageContext.getServletContext()); +href = Text.encodeIllegalXMLCharacters(href); +href += "/default/jcr:root"; + +%> + + +
+

Examples: Simplified Writing

+

If the JCR node at the specified absolute path allows to set a properties + with name title or text, submitting the form below will + will set those properties to the given values.

+

If no JCR node exists at the specified absolute path, the missing + intermediate nodes will be created if an applicable node type for the + specified node name(s) can be determined.

+ + + + + + + + + + + + + + +
Node Path
Title
Text
+

+


+
+ \ No newline at end of file Property changes on: jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/remoting/write_simple.jsp ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +author date id revision \ No newline at end of property Index: jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/search.jsp =================================================================== --- jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/search.jsp (nonexistent) +++ jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/search.jsp (working copy) @@ -0,0 +1,254 @@ +<%-- + 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. +--%><%@ page import="javax.jcr.Repository, + org.apache.jackrabbit.j2ee.RepositoryAccessServlet, + org.apache.jackrabbit.util.Text, + javax.jcr.Session, + javax.jcr.SimpleCredentials, + javax.jcr.query.Query, + javax.jcr.query.RowIterator, + java.text.NumberFormat, + javax.jcr.query.Row, + javax.jcr.Node, + java.net.URLEncoder, + java.text.SimpleDateFormat, + java.text.DateFormat, + java.util.List, + java.util.ArrayList, + java.util.Iterator, + javax.jcr.Value, + javax.jcr.RepositoryException"%> +<%@ page contentType="text/html;charset=UTF-8" %><% + Repository rep; + Session jcrSession; + try { + rep = RepositoryAccessServlet.getRepository(pageContext.getServletContext()); + jcrSession = rep.login(new SimpleCredentials("anonymous", "".toCharArray())); + } catch (Throwable e) { + %>Error while accessing the repository: <%= Text.encodeIllegalXMLCharacters(e.getMessage()) %>
<% + %>Check the configuration or use the easy setup wizard.<% + return; + } + try { + String wspName = jcrSession.getWorkspace().getName(); + String q = request.getParameter("q"); + if (q == null) { + q = ""; + } else { + q = new String(q.getBytes("ISO-8859-1"), "UTF-8"); + } + if (request.getParameter("as_q") != null) { + q += " " + new String(request.getParameter("as_q").getBytes("ISO-8859-1"), "UTF-8"); + } + String executedIn = ""; + String queryTerms = ""; + String totalResults = ""; + long from = 0; + long to = 10; + long total = 0; + long maxPage = 0; + long minPage = 0; + long currentPageIndex = 0; + List indexes = new ArrayList(); + RowIterator rows = null; + String suggestedQuery = null; + if (q != null && q.length() > 0) { + String stmt; + if (q.startsWith("related:")) { + String path = q.substring("related:".length()); + path = path.replaceAll("'", "''"); + stmt = "//element(*, nt:file)[rep:similar(jcr:content, '" + path + "/jcr:content')]/rep:excerpt(.) order by @jcr:score descending"; + queryTerms = "similar to " + Text.encodeIllegalXMLCharacters(path) + ""; + } else { + queryTerms = "for " + Text.encodeIllegalXMLCharacters(q) + ""; + q = q.replaceAll("'", "''"); + stmt = "//element(*, nt:file)[jcr:contains(jcr:content, '" + q + "')]/rep:excerpt(.) order by @jcr:score descending"; + } + Query query = jcrSession.getWorkspace().getQueryManager().createQuery(stmt, Query.XPATH); + long time = System.currentTimeMillis(); + rows = query.execute().getRows(); + time = System.currentTimeMillis() - time; + NumberFormat nf = NumberFormat.getNumberInstance(); + nf.setMaximumFractionDigits(2); + nf.setMinimumFractionDigits(2); + executedIn = nf.format(((double) time) / 1000d); + nf.setMaximumFractionDigits(0); + totalResults = nf.format(rows.getSize()); + if (request.getParameter("start") != null) { + from = Long.parseLong(request.getParameter("start")); + try { + rows.skip(from); + } catch (Exception e) { + // make sure rows are consumed + while (rows.hasNext()) { + rows.nextRow(); + } + } + } + to = Math.min(from + 10, rows.getSize()); + + total = rows.getSize(); + maxPage = total / 10L; + if (total % 10L > 0) { + maxPage++; + } + currentPageIndex = from / 10L; + maxPage = Math.min(maxPage, currentPageIndex + 10); + minPage = Math.max(0, currentPageIndex - 10); + for (long i = minPage; i < maxPage; i++) { + indexes.add(new Long(i)); + } + + if (total < 10 && !q.startsWith("related:")) { + try { + Value v = jcrSession.getWorkspace().getQueryManager().createQuery( + "/jcr:root[rep:spellcheck('" + q + "')]/(rep:spellcheck())", + Query.XPATH).execute().getRows().nextRow().getValue("rep:spellcheck()"); + if (v != null) { + suggestedQuery = v.getString(); + } + } catch (RepositoryException e) { + // ignore + } + } + } +request.setAttribute("title", "Search workspace " + wspName); +%> + +
+

+ +

+

+
+<% if (rows != null && rows.getSize() == 0) { %> +<% if (suggestedQuery != null) { %> +

Did you mean: + + <%= Text.encodeIllegalXMLCharacters(suggestedQuery) %> +
+

+<% } %> +

Your search - <%= Text.encodeIllegalXMLCharacters(q) %> - did not match any documents. +

Suggestions: +

    +
  • Make sure all words are spelled correctly.
  • +
  • Try different keywords.
  • +
  • Try more general keywords.
  • +
  • Try fewer keywords.
  • +
+ <% + } else if (rows != null) { + %> + + + +
Results <%= from + 1 %> - <%= to %> of about <%= totalResults %> <%= queryTerms %>. (<%= executedIn %> seconds) 
+<% if (suggestedQuery != null) { %> +

+ Did you mean: + + <%= Text.encodeIllegalXMLCharacters(suggestedQuery) %> +
+

+<% } %> +
+ <% + while (rows.hasNext() && rows.getPosition() < to) { + Row r = rows.nextRow(); + Node file = (Node) jcrSession.getItem(r.getValue("jcr:path").getString()); + Node resource = file.getNode("jcr:content"); + String size = ""; + if (resource.hasProperty("jcr:data")) { + double length = resource.getProperty("jcr:data").getLength(); + size = String.valueOf(Math.round(Math.ceil(length / 1000d))) + "k"; + } + DateFormat df = SimpleDateFormat.getDateInstance(SimpleDateFormat.LONG); + String lastModified = df.format(resource.getProperty("jcr:lastModified").getDate().getTime()); + %> +
" class=l><%= Text.encodeIllegalXMLCharacters(file.getName()) %>
+ + + +
<%= r.getValue("rep:excerpt(jcr:content)").getString() %> + <%= Text.encodeIllegalXMLCharacters(file.getPath()) %> - <%= size %> - <%= lastModified %> - ">Similar pages
+ <% + } // while + %> +
+ +
+ <% + if (indexes.size() > 1) { + %> +
+ + +
Result Page:  + <% + if (currentPageIndex != ((Long) indexes.get(0)).longValue()) { + %>&start=<%= (currentPageIndex - 1) * 10 %>>Previous<% + } else { + %><% + } + for (Iterator it = indexes.iterator(); it.hasNext(); ) { + long pageIdx = ((Long) it.next()).longValue(); + if (pageIdx == currentPageIndex) { + %><%= pageIdx + 1 %><% + } else { + %>&start=<%= pageIdx * 10 %>><%= pageIdx + 1 %><% + } + } + if (currentPageIndex < (maxPage - 1)) { + %>&start=<%= (currentPageIndex + 1) * 10 %>>Next<% + } else { + %><% + } + %> +
+
+ <% + } + %> + + +

+ + +

/search.jsp> + +
+
+ Search within results | Dissatisfied? Help us improve
+
+
+ + <% + } // if (rows != null) + + String tableClass = ""; + if (rows != null && rows.getSize() == 0) { + tableClass = " class=\"t n bt\""; + } + %> + +<% + } finally { + if (jcrSession != null) { + jcrSession.logout(); + } + } +%> \ No newline at end of file Property changes on: jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/search.jsp ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/swr.jsp =================================================================== --- jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/swr.jsp (nonexistent) +++ jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/swr.jsp (working copy) @@ -0,0 +1,69 @@ +<%-- + 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. +--%><%@ page import="javax.jcr.Repository, + javax.jcr.Session, + org.apache.jackrabbit.j2ee.RepositoryAccessServlet, + org.apache.jackrabbit.util.Text, + javax.jcr.SimpleCredentials, + java.text.NumberFormat" +%><%@ page contentType="text/html;charset=UTF-8" %><% + Repository rep; + Session jcrSession; + try { + rep = RepositoryAccessServlet.getRepository(pageContext.getServletContext()); + jcrSession = rep.login(new SimpleCredentials("anonymous", "".toCharArray())); + } catch (Throwable e) { + %>Error while accessing the repository: <%= Text.encodeIllegalXMLCharacters(e.getMessage()) %>
<% + %>Check the configuration or use the easy setup wizard.<% + return; + } + try { + String q = new String(request.getParameter("q").getBytes("ISO-8859-1"), "UTF-8"); + String swrnum = request.getParameter("swrnum"); + String numResults = null; + try { + numResults = NumberFormat.getNumberInstance().format(Long.parseLong(swrnum)); + } catch (NumberFormatException e) { + // ignore + } + if (q == null || numResults == null) { + return; + } + + request.setAttribute("title", "Search within results"); + %> +
+ + + +

There were about <%= numResults %> results for <%= Text.encodeIllegalXMLCharacters(q) %>.
+ Use the search box below to search within these results.

+
+
+ + + +
+
+
+ +<% + } finally { + if (jcrSession != null) { + jcrSession.logout(); + } + } +%> \ No newline at end of file Property changes on: jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/swr.jsp ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/troubleshooting.jsp =================================================================== --- jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/troubleshooting.jsp (nonexistent) +++ jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/troubleshooting.jsp (working copy) @@ -0,0 +1,105 @@ +<%-- + 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. +--%><%@page import="org.apache.jackrabbit.util.Text, + java.io.StringWriter, + java.io.PrintWriter"%><% +request.setAttribute("title", "Troubleshooting"); +%> +

+ If you experience problems with the Jackrabbit JCR server, please + check the following: +

+
    +
  1. + Did you encounter an exception? Copy the exception stack trace somewhere + so you don't loose it. The stack trace contains valuable information + for the Jackrabbit developers if you need to file a bug report for the + problem you encountered. +
  2. +
  3. + Is the repository up and running? Try browsing the + default workspace + to check if you can still see any content in the repository. You will + see an error message if the repository is not available. +
  4. +
  5. + What were you trying to do? Try to verify that your client code or + other manner of repository use is correct. Did it work before or are + you trying to do something new? +
  6. +
  7. + Are there any notable log entries? Check the log files for any related + warnings or errors. By default the Jackrabbit JCR Server writes log + entries to the standard output of the servlet container. You can customize + logging by editing the /WEB-INF/log4j.xml file and + redeploying this web application. +
  8. +
+

+ If none of the above steps help you identify or resolve the problem, + you can contact the Jackrabbit users mailing list or report the problem + in the Jackrabbit issue tracker to get support from the Jackrabbit community. + When contacting the community, please include any relevant details related + to the above questions and the environment information shown at the end + of this page. +

+ +

Jackrabbit mailing list

+

+ The Jackrabbit user mailing list, users@jackrabbit.apache.org, is the + place to discuss any problems or other issues regarding the use of + Apache Jackrabbit (or JCR content repositories in general). +

+

+ Feel free to subscribe the mailing list or browse the archives listed as + described in the + Jackrabbit mailing lists + page. +

+ +

Jackrabbit issue tracker

+

+ If you think you've identified a defect in Jackrabbit, you're welcome + to file a bug report in the + Jackrabbit issue tracker. + You can also use the issue tracker to request new features and other + improvements. +

+

+ You need an account in the issue tracker to report new issues or to comment + on existing. Use the + registration form + if you don't already have an account. No account is needed browsing + and searching existing issues. +

+ +

Environment information

+

+ This instance of the Jackrabbit JCR Server is running in + a <%= Text.encodeIllegalXMLCharacters(application.getServerInfo()) %> servlet container + that supports the Java Servlet API version + <%= application.getMajorVersion() %>.<%= application.getMinorVersion() %>. +

+

+ Details of the Java and operating system environment are included in + the system properties shown below: +

+<% +StringWriter buffer = new StringWriter(); +System.getProperties().list(new PrintWriter(buffer)); +%> +
<%= Text.encodeIllegalXMLCharacters(buffer.toString()) %>
+ Property changes on: jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/troubleshooting.jsp ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/webdav-jcr.jsp =================================================================== --- jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/webdav-jcr.jsp (nonexistent) +++ jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/webdav-jcr.jsp (working copy) @@ -0,0 +1,88 @@ +<%@ page import="org.apache.jackrabbit.j2ee.JCRWebdavServerServlet, + java.net.URI" +%><%-- + 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. +--%><%@page import="org.apache.jackrabbit.util.Text"%><% +request.setAttribute("title", "JCR Remoting Server"); + +URI uri = new URI(request.getRequestURL().toString()); +int port = uri.getPort(); +String href = + uri.getScheme() + "://" + uri.getHost() + (port == -1 ? "" : (":" + port)) + + request.getContextPath() + + JCRWebdavServerServlet.getPathPrefix(pageContext.getServletContext()); +href = Text.encodeIllegalXMLCharacters(href); +String shref = href + "/default/jcr:root"; +%> +

+ The JCR Remoting Server provides an item-based WebDAV view to the + JCR repository, mapping the functionality provided by JSR 170 to the + WebDAV protocol in order to allow remote content repository access + via WebDAV. +

+

+ See the draft document + JCR_Webdav_Protocol.zip + for more details regarding this remoting protocol. +

+

+ Batch read and write as well as the missing functionality (cross workspace + copy and clone) has been addressed with a extension + to the remoting server. +

+ +

Access the content repository

+

+ Use the following URLs to access the content repository in your remoting client: +

+
+
<%= href %>
+
to access all workspaces of your JCR repository
+
<%= shref %>
+
to access a single workspace (example with workspace named 'default')
+
+ +

Supported WebDAV functionality

+

+ This implementation focuses on replicating all JCR features for remote + access instead of providing standard WebDAV functionality or compatibility + with existing WebDAV clients. +

+

+ The following RFCs are used to implement the remoting functionality: +

+ + +

JCR Remoting Client

+

+ For the client counterpart of this WebDAV servlet please take a look at the + Jackrabbit SPI2DAV + module. +

+ +

Configuration

+
    +
  • Context Path: <%= Text.encodeIllegalXMLCharacters(request.getContextPath()) %>
  • +
  • Resource Path Prefix: <%= Text.encodeIllegalXMLCharacters(JCRWebdavServerServlet.getPathPrefix(pageContext.getServletContext())) %>
  • +
  • Workspace Name: optional (available workspaces are mapped as resources)
  • +
  • Additional servlet configuration: see /WEB-INF/web.xml
  • +
+ Property changes on: jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/webdav-jcr.jsp ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/webdav-remoting.jsp =================================================================== --- jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/webdav-remoting.jsp (nonexistent) +++ jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/webdav-remoting.jsp (working copy) @@ -0,0 +1,92 @@ +<%@ page import="org.apache.jackrabbit.j2ee.JCRWebdavServerServlet, + java.net.URI" +%><%-- + 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. +--%><%@page import="org.apache.jackrabbit.util.Text"%> +<%@ page import="org.apache.jackrabbit.j2ee.JcrRemotingServlet" %> +<% +request.setAttribute("title", "JCR Remoting Server with Batch Read/Write"); + +URI uri = new URI(request.getRequestURL().toString()); +int port = uri.getPort(); +String href = + uri.getScheme() + "://" + uri.getHost() + (port == -1 ? "" : (":" + port)) + + request.getContextPath() + + JCRWebdavServerServlet.getPathPrefix(pageContext.getServletContext()); +href = Text.encodeIllegalXMLCharacters(href); +String shref = href + "/default/jcr:root"; +%> +

+ The JCR Remoting Server provides an item-based WebDAV view to the + JCR repository, mapping the functionality provided by JSR 170 to the + WebDAV protocol in order to allow remote content repository access + via WebDAV. +

+

+ This implementation variant adds batch read and write functionality to the initial + JCR Remoting Server. In addition it supports + copy across workspaces and clone. +

+ +

Access the content repository

+

+ Use the following URLs to access the content repository in the remoting client: +

+
+
<%= href %>
+
to access all workspaces of your JCR repository
+
<%= shref %>
+
to access a single workspace (example with workspace named 'default')
+
+ +

Supported WebDAV functionality

+

+ See JCR Remoting Server. +

+ +

Batch Read

+

+Composes a JSON object for a node (and its child items) up to a explicitely +specified or configuration determined depth. +
+See JavaDoc for details +or try the Examples. +

+ +

Batch Write

+

+In contrast to the default JCR remoting this extended version allows to send +a block of modifications (SPI Batch) within a single POST request containing a +custom ":diff" parameter. +
+See the JavaDoc for details +or try the Examples. +

+ +

JCR Remoting Client

+

+ For the client counterpart of this WebDAV servlet please take a look at the extended SPI2DAV + project. +

+ +

Configuration

+
    +
  • Context Path: <%= Text.encodeIllegalXMLCharacters(request.getContextPath()) %>
  • +
  • Resource Path Prefix: <%= Text.encodeIllegalXMLCharacters(JcrRemotingServlet.getPathPrefix(pageContext.getServletContext())) %>
  • +
  • Workspace Name: optional (available workspaces are mapped as resources)
  • +
  • Additional servlet configuration: see /WEB-INF/web.xml
  • +
+ Property changes on: jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/webdav-remoting.jsp ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/webdav-simple.jsp =================================================================== --- jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/webdav-simple.jsp (nonexistent) +++ jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/webdav-simple.jsp (working copy) @@ -0,0 +1,84 @@ +<%@ page import="org.apache.jackrabbit.j2ee.SimpleWebdavServlet, + java.net.URI" +%><%-- + 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. +--%><%@page import="org.apache.jackrabbit.util.Text"%><% +request.setAttribute("title", "Standard WebDAV Server"); + +URI uri = new URI(request.getRequestURL().toString()); +int port = uri.getPort(); +String href = + uri.getScheme() + "://" + uri.getHost() + (port == -1 ? "" : (":" + port)) + + request.getContextPath() + + SimpleWebdavServlet.getPathPrefix(pageContext.getServletContext()) + + "/default/"; +href = Text.encodeIllegalXMLCharacters(href); +%> + +

+ The default WebDAV server (aka: Simple Server) is a + DAV 1,2 and + DeltaV + compliant WebDAV server implementation. It offers a file-based view to + the JCR repository, suitable for everybody looking for standard WebDAV + functionality. Essentially, the contents of the underlying content + repository are exposed as a hierarchical collection of files and folders. +

+ +

Access the content repository

+

+ Use the following URL to access the content repository in your WebDAV client: +

+ +

+ The server asks for authentication and will accept credentials for the default + admin user: admin/admin. You can modify this security policy in + the repository configuration file. +

+

+ To access other workspace than the default one, replace the last part of + the URL (/default/) with the name of another workspace. +

+

+ You can also search the default workspace. +

+ +

File system access

+

+ Many operating systems, including Windows and Mac OS X, allow you to + "mount" a WebDAV server as a shared network disk. You can use the above + URL to make the default workspace available as such a network disk, after + which you can use normal file system tools to copy files and folders to + and from the content repository. +

+ +

Supported WebDAV functionality

+ + +

Configuration

+
    +
  • Context path: <%= Text.encodeIllegalXMLCharacters(request.getContextPath()) %>
  • +
  • Resource path prefix: <%= Text.encodeIllegalXMLCharacters(SimpleWebdavServlet.getPathPrefix(pageContext.getServletContext())) %>
  • +
  • Servlet configuration: see /WEB-INF/web.xml
  • +
  • WebDAV specific resource configuration: see /WEB-INF/config.xml
  • +
+ Property changes on: jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/webdav-simple.jsp ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/welcome.jsp =================================================================== --- jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/welcome.jsp (nonexistent) +++ jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/welcome.jsp (working copy) @@ -0,0 +1,60 @@ +<%@ page import="org.apache.jackrabbit.j2ee.RepositoryAccessServlet, + javax.jcr.Repository" +%><%-- + 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. +--%><% + +Repository rep; +try { + rep = RepositoryAccessServlet.getRepository(pageContext.getServletContext()); +} catch (Throwable e) { + %><% +} + +request.setAttribute("title", "Apache Jackrabbit JCR Server"); +%> +

+ Welcome to the Apache Jackrabbit JCR Server. This web application + contains a JCR content repository and makes it available to clients + through WebDAV and other means. +

+

+ The following WebDAV view is provided for accessing the + content in the JCR content repository. +

+ +

+ In addition the JCR Server project provides means for JCR remoting over HTTP: +

+ +

+ Clients can also access the repository using the JCR API. Both local + and remote access is supported. +

+ +

+ For more information, including copyright and licensing details, visit the + About Apache Jackrabbit page. +

+ Property changes on: jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/welcome.jsp ___________________________________________________________________ Added: svn Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webapp-project/jackrabbit-webapp/src/test/java/org/apache/jackrabbit/j2ee/TomcatIT.java =================================================================== --- jackrabbit-webapp-project/jackrabbit-webapp/src/test/java/org/apache/jackrabbit/j2ee/TomcatIT.java (nonexistent) +++ jackrabbit-webapp-project/jackrabbit-webapp/src/test/java/org/apache/jackrabbit/j2ee/TomcatIT.java (working copy) @@ -0,0 +1,137 @@ +/* + * 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.j2ee; + +import java.io.BufferedWriter; +import java.io.File; +import java.io.IOException; +import java.net.URL; +import java.nio.charset.StandardCharsets; +import java.util.List; + +import junit.framework.TestCase; + +import org.apache.catalina.startup.Tomcat; +import org.apache.commons.io.FileUtils; +import org.slf4j.bridge.SLF4JBridgeHandler; + +import com.gargoylesoftware.htmlunit.WebClient; +import com.gargoylesoftware.htmlunit.html.HtmlElement; +import com.gargoylesoftware.htmlunit.html.HtmlForm; +import com.gargoylesoftware.htmlunit.html.HtmlInput; +import com.gargoylesoftware.htmlunit.html.HtmlPage; +import com.google.common.io.Files; + +public class TomcatIT extends TestCase { + + static { + SLF4JBridgeHandler.install(); + } + + private URL url; + + private Tomcat tomcat; + + private WebClient client; + + protected void setUp() throws Exception { + File war = null; + for (File f : new File("target").listFiles()) { + if (f.isDirectory() && new File(f, "WEB-INF/web.xml").isFile()) { + war = f; + break; + } + } + assertNotNull(war); + rewriteWebXml(war); + + File bootstrap = new File("target", "bootstrap.properties"); + bootstrap.delete(); + + File baseDir = new File("target", "tomcat"); + FileUtils.deleteQuietly(baseDir); + + File repoDir = new File("target", "repository"); + FileUtils.deleteQuietly(repoDir); + + url = new URL("http://localhost:12856/"); + + tomcat = new Tomcat(); + tomcat.setSilent(true); + tomcat.setBaseDir(baseDir.getPath()); + tomcat.setHostname(url.getHost()); + tomcat.setPort(url.getPort()); + + tomcat.addWebapp("", war.getAbsolutePath()); + + tomcat.start(); + + client = new WebClient(); + } + + public void testTomcat() throws Exception { + HtmlPage page = client.getPage(url); + assertEquals("Content Repository Setup", page.getTitleText()); + + page = submitNewRepositoryForm(page); + assertEquals("Content Repository Ready", page.getTitleText()); + + page = page.getAnchorByText("home").click(); + assertEquals("Apache Jackrabbit JCR Server", page.getTitleText()); + } + + private HtmlPage submitNewRepositoryForm(HtmlPage page) throws IOException { + for (HtmlForm form : page.getForms()) { + for (HtmlInput mode : form.getInputsByName("mode")) { + if ("new".equals(mode.getValueAttribute())) { + for (HtmlInput home : form.getInputsByName("repository_home")) { + home.setValueAttribute("target/repository"); + for (HtmlElement submit : form.getElementsByAttribute("input", "type", "submit")) { + return submit.click(); + } + } + } + } + } + fail(); + return null; + } + + private void rewriteWebXml(File war) throws IOException { + File webXml = new File(war, new File("WEB-INF","web.xml").getPath()); + assertTrue(webXml.exists()); + List lines = Files.readLines(webXml, StandardCharsets.UTF_8); + BufferedWriter writer = Files.newWriter(webXml, StandardCharsets.UTF_8); + try { + for (String line : lines) { + line = line.replace("jackrabbit/bootstrap.properties", + "target/bootstrap.properties"); + writer.write(line); + writer.write(System.lineSeparator()); + } + } finally { + writer.close(); + } + } + + protected void tearDown() throws Exception { + client.close(); + + tomcat.stop(); + } + +} Property changes on: jackrabbit-webapp-project/jackrabbit-webapp/src/test/java/org/apache/jackrabbit/j2ee/TomcatIT.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webapp-project/jackrabbit-webapp/src/test/resources/compatibility.zip =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Property changes on: jackrabbit-webapp-project/jackrabbit-webapp/src/test/resources/compatibility.zip ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: jackrabbit-webapp-project/jackrabbit-webapp/src/test/resources/logback-test.xml =================================================================== --- jackrabbit-webapp-project/jackrabbit-webapp/src/test/resources/logback-test.xml (nonexistent) +++ jackrabbit-webapp-project/jackrabbit-webapp/src/test/resources/logback-test.xml (working copy) @@ -0,0 +1,31 @@ + + + + + + target/jcr.log + + %date{HH:mm:ss.SSS} %-5level %-40([%thread] %F:%L) %msg%n + + + + + + + + Property changes on: jackrabbit-webapp-project/jackrabbit-webapp/src/test/resources/logback-test.xml ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webapp-project/jackrabbit-webapp =================================================================== --- jackrabbit-webapp-project/jackrabbit-webapp (nonexistent) +++ jackrabbit-webapp-project/jackrabbit-webapp (working copy) Property changes on: jackrabbit-webapp-project/jackrabbit-webapp ___________________________________________________________________ Added: svn:ignore ## -0,0 +1,5 ## +target +.* +*.iws +*.ipr +*.iml Index: jackrabbit-jcr-server/README.txt =================================================================== --- jackrabbit-jcr-server/README.txt (revision 1907912) +++ jackrabbit-jcr-server/README.txt (nonexistent) @@ -1,93 +0,0 @@ -================================ -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/README.txt ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-jcr-server/pom.xml =================================================================== --- jackrabbit-jcr-server/pom.xml (revision 1907912) +++ jackrabbit-jcr-server/pom.xml (nonexistent) @@ -1,297 +0,0 @@ - - - - - - 4.0.0 - - - - - - org.apache.jackrabbit - jackrabbit-parent - 2.21.16-SNAPSHOT - ../jackrabbit-parent/pom.xml - - 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 - - - - - - - - - - - - - javax.jcr - jcr - - - org.apache.jackrabbit - jackrabbit-spi-commons - ${project.version} - - - org.apache.jackrabbit - jackrabbit-jcr-commons - ${project.version} - - - org.apache.jackrabbit - jackrabbit-webdav - ${project.version} - - - org.apache.tika - tika-core - - - org.slf4j - slf4j-api - - - javax.servlet - javax.servlet-api - provided - - - commons-fileupload - commons-fileupload - - - - - org.osgi - org.osgi.compendium - 5.0.0 - provided - - - org.apache.felix - org.apache.felix.scr.annotations - 1.12.0 - provided - - - org.osgi - org.osgi.annotation - provided - - - - junit - junit - test - - - org.easymock - easymock - test - - - org.apache.jackrabbit - jackrabbit-core - ${project.version} - test - - - org.apache.jackrabbit - jackrabbit-jcr-tests - ${project.version} - test - - - org.eclipse.jetty - jetty-server - test - - - org.eclipse.jetty - jetty-servlet - test - - - ch.qos.logback - logback-classic - test - - - org.mockito - mockito-core - test - - - org.apache.derby - derby - test - - - - Property changes on: jackrabbit-jcr-server/pom.xml ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-jcr-server/src/main/appended-resources/META-INF/NOTICE =================================================================== --- jackrabbit-jcr-server/src/main/appended-resources/META-INF/NOTICE (revision 1907912) +++ jackrabbit-jcr-server/src/main/appended-resources/META-INF/NOTICE (nonexistent) @@ -1,2 +0,0 @@ -Based on source code originally developed by -Day Software (http://www.day.com/). Property changes on: jackrabbit-jcr-server/src/main/appended-resources/META-INF/NOTICE ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/BasicCredentialsProvider.java =================================================================== --- jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/BasicCredentialsProvider.java (revision 1907912) +++ jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/BasicCredentialsProvider.java (nonexistent) @@ -1,120 +0,0 @@ -/* - * 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/src/main/java/org/apache/jackrabbit/server/BasicCredentialsProvider.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Deleted: svn:keywords ## -1 +0,0 ## -author date id revision url \ No newline at end of property Index: jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/CredentialsProvider.java =================================================================== --- jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/CredentialsProvider.java (revision 1907912) +++ jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/CredentialsProvider.java (nonexistent) @@ -1,39 +0,0 @@ -/* - * 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/src/main/java/org/apache/jackrabbit/server/CredentialsProvider.java ___________________________________________________________________ Deleted: svn Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/SessionProvider.java =================================================================== --- jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/SessionProvider.java (revision 1907912) +++ jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/SessionProvider.java (nonexistent) @@ -1,51 +0,0 @@ -/* - * 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/src/main/java/org/apache/jackrabbit/server/SessionProvider.java ___________________________________________________________________ Deleted: svn Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/SessionProviderImpl.java =================================================================== --- jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/SessionProviderImpl.java (revision 1907912) +++ jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/SessionProviderImpl.java (nonexistent) @@ -1,109 +0,0 @@ -/* - * 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/src/main/java/org/apache/jackrabbit/server/SessionProviderImpl.java ___________________________________________________________________ Deleted: svn Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/AbstractExportContext.java =================================================================== --- jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/AbstractExportContext.java (revision 1907912) +++ jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/AbstractExportContext.java (nonexistent) @@ -1,70 +0,0 @@ -/* - * 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/src/main/java/org/apache/jackrabbit/server/io/AbstractExportContext.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Deleted: svn:keywords ## -1 +0,0 ## -author date id revision url \ No newline at end of property Index: jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/BoundedInputStream.java =================================================================== --- jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/BoundedInputStream.java (revision 1907912) +++ jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/BoundedInputStream.java (nonexistent) @@ -1,183 +0,0 @@ -/* - * 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/src/main/java/org/apache/jackrabbit/server/io/BoundedInputStream.java ___________________________________________________________________ Deleted: svn Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/CopyMoveContext.java =================================================================== --- jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/CopyMoveContext.java (revision 1907912) +++ jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/CopyMoveContext.java (nonexistent) @@ -1,43 +0,0 @@ -/* - * 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/src/main/java/org/apache/jackrabbit/server/io/CopyMoveContext.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Deleted: svn:keywords ## -1 +0,0 ## -Author Date Id Revision Rev URL \ No newline at end of property Index: jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/CopyMoveContextImpl.java =================================================================== --- jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/CopyMoveContextImpl.java (revision 1907912) +++ jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/CopyMoveContextImpl.java (nonexistent) @@ -1,61 +0,0 @@ -/* - * 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/src/main/java/org/apache/jackrabbit/server/io/CopyMoveContextImpl.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Deleted: svn:keywords ## -1 +0,0 ## -Author Date Id Revision Rev URL \ No newline at end of property Index: jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/CopyMoveHandler.java =================================================================== --- jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/CopyMoveHandler.java (revision 1907912) +++ jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/CopyMoveHandler.java (nonexistent) @@ -1,75 +0,0 @@ -/* - * 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/src/main/java/org/apache/jackrabbit/server/io/CopyMoveHandler.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Deleted: svn:keywords ## -1 +0,0 ## -Author Date Id Revision Rev URL \ No newline at end of property Index: jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/CopyMoveManager.java =================================================================== --- jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/CopyMoveManager.java (revision 1907912) +++ jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/CopyMoveManager.java (nonexistent) @@ -1,62 +0,0 @@ -/* - * 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/src/main/java/org/apache/jackrabbit/server/io/CopyMoveManager.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Deleted: svn:keywords ## -1 +0,0 ## -Author Date Id Revision Rev URL \ No newline at end of property Index: jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/CopyMoveManagerImpl.java =================================================================== --- jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/CopyMoveManagerImpl.java (revision 1907912) +++ jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/CopyMoveManagerImpl.java (nonexistent) @@ -1,100 +0,0 @@ -/* - * 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/src/main/java/org/apache/jackrabbit/server/io/CopyMoveManagerImpl.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Deleted: svn:keywords ## -1 +0,0 ## -Author Date Id Revision Rev URL \ No newline at end of property Index: jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/DefaultHandler.java =================================================================== --- jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/DefaultHandler.java (revision 1907912) +++ jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/DefaultHandler.java (nonexistent) @@ -1,867 +0,0 @@ -/* - * 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 importProperties(PropertyImportContext importContext, boolean isCollection) throws RepositoryException { - if (!canImport(importContext, isCollection)) { - throw new RepositoryException("PropertyHandler " + getName() + " failed import properties"); - } - - // loop over List and remember all properties and propertyNames - // that failed to be imported (set or remove). - Map failures = new HashMap(); - List changeList = importContext.getChangeList(); - - // for collections the import-root is the target node where properties - // are altered. in contrast 'non-collections' are with the handler - // represented by 'file' nodes, that must have a jcr:content child - // node, which holds all properties except jcr:created. - // -> see canImport for the corresponding assertions - Node cn = (Node) importContext.getImportRoot(); - if (!isCollection && cn.hasNode(JcrConstants.JCR_CONTENT)) { - cn = cn.getNode(JcrConstants.JCR_CONTENT); - } - - if (changeList != null) { - 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/src/main/java/org/apache/jackrabbit/server/io/DefaultHandler.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Deleted: svn:keywords ## -1 +0,0 ## -author date id revision url \ No newline at end of property Index: jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/DefaultIOListener.java =================================================================== --- jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/DefaultIOListener.java (revision 1907912) +++ jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/DefaultIOListener.java (nonexistent) @@ -1,59 +0,0 @@ -/* - * 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/src/main/java/org/apache/jackrabbit/server/io/DefaultIOListener.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Deleted: svn:keywords ## -1 +0,0 ## -author date id revision url \ No newline at end of property Index: jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/DefaultIOManager.java =================================================================== --- jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/DefaultIOManager.java (revision 1907912) +++ jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/DefaultIOManager.java (nonexistent) @@ -1,53 +0,0 @@ -/* - * 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/src/main/java/org/apache/jackrabbit/server/io/DefaultIOManager.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Deleted: svn:keywords ## -1 +0,0 ## -author date id revision url \ No newline at end of property Index: jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/DeleteContext.java =================================================================== --- jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/DeleteContext.java (revision 1907912) +++ jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/DeleteContext.java (nonexistent) @@ -1,32 +0,0 @@ -/* - * 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/src/main/java/org/apache/jackrabbit/server/io/DeleteContext.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/DeleteContextImpl.java =================================================================== --- jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/DeleteContextImpl.java (revision 1907912) +++ jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/DeleteContextImpl.java (nonexistent) @@ -1,39 +0,0 @@ -/* - * 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/src/main/java/org/apache/jackrabbit/server/io/DeleteContextImpl.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/DeleteHandler.java =================================================================== --- jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/DeleteHandler.java (revision 1907912) +++ jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/DeleteHandler.java (nonexistent) @@ -1,51 +0,0 @@ -/* - * 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/src/main/java/org/apache/jackrabbit/server/io/DeleteHandler.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/DeleteManager.java =================================================================== --- jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/DeleteManager.java (revision 1907912) +++ jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/DeleteManager.java (nonexistent) @@ -1,54 +0,0 @@ -/* - * 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/src/main/java/org/apache/jackrabbit/server/io/DeleteManager.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/DeleteManagerImpl.java =================================================================== --- jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/DeleteManagerImpl.java (revision 1907912) +++ jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/DeleteManagerImpl.java (nonexistent) @@ -1,77 +0,0 @@ -/* - * 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/src/main/java/org/apache/jackrabbit/server/io/DeleteManagerImpl.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/DirListingExportHandler.java =================================================================== --- jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/DirListingExportHandler.java (revision 1907912) +++ jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/DirListingExportHandler.java (nonexistent) @@ -1,299 +0,0 @@ -/* - * 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(""); - writer.print(Text.encodeIllegalHTMLCharacters(repName)); - writer.print(" "); - writer.print(Text.encodeIllegalHTMLCharacters(repVersion)); - writer.print(" "); - writer.print(Text.encodeIllegalHTMLCharacters(item.getPath())); - writer.print(""); - writer.print("

"); - writer.print(Text.encodeIllegalHTMLCharacters(item.getPath())); - 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#exportContent(ExportContext, DavResource) - */ - public boolean exportContent(ExportContext context, DavResource resource) throws IOException { - if (!canExport(context, resource)) { - 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(""); - writer.print(Text.encodeIllegalHTMLCharacters(repName)); - writer.print(" "); - writer.print(Text.encodeIllegalHTMLCharacters(repVersion)); - writer.print(" "); - writer.print(Text.encodeIllegalHTMLCharacters(resource.getResourcePath())); - writer.print(""); - writer.print("

"); - writer.print(Text.encodeIllegalHTMLCharacters(resource.getResourcePath())); - 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 importProperties(PropertyImportContext importContext, boolean isCollection) throws RepositoryException { - // export facilities only -> throw - throw new RepositoryException(getName() + ": Cannot import properties."); - } -} Property changes on: jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/DirListingExportHandler.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Deleted: svn:keywords ## -1 +0,0 ## -author date id revision url \ No newline at end of property Index: jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/ExportContext.java =================================================================== --- jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/ExportContext.java (revision 1907912) +++ jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/ExportContext.java (nonexistent) @@ -1,84 +0,0 @@ -/* - * 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/src/main/java/org/apache/jackrabbit/server/io/ExportContext.java ___________________________________________________________________ Deleted: svn Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/ExportContextImpl.java =================================================================== --- jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/ExportContextImpl.java (revision 1907912) +++ jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/ExportContextImpl.java (nonexistent) @@ -1,200 +0,0 @@ -/* - * 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/src/main/java/org/apache/jackrabbit/server/io/ExportContextImpl.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Deleted: svn:keywords ## -1 +0,0 ## -author date id revision url \ No newline at end of property Index: jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/IOContext.java =================================================================== --- jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/IOContext.java (revision 1907912) +++ jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/IOContext.java (nonexistent) @@ -1,47 +0,0 @@ -/* - * 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/src/main/java/org/apache/jackrabbit/server/io/IOContext.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Deleted: svn:keywords ## -1 +0,0 ## -author date id revision url \ No newline at end of property Index: jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/IOHandler.java =================================================================== --- jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/IOHandler.java (revision 1907912) +++ jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/IOHandler.java (nonexistent) @@ -1,162 +0,0 @@ -/* - * 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/src/main/java/org/apache/jackrabbit/server/io/IOHandler.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Deleted: svn:keywords ## -1 +0,0 ## -author date id revision url \ No newline at end of property Index: jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/IOListener.java =================================================================== --- jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/IOListener.java (revision 1907912) +++ jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/IOListener.java (nonexistent) @@ -1,40 +0,0 @@ -/* - * 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/src/main/java/org/apache/jackrabbit/server/io/IOListener.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Deleted: svn:keywords ## -1 +0,0 ## -author date id revision url \ No newline at end of property Index: jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/IOManager.java =================================================================== --- jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/IOManager.java (revision 1907912) +++ jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/IOManager.java (nonexistent) @@ -1,118 +0,0 @@ -/* - * 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/src/main/java/org/apache/jackrabbit/server/io/IOManager.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Deleted: svn:keywords ## -1 +0,0 ## -author date id revision url \ No newline at end of property Index: jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/IOManagerImpl.java =================================================================== --- jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/IOManagerImpl.java (revision 1907912) +++ jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/IOManagerImpl.java (nonexistent) @@ -1,185 +0,0 @@ -/* - * 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/src/main/java/org/apache/jackrabbit/server/io/IOManagerImpl.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Deleted: svn:keywords ## -1 +0,0 ## -author date id revision url \ No newline at end of property Index: jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/IOUtil.java =================================================================== --- jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/IOUtil.java (revision 1907912) +++ jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/IOUtil.java (nonexistent) @@ -1,200 +0,0 @@ -/* - * 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/src/main/java/org/apache/jackrabbit/server/io/IOUtil.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Deleted: svn:keywords ## -1 +0,0 ## -author date id revision url \ No newline at end of property Index: jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/ImportContext.java =================================================================== --- jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/ImportContext.java (revision 1907912) +++ jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/ImportContext.java (nonexistent) @@ -1,96 +0,0 @@ -/* - * 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/src/main/java/org/apache/jackrabbit/server/io/ImportContext.java ___________________________________________________________________ Deleted: svn Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/ImportContextImpl.java =================================================================== --- jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/ImportContextImpl.java (revision 1907912) +++ jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/ImportContextImpl.java (nonexistent) @@ -1,221 +0,0 @@ -/* - * 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/src/main/java/org/apache/jackrabbit/server/io/ImportContextImpl.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Deleted: svn:keywords ## -1 +0,0 ## -author date id revision url \ No newline at end of property Index: jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/PropertyExportContext.java =================================================================== --- jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/PropertyExportContext.java (revision 1907912) +++ jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/PropertyExportContext.java (nonexistent) @@ -1,26 +0,0 @@ -/* - * 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/src/main/java/org/apache/jackrabbit/server/io/PropertyExportContext.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Deleted: svn:keywords ## -1 +0,0 ## -author date id revision url \ No newline at end of property Index: jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/PropertyHandler.java =================================================================== --- jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/PropertyHandler.java (revision 1907912) +++ jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/PropertyHandler.java (nonexistent) @@ -1,87 +0,0 @@ -/* - * 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 importProperties(PropertyImportContext importContext, boolean isCollection) throws RepositoryException; - -} \ No newline at end of file Property changes on: jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/PropertyHandler.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Deleted: svn:keywords ## -1 +0,0 ## -author date id revision url \ No newline at end of property Index: jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/PropertyImportContext.java =================================================================== --- jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/PropertyImportContext.java (revision 1907912) +++ jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/PropertyImportContext.java (nonexistent) @@ -1,46 +0,0 @@ -/* - * 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 getChangeList(); -} Property changes on: jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/PropertyImportContext.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Deleted: svn:keywords ## -1 +0,0 ## -author date id revision url \ No newline at end of property Index: jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/PropertyManager.java =================================================================== --- jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/PropertyManager.java (revision 1907912) +++ jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/PropertyManager.java (nonexistent) @@ -1,44 +0,0 @@ -/* - * 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 alterProperties(PropertyImportContext importContext, boolean isCollection) throws RepositoryException; - - /** - */ - public void addPropertyHandler(PropertyHandler propertyHandler); - - /** - */ - public PropertyHandler[] getPropertyHandlers(); -} Property changes on: jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/PropertyManager.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Deleted: svn:keywords ## -1 +0,0 ## -author date id revision url \ No newline at end of property Index: jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/PropertyManagerImpl.java =================================================================== --- jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/PropertyManagerImpl.java (revision 1907912) +++ jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/PropertyManagerImpl.java (nonexistent) @@ -1,111 +0,0 @@ -/* - * 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 alterProperties(PropertyImportContext context, boolean isCollection) throws RepositoryException { - Map 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/src/main/java/org/apache/jackrabbit/server/io/PropertyManagerImpl.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Deleted: svn:keywords ## -1 +0,0 ## -author date id revision url \ No newline at end of property Index: jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/VersionHandler.java =================================================================== --- jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/VersionHandler.java (revision 1907912) +++ jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/VersionHandler.java (nonexistent) @@ -1,139 +0,0 @@ -/* - * 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 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/src/main/java/org/apache/jackrabbit/server/io/VersionHandler.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Deleted: svn:keywords ## -1 +0,0 ## -author date id revision url \ No newline at end of property Index: jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/VersionHistoryHandler.java =================================================================== --- jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/VersionHistoryHandler.java (revision 1907912) +++ jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/VersionHistoryHandler.java (nonexistent) @@ -1,133 +0,0 @@ -/* - * 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 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/src/main/java/org/apache/jackrabbit/server/io/VersionHistoryHandler.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Deleted: svn:keywords ## -1 +0,0 ## -author date id revision url \ No newline at end of property Index: jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/XmlHandler.java =================================================================== --- jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/XmlHandler.java (revision 1907912) +++ jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/XmlHandler.java (nonexistent) @@ -1,207 +0,0 @@ -/* - * 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/src/main/java/org/apache/jackrabbit/server/io/XmlHandler.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Deleted: svn:keywords ## -1 +0,0 ## -author date id revision url \ No newline at end of property Index: jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/ZipHandler.java =================================================================== --- jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/ZipHandler.java (revision 1907912) +++ jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/io/ZipHandler.java (nonexistent) @@ -1,377 +0,0 @@ -/* - * 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/src/main/java/org/apache/jackrabbit/server/io/ZipHandler.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Deleted: svn:keywords ## -1 +0,0 ## -author date id revision url \ No newline at end of property Index: jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/jcr/JCRWebdavServer.java =================================================================== --- jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/jcr/JCRWebdavServer.java (revision 1907912) +++ jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/jcr/JCRWebdavServer.java (nonexistent) @@ -1,418 +0,0 @@ -/* - * 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 referenceToSessionMap; - - /** - * Create a new session cache with the {@link #CONCURRENCY_LEVEL_DEFAULT default concurrency level}. - */ - private SessionCache() { - this(CONCURRENCY_LEVEL_DEFAULT); - } - - /** - * Create a new session cache with the specified the level of concurrency - * for this server. - * - * @param cacheConcurrencyLevel A positive int value specifying the - * concurrency level of the server. - */ - private SessionCache(int cacheConcurrencyLevel) { - sessionMap = new ConcurrentHashMap>(INITIAL_CAPACITY, .75f, cacheConcurrencyLevel); - referenceToSessionMap = new ConcurrentHashMap(INITIAL_CAPACITY_REF_TO_SESSION, .75f, cacheConcurrencyLevel); - } - - /** - * Try to retrieve DavSession if a TransactionId or - * SubscriptionId is present in the request header. If no cached session - * was found null is returned. - * - * @param request - * @return a cached DavSession or null. - * @throws DavException - */ - private DavSession get(WebdavRequest request) - throws DavException { - String txId = request.getTransactionId(); - String subscriptionId = request.getSubscriptionId(); - String lockToken = request.getLockToken(); - - DavSession session = null; - // try to retrieve a cached session - if (lockToken != null && containsReference(lockToken)) { - session = getSessionByReference(lockToken); - } else if (txId != null && containsReference(txId)) { - session = getSessionByReference(txId); - } else if (subscriptionId != null && containsReference(subscriptionId)) { - session = getSessionByReference(subscriptionId); - } - - if (session == null) { - // try tokens present in the if-header - IfHeader ifHeader = new IfHeader(request); - for (Iterator it = ifHeader.getAllTokens(); it.hasNext();) { - String token = it.next(); - if (containsReference(token)) { - session = getSessionByReference(token); - break; - } - } - } - - // no cached session present -> create new one. - if (session == null) { - Session repSession = getRepositorySession(request); - session = new DavSessionImpl(repSession); - - // TODO: review again if using ConcurrentMap#putIfAbsent() was more appropriate. - sessionMap.put(session, new HashSet()); - log.debug("login: User '" + repSession.getUserID() + "' logged in."); - } else { - log.debug("login: Retrieved cached session for user '" + getUserID(session) + "'"); - } - addReference(session, request); - return session; - } - - /** - * Add a references to the specified DavSession. - * - * @param session - * @param reference - */ - private void addReference(DavSession session, Object reference) { - Set referenceSet = sessionMap.get(session); - if (referenceSet != null) { - referenceSet.add(reference); - referenceToSessionMap.put(reference, session); - } else { - log.error("Failed to add reference to session. No entry in cache found."); - } - } - - /** - * Remove the given reference from the specified DavSession. - * - * @param session - * @param reference - */ - private void removeReference(DavSession session, Object reference) { - Set referenceSet = sessionMap.get(session); - if (referenceSet != null) { - if (referenceSet.remove(reference)) { - log.debug("Removed reference " + reference + " to session " + session); - referenceToSessionMap.remove(reference); - } else { - log.warn("Failed to remove reference " + reference + " to session " + session); - } - if (referenceSet.isEmpty()) { - log.debug("No more references present on webdav session -> clean up."); - sessionMap.remove(session); - try { - Session repSession = DavSessionImpl.getRepositorySession(session); - String usr = getUserID(session) ; - sessionProvider.releaseSession(repSession); - log.debug("Login: User '" + usr + "' logged out"); - } catch (DavException e) { - // should not occur, since we originally built a - // DavSessionImpl that wraps a repository session. - log.error("Unexpected error: " + e.getMessage(), e.getCause()); - } - } else { - log.debug(referenceSet.size() + " references remaining on webdav session " + session); - } - } else { - log.error("Failed to remove reference from session. No entry in cache found."); - } - } - - /** - * Returns true, if there exists a DavSession in the cache - * that is referenced by the specified object. - * - * @param reference - * @return true if a DavSession is referenced by the given - * object. - */ - private boolean containsReference(Object reference) { - return referenceToSessionMap.containsKey(reference); - } - - /** - * Returns the DavSession that is referenced by the - * specified reference object. - * - * @param reference - * @return DavSession that is referenced by this reference - * object. - * @see #containsReference(Object) - */ - private DavSession getSessionByReference(Object reference) { - return referenceToSessionMap.get(reference); - } - - /** - * Retrieve the {@link Session} object for the given request. - * - * @param request - * @return JCR session object used to build the DavSession - * @throws DavException - * @throws DavException in case a {@link javax.jcr.LoginException} or {@link javax.jcr.RepositoryException} occurs. - */ - private Session getRepositorySession(WebdavRequest request) throws DavException { - try { - String workspaceName = null; - if (DavMethods.DAV_MKWORKSPACE != DavMethods.getMethodCode(request.getMethod())) { - workspaceName = request.getRequestLocator().getWorkspaceName(); - } - - Session session = sessionProvider.getSession( - request, repository, workspaceName); - - // extract information from Link header fields - LinkHeaderFieldParser lhfp = - new LinkHeaderFieldParser(request.getHeaders("Link")); - setJcrUserData(session, lhfp); - setSessionIdentifier(session, lhfp); - - return session; - } catch (LoginException e) { - // LoginException results in UNAUTHORIZED, - throw new JcrDavException(e); - } catch (RepositoryException e) { - // RepositoryException results in FORBIDDEN - throw new JcrDavException(e); - } catch (ServletException e) { - throw new DavException(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); - } - } - - /** - * Find first link relation for JCR user data and set it as - * the user data of the observation manager of the given session. - */ - private void setJcrUserData( - Session session, LinkHeaderFieldParser lhfp) - throws RepositoryException { - String data = null; - - // extract User Data string from RFC 2397 "data" URI - // only supports the simple case of "data:,..." for now - String target = lhfp.getFirstTargetForRelation( - JcrRemotingConstants.RELATION_USER_DATA); - if (target != null) { - try { - URI uri = new URI(target); - // Poor Man's data: URI parsing - if ("data".equalsIgnoreCase(uri.getScheme())) { - String sspart = uri.getRawSchemeSpecificPart(); - if (sspart.startsWith(",")) { - data = Text.unescape(sspart.substring(1)); - } - } - } catch (URISyntaxException ex) { - // not a URI, skip - } - } - - try { - session.getWorkspace().getObservationManager().setUserData(data); - } catch (UnsupportedRepositoryOperationException ignore) { - } - } - - /** - * Find first link relation for remote session identifier and set - * it as an attribute of the given session. - */ - private void setSessionIdentifier( - Session session, LinkHeaderFieldParser lhfp) { - if (session instanceof SessionExtensions) { - String name = JcrRemotingConstants.RELATION_REMOTE_SESSION_ID; - String id = lhfp.getFirstTargetForRelation(name); - ((SessionExtensions) session).setAttribute(name, id); - } - } - - private String getUserID(DavSession session) { - try { - Session s = DavSessionImpl.getRepositorySession(session); - if (s != null) { - return s.getUserID(); - } - } catch (DavException e) { - log.error(e.toString()); - } - // fallback - return session.toString(); - } - } -} Property changes on: jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/jcr/JCRWebdavServer.java ___________________________________________________________________ Deleted: svn Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/package-info.java =================================================================== --- jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/package-info.java (revision 1907912) +++ jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/package-info.java (nonexistent) @@ -1,18 +0,0 @@ -/* - * 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. - */ -@org.osgi.annotation.versioning.Version("1.0") -package org.apache.jackrabbit.server; Property changes on: jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/package-info.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/remoting/davex/AclRemoveHandler.java =================================================================== --- jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/remoting/davex/AclRemoveHandler.java (revision 1907912) +++ jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/remoting/davex/AclRemoveHandler.java (nonexistent) @@ -1,61 +0,0 @@ -/* - * 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.remoting.davex; - -import javax.jcr.Item; -import javax.jcr.Node; -import javax.jcr.RepositoryException; -import javax.jcr.Session; -import javax.jcr.security.AccessControlManager; -import javax.jcr.security.AccessControlPolicy; - -import org.apache.jackrabbit.util.Text; - -public class AclRemoveHandler implements ProtectedItemRemoveHandler { - - private static final String NT_REP_ACL = "rep:ACL"; - - @Override - public boolean remove(Session session, String itemPath) throws RepositoryException { - if (canHandle(session, itemPath)) { - String controlledPath = Text.getRelativeParent(itemPath, 1); - AccessControlManager acMgr = session.getAccessControlManager(); - AccessControlPolicy[] policies = acMgr.getPolicies(controlledPath); - for (AccessControlPolicy policy : policies) { - acMgr.removePolicy(controlledPath, policy); - } - return true; - } - return false; - } - - // -----------------------------------------------------------< private >--- - private boolean canHandle(Session session, String itemPath) throws RepositoryException { - Item aclItem = session.getItem(itemPath); - if (aclItem.isNode() && itemPath.startsWith("/")) { - if (isJackrabbitAclNodeType((Node) aclItem)) { - return true; - } - } - return false; - } - - private boolean isJackrabbitAclNodeType(Node aclNode) throws RepositoryException { - String ntName = aclNode.getPrimaryNodeType().getName(); - return ntName.equals(NT_REP_ACL); - } -} Property changes on: jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/remoting/davex/AclRemoveHandler.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/remoting/davex/BatchReadConfig.java =================================================================== --- jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/remoting/davex/BatchReadConfig.java (revision 1907912) +++ jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/remoting/davex/BatchReadConfig.java (nonexistent) @@ -1,170 +0,0 @@ -/* - * 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.remoting.davex; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import javax.jcr.Node; -import javax.jcr.RepositoryException; -import java.util.Map; -import java.util.HashMap; -import java.util.Properties; -import java.util.Enumeration; -import java.io.InputStream; -import java.io.IOException; - -/** - * BatchReadConfig defines if and how deep child item - * information should be retrieved, when accessing a Node. - * The configuration is based on node type names. - */ -class BatchReadConfig { - - private static Logger log = LoggerFactory.getLogger(BatchReadConfig.class); - - private static final String NAME_DEFAULT = "default"; - public static final int DEPTH_DEFAULT = 0; - public static final int DEPTH_INFINITE = -1; - - private int defaultDepth = DEPTH_DEFAULT; - private final Map depthMap = new HashMap(); - - /** - * Create an empty batch-read config. - */ - BatchReadConfig() {} - - /** - * Load the batch read configuration. - * - * @param in An input stream. - * @throws IOException If an error occurs. - */ - public void load(InputStream in) throws IOException { - Properties props = new Properties(); - props.load(in); - add(props); - } - - /** - * Add the configuration entries present in the given properties. - * - * @param props - */ - public void add(Properties props) { - for (Enumeration en = props.propertyNames(); en.hasMoreElements();) { - String name = en.nextElement().toString(); - String depthStr = props.getProperty(name); - try { - int depth = Integer.parseInt(depthStr); - if (depth < DEPTH_INFINITE) { - log.warn("invalid depth " + depthStr + " -> ignoring."); - continue; - } - if (NAME_DEFAULT.equals(name)) { - setDefaultDepth(depth); - } else { - setDepth(name, depth); - } - } catch (NumberFormatException e) { - // invalid entry in the properties file -> ignore - log.warn("Invalid depth value for name " + name + ". " + depthStr + " cannot be parsed into an integer."); - } - } - } - - /** - * Return the depth for the given node type name. If the name is - * not defined in this configuration, the {@link #DEPTH_DEFAULT default value} - * is returned. - * - * @param ntName The jcr name of the node type. - * @return {@link #DEPTH_INFINITE -1} If all child infos should be return or - * any value greater than {@link #DEPTH_DEFAULT 0} if only parts of the - * subtree should be returned. If the given nodetype name is not defined - * in this configuration, the default depth {@link #DEPTH_DEFAULT 0} will - * be returned. - */ - public int getDepth(String ntName) { - if (depthMap.containsKey(ntName)) { - return depthMap.get(ntName); - } else { - return defaultDepth; - } - } - - /** - * Return the depth for the given node or the default depth if the config - * does not provide an specific entry for the given node. - * - * @param node The node for with depth information should be retrieved. - * @return {@link #DEPTH_INFINITE -1} If all child infos should be return or - * any value greater than {@link #DEPTH_DEFAULT 0} if only parts of the - * subtree should be returned. - */ - public int getDepth(Node node) { - int depth = defaultDepth; - try { - String ntName = node.getPrimaryNodeType().getName(); - if (depthMap.containsKey(ntName)) { - depth = depthMap.get(ntName); - } - } catch (RepositoryException e) { - // ignore and return default. - } - return depth; - } - - /** - * Define the batch-read depth for the given node type name. - * - * @param ntName jcr name of the node type for which depth is defined. - * @param depth Depth for the specified node type name. - * @throws IllegalArgumentException if ntName is null - * or depth is lower than {@link #DEPTH_INFINITE}. - */ - public void setDepth(String ntName, int depth) { - if (ntName == null || depth < DEPTH_INFINITE) { - throw new IllegalArgumentException(); - } - depthMap.put(ntName, depth); - } - - /** - * Returns the default depth. - * - * @return the default depth. - */ - public int getDefaultDepth() { - return defaultDepth; - } - - /** - * Set the default depth. - * - * @param depth The default depth. - * @throws IllegalArgumentException if depth is lower than - * {@link #DEPTH_INFINITE}. - */ - public void setDefaultDepth(int depth) { - if (depth < -1) { - throw new IllegalArgumentException(); - } - defaultDepth = depth; - } -} Property changes on: jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/remoting/davex/BatchReadConfig.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Deleted: svn:keywords ## -1 +0,0 ## -author date id revision url \ No newline at end of property Index: jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/remoting/davex/DavexServletService.java =================================================================== --- jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/remoting/davex/DavexServletService.java (revision 1907912) +++ jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/remoting/davex/DavexServletService.java (nonexistent) @@ -1,190 +0,0 @@ -/* - * 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.remoting.davex; - -import java.util.HashMap; -import java.util.HashSet; -import java.util.LinkedHashMap; -import java.util.Map; -import java.util.Set; - -import javax.jcr.LoginException; -import javax.jcr.Repository; -import javax.jcr.RepositoryException; -import javax.jcr.Session; -import javax.servlet.Servlet; -import javax.servlet.ServletException; -import javax.servlet.http.HttpServletRequest; - -import org.apache.felix.scr.annotations.Activate; -import org.apache.felix.scr.annotations.Component; -import org.apache.felix.scr.annotations.Properties; -import org.apache.felix.scr.annotations.Property; -import org.apache.felix.scr.annotations.Reference; -import org.apache.felix.scr.annotations.ReferenceCardinality; -import org.apache.felix.scr.annotations.ReferencePolicy; -import org.apache.felix.scr.annotations.Service; -import org.apache.jackrabbit.server.SessionProvider; -import org.apache.jackrabbit.webdav.server.AbstractWebdavServlet; -import org.apache.jackrabbit.webdav.util.CSRFUtil; - -@Component(metatype = true, label = "%dav.name", description = "%dav.description") -@Service(Servlet.class) -@Properties({ - @Property(name = "service.description", value = "Apache Jackrabbit JcrRemoting Servlet"), - @Property(name = JcrRemotingServlet.INIT_PARAM_AUTHENTICATE_HEADER, value = AbstractWebdavServlet.DEFAULT_AUTHENTICATE_HEADER), - @Property(name = JcrRemotingServlet.INIT_PARAM_CSRF_PROTECTION, value = CSRFUtil.DISABLED), - @Property(name = JcrRemotingServlet.INIT_PARAM_MISSING_AUTH_MAPPING, value = ""), - @Property(name = "contextId", value = "") }) -@Reference( - name = "providers", referenceInterface = SessionProvider.class, - policy = ReferencePolicy.DYNAMIC, - cardinality = ReferenceCardinality.OPTIONAL_MULTIPLE, - bind = "addSessionProvider", unbind = "removeSessionProvider") -public class DavexServletService extends JcrRemotingServlet - implements SessionProvider { - - /** Serial version UID */ - private static final long serialVersionUID = -901601294536148635L; - - private static final String DEFAULT_ALIAS = "/server"; - - @Property(value = DEFAULT_ALIAS) - private static final String PARAM_ALIAS = "alias"; - - @Reference - private Repository repository; - - private String alias; - - /** - * Currently available custom session providers. They're used - * first before the default provider gets consulted. The associated - * set of sessions is used to forcibly release all sessions acquired - * from a provider when that provider is being removed. - */ - private final Map> providers = - new LinkedHashMap>(); - - /** - * Currently active sessions. Used to link a session to the correct - * provider in the {@link #releaseSession(Session)} method. - */ - private final Map sessions = - new HashMap(); - - @Override - protected Repository getRepository() { - return repository; - } - - @Override - protected String getResourcePathPrefix() { - return alias; - } - - @Activate - public void activate(Map config) { - Object object = config.get(PARAM_ALIAS); - String string = ""; - if (object != null) { - string = object.toString(); - } - if (string.length() > 0) { - this.alias = string; - } else { - this.alias = DEFAULT_ALIAS; - } - } - - @Override - protected SessionProvider getSessionProvider() { - return this; - } - - /** - * Adds a custom session provider service. - * - * @param provider session provider - */ - public synchronized void addSessionProvider(SessionProvider provider) { - providers.put(provider, new HashSet()); - } - - /** - * Removes a custom session provider service. All active sessions - * acquired from that provider are forcibly released. - * - * @param provider session provider - */ - public synchronized void removeSessionProvider(SessionProvider provider) { - Set sessions = providers.remove(provider); - if (sessions != null) { - for (Session session : sessions) { - releaseSession(session); - } - } - } - - //-----------------------------------------------------< SessionProvider > - - /** - * Asks each available session provider in order for a session and - * returns the first session given. The default provider is used - * if no custom provider service is available or can provide a requested - * session. - */ - public synchronized Session getSession( - HttpServletRequest request, Repository repository, String workspace) - throws LoginException, ServletException, RepositoryException { - SessionProvider provider = null; - Session session = null; - - for (Map.Entry> entry : providers.entrySet()) { - provider = entry.getKey(); - session = provider.getSession(request, repository, workspace); - if (session != null) { - entry.getValue().add(session); - break; - } - } - - if (session == null) { - provider = super.getSessionProvider(); - session = provider.getSession(request, repository, workspace); - } - - if (session != null) { - sessions.put(session, provider); - } - - return session; - } - - /** - * Releases the given session using the provider from which it was acquired. - */ - public synchronized void releaseSession(Session session) { - SessionProvider provider = sessions.remove(session); - if (provider != null) { - provider.releaseSession(session); - } - } - -} Property changes on: jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/remoting/davex/DavexServletService.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/remoting/davex/DiffException.java =================================================================== --- jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/remoting/davex/DiffException.java (revision 1907912) +++ jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/remoting/davex/DiffException.java (nonexistent) @@ -1,41 +0,0 @@ -/* - * 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.remoting.davex; - -import java.io.IOException; - -/** - * DiffException... - */ -class DiffException extends IOException { - - private Throwable cause; - - public DiffException(String message) { - super(message); - } - - public DiffException(String message, Throwable cause) { - super(message); - this.cause = cause; - } - - @Override - public Throwable getCause() { - return cause; - } -} Property changes on: jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/remoting/davex/DiffException.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Deleted: svn:keywords ## -1 +0,0 ## -author date id revision url \ No newline at end of property Index: jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/remoting/davex/DiffHandler.java =================================================================== --- jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/remoting/davex/DiffHandler.java (revision 1907912) +++ jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/remoting/davex/DiffHandler.java (nonexistent) @@ -1,31 +0,0 @@ -/* - * 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.remoting.davex; - -/** - * DiffHandler... - */ -interface DiffHandler { - - void addNode(String targetPath, String diffValue) throws DiffException; - - void setProperty(String targetPath, String diffValue) throws DiffException; - - void remove(String targetPath, String diffValue) throws DiffException; - - void move(String targetPath, String diffValue) throws DiffException; -} Property changes on: jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/remoting/davex/DiffHandler.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Deleted: svn:keywords ## -1 +0,0 ## -author date id revision url \ No newline at end of property Index: jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/remoting/davex/DiffParser.java =================================================================== --- jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/remoting/davex/DiffParser.java (revision 1907912) +++ jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/remoting/davex/DiffParser.java (nonexistent) @@ -1,218 +0,0 @@ -/* - * 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.remoting.davex; - -import java.io.BufferedReader; -import java.io.IOException; -import java.io.Reader; -import java.io.StringReader; -import java.io.InputStream; -import java.io.InputStreamReader; - -/** DiffParser... */ -class DiffParser { - - // TODO: review again: currently all line-sep. chars before an diff-char are - // TODO: ignored unless they are escaped in way the handler understands (e.g. - // TODO: JSON does: \\r for \r). - // TODO: in contrast line sep. at the end of the string are treated as value. - // TODO: ... similar: line sep. following by non-diff symbol. - - private final DiffHandler handler; - - private static final int EOF = -1; - - private static final char SYMBOL_ADD_NODE = '+'; - private static final char SYMBOL_MOVE = '>'; - private static final char SYMBOL_REMOVE = '-'; - private static final char SYMBOL_SET_PROPERTY = '^'; - - private static final int STATE_START_LINE = 0; - private static final int STATE_START_TARGET = 1; - private static final int STATE_TARGET = 2; - private static final int STATE_START_VALUE = 3; - private static final int STATE_VALUE = 4; - - /** - * - * @param handler - */ - public DiffParser(DiffHandler handler) { - this.handler = handler; - } - - public void parse(String str) throws IOException, DiffException { - parse(new BufferedReader(new StringReader(str))); - } - - public void parse(InputStream input, String charSetName) throws IOException, DiffException { - parse(new BufferedReader(new InputStreamReader(input, charSetName))); - } - - public void parse(Reader reader) throws IOException, DiffException { - int action = -1; - String path = null; - - StringBuffer lineSeparator = null; - StringBuffer bf = null; - - int state = STATE_START_LINE; - int next = reader.read(); - - while (next != EOF) { - switch (state) { - case STATE_START_LINE: - if (isSymbol(next)) { - // notify the last action read - if (action > -1) { - informAction(action, path, bf); - } - // ... and start recording the next action - action = next; - bf = null; - lineSeparator = null; - state = STATE_START_TARGET; - } else if (isLineSeparator(next)) { - // still line-separator -> append c to the lineSeparator - // buffer and keep state set to STATE_START_LINE - if (lineSeparator == null) { - throw new DiffException("Invalid start of new line."); - } else { - lineSeparator.append((char) next); - } - } else if (lineSeparator != null && bf != null) { - // append the collected return/linefeed chars as part - // of the value read and continued reading value. - bf.append(lineSeparator); - bf.append((char) next); - lineSeparator = null; - state = STATE_VALUE; - } else { - throw new DiffException("Invalid start of new line."); - } - break; - - case STATE_START_TARGET: - if (Character.isWhitespace((char) next) || next == ':') { - throw new DiffException("Invalid start of target path '" + next + "'"); - } - bf = new StringBuffer(); - bf.append((char) next); - state = STATE_TARGET; - break; - - case STATE_TARGET: - if (Character.isWhitespace((char) next) && endsWithDelim(bf)) { - // a sequence of 'wsp:wsp' indicates the delimiter between - // the target path and the diff value. - path = bf.substring(0, bf.lastIndexOf(":")).trim(); - state = STATE_START_VALUE; - // reset buffer - bf = null; - } else { - // continue reading the path into the buffer. - bf.append((char) next); - } - break; - - case STATE_START_VALUE: - if (isLineSeparator(next)) { - lineSeparator = new StringBuffer(); - lineSeparator.append((char) next); - bf = new StringBuffer(); - state = STATE_START_LINE; - } else { - bf = new StringBuffer(); - bf.append((char) next); - state = STATE_VALUE; - } - break; - - case STATE_VALUE: - if (isLineSeparator(next)) { - lineSeparator = new StringBuffer(); - lineSeparator.append((char) next); - state = STATE_START_LINE; - } else { - bf.append((char) next); - // keep state set to STATE_VALUE - } - break; - - } - // read the next character. - next = reader.read(); - } - - // a diff ending after a command or within the target is invalid. - if (state == STATE_START_TARGET || state == STATE_TARGET) { - throw new DiffException("Invalid end of DIFF string: missing separator and value."); - } - if (state == STATE_START_VALUE ) { - // line separator AND buffer must be null - if (!(lineSeparator == null && bf == null)) { - throw new DiffException("Invalid end of DIFF string."); - } - } - - // append eventual remaining line-separators to the value - if (lineSeparator != null) { - bf.append(lineSeparator); - } - // notify the last action read - informAction(action, path, bf); - } - - private void informAction(int action, String path, StringBuffer diffVal) throws DiffException { - if (path == null) { - throw new DiffException("Missing path for action " + action + "(diffValue = '"+ diffVal +"')"); - } - String value = (diffVal == null) ? null : diffVal.toString(); - switch (action) { - case SYMBOL_ADD_NODE: - handler.addNode(path, value); - break; - case SYMBOL_SET_PROPERTY: - handler.setProperty(path, value); - break; - case SYMBOL_MOVE: - handler.move(path, value); - break; - case SYMBOL_REMOVE: - handler.remove(path, value); - break; - default: - throw new DiffException("Invalid action " + action); - } - } - - private static boolean isSymbol(int c) { - return c == SYMBOL_ADD_NODE || c == SYMBOL_SET_PROPERTY || c == SYMBOL_MOVE || c == SYMBOL_REMOVE; - } - - private static boolean isLineSeparator(int c) { - return c == '\n' || c == '\r'; - - } - private static boolean endsWithDelim(StringBuffer bf) { - if (bf.length() < 2) { - return false; - } else { - return ':' == bf.charAt(bf.length()-1) && Character.isWhitespace(bf.charAt(bf.length()-2)); - } - } -} Property changes on: jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/remoting/davex/DiffParser.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Deleted: svn:keywords ## -1 +0,0 ## -author date id revision url \ No newline at end of property Index: jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/remoting/davex/JcrRemotingServlet.java =================================================================== --- jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/remoting/davex/JcrRemotingServlet.java (revision 1907912) +++ jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/remoting/davex/JcrRemotingServlet.java (nonexistent) @@ -1,812 +0,0 @@ -/* - * 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.remoting.davex; - -import java.io.File; -import java.io.IOException; -import java.io.InputStream; -import java.nio.charset.StandardCharsets; -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashSet; -import java.util.Iterator; -import java.util.Locale; -import java.util.Set; - -import javax.jcr.Item; -import javax.jcr.ItemNotFoundException; -import javax.jcr.Node; -import javax.jcr.NodeIterator; -import javax.jcr.PathNotFoundException; -import javax.jcr.RepositoryException; -import javax.jcr.Session; -import javax.jcr.Workspace; -import javax.jcr.nodetype.NodeType; -import javax.servlet.ServletConfig; -import javax.servlet.ServletContext; -import javax.servlet.ServletException; -import javax.servlet.http.HttpServletResponse; - -import org.apache.jackrabbit.JcrConstants; -import org.apache.jackrabbit.server.util.RequestData; -import org.apache.jackrabbit.util.Text; -import org.apache.jackrabbit.webdav.DavException; -import org.apache.jackrabbit.webdav.DavLocatorFactory; -import org.apache.jackrabbit.webdav.DavMethods; -import org.apache.jackrabbit.webdav.DavResource; -import org.apache.jackrabbit.webdav.DavResourceFactory; -import org.apache.jackrabbit.webdav.DavResourceLocator; -import org.apache.jackrabbit.webdav.DavServletResponse; -import org.apache.jackrabbit.webdav.DavSession; -import org.apache.jackrabbit.webdav.WebdavRequest; -import org.apache.jackrabbit.webdav.WebdavResponse; -import org.apache.jackrabbit.webdav.jcr.JCRWebdavServerServlet; -import org.apache.jackrabbit.webdav.jcr.JcrDavException; -import org.apache.jackrabbit.webdav.jcr.JcrDavSession; -import org.apache.jackrabbit.webdav.jcr.transaction.TxLockManagerImpl; -import org.apache.jackrabbit.webdav.observation.SubscriptionManager; -import org.apache.jackrabbit.webdav.version.DeltaVConstants; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * JcrRemotingServlet is an extended version of the - * {@link org.apache.jackrabbit.webdav.jcr.JCRWebdavServerServlet JCR Remoting Servlet} - * that provides improved - * - * functionality and supports cross workspace copy and cloning. - * - *

Batch Read

- * - * Upon RepositoryService.getItemInfos a JSON object is composed containing - * the information for the requested node and its child items up to a - * specified or configuration determined depth. - *

- * Batch read is triggered by adding a '.json' extension to the resource href. - * Optionally the client may explicitly specify the desired batch read depth - * by appending '.depth.json' extension. If no json extension is present the - * GET request is processed by the base servlet. - *

- * The JSON writer applies the following rules: - * - *

- * - Nodes are represented as JSON objects.
- *
- * - Each Node has its properties included as JSON key/value pairs.
- *
- * - Single valued Properties are simple key/value pairs.
- *
- * - Multi valued Properties are represented as JSON array.
- *
- * - Each Node has its child nodes included as long a maximal depths is not reached.
- * 
- * - Nodes without any child nodes get a special JSON member named
- *   ::NodeIteratorSize, whose value is zero.
- *
- * - If the maximal depth is reached only name, index and unique id of the
- *   direct child are included (incomplete node info). In order to obtain
- *   the complete information the client sends another GET with .json extension.
- * 
- * - * Same name sibling nodes and properties whose type cannot be unambiguously be - * extracted from the JSON on the client side need some special handling: - * - *
- * - Node with index > 1, get a JSON key consisting of
- *   Node.getName() + "[" + Node.getIndex() + "]" 
- *
- * - Binary Property
- *   JSON value = length of the JCR value.
- *   The JCR value must be retrieved separately.
- *
- * - Name, Path, Reference and Date Property
- *   The JSON member representing the Property (name, value) is preceded by a
- *   special member consisting of
- *   JSON key = ":" + Property.getName()
- *   JSON value = PropertyType.nameFromValue(Property.getType())
- *
- * - Multi valued properties with Property.getValues().length == 0 will be
- *   treated as special property types above (extra property indicating the
- *   type of the property).
- *
- * - Double Property
- *   JSON value must not have any trailing ".0" removed.
- * 
- * - *

Multi Read

- *

- * Since Jackrabbit 2.3.6 it is also possible to request multiple subtrees - * in a single request. This is done by adding one or more ":include" - * parameters to a batch read request describe above. These extra parameters - * specify the (relative) paths of all the nodes to be included in the - * response. The response is a JSON object whose "nodes" property contains - * all the selected nodes keyed by path. Missing nodes are not included in - * the response. Each included node is serialized as defined above for - * batch read. - *

- * Example: - *

- * $ curl 'http://.../parent.json?:path=child1&:path=child2'
- * {"nodes":{"/parent/child1":{...},"/parent/child2":{...}}}
- * 
- * - *

Batch Write

- * - * The complete SPI Batch is sent to the server in a single request, currently a - * POST request containing a custom ":diff" parameter. - *
- * NOTE that this is targeted to be replaced by a PATCH request. - * - *

Diff format

- * - * The diff parameter currently consists of JSON-like key-value pairs with the - * following special requirements: - * - *
- *   diff       ::= members
- *   members    ::= pair | pairs
- *   pair       ::= key " : " value
- *   pairs      ::= pair line-end pair | pair line-end pairs
- *   line-end   ::= "\r\n" | "\n" | "\r"
- *   key        ::= diffchar path
- *   diffchar   ::= "+" | "^" | "-" | ">"
- *   path       ::= abspath | relpath
- *   abspath    ::= * absolute path to an item *
- *   relpath    ::= * relpath from item at request URI to an item *
- *   value      ::= value+ | value- | value^ | value>
- *   value+     ::= * a JSON object *
- *   value-     ::= ""
- *   value^     ::= * any JSON value except JSON object *
- *   value>     ::= path | path "#before" | path "#after" | "#first" | "#last"
- * 
- * - * In other words: - *
    - *
  • diff consists of one or more key-value pair(s)
  • - *
  • key must start with a diffchar followed by a rel. or abs. item path
  • - *
  • diffchar being any of "+", "^", "-" or ">" representing the transient - * item modifications as follows - *
    - *   "+" addNode
    - *   "^" setProperty / setValue / removeProperty
    - *   "-" remove Item
    - *   ">" move / reorder Nodes
    - * 
    - *
  • - *
  • key must be separated from the value by a ":" surrounded by whitespace.
  • - *
  • two pairs must be separated by a line end
  • - *
  • the format of the value depends on the diffchar
  • - *
  • for moving around node the value must consist of a abs. or rel. path. - * in contrast reordering of existing nodes is achieved by appending a trailing - * order position hint (#first, #last, #before or #after)
  • - *
- * - * NOTE the following special handling of JCR properties of type - * Binary, Name, Path, Date and Reference: - *
    - *
  • the JSON value must be missing
  • - *
  • the POST request is expected to contain extra multipart(s) or request - * parameter(s) for the property value(s)
  • - *
  • the content type of the extra parts/params must reflect the property - * type:"jcr-value/" + PropertyType.nameFromValue(Property.getType).toLowerCase()
  • - *
- * - * @see www.json.org for the definition of - * JSON object and JSON value. - */ -public abstract class JcrRemotingServlet extends JCRWebdavServerServlet { - - private static Logger log = LoggerFactory.getLogger(JcrRemotingServlet.class); - - /** - * the home init parameter. other relative filesystem paths are - * relative to this location. - */ - public static final String INIT_PARAM_HOME = "home"; - - /** - * the 'temp-directory' init parameter - */ - public static final String INIT_PARAM_TMP_DIRECTORY = "temp-directory"; - /** - * temp-dir attribute to be set to the servlet-context - */ - public static final String ATTR_TMP_DIRECTORY = "remoting-servlet.tmpdir"; - - /** - * the 'temp-directory' init parameter - */ - public static final String INIT_PARAM_BATCHREAD_CONFIG = "batchread-config"; - - /** - * the 'protectedhandlers-config' init paramter. this parameter contains the XML - * configuration file for protected item remove handlers. - */ - public static final String INIT_PARAM_PROTECTED_HANDLERS_CONFIG = "protectedhandlers-config"; - - private static final String PARAM_DIFF = ":diff"; - private static final String PARAM_COPY = ":copy"; - private static final String PARAM_CLONE = ":clone"; - private static final String PARAM_INCLUDE = ":include"; - - private static final String CONTENT_TYPE_APPLICATION_JSON = "application/json"; - - private BatchReadConfig brConfig; - private ProtectedRemoveManager protectedRemoveManager; - - @Override - public void init() throws ServletException { - super.init(); - - brConfig = new BatchReadConfig(); - String brConfigParam = getServletConfig().getInitParameter(INIT_PARAM_BATCHREAD_CONFIG); - if (brConfigParam == null) { - // TODO: define default values. - log.debug("batchread-config missing -> initialize defaults."); - brConfig.setDepth("nt:file", BatchReadConfig.DEPTH_INFINITE); - brConfig.setDefaultDepth(5); - } else { - try { - InputStream in = getServletContext().getResourceAsStream(brConfigParam); - if (in != null) { - brConfig.load(in); - } - } catch (IOException e) { - log.debug("Unable to build BatchReadConfig from " + brConfigParam + "."); - } - } - - String protectedHandlerConfig = getServletConfig().getInitParameter(INIT_PARAM_PROTECTED_HANDLERS_CONFIG); - InputStream in = null; - try { - in = getServletContext().getResourceAsStream(protectedHandlerConfig); - if (in != null){ - protectedRemoveManager = new ProtectedRemoveManager(); - protectedRemoveManager.load(in); - } else { - //Config might be direct class implementation - protectedRemoveManager = new ProtectedRemoveManager(protectedHandlerConfig); - } - } catch (IOException e) { - log.debug("Unable to create ProtectedRemoveManager from " + protectedHandlerConfig , e); - } finally{ - if (in != null){ - try { - in.close(); - } catch (IOException ignore) { - } - } - } - - // Determine the configured location for temporary files used when - // processing file uploads. Since JCR-3029 the default is the - // standard java.io.tmpdir location, but the presence of explicit - // configuration parameters restores the original behavior. - File tmp = null; - ServletConfig config = getServletConfig(); - String paramHome = config.getInitParameter(INIT_PARAM_HOME); - String paramTemp = config.getInitParameter(INIT_PARAM_TMP_DIRECTORY); - if (paramHome != null || paramTemp != null) { - if (paramHome == null) { - log.debug("Missing init-param " + INIT_PARAM_HOME - + ". Using default: 'jackrabbit'"); - paramHome = "jackrabbit"; - } else if (paramTemp == null) { - log.debug("Missing init-param " + INIT_PARAM_TMP_DIRECTORY - + ". Using default: 'tmp'"); - paramTemp = "tmp"; - } - - tmp = new File(paramHome, paramTemp); - try { - tmp = tmp.getCanonicalFile(); - tmp.mkdirs(); - log.debug(" temp-directory = " + tmp.getPath()); - } catch (IOException e) { - log.warn("Invalid temporary directory " + tmp.getPath() - + ", using system default instead", e); - tmp = null; - } - } - getServletContext().setAttribute(ATTR_TMP_DIRECTORY, tmp); - - // force usage of custom locator factory. - super.setLocatorFactory(new DavLocatorFactoryImpl(getResourcePathPrefix())); - } - - protected String getResourcePathPrefix() { - return getInitParameter(INIT_PARAM_RESOURCE_PATH_PREFIX); - } - - @Override - public DavResourceFactory getResourceFactory() { - return new ResourceFactoryImpl(txMgr, subscriptionMgr); - } - - @Override - protected void doGet(WebdavRequest webdavRequest, - WebdavResponse webdavResponse, - DavResource davResource) throws IOException, DavException { - if (canHandle(DavMethods.DAV_GET, webdavRequest, davResource)) { - // return json representation of the requested resource - DavResourceLocator locator = davResource.getLocator(); - String path = locator.getRepositoryPath(); - - Session session = getRepositorySession(webdavRequest); - try { - Node node = session.getNode(path); - int depth = ((WrappingLocator) locator).getDepth(); - - webdavResponse.setContentType(CONTENT_TYPE_APPLICATION_JSON); - webdavResponse.setCharacterEncoding(StandardCharsets.UTF_8.name()); - webdavResponse.setStatus(DavServletResponse.SC_OK); - JsonWriter writer = new JsonWriter(webdavResponse.getWriter()); - - String[] includes = webdavRequest.getParameterValues(PARAM_INCLUDE); - if (includes == null) { - if (depth < BatchReadConfig.DEPTH_INFINITE) { - NodeType type = node.getPrimaryNodeType(); - depth = brConfig.getDepth(type.getName()); - } - writer.write(node, depth); - } else { - writeMultiple(writer, node, includes, depth); - } - } catch (PathNotFoundException e) { - // properties cannot be requested as json object. - throw new JcrDavException( - new ItemNotFoundException("No node at " + path), - DavServletResponse.SC_NOT_FOUND); - } catch (RepositoryException e) { - // should only get here if the item does not exist. - log.debug(e.getMessage()); - throw new JcrDavException(e); - } - } else { - super.doGet(webdavRequest, webdavResponse, davResource); - } - } - - private void writeMultiple( - JsonWriter writer, Node node, String[] includes, int depth) - throws RepositoryException, IOException { - Collection nodes = new ArrayList(); - Set alreadyAdded = new HashSet(); - for (String include : includes) { - try { - Node n; - if (include.startsWith("/")) { - n = node.getSession().getNode(include); - } else { - n = node.getNode(include); - } - String np = n.getPath(); - if (!alreadyAdded.contains(np)) { - nodes.add(n); - alreadyAdded.add(np); - } - } catch (PathNotFoundException e) { - // skip missing node - } - } - writer.write(nodes, depth); - } - - @Override - protected void doPost(WebdavRequest webdavRequest, WebdavResponse webdavResponse, DavResource davResource) - throws IOException, DavException { - if (canHandle(DavMethods.DAV_POST, webdavRequest, davResource)) { - // special remoting request: the defined parameters are exclusive - // and cannot be combined. - Session session = getRepositorySession(webdavRequest); - RequestData data = new RequestData(webdavRequest, getTempDirectory(getServletContext())); - String loc = null; - try { - String[] pValues; - String[] includes = null; // multi-read over POST - if ((pValues = data.getParameterValues(PARAM_CLONE)) != null) { - loc = clone(session, pValues, davResource.getLocator()); - } else if ((pValues = data.getParameterValues(PARAM_COPY)) != null) { - loc = copy(session, pValues, davResource.getLocator()); - } else if (data.getParameterValues(PARAM_DIFF) != null) { - String targetPath = davResource.getLocator().getRepositoryPath(); - processDiff(session, targetPath, data, protectedRemoveManager); - } else if ((pValues = data.getParameterValues(PARAM_INCLUDE)) != null - && canHandle(DavMethods.DAV_GET, webdavRequest, davResource)) { - includes = pValues; - } else { - String targetPath = davResource.getLocator().getRepositoryPath(); - loc = modifyContent(session, targetPath, data, protectedRemoveManager); - } - - // TODO: append entity - if (loc == null) { - webdavResponse.setStatus(HttpServletResponse.SC_OK); - if (includes != null) { - webdavResponse.setContentType(CONTENT_TYPE_APPLICATION_JSON); - webdavResponse.setCharacterEncoding(StandardCharsets.UTF_8.name()); - JsonWriter writer = new JsonWriter(webdavResponse.getWriter()); - - DavResourceLocator locator = davResource.getLocator(); - String path = locator.getRepositoryPath(); - - Node node = session.getNode(path); - int depth = ((WrappingLocator) locator).getDepth(); - - writeMultiple(writer, node, includes, depth); - } - } else { - webdavResponse.setHeader(DeltaVConstants.HEADER_LOCATION, loc); - webdavResponse.setStatus(HttpServletResponse.SC_CREATED); - } - } catch (RepositoryException e) { - log.warn(e.getMessage(), e); - throw new JcrDavException(e); - } catch (DiffException e) { - log.warn(e.getMessage()); - Throwable cause = e.getCause(); - if (cause instanceof RepositoryException) { - throw new JcrDavException((RepositoryException) cause); - } else { - throw new DavException(DavServletResponse.SC_BAD_REQUEST, "Invalid diff format."); - } - } finally { - data.dispose(); - } - } else { - super.doPost(webdavRequest, webdavResponse, davResource); - } - } - - private boolean canHandle(int methodCode, WebdavRequest request, DavResource davResource) { - DavResourceLocator locator = davResource.getLocator(); - switch (methodCode) { - case DavMethods.DAV_GET: - return davResource.exists() && (locator instanceof WrappingLocator) - && ((WrappingLocator) locator).isJsonRequest; - case DavMethods.DAV_POST: - String ct = request.getContentType(); - if (ct == null) { - return false; - } else { - int semicolon = ct.indexOf(';'); - if (semicolon >= 0) { - ct = ct.substring(0, semicolon); - } - ct = ct.trim().toLowerCase(Locale.ENGLISH); - return "multipart/form-data".equals(ct) || "application/x-www-form-urlencoded".equals(ct); - } - default: - return false; - } - } - - private static String clone(Session session, String[] cloneArgs, DavResourceLocator reqLocator) throws RepositoryException { - Workspace wsp = session.getWorkspace(); - String destPath = null; - for (String cloneArg : cloneArgs) { - String[] args = cloneArg.split(","); - if (args.length == 4) { - wsp.clone(args[0], args[1], args[2], Boolean.valueOf(args[3])); - destPath = args[2]; - } else { - throw new RepositoryException(":clone parameter must have a value consisting of the 4 args needed for a Workspace.clone() call."); - } - } - return buildLocationHref(session, destPath, reqLocator); - } - - private static String copy(Session session, String[] copyArgs, DavResourceLocator reqLocator) throws RepositoryException { - Workspace wsp = session.getWorkspace(); - String destPath = null; - for (String copyArg : copyArgs) { - String[] args = copyArg.split(","); - switch (args.length) { - case 2: - wsp.copy(args[0], args[1]); - destPath = args[1]; - break; - case 3: - wsp.copy(args[0], args[1], args[2]); - destPath = args[2]; - break; - default: - throw new RepositoryException(":copy parameter must have a value consisting of 2 jcr paths or workspaceName plus 2 jcr paths separated by ','."); - } - } - return buildLocationHref(session, destPath, reqLocator); - } - - private static String buildLocationHref(Session s, String destPath, DavResourceLocator reqLocator) throws RepositoryException { - if (destPath != null) { - NodeIterator it = s.getRootNode().getNodes(destPath.substring(1)); - Node n = null; - while (it.hasNext()) { - n = it.nextNode(); - } - if (n != null) { - DavResourceLocator loc = reqLocator.getFactory().createResourceLocator(reqLocator.getPrefix(), reqLocator.getWorkspacePath(), n.getPath(), false); - return loc.getHref(true); - } - } - - // unable to determine -> no location header sent back. - return null; - } - - private static void processDiff(Session session, String targetPath, RequestData data, ProtectedRemoveManager protectedRemoveManager) - throws RepositoryException, DiffException, IOException { - - String[] diffs = data.getParameterValues(PARAM_DIFF); - DiffHandler handler = new JsonDiffHandler(session, targetPath, data, protectedRemoveManager); - DiffParser parser = new DiffParser(handler); - - for (String diff : diffs) { - boolean success = false; - try { - parser.parse(diff); - - session.save(); - success = true; - } finally { - if (!success) { - session.refresh(false); - } - } - } - } - - /** - * TODO: doesn't work properly with intermediate SNS-nodes - * TODO: doesn't respect jcr:uuid properties. - */ - private static String modifyContent(Session session, String targetPath, RequestData data, ProtectedRemoveManager protectedRemoveManager) - throws RepositoryException, DiffException { - - JsonDiffHandler dh = new JsonDiffHandler(session, targetPath, data, protectedRemoveManager); - boolean success = false; - try { - for (Iterator pNames = data.getParameterNames(); pNames.hasNext();) { - String paramName = pNames.next(); - String propPath = dh.getItemPath(paramName); - String parentPath = Text.getRelativeParent(propPath, 1); - - if (!session.itemExists(parentPath) || !session.getItem(parentPath).isNode()) { - createNode(session, parentPath, data); - } - - if (JcrConstants.JCR_PRIMARYTYPE.equals(Text.getName(propPath))) { - // already handled by createNode above -> ignore - continue; - } - // none of the special properties -> let the diffhandler take care - // of the property creation/modification. - dh.setProperty(paramName, null); - } - - // save the complete set of modifications - session.save(); - success = true; - } finally { - if (!success) { - session.refresh(false); - } - } - return null; // TODO build loc-href if items were created. - } - - private static void createNode(Session session, String nodePath, RequestData data) throws RepositoryException { - Node parent = session.getRootNode(); - String[] smgts = Text.explode(nodePath, '/'); - - for (String nodeName : smgts) { - if (parent.hasNode(nodeName)) { - parent = parent.getNode(nodeName); - } else { - // need to create the node - // TODO: won't work for SNS - String nPath = parent.getPath() + "/" + nodeName; - String ntName = data.getParameter(nPath + "/" + JcrConstants.JCR_PRIMARYTYPE); - if (ntName == null) { - parent = parent.addNode(nodeName); - } else { - parent = parent.addNode(nodeName, ntName); - } - } - } - } - - private static Session getRepositorySession(WebdavRequest request) throws DavException { - DavSession ds = request.getDavSession(); - return JcrDavSession.getRepositorySession(ds); - } - - /** - * Returns the temp directory - * - * @return the temp directory - */ - private static File getTempDirectory(ServletContext servletCtx) { - return (File) servletCtx.getAttribute(ATTR_TMP_DIRECTORY); - } - - //-------------------------------------------------------------------------- - /** - * Locator factory that specially deals with hrefs having a .json extension. - */ - private static class DavLocatorFactoryImpl extends org.apache.jackrabbit.webdav.jcr.DavLocatorFactoryImpl { - - public DavLocatorFactoryImpl(String s) { - super(s); - } - - @Override - public DavResourceLocator createResourceLocator(String prefix, String href) { - return createResourceLocator(prefix, href, false); - } - - @Override - public DavResourceLocator createResourceLocator(String prefix, String href, boolean forDestination) { - DavResourceLocator loc = super.createResourceLocator(prefix, href); - if (!forDestination && endsWithJson(href)) { - loc = new WrappingLocator(super.createResourceLocator(prefix, href)); - } - return loc; - } - - @Override - public DavResourceLocator createResourceLocator(String prefix, String workspacePath, String path, boolean isResourcePath) { - DavResourceLocator loc = super.createResourceLocator(prefix, workspacePath, path, isResourcePath); - if (isResourcePath && endsWithJson(path)) { - loc = new WrappingLocator(loc); - } - return loc; - } - - private static boolean endsWithJson(String s) { - return s.endsWith(".json"); - } - } - - /** - * Resource locator that removes trailing .json extensions and depth - * selector that do not form part of the repository path. - * As the locator and it's factory do not have access to a JCR session - * the extraJson flag may be reset later on. - * - * @see ResourceFactoryImpl#getItem(org.apache.jackrabbit.webdav.jcr.JcrDavSession, org.apache.jackrabbit.webdav.DavResourceLocator) - */ - private static class WrappingLocator implements DavResourceLocator { - - private final DavResourceLocator loc; - private boolean isJsonRequest = true; - private int depth = Integer.MIN_VALUE; - private String repositoryPath; - - private WrappingLocator(DavResourceLocator loc) { - this.loc = loc; - } - - private void extract() { - String rp = loc.getRepositoryPath(); - rp = rp.substring(0, rp.lastIndexOf('.')); - int pos = rp.lastIndexOf('.'); - if (pos > -1) { - String depthStr = rp.substring(pos + 1); - try { - depth = Integer.parseInt(depthStr); - rp = rp.substring(0, pos); - } catch (NumberFormatException e) { - // apparently no depth-info -> ignore - } - } - repositoryPath = rp; - } - - private int getDepth() { - if (isJsonRequest) { - if (repositoryPath == null) { - extract(); - } - return depth; - } else { - return Integer.MIN_VALUE; - } - } - - public String getPrefix() { - return loc.getPrefix(); - } - public String getResourcePath() { - return loc.getResourcePath(); - } - public String getWorkspacePath() { - return loc.getWorkspacePath(); - } - public String getWorkspaceName() { - return loc.getWorkspaceName(); - } - public boolean isSameWorkspace(DavResourceLocator davResourceLocator) { - return loc.isSameWorkspace(davResourceLocator); - } - public boolean isSameWorkspace(String string) { - return loc.isSameWorkspace(string); - } - public String getHref(boolean b) { - return loc.getHref(b); - } - public boolean isRootLocation() { - return loc.isRootLocation(); - } - public DavLocatorFactory getFactory() { - return loc.getFactory(); - } - public String getRepositoryPath() { - if (isJsonRequest) { - if (repositoryPath == null) { - extract(); - } - return repositoryPath; - } else { - return loc.getRepositoryPath(); - } - } - } - - /** - * Resource factory used to make sure that the .json extension was properly - * interpreted. - */ - private static class ResourceFactoryImpl extends org.apache.jackrabbit.webdav.jcr.DavResourceFactoryImpl { - - /** - * Create a new DavResourceFactoryImpl. - * - * @param txMgr - * @param subsMgr - */ - public ResourceFactoryImpl(TxLockManagerImpl txMgr, SubscriptionManager subsMgr) { - super(txMgr, subsMgr); - } - - @Override - protected Item getItem(JcrDavSession sessionImpl, DavResourceLocator locator) throws PathNotFoundException, RepositoryException { - if (locator instanceof WrappingLocator && ((WrappingLocator)locator).isJsonRequest) { - // check if the .json extension has been correctly interpreted. - Session s = sessionImpl.getRepositorySession(); - try { - if (s.itemExists(((WrappingLocator)locator).loc.getRepositoryPath())) { - // an item exists with the original calculated repo-path - // -> assume that the repository item path ends with .json - // or .depth.json. i.e. .json wasn't an extra extension - // appended to request the json-serialization of the node. - // -> change the flag in the WrappingLocator correspondingly. - ((WrappingLocator) locator).isJsonRequest = false; - } - } catch (RepositoryException e) { - // if the unmodified repository path isn't valid (e.g. /a/b[2].5.json) - // -> ignore. - } - } - return super.getItem(sessionImpl, locator); - } - } -} Property changes on: jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/remoting/davex/JcrRemotingServlet.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Deleted: svn:keywords ## -1 +0,0 ## -author date id revision url \ No newline at end of property Index: jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/remoting/davex/JsonDiffHandler.java =================================================================== --- jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/remoting/davex/JsonDiffHandler.java (revision 1907912) +++ jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/remoting/davex/JsonDiffHandler.java (nonexistent) @@ -1,1022 +0,0 @@ -/* - * 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.remoting.davex; - -import org.apache.jackrabbit.JcrConstants; -import org.apache.jackrabbit.commons.webdav.JcrValueType; -import org.apache.jackrabbit.server.util.RequestData; -import org.apache.jackrabbit.spi.Name; -import org.apache.jackrabbit.commons.json.JsonHandler; -import org.apache.jackrabbit.commons.json.JsonParser; -import org.apache.jackrabbit.util.Text; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.xml.sax.ContentHandler; -import org.xml.sax.SAXException; -import org.xml.sax.helpers.AttributesImpl; - -import javax.jcr.ImportUUIDBehavior; -import javax.jcr.Item; -import javax.jcr.ItemNotFoundException; -import javax.jcr.Node; -import javax.jcr.NodeIterator; -import javax.jcr.Property; -import javax.jcr.PropertyType; -import javax.jcr.RepositoryException; -import javax.jcr.Session; -import javax.jcr.Value; -import javax.jcr.ValueFactory; -import javax.jcr.ValueFormatException; -import javax.jcr.nodetype.ConstraintViolationException; -import javax.jcr.nodetype.ItemDefinition; -import javax.jcr.nodetype.NodeDefinition; -import javax.jcr.nodetype.NodeType; -import javax.jcr.nodetype.NodeTypeManager; -import javax.jcr.nodetype.PropertyDefinition; -import java.io.IOException; -import java.io.InputStream; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.Stack; -import java.util.LinkedList; - -/** JsonDiffHandler... */ -class JsonDiffHandler implements DiffHandler { - - private static final Logger log = LoggerFactory.getLogger(JsonDiffHandler.class); - - private static final String ORDER_POSITION_AFTER = "#after"; - private static final String ORDER_POSITION_BEFORE = "#before"; - private static final String ORDER_POSITION_FIRST = "#first"; - private static final String ORDER_POSITION_LAST = "#last"; - - private final Session session; - private final ValueFactory vf; - private final String requestItemPath; - private final RequestData data; - private final ProtectedRemoveManager protectedRemoveManager; - - private NodeTypeManager ntManager; - - JsonDiffHandler(Session session, String requestItemPath, RequestData data) throws RepositoryException { - this(session, requestItemPath, data, null); - } - - JsonDiffHandler(Session session, String requestItemPath, RequestData data, ProtectedRemoveManager protectedRemoveManager) throws RepositoryException { - this.session = session; - this.requestItemPath = requestItemPath; - this.data = data; - vf = session.getValueFactory(); - this.protectedRemoveManager = protectedRemoveManager; - } - - //--------------------------------------------------------< DiffHandler >--- - /** - * @see DiffHandler#addNode(String, String) - */ - @Override - public void addNode(String targetPath, String diffValue) throws DiffException { - if (diffValue == null || !(diffValue.startsWith("{") && diffValue.endsWith("}"))) { - throw new DiffException("Invalid 'addNode' value '" + diffValue + "'"); - } - - try { - String itemPath = getItemPath(targetPath); - String parentPath = Text.getRelativeParent(itemPath, 1); - String nodeName = Text.getName(itemPath); - - addNode(parentPath, nodeName, diffValue); - - } catch (RepositoryException e) { - throw new DiffException(e.getMessage(), e); - } - } - - /** - * @see DiffHandler#setProperty(String, String) - */ - @Override - public void setProperty(String targetPath, String diffValue) throws DiffException { - try { - String itemPath = getItemPath(targetPath); - Item item = session.getItem(Text.getRelativeParent(itemPath, 1)); - if (!item.isNode()) { - throw new DiffException("No such node " + itemPath, new ItemNotFoundException(itemPath)); - } - - Node parent = (Node) item; - String propName = Text.getName(itemPath); - - if (JcrConstants.JCR_MIXINTYPES.equals(propName)) { - setMixins(parent, extractValuesFromRequest(targetPath)); - } else if (JcrConstants.JCR_PRIMARYTYPE.equals(propName)) { - setPrimaryType(parent, extractValuesFromRequest(targetPath)); - } else { - if (diffValue == null || diffValue.length() == 0) { - // single valued property with value present in multipart. - Value[] vs = extractValuesFromRequest(targetPath); - if (vs.length == 0) { - if (parent.hasProperty(propName)) { - // avoid problems with single vs. multi valued props. - parent.getProperty(propName).remove(); - } else { - // property does not exist -> stick to rule that missing - // [] indicates single valued. - parent.setProperty(propName, (Value) null); - } - } else if (vs.length == 1) { - parent.setProperty(propName, vs[0]); - } else { - throw new DiffException("Unexpected number of values in multipart. Was " + vs.length + " but expected 1."); - } - } else if (diffValue.startsWith("[") && diffValue.endsWith("]")) { - // multivalued property - if (diffValue.length() == 2) { - // empty array OR values in multipart - Value[] vs = extractValuesFromRequest(targetPath); - parent.setProperty(propName, vs); - } else { - // json array - Value[] vs = extractValues(diffValue); - parent.setProperty(propName, vs); - } - } else { - // single prop value included in the diff - Value v = extractValue(diffValue); - parent.setProperty(propName, v); - } - } - } catch (RepositoryException e) { - throw new DiffException(e.getMessage(), e); - } catch (IOException e) { - if (e instanceof DiffException) { - throw (DiffException) e; - } else { - throw new DiffException(e.getMessage(), e); - } - } - } - - /** - * @see DiffHandler#remove(String, String) - */ - @Override - public void remove(String targetPath, String diffValue) throws DiffException { - if (!(diffValue == null || diffValue.trim().length() == 0)) { - throw new DiffException("'remove' may not have a diffValue."); - } - try { - String itemPath = getItemPath(targetPath); - Item item = session.getItem(itemPath); - - ItemDefinition def = (item.isNode()) ? ((Node) item).getDefinition() : ((Property) item).getDefinition(); - if (def.isProtected()) { - // delegate to the manager. - if (protectedRemoveManager == null || !protectedRemoveManager.remove(session, itemPath)) { - throw new ConstraintViolationException("Cannot remove protected node: no suitable handler configured."); - } - } else { - item.remove(); - } - } catch (RepositoryException e) { - throw new DiffException(e.getMessage(), e); - } - } - - /** - * @see DiffHandler#move(String, String) - */ - @Override - public void move(String targetPath, String diffValue) throws DiffException { - if (diffValue == null || diffValue.length() == 0) { - throw new DiffException("Invalid 'move' value '" + diffValue + "'"); - } - try { - String srcPath = getItemPath(targetPath); - String orderPosition = getOrderPosition(diffValue); - if (orderPosition == null) { - // simple move - String destPath = getItemPath(diffValue); - session.move(srcPath, destPath); - } else { - String srcName = Text.getName(srcPath); - int pos = diffValue.lastIndexOf('#'); - String destName = (pos == 0) ? null : Text.getName(diffValue.substring(0, pos)); - - Item item = session.getItem(Text.getRelativeParent(srcPath, 1)); - if (!item.isNode()) { - throw new ItemNotFoundException(srcPath); - } - Node parent = (Node) item; - - if (ORDER_POSITION_FIRST.equals(orderPosition)) { - if (destName != null) { - throw new DiffException(ORDER_POSITION_FIRST + " may not have a leading destination."); - } - destName = Text.getName(parent.getNodes().nextNode().getPath()); - parent.orderBefore(srcName, destName); - } else if (ORDER_POSITION_LAST.equals(orderPosition)) { - if (destName != null) { - throw new DiffException(ORDER_POSITION_LAST + " may not have a leading destination."); - } - parent.orderBefore(srcName, null); - } else if (ORDER_POSITION_AFTER.equals(orderPosition)) { - if (destName == null) { - throw new DiffException(ORDER_POSITION_AFTER + " must have a leading destination."); - } - for (NodeIterator it = parent.getNodes(); it.hasNext();) { - Node child = it.nextNode(); - if (destName.equals(child.getName())) { - if (it.hasNext()) { - destName = Text.getName(it.nextNode().getName()); - } else { - destName = null; - } - break; - } - } - // reorder... if no child node matches the original destName - // the reorder will fail. no extra check. - parent.orderBefore(srcName, destName); - } else { - // standard jcr reorder (before) - parent.orderBefore(srcName, destName); - } - } - - } catch (RepositoryException e) { - throw new DiffException(e.getMessage(), e); - } - } - - //-------------------------------------------------------------------------- - /** - * - * @param diffPath - * @return - * @throws RepositoryException - */ - String getItemPath(String diffPath) throws RepositoryException { - StringBuffer itemPath; - if (!diffPath.startsWith("/")) { - // diff path is relative to the item path retrieved from the - // request URI -> calculate item path. - itemPath = new StringBuffer(requestItemPath); - if (!requestItemPath.endsWith("/")) { - itemPath.append('/'); - } - itemPath.append(diffPath); - } else { - itemPath = new StringBuffer(diffPath); - } - return normalize(itemPath.toString()); - } - - private void addNode(String parentPath, String nodeName, String diffValue) - throws DiffException, RepositoryException { - Item item = session.getItem(parentPath); - if (!item.isNode()) { - throw new ItemNotFoundException(parentPath); - } - - Node parent = (Node) item; - try { - NodeHandler hndlr = new NodeHandler(parent, nodeName); - new JsonParser(hndlr).parse(diffValue); - } catch (IOException e) { - if (e instanceof DiffException) { - throw (DiffException) e; - } else { - throw new DiffException(e.getMessage(), e); - } - } - } - - private NodeTypeManager getNodeTypeManager() throws RepositoryException { - if (ntManager == null) { - ntManager = session.getWorkspace().getNodeTypeManager(); - } - return ntManager; - } - - private static String normalize(String path) { - if (path.indexOf('.') == -1) { - return path; - } - String[] elems = Text.explode(path, '/', false); - LinkedList queue = new LinkedList(); - String last = ".."; - for (String segm : elems) { - if ("..".equals(segm) && !"..".equals(last)) { - queue.removeLast(); - if (queue.isEmpty()) { - last = ".."; - } else { - last = queue.getLast(); - } - } else if (!".".equals(segm)) { - last = segm; - queue.add(last); - } - } - return "/" + Text.implode(queue.toArray(new String[queue.size()]), "/"); - } - - private static ContentHandler createContentHandler(Node parent) throws RepositoryException { - return parent.getSession().getImportContentHandler(parent.getPath(), ImportUUIDBehavior.IMPORT_UUID_COLLISION_THROW); - } - - private static Node importNode(Node parent, String nodeName, String ntName, - String uuid) throws RepositoryException { - - String uri = "http://www.jcp.org/jcr/sv/1.0"; - String prefix = "sv:"; - - ContentHandler ch = createContentHandler(parent); - try { - ch.startDocument(); - - String nN = "node"; - AttributesImpl attrs = new AttributesImpl(); - attrs.addAttribute(uri, "name", prefix + "name", "CDATA", nodeName); - ch.startElement(uri, nN, prefix + nN, attrs); - - // primary node type - String pN = "property"; - attrs = new AttributesImpl(); - attrs.addAttribute(uri, "name", prefix + "name", "CDATA", JcrConstants.JCR_PRIMARYTYPE); - attrs.addAttribute(uri, "type", prefix + "type", "CDATA", PropertyType.nameFromValue(PropertyType.NAME)); - ch.startElement(uri, pN, prefix + pN, attrs); - ch.startElement(uri, "value", prefix + "value", new AttributesImpl()); - char[] val = ntName.toCharArray(); - ch.characters(val, 0, val.length); - ch.endElement(uri, "value", prefix + "value"); - ch.endElement(uri, pN, prefix + pN); - - // uuid - attrs = new AttributesImpl(); - attrs.addAttribute(uri, "name", prefix + "name", "CDATA", JcrConstants.JCR_UUID); - attrs.addAttribute(uri, "type", prefix + "type", "CDATA", PropertyType.nameFromValue(PropertyType.STRING)); - ch.startElement(uri, pN, prefix + pN, attrs); - ch.startElement(uri, "value", prefix + "value", new AttributesImpl()); - val = uuid.toCharArray(); - ch.characters(val, 0, val.length); - ch.endElement(uri, "value", prefix + "value"); - ch.endElement(uri, pN, prefix + pN); - - ch.endElement(uri, nN, prefix + nN); - ch.endDocument(); - - } catch (SAXException e) { - throw new RepositoryException(e); - } - - Node n = null; - NodeIterator it = parent.getNodes(nodeName); - while (it.hasNext()) { - n = it.nextNode(); - } - if (n == null) { - throw new RepositoryException("Internal error: No child node added."); - } - return n; - } - - private static void setPrimaryType(Node n, Value[] values) throws RepositoryException, DiffException { - if (values.length == 1) { - String ntName = values[0].getString(); - if (!ntName.equals(n.getPrimaryNodeType().getName())) { - n.setPrimaryType(ntName); - } // else: same primaryType as before -> nothing to do. - } else { - throw new DiffException("Invalid diff: jcr:primarytype cannot have multiple values, nor can it's value be removed."); - } - } - - private static void setMixins(Node n, Value[] values) throws RepositoryException { - if (values.length == 0) { - // remove all mixins - NodeType[] mixins = n.getMixinNodeTypes(); - for (NodeType mixin : mixins) { - String mixinName = mixin.getName(); - n.removeMixin(mixinName); - } - } else { - List newMixins = new ArrayList(values.length); - for (Value value : values) { - newMixins.add(value.getString()); - } - NodeType[] mixins = n.getMixinNodeTypes(); - for (NodeType mixin : mixins) { - String mixinName = mixin.getName(); - if (!newMixins.remove(mixinName)) { - n.removeMixin(mixinName); - } - } - for (String newMixinName : newMixins) { - n.addMixin(newMixinName); - } - } - } - - private static String getOrderPosition(String diffValue) { - String position = null; - if (diffValue.indexOf('#') > -1) { - if (diffValue.endsWith(ORDER_POSITION_FIRST) || - diffValue.endsWith(ORDER_POSITION_LAST) || - diffValue.endsWith(ORDER_POSITION_BEFORE) || - diffValue.endsWith(ORDER_POSITION_AFTER)) { - position = diffValue.substring(diffValue.lastIndexOf('#')); - } // else: apparently # is part of the move path. - } - return position; - } - - private Value[] extractValuesFromRequest(String paramName) throws RepositoryException, IOException { - ValueFactory vf = session.getValueFactory(); - Value[] vs; - InputStream[] ins = data.getFileParameters(paramName); - if (ins != null) { - vs = new Value[ins.length]; - for (int i = 0; i < ins.length; i++) { - vs[i] = vf.createValue(ins[i]); - } - } else { - String[] strs = data.getParameterValues(paramName); - if (strs == null) { - vs = new Value[0]; - } else { - List valList = new ArrayList(strs.length); - for (int i = 0; i < strs.length; i++) { - if (strs[i] != null) { - String[] types = data.getParameterTypes(paramName); - int type = (types == null || types.length <= i) ? PropertyType.UNDEFINED : JcrValueType.typeFromContentType(types[i]); - if (type == PropertyType.UNDEFINED) { - valList.add(vf.createValue(strs[i])); - } else { - valList.add(vf.createValue(strs[i], type)); - } - } - } - vs = valList.toArray(new Value[valList.size()]); - } - } - return vs; - } - - private Value extractValue(String diffValue) throws RepositoryException, DiffException, IOException { - ValueHandler hndlr = new ValueHandler(); - // surround diff value { key : } to make it parsable - new JsonParser(hndlr).parse("{\"a\":"+diffValue+"}"); - - return hndlr.getValue(); - } - - private Value[] extractValues(String diffValue) throws RepositoryException, DiffException, IOException { - ValuesHandler hndlr = new ValuesHandler(); - // surround diff value { key : } to make it parsable - new JsonParser(hndlr).parse("{\"a\":" + diffValue + "}"); - - return hndlr.getValues(); - } - - //-------------------------------------------------------------------------- - /** - * Inner class used to parse a single value - */ - private final class ValueHandler implements JsonHandler { - private Value v; - - @Override - public void object() throws IOException { - // ignore - } - @Override - public void endObject() throws IOException { - // ignore - } - @Override - public void array() throws IOException { - // ignore - } - @Override - public void endArray() throws IOException { - // ignore - } - @Override - public void key(String key) throws IOException { - // ignore - } - - @Override - public void value(String value) throws IOException { - v = (value == null) ? null : vf.createValue(value); - } - @Override - public void value(boolean value) throws IOException { - v = vf.createValue(value); - } - @Override - public void value(long value) throws IOException { - v = vf.createValue(value); - } - @Override - public void value(double value) throws IOException { - v = vf.createValue(value); - } - - private Value getValue() { - return v; - } - } - - /** - * Inner class used to parse the values from a simple json array - */ - private final class ValuesHandler implements JsonHandler { - private List values = new ArrayList(); - - @Override - public void object() throws IOException { - // ignore - } - @Override - public void endObject() throws IOException { - // ignore - } - @Override - public void array() throws IOException { - // ignore - } - @Override - public void endArray() throws IOException { - // ignore - } - @Override - public void key(String key) throws IOException { - // ignore - } - - @Override - public void value(String value) throws IOException { - if (value != null) { - values.add(vf.createValue(value)); - } else { - log.warn("Null element for a multivalued property -> Ignore."); - } - } - @Override - public void value(boolean value) throws IOException { - values.add(vf.createValue(value)); - } - @Override - public void value(long value) throws IOException { - values.add(vf.createValue(value)); - } - @Override - public void value(double value) throws IOException { - values.add(vf.createValue(value)); - } - - private Value[] getValues() { - return values.toArray(new Value[values.size()]); - } - } - - /** - * Inner class for parsing a simple json object defining a node and its - * child nodes and/or child properties - */ - private final class NodeHandler implements JsonHandler { - private Node parent; - private String key; - - private Stack st = new Stack(); - - private NodeHandler(Node parent, String nodeName) throws IOException { - this.parent = parent; - key = nodeName; - } - - @Override - public void object() throws IOException { - ImportNode n; - if (st.isEmpty()) { - try { - n = new ImportNode(parent.getPath(), key); - } catch (RepositoryException e) { - throw new DiffException(e.getMessage(), e); - } - - } else { - ImportItem obj = st.peek(); - n = new ImportNode(obj.getPath(), key); - if (obj instanceof ImportNode) { - ((ImportNode) obj).addNode(n); - } else { - throw new DiffException("Invalid DIFF format: The JSONArray may only contain simple values."); - } - } - st.push(n); - } - - @Override - public void endObject() throws IOException { - // element on stack must be ImportMvProp since array may only - // contain simple values, no arrays/objects are allowed. - ImportItem obj = st.pop(); - if (!((obj instanceof ImportNode))) { - throw new DiffException("Invalid DIFF format."); - } - if (st.isEmpty()) { - // everything parsed -> start adding all nodes and properties - try { - if (obj.mandatesImport(parent)) { - obj.importItem(createContentHandler(parent)); - } else { - obj.createItem(parent); - } - } catch (IOException e) { - log.error(e.getMessage()); - throw new DiffException(e.getMessage(), e); - } catch (RepositoryException e) { - log.error(e.getMessage()); - throw new DiffException(e.getMessage(), e); - } - } - } - - @Override - public void array() throws IOException { - ImportItem obj = st.peek(); - ImportMvProp prop = new ImportMvProp(obj.getPath(), key); - if (obj instanceof ImportNode) { - ((ImportNode)obj).addProp(prop); - } else { - throw new DiffException("Invalid DIFF format: The JSONArray may only contain simple values."); - } - st.push(prop); - } - - @Override - public void endArray() throws IOException { - // element on stack must be ImportMvProp since array may only - // contain simple values, no arrays/objects are allowed. - ImportItem obj = st.pop(); - if (!((obj instanceof ImportMvProp))) { - throw new DiffException("Invalid DIFF format: The JSONArray may only contain simple values."); - } - } - - @Override - public void key(String key) throws IOException { - this.key = key; - } - - @Override - public void value(String value) throws IOException { - Value v = (value == null) ? null : vf.createValue(value); - value(v); - } - - @Override - public void value(boolean value) throws IOException { - value(vf.createValue(value)); - } - - @Override - public void value(long value) throws IOException { - Value v = vf.createValue(value); - value(v); - } - - @Override - public void value(double value) throws IOException { - value(vf.createValue(value)); - } - - private void value(Value v) throws IOException { - ImportItem obj = st.peek(); - if (obj instanceof ImportMvProp) { - ((ImportMvProp) obj).values.add(v); - } else { - ((ImportNode) obj).addProp(new ImportProp(obj.getPath(), key, v)); - } - } - } - - private abstract class ImportItem { - - static final String TYPE_CDATA = "CDATA"; - - final String parentPath; - final String name; - final String path; - - private ImportItem(String parentPath, String name) throws IOException { - if (name == null) { - throw new DiffException("Invalid DIFF format: NULL key."); - } - this.name = name; - this.parentPath = parentPath; - this.path = parentPath+"/"+name; - } - - void setNameAttribute(AttributesImpl attr) { - attr.addAttribute(Name.NS_SV_URI, "name", Name.NS_SV_PREFIX +":name", TYPE_CDATA, name); - } - - String getPath() { - return path; - } - - abstract boolean mandatesImport(Node parent); - - abstract void createItem(Node parent) throws RepositoryException, IOException; - - abstract void importItem(ContentHandler contentHandler) throws IOException; - } - - private final class ImportNode extends ImportItem { - - private static final String LOCAL_NAME = "node"; - - private ImportProp ntName; - private ImportProp uuid; - - private List childN = new ArrayList(); - private List childP = new ArrayList(); - - private ImportNode(String parentPath, String name) throws IOException { - super(parentPath, name); - } - - private String getUUID() { - if (uuid != null && uuid.value != null) { - try { - return uuid.value.getString(); - } catch (RepositoryException e) { - log.error(e.getMessage()); - } - } - return null; - } - - private String getPrimaryType() { - if (ntName != null && ntName.value != null) { - try { - return ntName.value.getString(); - } catch (RepositoryException e) { - log.error(e.getMessage()); - } - } - return null; - } - - @Override - boolean mandatesImport(Node parent) { - String primaryType = getPrimaryType(); - // Very simplistic and simplified test for protection that doesn't - // take mixin types into account and ignores all JCR primary types - if (!primaryType.startsWith(Name.NS_NT_PREFIX)) { - try { - NodeType nt = getNodeTypeManager().getNodeType(primaryType); - for (NodeDefinition nd : nt.getChildNodeDefinitions()) { - if (nd.isProtected()) { - return true; - } - } - for (PropertyDefinition pd : nt.getPropertyDefinitions()) { - if (!pd.getName().startsWith(Name.NS_JCR_PREFIX) && pd.isProtected()) { - return true; - } - } - } catch (RepositoryException e) { - log.warn(e.getMessage(), e); - } - } - return false; - } - - void addProp(ImportProp prop) { - if (prop.name.equals(JcrConstants.JCR_PRIMARYTYPE)) { - ntName = prop; - } else if (prop.name.equals(JcrConstants.JCR_UUID)) { - uuid = prop; - } else { - // regular property - childP.add(prop); - } - } - - void addProp(ImportMvProp prop) { - childP.add(prop); - } - - void addNode(ImportNode node) { - childN.add(node); - } - - @Override - void importItem(ContentHandler contentHandler) throws IOException { - try { - AttributesImpl attr = new AttributesImpl(); - setNameAttribute(attr); - contentHandler.startElement(Name.NS_SV_URI, LOCAL_NAME, Name.NS_SV_PREFIX+":"+LOCAL_NAME, attr); - - if (ntName != null && ntName.value != null) { - ntName.importItem(contentHandler); - } - if (uuid != null && uuid.value != null) { - uuid.importItem(contentHandler); - } - - for(ImportProperty prop : childP) { - prop.importItem(contentHandler); - } - - for(ImportNode node : childN) { - node.importItem(contentHandler); - } - contentHandler.endElement(Name.NS_SV_URI, LOCAL_NAME, Name.NS_SV_PREFIX+":"+LOCAL_NAME); - } catch(SAXException e) { - throw new DiffException(e.getMessage(), e); - } - } - - @Override - void createItem(Node parent) throws RepositoryException, IOException { - if (mandatesImport(parent)) { - ContentHandler ch = createContentHandler(parent); - try { - ch.startDocument(); - importItem(ch); - ch.endDocument(); - } catch (SAXException e) { - throw new DiffException(e.getMessage(), e); - } - } else { - Node n; - String uuidValue = getUUID(); - String primaryType = getPrimaryType(); - if (uuidValue == null) { - n = (primaryType == null) ? parent.addNode(name) : parent.addNode(name, primaryType); - } else { - n = importNode(parent, name, primaryType, uuidValue); - } - // create all properties - for (ImportItem obj : childP) { - obj.createItem(n); - } - // recursively create all child nodes - for (ImportItem obj : childN) { - obj.createItem(n); - } - } - } - } - - private abstract class ImportProperty extends ImportItem { - - static final String VALUE = "value"; - static final String TYPE = "type"; - static final String LOCAL_NAME = "property"; - - private ImportProperty(String parentPath, String name) throws IOException { - super(parentPath, name); - } - - @Override - boolean mandatesImport(Node parent) { - // TODO: verify again if a protected property (except for jcr:primaryType and jcr:mixinTypes) will ever change outside the scope of importing the whole tree. - return false; - } - - @Override - void importItem(ContentHandler contentHandler) throws IOException { - try { - AttributesImpl propAtts = new AttributesImpl(); - setNameAttribute(propAtts); - setTypeAttribute(propAtts); - contentHandler.startElement(Name.NS_SV_URI, LOCAL_NAME, Name.NS_SV_PREFIX+":"+LOCAL_NAME, propAtts); - startValueElement(contentHandler); - contentHandler.endElement(Name.NS_SV_URI, LOCAL_NAME, Name.NS_SV_PREFIX+":"+LOCAL_NAME); - } catch(SAXException e) { - throw new DiffException(e.getMessage(), e); - } - } - - void setTypeAttribute(AttributesImpl attr) { - String type = null; - if (name.equals(JcrConstants.JCR_PRIMARYTYPE)) { - type = PropertyType.nameFromValue(PropertyType.NAME); - } else if (name.equals(JcrConstants.JCR_MIXINTYPES)) { - type = PropertyType.nameFromValue(PropertyType.NAME); - } else if (name.equals(JcrConstants.JCR_UUID)) { - type = PropertyType.nameFromValue(PropertyType.STRING); - } else { - type = PropertyType.nameFromValue(PropertyType.UNDEFINED); - } - attr.addAttribute(Name.NS_SV_URI, TYPE, Name.NS_SV_PREFIX+":"+TYPE, TYPE_CDATA, type); - } - - abstract void startValueElement(ContentHandler contentHandler) throws IOException; - } - - private final class ImportProp extends ImportProperty { - - private final Value value; - - private ImportProp(String parentPath, String name, Value value) throws IOException { - super(parentPath, name); - try { - if (value == null) { - this.value = extractValuesFromRequest(getPath())[0]; - } else { - this.value = value; - } - } catch (RepositoryException e) { - throw new DiffException(e.getMessage(), e); - } - } - - @Override - void createItem(Node parent) throws RepositoryException { - parent.setProperty(name, value); - } - - @Override - void startValueElement(ContentHandler contentHandler) throws IOException { - try { - String str = value.getString(); - contentHandler.startElement(Name.NS_SV_URI, VALUE, Name.NS_SV_PREFIX + ":" + VALUE, new AttributesImpl()); - contentHandler.characters(str.toCharArray(), 0, str.length()); - contentHandler.endElement(Name.NS_SV_URI, VALUE, Name.NS_SV_PREFIX + ":" + VALUE); - } catch (SAXException e) { - throw new DiffException(e.getMessage()); - } catch (ValueFormatException e) { - throw new DiffException(e.getMessage()); - } catch (RepositoryException e) { - throw new DiffException(e.getMessage()); - } - } - } - - private final class ImportMvProp extends ImportProperty { - - private List values = new ArrayList(); - - private ImportMvProp(String parentPath, String name) throws IOException { - super(parentPath, name); - } - - @Override - void createItem(Node parent) throws RepositoryException { - Value[] vls = values.toArray(new Value[values.size()]); - if (JcrConstants.JCR_MIXINTYPES.equals(name)) { - setMixins(parent, vls); - } else { - parent.setProperty(name, vls); - } - } - - @Override - void startValueElement(ContentHandler contentHandler) throws IOException { - try { - // Multi-valued property with values present in the request - // multi-part - if (values.size() == 0) { - values = Arrays.asList(extractValuesFromRequest(getPath())); - } - - for (Value v : values) { - String str = v.getString(); - contentHandler.startElement(Name.NS_SV_URI, VALUE, Name.NS_SV_PREFIX + ":" + VALUE, new AttributesImpl()); - contentHandler.characters(str.toCharArray(), 0, str.length()); - contentHandler.endElement(Name.NS_SV_URI, VALUE, Name.NS_SV_PREFIX + ":" + VALUE); - } - } catch (SAXException e) { - throw new DiffException(e.getMessage()); - } catch (ValueFormatException e) { - throw new DiffException(e.getMessage()); - } catch (RepositoryException e) { - throw new DiffException(e.getMessage()); - } - } - } -} Property changes on: jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/remoting/davex/JsonDiffHandler.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Deleted: svn:keywords ## -1 +0,0 ## -author date id revision url \ No newline at end of property Index: jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/remoting/davex/JsonWriter.java =================================================================== --- jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/remoting/davex/JsonWriter.java (revision 1907912) +++ jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/remoting/davex/JsonWriter.java (nonexistent) @@ -1,292 +0,0 @@ -/* - * 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.remoting.davex; - -import java.io.IOException; -import java.io.Writer; -import java.util.Collection; -import javax.jcr.Node; -import javax.jcr.NodeIterator; -import javax.jcr.Property; -import javax.jcr.PropertyIterator; -import javax.jcr.PropertyType; -import javax.jcr.RepositoryException; -import javax.jcr.Value; - -import org.apache.jackrabbit.JcrConstants; -import org.apache.jackrabbit.commons.json.JsonUtil; - -/** - * JsonWriter traverses a tree of JCR items and writes a JSON object - * exposing nodes as JSON object members and properties as JSON pairs. - *

- * Note: Using JSON.org library is deliberately avoided for the - * following reasons. - *

    - *
  • JSONObject does not preserve the order of members added, which is required - * for JCR remoting.
  • - *
  • JSONObject#numberToString: - * Double numbers get their trailing '.0' stripped away, which removes - * the ability to distinguish between JCR values of type {@link PropertyType#DOUBLE} - * and {@link PropertyType#LONG}.
  • - *
- */ -class JsonWriter { - - private final Writer writer; - - /** - * Create a new JsonItemWriter - * - * @param writer Writer to which the generated JSON string is written. - */ - JsonWriter(Writer writer) { - this.writer = writer; - } - - void write(Node node, int maxLevels) throws RepositoryException, IOException { - write(node, 0, maxLevels); - } - - void write(Collection nodes, int maxLevels) - throws RepositoryException, IOException { - writer.write('{'); - writeKey("nodes"); - writer.write('{'); - boolean first = true; - for (Node node : nodes) { - if (first) { - first = false; - } else { - writer.write(','); - } - writeKey(node.getPath()); - write(node, maxLevels); - } - writer.write('}'); - writer.write('}'); - } - - private void write(Node node, int currentLevel, int maxLevels) - throws RepositoryException, IOException { - // start of node info - writer.write('{'); - - // append the jcr properties as JSON pairs. - PropertyIterator props = node.getProperties(); - while (props.hasNext()) { - Property prop = props.nextProperty(); - writeProperty(prop); - // add separator: next json pair/member is either a property or - // a childnode or the special no-children-present pair. - writer.write(','); - } - - // for jcr child nodes include member unless the max-depths is reached. - // in case there are no children at all, append a special pair. - final NodeIterator children = node.getNodes(); - if (!children.hasNext()) { - // no child present at all -> add special property. - writeKeyValue("::NodeIteratorSize", 0); - } else { - // the child nodes - while (children.hasNext()) { - final Node n = children.nextNode(); - String name = n.getName(); - int index = n.getIndex(); - if (index > 1) { - writeKey(name + "[" + index + "]"); - } else { - writeKey(name); - } - if (maxLevels < 0 || currentLevel < maxLevels) { - write(n, currentLevel + 1, maxLevels); - } else { - /** - * In order to be able to compute the set of child-node entries - * upon Node creation -> add incomplete "node info" JSON - * object for the child node omitting properties and child - * information except for the jcr:uuid property (if present - * at all). - * the latter is required in order to build the correct SPI - * ChildInfo for Node n. - */ - writeChildInfo(n); - } - if (children.hasNext()) { - writer.write(','); - } - } - } - - // end of node info - writer.write('}'); - } - - /** - * Write child info without including the complete node info. - * - * @param n - * @throws RepositoryException - * @throws IOException - */ - private void writeChildInfo(Node n) throws RepositoryException, IOException { - // start child info - writer.write('{'); - - // make sure the SPI childInfo can be built correctly on the - // client side -> pass uuid if present. - if (n.isNodeType(JcrConstants.MIX_REFERENCEABLE) && - n.hasProperty(JcrConstants.JCR_UUID)) { - writeProperty(n.getProperty(JcrConstants.JCR_UUID)); - } - - // end child info - writer.write('}'); - } - - /** - * Write a single property - * - * @param p - * @throws javax.jcr.RepositoryException - * @throws java.io.IOException - */ - private void writeProperty(Property p) throws RepositoryException, IOException { - // special handling for binaries: we dump the length and not the length - int type = p.getType(); - if (type == PropertyType.BINARY) { - // mark binary properties with a leading ':' - // the value(s) reflect the jcr-values length instead of the binary data. - String key = ":" + p.getName(); - if (p.isMultiple()) { - long[] binLengths = p.getLengths(); - writeKeyArray(key, binLengths); - } else { - writeKeyValue(key, p.getLength()); - } - } else { - boolean isMultiple = p.isMultiple(); - if (requiresTypeInfo(p) || (isMultiple && p.getValues().length == 0)) { - /* special property types that have no correspondence in JSON - are transported as String. the type is transported with an - extra key-value pair, the key having a leading ':' the value - reflects the type. - the same applies for multivalued properties consisting of an - empty array -> property type guessing would not be possible. - */ - writeKeyValue(":" + p.getName(), PropertyType.nameFromValue(type), true); - } - /* append key-value pair containing the jcr value(s). - for String, Boolean, Double, Long -> types in json available */ - if (isMultiple) { - writeKeyArray(p.getName(), p.getValues()); - } else { - writeKeyValue(p.getName(), p.getValue()); - } - } - } - - private static boolean requiresTypeInfo(Property p) throws RepositoryException { - switch (p.getType()) { - case PropertyType.NAME: - case PropertyType.PATH: - case PropertyType.REFERENCE: - case PropertyType.DATE: - case PropertyType.WEAKREFERENCE: - case PropertyType.URI: - case PropertyType.DECIMAL: - case PropertyType.DOUBLE: - return true; - default: - // any other property type - return false; - } - } - - private void writeKeyValue(String key, String value, boolean hasNext) throws IOException { - writeKey(key); - writer.write(JsonUtil.getJsonString(value)); - if (hasNext) { - writer.write(','); - } - } - - private void writeKeyValue(String key, Value value) throws RepositoryException, IOException { - writeKey(key); - writeJsonValue(value); - } - - private void writeKeyArray(String key, Value[] values) throws RepositoryException, IOException { - writeKey(key); - writer.write('['); - for (int i = 0; i < values.length; i++) { - if (i > 0) { - writer.write(','); - } - writeJsonValue(values[i]); - } - writer.write(']'); - } - - private void writeKeyValue(String key, long binLength) throws IOException { - writeKey(key); - writer.write(String.valueOf(binLength)); - } - - private void writeKeyArray(String key, long[] binLengths) throws RepositoryException, IOException { - writeKey(key); - writer.write('['); - for (int i = 0; i < binLengths.length; i++) { - if (i > 0) { - writer.write(','); - } - writer.write(String.valueOf(binLengths[i])); - } - writer.write(']'); - } - - private void writeKey(String key) throws IOException { - writer.write(JsonUtil.getJsonString(key)); - writer.write(':'); - } - - private void writeJsonValue(Value v) throws RepositoryException, IOException { - - switch (v.getType()) { - case PropertyType.BINARY: - // should never get here - throw new IllegalArgumentException(); - - case PropertyType.BOOLEAN: - case PropertyType.LONG: - writer.write(v.getString()); - break; - case PropertyType.DOUBLE: - double d = v.getDouble(); - String str = v.getString(); - if (Double.isNaN(d) || Double.isInfinite(d)) { - str = JsonUtil.getJsonString(str); - } - writer.write(str); - break; - - default: - writer.write(JsonUtil.getJsonString(v.getString())); - } - } -} Property changes on: jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/remoting/davex/JsonWriter.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Deleted: svn:keywords ## -1 +0,0 ## -author date id revision url \ No newline at end of property Index: jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/remoting/davex/ProtectedItemRemoveHandler.java =================================================================== --- jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/remoting/davex/ProtectedItemRemoveHandler.java (revision 1907912) +++ jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/remoting/davex/ProtectedItemRemoveHandler.java (nonexistent) @@ -1,28 +0,0 @@ -/* - * 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.remoting.davex; - -import javax.jcr.RepositoryException; -import javax.jcr.Session; - -/** - * ProtectedItemRemoveHandler... TODO - */ -public interface ProtectedItemRemoveHandler { - - public boolean remove(Session session, String itemPath) throws RepositoryException; -} Property changes on: jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/remoting/davex/ProtectedItemRemoveHandler.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/remoting/davex/ProtectedRemoveConfig.java =================================================================== --- jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/remoting/davex/ProtectedRemoveConfig.java (revision 1907912) +++ jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/remoting/davex/ProtectedRemoveConfig.java (nonexistent) @@ -1,83 +0,0 @@ -/* - * 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.remoting.davex; - -import java.io.IOException; -import java.io.InputStream; - -import javax.xml.parsers.ParserConfigurationException; - -import org.apache.jackrabbit.webdav.xml.DomUtil; -import org.apache.jackrabbit.webdav.xml.ElementIterator; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.w3c.dom.Element; -import org.xml.sax.SAXException; - -/** - * A configuration of ProtectedItemRemoveHandler(s). - * - * ProtectedRemoveConfig - */ -class ProtectedRemoveConfig { - - private static final Logger log = LoggerFactory.getLogger(ProtectedRemoveConfig.class); - - private static final String ELEMENT_HANDLER = "protecteditemremovehandler"; - private static final String ELEMENT_CLASS = "class"; - private static final String ATTRIBUTE_NAME = "name"; - - private final ProtectedRemoveManager manager; - - ProtectedRemoveConfig(ProtectedRemoveManager manager) { - this.manager = manager; - } - - void parse(InputStream inputStream) throws IOException { - Element config; - ProtectedItemRemoveHandler instance = null; - try { - config = DomUtil.parseDocument(inputStream).getDocumentElement(); - if (config == null) { - log.warn("Missing mandatory config element"); - return; - } - ElementIterator handlers = DomUtil.getChildren(config, ELEMENT_HANDLER, null); - while (handlers.hasNext()) { - Element handler = handlers.nextElement(); - instance = createHandler(handler); - manager.addHandler(instance); - } - } catch (ParserConfigurationException e) { - log.error(e.getMessage(), e); - } catch (SAXException e) { - log.error(e.getMessage(), e); - } - } - - private ProtectedItemRemoveHandler createHandler(Element parent) { - ProtectedItemRemoveHandler instance = null; - Element classElem = DomUtil.getChildElement(parent, ELEMENT_CLASS, null); - if (classElem != null) { - String className = DomUtil.getAttribute(classElem, ATTRIBUTE_NAME, null); - if (className != null) { - instance = manager.createHandler(className); - } - } - return instance; - } -} Property changes on: jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/remoting/davex/ProtectedRemoveConfig.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/remoting/davex/ProtectedRemoveManager.java =================================================================== --- jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/remoting/davex/ProtectedRemoveManager.java (revision 1907912) +++ jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/remoting/davex/ProtectedRemoveManager.java (nonexistent) @@ -1,112 +0,0 @@ -/* - * 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.remoting.davex; - -import java.io.File; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.IOException; -import java.io.InputStream; -import java.util.ArrayList; -import java.util.List; - -import javax.jcr.RepositoryException; -import javax.jcr.Session; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -class ProtectedRemoveManager { - - private static final Logger log = LoggerFactory.getLogger(ProtectedRemoveManager.class); - - private List handlers = new ArrayList(); - - ProtectedRemoveManager(){ - - } - - ProtectedRemoveManager(String config) throws IOException { - - if (config == null) { - log.warn("protectedhandlers-config is missing -> DIFF processing can fail for the Remove operation if the content to" - + "remove is protected!"); - } else { - File file = new File(config); - if (file.exists()) { - try { - InputStream fis = new FileInputStream(file); - load(fis); - } catch (FileNotFoundException e) { - throw new IOException(e.getMessage(), e); - } - } else { // config is an Impl class - if (!config.isEmpty()) { - ProtectedItemRemoveHandler handler = createHandler(config); - addHandler(handler); - } else { - log.debug("Fail to locate the protected-item-remove-handler properties file."); - } - } - } - } - - void load(InputStream fis) throws IOException { - ProtectedRemoveConfig prConfig = new ProtectedRemoveConfig(this); - prConfig.parse(fis); - } - - boolean remove(Session session, String itemPath) throws RepositoryException { - for (ProtectedItemRemoveHandler handler : handlers) { - if (handler.remove(session, itemPath)) { - return true; - } - } - return false; - } - - /** - * Instantiates and returns a concrete ProtectedItemRemoveHandler implementation. - * @param className - * @return - * @throws RepositoryException - */ - ProtectedItemRemoveHandler createHandler(String className) { - ProtectedItemRemoveHandler irHandler = null; - try { - if (!className.isEmpty()) { - Class irHandlerClass = Class.forName(className); - if (ProtectedItemRemoveHandler.class.isAssignableFrom(irHandlerClass)) { - irHandler = (ProtectedItemRemoveHandler) irHandlerClass.newInstance(); - } - } - } catch (ClassNotFoundException e) { - log.error(e.getMessage(), e); - } catch (InstantiationException e) { - log.error(e.getMessage(), e); - } catch (IllegalAccessException e) { - log.error(e.getMessage(), e); - } - return irHandler; - } - - void addHandler(ProtectedItemRemoveHandler instance) { - if (instance != null) { - handlers.add(instance); - } - } -} Property changes on: jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/remoting/davex/ProtectedRemoveManager.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/util/HttpMultipartPost.java =================================================================== --- jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/util/HttpMultipartPost.java (revision 1907912) +++ jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/util/HttpMultipartPost.java (nonexistent) @@ -1,286 +0,0 @@ -/* - * 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.util; - -import org.apache.commons.fileupload.FileItem; -import org.apache.commons.fileupload.FileItemFactory; -import org.apache.commons.fileupload.FileUploadException; -import org.apache.commons.fileupload.disk.DiskFileItemFactory; -import org.apache.commons.fileupload.servlet.ServletFileUpload; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import javax.servlet.http.HttpServletRequest; -import java.io.File; -import java.io.IOException; -import java.io.InputStream; -import java.util.ArrayList; -import java.util.HashSet; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; -import java.util.Set; - -/** - * HttpMultipartPost... - */ -class HttpMultipartPost { - - private static final Logger log = LoggerFactory.getLogger(HttpMultipartPost.class); - - private final Map> nameToItems = new LinkedHashMap>(); - private final Set fileParamNames = new HashSet(); - - private boolean initialized; - - HttpMultipartPost(HttpServletRequest request, File tmpDir) throws IOException { - extractMultipart(request, tmpDir); - initialized = true; - } - - private static FileItemFactory getFileItemFactory(File tmpDir) { - DiskFileItemFactory fiFactory = new DiskFileItemFactory(DiskFileItemFactory.DEFAULT_SIZE_THRESHOLD, tmpDir); - return fiFactory; - } - - private void extractMultipart(HttpServletRequest request, File tmpDir) - throws IOException { - if (!ServletFileUpload.isMultipartContent(request)) { - log.debug("Request does not contain multipart content -> ignoring."); - return; - } - - ServletFileUpload upload = new ServletFileUpload(getFileItemFactory(tmpDir)); - // make sure the content disposition headers are read with the charset - // specified in the request content type (or UTF-8 if no charset is specified). - // see JCR - if (request.getCharacterEncoding() == null) { - upload.setHeaderEncoding("UTF-8"); - } - try { - @SuppressWarnings("unchecked") - List fileItems = upload.parseRequest(request); - for (FileItem fileItem : fileItems) { - addItem(fileItem); - } - } catch (FileUploadException e) { - log.error("Error while processing multipart.", e); - throw new IOException(e.toString()); - } - } - - /** - * Add the given file item to the list defined for its name and make the - * list is present in the map. If the item does not represent a simple - * form field its name is also added to the fileParamNames set. - * - * @param item The {@link FileItem} to add. - */ - private void addItem(FileItem item) { - String name = item.getFieldName(); - List l = nameToItems.get(item.getFieldName()); - if (l == null) { - l = new ArrayList(); - nameToItems.put(name, l); - } - l.add(item); - - // if file parameter, add name to the set of file parameters in order to - // be able to extract the file parameter values later on without iterating - // over all keys. - if (!item.isFormField()) { - fileParamNames.add(name); - } - } - - private void checkInitialized() { - if (!initialized) { - throw new IllegalStateException("HttpMultipartPost not initialized (or already disposed)."); - } - } - - /** - * Release all file items hold with the name-to-items map. Especially those - * having a temporary file associated with. - * - * @see FileItem#delete() - */ - synchronized void dispose() { - checkInitialized(); - - for (List fileItems : nameToItems.values()) { - for (FileItem fileItem : fileItems) { - fileItem.delete(); - } - } - - nameToItems.clear(); - fileParamNames.clear(); - initialized = false; - } - - /** - * Returns an iterator over all file item names. - * - * @return a set of strings. - */ - Set getParameterNames() { - checkInitialized(); - return nameToItems.keySet(); - } - - - /** - * Returns the content types of the parameters with the given name. If - * the parameter does not exist null is returned. If the content - * type of any of the parameter values is not known, the corresponding entry - * in the array returned is null. - *

- * The content type of a parameter is only known here if the information - * has been sent by the client browser. This is generally only the case - * for file upload fields of HTML forms which have been posted using the - * HTTP POST with multipart/form-data encoding. - *

- * Example : For the form - *

-         
-
-
- -
- *
- * this method will return an array of two entries when called for the - * Upload parameter. The first entry will contain the content - * type (if transmitted by the client) of the file uploaded. The second - * entry will be null because the content type of the text - * input field will generally not be sent by the client. - * - * @param name The name of the parameter whose content type is to be - * returned. - * @return The content types of the file items with the specified name. - */ - String[] getParameterTypes(String name) { - checkInitialized(); - String[] cts = null; - List l = nameToItems.get(name); - if (l != null && !l.isEmpty()) { - cts = new String[l.size()]; - for (int i = 0; i < cts.length; i++) { - cts[i] = l.get(i).getContentType(); - } - } - return cts; - } - - /** - * Returns the first value of the file items with the given name. - * The byte to string conversion is done using either the content type of - * the file items or the formEncoding. - *

- * Please note that if the addressed parameter is an uploaded file rather - * than a simple form entry, the name of the original file is returned - * instead of the content. - * - * @param name the name of the parameter - * @return the string of the first value or null if the - * parameter does not exist - */ - String getParameter(String name) { - checkInitialized(); - List l = nameToItems.get(name); - if (l == null || l.isEmpty()) { - return null; - } else { - FileItem item = l.get(0); - if (item.isFormField()) { - return item.getString(); - } else { - return item.getName(); - } - } - } - - /** - * Returns an array of Strings with all values of the parameter addressed - * by name. the byte to string conversion is done using either - * the content type of the multipart body or the formEncoding. - *

- * Please note that if the addressed parameter is an uploaded file rather - * than a simple form entry, the name of the original file is returned - * instead of the content. - * - * @param name the name of the parameter - * @return a string array of values or null if no entry with the - * given name exists. - */ - String[] getParameterValues(String name) { - checkInitialized(); - List l = nameToItems.get(name); - if (l == null || l.isEmpty()) { - return null; - } else { - String[] values = new String[l.size()]; - for (int i = 0; i < values.length; i++) { - FileItem item = l.get(i); - if (item.isFormField()) { - values[i] = item.getString(); - } else { - values[i] = item.getName(); - } - } - return values; - } - } - - /** - * Returns a set of the file parameter names. An empty set if - * no file parameters were present in the request. - * - * @return an set of file item names representing the file - * parameters available with the request. - */ - Set getFileParameterNames() { - checkInitialized(); - return fileParamNames; - } - - /** - * Returns an array of input streams for uploaded file parameters. - * - * @param name the name of the file parameter(s) - * @return an array of input streams or null if no file params - * with the given name exist. - * @throws IOException if an I/O error occurs - */ - InputStream[] getFileParameterValues(String name) throws IOException { - checkInitialized(); - InputStream[] values = null; - if (fileParamNames.contains(name)) { - List l = nameToItems.get(name); - if (l != null && !l.isEmpty()) { - List ins = new ArrayList(l.size()); - for (FileItem item : l) { - if (!item.isFormField()) { - ins.add(item.getInputStream()); - } - } - values = ins.toArray(new InputStream[ins.size()]); - } - } - return values; - } -} Property changes on: jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/util/HttpMultipartPost.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Deleted: svn:keywords ## -1 +0,0 ## -author date id revision url \ No newline at end of property Index: jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/util/RequestData.java =================================================================== --- jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/util/RequestData.java (revision 1907912) +++ jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/util/RequestData.java (nonexistent) @@ -1,118 +0,0 @@ -/* - * 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.util; - -import javax.servlet.http.HttpServletRequest; -import java.io.File; -import java.io.IOException; -import java.io.InputStream; -import java.util.HashSet; -import java.util.Iterator; - -/** - * RequestData... - */ -public class RequestData { - - private final HttpServletRequest request; - private final HttpMultipartPost mpReq; - - public RequestData(HttpServletRequest request, File tmpDir) throws IOException { - this.request = request; - this.mpReq = new HttpMultipartPost(request, tmpDir); - } - - /** - * Dispose resources used. - */ - public void dispose() { - mpReq.dispose(); - } - - /** - * Returns an iterator over all parameter names. - * - * @return an iterator over strings. - */ - public Iterator getParameterNames() { - @SuppressWarnings("unchecked") - HashSet names = new HashSet(request.getParameterMap().keySet()); - names.addAll(mpReq.getParameterNames()); - - return names.iterator(); - } - - /** - * Returns the first value of the parameter with the given name. - * The byte to string conversion is done using either the content type of - * the parameter or the formEncoding. - *

- * Please note that if the addressed parameter is a file parameter, the - * name of the original file is returned, and not its content. - * - * @param name the name of the parameter - * @return the string of the first value or null if the - * parameter does not exist - */ - public String getParameter(String name) { - String ret = mpReq.getParameter(name); - return (ret == null) ? request.getParameter(name) : ret; - } - - /** - * Returns the content types retrieved for parameters with the specified - * name from the multipart or null if the multipart does not - * contain parameter(s) with the given name. - * - * @param name parameter name - * @return the parameter types retrieved for the specified parameter - * name from the multipart or null. - */ - public String[] getParameterTypes(String name) { - String[] types = mpReq.getParameterTypes(name); - return types == null ? null : types; - } - - /** - * Returns an array of Strings with all values of the parameter addressed - * by name. the byte to string conversion is done using either - * the content type of the multipart body or the formEncoding. - *

- * Please note that if the addressed parameter is a file parameter, the - * name of the original file is returned, and not its content. - * - * @param name the name of the parameter - * @return a string array of values or null if the parameter - * does not exist. - */ - public String[] getParameterValues(String name) { - String[] ret = mpReq.getParameterValues(name); - return ret == null ? request.getParameterValues(name) : ret; - } - - /** - * Returns an array of input streams for uploaded file parameters. - * - * @param name the name of the file parameter(s) - * @return an array of input streams or an empty array if no file params - * with the given name exist. - * @throws IOException if an I/O error occurs - */ - public InputStream[] getFileParameters(String name) throws IOException { - return mpReq.getFileParameterValues(name); - } -} Property changes on: jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/util/RequestData.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Deleted: svn:keywords ## -1 +0,0 ## -author date id revision url \ No newline at end of property Index: jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/AbstractItemResource.java =================================================================== --- jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/AbstractItemResource.java (revision 1907912) +++ jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/AbstractItemResource.java (nonexistent) @@ -1,482 +0,0 @@ -/* - * 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.webdav.jcr; - -import org.apache.jackrabbit.util.Text; -import org.apache.jackrabbit.webdav.DavCompliance; -import org.apache.jackrabbit.webdav.DavException; -import org.apache.jackrabbit.webdav.DavResource; -import org.apache.jackrabbit.webdav.DavResourceFactory; -import org.apache.jackrabbit.webdav.DavResourceLocator; -import org.apache.jackrabbit.webdav.DavServletResponse; -import org.apache.jackrabbit.webdav.io.OutputContext; -import org.apache.jackrabbit.webdav.jcr.nodetype.ItemDefinitionImpl; -import org.apache.jackrabbit.webdav.jcr.nodetype.NodeDefinitionImpl; -import org.apache.jackrabbit.webdav.jcr.nodetype.PropertyDefinitionImpl; -import org.apache.jackrabbit.webdav.jcr.property.JcrDavPropertyNameSet; -import org.apache.jackrabbit.webdav.observation.EventDiscovery; -import org.apache.jackrabbit.webdav.observation.ObservationConstants; -import org.apache.jackrabbit.webdav.observation.ObservationResource; -import org.apache.jackrabbit.webdav.observation.Subscription; -import org.apache.jackrabbit.webdav.observation.SubscriptionInfo; -import org.apache.jackrabbit.webdav.observation.SubscriptionManager; -import org.apache.jackrabbit.webdav.property.DavProperty; -import org.apache.jackrabbit.webdav.property.DavPropertyName; -import org.apache.jackrabbit.webdav.property.DefaultDavProperty; -import org.apache.jackrabbit.webdav.property.HrefProperty; -import org.apache.jackrabbit.webdav.transaction.TxLockEntry; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import javax.jcr.Item; -import javax.jcr.Node; -import javax.jcr.PathNotFoundException; -import javax.jcr.Property; -import javax.jcr.RepositoryException; -import javax.jcr.Workspace; -import java.io.IOException; - -/** - * AbstractItemResource covers common functionality for the various - * resources, that represent a repository item. - */ -abstract class AbstractItemResource extends AbstractResource implements - ObservationResource, ItemResourceConstants { - - private static Logger log = LoggerFactory.getLogger(AbstractItemResource.class); - - private SubscriptionManager subsMgr; - protected final Item item; - - /** - * Create a new AbstractItemResource. - * - * @param locator - * @param session - * @param factory - * @param item - */ - AbstractItemResource(DavResourceLocator locator, JcrDavSession session, - DavResourceFactory factory, Item item) { - super(locator, session, factory); - this.item = item; - - // initialize the supported locks and reports - initLockSupport(); - initSupportedReports(); - } - - //----------------------------------------------< DavResource interface >--- - /** - * @see org.apache.jackrabbit.webdav.DavResource#getComplianceClass() - */ - @Override - public String getComplianceClass() { - return DavCompliance.concatComplianceClasses( - new String[] { - super.getComplianceClass(), - DavCompliance.OBSERVATION, - } - ); - } - - @Override - public DavProperty getProperty(DavPropertyName name) { - DavProperty prop = super.getProperty(name); - if (prop == null) { - if (JCR_DEFINITION.equals(name)) { - if (exists()) { - try { - - // protected 'definition' property revealing the item definition - ItemDefinitionImpl val; - if (item.isNode()) { - val = NodeDefinitionImpl.create(((Node)item).getDefinition()); - } else { - val = PropertyDefinitionImpl.create(((Property)item).getDefinition()); - } - prop = new DefaultDavProperty(JCR_DEFINITION, val, true); - } catch (RepositoryException e) { - // should not get here - log.error("Error while accessing item definition: " + e.getMessage()); - } - } - } else if (JCR_ISNEW.equals(name)) { - // transaction resource additional protected properties - if (exists() && item.isNew()) { - prop = new DefaultDavProperty(JCR_ISNEW, null, true); - } - } else if (JCR_ISMODIFIED.equals(name)) { - // transaction resource additional protected properties - if (exists() && item.isModified()) { - prop = new DefaultDavProperty(JCR_ISMODIFIED, null, true); - } - } else if (ObservationConstants.SUBSCRIPTIONDISCOVERY.equals(name)) { - // observation resource - prop = subsMgr.getSubscriptionDiscovery(this); - } - } - - return prop; - } - - /** - * @see org.apache.jackrabbit.webdav.DavResource#getSupportedMethods() - */ - @Override - public String getSupportedMethods() { - return ItemResourceConstants.METHODS; - } - - /** - * Returns true if there exists a {@link Item repository item} with the given - * resource path, false otherwise. - * - * @see org.apache.jackrabbit.webdav.DavResource#exists() - */ - @Override - public boolean exists() { - return item != null; - } - - /** - * Retrieves the last segment of the item path (or the resource path if - * this resource does not exist). An item path is in addition first translated - * to the corresponding resource path.
- * NOTE: the display name is not equivalent to {@link Item#getName() item name} - * which is exposed with the {@link ItemResourceConstants#JCR_NAME - * {http://www.day.com/jcr/webdav/1.0}name} property. - * - * @see org.apache.jackrabbit.webdav.DavResource#getDisplayName() - */ - @Override - public String getDisplayName() { - String resPath = getResourcePath(); - return (resPath != null) ? Text.getName(resPath) : resPath; - } - - /** - * Spools the properties of this resource to the context. Note that subclasses - * are in charge of spooling the data to the output stream provided by the - * context. - * - * @see DavResource#spool(OutputContext) - */ - @Override - public void spool(OutputContext outputContext) throws IOException { - if (!initedProps) { - initProperties(); - } - // export properties - outputContext.setModificationTime(getModificationTime()); - DavProperty etag = getProperty(DavPropertyName.GETETAG); - if (etag != null) { - outputContext.setETag(String.valueOf(etag.getValue())); - } - DavProperty contentType = getProperty(DavPropertyName.GETCONTENTTYPE); - if (contentType != null) { - outputContext.setContentType(String.valueOf(contentType.getValue())); - } - DavProperty contentLength = getProperty(DavPropertyName.GETCONTENTLENGTH); - if (contentLength != null) { - try { - long length = Long.parseLong(contentLength.getValue() + ""); - if (length > 0) { - outputContext.setContentLength(length); - } - } catch (NumberFormatException e) { - log.error("Could not build content length from property value '" + contentLength.getValue() + "'"); - } - } - DavProperty contentLanguage = getProperty(DavPropertyName.GETCONTENTLANGUAGE); - if (contentLanguage != null) { - outputContext.setContentLanguage(contentLanguage.getValue().toString()); - } - } - - /** - * Returns the resource representing the parent item of the repository item - * represented by this resource. If this resoure represents the root item - * a {@link RootCollection} is returned. - * - * @return the collection this resource is internal member of. Except for the - * repository root, the returned collection always represent the parent - * repository node. - * @see org.apache.jackrabbit.webdav.DavResource#getCollection() - */ - @Override - public DavResource getCollection() { - DavResource collection = null; - - String parentPath = Text.getRelativeParent(getResourcePath(), 1); - DavResourceLocator parentLoc = getLocator().getFactory().createResourceLocator(getLocator().getPrefix(), getLocator().getWorkspacePath(), parentPath); - try { - collection = createResourceFromLocator(parentLoc); - } catch (DavException e) { - log.error("Unexpected error while retrieving collection: " + e.getMessage()); - } - - return collection; - } - - /** - * Moves the underlying repository item to the indicated destination. - * - * @param destination - * @throws DavException - * @see DavResource#move(DavResource) - * @see javax.jcr.Session#move(String, String) - */ - @Override - public void move(DavResource destination) throws DavException { - if (!exists()) { - throw new DavException(DavServletResponse.SC_NOT_FOUND); - } - DavResourceLocator destLocator = destination.getLocator(); - if (!getLocator().isSameWorkspace(destLocator)) { - throw new DavException(DavServletResponse.SC_FORBIDDEN); - } - - try { - String itemPath = getLocator().getRepositoryPath(); - String destItemPath = destination.getLocator().getRepositoryPath(); - if (getTransactionId() == null) { - // if not part of a transaction directly import on workspace - getRepositorySession().getWorkspace().move(itemPath, destItemPath); - } else { - // changes will not be persisted unless the tx is completed. - getRepositorySession().move(itemPath, destItemPath); - } - // no use in calling 'complete' that would fail for a moved item anyway. - } catch (PathNotFoundException e) { - // according to rfc 2518 - throw new DavException(DavServletResponse.SC_CONFLICT, e.getMessage()); - } catch (RepositoryException e) { - throw new JcrDavException(e); - } - } - - /** - * Copies the underlying repository item to the indicated destination. If - * the locator of the specified destination resource indicates a different - * workspace, {@link Workspace#copy(String, String, String)} is used to perform - * the copy operation, {@link Workspace#copy(String, String)} otherwise. - *

- * Note, that this implementation does not support shallow copy. - * - * @param destination - * @param shallow - * @throws DavException - * @see DavResource#copy(DavResource, boolean) - * @see Workspace#copy(String, String) - * @see Workspace#copy(String, String, String) - */ - @Override - public void copy(DavResource destination, boolean shallow) throws DavException { - if (!exists()) { - throw new DavException(DavServletResponse.SC_NOT_FOUND); - } - // TODO: support shallow and deep copy is required by RFC 2518 - if (shallow) { - throw new DavException(DavServletResponse.SC_FORBIDDEN, "Unable to perform shallow copy."); - } - - try { - String itemPath = getLocator().getRepositoryPath(); - String destItemPath = destination.getLocator().getRepositoryPath(); - Workspace workspace = getRepositorySession().getWorkspace(); - if (getLocator().isSameWorkspace(destination.getLocator())) { - workspace.copy(itemPath, destItemPath); - } else { - log.error("Copy between workspaces is not yet implemented (src: '" + getHref() + "', dest: '" + destination.getHref() + "')"); - throw new DavException(DavServletResponse.SC_NOT_IMPLEMENTED); - } - } catch (PathNotFoundException e) { - // according to RFC 2518, should not occur - throw new DavException(DavServletResponse.SC_NOT_FOUND, e.getMessage()); - } catch (RepositoryException e) { - throw new JcrDavException(e); - } - } - - //--------------------------------------< ObservationResource interface >--- - /** - * @see ObservationResource#init(SubscriptionManager) - */ - @Override - public void init(SubscriptionManager subsMgr) { - this.subsMgr = subsMgr; - } - - /** - * @see ObservationResource#subscribe(org.apache.jackrabbit.webdav.observation.SubscriptionInfo, String) - * @see SubscriptionManager#subscribe(org.apache.jackrabbit.webdav.observation.SubscriptionInfo, String, org.apache.jackrabbit.webdav.observation.ObservationResource) - */ - @Override - public Subscription subscribe(SubscriptionInfo info, String subscriptionId) - throws DavException { - return subsMgr.subscribe(info, subscriptionId, this); - } - - /** - * @see ObservationResource#unsubscribe(String) - * @see SubscriptionManager#unsubscribe(String, org.apache.jackrabbit.webdav.observation.ObservationResource) - */ - @Override - public void unsubscribe(String subscriptionId) throws DavException { - subsMgr.unsubscribe(subscriptionId, this); - } - - /** - * @see ObservationResource#poll(String, long) - * @see SubscriptionManager#poll(String, long, org.apache.jackrabbit.webdav.observation.ObservationResource) - */ - @Override - public EventDiscovery poll(String subscriptionId, long timeout) throws DavException { - return subsMgr.poll(subscriptionId, timeout, this); - } - - //-------------------------------------------------------------------------- - /** - * Initialize the {@link org.apache.jackrabbit.webdav.lock.SupportedLock} property - * with entries that are valid for any type item resources. - * - * @see org.apache.jackrabbit.webdav.lock.SupportedLock - * @see org.apache.jackrabbit.webdav.transaction.TxLockEntry - * @see AbstractResource#initLockSupport() - */ - @Override - protected void initLockSupport() { - if (exists()) { - // add supported lock entries for local and eventually for global - // transaction locks - supportedLock.addEntry(new TxLockEntry(true)); - supportedLock.addEntry(new TxLockEntry(false)); - } - } - - @Override - protected void initPropertyNames() { - super.initPropertyNames(); - if (exists()) { - names.addAll(JcrDavPropertyNameSet.EXISTING_ITEM_BASE_SET); - try { - if (item.getDepth() > 0) { - names.add(JCR_PARENT); - } - } catch (RepositoryException e) { - log.warn("Error while accessing node depth: " + e.getMessage()); - } - if (item.isNew()) { - names.add(JCR_ISNEW); - } else if (item.isModified()) { - names.add(JCR_ISMODIFIED); - } - } else { - names.addAll(JcrDavPropertyNameSet.ITEM_BASE_SET); - } - } - - /** - * Fill the property set for this resource. - */ - @Override - protected void initProperties() { - super.initProperties(); - if (exists()) { - try { - properties.add(new DefaultDavProperty(JCR_NAME, item.getName())); - properties.add(new DefaultDavProperty(JCR_PATH, item.getPath())); - int depth = item.getDepth(); - properties.add(new DefaultDavProperty(JCR_DEPTH, String.valueOf(depth))); - // add href-property for the items parent unless its the root item - if (depth > 0) { - String parentHref = getLocatorFromItem(item.getParent()).getHref(true); - properties.add(new HrefProperty(JCR_PARENT, parentHref, false)); - } - } catch (RepositoryException e) { - // should not get here - log.error("Error while accessing jcr properties: " + e.getMessage()); - } - } - } - - /** - * @return href of the workspace or null if this resource - * does not represent a repository item. - * - * @see AbstractResource#getWorkspaceHref() - */ - @Override - protected String getWorkspaceHref() { - String workspaceHref = null; - DavResourceLocator locator = getLocator(); - if (locator != null && locator.getWorkspacePath() != null) { - String wspPath = locator.getWorkspacePath(); - DavResourceLocator wspLocator = locator.getFactory().createResourceLocator(locator.getPrefix(), wspPath, wspPath); - workspaceHref = wspLocator.getHref(true); - } - log.debug(workspaceHref); - return workspaceHref; - } - - /** - * If this resource exists but does not contain a transaction id, complete - * will try to persist any modifications present on the underlying - * repository item. - * - * @throws DavException if calling {@link Item#save()} fails - */ - void complete() throws DavException { - if (exists() && getTransactionId() == null) { - try { - if (item.isModified()) { - item.save(); - } - } catch (RepositoryException e) { - // this includes LockException, ConstraintViolationException etc. not detected before - log.error("Error while completing request: " + e.getMessage() +" -> reverting changes."); - try { - item.refresh(false); - } catch (RepositoryException re) { - log.error("Error while reverting changes: " + re.getMessage()); - } - throw new JcrDavException(e); - } - } - } - - /** - * Retrieves the last segment of the given path and removes the index if - * present. - * - * @param itemPath - * @return valid jcr item name - */ - protected static String getItemName(String itemPath) { - if (itemPath == null) { - throw new IllegalArgumentException("Cannot retrieve name from a 'null' item path."); - } - // retrieve the last part of the path - String name = Text.getName(itemPath); - // remove index - if (name.endsWith("]")) { - name = name.substring(0, name.lastIndexOf('[')); - } - return name; - } -} Property changes on: jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/AbstractItemResource.java ___________________________________________________________________ Deleted: svn Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/AbstractResource.java =================================================================== --- jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/AbstractResource.java (revision 1907912) +++ jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/AbstractResource.java (nonexistent) @@ -1,861 +0,0 @@ -/* - * 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.webdav.jcr; - -import org.apache.jackrabbit.server.io.IOUtil; -import org.apache.jackrabbit.webdav.DavException; -import org.apache.jackrabbit.webdav.DavLocatorFactory; -import org.apache.jackrabbit.webdav.DavResource; -import org.apache.jackrabbit.webdav.DavResourceFactory; -import org.apache.jackrabbit.webdav.DavResourceLocator; -import org.apache.jackrabbit.webdav.DavServletResponse; -import org.apache.jackrabbit.webdav.DavSession; -import org.apache.jackrabbit.webdav.MultiStatus; -import org.apache.jackrabbit.webdav.MultiStatusResponse; -import org.apache.jackrabbit.webdav.WebdavRequest; -import org.apache.jackrabbit.webdav.WebdavRequestContext; -import org.apache.jackrabbit.webdav.DavCompliance; -import org.apache.jackrabbit.webdav.jcr.property.JcrDavPropertyNameSet; -import org.apache.jackrabbit.webdav.util.HttpDateFormat; -import org.apache.jackrabbit.webdav.jcr.search.SearchResourceImpl; -import org.apache.jackrabbit.webdav.jcr.transaction.TxLockManagerImpl; -import org.apache.jackrabbit.webdav.jcr.version.report.NodeTypesReport; -import org.apache.jackrabbit.webdav.jcr.version.report.LocateByUuidReport; -import org.apache.jackrabbit.webdav.jcr.version.report.RegisteredNamespacesReport; -import org.apache.jackrabbit.webdav.jcr.version.report.RepositoryDescriptorsReport; -import org.apache.jackrabbit.webdav.lock.ActiveLock; -import org.apache.jackrabbit.webdav.lock.LockDiscovery; -import org.apache.jackrabbit.webdav.lock.LockInfo; -import org.apache.jackrabbit.webdav.lock.LockManager; -import org.apache.jackrabbit.webdav.lock.Scope; -import org.apache.jackrabbit.webdav.lock.SupportedLock; -import org.apache.jackrabbit.webdav.lock.Type; -import org.apache.jackrabbit.webdav.property.DavProperty; -import org.apache.jackrabbit.webdav.property.DavPropertyName; -import org.apache.jackrabbit.webdav.property.DavPropertyNameSet; -import org.apache.jackrabbit.webdav.property.DavPropertySet; -import org.apache.jackrabbit.webdav.property.DefaultDavProperty; -import org.apache.jackrabbit.webdav.property.HrefProperty; -import org.apache.jackrabbit.webdav.property.ResourceType; -import org.apache.jackrabbit.webdav.property.PropEntry; -import org.apache.jackrabbit.webdav.search.QueryGrammerSet; -import org.apache.jackrabbit.webdav.search.SearchInfo; -import org.apache.jackrabbit.webdav.search.SearchResource; -import org.apache.jackrabbit.webdav.server.WebdavRequestContextHolder; -import org.apache.jackrabbit.webdav.transaction.TransactionConstants; -import org.apache.jackrabbit.webdav.transaction.TransactionInfo; -import org.apache.jackrabbit.webdav.transaction.TransactionResource; -import org.apache.jackrabbit.webdav.transaction.TxLockManager; -import org.apache.jackrabbit.webdav.version.DeltaVConstants; -import org.apache.jackrabbit.webdav.version.DeltaVResource; -import org.apache.jackrabbit.webdav.version.OptionsInfo; -import org.apache.jackrabbit.webdav.version.OptionsResponse; -import org.apache.jackrabbit.webdav.version.SupportedMethodSetProperty; -import org.apache.jackrabbit.webdav.version.report.Report; -import org.apache.jackrabbit.webdav.version.report.ReportInfo; -import org.apache.jackrabbit.webdav.version.report.ReportType; -import org.apache.jackrabbit.webdav.version.report.SupportedReportSetProperty; -import org.apache.jackrabbit.webdav.xml.DomUtil; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.w3c.dom.Element; - -import javax.jcr.Item; -import javax.jcr.RepositoryException; -import javax.jcr.Session; -import javax.jcr.observation.EventListener; -import javax.jcr.observation.Event; -import javax.jcr.observation.EventIterator; -import javax.xml.parsers.ParserConfigurationException; - -import java.util.ArrayList; -import java.util.Date; -import java.util.Iterator; -import java.util.List; - -/** - * AbstractResource provides functionality common to all - * resources. - */ -abstract class AbstractResource implements DavResource, TransactionResource, - DeltaVResource, SearchResource { - - private static Logger log = LoggerFactory.getLogger(AbstractResource.class); - - private static final String COMPLIANCE_CLASSES = - DavCompliance.concatComplianceClasses(new String[] { - DavCompliance._1_, - DavCompliance._2_, - DavCompliance._3_, - DavCompliance.VERSION_CONTROL, - DavCompliance.VERSION_HISTORY, - DavCompliance.CHECKOUT_IN_PLACE, - DavCompliance.LABEL, - DavCompliance.MERGE, - DavCompliance.UPDATE, - DavCompliance.WORKSPACE - }); - - private final DavResourceLocator locator; - private final JcrDavSession session; - private final DavResourceFactory factory; - - private TxLockManagerImpl txMgr; - private String transactionId; - - protected boolean initedProps; - protected DavPropertySet properties = new DavPropertySet(); - protected DavPropertyNameSet names; - protected SupportedLock supportedLock = new SupportedLock(); - protected SupportedReportSetProperty supportedReports = new SupportedReportSetProperty(); - - /** - * Create a new AbstractResource - * - * @param locator - * @param session - * @param factory - */ - AbstractResource(DavResourceLocator locator, JcrDavSession session, - DavResourceFactory factory) { - if (session == null) { - throw new IllegalArgumentException("Creating AbstractItemResource: DavSession must not be null and must provide a JCR session."); - } - this.locator = locator; - this.session = session; - this.factory = factory; - } - - /** - * Returns a string listing the compliance classes for this resource as it - * is required for the DAV response header. This includes DAV 1, 2 which - * is supported by all derived classes as well as a subset of the - * classes defined by DeltaV: version-control, version-history, checkout-in-place, - * label, merge, update and workspace.
- * Those compliance classes are added as required by RFC3253 since all - * all resources in the jcr-server support at least the reporting and some - * basic versioning functionality. - * - * @return string listing the compliance classes. - * @see org.apache.jackrabbit.webdav.DavResource#getComplianceClass() - */ - @Override - public String getComplianceClass() { - return COMPLIANCE_CLASSES; - } - - /** - * @see org.apache.jackrabbit.webdav.DavResource#getLocator() - */ - @Override - public DavResourceLocator getLocator() { - return locator; - } - - /** - * Returns the path of the underlying repository item or the item to - * be created (PUT/MKCOL). If the resource exists but does not represent - * a repository item null is returned. - * - * @return path of the underlying repository item. - * @see DavResource#getResourcePath() - * @see org.apache.jackrabbit.webdav.DavResourceLocator#getResourcePath() - */ - @Override - public String getResourcePath() { - return locator.getResourcePath(); - } - - /** - * @see DavResource#getHref() - * @see DavResourceLocator#getHref(boolean) - */ - @Override - public String getHref() { - return locator.getHref(isCollection()); - } - - /** - * @see org.apache.jackrabbit.webdav.DavResource#getPropertyNames() - */ - @Override - public DavPropertyName[] getPropertyNames() { - initPropertyNames(); - return names.getContent().toArray(new DavPropertyName[names.getContentSize()]); - } - - /** - * @see org.apache.jackrabbit.webdav.DavResource#getProperty(org.apache.jackrabbit.webdav.property.DavPropertyName) - */ - @Override - public DavProperty getProperty(DavPropertyName name) { - DavProperty prop = getProperties().get(name); - if (prop == null) { - if (DeltaVConstants.SUPPORTED_METHOD_SET.equals(name)) { - prop = new SupportedMethodSetProperty(getSupportedMethods().split(",\\s")); - } else if (DeltaVConstants.SUPPORTED_REPORT_SET.equals(name)) { - prop = supportedReports; - } else if (DeltaVConstants.CREATOR_DISPLAYNAME.equals(name)) { - // DAV:creator-displayname default value : not available - prop = new DefaultDavProperty(DeltaVConstants.CREATOR_DISPLAYNAME, getCreatorDisplayName(), true); - } else if (DeltaVConstants.COMMENT.equals(name)) { - // DAV:comment not value available from jcr - prop = new DefaultDavProperty(DeltaVConstants.COMMENT, null, true); - } else if (DeltaVConstants.WORKSPACE.equals(name)) { - // 'workspace' property as defined by RFC 3253 - String workspaceHref = getWorkspaceHref(); - if (workspaceHref != null) { - prop = new HrefProperty(DeltaVConstants.WORKSPACE, workspaceHref, true); - } - } - } - - // TODO: required supported-live-property-set - return prop; - } - - /** - * @see org.apache.jackrabbit.webdav.DavResource#getProperties() - */ - @Override - public DavPropertySet getProperties() { - if (!initedProps) { - initProperties(); - } - return properties; - } - - /** - * Throws {@link DavServletResponse#SC_METHOD_NOT_ALLOWED} - * - * @param property - * @throws DavException Always throws {@link DavServletResponse#SC_METHOD_NOT_ALLOWED} - * @see org.apache.jackrabbit.webdav.DavResource#setProperty(org.apache.jackrabbit.webdav.property.DavProperty) - */ - @Override - public void setProperty(DavProperty property) throws DavException { - throw new DavException(DavServletResponse.SC_METHOD_NOT_ALLOWED); - } - - /** - * Throws {@link DavServletResponse#SC_METHOD_NOT_ALLOWED} - * - * @param propertyName - * @throws DavException Always throws {@link DavServletResponse#SC_METHOD_NOT_ALLOWED} - * @see org.apache.jackrabbit.webdav.DavResource#removeProperty(org.apache.jackrabbit.webdav.property.DavPropertyName) - */ - @Override - public void removeProperty(DavPropertyName propertyName) throws DavException { - throw new DavException(DavServletResponse.SC_METHOD_NOT_ALLOWED); - } - - /** - * Throws {@link DavServletResponse#SC_METHOD_NOT_ALLOWED} - * - * @see DavResource#alterProperties(List) - */ - @Override - public MultiStatusResponse alterProperties(List changeList) throws DavException { - throw new DavException(DavServletResponse.SC_METHOD_NOT_ALLOWED); - } - - /** - * Throws {@link DavServletResponse#SC_METHOD_NOT_ALLOWED} - * - * @param destination - * @throws DavException Always throws {@link DavServletResponse#SC_METHOD_NOT_ALLOWED} - * @see DavResource#move(org.apache.jackrabbit.webdav.DavResource) - */ - @Override - public void move(DavResource destination) throws DavException { - throw new DavException(DavServletResponse.SC_METHOD_NOT_ALLOWED); - } - - /** - * Throws {@link DavServletResponse#SC_METHOD_NOT_ALLOWED} - * - * @param destination - * @param shallow - * @throws DavException Always throws {@link DavServletResponse#SC_METHOD_NOT_ALLOWED} - * @see DavResource#copy(org.apache.jackrabbit.webdav.DavResource, boolean) - */ - @Override - public void copy(DavResource destination, boolean shallow) throws DavException { - throw new DavException(DavServletResponse.SC_METHOD_NOT_ALLOWED); - } - - - /** - * Returns true, if the {@link SupportedLock} property contains an entry - * with the given type and scope. By default resources allow for {@link org.apache.jackrabbit.webdav.transaction.TransactionConstants#XML_TRANSACTION - * transaction} lock only. - * - * @param type - * @param scope - * @return true if this resource may be locked by the given type and scope. - * @see DavResource#isLockable(org.apache.jackrabbit.webdav.lock.Type, org.apache.jackrabbit.webdav.lock.Scope) - */ - @Override - public boolean isLockable(Type type, Scope scope) { - return supportedLock.isSupportedLock(type, scope); - } - - /** - * Returns true if this resource has a lock applied with the given type and scope. - * - * @param type - * @param scope - * @return true if this resource has a lock applied with the given type and scope. - * @see DavResource#hasLock(Type, Scope) - */ - @Override - public boolean hasLock(Type type, Scope scope) { - return getLock(type, scope) != null; - } - - /** - * @see DavResource#getLock(Type, Scope) - */ - @Override - public ActiveLock getLock(Type type, Scope scope) { - ActiveLock lock = null; - if (TransactionConstants.TRANSACTION.equals(type)) { - lock = txMgr.getLock(type, scope, this); - } - return lock; - } - - /** - * @see DavResource#getLocks() - * todo improve.... - */ - @Override - public ActiveLock[] getLocks() { - List locks = new ArrayList(); - // tx locks - ActiveLock l = getLock(TransactionConstants.TRANSACTION, TransactionConstants.LOCAL); - if (l != null) { - locks.add(l); - } - l = getLock(TransactionConstants.TRANSACTION, TransactionConstants.GLOBAL); - if (l != null) { - locks.add(l); - } - // write lock (either exclusive or session-scoped). - l = getLock(Type.WRITE, Scope.EXCLUSIVE); - if (l != null) { - locks.add(l); - } else { - l = getLock(Type.WRITE, ItemResourceConstants.EXCLUSIVE_SESSION); - if (l != null) { - locks.add(l); - } - } - return locks.toArray(new ActiveLock[locks.size()]); - } - - /** - * @see DavResource#lock(org.apache.jackrabbit.webdav.lock.LockInfo) - */ - @Override - public ActiveLock lock(LockInfo reqLockInfo) throws DavException { - if (isLockable(reqLockInfo.getType(), reqLockInfo.getScope())) { - return txMgr.createLock(reqLockInfo, this); - } else { - throw new DavException(DavServletResponse.SC_PRECONDITION_FAILED); - } - } - - /** - * Only transaction lock may be available on this resource. - * - * @param info - * @param lockToken - * @throws DavException - * @see DavResource#refreshLock(org.apache.jackrabbit.webdav.lock.LockInfo, String) - */ - @Override - public ActiveLock refreshLock(LockInfo info, String lockToken) throws DavException { - return txMgr.refreshLock(info, lockToken, this); - } - - /** - * Throws {@link DavServletResponse#SC_METHOD_NOT_ALLOWED} since only transaction - * locks may be present on this resource, that need to be released by calling - * {@link TransactionResource#unlock(String, org.apache.jackrabbit.webdav.transaction.TransactionInfo)}. - * - * @param lockToken - * @throws DavException Always throws {@link DavServletResponse#SC_METHOD_NOT_ALLOWED} - */ - @Override - public void unlock(String lockToken) throws DavException { - throw new DavException(DavServletResponse.SC_PRECONDITION_FAILED); - } - - /** - * @see DavResource#addLockManager(org.apache.jackrabbit.webdav.lock.LockManager) - */ - @Override - public void addLockManager(LockManager lockMgr) { - if (lockMgr instanceof TxLockManagerImpl) { - txMgr = (TxLockManagerImpl) lockMgr; - } - } - - /** - * @see org.apache.jackrabbit.webdav.DavResource#getFactory() - */ - @Override - public DavResourceFactory getFactory() { - return factory; - } - - //-------------------------------------------------------------------------- - /** - * @see org.apache.jackrabbit.webdav.transaction.TransactionResource#getSession() - * @see org.apache.jackrabbit.webdav.observation.ObservationResource#getSession() - */ - @Override - public DavSession getSession() { - return session; - } - - //--------------------------------------< TransactionResource interface >--- - /** - * @see TransactionResource#init(TxLockManager, String) - */ - @Override - public void init(TxLockManager txMgr, String transactionId) { - this.txMgr = (TxLockManagerImpl) txMgr; - this.transactionId = transactionId; - } - - /** - * @see TransactionResource#unlock(String, org.apache.jackrabbit.webdav.transaction.TransactionInfo) - */ - @Override - public void unlock(String lockToken, TransactionInfo tInfo) throws DavException { - txMgr.releaseLock(tInfo, lockToken, this); - } - - /** - * @see TransactionResource#getTransactionId() - */ - @Override - public String getTransactionId() { - return transactionId; - } - - //-------------------------------------------< DeltaVResource interface >--- - /** - * @param optionsInfo - * @return object to be used in the OPTIONS response body or null - * @see DeltaVResource#getOptionResponse(org.apache.jackrabbit.webdav.version.OptionsInfo) - */ - @Override - public OptionsResponse getOptionResponse(OptionsInfo optionsInfo) { - OptionsResponse oR = null; - if (optionsInfo != null) { - oR = new OptionsResponse(); - // currently only DAV:version-history-collection-set and - // DAV:workspace-collection-set is supported. - if (optionsInfo.containsElement(DeltaVConstants.XML_VH_COLLECTION_SET, DeltaVConstants.NAMESPACE)) { - String[] hrefs = new String[] { - getLocatorFromItemPath(ItemResourceConstants.VERSIONSTORAGE_PATH).getHref(true) - }; - oR.addEntry(DeltaVConstants.XML_VH_COLLECTION_SET, DeltaVConstants.NAMESPACE, hrefs); - } - if (optionsInfo.containsElement(DeltaVConstants.XML_WSP_COLLECTION_SET, DeltaVConstants.NAMESPACE)) { - // workspaces cannot be created anywhere. - oR.addEntry(DeltaVConstants.XML_WSP_COLLECTION_SET, DeltaVConstants.NAMESPACE, new String[0]); - } - } - return oR; - } - - /** - * @param reportInfo - * @return the requested report - * @throws DavException - * @see DeltaVResource#getReport(org.apache.jackrabbit.webdav.version.report.ReportInfo) - */ - @Override - public Report getReport(ReportInfo reportInfo) throws DavException { - if (reportInfo == null) { - throw new DavException(DavServletResponse.SC_BAD_REQUEST, "A REPORT request must provide a valid XML request body."); - } - if (!exists()) { - throw new DavException(DavServletResponse.SC_NOT_FOUND); - } - - if (!supportedReports.isSupportedReport(reportInfo)) { - Element condition = null; - try { - condition = DomUtil.createDocument().createElementNS("DAV:", "supported-report"); - } catch (ParserConfigurationException ex) { - // we don't care THAT much - } - throw new DavException(DavServletResponse.SC_CONFLICT, - "Unknown report '" + reportInfo.getReportName() + "' requested.", null, condition); - } - - return ReportType.getType(reportInfo).createReport(this, reportInfo); - } - - /** - * The JCR api does not provide methods to create new workspaces. Calling - * addWorkspace on this resource will always fail. - * - * @param workspace - * @throws DavException Always throws. - * @see DeltaVResource#addWorkspace(org.apache.jackrabbit.webdav.DavResource) - */ - @Override - public void addWorkspace(DavResource workspace) throws DavException { - throw new DavException(DavServletResponse.SC_FORBIDDEN); - } - - /** - * Return an array of DavResource objects that are referenced - * by the property with the specified name. - * - * @param hrefPropertyName - * @return array of DavResources - * @throws DavException - * @see DeltaVResource#getReferenceResources(org.apache.jackrabbit.webdav.property.DavPropertyName) - */ - @Override - public DavResource[] getReferenceResources(DavPropertyName hrefPropertyName) throws DavException { - DavProperty prop = getProperty(hrefPropertyName); - if (prop == null || !(prop instanceof HrefProperty)) { - throw new DavException(DavServletResponse.SC_CONFLICT, "Unknown Href-Property '" + hrefPropertyName + "' on resource " + getResourcePath()); - } - - List hrefs = ((HrefProperty)prop).getHrefs(); - DavResource[] refResources = new DavResource[hrefs.size()]; - Iterator hrefIter = hrefs.iterator(); - int i = 0; - while (hrefIter.hasNext()) { - refResources[i] = getResourceFromHref(hrefIter.next()); - i++; - } - return refResources; - } - - /** - * Retrieve the DavResource object that is represented by - * the given href String. - * - * @param href - * @return DavResource object - */ - private DavResource getResourceFromHref(String href) throws DavException { - // build a new locator: remove trailing prefix - DavResourceLocator locator = getLocator(); - String prefix = locator.getPrefix(); - DavResourceLocator loc = locator.getFactory().createResourceLocator(prefix, href); - - // create a new resource object - try { - DavResource res; - if (getRepositorySession().itemExists(loc.getRepositoryPath())) { - res = createResourceFromLocator(loc); - } else { - throw new DavException(DavServletResponse.SC_NOT_FOUND); - } - return res; - } catch (RepositoryException e) { - throw new JcrDavException(e); - } - } - - //-------------------------------------------< SearchResource interface >--- - /** - * @return - * @see org.apache.jackrabbit.webdav.search.SearchResource#getQueryGrammerSet() - */ - @Override - public QueryGrammerSet getQueryGrammerSet() { - return new SearchResourceImpl(getLocator(), session).getQueryGrammerSet(); - } - - /** - * @param sInfo - * @return - * @throws DavException - * @see SearchResource#search(org.apache.jackrabbit.webdav.search.SearchInfo) - */ - @Override - public MultiStatus search(SearchInfo sInfo) throws DavException { - return new SearchResourceImpl(getLocator(), session).search(sInfo); - } - - //-------------------------------------------------------------------------- - /** - * Property names common to all resources. - */ - protected void initPropertyNames() { - names = new DavPropertyNameSet(JcrDavPropertyNameSet.BASE_SET); - } - - /** - * Fill the set of default properties - */ - protected void initProperties() { - if (getDisplayName() != null) { - properties.add(new DefaultDavProperty(DavPropertyName.DISPLAYNAME, getDisplayName())); - } - if (isCollection()) { - properties.add(new ResourceType(ResourceType.COLLECTION)); - // Windows XP support - properties.add(new DefaultDavProperty(DavPropertyName.ISCOLLECTION, "1")); - } else { - properties.add(new ResourceType(ResourceType.DEFAULT_RESOURCE)); - // Windows XP support - properties.add(new DefaultDavProperty(DavPropertyName.ISCOLLECTION, "0")); - } - // todo: add etag - - // default last modified - String lastModified = IOUtil.getLastModified(getModificationTime()); - properties.add(new DefaultDavProperty(DavPropertyName.GETLASTMODIFIED, lastModified)); - - // default creation time - properties.add(new DefaultDavProperty(DavPropertyName.CREATIONDATE, getCreationDate())); - - // supported lock property - properties.add(supportedLock); - - // set current lock information. If no lock is applied to this resource, - // an empty xlockdiscovery will be returned in the response. - properties.add(new LockDiscovery(getLocks())); - - // name of the jcr workspace - properties.add(new DefaultDavProperty(ItemResourceConstants.JCR_WORKSPACE_NAME, - getRepositorySession().getWorkspace().getName())); - } - - /** - * Create a new DavResource from the given locator. - * @param loc - * @return new DavResource - * @throws org.apache.jackrabbit.webdav.DavException - */ - protected DavResource createResourceFromLocator(DavResourceLocator loc) - throws DavException { - DavResource res = factory.createResource(loc, session); - if (res instanceof AbstractResource) { - ((AbstractResource)res).transactionId = this.transactionId; - } - return res; - } - - /** - * Build a DavResourceLocator from the given itemPath path. - * - * @param itemPath - * @return a new DavResourceLocator - * @see DavLocatorFactory#createResourceLocator(String, String, String) - */ - protected DavResourceLocator getLocatorFromItemPath(String itemPath) { - DavResourceLocator loc = locator.getFactory().createResourceLocator(locator.getPrefix(), locator.getWorkspacePath(), itemPath, false); - return loc; - } - - /** - * Build a new {@link DavResourceLocator} from the given repository item. - * - * @param repositoryItem - * @return a new locator for the specified item. - * @see #getLocatorFromItemPath(String) - */ - protected DavResourceLocator getLocatorFromItem(Item repositoryItem) { - String itemPath = null; - try { - if (repositoryItem != null) { - itemPath = repositoryItem.getPath(); - } - } catch (RepositoryException e) { - // ignore: should not occur - log.warn(e.getMessage()); - } - return getLocatorFromItemPath(itemPath); - } - - /** - * Shortcut for getSession().getRepositorySession() - * - * @return repository session present in the {@link AbstractResource#session}. - */ - protected Session getRepositorySession() { - return session.getRepositorySession(); - } - - /** - * Define the set of locks supported by this resource. - * - * @see org.apache.jackrabbit.webdav.lock.SupportedLock - */ - abstract protected void initLockSupport(); - - /** - * Define the set of reports supported by this resource. - * - * @see org.apache.jackrabbit.webdav.version.report.SupportedReportSetProperty - */ - /** - * Define the set of reports supported by this resource. - * - * @see org.apache.jackrabbit.webdav.version.report.SupportedReportSetProperty - * @see AbstractResource#initSupportedReports() - */ - protected void initSupportedReports() { - if (exists()) { - supportedReports = new SupportedReportSetProperty(new ReportType[] { - ReportType.EXPAND_PROPERTY, - NodeTypesReport.NODETYPES_REPORT, - LocateByUuidReport.LOCATE_BY_UUID_REPORT, - RegisteredNamespacesReport.REGISTERED_NAMESPACES_REPORT, - RepositoryDescriptorsReport.REPOSITORY_DESCRIPTORS_REPORT - }); - } - } - - /** - * Retrieve the href of the workspace the current session belongs to. - * - * @return href of the workspace - */ - abstract protected String getWorkspaceHref(); - - /** - * Returns the display name of the creator which is used for the protected - * {@link DeltaVConstants#CREATOR_DISPLAYNAME} property. - * - * @return always null; subclasses may provide a regular value. - */ - protected String getCreatorDisplayName() { - return null; - } - - /** - * Returns the creation date which is used for the - * {@link DavPropertyName#CREATIONDATE} property. - * - * @return a dummy date; subclasses may provide a reasonable value. - */ - protected String getCreationDate() { - return HttpDateFormat.creationDateFormat().format(new Date(0)); - } - - /** - * Normalize the resource {@code href}. For example, remove contextPath prefix if found. - * @param href resource href - * @return normalized resource {@code href} - */ - protected String normalizeResourceHref(final String href) { - if (href == null) { - return href; - } - - final WebdavRequestContext requestContext = WebdavRequestContextHolder.getContext(); - final WebdavRequest request = (requestContext != null) ? requestContext.getRequest() : null; - - if (request == null) { - log.error("WebdavRequest is unavailable in the current execution context."); - return href; - } - - final String contextPath = request.getContextPath(); - - if (!contextPath.isEmpty() && href.startsWith(contextPath)) { - return href.substring(contextPath.length()); - } - - return href; - } - - //-------------------------------------------------------------------------- - /** - * Register the specified event listener with the observation manager present - * the repository session. - * - * @param listener - * @param nodePath - * @throws javax.jcr.RepositoryException - */ - void registerEventListener(EventListener listener, String nodePath) throws RepositoryException { - getRepositorySession().getWorkspace().getObservationManager().addEventListener(listener, EListener.ALL_EVENTS, nodePath, true, null, null, false); - } - - /** - * Unregister the specified event listener with the observation manager present - * the repository session. - * - * @param listener - * @throws javax.jcr.RepositoryException - */ - void unregisterEventListener(EventListener listener) throws RepositoryException { - getRepositorySession().getWorkspace().getObservationManager().removeEventListener(listener); - } - - //------------------------------------------------------< inner classes >--- - /** - * Simple EventListener that creates a new {@link org.apache.jackrabbit.webdav.MultiStatusResponse} object - * for each event and adds it to the specified {@link org.apache.jackrabbit.webdav.MultiStatus}. - */ - class EListener implements EventListener { - - private static final int ALL_EVENTS = Event.NODE_ADDED - | Event.NODE_REMOVED - | Event.PROPERTY_ADDED - | Event.PROPERTY_CHANGED - | Event.PROPERTY_REMOVED - | Event.NODE_MOVED - | Event.PERSIST; - - private final DavPropertyNameSet propNameSet; - private MultiStatus ms; - - EListener(DavPropertyNameSet propNameSet, MultiStatus ms) { - this.propNameSet = propNameSet; - this.ms = ms; - } - - /** - * @see EventListener#onEvent(javax.jcr.observation.EventIterator) - */ - @Override - public void onEvent(EventIterator events) { - while (events.hasNext()) { - try { - Event e = events.nextEvent(); - DavResourceLocator loc = getLocatorFromItemPath(e.getPath()); - DavResource res = createResourceFromLocator(loc); - ms.addResponse(new MultiStatusResponse(res, propNameSet)); - - } catch (DavException e) { - // should not occur - log.error("Error while building MultiStatusResponse from Event: " + e.getMessage()); - } catch (RepositoryException e) { - // should not occur - log.error("Error while building MultiStatusResponse from Event: " + e.getMessage()); - } - } - } - } -} Property changes on: jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/AbstractResource.java ___________________________________________________________________ Deleted: svn Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/DavLocatorFactoryImpl.java =================================================================== --- jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/DavLocatorFactoryImpl.java (revision 1907912) +++ jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/DavLocatorFactoryImpl.java (nonexistent) @@ -1,94 +0,0 @@ -/* - * 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.webdav.jcr; - -import org.apache.jackrabbit.webdav.AbstractLocatorFactory; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * DavLocatorFactoryImpl... - */ -public class DavLocatorFactoryImpl extends AbstractLocatorFactory { - - private static Logger log = LoggerFactory.getLogger(DavLocatorFactoryImpl.class); - - /** - * Create a new factory - * - * @param pathPrefix Prefix, that needs to be removed in order to retrieve - * the repository path from a given href. - */ - public DavLocatorFactoryImpl(String pathPrefix) { - super(pathPrefix); - } - - //---------------------------------------------------------------------- - /** - * - * @param resourcePath - * @param wspPath - * @return - * @see AbstractLocatorFactory#getRepositoryPath(String, String) - */ - @Override - protected String getRepositoryPath(String resourcePath, String wspPath) { - if (resourcePath == null) { - return null; - } - if (resourcePath.equals(wspPath)) { - // workspace - log.debug("Resource path represents workspace path -> repository path is null."); - return null; - } else { - // a repository item -> remove wspPath + /jcr:root - String pfx = wspPath + ItemResourceConstants.ROOT_ITEM_RESOURCEPATH; - if (resourcePath.startsWith(pfx)) { - String repositoryPath = resourcePath.substring(pfx.length()); - return (repositoryPath.length() == 0) ? ItemResourceConstants.ROOT_ITEM_PATH : repositoryPath; - } else { - log.error("Unexpected format of resource path."); - throw new IllegalArgumentException("Unexpected format of resource path: " + resourcePath + " (workspace: " + wspPath + ")"); - } - } - } - - /** - * - * @param repositoryPath - * @param wspPath - * @return - * @see AbstractLocatorFactory#getResourcePath(String, String) - */ - @Override - protected String getResourcePath(String repositoryPath, String wspPath) { - if (wspPath != null) { - StringBuffer b = new StringBuffer(wspPath); - if (repositoryPath != null) { - b.append(ItemResourceConstants.ROOT_ITEM_RESOURCEPATH); - if (!ItemResourceConstants.ROOT_ITEM_PATH.equals(repositoryPath)) { - b.append(repositoryPath); - } - } - return b.toString(); - } else { - log.debug("Workspace path is 'null' -> 'null' resource path"); - return null; - } - } -} - Property changes on: jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/DavLocatorFactoryImpl.java ___________________________________________________________________ Deleted: svn Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/DavResourceFactoryImpl.java =================================================================== --- jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/DavResourceFactoryImpl.java (revision 1907912) +++ jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/DavResourceFactoryImpl.java (nonexistent) @@ -1,251 +0,0 @@ -/* - * 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.webdav.jcr; - -import javax.jcr.AccessDeniedException; -import javax.jcr.Item; -import javax.jcr.Node; -import javax.jcr.PathNotFoundException; -import javax.jcr.RepositoryException; -import javax.jcr.observation.EventJournal; -import javax.jcr.version.Version; -import javax.jcr.version.VersionHistory; -import javax.servlet.http.HttpServletResponse; - -import org.apache.jackrabbit.JcrConstants; -import org.apache.jackrabbit.util.Text; -import org.apache.jackrabbit.webdav.DavException; -import org.apache.jackrabbit.webdav.DavMethods; -import org.apache.jackrabbit.webdav.DavResource; -import org.apache.jackrabbit.webdav.DavResourceFactory; -import org.apache.jackrabbit.webdav.DavResourceLocator; -import org.apache.jackrabbit.webdav.DavServletRequest; -import org.apache.jackrabbit.webdav.DavServletResponse; -import org.apache.jackrabbit.webdav.DavSession; -import org.apache.jackrabbit.webdav.jcr.transaction.TxLockManagerImpl; -import org.apache.jackrabbit.webdav.jcr.version.VersionHistoryItemCollection; -import org.apache.jackrabbit.webdav.jcr.version.VersionItemCollection; -import org.apache.jackrabbit.webdav.observation.ObservationResource; -import org.apache.jackrabbit.webdav.observation.SubscriptionManager; -import org.apache.jackrabbit.webdav.transaction.TransactionDavServletRequest; -import org.apache.jackrabbit.webdav.transaction.TransactionResource; -import org.apache.jackrabbit.webdav.version.DeltaVServletRequest; -import org.apache.jackrabbit.webdav.version.VersionControlledResource; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * DavResourceFactoryImpl... - */ -public class DavResourceFactoryImpl implements DavResourceFactory { - - private static Logger log = LoggerFactory.getLogger(DavResourceFactoryImpl.class); - - private final TxLockManagerImpl txMgr; - private final SubscriptionManager subsMgr; - - /** - * Create a new DavResourceFactoryImpl. - * - * @param txMgr - * @param subsMgr - */ - public DavResourceFactoryImpl(TxLockManagerImpl txMgr, SubscriptionManager subsMgr) { - this.txMgr = txMgr; - this.subsMgr = subsMgr; - } - - /** - * Create a new DavResource from the specified locator and request - * objects. Note, that in contrast to - * {@link #createResource(DavResourceLocator, DavSession)} the locator may - * point to a non-existing resource. - *

- * If the request contains a {@link org.apache.jackrabbit.webdav.version.DeltaVServletRequest#getLabel() - * Label header}, the resource is build from the indicated - * {@link org.apache.jackrabbit.webdav.version.VersionResource version} instead. - * - * @param locator - * @param request - * @param response - * @return - * @see DavResourceFactory#createResource(org.apache.jackrabbit.webdav.DavResourceLocator, org.apache.jackrabbit.webdav.DavServletRequest, org.apache.jackrabbit.webdav.DavServletResponse) - */ - public DavResource createResource(DavResourceLocator locator, - DavServletRequest request, - DavServletResponse response) throws DavException { - JcrDavSession.checkImplementation(request.getDavSession()); - JcrDavSession session = (JcrDavSession)request.getDavSession(); - - DavResource resource; - String type = request.getParameter("type"); - - if (locator.isRootLocation()) { - // root - resource = new RootCollection(locator, session, this); - } else if ("journal".equals(type) && locator.getResourcePath().equals(locator.getWorkspacePath())) { - // feed/event journal resource - try { - EventJournal ej = session.getRepositorySession().getWorkspace().getObservationManager() - .getEventJournal(); - if (ej == null) { - throw new DavException(HttpServletResponse.SC_NOT_IMPLEMENTED, "event journal not supported"); - } - resource = new EventJournalResourceImpl(ej, locator, session, request, this); - } catch (AccessDeniedException ex) { - // EventJournal only allowed for admin? - throw new DavException(HttpServletResponse.SC_UNAUTHORIZED, ex); - } catch (RepositoryException ex) { - throw new DavException(HttpServletResponse.SC_BAD_REQUEST, ex); - } - } else if (locator.getResourcePath().equals(locator.getWorkspacePath())) { - // workspace resource - resource = new WorkspaceResourceImpl(locator, session, this); - } else { - // resource corresponds to a repository item - try { - resource = createResourceForItem(locator, session); - - Item item = getItem(session, locator); - boolean versionable = item.isNode() && ((Node) item).isNodeType(JcrConstants.MIX_VERSIONABLE); - - /* if the created resource is version-controlled and the request - contains a Label header, the corresponding Version must be used - instead.*/ - if (request instanceof DeltaVServletRequest && versionable) { - String labelHeader = ((DeltaVServletRequest)request).getLabel(); - if (labelHeader != null && DavMethods.isMethodAffectedByLabel(request) && isVersionControlled(resource)) { - Version v = ((Node)item).getVersionHistory().getVersionByLabel(labelHeader); - DavResourceLocator vloc = locator.getFactory().createResourceLocator(locator.getPrefix(), locator.getWorkspacePath(), v.getPath(), false); - resource = new VersionItemCollection(vloc, session, this, v); - } - } - } catch (PathNotFoundException e) { - /* item does not exist yet: create the default resources - Note: MKCOL request forces a collection-resource even if there already - exists a repository-property with the given path. the MKCOL will - in that particular case fail with a 405 (method not allowed).*/ - if (DavMethods.getMethodCode(request.getMethod()) == DavMethods.DAV_MKCOL) { - resource = new VersionControlledItemCollection(locator, session, this, null); - } else { - resource = new DefaultItemResource(locator, session, this, null); - } - } catch (RepositoryException e) { - log.error("Failed to build resource from item '"+ locator.getRepositoryPath() + "'"); - throw new JcrDavException(e); - } - } - - if (request instanceof TransactionDavServletRequest && resource instanceof TransactionResource) { - ((TransactionResource)resource).init(txMgr, ((TransactionDavServletRequest)request).getTransactionId()); - } - if (resource instanceof ObservationResource) { - ((ObservationResource)resource).init(subsMgr); - } - return resource; - } - - /** - * Create a new DavResource from the given locator and session. - * - * @param locator - * @param session - * @return DavResource representing either a repository item or the {@link RootCollection}. - * @throws DavException if the given locator does neither refer to a repository item - * nor does represent the {@link org.apache.jackrabbit.webdav.DavResourceLocator#isRootLocation() - * root location}. - */ - public DavResource createResource(DavResourceLocator locator, DavSession session) throws DavException { - JcrDavSession.checkImplementation(session); - JcrDavSession sessionImpl = (JcrDavSession)session; - - DavResource resource; - if (locator.isRootLocation()) { - resource = new RootCollection(locator, sessionImpl, this); - } else if (locator.getResourcePath().equals(locator.getWorkspacePath())) { - resource = new WorkspaceResourceImpl(locator, sessionImpl, this); - } else { - try { - resource = createResourceForItem(locator, sessionImpl); - } catch (RepositoryException e) { - log.debug("Creating resource for non-existing repository item: " + locator.getRepositoryPath()); - // todo: is this correct? - resource = new VersionControlledItemCollection(locator, sessionImpl, this, null); - } - } - - // todo: currently transactionId is set manually after creation > to be improved. - resource.addLockManager(txMgr); - if (resource instanceof ObservationResource) { - ((ObservationResource)resource).init(subsMgr); - } - return resource; - } - - /** - * Tries to retrieve the repository item defined by the locator's resource - * path and build the corresponding WebDAV resource. The following distinction - * is made between items: Version nodes, VersionHistory nodes, root node, - * unspecified nodes and finally property items. - * - * @param locator - * @param sessionImpl - * @return DavResource representing a repository item. - * @throws RepositoryException if {@link javax.jcr.Session#getItem(String)} fails. - */ - private DavResource createResourceForItem(DavResourceLocator locator, JcrDavSession sessionImpl) throws RepositoryException, DavException { - DavResource resource; - Item item = getItem(sessionImpl, locator); - if (item.isNode()) { - // create special resources for Version and VersionHistory - if (item instanceof Version) { - resource = new VersionItemCollection(locator, sessionImpl, this, item); - } else if (item instanceof VersionHistory) { - resource = new VersionHistoryItemCollection(locator, sessionImpl, this, item); - } else{ - resource = new VersionControlledItemCollection(locator, sessionImpl, this, item); - } - } else { - resource = new DefaultItemResource(locator, sessionImpl, this, item); - } - return resource; - } - - protected Item getItem(JcrDavSession sessionImpl, DavResourceLocator locator) - throws PathNotFoundException, RepositoryException { - return sessionImpl.getRepositorySession().getItem(locator.getRepositoryPath()); - } - - /** - * Returns true, if the specified resource is a {@link VersionControlledResource} - * and has a version history. - * - * @param resource - * @return true if the specified resource is version-controlled. - */ - private boolean isVersionControlled(DavResource resource) { - boolean vc = false; - if (resource instanceof VersionControlledResource) { - try { - vc = ((VersionControlledResource)resource).getVersionHistory() != null; - } catch (DavException e) { - log.debug("Resource '" + resource.getHref() + "' is not version-controlled."); - } - } - return vc; - } -} Property changes on: jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/DavResourceFactoryImpl.java ___________________________________________________________________ Deleted: svn Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/DefaultItemCollection.java =================================================================== --- jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/DefaultItemCollection.java (revision 1907912) +++ jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/DefaultItemCollection.java (nonexistent) @@ -1,1168 +0,0 @@ -/* - * 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.webdav.jcr; - -import java.io.BufferedReader; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.io.OutputStream; -import java.util.ArrayList; -import java.util.Date; -import java.util.List; -import java.util.Set; - -import javax.jcr.AccessDeniedException; -import javax.jcr.ImportUUIDBehavior; -import javax.jcr.Item; -import javax.jcr.ItemExistsException; -import javax.jcr.ItemNotFoundException; -import javax.jcr.Node; -import javax.jcr.NodeIterator; -import javax.jcr.PathNotFoundException; -import javax.jcr.Property; -import javax.jcr.PropertyIterator; -import javax.jcr.PropertyType; -import javax.jcr.RepositoryException; -import javax.jcr.Session; -import javax.jcr.UnsupportedRepositoryOperationException; -import javax.jcr.version.VersionIterator; -import javax.jcr.version.Version; -import javax.jcr.lock.Lock; -import javax.jcr.nodetype.NodeType; -import javax.xml.parsers.ParserConfigurationException; - -import org.apache.jackrabbit.JcrConstants; -import org.apache.jackrabbit.commons.webdav.JcrValueType; -import org.apache.jackrabbit.server.io.IOUtil; -import org.apache.jackrabbit.util.Text; -import org.apache.jackrabbit.webdav.DavCompliance; -import org.apache.jackrabbit.webdav.DavException; -import org.apache.jackrabbit.webdav.DavResource; -import org.apache.jackrabbit.webdav.DavResourceFactory; -import org.apache.jackrabbit.webdav.DavResourceIterator; -import org.apache.jackrabbit.webdav.DavResourceIteratorImpl; -import org.apache.jackrabbit.webdav.DavResourceLocator; -import org.apache.jackrabbit.webdav.DavServletResponse; -import org.apache.jackrabbit.webdav.MultiStatusResponse; -import org.apache.jackrabbit.webdav.jcr.property.JcrDavPropertyNameSet; -import org.apache.jackrabbit.webdav.jcr.security.JcrUserPrivilegesProperty; -import org.apache.jackrabbit.webdav.jcr.security.JcrSupportedPrivilegesProperty; -import org.apache.jackrabbit.webdav.jcr.security.SecurityUtils; -import org.apache.jackrabbit.webdav.security.SecurityConstants; -import org.apache.jackrabbit.webdav.util.HttpDateFormat; -import org.apache.jackrabbit.webdav.io.InputContext; -import org.apache.jackrabbit.webdav.io.OutputContext; -import org.apache.jackrabbit.webdav.jcr.lock.JcrActiveLock; -import org.apache.jackrabbit.webdav.jcr.lock.SessionScopedLockEntry; -import org.apache.jackrabbit.webdav.jcr.nodetype.NodeTypeProperty; -import org.apache.jackrabbit.webdav.jcr.property.ValuesProperty; -import org.apache.jackrabbit.webdav.jcr.version.report.ExportViewReport; -import org.apache.jackrabbit.webdav.jcr.version.report.LocateCorrespondingNodeReport; -import org.apache.jackrabbit.webdav.lock.ActiveLock; -import org.apache.jackrabbit.webdav.lock.LockInfo; -import org.apache.jackrabbit.webdav.lock.Scope; -import org.apache.jackrabbit.webdav.lock.Type; -import org.apache.jackrabbit.webdav.ordering.OrderPatch; -import org.apache.jackrabbit.webdav.ordering.OrderingConstants; -import org.apache.jackrabbit.webdav.ordering.OrderingResource; -import org.apache.jackrabbit.webdav.ordering.OrderingType; -import org.apache.jackrabbit.webdav.ordering.Position; -import org.apache.jackrabbit.webdav.property.DavProperty; -import org.apache.jackrabbit.webdav.property.DavPropertyName; -import org.apache.jackrabbit.webdav.property.DefaultDavProperty; -import org.apache.jackrabbit.webdav.property.HrefProperty; -import org.apache.jackrabbit.webdav.property.PropEntry; -import org.apache.jackrabbit.webdav.xml.DomUtil; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.w3c.dom.Document; -import org.xml.sax.SAXException; - -/** - * DefaultItemCollection represents a JCR node item. - */ -public class DefaultItemCollection extends AbstractItemResource - implements OrderingResource { - - private static Logger log = LoggerFactory.getLogger(DefaultItemCollection.class); - private static final String TMP_PREFIX = "_tmp_"; - - /** - * Create a new DefaultItemCollection. - * - * @param locator - * @param session - * @param factory - * @param item - */ - protected DefaultItemCollection(DavResourceLocator locator, - JcrDavSession session, - DavResourceFactory factory, Item item) { - super(locator, session, factory, item); - if (exists() && !(item instanceof Node)) { - throw new IllegalArgumentException("A collection resource can not be constructed from a Property item."); - } - } - - //----------------------------------------------< DavResource interface >--- - /** - * @see org.apache.jackrabbit.webdav.DavResource#getComplianceClass() - */ - @Override - public String getComplianceClass() { - String cc = super.getComplianceClass(); - if (isOrderable()) { - return DavCompliance.concatComplianceClasses( - new String[] { - cc, - DavCompliance.ORDERED_COLLECTIONS, - } - ); - } else { - return cc; - } - } - - @Override - public long getModificationTime() { - // retrieve mod-time from jcr:lastmodified property if existing - if (exists()) { - try { - if (((Node)item).hasProperty(JcrConstants.JCR_LASTMODIFIED)) { - return ((Node)item).getProperty(JcrConstants.JCR_LASTMODIFIED).getLong(); - } - } catch (RepositoryException e) { - log.warn("Error while accessing jcr:lastModified property"); - } - } - // fallback: return 'now' - return new Date().getTime(); - } - - /** - * @see org.apache.jackrabbit.webdav.DavResource#getSupportedMethods() - */ - @Override - public String getSupportedMethods() { - String ms = super.getSupportedMethods(); - if (isOrderable()) { - StringBuffer sb = new StringBuffer(ms); - sb.append(", ").append(OrderingResource.METHODS); - return sb.toString(); - } else { - return ms; - } - } - - /** - * Always returns true - * - * @return true - * @see org.apache.jackrabbit.webdav.DavResource#isCollection() - */ - @Override - public boolean isCollection() { - return true; - } - - /** - * If this resource represents an existing Node the system - * view is spooled as resource content. - * - * @param outputContext - * @throws IOException - * @see Session#exportSystemView(String, OutputStream, boolean, boolean) - */ - @Override - public void spool(OutputContext outputContext) throws IOException { - // spool properties - super.spool(outputContext); - // spool data - try { - OutputStream out = outputContext.getOutputStream(); - if (out != null && exists()) { - getRepositorySession().exportSystemView(item.getPath(), out, false, true); - } - } catch (PathNotFoundException e) { - log.error("Error while spooling resource content: " + e.getMessage()); - } catch (RepositoryException e) { - log.error("Error while spooling resource content: " + e.getMessage()); - } - } - - @Override - public DavProperty getProperty(DavPropertyName name) { - DavProperty prop = super.getProperty(name); - - if (prop == null && exists()) { - Node n = (Node) item; - - // add node-specific resource properties - try { - if (JCR_INDEX.equals(name)) { - prop = new DefaultDavProperty(JCR_INDEX, n.getIndex(), true); - } else if (JCR_REFERENCES.equals(name)) { - prop = getHrefProperty(JCR_REFERENCES, n.getReferences(), true); - } else if (JCR_WEAK_REFERENCES.equals(name)) { - prop = getHrefProperty(JCR_WEAK_REFERENCES, n.getWeakReferences(), true); - } else if (JCR_UUID.equals(name)) { - if (isReferenceable()) { - prop = new DefaultDavProperty(JCR_UUID, n.getUUID(), true); - } - } else if (JCR_PRIMARYITEM.equals(name)) { - if (hasPrimaryItem()) { - Item primaryItem = n.getPrimaryItem(); - prop = getHrefProperty(JCR_PRIMARYITEM, new Item[] {primaryItem}, true); - } - } else if (OrderingConstants.ORDERING_TYPE.equals(name) && isOrderable()) { - // property defined by RFC 3648: this resource always has custom ordering! - prop = new OrderingType(OrderingConstants.ORDERING_TYPE_CUSTOM); - } else if (SecurityConstants.SUPPORTED_PRIVILEGE_SET.equals(name)) { - prop = new JcrSupportedPrivilegesProperty(getRepositorySession(), n.getPath()).asDavProperty(); - } else if (SecurityConstants.CURRENT_USER_PRIVILEGE_SET.equals(name)) { - prop = new JcrUserPrivilegesProperty(getRepositorySession(), n.getPath()).asDavProperty(); - } - } catch (RepositoryException e) { - log.error("Failed to retrieve node-specific property: " + e); - } - } - - return prop; - } - - /** - * This implementation of the DavResource does only allow - * to set the mixinnodetypes property. Please note that the existing list of - * mixin nodetypes will be completely replaced.
- * In order to add / set any other repository property on the underlying - * {@link javax.jcr.Node} use addMember(DavResource) or - * addMember(DavResource, InputStream) or modify the value - * of the corresponding resource. - * - * @param property - * @throws org.apache.jackrabbit.webdav.DavException - * @see org.apache.jackrabbit.webdav.DavResource#setProperty(org.apache.jackrabbit.webdav.property.DavProperty) - * @see #JCR_MIXINNODETYPES - */ - @Override - public void setProperty(DavProperty property) throws DavException { - internalSetProperty(property); - complete(); - } - - /** - * Internal method used to set or add the given property - * - * @param property - * @throws DavException - * @see #setProperty(DavProperty) - */ - private void internalSetProperty(DavProperty property) throws DavException { - if (!exists()) { - throw new DavException(DavServletResponse.SC_NOT_FOUND); - } - DavPropertyName propName = property.getName(); - if (JCR_MIXINNODETYPES.equals(propName)) { - Node n = (Node) item; - try { - NodeTypeProperty mix = new NodeTypeProperty(property); - Set mixins = mix.getNodeTypeNames(); - - for (NodeType existingMixin : n.getMixinNodeTypes()) { - String name = existingMixin.getName(); - if (mixins.contains(name)){ - // do not add existing mixins - mixins.remove(name); - } else { - // remove mixin that are not contained in the new list - n.removeMixin(name); - } - } - - // add the remaining mixing types that are not yet set - for (String mixin : mixins) { - n.addMixin(mixin); - } - } catch (RepositoryException e) { - throw new JcrDavException(e); - } - } else if (JCR_PRIMARYNODETYPE.equals(propName)) { - Node n = (Node) item; - try { - NodeTypeProperty ntProp = new NodeTypeProperty(property); - Set names = ntProp.getNodeTypeNames(); - if (names.size() == 1) { - String ntName = names.iterator().next(); - n.setPrimaryType(ntName); - } else { - // only a single node type can be primary node type. - throw new DavException(DavServletResponse.SC_BAD_REQUEST); - } - } catch (RepositoryException e) { - throw new JcrDavException(e); - } - } else { - // all props except for mixin node types and primaryType are read-only - throw new DavException(DavServletResponse.SC_CONFLICT); - } - } - - /** - * This implementation of the DavResource does only allow - * to remove the mixinnodetypes property. - * - * @param propertyName - * @throws org.apache.jackrabbit.webdav.DavException - * @see org.apache.jackrabbit.webdav.DavResource#removeProperty(org.apache.jackrabbit.webdav.property.DavPropertyName) - * @see #JCR_MIXINNODETYPES - */ - @Override - public void removeProperty(DavPropertyName propertyName) throws DavException { - internalRemoveProperty(propertyName); - complete(); - } - - /** - * Internal method used to remove the property with the given name. - * - * @param propertyName - * @throws DavException - * @see #removeProperty(DavPropertyName) - */ - private void internalRemoveProperty(DavPropertyName propertyName) throws DavException { - if (!exists()) { - throw new DavException(DavServletResponse.SC_NOT_FOUND); - } - if (JCR_MIXINNODETYPES.equals(propertyName)) { - // remove all mixin nodetypes - try { - Node n = (Node)item; - for (NodeType mixin : n.getMixinNodeTypes()) { - n.removeMixin(mixin.getName()); - } - } catch (RepositoryException e) { - // NoSuchNodeTypeException, ConstraintViolationException should never occur... - throw new JcrDavException(e); - } - } else { - // all props except for mixin node types are read-only - throw new DavException(DavServletResponse.SC_CONFLICT); - } - } - - /** - * Loops over the given Lists and alters the properties accordingly. - * Changes are persisted at the end according to the rules defined with - * the {@link AbstractItemResource#complete()} method.

- * Please note: since there is only a single property - * ({@link ItemResourceConstants#JCR_MIXINNODETYPES} - * that can be set or removed with PROPPATCH, this method either succeeds - * or throws an exception, even if this violates RFC 2518. Thus no property - * specific multistatus will be created in case of an error. - * - * @param changeList - * @return - * @throws DavException - */ - @Override - public MultiStatusResponse alterProperties(List changeList) throws DavException { - for (PropEntry propEntry : changeList) { - if (propEntry instanceof DavPropertyName) { - // use the internal remove method in order to prevent premature 'save' - DavPropertyName propName = (DavPropertyName) propEntry; - internalRemoveProperty(propName); - } else if (propEntry instanceof DavProperty) { - // use the internal set method in order to prevent premature 'save' - DavProperty prop = (DavProperty) propEntry; - internalSetProperty(prop); - } else { - throw new IllegalArgumentException("unknown object in change list: " + propEntry.getClass().getName()); - } - } - // TODO: missing undo of successful set/remove if subsequent operation fails - // NOTE, that this is relevant with transactions only. - - // success: save all changes together if no error occurred - complete(); - return new MultiStatusResponse(getHref(), DavServletResponse.SC_OK); - } - - /** - * If the specified resource represents a collection, a new node is {@link Node#addNode(String) - * added} to the item represented by this resource. If an input stream is specified - * together with a collection resource {@link Session#importXML(String, java.io.InputStream, int)} - * is called instead and this resource path is used as parentAbsPath argument. - *

- * However, if the specified resource is not of resource type collection a - * new {@link Property} is set or an existing one is changed by modifying its - * value.
- * NOTE: with the current implementation it is not possible to create or - * modify multivalue JCR properties.
- * NOTE: if the JCR property represented by the specified resource has an - * {@link PropertyType#UNDEFINED undefined} resource type, its value will be - * changed/set to type {@link PropertyType#BINARY binary}. - * - * @param resource - * @param inputContext - * @throws org.apache.jackrabbit.webdav.DavException - * @see org.apache.jackrabbit.webdav.DavResource#addMember(org.apache.jackrabbit.webdav.DavResource, InputContext) - * @see Node#addNode(String) - * @see Node#setProperty(String, java.io.InputStream) - */ - @Override - public void addMember(DavResource resource, InputContext inputContext) - throws DavException { - - /* RFC 2815 states that all 'parents' must exist in order all addition of members */ - if (!exists()) { - throw new DavException(DavServletResponse.SC_CONFLICT); - } - - File tmpFile = null; - try { - Node n = (Node) item; - InputStream in = (inputContext != null) ? inputContext.getInputStream() : null; - String itemPath = getLocator().getRepositoryPath(); - String memberName = getItemName(resource.getLocator().getRepositoryPath()); - if (resource.isCollection()) { - if (in == null) { - // MKCOL without a request body, try if a default-primary-type is defined. - n.addNode(memberName); - } else { - // MKCOL, which is not allowed for existing resources - int uuidBehavior = ImportUUIDBehavior.IMPORT_UUID_CREATE_NEW; - String str = inputContext.getProperty(IMPORT_UUID_BEHAVIOR); - if (str != null) { - try { - uuidBehavior = Integer.parseInt(str); - } catch (NumberFormatException e) { - throw new DavException(DavServletResponse.SC_BAD_REQUEST); - } - } - if (getTransactionId() == null) { - // if not part of a transaction directly import on workspace - // since changes would be explicitly saved in the - // complete-call. - getRepositorySession().getWorkspace().importXML(itemPath, in, uuidBehavior); - } else { - // changes will not be persisted unless the tx is completed. - getRepositorySession().importXML(itemPath, in, uuidBehavior); - } - } - } else { - if (in == null) { - // PUT: not possible without request body - throw new DavException(DavServletResponse.SC_BAD_REQUEST, "Cannot create a new non-collection resource without request body."); - } - // PUT : create new or overwrite existing property. - String ct = inputContext.getContentType(); - int type = JcrValueType.typeFromContentType(ct); - if (type != PropertyType.UNDEFINED) { - // no need to create value/values property. instead - // prop-value can be retrieved directly: - int pos = ct.indexOf(';'); - String charSet = (pos > -1) ? ct.substring(pos) : "UTF-8"; - if (type == PropertyType.BINARY) { - n.setProperty(memberName, inputContext.getInputStream()); - } else { - BufferedReader r = new BufferedReader(new InputStreamReader(inputContext.getInputStream(), charSet)); - String line; - StringBuffer value = new StringBuffer(); - while ((line = r.readLine()) != null) { - value.append(line); - } - n.setProperty(memberName, value.toString(), type); - } - } else { - // try to parse the request body into a 'values' property. - tmpFile = File.createTempFile(TMP_PREFIX + Text.escape(memberName), null, null); - FileOutputStream out = new FileOutputStream(tmpFile); - IOUtil.spool(in, out); - out.close(); - // try to parse the request body into a 'values' property. - ValuesProperty vp = buildValuesProperty(new FileInputStream(tmpFile)); - if (vp != null) { - if (JCR_VALUE.equals(vp.getName())) { - n.setProperty(memberName, vp.getJcrValue()); - } else { - n.setProperty(memberName, vp.getJcrValues()); - } - } else { - // request body cannot be parsed into a 'values' property. - // fallback: try to import as single value from stream. - n.setProperty(memberName, new FileInputStream(tmpFile)); - } - } - } - if (resource.exists() && resource instanceof AbstractItemResource) { - // PUT may modify value of existing jcr property. thus, this - // node is not modified by the 'addMember' call. - ((AbstractItemResource)resource).complete(); - } else { - complete(); - } - } catch (ItemExistsException e) { - // according to RFC 2518: MKCOL only possible on non-existing/deleted resource - throw new JcrDavException(e, DavServletResponse.SC_METHOD_NOT_ALLOWED); - } catch (RepositoryException e) { - throw new JcrDavException(e); - } catch (IOException e) { - throw new DavException(DavServletResponse.SC_UNPROCESSABLE_ENTITY, e.getMessage()); - } finally { - if (tmpFile != null) { - tmpFile.delete(); - } - } - } - - /** - * @see org.apache.jackrabbit.webdav.DavResource#getMembers() - */ - @Override - public DavResourceIterator getMembers() { - ArrayList memberList = new ArrayList(); - if (exists()) { - try { - Node n = (Node)item; - // add all node members - NodeIterator it = n.getNodes(); - while (it.hasNext()) { - Node node = it.nextNode(); - DavResourceLocator loc = getLocatorFromItem(node); - memberList.add(createResourceFromLocator(loc)); - } - // add all property members - PropertyIterator propIt = n.getProperties(); - while (propIt.hasNext()) { - Property prop = propIt.nextProperty(); - DavResourceLocator loc = getLocatorFromItem(prop); - memberList.add(createResourceFromLocator(loc)); - } - } catch (RepositoryException e) { - // ignore - log.error(e.getMessage()); - } catch (DavException e) { - // should never occur. - log.error(e.getMessage()); - } - } - return new DavResourceIteratorImpl(memberList); - } - - /** - * Removes the repository item represented by the specified member - * resource. - * - * @throws DavException if this resource does not exist or if an error occurs - * while deleting the underlying item. - * @see DavResource#removeMember(DavResource) - * @see javax.jcr.Item#remove() - */ - @Override - public void removeMember(DavResource member) throws DavException { - Session session = getRepositorySession(); - try { - String itemPath = member.getLocator().getRepositoryPath(); - if (!exists() || !session.itemExists(itemPath)) { - throw new DavException(DavServletResponse.SC_NOT_FOUND); - } - if (!getResourcePath().equals(Text.getRelativeParent(member.getResourcePath(), 1))) { - throw new DavException(DavServletResponse.SC_CONFLICT, member.getResourcePath() + "is not member of this resource (" + getResourcePath() + ")"); - } - getRepositorySession().getItem(itemPath).remove(); - complete(); - } catch (RepositoryException e) { - log.error("Unexpected error: " + e.getMessage()); - throw new JcrDavException(e); - } - } - - /** - * @param type - * @param scope - * @return true if a lock with the specified type and scope is present on - * this resource, false otherwise. If retrieving the corresponding information - * fails, false is returned. - * @see org.apache.jackrabbit.webdav.DavResource#hasLock(org.apache.jackrabbit.webdav.lock.Type, org.apache.jackrabbit.webdav.lock.Scope) - */ - @Override - public boolean hasLock(Type type, Scope scope) { - if (isLockable(type, scope)) { - if (Type.WRITE.equals(type)) { - try { - return ((Node) item).isLocked(); - } catch (RepositoryException e) { - log.error(e.getMessage()); - } - } else { - return super.hasLock(type, scope); - } - } - return false; - } - - /** - * Retrieve the lock with the specified type and scope. - * - * @param type - * @param scope - * @return lock with the specified type and scope is present on this - * resource or null. NOTE: If retrieving the write lock present - * on the underlying repository item fails, null is return. - * @see org.apache.jackrabbit.webdav.DavResource#getLock(org.apache.jackrabbit.webdav.lock.Type, org.apache.jackrabbit.webdav.lock.Scope) - * @see javax.jcr.Node#getLock() for the write locks. - */ - @Override - public ActiveLock getLock(Type type, Scope scope) { - ActiveLock lock = null; - if (Type.WRITE.equals(type)) { - try { - if (!exists()) { - log.warn("Unable to retrieve lock: no item found at '" + getResourcePath() + "'"); - } else if (((Node) item).isLocked()) { - Lock jcrLock = ((Node) item).getLock(); - lock = new JcrActiveLock(jcrLock); - DavResourceLocator locator = super.getLocator(); - String lockroot = locator - .getFactory() - .createResourceLocator(locator.getPrefix(), locator.getWorkspacePath(), jcrLock.getNode().getPath(), - false).getHref(false); - lock.setLockroot(lockroot); - } - } catch (AccessDeniedException e) { - log.error("Error while accessing resource lock: "+e.getMessage()); - } catch (UnsupportedRepositoryOperationException e) { - log.error("Error while accessing resource lock: "+e.getMessage()); - } catch (RepositoryException e) { - log.error("Error while accessing resource lock: "+e.getMessage()); - } - } else { - lock = super.getLock(type, scope); - } - return lock; - } - - /** - * Creates a lock on this resource by locking the underlying - * {@link javax.jcr.Node node}. Except for the {@link org.apache.jackrabbit.webdav.lock.LockInfo#isDeep()} } - * all information included in the LockInfo object is ignored. - * Lock timeout is defined by JCR implementation. - * - * @param reqLockInfo - * @return lock object representing the lock created on this resource. - * @throws org.apache.jackrabbit.webdav.DavException - * @see org.apache.jackrabbit.webdav.DavResource#lock(org.apache.jackrabbit.webdav.lock.LockInfo) - * @see Node#lock(boolean, boolean) - */ - @Override - public ActiveLock lock(LockInfo reqLockInfo) throws DavException { - - if (!isLockable(reqLockInfo.getType(), reqLockInfo.getScope())) { - throw new DavException(DavServletResponse.SC_PRECONDITION_FAILED); - } - - if (Type.WRITE.equals(reqLockInfo.getType())) { - if (!exists()) { - log.warn("Cannot create a write lock for non-existing JCR node (" + getResourcePath() + ")"); - throw new DavException(DavServletResponse.SC_NOT_FOUND); - } - try { - boolean sessionScoped = EXCLUSIVE_SESSION.equals(reqLockInfo.getScope()); - long timeout = reqLockInfo.getTimeout(); - if (timeout == LockInfo.INFINITE_TIMEOUT) { - timeout = Long.MAX_VALUE; - } else { - timeout = timeout/1000; - } - javax.jcr.lock.LockManager lockMgr = getRepositorySession().getWorkspace().getLockManager(); - Lock jcrLock = lockMgr.lock((item).getPath(), reqLockInfo.isDeep(), - sessionScoped, timeout, reqLockInfo.getOwner()); - ActiveLock lock = new JcrActiveLock(jcrLock); - // add reference to DAVSession for this lock - getSession().addReference(lock.getToken()); - return lock; - } catch (RepositoryException e) { - // UnsupportedRepositoryOperationException should not occur... - throw new JcrDavException(e); - } - } else { - return super.lock(reqLockInfo); - } - } - - /** - * Refreshes the lock on this resource. With this implementation the - * {@link javax.jcr.lock lock} present on the underlying {@link javax.jcr.Node node} - * is refreshed. The timeout indicated by the LockInfo - * object is ignored. - * - * @param reqLockInfo LockInfo as build from the request. - * @param lockToken - * @return the updated lock info object. - * @throws org.apache.jackrabbit.webdav.DavException in case the lock could not be refreshed. - * @see org.apache.jackrabbit.webdav.DavResource#refreshLock(org.apache.jackrabbit.webdav.lock.LockInfo, String) - * @see javax.jcr.lock.Lock#refresh() - */ - @Override - public ActiveLock refreshLock(LockInfo reqLockInfo, String lockToken) - throws DavException { - - if (lockToken == null) { - throw new DavException(DavServletResponse.SC_PRECONDITION_FAILED); - } - - ActiveLock lock = getLock(reqLockInfo.getType(), reqLockInfo.getScope()); - if (lock == null) { - throw new DavException(DavServletResponse.SC_PRECONDITION_FAILED, "No lock with the given scope/type present on this resource."); - } - - if (Type.WRITE.equals(lock.getType())) { - try { - Lock jcrLock = ((Node) item).getLock(); - jcrLock.refresh(); - return new JcrActiveLock(jcrLock); - } catch (RepositoryException e) { - /* - NOTE: LockException is only thrown by Lock.refresh() - the lock exception thrown by Node.getLock() was circumvented - by the init test if there is a lock applied... - NOTE: UnsupportedRepositoryOperationException should not occur - */ - throw new JcrDavException(e); - } - } else { - return super.refreshLock(reqLockInfo, lockToken); - } - } - - /** - * Remove the write lock from this resource by unlocking the underlying - * {@link javax.jcr.Node node}. - * - * @param lockToken - * @throws org.apache.jackrabbit.webdav.DavException - * @see org.apache.jackrabbit.webdav.DavResource#unlock(String) - * @see javax.jcr.Node#unlock() - */ - @Override - public void unlock(String lockToken) throws DavException { - ActiveLock lock = getWriteLock(); - if (lock != null && lockToken.equals(lock.getToken())) { - try { - ((Node) item).unlock(); - getSession().removeReference(lock.getToken()); - } catch (RepositoryException e) { - throw new JcrDavException(e); - } - } else { - super.unlock(lockToken); - } - } - - /** - * Returns the write lock present on this resource or null if - * no write lock exists. NOTE: that the scope of a write lock may either - * be {@link org.apache.jackrabbit.webdav.lock.Scope#EXCLUSIVE} or - * {@link ItemResourceConstants#EXCLUSIVE_SESSION}. - * - * @return write lock or null - * @throws DavException if this resource does not represent a repository item. - */ - private ActiveLock getWriteLock() throws DavException { - if (!exists()) { - throw new DavException(DavServletResponse.SC_NOT_FOUND, "Unable to retrieve write lock for non existing repository item (" + getResourcePath() + ")"); - } - ActiveLock writeLock = getLock(Type.WRITE, Scope.EXCLUSIVE); - if (writeLock == null) { - writeLock = getLock(Type.WRITE, EXCLUSIVE_SESSION); - } - return writeLock; - } - - //-----------------------------------------< OrderingResource interface >--- - /** - * Returns true if this resource exists and the nodetype defining the - * underlying repository node allow to reorder this nodes children. - * - * @return true if {@link DefaultItemCollection#orderMembers(OrderPatch)} - * can be called on this resource. - * @see org.apache.jackrabbit.webdav.ordering.OrderingResource#isOrderable() - * @see javax.jcr.nodetype.NodeType#hasOrderableChildNodes() - */ - @Override - public boolean isOrderable() { - boolean orderable = false; - if (exists()) { - try { - orderable = ((Node) item).getPrimaryNodeType().hasOrderableChildNodes(); - } catch (RepositoryException e) { - log.warn(e.getMessage()); - } - } - return orderable; - } - - /** - * Reorder the child nodes of the repository item represented by this - * resource as indicated by the specified {@link OrderPatch} object. - * - * @param orderPatch - * @throws org.apache.jackrabbit.webdav.DavException - * @see org.apache.jackrabbit.webdav.ordering.OrderingResource#orderMembers(org.apache.jackrabbit.webdav.ordering.OrderPatch) - * @see Node#orderBefore(String, String) - */ - @Override - public void orderMembers(OrderPatch orderPatch) throws DavException { - if (!isOrderable()) { - throw new DavException(DavServletResponse.SC_METHOD_NOT_ALLOWED); - } - // only custom ordering is allowed - if (!OrderingConstants.ORDERING_TYPE_CUSTOM.equalsIgnoreCase(orderPatch.getOrderingType())) { - throw new DavException(DavServletResponse.SC_UNPROCESSABLE_ENTITY, "Only DAV:custom ordering type supported."); - } - - Node n = (Node)item; - try { - for (OrderPatch.Member instruction : orderPatch.getOrderInstructions()) { - String srcRelPath = Text.unescape(instruction.getMemberHandle()); - Position pos = instruction.getPosition(); - String destRelPath = getRelDestinationPath(pos, n.getNodes()); - // preform the reordering - n.orderBefore(srcRelPath, destRelPath); - } - complete(); - } catch (RepositoryException e) { - // UnsupportedRepositoryException should not occur - throw new JcrDavException(e); - } - } - - /** - * Retrieve the relative path of the child node that acts as destination. - * A null destination path is used to place the child node indicated - * by the source path at the end of the list. - * - * @param position - * @param childNodes - * @return the relative path of the child node used as destination or null - * if the source node should be placed at the last position. - * @throws javax.jcr.RepositoryException - */ - private String getRelDestinationPath(Position position, NodeIterator childNodes) - throws RepositoryException { - - String destRelPath = null; - if (OrderingConstants.XML_FIRST.equals(position.getType())) { - if (childNodes.hasNext()) { - Node firstChild = childNodes.nextNode(); - // use last segment of node-path instead of name. - destRelPath = Text.getName(firstChild.getPath()); - } - // no child nodes available > reordering to 'first' position fails. - if (destRelPath == null) { - throw new ItemNotFoundException("No 'first' item found for reordering."); - } - } else if (OrderingConstants.XML_AFTER.equals(position.getType())) { - String afterRelPath = position.getSegment(); - boolean found = false; - // jcr only knows order-before > retrieve the node that follows the - // one indicated by the 'afterRelPath'. - while (childNodes.hasNext() && destRelPath == null) { - // compare to last segment of node-path instead of name. - String childRelPath = Text.getName(childNodes.nextNode().getPath()); - if (found) { - destRelPath = childRelPath; - } else { - found = afterRelPath.equals(childRelPath); - } - } - } else { - // before or last. in the latter case the segment is 'null' - destRelPath = position.getSegment(); - } - if (destRelPath != null) { - destRelPath = Text.unescape(destRelPath); - } - return destRelPath; - } - - //-------------------------------------------------------------------------- - /** - * Extend the general {@link AbstractResource#supportedLock} field by - * lock entries specific for this resource: write locks (exclusive or - * exclusive session-scoped) in case the underlying node has the node - * type mix:lockable. - * - * @see org.apache.jackrabbit.JcrConstants#MIX_LOCKABLE - */ - @Override - protected void initLockSupport() { - super.initLockSupport(); - // add exclusive write lock if allowed for the given node - try { - if (exists() && ((Node)item).isNodeType(JcrConstants.MIX_LOCKABLE)) { - supportedLock.addEntry(Type.WRITE, Scope.EXCLUSIVE); - supportedLock.addEntry(new SessionScopedLockEntry()); - } - } catch (RepositoryException e) { - log.warn(e.getMessage()); - } - } - - /** - * Defines the additional reports supported by this resource (reports - * specific for resources representing a repository {@link Node node}): - *

    - *
  • {@link ExportViewReport export view report}
  • - *
  • {@link LocateCorrespondingNodeReport locate corresponding node report}
  • - *
- * - * @see org.apache.jackrabbit.webdav.version.report.SupportedReportSetProperty - */ - @Override - protected void initSupportedReports() { - super.initSupportedReports(); - if (exists()) { - supportedReports.addReportType(ExportViewReport.EXPORTVIEW_REPORT); - supportedReports.addReportType(LocateCorrespondingNodeReport.LOCATE_CORRESPONDING_NODE_REPORT); - } - } - - @Override - protected void initPropertyNames() { - super.initPropertyNames(); - - if (exists()) { - names.addAll(JcrDavPropertyNameSet.NODE_SET); - - if (isReferenceable()) { - names.add(JCR_UUID); - } - if (hasPrimaryItem()) { - names.add(JCR_PRIMARYITEM); - } - if (isOrderable()) { - names.add(OrderingConstants.ORDERING_TYPE); - } - if (SecurityUtils.supportsAccessControl(getRepositorySession())) { - names.add(SecurityConstants.SUPPORTED_PRIVILEGE_SET); - names.add(SecurityConstants.CURRENT_USER_PRIVILEGE_SET); - } - } - } - - /** - * Fill the property set for this resource. - */ - @Override - protected void initProperties() { - super.initProperties(); - if (exists()) { - // resource is serialized as system-view (xml) - properties.add(new DefaultDavProperty(DavPropertyName.GETCONTENTTYPE, "text/xml")); - Node n = (Node)item; - - // add node-specific resource properties - try { - properties.add(new NodeTypeProperty(JCR_PRIMARYNODETYPE, n.getPrimaryNodeType(), false)); - properties.add(new NodeTypeProperty(JCR_MIXINNODETYPES, n.getMixinNodeTypes(), false)); - } catch (RepositoryException e) { - log.error("Failed to retrieve node-specific property: " + e); - } - } - } - - @Override - protected String getCreatorDisplayName() { - // overwrite the default creation date and creator-displayname if possible - try { - // DAV:creator-displayname -> use jcr:createBy if present. - if (exists() && ((Node) item).hasProperty(Property.JCR_CREATED_BY)) { - return ((Node) item).getProperty(Property.JCR_CREATED_BY).getString(); - } - } catch (RepositoryException e) { - log.warn("Error while accessing jcr:createdBy property"); - } - - // fallback - return super.getCreatorDisplayName(); - } - - @Override - protected String getCreationDate() { - // overwrite the default creation date and creator-displayname if possible - try { - if (exists() && ((Node) item).hasProperty(JcrConstants.JCR_CREATED)) { - long creationTime = ((Node) item).getProperty(JcrConstants.JCR_CREATED).getValue().getLong(); - return HttpDateFormat.creationDateFormat().format(new Date(creationTime)); - } - } catch (RepositoryException e) { - log.warn("Error while accessing jcr:created property"); - } - - // fallback - return super.getCreationDate(); - } - - /** - * Creates a new HrefProperty with the specified name using the given - * array of items as value. - * - * @param name - * @param values - * @param isProtected - * @return - */ - protected HrefProperty getHrefProperty(DavPropertyName name, Item[] values, boolean isProtected) { - String[] pHref = new String[values.length]; - for (int i = 0; i < values.length; i++) { - pHref[i] = getLocatorFromItem(values[i]).getHref(true); - } - return new HrefProperty(name, pHref, isProtected); - } - - /** - * Add a {@link org.apache.jackrabbit.webdav.property.HrefProperty} with the - * specified property name and values. Each item present in the specified - * values array is referenced in the resulting property. - * - * @param name - * @param values - * @param isProtected - */ - protected void addHrefProperty(DavPropertyName name, Item[] values, boolean isProtected) { - properties.add(getHrefProperty(name, values, isProtected)); - } - - /** - * Creates a new {@link HrefProperty href property} to the property set, where - * all properties present in the specified iterator are referenced in the - * resulting property. - * - * @param name - * @param itemIterator - * @param isProtected - * @return - */ - protected HrefProperty getHrefProperty(DavPropertyName name, PropertyIterator itemIterator, - boolean isProtected) { - ArrayList l = new ArrayList(); - while (itemIterator.hasNext()) { - l.add(itemIterator.nextProperty()); - } - return getHrefProperty(name, l.toArray(new Property[l.size()]), isProtected); - } - - /** - * Add a new {@link HrefProperty href property} to the property set, where - * all properties present in the specified iterator are referenced in the - * resulting property. - * - * @param name - * @param itemIterator - * @param isProtected - * @see #addHrefProperty(DavPropertyName, Item[], boolean) - */ - protected void addHrefProperty(DavPropertyName name, PropertyIterator itemIterator, - boolean isProtected) { - properties.add(getHrefProperty(name, itemIterator, isProtected)); - } - - /** - * Add a new {@link HrefProperty href property} to the property set, where - * all versions present in the specified iterator are referenced in the - * resulting property. - * - * @param name - * @param itemIterator - * @param isProtected - */ - protected HrefProperty getHrefProperty(DavPropertyName name, VersionIterator itemIterator, - boolean isProtected) { - ArrayList l = new ArrayList(); - while (itemIterator.hasNext()) { - l.add(itemIterator.nextVersion()); - } - return getHrefProperty(name, l.toArray(new Version[l.size()]), isProtected); - } - - /** - * Add a new {@link HrefProperty href property} to the property set, where - * all versions present in the specified iterator are referenced in the - * resulting property. - * - * @param name - * @param itemIterator - * @param isProtected - */ - protected void addHrefProperty(DavPropertyName name, VersionIterator itemIterator, - boolean isProtected) { - properties.add(getHrefProperty(name, itemIterator, isProtected)); - } - - /** - * Tries to parse the given input stream as xml document and build a - * {@link ValuesProperty} out of it. - * - * @param in - * @return values property or 'null' if the given stream cannot be parsed - * into an XML document or if build the property fails. - */ - private ValuesProperty buildValuesProperty(InputStream in) { - String errorMsg = "Cannot parse stream into a 'ValuesProperty'."; - try { - Document reqBody = DomUtil.parseDocument(in); - DavProperty defaultProp = DefaultDavProperty.createFromXml(reqBody.getDocumentElement()); - ValuesProperty vp = new ValuesProperty(defaultProp, PropertyType.STRING, getRepositorySession().getValueFactory()); - return vp; - } catch (IOException e) { - log.debug(errorMsg, e); - } catch (ParserConfigurationException e) { - log.debug(errorMsg, e); - } catch (SAXException e) { - log.debug(errorMsg, e); - } catch (DavException e) { - log.debug(errorMsg, e); - } catch (RepositoryException e) { - log.debug(errorMsg, e); - } - // cannot parse request body into a 'values' property - return null; - } - - private boolean hasPrimaryItem() { - try { - return exists() && ((Node) item).getPrimaryNodeType().getPrimaryItemName() != null; - } catch (RepositoryException e) { - log.warn(e.getMessage()); - } - return false; - } - - private boolean isReferenceable() { - try { - return exists() && ((Node) item).isNodeType(JcrConstants.MIX_REFERENCEABLE); - } catch (RepositoryException e) { - log.warn(e.getMessage()); - } - return false; - } -} Property changes on: jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/DefaultItemCollection.java ___________________________________________________________________ Deleted: svn Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/DefaultItemResource.java =================================================================== --- jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/DefaultItemResource.java (revision 1907912) +++ jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/DefaultItemResource.java (nonexistent) @@ -1,421 +0,0 @@ -/* - * 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.webdav.jcr; - -import org.apache.jackrabbit.commons.webdav.JcrValueType; -import org.apache.jackrabbit.commons.xml.SerializingContentHandler; -import org.apache.jackrabbit.server.io.IOUtil; -import org.apache.jackrabbit.webdav.DavException; -import org.apache.jackrabbit.webdav.DavResource; -import org.apache.jackrabbit.webdav.DavResourceFactory; -import org.apache.jackrabbit.webdav.DavResourceIterator; -import org.apache.jackrabbit.webdav.DavResourceIteratorImpl; -import org.apache.jackrabbit.webdav.DavResourceLocator; -import org.apache.jackrabbit.webdav.DavServletResponse; -import org.apache.jackrabbit.webdav.MultiStatusResponse; -import org.apache.jackrabbit.webdav.io.InputContext; -import org.apache.jackrabbit.webdav.io.OutputContext; -import org.apache.jackrabbit.webdav.jcr.property.JcrDavPropertyNameSet; -import org.apache.jackrabbit.webdav.jcr.property.LengthsProperty; -import org.apache.jackrabbit.webdav.jcr.property.ValuesProperty; -import org.apache.jackrabbit.webdav.lock.ActiveLock; -import org.apache.jackrabbit.webdav.lock.Scope; -import org.apache.jackrabbit.webdav.lock.Type; -import org.apache.jackrabbit.webdav.property.DavProperty; -import org.apache.jackrabbit.webdav.property.DavPropertyName; -import org.apache.jackrabbit.webdav.property.DavPropertyNameSet; -import org.apache.jackrabbit.webdav.property.DefaultDavProperty; -import org.apache.jackrabbit.webdav.property.PropEntry; -import org.apache.jackrabbit.webdav.xml.DomUtil; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.w3c.dom.Document; -import org.xml.sax.ContentHandler; -import org.xml.sax.SAXException; - -import javax.jcr.Binary; -import javax.jcr.Item; -import javax.jcr.Property; -import javax.jcr.PropertyType; -import javax.jcr.RepositoryException; -import javax.jcr.Value; -import javax.jcr.ValueFactory; -import javax.xml.parsers.ParserConfigurationException; -import javax.xml.transform.Transformer; -import javax.xml.transform.TransformerConfigurationException; -import javax.xml.transform.TransformerException; -import javax.xml.transform.TransformerFactory; -import javax.xml.transform.dom.DOMSource; -import javax.xml.transform.sax.SAXResult; - -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.util.Collections; -import java.util.Date; -import java.util.List; - -/** - * DefaultItemResource represents JCR property item. - * - * @see Property - */ -public class DefaultItemResource extends AbstractItemResource { - - private static Logger log = LoggerFactory.getLogger(DefaultItemResource.class); - - /** - * Create a new DefaultItemResource. - * - * @param locator - * @param session - */ - public DefaultItemResource(DavResourceLocator locator, JcrDavSession session, - DavResourceFactory factory, Item item) { - super(locator, session, factory, item); - } - - //----------------------------------------------< DavResource interface >--- - /** - * Returns false. - * - * @return false - * @see DavResource#isCollection() - */ - @Override - public boolean isCollection() { - return false; - } - - /** - * Always returns 'now' - * - * @return - * @see DavResource#getModificationTime() - */ - @Override - public long getModificationTime() { - return new Date().getTime(); - } - - /** - * In case an underlying repository {@link Property property} exists the following - * logic is applied to spool the property content: - *
    - *
  • Property is not multi valued: Return the {@link javax.jcr.Value#getStream() - * stream representation} of the property value.
  • - *
  • Property is multivalue: Return the xml representation of the values.
  • - *
- * - * @param outputContext - * @see DavResource#spool(OutputContext) - */ - @Override - public void spool(OutputContext outputContext) throws IOException { - // write properties - super.spool(outputContext); - // spool content - OutputStream out = outputContext.getOutputStream(); - if (out != null && exists()) { - if (isMultiple()) { - spoolMultiValued(out); - } else { - spoolSingleValued(out); - } - } - } - - private void spoolMultiValued(OutputStream out) { - try { - Document doc = DomUtil.createDocument(); - doc.appendChild(getProperty(JCR_VALUES).toXml(doc)); - - ContentHandler handler = - SerializingContentHandler.getSerializer(out); - - Transformer transformer = - TransformerFactory.newInstance().newTransformer(); - transformer.transform( - new DOMSource(doc), new SAXResult(handler)); - } catch (SAXException e) { - log.error("Failed to set up XML serializer for " + item, e); - } catch (TransformerConfigurationException e) { - log.error("Failed to set up XML transformer for " + item, e); - } catch (ParserConfigurationException e) { - log.error("Failed to set up XML document for " + item, e); - } catch (TransformerException e) { - log.error("Failed to serialize the values of " + item, e); - } - } - - private void spoolSingleValued(OutputStream out) throws IOException { - try { - Binary binary = ((Property) item).getBinary(); - try { - InputStream in = binary.getStream(); - try { - IOUtil.spool(in, out); - } finally { - in.close(); - } - } finally { - binary.dispose(); - } - } catch (RepositoryException e) { - log.error("Cannot obtain stream from " + item, e); - } - } - - @Override - public DavProperty getProperty(DavPropertyName name) { - DavProperty prop = super.getProperty(name); - - if (prop == null && exists()) { - try { - Property p = (Property) item; - if (isMultiple()) { - if (JCR_LENGTHS.equals(name)) { - prop = new LengthsProperty(p.getLengths()); - } - } else { - if (JCR_LENGTH.equals(name)) { - long length = p.getLength(); - prop = new DefaultDavProperty(JCR_LENGTH, String.valueOf(length), true); - } else if (JCR_GET_STRING.equals(name) && p.getType() != PropertyType.BINARY) { - // getstring property is only created for single value - // non-binary jcr properties - prop = new DefaultDavProperty(JCR_GET_STRING, p.getString(), true); - } - } - } catch (RepositoryException e) { - log.error("Failed to retrieve resource properties: "+e.getMessage()); - } - } - - return prop; - } - - /** - * Sets the given property. Note, that {@link #JCR_VALUE} and {@link #JCR_VALUES} - * are the only resource properties that are allowed to be modified. Any other - * property is read-only and will throw an exception ('Conflict'). - * - * @param property - * @throws DavException - * @see DavResource#setProperty(org.apache.jackrabbit.webdav.property.DavProperty) - */ - @Override - public void setProperty(DavProperty property) throws DavException { - internalSetProperty(property); - complete(); - } - - /** - * Internal method that performs the setting or adding of properties - * - * @param property - * @throws DavException - * @see #setProperty(DavProperty) - * @see #alterProperties(List) - */ - private void internalSetProperty(DavProperty property) throws DavException { - if (!exists()) { - throw new DavException(DavServletResponse.SC_NOT_FOUND); - } - try { - Property prop = (Property) item; - int defaultType = prop.getType(); - ValueFactory vfact = getRepositorySession().getValueFactory(); - ValuesProperty vp = new ValuesProperty(property, defaultType, vfact); - if (property.getName().equals(JCR_VALUE)) { - prop.setValue(vp.getJcrValue(vp.getValueType(), vfact)); - } else if (property.getName().equals(JCR_VALUES)) { - prop.setValue(vp.getJcrValues()); - } else { - throw new DavException(DavServletResponse.SC_CONFLICT); - } - } catch (RepositoryException e) { - throw new JcrDavException(e); - } - } - - /** - * Removing properties is not allowed, for a single-value JCR-property without - * a value does not exist. For multivalue properties an empty {@link Value values array} - * may be specified with by setting the {@link #JCR_VALUES 'values' webdav property}. - * - * @param propertyName - * @throws DavException - * @see org.apache.jackrabbit.webdav.DavResource#removeProperty(org.apache.jackrabbit.webdav.property.DavPropertyName) - */ - @Override - public void removeProperty(DavPropertyName propertyName) throws DavException { - if (!exists()) { - throw new DavException(DavServletResponse.SC_NOT_FOUND); - } - throw new DavException(DavServletResponse.SC_FORBIDDEN); - } - - /** - * Loops over the given List and alters the properties accordingly. - * Changes are persisted at the end only according to the rules defined with - * the {@link #complete()} method.

- * Please note: since there is only a single property than can be set - * from a client (i.e. jcr:value OR jcr:values) this method either succeeds - * or throws an exception, even if this violates RFC 2518. - * - * @param changeList - * @throws DavException - * @see DavResource#alterProperties(List) - */ - @Override - public MultiStatusResponse alterProperties(List changeList) throws DavException { - for (PropEntry propEntry : changeList) { - if (propEntry instanceof DavPropertyName) { - // altering any properties fails if an attempt is made to remove - // a property - throw new DavException(DavServletResponse.SC_FORBIDDEN); - } else if (propEntry instanceof DavProperty) { - DavProperty prop = (DavProperty) propEntry; - internalSetProperty(prop); - } else { - throw new IllegalArgumentException("unknown object in change list: " + propEntry.getClass().getName()); - } - } - complete(); - return new MultiStatusResponse(getHref(), DavServletResponse.SC_OK); - } - - /** - * Method is not allowed. - * - * @see org.apache.jackrabbit.webdav.DavResource#addMember(org.apache.jackrabbit.webdav.DavResource, InputContext) - */ - @Override - public void addMember(DavResource resource, InputContext inputContext) throws DavException { - throw new DavException(DavServletResponse.SC_METHOD_NOT_ALLOWED, "Cannot add members to a non-collection resource"); - } - - /** - * Always returns an empty iterator for a non-collection resource might - * not have internal members. - * - * @return an empty iterator - * @see DavResource#getMembers() - */ - @Override - public DavResourceIterator getMembers() { - log.warn("A non-collection resource never has internal members."); - List drl = Collections.emptyList(); - return new DavResourceIteratorImpl(drl); - } - - /** - * Method is not allowed. - * - * @see DavResource#removeMember(DavResource) - */ - @Override - public void removeMember(DavResource member) throws DavException { - throw new DavException(DavServletResponse.SC_METHOD_NOT_ALLOWED, "Cannot remove members from a non-collection resource"); - } - - /** - * {@link javax.jcr.Property JCR properties} are locked if their - * parent node is locked; thus this method will always return the - * {@link ActiveLock lock} object from the collection this resource is - * internal member of. - * - * @param type - * @param scope - * @return lock present on this resource or null if this resource - * has no lock. - * @see DavResource#getLock(Type, Scope) - */ - @Override - public ActiveLock getLock(Type type, Scope scope) { - if (Type.WRITE.equals(type)) { - return getCollection().getLock(type, scope); - } else { - return super.getLock(type, scope); - } - } - - //-------------------------------------------------------------------------- - @Override - protected void initPropertyNames() { - super.initPropertyNames(); - if (exists()) { - DavPropertyNameSet propNames = (isMultiple() ? - JcrDavPropertyNameSet.PROPERTY_MV_SET : - JcrDavPropertyNameSet.PROPERTY_SET); - names.addAll(propNames); - } - } - - /** - * Add resource specific properties. - */ - @Override - protected void initProperties() { - super.initProperties(); - if (exists()) { - try { - Property prop = (Property)item; - int type = prop.getType(); - - // set the content type - String contentType; - if (isMultiple()) { - contentType = IOUtil.buildContentType("text/xml","utf-8"); - } else { - contentType = IOUtil.buildContentType(JcrValueType.contentTypeFromType(type), "utf-8"); - - } - properties.add(new DefaultDavProperty(DavPropertyName.GETCONTENTTYPE, contentType)); - - // add jcr-specific resource properties - properties.add(new DefaultDavProperty(JCR_TYPE, PropertyType.nameFromValue(type))); - if (isMultiple()) { - properties.add(new ValuesProperty(prop.getValues())); - } else { - properties.add(new ValuesProperty(prop.getValue())); - } - } catch (RepositoryException e) { - log.error("Failed to retrieve resource properties: "+e.getMessage()); - } - } - } - - /** - * Returns true if the JCR Property represented by this resource is a multi - * value property. Note: if this resource does not exist or if the definition - * could not be retrieved false is returned. - * - * @return true if the underlying resource is a multi value property. - */ - private boolean isMultiple() { - try { - if (exists() && ((Property)item).isMultiple()) { - return true; - } - } catch (RepositoryException e) { - log.error("Error while retrieving property definition: " + e.getMessage()); - } - return false; - } -} Property changes on: jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/DefaultItemResource.java ___________________________________________________________________ Deleted: svn Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/EventJournalResourceImpl.java =================================================================== --- jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/EventJournalResourceImpl.java (revision 1907912) +++ jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/EventJournalResourceImpl.java (nonexistent) @@ -1,483 +0,0 @@ -/* - * 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.webdav.jcr; - -import java.io.IOException; -import java.io.OutputStream; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Calendar; -import java.util.Collections; -import java.util.List; -import java.util.Locale; -import java.util.Map; -import java.util.Set; - -import javax.jcr.RepositoryException; -import javax.jcr.UnsupportedRepositoryOperationException; -import javax.jcr.observation.Event; -import javax.jcr.observation.EventJournal; -import javax.servlet.http.HttpServletRequest; -import javax.xml.transform.OutputKeys; -import javax.xml.transform.Transformer; -import javax.xml.transform.TransformerFactory; -import javax.xml.transform.sax.SAXTransformerFactory; -import javax.xml.transform.sax.TransformerHandler; -import javax.xml.transform.stream.StreamResult; - -import org.apache.jackrabbit.commons.webdav.AtomFeedConstants; -import org.apache.jackrabbit.commons.webdav.EventUtil; -import org.apache.jackrabbit.spi.Name; -import org.apache.jackrabbit.spi.commons.AdditionalEventInfo; -import org.apache.jackrabbit.util.ISO8601; -import org.apache.jackrabbit.webdav.DavConstants; -import org.apache.jackrabbit.webdav.DavException; -import org.apache.jackrabbit.webdav.DavResource; -import org.apache.jackrabbit.webdav.DavResourceFactory; -import org.apache.jackrabbit.webdav.DavResourceIterator; -import org.apache.jackrabbit.webdav.DavResourceIteratorImpl; -import org.apache.jackrabbit.webdav.DavResourceLocator; -import org.apache.jackrabbit.webdav.DavServletResponse; -import org.apache.jackrabbit.webdav.io.InputContext; -import org.apache.jackrabbit.webdav.io.OutputContext; -import org.apache.jackrabbit.webdav.observation.ObservationConstants; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.xml.sax.Attributes; -import org.xml.sax.SAXException; -import org.xml.sax.helpers.AttributesImpl; - -/** - * Implements a JCR {@link EventJournal} in terms of an RFC 4287 Atom feed. - *

- * Each feed entry represents either a single event, or, if the repository - * supports the {@link Event#PERSIST} event, an event bundle. The actual event - * data is sent in the Atom <content> element and uses the same XML - * serialization as the one used for subscriptions. - *

- * Skipping is implemented by specifying the desired time offset (represented - * as hexadecimal long in ms since the epoch) disguised as ETag in the HTTP "If-None-Match" - * header field. - *

- * The generated feed may not be complete; the total number of events is limited in - * order not to overload the client. - *

- * Furthermore, the number of events is limited by going up to 2000 ms into the future - * (based on the request time). This is supposed to limit the wait time for the client). - */ -public class EventJournalResourceImpl extends AbstractResource { - - public static final String RELURIFROMWORKSPACE = "?type=journal"; - - public static final String EVENTMEDIATYPE = "application/vnd.apache.jackrabbit.event+xml"; - - private static Logger log = LoggerFactory.getLogger(EventJournalResourceImpl.class); - - private final HttpServletRequest request; - private final EventJournal journal; - private final DavResourceLocator locator; - - EventJournalResourceImpl(EventJournal journal, DavResourceLocator locator, JcrDavSession session, - HttpServletRequest request, DavResourceFactory factory) { - super(locator, session, factory); - this.journal = journal; - this.locator = locator; - this.request = request; - } - - @Override - public String getSupportedMethods() { - return "GET, HEAD"; - } - - @Override - public boolean exists() { - try { - List available = Arrays.asList(getRepositorySession().getWorkspace().getAccessibleWorkspaceNames()); - return available.contains(getLocator().getWorkspaceName()); - } catch (RepositoryException e) { - log.warn(e.getMessage()); - return false; - } - } - - @Override - public boolean isCollection() { - return false; - } - - @Override - public String getDisplayName() { - return "event journal for " + getLocator().getWorkspaceName(); - } - - @Override - public long getModificationTime() { - return System.currentTimeMillis(); - } - - private static final String ATOMNS = AtomFeedConstants.NS_URI; - private static final String EVNS = ObservationConstants.NAMESPACE.getURI(); - - private static final String AUTHOR = AtomFeedConstants.XML_AUTHOR; - private static final String CONTENT = AtomFeedConstants.XML_CONTENT; - private static final String ENTRY = AtomFeedConstants.XML_ENTRY; - private static final String FEED = AtomFeedConstants.XML_FEED; - private static final String ID = AtomFeedConstants.XML_ID; - private static final String LINK = AtomFeedConstants.XML_LINK; - private static final String NAME = AtomFeedConstants.XML_NAME; - private static final String TITLE = AtomFeedConstants.XML_TITLE; - private static final String UPDATED = AtomFeedConstants.XML_UPDATED; - - private static final String E_EVENT = ObservationConstants.XML_EVENT; - private static final String E_EVENTDATE = ObservationConstants.XML_EVENTDATE; - private static final String E_EVENTIDENTIFIER = ObservationConstants.XML_EVENTIDENTIFIER; - private static final String E_EVENTINFO = ObservationConstants.XML_EVENTINFO; - private static final String E_EVENTTYPE = ObservationConstants.XML_EVENTTYPE; - private static final String E_EVENTMIXINNODETYPE = ObservationConstants.XML_EVENTMIXINNODETYPE; - private static final String E_EVENTPRIMARNODETYPE = ObservationConstants.XML_EVENTPRIMARNODETYPE; - private static final String E_EVENTUSERDATA = ObservationConstants.XML_EVENTUSERDATA; - - private static final int MAXWAIT = 2000; // maximal wait time - private static final int MAXEV = 10000; // maximal event number - - private static final Attributes NOATTRS = new AttributesImpl(); - - @Override - public void spool(OutputContext outputContext) throws IOException { - - Calendar cal = Calendar.getInstance(Locale.ENGLISH); - - try { - outputContext.setContentType("application/atom+xml; charset=UTF-8"); - outputContext.setProperty("Vary", "If-None-Match"); - // TODO: Content-Encoding: gzip - - // find out where to start - long prevts = -1; - String inm = request.getHeader("If-None-Match"); - if (inm != null) { - // TODO: proper parsing when comma-delimited - inm = inm.trim(); - if (inm.startsWith("\"") && inm.endsWith("\"")) { - String tmp = inm.substring(1, inm.length() - 1); - try { - prevts = Long.parseLong(tmp, 16); - journal.skipTo(prevts); - } catch (NumberFormatException ex) { - // broken etag - } - } - } - - boolean hasPersistEvents = false; - - if (outputContext.hasStream()) { - - long lastts = -1; - long now = System.currentTimeMillis(); - boolean done = false; - - // collect events - List events = new ArrayList(MAXEV); - - while (!done && journal.hasNext()) { - Event e = journal.nextEvent(); - - hasPersistEvents |= e.getType() == Event.PERSIST; - - if (e.getDate() != lastts) { - // consider stopping - if (events.size() > MAXEV) { - done = true; - } - if (e.getDate() > now + MAXWAIT) { - done = true; - } - } - - if (!done && (prevts == -1 || e.getDate() >= prevts)) { - events.add(e); - } - - lastts = e.getDate(); - } - - if (lastts >= 0) { - // construct ETag from newest event - outputContext.setETag("\"" + Long.toHexString(lastts) + "\""); - } - - OutputStream os = outputContext.getOutputStream(); - StreamResult streamResult = new StreamResult(os); - SAXTransformerFactory tf = (SAXTransformerFactory) TransformerFactory.newInstance(); - TransformerHandler th = tf.newTransformerHandler(); - Transformer s = th.getTransformer(); - s.setOutputProperty(OutputKeys.ENCODING, "UTF-8"); - s.setOutputProperty(OutputKeys.INDENT, "yes"); - s.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes"); - - th.setResult(streamResult); - - th.startDocument(); - - th.startElement(ATOMNS, FEED, FEED, NOATTRS); - - writeAtomElement(th, TITLE, "EventJournal for " + getLocator().getWorkspaceName()); - - th.startElement(ATOMNS, AUTHOR, AUTHOR, NOATTRS); - writeAtomElement(th, NAME, "Jackrabbit Event Journal Feed Generator"); - th.endElement(ATOMNS, AUTHOR, AUTHOR); - - String id = getFullUri(request); - writeAtomElement(th, ID, id); - - AttributesImpl linkattrs = new AttributesImpl(); - linkattrs.addAttribute(null, "self", "self", "CDATA", id); - writeAtomElement(th, LINK, linkattrs, null); - - cal.setTimeInMillis(lastts >= 0 ? lastts : now); - String upd = ISO8601.format(cal); - writeAtomElement(th, UPDATED, upd); - - String lastDateString = ""; - long lastTimeStamp = 0; - long index = 0; - - AttributesImpl contentatt = new AttributesImpl(); - contentatt.addAttribute(null, "type", "type", "CDATA", EVENTMEDIATYPE); - - while (!events.isEmpty()) { - - List bundle = null; - String path = null; - String op; - - if (hasPersistEvents) { - bundle = new ArrayList(); - Event e = null; - op = "operations"; - - do { - e = events.remove(0); - bundle.add(e); - - // compute common path - if (path == null) { - path = e.getPath(); - } else { - if (e.getPath() != null && e.getPath().length() < path.length()) { - path = e.getPath(); - } - } - } while (e.getType() != Event.PERSIST && !events.isEmpty()); - } else { - // no persist events - Event e = events.remove(0); - bundle = Collections.singletonList(e); - path = e.getPath(); - op = EventUtil.getEventName(e.getType()); - } - - Event firstEvent = bundle.get(0); - - String entryupd = lastDateString; - if (lastTimeStamp != firstEvent.getDate()) { - cal.setTimeInMillis(firstEvent.getDate()); - entryupd = ISO8601.format(cal); - index = 0; - } else { - index += 1; - } - - th.startElement(ATOMNS, ENTRY, ENTRY, NOATTRS); - - String entrytitle = op + (path != null ? (": " + path) : ""); - writeAtomElement(th, TITLE, entrytitle); - - String entryid = id + "?type=journal&ts=" + Long.toHexString(firstEvent.getDate()) + "-" + index; - writeAtomElement(th, ID, entryid); - - String author = firstEvent.getUserID() == null || firstEvent.getUserID().length() == 0 ? null - : firstEvent.getUserID(); - if (author != null) { - th.startElement(ATOMNS, AUTHOR, AUTHOR, NOATTRS); - writeAtomElement(th, NAME, author); - th.endElement(ATOMNS, AUTHOR, AUTHOR); - } - - writeAtomElement(th, UPDATED, entryupd); - - th.startElement(ATOMNS, CONTENT, CONTENT, contentatt); - - for (Event e : bundle) { - - // serialize the event - th.startElement(EVNS, E_EVENT, E_EVENT, NOATTRS); - - // DAV:href - if (e.getPath() != null) { - boolean isCollection = (e.getType() == Event.NODE_ADDED || e.getType() == Event.NODE_REMOVED); - String href = locator - .getFactory() - .createResourceLocator(locator.getPrefix(), locator.getWorkspacePath(), - e.getPath(), false).getHref(isCollection); - th.startElement(DavConstants.NAMESPACE.getURI(), DavConstants.XML_HREF, - DavConstants.XML_HREF, NOATTRS); - th.characters(href.toCharArray(), 0, href.length()); - th.endElement(DavConstants.NAMESPACE.getURI(), DavConstants.XML_HREF, DavConstants.XML_HREF); - } - - // event type - String evname = EventUtil.getEventName(e.getType()); - th.startElement(EVNS, E_EVENTTYPE, E_EVENTTYPE, NOATTRS); - th.startElement(EVNS, evname, evname, NOATTRS); - th.endElement(EVNS, evname, evname); - th.endElement(EVNS, E_EVENTTYPE, E_EVENTTYPE); - - // date - writeObsElement(th, E_EVENTDATE, Long.toString(e.getDate())); - - // user data - if (e.getUserData() != null && e.getUserData().length() > 0) { - writeObsElement(th, E_EVENTUSERDATA, firstEvent.getUserData()); - } - - // user id: already sent as Atom author/name - - // try to compute nodetype information - if (e instanceof AdditionalEventInfo) { - try { - Name pnt = ((AdditionalEventInfo) e).getPrimaryNodeTypeName(); - if (pnt != null) { - writeObsElement(th, E_EVENTPRIMARNODETYPE, pnt.toString()); - } - - Set mixins = ((AdditionalEventInfo) e).getMixinTypeNames(); - if (mixins != null) { - for (Name mixin : mixins) { - writeObsElement(th, E_EVENTMIXINNODETYPE, mixin.toString()); - } - } - - } catch (UnsupportedRepositoryOperationException ex) { - // optional - } - } - - // identifier - if (e.getIdentifier() != null) { - writeObsElement(th, E_EVENTIDENTIFIER, e.getIdentifier()); - } - - // info - if (!e.getInfo().isEmpty()) { - th.startElement(EVNS, E_EVENTINFO, E_EVENTINFO, NOATTRS); - Map m = e.getInfo(); - for (Map.Entry entry : m.entrySet()) { - String key = entry.getKey().toString(); - Object value = entry.getValue(); - String t = value != null ? value.toString() : null; - writeElement(th, null, key, NOATTRS, t); - } - th.endElement(EVNS, E_EVENTINFO, E_EVENTINFO); - } - - th.endElement(EVNS, E_EVENT, E_EVENT); - - lastTimeStamp = e.getDate(); - lastDateString = entryupd; - } - - th.endElement(ATOMNS, CONTENT, CONTENT); - th.endElement(ATOMNS, ENTRY, ENTRY); - } - - th.endElement(ATOMNS, FEED, FEED); - - th.endDocument(); - - os.flush(); - } - } catch (Exception ex) { - throw new IOException("error generating feed: " + ex.getMessage()); - } - } - - @Override - public DavResource getCollection() { - return null; - } - - @Override - public void addMember(DavResource resource, InputContext inputContext) throws DavException { - throw new DavException(DavServletResponse.SC_FORBIDDEN); - } - - @Override - public DavResourceIterator getMembers() { - return DavResourceIteratorImpl.EMPTY; - } - - @Override - public void removeMember(DavResource member) throws DavException { - throw new DavException(DavServletResponse.SC_FORBIDDEN); - } - - @Override - protected void initLockSupport() { - // lock not allowed - } - - @Override - protected String getWorkspaceHref() { - return getHref(); - } - - private void writeElement(TransformerHandler th, String ns, String name, Attributes attrs, String textContent) - throws SAXException { - th.startElement(ns, name, name, attrs); - if (textContent != null) { - th.characters(textContent.toCharArray(), 0, textContent.length()); - } - th.endElement(ns, name, name); - } - - private void writeAtomElement(TransformerHandler th, String name, Attributes attrs, String textContent) - throws SAXException { - writeElement(th, ATOMNS, name, attrs, textContent); - } - - private void writeAtomElement(TransformerHandler th, String name, String textContent) throws SAXException { - writeAtomElement(th, name, NOATTRS, textContent); - } - - private void writeObsElement(TransformerHandler th, String name, String textContent) throws SAXException { - writeElement(th, EVNS, name, NOATTRS, textContent); - } - - private String getFullUri(HttpServletRequest req) { - - String scheme = req.getScheme(); - int port = req.getServerPort(); - boolean isDefaultPort = (scheme.equals("http") && port == 80) || (scheme.equals("http") && port == 443); - String query = request.getQueryString() != null ? "?" + request.getQueryString() : ""; - - return String.format("%s://%s%s%s%s%s", scheme, req.getServerName(), isDefaultPort ? ":" : "", - isDefaultPort ? Integer.toString(port) : "", req.getRequestURI(), query); - } -} Property changes on: jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/EventJournalResourceImpl.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/ItemResourceConstants.java =================================================================== --- jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/ItemResourceConstants.java (revision 1907912) +++ jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/ItemResourceConstants.java (nonexistent) @@ -1,125 +0,0 @@ -/* - * 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.webdav.jcr; - -import javax.jcr.Session; - -import org.apache.jackrabbit.commons.webdav.JcrRemotingConstants; -import org.apache.jackrabbit.webdav.DavResource; -import org.apache.jackrabbit.webdav.lock.Scope; -import org.apache.jackrabbit.webdav.observation.ObservationResource; -import org.apache.jackrabbit.webdav.property.DavPropertyName; -import org.apache.jackrabbit.webdav.search.SearchResource; -import org.apache.jackrabbit.webdav.security.Privilege; -import org.apache.jackrabbit.webdav.version.DeltaVResource; -import org.apache.jackrabbit.webdav.xml.Namespace; - -/** - * ItemResourceConstants provides constants for any resources - * representing repository items. - */ -public interface ItemResourceConstants extends JcrRemotingConstants { - - /** - * Methods common to all item resources. - */ - public static final String METHODS = DavResource.METHODS + ", " + ObservationResource.METHODS + ", " + SearchResource.METHODS + ", " +DeltaVResource.METHODS; - - /** - * The namespace for all jcr specific extensions. - */ - public static final Namespace NAMESPACE = Namespace.getNamespace(NS_PREFIX, NS_URI); - - /** - * Extension to the WebDAV 'exclusive' lock, that allows to distinguish - * the session-scoped and open-scoped locks on a JCR node. - * - * @see javax.jcr.Node#lock(boolean, boolean) - */ - public static final Scope EXCLUSIVE_SESSION = Scope.create(XML_EXCLUSIVE_SESSION_SCOPED, NAMESPACE); - - // name of the workspace for which the repository session has been created. - public static final DavPropertyName JCR_WORKSPACE_NAME = DavPropertyName.create(JCR_WORKSPACE_NAME_LN, NAMESPACE); - - // general property names - public static final DavPropertyName JCR_NAME = DavPropertyName.create(JCR_NAME_LN, NAMESPACE); - public static final DavPropertyName JCR_PATH = DavPropertyName.create(JCR_PATH_LN, NAMESPACE); - public static final DavPropertyName JCR_DEPTH = DavPropertyName.create(JCR_DEPTH_LN, NAMESPACE); - public static final DavPropertyName JCR_PARENT = DavPropertyName.create(JCR_PARENT_LN, NAMESPACE); - public static final DavPropertyName JCR_ISNEW = DavPropertyName.create(JCR_ISNEW_LN, NAMESPACE); - public static final DavPropertyName JCR_ISMODIFIED = DavPropertyName.create(JCR_ISMODIFIED_LN, NAMESPACE); - public static final DavPropertyName JCR_DEFINITION = DavPropertyName.create(JCR_DEFINITION_LN, NAMESPACE); - public static final DavPropertyName JCR_SELECTOR_NAME = DavPropertyName.create(JCR_SELECTOR_NAME_LN, NAMESPACE); - - // property names used for resources representing jcr-nodes - public static final DavPropertyName JCR_PRIMARYNODETYPE = DavPropertyName.create(JCR_PRIMARYNODETYPE_LN, NAMESPACE); - public static final DavPropertyName JCR_MIXINNODETYPES = DavPropertyName.create(JCR_MIXINNODETYPES_LN, NAMESPACE); - public static final DavPropertyName JCR_INDEX = DavPropertyName.create(JCR_INDEX_LN, NAMESPACE); - public static final DavPropertyName JCR_REFERENCES = DavPropertyName.create(JCR_REFERENCES_LN, NAMESPACE); - /** - * @since JCR 2.0 - */ - public static final DavPropertyName JCR_WEAK_REFERENCES = DavPropertyName.create(JCR_WEAK_REFERENCES_LN, NAMESPACE); - public static final DavPropertyName JCR_UUID = DavPropertyName.create(JCR_UUID_LN, NAMESPACE); - public static final DavPropertyName JCR_PRIMARYITEM = DavPropertyName.create(JCR_PRIMARYITEM_LN, NAMESPACE); - - // property names used for resources representing jcr-properties - public static final DavPropertyName JCR_TYPE = DavPropertyName.create(JCR_TYPE_LN, NAMESPACE); - public static final DavPropertyName JCR_VALUE = DavPropertyName.create(JCR_VALUE_LN, NAMESPACE); - public static final DavPropertyName JCR_VALUES = DavPropertyName.create(JCR_VALUES_LN, NAMESPACE); - public static final DavPropertyName JCR_LENGTH = DavPropertyName.create(JCR_LENGTH_LN, NAMESPACE); - public static final DavPropertyName JCR_LENGTHS = DavPropertyName.create(JCR_LENGTHS_LN, NAMESPACE); - public static final DavPropertyName JCR_GET_STRING = DavPropertyName.create(JCR_GET_STRING_LN, NAMESPACE); - - // property names used for resource representing a workspace - public static final DavPropertyName JCR_NAMESPACES = DavPropertyName.create(JCR_NAMESPACES_LN, NAMESPACE); - public static final DavPropertyName JCR_NODETYPES_CND = DavPropertyName.create(JCR_NODETYPES_CND_LN, NAMESPACE); - - // property names used for resource representing a version history - public static final DavPropertyName JCR_VERSIONABLEUUID = DavPropertyName.create(JCR_VERSIONABLEUUID_LN, NAMESPACE); - - //-----------------------------------------< JSR170 specific privileges >--- - /** - * Privilege representing the JSR170 'read' action. - *

Note: the name of this constant is somewhat misleading - * as it corresponds to {@link javax.jcr.Session#ACTION_READ} and not - * to {@link javax.jcr.security.Privilege#JCR_READ}.

- */ - public static final Privilege PRIVILEGE_JCR_READ = Privilege.getPrivilege(Session.ACTION_READ, NAMESPACE); - /** - * Privilege representing the JSR170 'add_node' action. - *

Note: the name of this constant is somewhat misleading - * as it corresponds to {@link javax.jcr.Session#ACTION_ADD_NODE} and not - * to {@link javax.jcr.security.Privilege#JCR_ADD_CHILD_NODES}.

- */ - public static final Privilege PRIVILEGE_JCR_ADD_NODE = Privilege.getPrivilege(Session.ACTION_ADD_NODE, NAMESPACE); - /** - * Privilege representing the JSR170 'set_property' action. - *

Note: the name of this constant is somewhat misleading - * as it corresponds to {@link javax.jcr.Session#ACTION_SET_PROPERTY} and not - * to {@link javax.jcr.security.Privilege#JCR_MODIFY_PROPERTIES}.

- */ - public static final Privilege PRIVILEGE_JCR_SET_PROPERTY = Privilege.getPrivilege(Session.ACTION_SET_PROPERTY, NAMESPACE); - /** - * Privilege representing the JSR170 'remove' action. - *

Note: the name of this constant is somewhat misleading - * as it corresponds to {@link javax.jcr.Session#ACTION_REMOVE} and not - * to {@link javax.jcr.security.Privilege#JCR_REMOVE_NODE} or - * {@link javax.jcr.security.Privilege#JCR_REMOVE_CHILD_NODES}.

- */ - public static final Privilege PRIVILEGE_JCR_REMOVE = Privilege.getPrivilege(Session.ACTION_REMOVE, NAMESPACE); -} Property changes on: jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/ItemResourceConstants.java ___________________________________________________________________ Deleted: svn Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/JCRWebdavServerServlet.java =================================================================== --- jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/JCRWebdavServerServlet.java (revision 1907912) +++ jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/JCRWebdavServerServlet.java (nonexistent) @@ -1,321 +0,0 @@ -/* - * 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.webdav.jcr; - -import org.apache.jackrabbit.server.BasicCredentialsProvider; -import org.apache.jackrabbit.server.CredentialsProvider; -import org.apache.jackrabbit.server.SessionProvider; -import org.apache.jackrabbit.server.SessionProviderImpl; -import org.apache.jackrabbit.server.jcr.JCRWebdavServer; -import org.apache.jackrabbit.webdav.DavException; -import org.apache.jackrabbit.webdav.DavLocatorFactory; -import org.apache.jackrabbit.webdav.DavMethods; -import org.apache.jackrabbit.webdav.DavResource; -import org.apache.jackrabbit.webdav.DavResourceFactory; -import org.apache.jackrabbit.webdav.DavServletResponse; -import org.apache.jackrabbit.webdav.DavSessionProvider; -import org.apache.jackrabbit.webdav.WebdavRequest; -import org.apache.jackrabbit.webdav.jcr.observation.SubscriptionManagerImpl; -import org.apache.jackrabbit.webdav.jcr.transaction.TxLockManagerImpl; -import org.apache.jackrabbit.webdav.observation.SubscriptionManager; -import org.apache.jackrabbit.webdav.server.AbstractWebdavServlet; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import javax.jcr.Repository; -import javax.jcr.Session; -import javax.servlet.ServletContext; -import javax.servlet.ServletException; - -/** - * JCRWebdavServerServlet provides request/response handling for the - * JCRWebdavServer. - *

- * Implementations of this abstract class must implement the - * {@link #getRepository()} method to access the repository. - */ -public abstract class JCRWebdavServerServlet extends AbstractWebdavServlet { - - /** - * the default logger - */ - private static Logger log = LoggerFactory.getLogger(JCRWebdavServerServlet.class); - - /** - * Init parameter specifying the prefix used with the resource path. - */ - public static final String INIT_PARAM_RESOURCE_PATH_PREFIX = "resource-path-prefix"; - - /** - * Optional 'concurrency-level' parameter defining the concurrency level - * within the jcr-server. If the parameter is omitted the internal default - * value (50) is used. - */ - public final static String INIT_PARAM_CONCURRENCY_LEVEL = "concurrency-level"; - - /** - * Servlet context attribute used to store the path prefix instead of - * having a static field with this servlet. The latter causes problems - * when running multiple - */ - public static final String CTX_ATTR_RESOURCE_PATH_PREFIX = "jackrabbit.webdav.jcr.resourcepath"; - - private String pathPrefix; - - private JCRWebdavServer server; - private DavResourceFactory resourceFactory; - private DavLocatorFactory locatorFactory; - protected TxLockManagerImpl txMgr; - protected SubscriptionManager subscriptionMgr; - - /** - * Initializes the servlet set reads the following parameter from the - * servlet configuration: - *

    - *
  • resource-path-prefix: optional prefix for all resources.
  • - *
- * - * @throws ServletException - */ - @Override - public void init() throws ServletException { - super.init(); - - // set resource path prefix - pathPrefix = getInitParameter(INIT_PARAM_RESOURCE_PATH_PREFIX); - getServletContext().setAttribute(CTX_ATTR_RESOURCE_PATH_PREFIX, pathPrefix); - log.debug(INIT_PARAM_RESOURCE_PATH_PREFIX + " = " + pathPrefix); - - txMgr = new TxLockManagerImpl(); - subscriptionMgr = new SubscriptionManagerImpl(); - txMgr.addTransactionListener((SubscriptionManagerImpl) subscriptionMgr); - - // todo: eventually make configurable - resourceFactory = new DavResourceFactoryImpl(txMgr, subscriptionMgr); - locatorFactory = new DavLocatorFactoryImpl(pathPrefix); - } - - /** - * Returns true if the preconditions are met. This includes validation of - * {@link WebdavRequest#matchesIfHeader(DavResource) If header} and validation - * of {@link org.apache.jackrabbit.webdav.transaction.TransactionConstants#HEADER_TRANSACTIONID - * TransactionId header}. This method will also return false if the requested - * resource resides within a different workspace as is assigned to the repository - * session attached to the given request. - * - * @see AbstractWebdavServlet#isPreconditionValid(WebdavRequest, DavResource) - */ - @Override - protected boolean isPreconditionValid(WebdavRequest request, DavResource resource) { - // first check matching If header - if (!request.matchesIfHeader(resource)) { - return false; - } - - // test if the requested path matches to the existing session - // this may occur if the session was retrieved from the cache. - try { - Session repositorySesssion = JcrDavSession.getRepositorySession(request.getDavSession()); - String reqWspName = resource.getLocator().getWorkspaceName(); - String wsName = repositorySesssion.getWorkspace().getName(); - // compare workspace names if the requested resource isn't the - // root-collection and the request not MKWORKSPACE. - if (DavMethods.DAV_MKWORKSPACE != DavMethods.getMethodCode(request.getMethod()) && - reqWspName != null && !reqWspName.equals(wsName)) { - return false; - } - } catch (DavException e) { - log.error("Internal error: " + e.toString()); - return false; - } - - - // make sure, the TransactionId header is valid - String txId = request.getTransactionId(); - return txId == null || txMgr.hasLock(txId, resource); - } - - /** - * Returns the DavSessionProvider - * - * @return server - * @see AbstractWebdavServlet#getDavSessionProvider() - */ - @Override - public DavSessionProvider getDavSessionProvider() { - if (server == null) { - Repository repository = getRepository(); - String cl = getInitParameter(INIT_PARAM_CONCURRENCY_LEVEL); - if (cl != null) { - try { - server = new JCRWebdavServer(repository, getSessionProvider(), Integer.parseInt(cl)); - } catch (NumberFormatException e) { - log.debug("Invalid value '" + cl+ "' for init-param 'concurrency-level'. Using default instead."); - server = new JCRWebdavServer(repository, getSessionProvider()); - } - } else { - server = new JCRWebdavServer(repository, getSessionProvider()); - } - } - return server; - } - - /** - * Throws UnsupportedOperationException. - * - * @see AbstractWebdavServlet#setDavSessionProvider(DavSessionProvider) - */ - @Override - public void setDavSessionProvider(DavSessionProvider davSessionProvider) { - throw new UnsupportedOperationException("Not implemented. DavSession(s) are provided by the 'JCRWebdavServer'"); - } - - /** - * Returns the DavLocatorFactory - * - * @see AbstractWebdavServlet#getLocatorFactory() - */ - @Override - public DavLocatorFactory getLocatorFactory() { - if (locatorFactory == null) { - locatorFactory = new DavLocatorFactoryImpl(pathPrefix); - } - return locatorFactory; - } - - /** - * Sets the DavLocatorFactory - * - * @see AbstractWebdavServlet#setLocatorFactory(DavLocatorFactory) - */ - @Override - public void setLocatorFactory(DavLocatorFactory locatorFactory) { - this.locatorFactory = locatorFactory; - } - - /** - * Returns the DavResourceFactory. - * - * @see AbstractWebdavServlet#getResourceFactory() - */ - @Override - public DavResourceFactory getResourceFactory() { - if (resourceFactory == null) { - resourceFactory = new DavResourceFactoryImpl(txMgr, subscriptionMgr); - } - return resourceFactory; - } - - /** - * Sets the DavResourceFactory. - * - * @see AbstractWebdavServlet#setResourceFactory(org.apache.jackrabbit.webdav.DavResourceFactory) - */ - @Override - public void setResourceFactory(DavResourceFactory resourceFactory) { - this.resourceFactory = resourceFactory; - } - - /** - * Modified variant needed for JCR move and copy that isn't compliant to - * WebDAV. The latter requires both methods to fail if the destination already - * exists and Overwrite is set to F (false); in JCR however this depends on - * the node type characteristics of the parent (SNSiblings allowed or not). - * - * @param destResource destination resource to be validated. - * @param request The webdav request - * @param checkHeader flag indicating if the destination header must be present. - * @return status code indicating whether the destination is valid. - */ - @Override - protected int validateDestination(DavResource destResource, WebdavRequest request, boolean checkHeader) - throws DavException { - - if (checkHeader) { - String destHeader = request.getHeader(HEADER_DESTINATION); - if (destHeader == null || "".equals(destHeader)) { - return DavServletResponse.SC_BAD_REQUEST; - } - } - if (destResource.getLocator().equals(request.getRequestLocator())) { - return DavServletResponse.SC_FORBIDDEN; - } - - int status; - if (destResource.exists()) { - if (request.isOverwrite()) { - // matching if-header required for existing resources - if (!request.matchesIfHeader(destResource)) { - return DavServletResponse.SC_PRECONDITION_FAILED; - } else { - // overwrite existing resource - destResource.getCollection().removeMember(destResource); - status = DavServletResponse.SC_NO_CONTENT; - } - } else { - /* NO overwrite header: - - but, instead of return the 412 Precondition-Failed code required - by the WebDAV specification(s) leave the validation to the - JCR repository. - */ - status = DavServletResponse.SC_CREATED; - } - - } else { - // destination does not exist >> copy/move can be performed - status = DavServletResponse.SC_CREATED; - } - return status; - } - - /** - * Returns the configured path prefix - * - * @param ctx The servlet context. - * @return resourcePathPrefix - * @see #INIT_PARAM_RESOURCE_PATH_PREFIX - */ - public static String getPathPrefix(ServletContext ctx) { - return (String) ctx.getAttribute(CTX_ATTR_RESOURCE_PATH_PREFIX); - } - - /** - * Returns the repository to be used by this servlet. - * - * @return the JCR repository to be used by this servlet - */ - protected abstract Repository getRepository(); - - /** - * Returns a new instanceof BasicCredentialsProvider. - * - * @return a new credentials provider - */ - protected CredentialsProvider getCredentialsProvider() { - return new BasicCredentialsProvider(getInitParameter(INIT_PARAM_MISSING_AUTH_MAPPING)); - } - - /** - * Returns a new instanceof SessionProviderImpl. - * - * @return a new session provider - */ - protected SessionProvider getSessionProvider() { - return new SessionProviderImpl(getCredentialsProvider()); - } -} Property changes on: jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/JCRWebdavServerServlet.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/JcrDavException.java =================================================================== --- jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/JcrDavException.java (revision 1907912) +++ jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/JcrDavException.java (nonexistent) @@ -1,162 +0,0 @@ -/* - * 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.webdav.jcr; - -import org.apache.jackrabbit.webdav.DavConstants; -import org.apache.jackrabbit.webdav.DavException; -import org.apache.jackrabbit.webdav.DavServletResponse; -import org.apache.jackrabbit.webdav.xml.DomUtil; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.w3c.dom.Document; -import org.w3c.dom.Element; - -import javax.jcr.AccessDeniedException; -import javax.jcr.InvalidItemStateException; -import javax.jcr.InvalidSerializedDataException; -import javax.jcr.ItemExistsException; -import javax.jcr.ItemNotFoundException; -import javax.jcr.LoginException; -import javax.jcr.MergeException; -import javax.jcr.NamespaceException; -import javax.jcr.NoSuchWorkspaceException; -import javax.jcr.PathNotFoundException; -import javax.jcr.ReferentialIntegrityException; -import javax.jcr.RepositoryException; -import javax.jcr.UnsupportedRepositoryOperationException; -import javax.jcr.ValueFormatException; -import javax.jcr.lock.LockException; -import javax.jcr.nodetype.ConstraintViolationException; -import javax.jcr.nodetype.NoSuchNodeTypeException; -import javax.jcr.query.InvalidQueryException; -import javax.jcr.version.VersionException; -import java.util.Map; -import java.util.LinkedHashMap; - - -/** - * JcrDavException extends the {@link DavException} in order to - * wrap various repository exceptions. - */ -public class JcrDavException extends DavException { - - private static Logger log = LoggerFactory.getLogger(JcrDavException.class); - - // ordered mapping of Jcr exceptions to error codes. - private static Map, Integer> codeMap = new LinkedHashMap, Integer>(20); - static { - codeMap.put(AccessDeniedException.class, DavServletResponse.SC_FORBIDDEN); - codeMap.put(ConstraintViolationException.class, DavServletResponse.SC_CONFLICT); - codeMap.put(InvalidItemStateException.class, DavServletResponse.SC_CONFLICT); - codeMap.put(InvalidSerializedDataException.class, DavServletResponse.SC_BAD_REQUEST); - codeMap.put(InvalidQueryException.class, DavServletResponse.SC_BAD_REQUEST); - codeMap.put(ItemExistsException.class, DavServletResponse.SC_CONFLICT); - codeMap.put(ItemNotFoundException.class, DavServletResponse.SC_FORBIDDEN); - codeMap.put(LockException.class, DavServletResponse.SC_LOCKED); - codeMap.put(MergeException.class, DavServletResponse.SC_CONFLICT); - codeMap.put(NamespaceException.class, DavServletResponse.SC_CONFLICT); - codeMap.put(NoSuchNodeTypeException.class, DavServletResponse.SC_CONFLICT); - codeMap.put(NoSuchWorkspaceException.class, DavServletResponse.SC_CONFLICT); - codeMap.put(PathNotFoundException.class, DavServletResponse.SC_CONFLICT); - codeMap.put(ReferentialIntegrityException.class, DavServletResponse.SC_CONFLICT); - codeMap.put(LoginException.class, DavServletResponse.SC_UNAUTHORIZED); - codeMap.put(UnsupportedRepositoryOperationException.class, DavServletResponse.SC_NOT_IMPLEMENTED); - codeMap.put(ValueFormatException.class, DavServletResponse.SC_CONFLICT); - codeMap.put(VersionException.class, DavServletResponse.SC_CONFLICT); - codeMap.put(RepositoryException.class, DavServletResponse.SC_FORBIDDEN); - } - - private static int lookupErrorCode(Class exceptionClass) { - Integer code = codeMap.get(exceptionClass); - if (code == null) { - for (Class jcrExceptionClass : codeMap.keySet()) { - if (jcrExceptionClass.isAssignableFrom(exceptionClass)) { - code = codeMap.get(jcrExceptionClass); - break; - } - } - if (code == null) { - code = DavServletResponse.SC_FORBIDDEN; // fallback - } - } - return code; - } - - /** - * The exception wrapped by this DavException instance. - */ - private Class exceptionClass; - - /** - * Create a new JcrDavException. - * - * @param cause The original cause of this DavException. Note, that - * in contrast to {@link Throwable#Throwable(Throwable)}, {@link Throwable#Throwable(String, Throwable)} and - * {@link Throwable#initCause(Throwable)} the cause must not be null. - * @param errorCode Status code for the response. - * @throws NullPointerException if the given exception is null. - * @see DavException#DavException(int, String) - * @see DavException#DavException(int) - */ - public JcrDavException(Throwable cause, int errorCode) { - super(errorCode, cause.getMessage(), cause, null); - exceptionClass = cause.getClass(); - if (log.isDebugEnabled()) { - log.debug("Handling exception with error code " + errorCode, cause); - } - } - - /** - * Same as {@link JcrDavException#JcrDavException(Throwable, int)} where the - * error code is retrieved from an internal mapping. - * - * @param cause Cause of this DavException - * @throws NullPointerException if the given exception is null. - * @see JcrDavException#JcrDavException(Throwable, int) - */ - public JcrDavException(RepositoryException cause) { - this(cause, lookupErrorCode(cause.getClass())); - } - - /** - * Always returns true. - * - * @return true - */ - @Override - public boolean hasErrorCondition() { - return true; - } - - /** - * Returns a DAV:error Xml element containing the exceptions class and the - * message as child elements. - * - * @return Xml representation of this exception. - * @see org.apache.jackrabbit.webdav.xml.XmlSerializable#toXml(Document) - * @param document - */ - @Override - public Element toXml(Document document) { - Element error = DomUtil.createElement(document, XML_ERROR, DavConstants.NAMESPACE); - Element excep = DomUtil.createElement(document, "exception", ItemResourceConstants.NAMESPACE); - DomUtil.addChildElement(excep, "class", ItemResourceConstants.NAMESPACE, exceptionClass.getName()); - DomUtil.addChildElement(excep, "message", ItemResourceConstants.NAMESPACE, getMessage()); - error.appendChild(excep); - return error; - } -} Property changes on: jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/JcrDavException.java ___________________________________________________________________ Deleted: svn Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/JcrDavSession.java =================================================================== --- jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/JcrDavSession.java (revision 1907912) +++ jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/JcrDavSession.java (nonexistent) @@ -1,140 +0,0 @@ -/* - * 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.webdav.jcr; - -import org.apache.jackrabbit.webdav.DavException; -import org.apache.jackrabbit.webdav.DavServletResponse; -import org.apache.jackrabbit.webdav.DavSession; -import org.apache.jackrabbit.webdav.jcr.lock.LockTokenMapper; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import javax.jcr.RepositoryException; -import javax.jcr.Session; -import java.util.HashSet; - -/** - * JcrDavSession specific base implementation of the - * DavSession interface, which simply wraps a {@link Session} - * object. This implementation adds a utility method that allows to - * {@link #getRepositorySession() unwrap} the underlying repository session. - *
- * Note, that in this basic implementation the following methods are simply - * forwarded to the corresponding call on Session: - *
    - *
  • {@link #getLockTokens()} => {@link Session#getLockTokens()}
  • - *
  • {@link #addLockToken(String)} => {@link Session#addLockToken(String)}
  • - *
  • {@link #removeLockToken(String)} => {@link Session#removeLockToken(String)}
  • - *
- * Subclasses may overwrite or extend this behaviour. - */ -public abstract class JcrDavSession implements DavSession { - - private static Logger log = LoggerFactory.getLogger(JcrDavSession.class); - - /** the underlying jcr session */ - private final Session session; - - /** the lock tokens of this session */ - private final HashSet lockTokens = new HashSet(); - - /** - * - * @param session - */ - protected JcrDavSession(Session session) { - this.session = session; - } - - /** - * - * @param davSession - * @throws DavException - */ - public static void checkImplementation(DavSession davSession) throws DavException { - if (!(davSession instanceof JcrDavSession)) { - throw new DavException(DavServletResponse.SC_INTERNAL_SERVER_ERROR, "JCR specific DavSession expected. Found: " + davSession); - } - } - - /** - * - * @param davSession - * @return - * @throws DavException - */ - public static Session getRepositorySession(DavSession davSession) throws DavException { - checkImplementation(davSession); - return ((JcrDavSession)davSession).getRepositorySession(); - } - - /** - * Unwrap the {@link Session repository session} object. - * - * @return the session object wrapped by this DavSession - */ - public Session getRepositorySession() { - return session; - } - - //---------------------------------------------------------< DavSession >--- - /** - * - * @param token - * @see DavSession#addLockToken(String) - */ - @Override - public void addLockToken(String token) { - if (!LockTokenMapper.isForSessionScopedLock(token)) { - try { - session.getWorkspace().getLockManager().addLockToken(LockTokenMapper.getJcrLockToken(token)); - } - catch (RepositoryException ex) { - log.debug("trying to add lock token " + token + " to session", ex); - } - } - lockTokens.add(token); - } - - /** - * - * @return - * @see DavSession#getLockTokens() - */ - @Override - public String[] getLockTokens() { - return lockTokens.toArray(new String[lockTokens.size()]); - } - - /** - * - * @param token - * @see DavSession#removeLockToken(String) - */ - @Override - public void removeLockToken(String token) { - if (!LockTokenMapper.isForSessionScopedLock(token)) { - try { - session.getWorkspace().getLockManager().removeLockToken(LockTokenMapper.getJcrLockToken(token)); - } - catch (RepositoryException ex) { - log.debug("trying to remove lock token " + token + " to session", ex); - } - } - lockTokens.remove(token); - } -} Property changes on: jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/JcrDavSession.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Deleted: svn:keywords ## -1 +0,0 ## -author date id revision url \ No newline at end of property Index: jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/JcrValueType.java =================================================================== --- jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/JcrValueType.java (revision 1907912) +++ jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/JcrValueType.java (nonexistent) @@ -1,25 +0,0 @@ -/* - * 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.webdav.jcr; - -/** JcrValueType... - * - * @deprecated As of Jackrabbit 2.2. Please Use {@link org.apache.jackrabbit.commons.webdav.JcrValueType} instead. - */ -public final class JcrValueType extends org.apache.jackrabbit.commons.webdav.JcrValueType { - -} \ No newline at end of file Property changes on: jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/JcrValueType.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Deleted: svn:keywords ## -1 +0,0 ## -author date id revision url \ No newline at end of property Index: jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/RootCollection.java =================================================================== --- jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/RootCollection.java (revision 1907912) +++ jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/RootCollection.java (nonexistent) @@ -1,310 +0,0 @@ -/* - * 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.webdav.jcr; - -import java.io.IOException; -import java.io.OutputStreamWriter; -import java.io.PrintWriter; -import java.util.ArrayList; -import java.util.Date; -import java.util.List; -import javax.jcr.Repository; -import javax.jcr.RepositoryException; -import javax.jcr.Session; -import javax.jcr.Workspace; - -import org.apache.jackrabbit.util.Text; -import org.apache.jackrabbit.webdav.DavException; -import org.apache.jackrabbit.webdav.DavResource; -import org.apache.jackrabbit.webdav.DavResourceFactory; -import org.apache.jackrabbit.webdav.DavResourceIterator; -import org.apache.jackrabbit.webdav.DavResourceIteratorImpl; -import org.apache.jackrabbit.webdav.DavResourceLocator; -import org.apache.jackrabbit.webdav.DavServletResponse; -import org.apache.jackrabbit.webdav.io.InputContext; -import org.apache.jackrabbit.webdav.io.OutputContext; -import org.apache.jackrabbit.webdav.jcr.security.JcrSupportedPrivilegesProperty; -import org.apache.jackrabbit.webdav.jcr.security.SecurityUtils; -import org.apache.jackrabbit.webdav.property.DavProperty; -import org.apache.jackrabbit.webdav.property.DavPropertyName; -import org.apache.jackrabbit.webdav.search.SearchResource; -import org.apache.jackrabbit.webdav.security.SecurityConstants; -import org.apache.jackrabbit.webdav.version.DeltaVResource; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * RootCollection represent the WebDAV root resource that does not - * represent any repository item. A call to getMembers() returns a - * DavResourceIterator containing only workspace resources - * resources, thus revealing the names of the accessible JCR workspaces. - */ -public class RootCollection extends AbstractResource { - - private static Logger log = LoggerFactory.getLogger(RootCollection.class); - - /** - * Create a new RootCollection. - * - * @param locator - * @param session - * @param factory - */ - protected RootCollection(DavResourceLocator locator, JcrDavSession session, - DavResourceFactory factory) { - super(locator, session, factory); - - // initialize the supported locks and reports - initLockSupport(); - initSupportedReports(); - } - - //--------------------------------------------------------< DavResource >--- - /** - * Returns a string listing the METHODS for this resource as it - * is required for the "Allow" response header. - * - * @return string listing the METHODS allowed - * @see org.apache.jackrabbit.webdav.DavResource#getSupportedMethods() - */ - @Override - public String getSupportedMethods() { - StringBuilder sb = new StringBuilder(DavResource.METHODS); - sb.append(", "); - sb.append(DeltaVResource.METHODS_INCL_MKWORKSPACE); - sb.append(", "); - sb.append(SearchResource.METHODS); - return sb.toString(); - } - - /** - * Returns true - * - * @return true - * @see org.apache.jackrabbit.webdav.DavResource#exists() - */ - @Override - public boolean exists() { - return true; - } - - @Override - public DavProperty getProperty(DavPropertyName name) { - DavProperty prop = super.getProperty(name); - if (prop == null) { - try { - if (SecurityConstants.SUPPORTED_PRIVILEGE_SET.equals(name)) { - prop = new JcrSupportedPrivilegesProperty(getRepositorySession()).asDavProperty(); - } - } catch (RepositoryException e) { - log.error("Failed to build SupportedPrivilegeSet property: " + e.getMessage()); - } - } - return prop; - } - - /** - * Returns true - * - * @return true - * @see org.apache.jackrabbit.webdav.DavResource#isCollection() - */ - @Override - public boolean isCollection() { - return true; - } - - /** - * Returns an empty string. - * - * @return empty string - * @see org.apache.jackrabbit.webdav.DavResource#getDisplayName() - */ - @Override - public String getDisplayName() { - return ""; - } - - /** - * Always returns 'now' - * - * @return - * @see org.apache.jackrabbit.webdav.DavResource#getModificationTime() - */ - @Override - public long getModificationTime() { - return new Date().getTime(); - } - - /** - * Sets content lengths to '0' and retrieves the modification time. - * - * @param outputContext - * @throws IOException - * @see DavResource#spool(org.apache.jackrabbit.webdav.io.OutputContext) - */ - @Override - public void spool(OutputContext outputContext) throws IOException { - if (outputContext.hasStream()) { - Session session = getRepositorySession(); - Repository rep = session.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); - String repostr = repName + " " + repVersion; - - StringBuilder sb = new StringBuilder(); - sb.append(""); - sb.append(repostr); - sb.append(""); - sb.append("

").append(repostr).append("

"); - sb.append("

Available Workspace Resources:


Powered by ").append(repName); - sb.append(" ").append(repVersion); - sb.append(""); - - outputContext.setContentLength(sb.length()); - outputContext.setModificationTime(getModificationTime()); - PrintWriter writer = new PrintWriter(new OutputStreamWriter(outputContext.getOutputStream(), "utf8")); - writer.print(sb.toString()); - writer.close(); - } else { - outputContext.setContentLength(0); - outputContext.setModificationTime(getModificationTime()); - } - } - - /** - * Always returns null - * - * @return null for the root resource is not internal member - * of any resource. - * @see org.apache.jackrabbit.webdav.DavResource#getCollection() - */ - @Override - public DavResource getCollection() { - return null; - } - - /** - * Throws exception: 403 Forbidden. - * @see DavResource#addMember(DavResource, InputContext) - */ - @Override - public void addMember(DavResource resource, InputContext inputContext) throws DavException { - throw new DavException(DavServletResponse.SC_FORBIDDEN); - } - - /** - * Returns an iterator over the member resources, which are all - * workspace resources available. - * - * @return members of this collection - * @see org.apache.jackrabbit.webdav.DavResource#getMembers() - */ - @Override - public DavResourceIterator getMembers() { - List memberList = new ArrayList(); - try { - String[] wsNames = getRepositorySession().getWorkspace().getAccessibleWorkspaceNames(); - for (String wsName : wsNames) { - String wspPath = "/" + wsName; - DavResourceLocator childLoc = getLocator().getFactory().createResourceLocator(getLocator().getPrefix(), wspPath, wspPath); - memberList.add(createResourceFromLocator(childLoc)); - } - } catch (RepositoryException e) { - log.error(e.getMessage()); - } catch (DavException e) { - // should never occur - log.error(e.getMessage()); - } - return new DavResourceIteratorImpl(memberList); - } - - /** - * Calls {@link Workspace#deleteWorkspace(String)} for the workspace with - * the name as indicated by the specified member. - * - * @see DavResource#removeMember(org.apache.jackrabbit.webdav.DavResource) - */ - @Override - public void removeMember(DavResource member) throws DavException { - Workspace wsp = getRepositorySession().getWorkspace(); - String name = Text.getName(member.getResourcePath()); - try { - wsp.deleteWorkspace(name); - } catch (RepositoryException e) { - throw new JcrDavException(e); - } - } - - //-----------------------------------------------------< DeltaVResource >--- - /** - * @see DeltaVResource#addWorkspace(org.apache.jackrabbit.webdav.DavResource) - */ - @Override - public void addWorkspace(DavResource workspace) throws DavException { - Workspace wsp = getRepositorySession().getWorkspace(); - String name = workspace.getDisplayName(); - try { - wsp.createWorkspace(name); - } catch (RepositoryException e) { - throw new JcrDavException(e); - } - } - - //-------------------------------------------------------------------------- - /** - * @see AbstractResource#initLockSupport() - */ - @Override - protected void initLockSupport() { - // no locking supported - } - - /** - * Since the root resource does not represent a repository item and therefore - * is not member of a workspace resource, this method always returns - * null. - * - * @return null - * @see AbstractResource#getWorkspaceHref() - */ - @Override - protected String getWorkspaceHref() { - return null; - } - - @Override - protected void initPropertyNames() { - super.initPropertyNames(); - if (SecurityUtils.supportsAccessControl(getRepositorySession())) { - names.add(SecurityConstants.SUPPORTED_PRIVILEGE_SET); - } - } -} Property changes on: jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/RootCollection.java ___________________________________________________________________ Deleted: svn Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/VersionControlledItemCollection.java =================================================================== --- jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/VersionControlledItemCollection.java (revision 1907912) +++ jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/VersionControlledItemCollection.java (nonexistent) @@ -1,704 +0,0 @@ -/* - * 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.webdav.jcr; - -import org.apache.jackrabbit.JcrConstants; -import org.apache.jackrabbit.webdav.DavConstants; -import org.apache.jackrabbit.webdav.DavException; -import org.apache.jackrabbit.webdav.DavLocatorFactory; -import org.apache.jackrabbit.webdav.DavResource; -import org.apache.jackrabbit.webdav.DavResourceFactory; -import org.apache.jackrabbit.webdav.DavResourceLocator; -import org.apache.jackrabbit.webdav.DavServletResponse; -import org.apache.jackrabbit.webdav.MultiStatus; -import org.apache.jackrabbit.webdav.MultiStatusResponse; -import org.apache.jackrabbit.webdav.jcr.property.JcrDavPropertyNameSet; -import org.apache.jackrabbit.webdav.property.DavPropertyName; -import org.apache.jackrabbit.webdav.property.DefaultDavProperty; -import org.apache.jackrabbit.webdav.property.HrefProperty; -import org.apache.jackrabbit.webdav.property.DavProperty; -import org.apache.jackrabbit.webdav.property.PropEntry; -import org.apache.jackrabbit.webdav.version.LabelInfo; -import org.apache.jackrabbit.webdav.version.MergeInfo; -import org.apache.jackrabbit.webdav.version.UpdateInfo; -import org.apache.jackrabbit.webdav.version.VersionControlledResource; -import org.apache.jackrabbit.webdav.version.VersionHistoryResource; -import org.apache.jackrabbit.webdav.version.VersionResource; -import org.apache.jackrabbit.webdav.version.VersionableResource; -import org.apache.jackrabbit.webdav.version.report.ReportType; -import org.apache.jackrabbit.webdav.version.report.SupportedReportSetProperty; -import org.apache.jackrabbit.webdav.xml.DomUtil; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.w3c.dom.Element; - -import javax.jcr.Item; -import javax.jcr.Node; -import javax.jcr.NodeIterator; -import javax.jcr.RepositoryException; -import javax.jcr.Session; -import javax.jcr.Value; -import javax.jcr.ValueFormatException; -import javax.jcr.observation.EventListener; -import javax.jcr.version.Version; -import javax.jcr.version.VersionHistory; -import javax.jcr.version.VersionManager; -import java.util.List; -import java.util.Collections; - -/** - * VersionControlledItemCollection represents a JCR node item and - * covers all functionality related to versioning of {@link Node}s. - * - * @see Node - */ -public class VersionControlledItemCollection extends DefaultItemCollection - implements VersionControlledResource { - - private static Logger log = LoggerFactory.getLogger(VersionControlledItemCollection.class); - - /** - * Create a new VersionControlledItemCollection. - * - * @param locator - * @param session - * @param factory - * @param item - */ - public VersionControlledItemCollection(DavResourceLocator locator, - JcrDavSession session, - DavResourceFactory factory, - Item item) { - super(locator, session, factory, item); - if (exists() && !(item instanceof Node)) { - throw new IllegalArgumentException("A collection resource can not be constructed from a Property item."); - } - } - - //----------------------------------------------< DavResource interface >--- - /** - * Return a comma separated string listing the supported method names. - * - * @return the supported method names. - * @see org.apache.jackrabbit.webdav.DavResource#getSupportedMethods() - */ - @Override - public String getSupportedMethods() { - StringBuffer sb = new StringBuffer(super.getSupportedMethods()); - // Versioning support - sb.append(", ").append(VersionableResource.METHODS); - if (isVersionControlled()) { - try { - if (((Node)item).isCheckedOut()) { - sb.append(", ").append(VersionControlledResource.methods_checkedOut); - } else { - sb.append(", ").append(VersionControlledResource.methods_checkedIn); - } - } catch (RepositoryException e) { - // should not occur. - log.error(e.getMessage()); - } - } - return sb.toString(); - } - - @Override - public DavProperty getProperty(DavPropertyName name) { - DavProperty prop = super.getProperty(name); - if (prop == null && isVersionControlled()) { - Node n = (Node) item; - // properties defined by RFC 3253 for version-controlled resources - // workspace property already set in AbstractResource.initProperties() - try { - if (VERSION_HISTORY.equals(name)) { - // DAV:version-history (computed) - String vhHref = getLocatorFromItem(n.getVersionHistory()).getHref(true); - prop = new HrefProperty(VERSION_HISTORY, vhHref, true); - } else if (CHECKED_OUT.equals(name) && n.isCheckedOut()) { - // DAV:checked-out property (protected) - String baseVHref = getLocatorFromItem(n.getBaseVersion()).getHref(true); - prop = new HrefProperty(CHECKED_OUT, baseVHref, true); - } else if (CHECKED_IN.equals(name) && !n.isCheckedOut()) { - // DAV:checked-in property (protected) - String baseVHref = getLocatorFromItem(n.getBaseVersion()).getHref(true); - prop = new HrefProperty(CHECKED_IN, baseVHref, true); - } - } catch (RepositoryException e) { - log.error(e.getMessage()); - } - } - - return prop; - } - - /** - * @param changeList - * @throws DavException - * @see DefaultItemCollection#alterProperties(List) - * for additional description of non-compliant behaviour. - */ - @Override - public MultiStatusResponse alterProperties(List changeList) throws DavException { - /* first resolve merge conflict since they cannot be handled by - setting property values in jcr (and are persisted immediately). - NOTE: this violates RFC 2518 that requires that proppatch - is processed in the order entries are present in the xml and that - required that no changes must be persisted if any set/remove fails. - */ - // TODO: solve violation of RFC 2518 - resolveMergeConflict(changeList); - // alter other properties only if merge-conflicts could be handled - return super.alterProperties(changeList); - } - - /** - * Resolve one or multiple merge conflicts present on this resource. Please - * note that the 'setProperties' or 'removeProperties' set my contain additional - * resource properties, that need to be changed. Those properties are left - * untouched, whereas the {@link #AUTO_MERGE_SET DAV:auto-merge-set}, is - * removed from the list upon successful resolution of a merge conflict.
- * If the removeProperties or setProperties set do not contain the mentioned - * merge conflict resource properties or if the value of those properties do - * not allow for a resolution of an existing merge conflict, this method - * returns silently. - * - * @param changeList - * @throws org.apache.jackrabbit.webdav.DavException - * @see Node#doneMerge(Version) - * @see Node#cancelMerge(Version) - */ - private void resolveMergeConflict(List changeList) throws DavException { - if (!exists()) { - throw new DavException(DavServletResponse.SC_NOT_FOUND); - } - try { - Node n = (Node) item; - VersionManager vMgr = getVersionManager(); - String path = item.getPath(); - - DavProperty autoMergeSet = null; - DavProperty predecessorSet = null; - /* find DAV:auto-merge-set entries. If none exists no attempt is made - to resolve merge conflict > return silently */ - for (int i = 0; i < changeList.size(); i++) { - PropEntry propEntry = changeList.get(i); - // If DAV:auto-merge-set is DavPropertyName all remaining merge - // conflicts are resolved with 'cancel' - if (propEntry instanceof DavPropertyName && AUTO_MERGE_SET.equals(propEntry)) { - // retrieve the current jcr:mergeFailed property values - if (!n.hasProperty(JcrConstants.JCR_MERGEFAILED)) { - throw new DavException(DavServletResponse.SC_CONFLICT, "Attempt to resolve non-existing merge conflicts."); - } - Value[] mergeFailed = n.getProperty(JcrConstants.JCR_MERGEFAILED).getValues(); - for (Value value : mergeFailed) { - vMgr.cancelMerge(path, (Version) getRepositorySession().getNodeByIdentifier(value.getString())); - } - // remove this entry from the changeList - changeList.remove(propEntry); - } else if (propEntry instanceof DavProperty) { - if (AUTO_MERGE_SET.equals(((DavProperty)propEntry).getName())) { - autoMergeSet = (DavProperty) propEntry; - } else if (PREDECESSOR_SET.equals(((DavProperty)propEntry).getName())) { - predecessorSet = (DavProperty) propEntry; - } - } - } - - // If DAV:auto-merge-set is a DavProperty merge conflicts need to be - // resolved individually according to the DAV:predecessor-set property. - if (autoMergeSet != null) { - // retrieve the current jcr:mergeFailed property values - if (!n.hasProperty(JcrConstants.JCR_MERGEFAILED)) { - throw new DavException(DavServletResponse.SC_CONFLICT, "Attempt to resolve non-existing merge conflicts."); - } - - List mergeset = new HrefProperty(autoMergeSet).getHrefs(); - List predecL; - if (predecessorSet == null) { - predecL = Collections.emptyList(); - } else { - predecL = new HrefProperty(predecessorSet).getHrefs(); - } - - Session session = getRepositorySession(); - // loop over the mergeFailed values (versions) and test whether they are - // removed from the DAV:auto-merge-set thus indicating resolution. - Value[] mergeFailed = n.getProperty(JcrConstants.JCR_MERGEFAILED).getValues(); - for (Value value : mergeFailed) { - // build version-href from each entry in the jcr:mergeFailed property - // in order to be able to compare to the entries in the HrefProperty. - Version version = (Version) session.getNodeByIdentifier(value.getString()); - String href = getLocatorFromItem(version).getHref(true); - - // Test if that version has been removed from the merge-set. - // thus indicating that this merge conflict needs to be resolved. - if (!mergeset.contains(href)) { - // If the conflict value has been moved over from DAV:auto-merge-set - // to the predecessor-set, resolution with 'doneMerge' is - // appropriate. If the value has been removed from the - // merge-set but not added to the predecessors 'cancelMerge' - // must be called. - if (predecL.contains(href)) { - vMgr.doneMerge(path, version); - } else { - vMgr.cancelMerge(path, version); - } - } - } - // after successful resolution of merge-conflicts according to - // DAV:auto-merge-set and DAV:predecessor-set remove these entries - // from the changeList. - changeList.remove(autoMergeSet); - if (predecessorSet != null) { - changeList.remove(predecessorSet); - } - } - } catch (RepositoryException e) { - throw new JcrDavException(e); - } - } - - //--------------------------------------< VersionableResource interface >--- - /** - * Adds version control to this resource. If the resource is already under - * version control, this method has no effect. - * - * @throws org.apache.jackrabbit.webdav.DavException if this resource does not - * exist yet or if an error occurs while making the underlying node versionable. - * @see org.apache.jackrabbit.webdav.version.VersionableResource#addVersionControl() - */ - @Override - public void addVersionControl() throws DavException { - if (!exists()) { - throw new DavException(DavServletResponse.SC_NOT_FOUND); - } - if (!isVersionControlled()) { - try { - ((Node)item).addMixin(JcrConstants.MIX_VERSIONABLE); - item.save(); - } catch (RepositoryException e) { - throw new JcrDavException(e); - } - } // else: is already version controlled -> ignore - } - - //--------------------------------< VersionControlledResource interface >--- - /** - * Calls {@link javax.jcr.Node#checkin()} on the underlying repository node. - * - * @throws org.apache.jackrabbit.webdav.DavException - * @see org.apache.jackrabbit.webdav.version.VersionControlledResource#checkin() - */ - @Override - public String checkin() throws DavException { - if (!exists()) { - throw new DavException(DavServletResponse.SC_NOT_FOUND); - } - if (!isVersionControlled()) { - throw new DavException(DavServletResponse.SC_METHOD_NOT_ALLOWED); - } - try { - Version v = getVersionManager().checkin(item.getPath()); - String versionHref = getLocatorFromItem(v).getHref(true); - return versionHref; - } catch (RepositoryException e) { - // UnsupportedRepositoryException should not occur - throw new JcrDavException(e); - } - } - - /** - * Calls {@link javax.jcr.Node#checkout()} on the underlying repository node. - * - * @throws org.apache.jackrabbit.webdav.DavException - * @see org.apache.jackrabbit.webdav.version.VersionControlledResource#checkout() - */ - @Override - public void checkout() throws DavException { - if (!exists()) { - throw new DavException(DavServletResponse.SC_NOT_FOUND); - } - if (!isVersionControlled()) { - throw new DavException(DavServletResponse.SC_METHOD_NOT_ALLOWED); - } - try { - getVersionManager().checkout(item.getPath()); - } catch (RepositoryException e) { - // UnsupportedRepositoryException should not occur - throw new JcrDavException(e); - } - } - - /** - * Not implemented. Always throws a DavException with error code - * {@link org.apache.jackrabbit.webdav.DavServletResponse#SC_NOT_IMPLEMENTED}. - * - * @throws org.apache.jackrabbit.webdav.DavException - * @see org.apache.jackrabbit.webdav.version.VersionControlledResource#uncheckout() - */ - @Override - public void uncheckout() throws DavException { - throw new DavException(DavServletResponse.SC_NOT_IMPLEMENTED); - } - - /** - * Perform an update on this resource. Depending on the format of the updateInfo - * this is translated to one of the following methods defined by the JCR API: - *
    - *
  • {@link Node#restore(javax.jcr.version.Version, boolean)}
  • - *
  • {@link Node#restore(javax.jcr.version.Version, String, boolean)}
  • - *
  • {@link Node#restoreByLabel(String, boolean)}
  • - *
  • {@link Node#update(String)}
  • - *
- *

- * Limitation: note that the MultiStatus returned by this method - * will not list any nodes that have been removed due to an Uuid conflict. - * - * @param updateInfo - * @return - * @throws org.apache.jackrabbit.webdav.DavException - * @see org.apache.jackrabbit.webdav.version.VersionControlledResource#update(org.apache.jackrabbit.webdav.version.UpdateInfo) - */ - //TODO: with jcr the node must not be versionable in order to perform Node.update. - @Override - public MultiStatus update(UpdateInfo updateInfo) throws DavException { - if (updateInfo == null) { - throw new DavException(DavServletResponse.SC_BAD_REQUEST, "Valid update request body required."); - } - if (!exists()) { - throw new DavException(DavServletResponse.SC_NOT_FOUND); - } - - MultiStatus ms = new MultiStatus(); - try { - Node node = (Node)item; - Element udElem = updateInfo.getUpdateElement(); - boolean removeExisting = DomUtil.hasChildElement(udElem, XML_REMOVEEXISTING, NAMESPACE); - - // register eventListener in order to be able to report the modified resources. - EventListener el = new EListener(updateInfo.getPropertyNameSet(), ms); - registerEventListener(el, node.getPath()); - - // perform the update/restore according to the update info - if (updateInfo.getVersionHref() != null) { - String[] hrefs = updateInfo.getVersionHref(); - if (hrefs.length != 1) { - throw new DavException(DavServletResponse.SC_BAD_REQUEST, "Invalid update request body missing version href or containing multiple version hrefs."); - } - - final String href = normalizeResourceHref(hrefs[0]); - String versionPath = getLocatorFromHref(href).getRepositoryPath(); - String versionName = getItemName(versionPath); - - String relPath = DomUtil.getChildText(udElem, XML_RELPATH, NAMESPACE); - if (relPath == null) { - // restore version by name - node.restore(versionName, removeExisting); - } else if (node.hasNode(relPath)) { - Version v = node.getNode(relPath).getVersionHistory().getVersion(versionName); - node.restore(v, relPath, removeExisting); - } else { - Version v = (Version) getRepositorySession().getNode(versionPath); - node.restore(v, relPath, removeExisting); - } - - } else if (updateInfo.getLabelName() != null) { - String[] labels = updateInfo.getLabelName(); - if (labels.length != 1) { - throw new DavException(DavServletResponse.SC_BAD_REQUEST, "Invalid update request body: Multiple labels specified."); - } - node.restoreByLabel(labels[0], removeExisting); - - } else if (updateInfo.getWorkspaceHref() != null) { - String href = normalizeResourceHref(obtainAbsolutePathFromUri(updateInfo.getWorkspaceHref())); - String workspaceName = getLocatorFromHref(href).getWorkspaceName(); - node.update(workspaceName); - } else { - throw new DavException(DavServletResponse.SC_BAD_REQUEST, "Invalid update request body."); - } - - // unregister the event listener again - unregisterEventListener(el); - - } catch (RepositoryException e) { - throw new JcrDavException(e); - } - return ms; - } - - /** - * Merge the repository node represented by this resource according to the - * information present in the given {@link MergeInfo} object. - * - * @param mergeInfo - * @return MultiStatus recording all repository items modified - * by this merge call as well as the resources that a client must modify to - * complete the merge (see RFC 3253) - * @throws org.apache.jackrabbit.webdav.DavException - * @see org.apache.jackrabbit.webdav.version.VersionControlledResource#merge(org.apache.jackrabbit.webdav.version.MergeInfo) - * @see Node#merge(String, boolean) - */ - //TODO: with jcr the node must not be versionable in order to perform Node.merge - @Override - public MultiStatus merge(MergeInfo mergeInfo) throws DavException { - if (mergeInfo == null) { - throw new DavException(DavServletResponse.SC_BAD_REQUEST); - } - if (!exists()) { - throw new DavException(DavServletResponse.SC_NOT_FOUND); - } - - MultiStatus ms = new MultiStatus(); - try { - // NOTE: RFC requires that all modified resources are reported in the - // multistatus response. this doesn't work however with the remoting - // there is no way to distinguish the 'failedId's from any other - // resources that got modified by this merge operation -> omitted. - - // todo: RFC allows multiple href elements inside the DAV:source element - final String href = normalizeResourceHref(mergeInfo.getSourceHrefs()[0]); - String workspaceName = getLocatorFromHref(href).getWorkspaceName(); - - String depth = DomUtil.getChildTextTrim(mergeInfo.getMergeElement(), DavConstants.XML_DEPTH, DavConstants.NAMESPACE); - boolean isShallow = "0".equals(depth); - - NodeIterator failed = getVersionManager().merge(item.getPath(), workspaceName, !mergeInfo.isNoAutoMerge(), isShallow); - - // add resources to the multistatus, that failed to be merged - while (failed.hasNext()) { - Node failedNode = failed.nextNode(); - DavResourceLocator loc = getLocatorFromItem(failedNode); - DavResource res = createResourceFromLocator(loc); - ms.addResponse(new MultiStatusResponse(res, mergeInfo.getPropertyNameSet())); - } - - } catch (RepositoryException e) { - throw new JcrDavException(e); - } - - return ms; - } - - /** - * Modify the labels present with the versions of this resource. - * - * @param labelInfo - * @throws DavException - * @see VersionHistory#addVersionLabel(String, String, boolean) - * @see VersionHistory#removeVersionLabel(String) - */ - @Override - public void label(LabelInfo labelInfo) throws DavException { - if (labelInfo == null) { - throw new DavException(DavServletResponse.SC_BAD_REQUEST, "Valid label request body required."); - } - if (!exists()) { - throw new DavException(DavServletResponse.SC_NOT_FOUND); - } - - try { - if (!isVersionControlled() || ((Node)item).isCheckedOut()) { - throw new DavException(DavServletResponse.SC_PRECONDITION_FAILED, "A LABEL request may only be applied to a version-controlled, checked-in resource."); - } - DavResource[] resArr = this.getReferenceResources(CHECKED_IN); - if (resArr.length == 1 && resArr[0] instanceof VersionResource) { - ((VersionResource)resArr[0]).label(labelInfo); - } else { - throw new DavException(DavServletResponse.SC_INTERNAL_SERVER_ERROR, "DAV:checked-in property on '" + getHref() + "' did not point to a single VersionResource."); - } - } catch (RepositoryException e) { - throw new JcrDavException(e); - } - } - - /** - * Returns the {@link VersionHistory} associated with the repository node. - * If the node is not versionable an exception is thrown. - * - * @return the {@link VersionHistoryResource} associated with this resource. - * @throws org.apache.jackrabbit.webdav.DavException - * @see org.apache.jackrabbit.webdav.version.VersionControlledResource#getVersionHistory() - * @see javax.jcr.Node#getVersionHistory() - */ - @Override - public VersionHistoryResource getVersionHistory() throws DavException { - if (!exists()) { - throw new DavException(DavServletResponse.SC_NOT_FOUND); - } - - try { - VersionHistory vh = ((Node)item).getVersionHistory(); - DavResourceLocator loc = getLocatorFromItem(vh); - return (VersionHistoryResource) createResourceFromLocator(loc); - } catch (RepositoryException e) { - throw new JcrDavException(e); - } - } - - //-------------------------------------------------------------------------- - /** - * Define the set of reports supported by this resource. - * - * @see SupportedReportSetProperty - */ - @Override - protected void initSupportedReports() { - super.initSupportedReports(); - if (exists()) { - supportedReports.addReportType(ReportType.LOCATE_BY_HISTORY); - if (this.isVersionControlled()) { - supportedReports.addReportType(ReportType.VERSION_TREE); - } - } - } - - @Override - protected void initPropertyNames() { - super.initPropertyNames(); - - if (isVersionControlled()) { - names.addAll(JcrDavPropertyNameSet.VERSIONABLE_SET); - - Node n = (Node) item; - try { - if (n.isCheckedOut()) { - names.add(CHECKED_OUT); - if (n.hasProperty(JcrConstants.JCR_PREDECESSORS)) { - names.add(PREDECESSOR_SET); - } - if (n.hasProperty(JcrConstants.JCR_MERGEFAILED)) { - names.add(AUTO_MERGE_SET); - } - // todo: checkout-fork, checkin-fork - } else { - names.add(CHECKED_IN); - } - } catch (RepositoryException e) { - log.warn(e.getMessage()); - } - } - } - - /** - * Fill the property set for this resource. - */ - @Override - protected void initProperties() { - super.initProperties(); - if (isVersionControlled()) { - Node n = (Node)item; - // properties defined by RFC 3253 for version-controlled resources - // workspace property already set in AbstractResource.initProperties() - try { - // DAV:version-history (computed) - String vhHref = getLocatorFromItem(n.getVersionHistory()).getHref(true); - properties.add(new HrefProperty(VERSION_HISTORY, vhHref, true)); - - // DAV:auto-version property: there is no auto version, explicit CHECKOUT is required. - properties.add(new DefaultDavProperty(AUTO_VERSION, null, false)); - - String baseVHref = getLocatorFromItem(n.getBaseVersion()).getHref(true); - if (n.isCheckedOut()) { - // DAV:predecessors property - if (n.hasProperty(JcrConstants.JCR_PREDECESSORS)) { - Value[] predec = n.getProperty(JcrConstants.JCR_PREDECESSORS).getValues(); - addHrefProperty(PREDECESSOR_SET, predec, false); - } - // DAV:auto-merge-set property. NOTE: the DAV:merge-set - // never occurs, because merging without bestEffort flag - // being set results in an exception on failure. - if (n.hasProperty(JcrConstants.JCR_MERGEFAILED)) { - Value[] mergeFailed = n.getProperty(JcrConstants.JCR_MERGEFAILED).getValues(); - addHrefProperty(AUTO_MERGE_SET, mergeFailed, false); - } - // todo: checkout-fork, checkin-fork - } - } catch (RepositoryException e) { - log.error(e.getMessage()); - } - } - } - - /** - * Add a {@link org.apache.jackrabbit.webdav.property.HrefProperty} with the - * specified property name and values. - * - * @param name - * @param values Array of {@link Value}s. - * @param isProtected - * @throws javax.jcr.ValueFormatException - * @throws IllegalStateException - * @throws javax.jcr.RepositoryException - */ - private void addHrefProperty(DavPropertyName name, Value[] values, - boolean isProtected) - throws ValueFormatException, IllegalStateException, RepositoryException { - Node[] nodes = new Node[values.length]; - for (int i = 0; i < values.length; i++) { - nodes[i] = getRepositorySession().getNodeByIdentifier(values[i].getString()); - } - addHrefProperty(name, nodes, isProtected); - } - - /** - * @return true, if this resource represents an existing repository node - * that has the mixin nodetype 'mix:versionable' set. - */ - private boolean isVersionControlled() { - boolean vc = false; - if (exists()) { - try { - vc = ((Node) item).isNodeType(JcrConstants.MIX_VERSIONABLE); - } catch (RepositoryException e) { - log.warn(e.getMessage()); - } - } - return vc; - } - - /** - * Build a new locator for the given href. - * - * @param href - * @return - */ - private DavResourceLocator getLocatorFromHref(String href) { - DavLocatorFactory f = getLocator().getFactory(); - String prefix = getLocator().getPrefix(); - return f.createResourceLocator(prefix, href); - } - - private VersionManager getVersionManager() throws RepositoryException { - return getRepositorySession().getWorkspace().getVersionManager(); - } - - private static String obtainAbsolutePathFromUri(String uri) { - try { - java.net.URI u = new java.net.URI(uri); - StringBuilder sb = new StringBuilder(); - sb.append(u.getRawPath()); - if (u.getRawQuery() != null) { - sb.append("?").append(u.getRawQuery()); - } - return sb.toString(); - } - catch (java.net.URISyntaxException ex) { - log.warn("parsing " + uri, ex); - return uri; - } - } -} Property changes on: jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/VersionControlledItemCollection.java ___________________________________________________________________ Deleted: svn Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/WorkspaceResourceImpl.java =================================================================== --- jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/WorkspaceResourceImpl.java (revision 1907912) +++ jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/WorkspaceResourceImpl.java (nonexistent) @@ -1,627 +0,0 @@ -/* - * 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.webdav.jcr; - -import org.apache.jackrabbit.commons.cnd.CompactNodeTypeDefReader; -import org.apache.jackrabbit.commons.cnd.CompactNodeTypeDefWriter; -import org.apache.jackrabbit.commons.cnd.DefinitionBuilderFactory; -import org.apache.jackrabbit.commons.cnd.ParseException; -import org.apache.jackrabbit.commons.cnd.TemplateBuilderFactory; -import org.apache.jackrabbit.commons.webdav.AtomFeedConstants; -import org.apache.jackrabbit.webdav.DavException; -import org.apache.jackrabbit.webdav.DavMethods; -import org.apache.jackrabbit.webdav.DavResource; -import org.apache.jackrabbit.webdav.DavResourceFactory; -import org.apache.jackrabbit.webdav.DavResourceIterator; -import org.apache.jackrabbit.webdav.DavResourceIteratorImpl; -import org.apache.jackrabbit.webdav.DavResourceLocator; -import org.apache.jackrabbit.webdav.DavServletResponse; -import org.apache.jackrabbit.webdav.MultiStatus; -import org.apache.jackrabbit.webdav.MultiStatusResponse; -import org.apache.jackrabbit.webdav.io.InputContext; -import org.apache.jackrabbit.webdav.io.OutputContext; -import org.apache.jackrabbit.webdav.jcr.property.JcrDavPropertyNameSet; -import org.apache.jackrabbit.webdav.jcr.property.NamespacesProperty; -import org.apache.jackrabbit.webdav.jcr.security.JcrUserPrivilegesProperty; -import org.apache.jackrabbit.webdav.jcr.security.JcrSupportedPrivilegesProperty; -import org.apache.jackrabbit.webdav.jcr.security.SecurityUtils; -import org.apache.jackrabbit.webdav.jcr.version.report.JcrPrivilegeReport; -import org.apache.jackrabbit.webdav.property.DavProperty; -import org.apache.jackrabbit.webdav.property.DavPropertyName; -import org.apache.jackrabbit.webdav.property.DefaultDavProperty; -import org.apache.jackrabbit.webdav.property.PropEntry; -import org.apache.jackrabbit.webdav.search.SearchResource; -import org.apache.jackrabbit.webdav.security.SecurityConstants; -import org.apache.jackrabbit.webdav.version.DeltaVResource; -import org.apache.jackrabbit.webdav.version.LabelInfo; -import org.apache.jackrabbit.webdav.version.MergeInfo; -import org.apache.jackrabbit.webdav.version.UpdateInfo; -import org.apache.jackrabbit.webdav.version.VersionControlledResource; -import org.apache.jackrabbit.webdav.version.VersionHistoryResource; -import org.apache.jackrabbit.webdav.version.WorkspaceResource; -import org.apache.jackrabbit.webdav.xml.DomUtil; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.w3c.dom.Element; - -import javax.jcr.Item; -import javax.jcr.NamespaceRegistry; -import javax.jcr.Repository; -import javax.jcr.RepositoryException; -import javax.jcr.Session; -import javax.jcr.Workspace; -import javax.jcr.nodetype.NodeTypeIterator; -import javax.jcr.nodetype.NodeTypeManager; -import javax.jcr.nodetype.NodeTypeTemplate; -import javax.jcr.observation.EventListener; -import javax.jcr.version.Version; -import java.io.IOException; -import java.io.OutputStreamWriter; -import java.io.PrintWriter; -import java.io.StringReader; -import java.io.StringWriter; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.Date; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -/** - * WorkspaceResourceImpl... - */ -public class WorkspaceResourceImpl extends AbstractResource - implements WorkspaceResource, VersionControlledResource { - - private static Logger log = LoggerFactory.getLogger(WorkspaceResourceImpl.class); - - /** - * Create a new WorkspaceResourceImpl - * - * @param locator - * @param session - * @param factory - */ - WorkspaceResourceImpl(DavResourceLocator locator, JcrDavSession session, DavResourceFactory factory) { - super(locator, session, factory); - - // initialize the supported locks and reports - initLockSupport(); - initSupportedReports(); - } - - @Override - public DavProperty getProperty(DavPropertyName name) { - DavProperty prop = super.getProperty(name); - if (prop == null) { - StringWriter writer = null; - try { - if (ItemResourceConstants.JCR_NODETYPES_CND.equals(name)) { - writer = new StringWriter(); - Session s = getRepositorySession(); - - CompactNodeTypeDefWriter cndWriter = new CompactNodeTypeDefWriter(writer, s, true); - NodeTypeIterator ntIterator = s.getWorkspace().getNodeTypeManager().getAllNodeTypes(); - while (ntIterator.hasNext()) { - cndWriter.write(ntIterator.nextNodeType()); - } - cndWriter.close(); - /* - NOTE: avoid having JCR_NODETYPES_CND exposed upon allprop - PROPFIND request since it needs to be calculated. - nevertheless, this property can be altered using - PROPPATCH, which is not consistent with the specification - */ - prop = new DefaultDavProperty(ItemResourceConstants.JCR_NODETYPES_CND, writer.toString(), true); - - } else if (SecurityConstants.SUPPORTED_PRIVILEGE_SET.equals(name)) { - prop = new JcrSupportedPrivilegesProperty(getRepositorySession(), null).asDavProperty(); - } else if (SecurityConstants.CURRENT_USER_PRIVILEGE_SET.equals(name)) { - prop = new JcrUserPrivilegesProperty(getRepositorySession(), null).asDavProperty(); - } - } catch (RepositoryException e) { - log.error("Failed to access NodeTypeManager: " + e.getMessage()); - } catch (IOException e) { - log.error("Failed to write compact node definition: " + e.getMessage()); - } finally { - if (writer != null) { - try { - writer.close(); - } catch (IOException e) { - log.error(e.getMessage()); - } - } - } - } - - // TODO: required property DAV:workspace-checkout-set (computed) - - return prop; - } - - //--------------------------------------------------------< DavResource >--- - - @Override - public String getSupportedMethods() { - StringBuilder sb = new StringBuilder(DavResource.METHODS); - sb.append(", "); - sb.append(DeltaVResource.METHODS_INCL_MKWORKSPACE); - sb.append(", "); - sb.append(SearchResource.METHODS); - // from vc-resource methods only UPDATE is supported - sb.append(", "); - sb.append(DavMethods.METHOD_UPDATE); - return sb.toString(); - } - - /** - * @return true if the workspace name (see {@link #getDisplayName()} is - * present in the list of available workspace names such as exposed by - * the editing JCR session. - */ - @Override - public boolean exists() { - try { - List available = Arrays.asList(getRepositorySession().getWorkspace().getAccessibleWorkspaceNames()); - return available.contains(getDisplayName()); - } catch (RepositoryException e) { - log.warn(e.getMessage()); - return false; - } - } - - /** - * @return true - */ - @Override - public boolean isCollection() { - return true; - } - - /** - * Returns the name of the workspace. - * - * @return The workspace name - * @see org.apache.jackrabbit.webdav.DavResource#getDisplayName() - * @see javax.jcr.Workspace#getName() - */ - @Override - public String getDisplayName() { - return getLocator().getWorkspaceName(); - } - - /** - * Always returns 'now' - * - * @return - */ - @Override - public long getModificationTime() { - return new Date().getTime(); - } - - /** - * @param outputContext - * @throws IOException - */ - @Override - public void spool(OutputContext outputContext) throws IOException { - - outputContext.setProperty("Link", "; title=\"Event Journal\"; rel=alternate; type=\"" + AtomFeedConstants.MEDIATYPE + "\""); - - if (outputContext.hasStream()) { - Session session = getRepositorySession(); - Repository rep = session.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); - String repostr = repName + " " + repVersion; - - StringBuilder sb = new StringBuilder(); - sb.append(""); - sb.append(repostr); - sb.append(""); - sb.append(""); - sb.append(""); - sb.append("

").append(repostr).append("


Powered by ").append(repName); - sb.append(" ").append(repVersion); - sb.append(""); - - outputContext.setContentLength(sb.length()); - outputContext.setModificationTime(getModificationTime()); - PrintWriter writer = new PrintWriter(new OutputStreamWriter(outputContext.getOutputStream(), "utf8")); - writer.print(sb.toString()); - writer.close(); - } else { - outputContext.setContentLength(0); - outputContext.setModificationTime(getModificationTime()); - } - } - - /** - * Retrieve the collection that has all workspace collections - * as internal members. - * - * @see org.apache.jackrabbit.webdav.DavResource#getCollection() - */ - @Override - public DavResource getCollection() { - DavResource collection = null; - // create location with 'null' values for workspace-path and resource-path - DavResourceLocator parentLoc = getLocator().getFactory().createResourceLocator(getLocator().getPrefix(), null, null, false); - try { - collection = createResourceFromLocator(parentLoc); - } catch (DavException e) { - log.error("Unexpected error while retrieving collection: " + e.getMessage()); - } - return collection; - } - - /** - * Throws 403 exception (Forbidden) - * - * @param resource - * @param inputContext - * @throws DavException - */ - @Override - public void addMember(DavResource resource, InputContext inputContext) throws DavException { - log.error("Cannot add a new member to the workspace resource."); - throw new DavException(DavServletResponse.SC_FORBIDDEN); - } - - /** - * Returns the resource representing the JCR root node. - * - * @return - */ - @Override - public DavResourceIterator getMembers() { - try { - DavResourceLocator loc = getLocatorFromItem(getRepositorySession().getRootNode()); - List list = Collections.singletonList(createResourceFromLocator(loc)); - return new DavResourceIteratorImpl(list); - } catch (DavException e) { - log.error("Internal error while building resource for the root node.", e); - return DavResourceIteratorImpl.EMPTY; - } catch (RepositoryException e) { - log.error("Internal error while building resource for the root node.", e); - return DavResourceIteratorImpl.EMPTY; - } - } - - /** - * Throws 403 exception (Forbidden) - * - * @param member - * @throws DavException - */ - @Override - public void removeMember(DavResource member) throws DavException { - log.error("Cannot add a remove the root node."); - throw new DavException(DavServletResponse.SC_FORBIDDEN); - } - - /** - * Allows to alter the registered namespaces ({@link ItemResourceConstants#JCR_NAMESPACES}) - * or register node types {@link ItemResourceConstants#JCR_NODETYPES_CND} - * where the passed value is a cnd string containing the definition - * and forwards any other property to the super class. - *

- * Note that again no property status is set. Any failure while setting - * a property results in an exception (violating RFC 2518). - * - * @param property - * @throws DavException - * @see DavResource#setProperty(org.apache.jackrabbit.webdav.property.DavProperty) - */ - @Override - public void setProperty(DavProperty property) throws DavException { - if (ItemResourceConstants.JCR_NAMESPACES.equals(property.getName())) { - NamespacesProperty nsp = new NamespacesProperty(property); - try { - Map changes = new HashMap(nsp.getNamespaces()); - NamespaceRegistry nsReg = getRepositorySession().getWorkspace().getNamespaceRegistry(); - for (String prefix : nsReg.getPrefixes()) { - if (!changes.containsKey(prefix)) { - // prefix not present amongst the new values any more > unregister - nsReg.unregisterNamespace(prefix); - } else if (changes.get(prefix).equals(nsReg.getURI(prefix))) { - // present with same uri-value >> no action required - changes.remove(prefix); - } - } - - // try to register any prefix/uri pair that has a changed uri or - // it has not been present before. - for (String prefix : changes.keySet()) { - String uri = changes.get(prefix); - nsReg.registerNamespace(prefix, uri); - } - } catch (RepositoryException e) { - throw new JcrDavException(e); - } - } else if (ItemResourceConstants.JCR_NODETYPES_CND.equals(property.getName())) { - try { - Object value = property.getValue(); - List cmds; - if (value instanceof List) { - cmds = (List) value; - } else if (value instanceof Element) { - cmds = Collections.singletonList(value); - } else { - log.warn("Unexpected structure of dcr:nodetypes-cnd property."); - throw new DavException(DavServletResponse.SC_INTERNAL_SERVER_ERROR); - } - - String registerCnd = null; - boolean allowUpdate = false; - List unregisterNames = new ArrayList(); - - for (Object listEntry : cmds) { - if (listEntry instanceof Element) { - Element e = (Element) listEntry; - String localName = e.getLocalName(); - if (ItemResourceConstants.XML_CND.equals(localName)) { - registerCnd = DomUtil.getText(e); - } else if (ItemResourceConstants.XML_ALLOWUPDATE.equals(localName)) { - String allow = DomUtil.getTextTrim(e); - allowUpdate = Boolean.parseBoolean(allow); - } else if (ItemResourceConstants.XML_NODETYPENAME.equals(localName)) { - unregisterNames.add(DomUtil.getTextTrim(e)); - } - } - } - - // TODO: for simplicity it's currently either registration or unregistration as nt-modifications are immediately persisted. - Session s = getRepositorySession(); - NodeTypeManager ntMgr = s.getWorkspace().getNodeTypeManager(); - if (registerCnd != null) { - StringReader reader = new StringReader(registerCnd); - DefinitionBuilderFactory factory = - new TemplateBuilderFactory(ntMgr, s.getValueFactory(), s.getWorkspace().getNamespaceRegistry()); - - CompactNodeTypeDefReader cndReader = - new CompactNodeTypeDefReader(reader, "davex", factory); - - List ntts = cndReader.getNodeTypeDefinitions(); - ntMgr.registerNodeTypes(ntts.toArray(new NodeTypeTemplate[ntts.size()]), allowUpdate); - } else if (!unregisterNames.isEmpty()) { - ntMgr.unregisterNodeTypes(unregisterNames.toArray(new String[unregisterNames.size()])); - } - - } catch (ParseException e) { - throw new DavException(DavServletResponse.SC_BAD_REQUEST, e); - } - catch (RepositoryException e) { - throw new JcrDavException(e); - } - } else { - // only jcr:namespace or node types can be modified - throw new DavException(DavServletResponse.SC_CONFLICT); - } - } - - /** - * Handles an attempt to set {@link ItemResourceConstants#JCR_NAMESPACES} - * and forwards any other set or remove requests to the super class. - * - * @see #setProperty(DavProperty) - * @see DefaultItemCollection#alterProperties(List) - */ - @Override - public MultiStatusResponse alterProperties(List changeList) throws DavException { - if (changeList.size() == 1) { - PropEntry propEntry = changeList.get(0); - // only modification of prop is allowed. removal is not possible - if (propEntry instanceof DavProperty - && (ItemResourceConstants.JCR_NAMESPACES.equals(((DavProperty)propEntry).getName()) - || ItemResourceConstants.JCR_NODETYPES_CND.equals(((DavProperty)propEntry).getName()))) { - setProperty((DavProperty) propEntry); - } else { - // attempt to remove the namespace property - throw new DavException(DavServletResponse.SC_CONFLICT); - } - } else { - // change list contains more than the jcr:namespaces property - // TODO: build multistatus instead - throw new DavException(DavServletResponse.SC_CONFLICT); - } - return new MultiStatusResponse(getHref(), DavServletResponse.SC_OK); - } - - //------------------------------------------------< VersionableResource >--- - /** - * @throws DavException (403) since workspace is not versionable. implementing - * VersionControlledResource only for 'update'. - */ - @Override - public void addVersionControl() throws DavException { - throw new DavException(DavServletResponse.SC_FORBIDDEN); - } - - //------------------------------------------< VersionControlledResource >--- - /** - * @throws DavException (403) since workspace is not versionable. implementing - * VersionControlledResource only for 'update'. - */ - @Override - public String checkin() throws DavException { - throw new DavException(DavServletResponse.SC_FORBIDDEN); - } - - /** - * @throws DavException (403) since workspace is not versionable. implementing - * VersionControlledResource only for 'update'. - */ - @Override - public void checkout() throws DavException { - throw new DavException(DavServletResponse.SC_FORBIDDEN); - } - - /** - * @throws DavException (403) since workspace is not versionable. implementing - * VersionControlledResource only for 'update'. - */ - @Override - public void uncheckout() throws DavException { - throw new DavException(DavServletResponse.SC_FORBIDDEN); - } - - /** - * While RFC 3253 does not define any version-related operations for the - * workspace resource, this implementation uses {@link VersionControlledResource#update(UpdateInfo)} - * to map {@link Workspace#restore(javax.jcr.version.Version[], boolean)} to - * a WebDAV call. - *

- * Limitation: note that the MultiStatus returned by this method - * will not list any nodes that have been removed due to an Uuid conflict. - * - * @param updateInfo - * @return - * @throws org.apache.jackrabbit.webdav.DavException - * @see org.apache.jackrabbit.webdav.version.VersionControlledResource#update(org.apache.jackrabbit.webdav.version.UpdateInfo) - */ - @Override - public MultiStatus update(UpdateInfo updateInfo) throws DavException { - if (updateInfo == null) { - throw new DavException(DavServletResponse.SC_BAD_REQUEST, "Valid update request body required."); - } - if (!exists()) { - throw new DavException(DavServletResponse.SC_NOT_FOUND); - } - - Session session = getRepositorySession(); - MultiStatus ms = new MultiStatus(); - try { - Element udElem = updateInfo.getUpdateElement(); - boolean removeExisting = DomUtil.hasChildElement(udElem, ItemResourceConstants.XML_REMOVEEXISTING, ItemResourceConstants.NAMESPACE); - - // register eventListener in order to be able to report the modified resources. - EventListener el = new EListener(updateInfo.getPropertyNameSet(), ms); - registerEventListener(el, session.getRootNode().getPath()); - - String[] hrefs = updateInfo.getVersionHref(); - if (hrefs == null || hrefs.length < 1) { - throw new DavException(DavServletResponse.SC_BAD_REQUEST, "Invalid update request body: at least a single version href must be specified."); - } - // perform the update/restore according to the update info - Version[] versions = new Version[hrefs.length]; - for (int i = 0; i < hrefs.length; i++) { - final String href = normalizeResourceHref(hrefs[i]); - DavResourceLocator vLoc = getLocator().getFactory().createResourceLocator(getLocator().getPrefix(), href); - String versionPath = vLoc.getRepositoryPath(); - Item item = getRepositorySession().getItem(versionPath); - if (item instanceof Version) { - versions[i] = (Version) item; - } else { - throw new DavException(DavServletResponse.SC_BAD_REQUEST, "Invalid update request body: href does not identify a version " + hrefs[i]); - } - } - session.getWorkspace().restore(versions, removeExisting); - - // unregister the event listener again - unregisterEventListener(el); - - } catch (RepositoryException e) { - throw new JcrDavException(e); - } - return ms; - } - - /** - * @throws DavException (403) since workspace is not versionable. implementing - * VersionControlledResource only for 'update'. - */ - @Override - public MultiStatus merge(MergeInfo mergeInfo) throws DavException { - throw new DavException(DavServletResponse.SC_FORBIDDEN); - } - - /** - * @throws DavException (403) since workspace is not versionable. implementing - * VersionControlledResource only for 'update'. - */ - @Override - public void label(LabelInfo labelInfo) throws DavException { - throw new DavException(DavServletResponse.SC_FORBIDDEN); - } - - /** - * @throws DavException (403) since workspace is not versionable. implementing - * VersionControlledResource only for 'update'. - */ - @Override - public VersionHistoryResource getVersionHistory() throws DavException { - throw new DavException(DavServletResponse.SC_FORBIDDEN); - } - - //---------------------------------------------------< AbstractResource >--- - @Override - protected void initLockSupport() { - // lock not allowed - } - - @Override - protected void initSupportedReports() { - super.initSupportedReports(); - supportedReports.addReportType(JcrPrivilegeReport.PRIVILEGES_REPORT); - } - - @Override - protected String getWorkspaceHref() { - return getHref(); - } - - @Override - protected void initPropertyNames() { - super.initPropertyNames(); - names.addAll(JcrDavPropertyNameSet.WORKSPACE_SET); - if (SecurityUtils.supportsAccessControl(getRepositorySession())) { - names.add(SecurityConstants.SUPPORTED_PRIVILEGE_SET); - names.add(SecurityConstants.CURRENT_USER_PRIVILEGE_SET); - } - } - - @Override - protected void initProperties() { - super.initProperties(); - try { - // init workspace specific properties - NamespaceRegistry nsReg = getRepositorySession().getWorkspace().getNamespaceRegistry(); - DavProperty namespacesProp = new NamespacesProperty(nsReg); - properties.add(namespacesProp); - } catch (RepositoryException e) { - log.error("Failed to access NamespaceRegistry: " + e.getMessage()); - } - } -} Property changes on: jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/WorkspaceResourceImpl.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Deleted: svn:keywords ## -1 +0,0 ## -author date id revision url \ No newline at end of property Index: jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/lock/JcrActiveLock.java =================================================================== --- jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/lock/JcrActiveLock.java (revision 1907912) +++ jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/lock/JcrActiveLock.java (nonexistent) @@ -1,192 +0,0 @@ -/* - * 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.webdav.jcr.lock; - -import org.apache.jackrabbit.webdav.DavConstants; -import org.apache.jackrabbit.webdav.jcr.ItemResourceConstants; -import org.apache.jackrabbit.webdav.lock.AbstractActiveLock; -import org.apache.jackrabbit.webdav.lock.ActiveLock; -import org.apache.jackrabbit.webdav.lock.Scope; -import org.apache.jackrabbit.webdav.lock.Type; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import javax.jcr.RepositoryException; -import javax.jcr.lock.Lock; - -/** - * JcrActiveLock wraps a {@link Lock JCR lock} object. - */ -public class JcrActiveLock extends AbstractActiveLock implements ActiveLock, DavConstants { - - private static Logger log = LoggerFactory.getLogger(JcrActiveLock.class); - - private final Lock lock; - - /** - * Create a new ActiveLock object with type '{@link Type#WRITE write}' - * and scope '{@link Scope#EXCLUSIVE exclusive}'. - * - * @param lock - */ - public JcrActiveLock(Lock lock) { - if (lock == null) { - throw new IllegalArgumentException("Can not create a ActiveLock with a 'null' argument."); - } - this.lock = lock; - } - - /** - * Return true if the given lock token equals the token holding that lock. - * - * @param lockToken - * @return true if the given lock token equals this locks token. - * @see org.apache.jackrabbit.webdav.lock.ActiveLock#isLockedByToken(String) - */ - public boolean isLockedByToken(String lockToken) { - if (lockToken != null && lockToken.equals(getToken())) { - return true; - } - return false; - } - - /** - * @see ActiveLock#isExpired() - */ - public boolean isExpired() { - try { - return !lock.isLive(); - } catch (RepositoryException e) { - log.error("Unexpected error: " + e.getMessage()); - return false; - } - } - - /** - * Return the lock token if the {@link javax.jcr.Session} that obtained the lock - * is the lock token holder, null otherwise.
- * NOTE: currently the token generated by the underlying JCR repository - * is not checked for compliance with RFC 2518 ("OpaqueLockToken-URI = "opaquelocktoken:" - * UUID [Extension] ; The UUID production is the string representation of a - * UUID, as defined in [ISO-11578]. Note that white space (LWS) is not allowed - * between elements of this production."). - *

- * In case of session-scoped JCR 2.0 locks, the token is never exposed even - * if the current session is lock holder. In order to cope with DAV specific - * requirements and the fulfill the requirement stated above, the node's - * identifier is subsequently exposed as DAV-token. - * - * @see ActiveLock#getToken() - */ - public String getToken() { - try { - return LockTokenMapper.getDavLocktoken(lock); - } catch (RepositoryException e) { - // should never get here - log.warn("Unexpected error while retrieving node identifier for building a DAV specific lock token. {}", - e.getMessage()); - return null; - } - } - - /** - * @see ActiveLock#getOwner() - */ - public String getOwner() { - return lock.getLockOwner(); - } - - /** - * @see ActiveLock#setOwner(String) - */ - public void setOwner(String owner) { - throw new UnsupportedOperationException("setOwner is not implemented"); - } - - /** - * Calculates the milliseconds of the timeout from - * {@link javax.jcr.lock.Lock#getSecondsRemaining()}. If the timeout of - * jcr lock is undefined or infinite {@link #INFINITE_TIMEOUT} is - * returned. - * - * @see ActiveLock#getTimeout() - */ - public long getTimeout() { - try { - long to = lock.getSecondsRemaining(); - long reportAs; - - if (to == Long.MAX_VALUE) { - reportAs = INFINITE_TIMEOUT; - } - else if (to / 1000 <= Long.MAX_VALUE / 1000) { - // expressible as long? - reportAs = to * 1000; - } - else { - reportAs = INFINITE_TIMEOUT; - } - - return reportAs; - } catch (RepositoryException e) { - return INFINITE_TIMEOUT; - } - } - - /** - * Throws UnsupportedOperationException - * - * @see ActiveLock#setTimeout(long) - */ - public void setTimeout(long timeout) { - throw new UnsupportedOperationException("setTimeout is not implemented"); - } - - /** - * @see ActiveLock#isDeep() - */ - public boolean isDeep() { - return lock.isDeep(); - } - - /** - * @see ActiveLock#setIsDeep(boolean) - */ - public void setIsDeep(boolean isDeep) { - throw new UnsupportedOperationException("setIsDeep is not implemented"); - } - - /** - * Always returns {@link Type#WRITE}. - * - * @return {@link Type#WRITE} - * @see ActiveLock#getType() - */ - public Type getType() { - return Type.WRITE; - } - - /** - * @return The scope of this lock, which may either by an {@link Scope#EXCLUSIVE exclusive} - * or {@link ItemResourceConstants#EXCLUSIVE_SESSION exclusive session scoped} - * lock. - * @see ActiveLock#getScope() - */ - public Scope getScope() { - return (lock.isSessionScoped()) ? ItemResourceConstants.EXCLUSIVE_SESSION : Scope.EXCLUSIVE; - } -} Property changes on: jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/lock/JcrActiveLock.java ___________________________________________________________________ Deleted: svn Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/lock/LockTokenMapper.java =================================================================== --- jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/lock/LockTokenMapper.java (revision 1907912) +++ jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/lock/LockTokenMapper.java (nonexistent) @@ -1,74 +0,0 @@ -/* - * 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.webdav.jcr.lock; - -import javax.jcr.RepositoryException; -import javax.jcr.lock.Lock; - -import org.apache.jackrabbit.util.Text; - -/** - * Maps between WebDAV lock tokens and JCR lock tokens. - *

- * The following notations are used: - * - *

- * opaquelocktoken:SESSIONSCOPED:NODEIDENTIFIER
- * opaquelocktoken:OPENSCOPED:JCRLOCKTOKEN
- * 
- * - * The first format is used if the JCR lock does not reveal a lock token, such - * as when it is a session-scoped lock (where SESSIONSCOPED is a constant UUID - * defined below, and NODEIDENTIFIER is the suitably escaped JCR Node - * identifier). - *

- * The second format is used for open-scoped locks (where OPENSCOPED is another - * constant UUID defined below, and JCRLOCKTOKEN is the suitably escaped JCR - * lock token). - */ -public class LockTokenMapper { - - private static final String OL = "opaquelocktoken:"; - - private static final String SESSIONSCOPED = "4403ef44-4124-11e1-b965-00059a3c7a00"; - private static final String OPENSCOPED = "dccce564-412e-11e1-b969-00059a3c7a00"; - - private static final String SESSPREFIX = OL + SESSIONSCOPED + ":"; - private static final String OPENPREFIX = OL + OPENSCOPED + ":"; - - public static String getDavLocktoken(Lock lock) throws RepositoryException { - String jcrLockToken = lock.getLockToken(); - - if (jcrLockToken == null) { - return SESSPREFIX + Text.escape(lock.getNode().getIdentifier()); - } else { - return OPENPREFIX + Text.escape(jcrLockToken); - } - } - - public static String getJcrLockToken(String token) throws RepositoryException { - if (token.startsWith(OPENPREFIX)) { - return Text.unescape(token.substring(OPENPREFIX.length())); - } else { - throw new RepositoryException("not a token for an open-scoped JCR lock: " + token); - } - } - - public static boolean isForSessionScopedLock(String token) { - return token.startsWith(SESSPREFIX); - } -} Property changes on: jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/lock/LockTokenMapper.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/lock/SessionScopedLockEntry.java =================================================================== --- jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/lock/SessionScopedLockEntry.java (revision 1907912) +++ jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/lock/SessionScopedLockEntry.java (nonexistent) @@ -1,50 +0,0 @@ -/* - * 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.webdav.jcr.lock; - -import org.apache.jackrabbit.webdav.jcr.ItemResourceConstants; -import org.apache.jackrabbit.webdav.lock.AbstractLockEntry; -import org.apache.jackrabbit.webdav.lock.LockEntry; -import org.apache.jackrabbit.webdav.lock.Scope; -import org.apache.jackrabbit.webdav.lock.Type; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * SessionScopedLockEntry represents the 'session-scoped' write - * lock as defined by JCR. - */ -public class SessionScopedLockEntry extends AbstractLockEntry { - - private static Logger log = LoggerFactory.getLogger(SessionScopedLockEntry.class); - - /** - * @return always returns {@link Type#WRITE write}. - * @see LockEntry#getType() - */ - public Type getType() { - return Type.WRITE; - } - - /** - * @return returns {@link ItemResourceConstants#EXCLUSIVE_SESSION}. - * @see LockEntry#getScope() - */ - public Scope getScope() { - return ItemResourceConstants.EXCLUSIVE_SESSION; - } -} \ No newline at end of file Property changes on: jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/lock/SessionScopedLockEntry.java ___________________________________________________________________ Deleted: svn Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/nodetype/ItemDefinitionImpl.java =================================================================== --- jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/nodetype/ItemDefinitionImpl.java (revision 1907912) +++ jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/nodetype/ItemDefinitionImpl.java (nonexistent) @@ -1,126 +0,0 @@ -/* - * 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.webdav.jcr.nodetype; - -import org.apache.jackrabbit.commons.webdav.NodeTypeConstants; -import org.apache.jackrabbit.webdav.xml.XmlSerializable; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.w3c.dom.Document; -import org.w3c.dom.Element; - -import javax.jcr.nodetype.ItemDefinition; -import javax.jcr.nodetype.NodeType; -import javax.jcr.version.OnParentVersionAction; - -/** - * ItemDefinitionImpl... - */ -abstract public class ItemDefinitionImpl implements ItemDefinition, NodeTypeConstants, XmlSerializable { - - private static Logger log = LoggerFactory.getLogger(ItemDefinitionImpl.class); - - private final String name; - private NodeType declaringNodeType; - private final boolean isAutoCreated; - private final boolean isMandatory; - private final boolean isProtected; - private final int onParentVersion; - - ItemDefinitionImpl(ItemDefinition definition) { - if (definition == null) { - throw new IllegalArgumentException("PropDef argument can not be null"); - } - name = definition.getName(); - declaringNodeType = definition.getDeclaringNodeType(); - isAutoCreated = definition.isAutoCreated(); - isMandatory = definition.isMandatory(); - isProtected = definition.isProtected(); - onParentVersion = definition.getOnParentVersion(); - } - - /** - * @see ItemDefinition#getDeclaringNodeType() - */ - public NodeType getDeclaringNodeType() { - return declaringNodeType; - } - - /** - * @see ItemDefinition#getName() - */ - public String getName() { - return name; - } - - /** - * @see ItemDefinition#isAutoCreated() - */ - public boolean isAutoCreated() { - return isAutoCreated; - } - - /** - * @see ItemDefinition#isMandatory() - */ - public boolean isMandatory() { - return isMandatory; - } - - /** - * @see ItemDefinition#getOnParentVersion() - */ - public int getOnParentVersion() { - return onParentVersion; - } - - /** - * @see ItemDefinition#isProtected() - */ - public boolean isProtected() { - return isProtected; - } - - //------------------------------------------< XmlSerializable interface >--- - /** - * Returns the Xml representation of a {@link ItemDefinition} object. - * - * @return Xml representation of the specified {@link ItemDefinition def}. - * @param document - */ - public Element toXml(Document document) { - Element elem = document.createElement(getElementName()); - NodeType dnt = getDeclaringNodeType(); - if (dnt != null) { - elem.setAttribute(DECLARINGNODETYPE_ATTRIBUTE, dnt.getName()); - } - elem.setAttribute(NAME_ATTRIBUTE, getName()); - elem.setAttribute(AUTOCREATED_ATTRIBUTE, Boolean.toString(isAutoCreated())); - elem.setAttribute(MANDATORY_ATTRIBUTE, Boolean.toString(isMandatory())); - elem.setAttribute(ONPARENTVERSION_ATTRIBUTE, OnParentVersionAction.nameFromValue(getOnParentVersion())); - elem.setAttribute(PROTECTED_ATTRIBUTE, Boolean.toString(isProtected())); - return elem; - } - - //-------------------------------------< implementation specific method >--- - /** - * Returns the name of the root element - * - * @return the name of the root element - */ - abstract String getElementName(); -} \ No newline at end of file Property changes on: jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/nodetype/ItemDefinitionImpl.java ___________________________________________________________________ Deleted: svn Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/nodetype/NodeDefinitionImpl.java =================================================================== --- jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/nodetype/NodeDefinitionImpl.java (revision 1907912) +++ jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/nodetype/NodeDefinitionImpl.java (nonexistent) @@ -1,133 +0,0 @@ -/* - * 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.webdav.jcr.nodetype; - -import org.apache.jackrabbit.webdav.xml.DomUtil; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.w3c.dom.Document; -import org.w3c.dom.Element; - -import javax.jcr.nodetype.NodeDefinition; -import javax.jcr.nodetype.NodeType; - -/** - * NodeDefinitionImpl... - */ -public final class NodeDefinitionImpl extends ItemDefinitionImpl implements NodeDefinition { - - private static Logger log = LoggerFactory.getLogger(NodeDefinitionImpl.class); - - private final NodeType[] requiredPrimaryTypes; - private final NodeType defaultPrimaryType; - private final boolean allowsSameNameSiblings; - - private NodeDefinitionImpl(NodeDefinition definition) { - super(definition); - - requiredPrimaryTypes = definition.getRequiredPrimaryTypes(); - defaultPrimaryType = definition.getDefaultPrimaryType(); - allowsSameNameSiblings = definition.allowsSameNameSiblings(); - } - - public static NodeDefinitionImpl create(NodeDefinition definition) { - if (definition instanceof NodeDefinitionImpl) { - return (NodeDefinitionImpl) definition; - } else { - return new NodeDefinitionImpl(definition); - } - } - - //-----------------------------------------------------< NodeDefinition >--- - /** - * @see javax.jcr.nodetype.NodeDefinition#getRequiredPrimaryTypes() - */ - public NodeType[] getRequiredPrimaryTypes() { - return requiredPrimaryTypes; - } - - /** - * @see javax.jcr.nodetype.NodeDefinition#getDefaultPrimaryType() - */ - public NodeType getDefaultPrimaryType() { - return defaultPrimaryType; - } - - /** - * @see javax.jcr.nodetype.NodeDefinition#allowsSameNameSiblings() - */ - public boolean allowsSameNameSiblings() { - return allowsSameNameSiblings; - } - - /** - * @see javax.jcr.nodetype.NodeDefinition#getDefaultPrimaryTypeName() - */ - public String getDefaultPrimaryTypeName() { - return defaultPrimaryType.getName(); - } - - /** - * @see javax.jcr.nodetype.NodeDefinition#getRequiredPrimaryTypeNames() - */ - public String[] getRequiredPrimaryTypeNames() { - String[] names = new String[requiredPrimaryTypes.length]; - for (int i = 0; i < requiredPrimaryTypes.length; i++) { - names[i] = requiredPrimaryTypes[i].getName(); - } - return names; - } - - //-------------------------------------< implementation specific method >--- - /** - * Returns xml representation - * - * @return xml representation - * @param document - */ - @Override - public Element toXml(Document document) { - Element elem = super.toXml(document); - elem.setAttribute(SAMENAMESIBLINGS_ATTRIBUTE, Boolean.toString(allowsSameNameSiblings())); - // defaultPrimaryType can be 'null' - NodeType defaultPrimaryType = getDefaultPrimaryType(); - if (defaultPrimaryType != null) { - elem.setAttribute(DEFAULTPRIMARYTYPE_ATTRIBUTE, defaultPrimaryType.getName()); - } - // reqPrimaryTypes: minimal set is nt:base. - Element reqPrimaryTypes = document.createElement(REQUIREDPRIMARYTYPES_ELEMENT); - for (NodeType nt : getRequiredPrimaryTypes()) { - Element rptElem = document.createElement(REQUIREDPRIMARYTYPE_ELEMENT); - DomUtil.setText(rptElem, nt.getName()); - reqPrimaryTypes.appendChild(rptElem); - - } - elem.appendChild(reqPrimaryTypes); - return elem; - } - - /** - * Returns {@link #CHILDNODEDEFINITION_ELEMENT} - * - * @return always returns {@link #CHILDNODEDEFINITION_ELEMENT}. - */ - @Override - String getElementName() { - return CHILDNODEDEFINITION_ELEMENT; - } - -} Property changes on: jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/nodetype/NodeDefinitionImpl.java ___________________________________________________________________ Deleted: svn Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/nodetype/NodeTypeProperty.java =================================================================== --- jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/nodetype/NodeTypeProperty.java (revision 1907912) +++ jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/nodetype/NodeTypeProperty.java (nonexistent) @@ -1,105 +0,0 @@ -/* - * 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.webdav.jcr.nodetype; - -import org.apache.jackrabbit.commons.webdav.NodeTypeConstants; -import org.apache.jackrabbit.commons.webdav.NodeTypeUtil; -import org.apache.jackrabbit.webdav.property.AbstractDavProperty; -import org.apache.jackrabbit.webdav.property.DavProperty; -import org.apache.jackrabbit.webdav.property.DavPropertyName; -import org.w3c.dom.Document; -import org.w3c.dom.Element; - -import javax.jcr.nodetype.NodeType; -import java.util.Collections; -import java.util.HashSet; -import java.util.Set; - -/** - * NodeTypeProperty... - */ -public class NodeTypeProperty extends AbstractDavProperty> implements NodeTypeConstants { - - private final Set nodetypeNames = new HashSet(); - - public NodeTypeProperty(DavPropertyName name, NodeType nodeType, boolean isProtected) { - this(name, new NodeType[]{nodeType}, isProtected); - } - - public NodeTypeProperty(DavPropertyName name, NodeType[] nodeTypes, boolean isProtected) { - super(name, isProtected); - for (NodeType nt : nodeTypes) { - if (nt != null) { - nodetypeNames.add(nt.getName()); - } - } - } - - public NodeTypeProperty(DavPropertyName name, String[] nodeTypeNames, boolean isProtected) { - super(name, isProtected); - for (String nodeTypeName : nodeTypeNames) { - if (nodeTypeName != null) { - nodetypeNames.add(nodeTypeName); - } - } - } - - /** - * Create a new NodeTypeProperty from the specified general - * DavProperty object. - * - * @param property - */ - public NodeTypeProperty(DavProperty property) { - super(property.getName(), property.isInvisibleInAllprop()); - if (property instanceof NodeTypeProperty) { - nodetypeNames.addAll(((NodeTypeProperty) property).nodetypeNames); - } else { - nodetypeNames.addAll(NodeTypeUtil.ntNamesFromXml(property.getValue())); - } - } - - /** - * Return a set of node type names present in this property. - * - * @return set of node type names - */ - public Set getNodeTypeNames() { - return Collections.unmodifiableSet(nodetypeNames); - } - - /** - * Returns the value of this property which is a Set of nodetype names. - * - * @return a Set of nodetype names (String). - */ - public Set getValue() { - return Collections.unmodifiableSet(nodetypeNames); - } - - /** - * @see org.apache.jackrabbit.webdav.xml.XmlSerializable#toXml(Document) - */ - @Override - public Element toXml(Document document) { - Element elem = getName().toXml(document); - for (String name : getNodeTypeNames()) { - elem.appendChild(NodeTypeUtil.ntNameToXml(name, document)); - } - return elem; - } -} Property changes on: jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/nodetype/NodeTypeProperty.java ___________________________________________________________________ Deleted: svn Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/nodetype/PropertyDefinitionImpl.java =================================================================== --- jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/nodetype/PropertyDefinitionImpl.java (revision 1907912) +++ jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/nodetype/PropertyDefinitionImpl.java (nonexistent) @@ -1,179 +0,0 @@ -/* - * 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.webdav.jcr.nodetype; - -import org.apache.jackrabbit.webdav.xml.DomUtil; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.w3c.dom.Document; -import org.w3c.dom.Element; - -import javax.jcr.PropertyType; -import javax.jcr.RepositoryException; -import javax.jcr.Value; -import javax.jcr.nodetype.PropertyDefinition; - -/** - * PropertyDefinitionImpl... - */ -public final class PropertyDefinitionImpl extends ItemDefinitionImpl implements PropertyDefinition { - - private static Logger log = LoggerFactory.getLogger(PropertyDefinitionImpl.class); - - private final int type; - private final String[] valueConstraints; - private final Value[] defaultValues; - private final boolean isMultiple; - private final String[] availableQueryOperators; - private final boolean isFullTextSearchable; - private final boolean isQueryOrderable; - - private PropertyDefinitionImpl(PropertyDefinition definition) { - super(definition); - - type = definition.getRequiredType(); - valueConstraints = definition.getValueConstraints(); - defaultValues = definition.getDefaultValues(); - isMultiple = definition.isMultiple(); - availableQueryOperators = definition.getAvailableQueryOperators(); - isFullTextSearchable = definition.isFullTextSearchable(); - isQueryOrderable = definition.isQueryOrderable(); - } - - public static PropertyDefinitionImpl create(PropertyDefinition definition) { - if (definition instanceof PropertyDefinitionImpl) { - return (PropertyDefinitionImpl)definition; - } else { - return new PropertyDefinitionImpl(definition); - } - } - - //----------------------------------------< PropertyDefintion interface >--- - /** - * @see PropertyDefinition#getRequiredType() - */ - public int getRequiredType() { - return type; - } - - /** - * @see PropertyDefinition#getValueConstraints() - */ - public String[] getValueConstraints() { - return valueConstraints; - } - - /** - * @see PropertyDefinition#getDefaultValues() - */ - public Value[] getDefaultValues() { - return defaultValues; - } - - /** - * @see PropertyDefinition#isMultiple() - */ - public boolean isMultiple() { - return isMultiple; - } - - /** - * @see PropertyDefinition#getAvailableQueryOperators() - */ - public String[] getAvailableQueryOperators() { - return availableQueryOperators; - } - - /** - * @see PropertyDefinition#isFullTextSearchable() - */ - public boolean isFullTextSearchable() { - return isFullTextSearchable; - } - - /** - * @see PropertyDefinition#isQueryOrderable() - */ - public boolean isQueryOrderable() { - return isQueryOrderable; - } - - //-------------------------------------< implementation specific method >--- - /** - * Return xml representation - * - * @return xml representation - * @param document - */ - @Override - public Element toXml(Document document) { - Element elem = super.toXml(document); - - elem.setAttribute(MULTIPLE_ATTRIBUTE, Boolean.toString(isMultiple())); - elem.setAttribute(REQUIREDTYPE_ATTRIBUTE, PropertyType.nameFromValue(getRequiredType())); - - // JCR 2.0 extensions - elem.setAttribute(FULL_TEXT_SEARCHABLE_ATTRIBUTE, Boolean.toString(isFullTextSearchable())); - elem.setAttribute(QUERY_ORDERABLE_ATTRIBUTE, Boolean.toString(isQueryOrderable())); - - // default values may be 'null' - Value[] values = getDefaultValues(); - if (values != null) { - Element dvElement = document.createElement(DEFAULTVALUES_ELEMENT); - for (Value value : values) { - try { - Element valElem = document.createElement(DEFAULTVALUE_ELEMENT); - DomUtil.setText(valElem, value.getString()); - dvElement.appendChild(valElem); - } catch (RepositoryException e) { - // should not occur - log.error(e.getMessage()); - } - } - elem.appendChild(dvElement); - } - // value constraints array is never null. - Element constrElem = document.createElement(VALUECONSTRAINTS_ELEMENT); - for (String constraint : getValueConstraints()) { - Element vcElem = document.createElement(VALUECONSTRAINT_ELEMENT); - DomUtil.setText(vcElem, constraint); - constrElem.appendChild(vcElem); - } - elem.appendChild(constrElem); - - // JCR 2.0 extension - Element qopElem = document.createElement(AVAILABLE_QUERY_OPERATORS_ELEMENT); - for (String qop : getAvailableQueryOperators()) { - Element opElem = document.createElement(AVAILABLE_QUERY_OPERATOR_ELEMENT); - DomUtil.setText(opElem, qop); - qopElem.appendChild(opElem); - } - elem.appendChild(qopElem); - - return elem; - } - - /** - * Returns {@link #PROPERTYDEFINITION_ELEMENT}. - * - * @return always returns {@link #PROPERTYDEFINITION_ELEMENT} - */ - @Override - String getElementName() { - return PROPERTYDEFINITION_ELEMENT; - } -} Property changes on: jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/nodetype/PropertyDefinitionImpl.java ___________________________________________________________________ Deleted: svn Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/observation/SubscriptionImpl.java =================================================================== --- jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/observation/SubscriptionImpl.java (revision 1907912) +++ jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/observation/SubscriptionImpl.java (nonexistent) @@ -1,637 +0,0 @@ -/* - * 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.webdav.jcr.observation; - -import org.apache.jackrabbit.commons.webdav.EventUtil; -import org.apache.jackrabbit.commons.webdav.JcrRemotingConstants; -import org.apache.jackrabbit.spi.Name; -import org.apache.jackrabbit.spi.commons.AdditionalEventInfo; -import org.apache.jackrabbit.spi.commons.SessionExtensions; -import org.apache.jackrabbit.webdav.DavException; -import org.apache.jackrabbit.webdav.DavResourceLocator; -import org.apache.jackrabbit.webdav.DavServletResponse; -import org.apache.jackrabbit.webdav.transaction.TransactionResource; -import org.apache.jackrabbit.webdav.jcr.transaction.TransactionListener; -import org.apache.jackrabbit.webdav.jcr.JcrDavException; -import org.apache.jackrabbit.webdav.jcr.JcrDavSession; -import org.apache.jackrabbit.webdav.observation.EventBundle; -import org.apache.jackrabbit.webdav.observation.EventDiscovery; -import org.apache.jackrabbit.webdav.observation.EventType; -import org.apache.jackrabbit.webdav.observation.Filter; -import org.apache.jackrabbit.webdav.observation.ObservationConstants; -import org.apache.jackrabbit.webdav.observation.ObservationResource; -import org.apache.jackrabbit.webdav.observation.Subscription; -import org.apache.jackrabbit.webdav.observation.SubscriptionInfo; -import org.apache.jackrabbit.webdav.observation.DefaultEventType; -import org.apache.jackrabbit.webdav.xml.DomUtil; -import org.apache.jackrabbit.webdav.xml.Namespace; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.w3c.dom.Document; -import org.w3c.dom.Element; - -import javax.jcr.RepositoryException; -import javax.jcr.Session; -import javax.jcr.UnsupportedRepositoryOperationException; -import javax.jcr.observation.Event; -import javax.jcr.observation.EventIterator; -import javax.jcr.observation.EventListener; -import javax.jcr.observation.ObservationManager; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import java.util.UUID; - -/** - * The Subscription class encapsulates a single subscription with - * the following responsibilities:

    - *
  • Providing access to the subscription info,
  • - *
  • Recording events this subscription is interested in,
  • - *
  • Providing access to the events.
  • - *
- */ -public class SubscriptionImpl implements Subscription, ObservationConstants, EventListener { - - private static Logger log = LoggerFactory.getLogger(SubscriptionImpl.class); - private static final long DEFAULT_TIMEOUT = 300000; // 5 minutes - - private SubscriptionInfo info; - private long expirationTime; - - private final DavResourceLocator locator; - private final String subscriptionId = UUID.randomUUID().toString(); - private final List eventBundles = new ArrayList(); - private final ObservationManager obsMgr; - private final Session session; - - /** - * Create a new Subscription with the given {@link SubscriptionInfo} - * and {@link org.apache.jackrabbit.webdav.observation.ObservationResource resource}. - * - * @param info - * @param resource - * @throws DavException if resource is not based on a JCR repository or - * the repository does not support observation. - */ - public SubscriptionImpl(SubscriptionInfo info, ObservationResource resource) - throws DavException { - setInfo(info); - locator = resource.getLocator(); - session = JcrDavSession.getRepositorySession(resource.getSession()); - try { - obsMgr = session.getWorkspace().getObservationManager(); - } catch (RepositoryException e) { - throw new DavException(DavServletResponse.SC_INTERNAL_SERVER_ERROR, e); - } - } - - //-------------------------------------------------------< Subscription >--- - /** - * Returns the id of this subscription. - * - * @return subscriptionId - */ - public String getSubscriptionId() { - return subscriptionId; - } - - public boolean eventsProvideNodeTypeInformation() { - String t = session.getRepository().getDescriptor("org.apache.jackrabbit.spi.commons.AdditionalEventInfo"); - return t == null ? false : Boolean.parseBoolean(t); - } - - public boolean eventsProvideNoLocalFlag() { - return session instanceof SessionExtensions; - } - - //----------------------------------------------------< XmlSerializable >--- - /** - * Return the Xml representation of this Subscription as required - * for the {@link org.apache.jackrabbit.webdav.observation.SubscriptionDiscovery} - * webdav property that in included in the response body of a successful SUBSCRIBE - * request or as part of a PROPFIND response. - * - * @return Xml representation - * @see org.apache.jackrabbit.webdav.xml.XmlSerializable#toXml(Document) - * @param document - */ - public Element toXml(Document document) { - Element subscr = DomUtil.createElement(document, XML_SUBSCRIPTION, NAMESPACE); - - subscr.appendChild(info.toXml(document)); - subscr.appendChild(DomUtil.depthToXml(info.isDeep(), document)); - subscr.appendChild(DomUtil.timeoutToXml(info.getTimeOut(), document)); - - if (getSubscriptionId() != null) { - Element id = DomUtil.addChildElement(subscr, XML_SUBSCRIPTIONID, NAMESPACE); - id.appendChild(DomUtil.hrefToXml(getSubscriptionId(), document)); - } - - DomUtil.addChildElement(subscr, XML_EVENTSWITHTYPES, NAMESPACE, - Boolean.toString(eventsProvideNodeTypeInformation())); - DomUtil.addChildElement(subscr, XML_EVENTSWITHLOCALFLAG, NAMESPACE, - Boolean.toString(eventsProvideNoLocalFlag())); - - return subscr; - } - - //--------------------------------------------< implementation specific >--- - /** - * Modify the {@link SubscriptionInfo} for this subscription. - * - * @param info - */ - void setInfo(SubscriptionInfo info) { - this.info = info; - // validate the timeout and adjust value, if it is invalid or missing - long timeout = info.getTimeOut(); - if (timeout <= 0) { - timeout = DEFAULT_TIMEOUT; - } - expirationTime = System.currentTimeMillis() + timeout; - } - - /** - * @return JCR compliant integer representation of the event types defined - * for this {@link SubscriptionInfo}. - */ - int getJcrEventTypes() throws DavException { - EventType[] eventTypes = info.getEventTypes(); - int events = 0; - for (EventType eventType : eventTypes) { - events |= getJcrEventType(eventType); - } - return events; - } - - /** - * @return a String array with size > 0 or null - */ - String[] getUuidFilters() { - return getFilterValues(XML_UUID); - } - - /** - * @return a String array with size > 0 or null - */ - String[] getNodetypeNameFilters() { - return getFilterValues(XML_NODETYPE_NAME); - } - - private String[] getFilterValues(String filterLocalName) { - List values = new ArrayList(); - for (Filter filter : info.getFilters(filterLocalName, NAMESPACE)) { - String val = filter.getValue(); - if (val != null) { - values.add(val); - } - } - return (values.size() > 0) ? values.toArray(new String[values.size()]) : null; - } - - /** - * - * @return true if a {@link ObservationConstants#XML_NOLOCAL} element - * is present in the {@link SubscriptionInfo}. - */ - boolean isNoLocal() { - return info.isNoLocal(); - } - - /** - * @return true if this subscription is intended to be deep. - */ - boolean isDeep() { - return info.isDeep(); - } - - /** - * @return the locator of the {@link ObservationResource resource} this - * Subscription was requested for. - */ - DavResourceLocator getLocator() { - return locator; - } - - /** - * Returns true if this Subscription matches the given - * resource. - * - * @param resource - * @return true if this Subscription matches the given - * resource. - */ - boolean isSubscribedToResource(ObservationResource resource) { - return locator.getResourcePath().equals(resource.getResourcePath()); - } - - /** - * Returns true if this Subscription is expired and therefore - * stopped recording events. - * - * @return true if this Subscription is expired - */ - boolean isExpired() { - return System.currentTimeMillis() > expirationTime; - } - - /** - * Returns a {@link org.apache.jackrabbit.webdav.observation.EventDiscovery} object listing all events that were - * recorded since the last call to this method and clears the list of event - * bundles. - * - * @param timeout time in milliseconds to wait at most for events if none - * are present currently. - * @return object listing all events that were recorded. - * @see #onEvent(EventIterator) - */ - synchronized EventDiscovery discoverEvents(long timeout) { - EventDiscovery ed = new EventDiscovery(); - if (eventBundles.isEmpty() && timeout > 0) { - try { - wait(timeout); - } catch (InterruptedException e) { - // continue and possibly return empty event discovery - } - } - for (EventBundle eb : eventBundles) { - ed.addEventBundle(eb); - } - // clear list - eventBundles.clear(); - return ed; - } - - /** - * Creates a new transaction listener for the scope of a transaction - * commit (save call). - * @return a transaction listener for this subscription. - */ - TransactionListener createTransactionListener() { - if (info.isNoLocal()) { - // a subscription which is not interested in local changes does - // not need the transaction id - return new TransactionEvent() { - @Override - public void onEvent(EventIterator events) { - // ignore - } - - @Override - public void beforeCommit(TransactionResource resource, String lockToken) { - // ignore - } - - @Override - public void afterCommit(TransactionResource resource, - String lockToken, - boolean success) { - // ignore - } - }; - } else { - return new TransactionEvent(); - } - } - - /** - * Suspend this subscription. This call will remove this subscription as - * event listener from the observation manager. - */ - void suspend() throws DavException { - try { - obsMgr.removeEventListener(this); - } catch (RepositoryException e) { - throw new JcrDavException(e); - } - } - - /** - * Resumes this subscription. This call will register this subscription - * again as event listener to the observation manager. - */ - void resume() throws DavException { - try { - obsMgr.addEventListener(this, getJcrEventTypes(), - getLocator().getRepositoryPath(), isDeep(), getUuidFilters(), - getNodetypeNameFilters(), isNoLocal()); - } catch (RepositoryException e) { - throw new JcrDavException(e); - } - } - - //--------------------------------------------< EventListener interface >--- - /** - * Records the events passed as a new event bundle in order to make them - * available with the next {@link #discoverEvents(long)} request. If this - * subscription is expired it will remove itself as listener from the - * observation manager. - * - * @param events to be recorded. - * @see EventListener#onEvent(EventIterator) - * @see #discoverEvents(long) - */ - public synchronized void onEvent(EventIterator events) { - if (!isExpired()) { - eventBundles.add(new EventBundleImpl(events)); - } else { - // expired -> unsubscribe - try { - obsMgr.removeEventListener(this); - } catch (RepositoryException e) { - log.warn("Exception while unsubscribing: " + e); - } - } - notifyAll(); - } - - //-------------------------------------------------------------------------- - /** - * Static utility method to convert the type defined by a - * {@link javax.jcr.observation.Event JCR event} into an EventType - * object. - * - * @param jcrEventType - * @return EventType representation of the given JCR event type. - * @throws IllegalArgumentException if the given int does not represent a - * valid type constants as defined by {@link Event}.
- * Valid values are - *
    - *
  • {@link Event#NODE_ADDED}
  • - *
  • {@link Event#NODE_REMOVED}
  • - *
  • {@link Event#PROPERTY_ADDED}
  • - *
  • {@link Event#PROPERTY_REMOVED}
  • - *
  • {@link Event#PROPERTY_CHANGED}
  • - *
  • {@link Event#NODE_MOVED}
  • - *
  • {@link Event#PERSIST}
  • - *
- */ - public static EventType getEventType(int jcrEventType) { - String localName = EventUtil.getEventName(jcrEventType); - return DefaultEventType.create(localName, NAMESPACE); - } - - /** - * @return The DAV event type representation for all known JCR event types. - */ - public static EventType[] getAllEventTypes() { - EventType[] types = DefaultEventType.create(EventUtil.EVENT_ALL, NAMESPACE); - return types; - } - - /** - * Static utility method to convert an EventType as present in - * the Xml body into the corresponding JCR event constant defined by - * {@link javax.jcr.observation.Event}. - * - * @param eventType - * @return Any of the event types defined by {@link Event}.
- * Possible values are - *
    - *
  • {@link Event#NODE_ADDED}
  • - *
  • {@link Event#NODE_REMOVED}
  • - *
  • {@link Event#PROPERTY_ADDED}
  • - *
  • {@link Event#PROPERTY_REMOVED}
  • - *
  • {@link Event#PROPERTY_CHANGED}
  • - *
  • {@link Event#NODE_MOVED}
  • - *
  • {@link Event#PERSIST}
  • - *
- * @throws DavException if the given event type does not define a valid - * JCR event type, such as returned by {@link #getEventType(int)}. - */ - public static int getJcrEventType(EventType eventType) throws DavException { - if (eventType == null || !NAMESPACE.equals(eventType.getNamespace())) { - throw new DavException(DavServletResponse.SC_UNPROCESSABLE_ENTITY, "Invalid JCR event type: "+ eventType + ": Namespace mismatch."); - } - String eventName = eventType.getName(); - if (!EventUtil.isValidEventName(eventName)) { - throw new DavException(DavServletResponse.SC_UNPROCESSABLE_ENTITY, "Invalid event type: "+eventName); - } - return EventUtil.getJcrEventType(eventName); - } - - /** - * Inner class EventBundle encapsulates an event bundle as - * recorded {@link SubscriptionImpl#onEvent(EventIterator) on event} and - * provides the possibility to retrieve the Xml representation of the - * bundle and the events included in order to respond to a POLL request. - * - * @see SubscriptionImpl#discoverEvents(long) - */ - private class EventBundleImpl implements EventBundle { - - private final EventIterator events; - - private final String transactionId; - - private EventBundleImpl(EventIterator events) { - this(events, null); - } - - private EventBundleImpl(EventIterator events, String transactionId) { - this.events = events; - this.transactionId = transactionId; - } - - public Element toXml(Document document) { - Element bundle = DomUtil.createElement(document, XML_EVENTBUNDLE, NAMESPACE); - // TODO: this appears to be unused now - if (transactionId != null) { - DomUtil.setAttribute(bundle, XML_EVENT_TRANSACTION_ID, NAMESPACE, transactionId); - } - - boolean localFlagSet = false; - - while (events.hasNext()) { - Event event = events.nextEvent(); - - if (!localFlagSet) { - // obtain remote session identifier - localFlagSet = true; - String name = JcrRemotingConstants.RELATION_REMOTE_SESSION_ID; - Object forSessionId = session.getAttribute(name); - // calculate "local" flags - if (forSessionId != null - && event instanceof AdditionalEventInfo) { - AdditionalEventInfo aei = (AdditionalEventInfo) event; - try { - boolean isLocal = forSessionId.equals( - aei.getSessionAttribute(name)); - DomUtil.setAttribute( - bundle, XML_EVENT_LOCAL, null, - Boolean.toString(isLocal)); - } catch (UnsupportedRepositoryOperationException ex) { - // optional feature - } - } - } - - Element eventElem = DomUtil.addChildElement(bundle, XML_EVENT, NAMESPACE); - // href - String eHref = ""; - try { - boolean isCollection = (event.getType() == Event.NODE_ADDED || event.getType() == Event.NODE_REMOVED); - eHref = locator.getFactory().createResourceLocator(locator.getPrefix(), locator.getWorkspacePath(), event.getPath(), false).getHref(isCollection); - } catch (RepositoryException e) { - // should not occur.... - log.error(e.getMessage()); - } - eventElem.appendChild(DomUtil.hrefToXml(eHref, document)); - // event type - Element eType = DomUtil.addChildElement(eventElem, XML_EVENTTYPE, NAMESPACE); - eType.appendChild(getEventType(event.getType()).toXml(document)); - // user id - DomUtil.addChildElement(eventElem, XML_EVENTUSERID, NAMESPACE, event.getUserID()); - - // try to compute nodetype information - if (event instanceof AdditionalEventInfo) { - try { - DomUtil.addChildElement(eventElem, - XML_EVENTPRIMARNODETYPE, NAMESPACE, - ((AdditionalEventInfo) event) - .getPrimaryNodeTypeName().toString()); - for (Name mixin : ((AdditionalEventInfo) event) - .getMixinTypeNames()) { - DomUtil.addChildElement(eventElem, - XML_EVENTMIXINNODETYPE, NAMESPACE, - mixin.toString()); - } - } catch (UnsupportedRepositoryOperationException ex) { - // optional - } - } - - // Additional JCR 2.0 event information - // user data - try { - DomUtil.addChildElement(eventElem, XML_EVENTUSERDATA, NAMESPACE, event.getUserData()); - } catch (RepositoryException e) { - log.error("Internal error while retrieving event user data. {}", e.getMessage()); - } - // time stamp - try { - DomUtil.addChildElement(eventElem, XML_EVENTDATE, NAMESPACE, String.valueOf(event.getDate())); - } catch (RepositoryException e) { - log.error("Internal error while retrieving event date. {}", e.getMessage()); - } - // identifier - try { - DomUtil.addChildElement(eventElem, XML_EVENTIDENTIFIER, NAMESPACE, event.getIdentifier()); - } catch (RepositoryException e) { - log.error("Internal error while retrieving event identifier. {}", e.getMessage()); - } - // info - try { - serializeInfoMap(eventElem, session, event.getInfo()); - } catch (RepositoryException e) { - log.error("Internal error while retrieving event info. {}", e.getMessage()); - } - } - return bundle; - } - } - - protected static void serializeInfoMap(Element eventElem, Session session, Map map) { - // info - Element info = DomUtil.addChildElement(eventElem, XML_EVENTINFO, NAMESPACE); - Map m = map; - for (Map.Entry entry : m.entrySet()) { - try { - String key = entry.getKey().toString(); - Namespace ns = Namespace.EMPTY_NAMESPACE; - int colon = key.indexOf(':'); - if (colon >= 0) { - String prefix = key.substring(0, colon); - String localname = key.substring(colon + 1); - ns = Namespace.getNamespace(prefix, session.getNamespaceURI(prefix)); - key = localname; - } - Object value = entry.getValue(); - if (value != null) { - DomUtil.addChildElement(info, key, ns, value.toString()); - } else { - DomUtil.addChildElement(info, key, ns); - } - } catch (RepositoryException nse) { - log.error("Internal error while getting namespaceUri, info map field skipped for {}", entry.getKey()); - } - } - } - - //----------------------------< TransactionEvent >------------------------ - - /** - * Implements a transaction event which listeners for events during a save - * call on the repository. - */ - private class TransactionEvent implements EventListener, TransactionListener { - - private String transactionId; - - /** - * {@inheritDoc} - */ - public void onEvent(EventIterator events) { - String tId = transactionId; - if (tId == null) { - tId = UUID.randomUUID().toString(); - } - synchronized (SubscriptionImpl.this) { - eventBundles.add(new EventBundleImpl(events, tId)); - SubscriptionImpl.this.notifyAll(); - } - } - - //-----------------------------< TransactionListener >------------------ - - /** - * {@inheritDoc} - */ - public void beforeCommit(TransactionResource resource, String lockToken) { - try { - transactionId = lockToken; - obsMgr.addEventListener(this, getJcrEventTypes(), - getLocator().getRepositoryPath(), isDeep(), getUuidFilters(), - getNodetypeNameFilters(), isNoLocal()); - // suspend the subscription - suspend(); - } catch (RepositoryException e) { - log.warn("Unable to register TransactionListener: " + e); - } catch (DavException e) { - log.warn("Unable to register TransactionListener: " + e); - } - } - - /** - * {@inheritDoc} - */ - public void afterCommit(TransactionResource resource, - String lockToken, - boolean success) { - try { - // resume the subscription - resume(); - // remove this transaction event - obsMgr.removeEventListener(this); - } catch (RepositoryException e) { - log.warn("Unable to remove listener: " + e); - } catch (DavException e) { - log.warn("Unable to resume Subscription: " + e); - } - } - } -} Property changes on: jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/observation/SubscriptionImpl.java ___________________________________________________________________ Deleted: svn Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/observation/SubscriptionManagerImpl.java =================================================================== --- jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/observation/SubscriptionManagerImpl.java (revision 1907912) +++ jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/observation/SubscriptionManagerImpl.java (nonexistent) @@ -1,358 +0,0 @@ -/* - * 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.webdav.jcr.observation; - -import org.apache.jackrabbit.webdav.DavException; -import org.apache.jackrabbit.webdav.DavResourceLocator; -import org.apache.jackrabbit.webdav.DavServletResponse; -import org.apache.jackrabbit.webdav.transaction.TransactionResource; -import org.apache.jackrabbit.webdav.jcr.JcrDavException; -import org.apache.jackrabbit.webdav.jcr.JcrDavSession; -import org.apache.jackrabbit.webdav.jcr.transaction.TransactionListener; -import org.apache.jackrabbit.webdav.observation.EventDiscovery; -import org.apache.jackrabbit.webdav.observation.ObservationResource; -import org.apache.jackrabbit.webdav.observation.Subscription; -import org.apache.jackrabbit.webdav.observation.SubscriptionDiscovery; -import org.apache.jackrabbit.webdav.observation.SubscriptionInfo; -import org.apache.jackrabbit.webdav.observation.SubscriptionManager; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.w3c.dom.Element; -import org.w3c.dom.Document; - -import javax.jcr.RepositoryException; -import javax.jcr.Session; -import javax.jcr.observation.ObservationManager; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Iterator; -import java.util.Set; -import java.util.Map; -import java.util.List; -import java.util.ArrayList; - -/** - * SubscriptionManager collects all subscriptions requested, handles - * the subscription timeout and provides METHODS to discover subscriptions - * present on a given resource as well as events for an specific subscription. - */ -// todo: make sure all expired subscriptions are removed! -public class SubscriptionManagerImpl implements SubscriptionManager, TransactionListener { - - private static Logger log = LoggerFactory.getLogger(SubscriptionManagerImpl.class); - - /** - * Map containing all {@link org.apache.jackrabbit.webdav.observation.Subscription subscriptions}. - */ - private final SubscriptionMap subscriptions = new SubscriptionMap(); - - private final Map> transactionListenerById = new HashMap>(); - - /** - * Retrieve the {@link org.apache.jackrabbit.webdav.observation.SubscriptionDiscovery} - * object for the given resource. Note, that the discovery object will be empty - * if there are no subscriptions present.
- * Note that all subscriptions present on the given resource are returned. - * However, the subscription id will not be visible in order to avoid abuse - * by clients not having registered the subscription originally. - * - * @param resource - */ - public SubscriptionDiscovery getSubscriptionDiscovery(ObservationResource resource) { - Subscription[] subsForResource = subscriptions.getByPath(resource.getLocator()); - return new SubscriptionDiscovery(subsForResource); - } - - /** - * Create a new Subscription or update an existing Subscription - * and add it as eventlistener to the {@link javax.jcr.observation.ObservationManager}. - * - * @param info - * @param subscriptionId - * @param resource - * @return Subscription that has been added to the {@link javax.jcr.observation.ObservationManager} - * @throws DavException if the subscription fails - */ - public Subscription subscribe(SubscriptionInfo info, String subscriptionId, - ObservationResource resource) - throws DavException { - - Subscription subscription; - if (subscriptionId == null) { - // new subscription - SubscriptionImpl newSubs = new SubscriptionImpl(info, resource); - registerSubscription(newSubs, resource); - - // adjust references to this subscription - subscriptions.put(newSubs.getSubscriptionId(), newSubs); - resource.getSession().addReference(newSubs.getSubscriptionId()); - subscription = newSubs; - } else { - // refresh/modify existing one - SubscriptionImpl existing = validate(subscriptionId, resource); - existing.setInfo(info); - registerSubscription(existing, resource); - - subscription = new WrappedSubscription(existing); - } - return subscription; - } - - /** - * Register the event listener defined by the given subscription to the - * repository's observation manager. - * - * @param subscription - * @param resource - * @throws DavException - */ - private void registerSubscription(SubscriptionImpl subscription, - ObservationResource resource) throws DavException { - try { - Session session = getRepositorySession(resource); - ObservationManager oMgr = session.getWorkspace().getObservationManager(); - String itemPath = subscription.getLocator().getRepositoryPath(); - oMgr.addEventListener(subscription, subscription.getJcrEventTypes(), - itemPath, subscription.isDeep(), - subscription.getUuidFilters(), - subscription.getNodetypeNameFilters(), - subscription.isNoLocal()); - } catch (RepositoryException e) { - log.error("Unable to register eventlistener: "+e.getMessage()); - throw new JcrDavException(e); - } - } - - /** - * Unsubscribe the Subscription with the given id and remove it - * from the {@link javax.jcr.observation.ObservationManager} as well as - * from the internal map. - * - * @param subscriptionId - * @param resource - * @throws DavException - */ - public void unsubscribe(String subscriptionId, ObservationResource resource) - throws DavException { - - SubscriptionImpl subs = validate(subscriptionId, resource); - unregisterSubscription(subs, resource); - } - - /** - * Remove the event listener defined by the specified subscription from - * the repository's observation manager and clean up the references present - * on the DavSession. - * - * @param subscription - * @param resource - * @throws DavException - */ - private void unregisterSubscription(SubscriptionImpl subscription, - ObservationResource resource) throws DavException { - try { - Session session = getRepositorySession(resource); - session.getWorkspace().getObservationManager().removeEventListener(subscription); - String sId = subscription.getSubscriptionId(); - - // clean up any references - subscriptions.remove(sId); - resource.getSession().removeReference(sId); - - } catch (RepositoryException e) { - log.error("Unable to remove eventlistener: "+e.getMessage()); - throw new JcrDavException(e); - } - } - - /** - * Retrieve all event bundles accumulated since for the subscription specified - * by the given id. - * - * @param subscriptionId - * @param timeout timeout in milliseconds - * @param resource - * @return object encapsulating the events. - */ - public EventDiscovery poll(String subscriptionId, long timeout, ObservationResource resource) - throws DavException { - - SubscriptionImpl subs = validate(subscriptionId, resource); - return subs.discoverEvents(timeout); - } - - /** - * Validate the given subscription id. The validation will fail under the following - * conditions:
    - *
  • The subscription with the given id does not exist,
  • - *
  • DavResource path does not match the subscription id,
  • - *
  • The subscription with the given id is already expired.
  • - *
- * - * @param subscriptionId - * @param resource - * @return Subscription with the given id. - * @throws DavException if an error occurred while retrieving the Subscription - */ - private SubscriptionImpl validate(String subscriptionId, ObservationResource resource) - throws DavException { - - SubscriptionImpl subs; - if (subscriptions.contains(subscriptionId)) { - subs = subscriptions.get(subscriptionId); - if (!subs.isSubscribedToResource(resource)) { - throw new DavException(DavServletResponse.SC_PRECONDITION_FAILED, "Attempt to operate on subscription with invalid resource path."); - } - if (subs.isExpired()) { - unregisterSubscription(subs, resource); - throw new DavException(DavServletResponse.SC_PRECONDITION_FAILED, "Attempt to operate on expired subscription."); - } - return subs; - } else { - throw new DavException(DavServletResponse.SC_PRECONDITION_FAILED, "Attempt to modify or to poll for non-existing subscription."); - } - } - - /** - * @param resource - * @return JCR session - */ - private static Session getRepositorySession(ObservationResource resource) throws DavException { - return JcrDavSession.getRepositorySession(resource.getSession()); - } - - //---------------------------< TransactionListener >------------------------ - - /** - * {@inheritDoc} - */ - public synchronized void beforeCommit(TransactionResource resource, - String lockToken) { - // suspend regular subscriptions during a commit - List transactionListeners = new ArrayList(); - for (Iterator it = subscriptions.iterator(); it.hasNext(); ) { - SubscriptionImpl sub = it.next(); - TransactionListener tl = sub.createTransactionListener(); - tl.beforeCommit(resource, lockToken); - transactionListeners.add(tl); - } - transactionListenerById.put(lockToken, transactionListeners); - } - - /** - * {@inheritDoc} - */ - public void afterCommit(TransactionResource resource, String lockToken, boolean success) { - List transactionListeners = transactionListenerById.remove(lockToken); - if (transactionListeners != null) { - for (TransactionListener txListener : transactionListeners) { - txListener.afterCommit(resource, lockToken, success); - } - } - } - - //----------------------------------------------< private inner classes >--- - /** - * Private inner class wrapping around an Subscription as - * present in the internal map. This allows to hide the subscription Id - * from other sessions, that did create the subscription. - */ - private static class WrappedSubscription implements Subscription { - - private final Subscription delegatee; - - private WrappedSubscription(Subscription subsc) { - this.delegatee = subsc; - } - - public String getSubscriptionId() { - // always return null, since the subscription id must not be exposed - // but to the client, that created the subscription. - return null; - } - - public Element toXml(Document document) { - return delegatee.toXml(document); - } - - public boolean eventsProvideNodeTypeInformation() { - return delegatee.eventsProvideNodeTypeInformation(); - } - - public boolean eventsProvideNoLocalFlag() { - return delegatee.eventsProvideNoLocalFlag(); - } - } - - /** - * Private inner class SubscriptionMap that allows for quick - * access by resource path as well as by subscription id. - */ - private class SubscriptionMap { - - private HashMap subscriptions = new HashMap(); - private HashMap> ids = new HashMap>(); - - private boolean contains(String subscriptionId) { - return subscriptions.containsKey(subscriptionId); - } - - private SubscriptionImpl get(String subscriptionId) { - return subscriptions.get(subscriptionId); - } - - private Iterator iterator() { - return subscriptions.values().iterator(); - } - - private void put(String subscriptionId, SubscriptionImpl subscription) { - subscriptions.put(subscriptionId, subscription); - DavResourceLocator key = subscription.getLocator(); - Set idSet; - if (ids.containsKey(key)) { - idSet = ids.get(key); - } else { - idSet = new HashSet(); - ids.put(key, idSet); - } - if (!idSet.contains(subscriptionId)) { - idSet.add(subscriptionId); - } - } - - private void remove(String subscriptionId) { - SubscriptionImpl sub = subscriptions.remove(subscriptionId); - ids.get(sub.getLocator()).remove(subscriptionId); - } - - private Subscription[] getByPath(DavResourceLocator locator) { - Set idSet = ids.get(locator); - if (idSet != null && !idSet.isEmpty()) { - Subscription[] subsForResource = new Subscription[idSet.size()]; - int i = 0; - for (String id : idSet) { - SubscriptionImpl s = subscriptions.get(id); - subsForResource[i] = new WrappedSubscription(s); - i++; - } - return subsForResource; - } else { - return new Subscription[0]; - } - } - } -} Property changes on: jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/observation/SubscriptionManagerImpl.java ___________________________________________________________________ Deleted: svn Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/property/JcrDavPropertyNameSet.java =================================================================== --- jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/property/JcrDavPropertyNameSet.java (revision 1907912) +++ jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/property/JcrDavPropertyNameSet.java (nonexistent) @@ -1,155 +0,0 @@ -/* - * 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.webdav.jcr.property; - -import org.apache.jackrabbit.webdav.jcr.ItemResourceConstants; -import org.apache.jackrabbit.webdav.observation.ObservationConstants; -import org.apache.jackrabbit.webdav.property.DavPropertyName; -import org.apache.jackrabbit.webdav.property.DavPropertyNameSet; -import org.apache.jackrabbit.webdav.version.DeltaVConstants; -import org.apache.jackrabbit.webdav.version.VersionControlledResource; -import org.apache.jackrabbit.webdav.version.VersionHistoryResource; -import org.apache.jackrabbit.webdav.version.VersionResource; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * JcrDavPropertyNameSet... - */ -public final class JcrDavPropertyNameSet implements ItemResourceConstants { - - /** - * logger instance - */ - private static final Logger log = LoggerFactory.getLogger(JcrDavPropertyNameSet.class); - - - //------------------------------------------------< property name sets >---- - /** - * Default property names present with all resources. - */ - public static final DavPropertyNameSet BASE_SET = new DavPropertyNameSet(); - static { - BASE_SET.add(DavPropertyName.DISPLAYNAME); - BASE_SET.add(DavPropertyName.RESOURCETYPE); - BASE_SET.add(DavPropertyName.ISCOLLECTION); - BASE_SET.add(DavPropertyName.GETLASTMODIFIED); - BASE_SET.add(DavPropertyName.CREATIONDATE); - BASE_SET.add(DavPropertyName.SUPPORTEDLOCK); - BASE_SET.add(DavPropertyName.LOCKDISCOVERY); - BASE_SET.add(DeltaVConstants.SUPPORTED_METHOD_SET); - BASE_SET.add(DeltaVConstants.SUPPORTED_REPORT_SET); - BASE_SET.add(DeltaVConstants.CREATOR_DISPLAYNAME); - BASE_SET.add(DeltaVConstants.COMMENT); - BASE_SET.add(JCR_WORKSPACE_NAME); - } - - /** - * Property names defined for JCR workspace resources. - */ - public static final DavPropertyNameSet WORKSPACE_SET = new DavPropertyNameSet(); - static { - WORKSPACE_SET.add(DeltaVConstants.WORKSPACE); - WORKSPACE_SET.add(JCR_NAMESPACES); - WORKSPACE_SET.add(JCR_NODETYPES_CND); - } - - /** - * Additional property names defined for existing and non-existing item resources. - */ - public static final DavPropertyNameSet ITEM_BASE_SET = new DavPropertyNameSet(); - static { - ITEM_BASE_SET.add(DavPropertyName.GETCONTENTTYPE); - ITEM_BASE_SET.add(DeltaVConstants.WORKSPACE); - ITEM_BASE_SET.add(ObservationConstants.SUBSCRIPTIONDISCOVERY); - } - - /** - * Additional property names defined for existing item resources. - */ - public static final DavPropertyNameSet EXISTING_ITEM_BASE_SET = new DavPropertyNameSet(ITEM_BASE_SET); - static { - EXISTING_ITEM_BASE_SET.add(JCR_NAME); - EXISTING_ITEM_BASE_SET.add(JCR_PATH); - EXISTING_ITEM_BASE_SET.add(JCR_DEPTH); - EXISTING_ITEM_BASE_SET.add(JCR_DEFINITION); - } - - /** - * Additional property names defined by single value JCR properties. - */ - public static final DavPropertyNameSet PROPERTY_SET = new DavPropertyNameSet(); - static { - PROPERTY_SET.add(JCR_TYPE); - PROPERTY_SET.add(JCR_VALUE); - PROPERTY_SET.add(JCR_LENGTH); - } - - /** - * Additional property names defined by single value JCR properties. - */ - public static final DavPropertyNameSet PROPERTY_MV_SET = new DavPropertyNameSet(); - static { - PROPERTY_MV_SET.add(JCR_TYPE); - PROPERTY_MV_SET.add(JCR_VALUES); - PROPERTY_MV_SET.add(JCR_LENGTHS); - } - - /** - * Additional property names defined by regular JCR nodes. - */ - public static final DavPropertyNameSet NODE_SET = new DavPropertyNameSet(); - static { - NODE_SET.add(JCR_PRIMARYNODETYPE); - NODE_SET.add(JCR_MIXINNODETYPES); - NODE_SET.add(JCR_INDEX); - NODE_SET.add(JCR_REFERENCES); - NODE_SET.add(JCR_WEAK_REFERENCES); - } - - /** - * Additional property names defined by versionable JCR nodes. - */ - public static final DavPropertyNameSet VERSIONABLE_SET = new DavPropertyNameSet(); - static { - VERSIONABLE_SET.add(VersionControlledResource.VERSION_HISTORY); - VERSIONABLE_SET.add(VersionControlledResource.AUTO_VERSION); - } - - /** - * Additional property names defined by JCR version nodes. - */ - public static final DavPropertyNameSet VERSION_SET = new DavPropertyNameSet(); - static { - VERSION_SET.add(VersionResource.VERSION_NAME); - VERSION_SET.add(VersionResource.LABEL_NAME_SET); - VERSION_SET.add(VersionResource.PREDECESSOR_SET); - VERSION_SET.add(VersionResource.SUCCESSOR_SET); - VERSION_SET.add(VersionResource.VERSION_HISTORY); - VERSION_SET.add(VersionResource.CHECKOUT_SET); - } - - /** - * Additional property names defined by JCR version history nodes. - */ - public static final DavPropertyNameSet VERSIONHISTORY_SET = new DavPropertyNameSet(); - static { - VERSIONHISTORY_SET.add(VersionHistoryResource.ROOT_VERSION); - VERSIONHISTORY_SET.add(VersionHistoryResource.VERSION_SET); - VERSIONHISTORY_SET.add(JCR_VERSIONABLEUUID); - } -} \ No newline at end of file Property changes on: jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/property/JcrDavPropertyNameSet.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Deleted: svn:keywords ## -1 +0,0 ## -Author Date Id Revision Rev URL \ No newline at end of property Index: jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/property/LengthsProperty.java =================================================================== --- jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/property/LengthsProperty.java (revision 1907912) +++ jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/property/LengthsProperty.java (nonexistent) @@ -1,67 +0,0 @@ -/* - * 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.webdav.jcr.property; - -import org.apache.jackrabbit.webdav.jcr.ItemResourceConstants; -import org.apache.jackrabbit.webdav.property.AbstractDavProperty; -import org.apache.jackrabbit.webdav.xml.DomUtil; -import org.w3c.dom.Document; -import org.w3c.dom.Element; - -/** - * LengthsProperty extends {@link org.apache.jackrabbit.webdav.property.DavProperty} providing - * utilities to handle the multiple lengths of the property item represented - * by this resource. - */ -public class LengthsProperty extends AbstractDavProperty implements ItemResourceConstants { - - private final long[] value; - - /** - * Create a new LengthsProperty from the given long array. - * - * @param lengths as retrieved from the JCR property - */ - public LengthsProperty(long[] lengths) { - super(JCR_LENGTHS, true); - this.value = lengths; - } - - /** - * Returns an array of {@link long}s representing the value of this - * property. - * - * @return an array of {@link long}s - */ - public long[] getValue() { - return value; - } - - /** - * @see org.apache.jackrabbit.webdav.xml.XmlSerializable#toXml(Document) - */ - @Override - public Element toXml(Document document) { - Element elem = getName().toXml(document); - for (long length : value) { - String txtContent = String.valueOf(length); - DomUtil.addChildElement(elem, XML_LENGTH, ItemResourceConstants.NAMESPACE, txtContent); - } - return elem; - } - -} Property changes on: jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/property/LengthsProperty.java ___________________________________________________________________ Deleted: svn Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/property/NamespacesProperty.java =================================================================== --- jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/property/NamespacesProperty.java (revision 1907912) +++ jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/property/NamespacesProperty.java (nonexistent) @@ -1,107 +0,0 @@ -/* - * 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.webdav.jcr.property; - -import org.apache.jackrabbit.webdav.DavException; -import org.apache.jackrabbit.webdav.DavServletResponse; -import org.apache.jackrabbit.webdav.jcr.ItemResourceConstants; -import org.apache.jackrabbit.webdav.property.AbstractDavProperty; -import org.apache.jackrabbit.webdav.property.DavProperty; -import org.apache.jackrabbit.webdav.xml.DomUtil; -import org.apache.jackrabbit.webdav.xml.Namespace; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.w3c.dom.Document; -import org.w3c.dom.Element; - -import javax.jcr.NamespaceRegistry; -import javax.jcr.RepositoryException; -import java.util.List; -import java.util.Map; -import java.util.HashMap; -import java.util.Collections; - -/** - * NamespacesProperty... - */ -public class NamespacesProperty extends AbstractDavProperty> implements ItemResourceConstants { - - private static Logger log = LoggerFactory.getLogger(NamespacesProperty.class); - - private final Map value = new HashMap(); - - public NamespacesProperty(NamespaceRegistry nsReg) throws RepositoryException { - super(JCR_NAMESPACES, false); - if (nsReg != null) { - for (String prefix : nsReg.getPrefixes()) { - value.put(prefix, nsReg.getURI(prefix)); - } - } - } - - public NamespacesProperty(Map namespaces) { - super(JCR_NAMESPACES, false); - value.putAll(namespaces); - } - - public NamespacesProperty(DavProperty property) throws DavException { - super(JCR_NAMESPACES, false); - Object v = property.getValue(); - if (!(v instanceof List)) { - log.warn("Unexpected structure of dcr:namespace property."); - throw new DavException(DavServletResponse.SC_INTERNAL_SERVER_ERROR); - } - // retrieve list of prefix/uri pairs that build the new values of - // the ns-registry - for (Object listEntry : (List) v) { - if (listEntry instanceof Element) { - Element e = (Element)listEntry; - if (XML_NAMESPACE.equals(e.getLocalName())) { - Element pElem = DomUtil.getChildElement(e, XML_PREFIX, ItemResourceConstants.NAMESPACE); - String prefix = DomUtil.getText(pElem, Namespace.EMPTY_NAMESPACE.getPrefix()); - Element uElem = DomUtil.getChildElement(e, XML_URI, ItemResourceConstants.NAMESPACE); - String uri = DomUtil.getText(uElem, Namespace.EMPTY_NAMESPACE.getURI()); - value.put(prefix, uri); - } - } - } - } - - public Map getNamespaces() { - return Collections.unmodifiableMap(value); - } - - public Map getValue() { - return Collections.unmodifiableMap(value); - } - - /** - * @see org.apache.jackrabbit.webdav.xml.XmlSerializable#toXml(Document) - */ - @Override - public Element toXml(Document document) { - Element elem = getName().toXml(document); - for (String prefix : value.keySet()) { - String uri = value.get(prefix); - Element nsElem = DomUtil.addChildElement(elem, XML_NAMESPACE, ItemResourceConstants.NAMESPACE); - DomUtil.addChildElement(nsElem, XML_PREFIX, ItemResourceConstants.NAMESPACE, prefix); - DomUtil.addChildElement(nsElem, XML_URI, ItemResourceConstants.NAMESPACE, uri); - } - return elem; - } - -} Property changes on: jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/property/NamespacesProperty.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Deleted: svn:keywords ## -1 +0,0 ## -author date id revision url \ No newline at end of property Index: jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/property/ValuesProperty.java =================================================================== --- jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/property/ValuesProperty.java (revision 1907912) +++ jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/property/ValuesProperty.java (nonexistent) @@ -1,191 +0,0 @@ -/* - * 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.webdav.jcr.property; - -import org.apache.jackrabbit.commons.webdav.ValueUtil; -import org.apache.jackrabbit.value.ValueHelper; -import org.apache.jackrabbit.webdav.DavException; -import org.apache.jackrabbit.webdav.DavServletResponse; -import org.apache.jackrabbit.webdav.jcr.ItemResourceConstants; -import org.apache.jackrabbit.webdav.property.AbstractDavProperty; -import org.apache.jackrabbit.webdav.property.DavProperty; -import org.apache.jackrabbit.webdav.property.DavPropertyName; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.w3c.dom.Document; -import org.w3c.dom.Element; - -import javax.jcr.PropertyType; -import javax.jcr.RepositoryException; -import javax.jcr.Value; -import javax.jcr.ValueFormatException; -import javax.jcr.ValueFactory; - -/** - * ValuesProperty implements {@link org.apache.jackrabbit.webdav.property.DavProperty} - * providing utilities to handle the value(s) of a JCR property item resource. - * In case the property is multivalued the DavProperty value consists of - * an element named {@link #JCR_VALUES} otherwise its name is {@link #JCR_VALUE}. - */ -public class ValuesProperty extends AbstractDavProperty implements ItemResourceConstants { - - private static Logger log = LoggerFactory.getLogger(ValuesProperty.class); - - private final Value[] jcrValues; - - /** - * Create a new ValuesProperty from the given single {@link Value}. - * - * @param value Array of Value objects as obtained from the JCR property. - */ - public ValuesProperty(Value value) { - super(JCR_VALUE, false); - // finally set the value to the DavProperty - jcrValues = (value == null) ? new Value[0] : new Value[] {value}; - } - - /** - * Create a new ValuesProperty from the given {@link javax.jcr.Value Value - * array}. - * - * @param values Array of Value objects as obtained from the JCR property. - */ - public ValuesProperty(Value[] values) { - super(JCR_VALUES, false); - // finally set the value to the DavProperty - jcrValues = (values == null) ? new Value[0] : values; - } - - /** - * Wrap the specified DavProperty in a new ValuesProperty. - * - * @param property - * @param defaultType default type of the values to be deserialized. If however - * the {@link #XML_VALUE 'value'} elements provide a {@link #ATTR_VALUE_TYPE 'type'} - * attribute, the default value is ignored. - * @param valueFactory Factory used to retrieve JCR values from the value - * of the given DavProperty. - */ - public ValuesProperty(DavProperty property, int defaultType, - ValueFactory valueFactory) - throws RepositoryException, DavException { - super(property.getName(), false); - - if (!(JCR_VALUES.equals(property.getName()) || JCR_VALUE.equals(getName()))) { - throw new DavException(DavServletResponse.SC_BAD_REQUEST, "ValuesProperty may only be created with a property that has name="+JCR_VALUES.getName()); - } - - jcrValues = ValueUtil.valuesFromXml(property.getValue(), defaultType, valueFactory); - } - - private void checkPropertyName(DavPropertyName reqName) throws ValueFormatException { - if (!reqName.equals(getName())) { - throw new ValueFormatException("Attempt to retrieve multiple values from single property '" + getName() + "'."); - } - } - - /** - * Converts the value of this property to a {@link javax.jcr.Value value array}. - * - * @return Array of Value objects - * @throws ValueFormatException if converting the internal jcr values to - * the specified value type fails. - */ - public Value[] getJcrValues(int propertyType, ValueFactory valueFactory) throws ValueFormatException { - checkPropertyName(JCR_VALUES); - Value[] vs = new Value[jcrValues.length]; - for (int i = 0; i < jcrValues.length; i++) { - vs[i] = ValueHelper.convert(jcrValues[i], propertyType, valueFactory); - } - return vs; - } - - /** - * Returns the internal property value as jcr Value array - * - * @return the internal property value as jcr Value array - */ - public Value[] getJcrValues() throws ValueFormatException { - checkPropertyName(JCR_VALUES); - return jcrValues; - } - - /** - * - * @param propertyType - * @return - * @throws ValueFormatException - */ - public Value getJcrValue(int propertyType, ValueFactory valueFactory) throws ValueFormatException { - checkPropertyName(JCR_VALUE); - return (jcrValues.length == 0) - ? null - : ValueHelper.convert(jcrValues[0], propertyType, valueFactory); - } - - /** - * - * @return - * @throws ValueFormatException - */ - public Value getJcrValue() throws ValueFormatException { - checkPropertyName(JCR_VALUE); - return (jcrValues.length == 0) ? null : jcrValues[0]; - } - - /** - * Returns the type of the {@link Value value}s present in this property - * or {@link PropertyType#UNDEFINED} if no values are available. - * - * @return type of values or {@link PropertyType#UNDEFINED} - */ - public int getValueType() { - // TODO: check if correct behaviour if values array is empty - return (jcrValues.length > 0) ? jcrValues[0].getType() : PropertyType.UNDEFINED; - } - - /** - * Returns an array of {@link Value}s representing the value of this - * property. - * - * @return an array of {@link Value}s - * @see #getJcrValues() - * @see #getJcrValue() - */ - public Value[] getValue() { - return jcrValues; - } - - /** - * - * @param document - * @return the xml element - */ - @Override - public Element toXml(Document document) { - Element elem = getName().toXml(document); - try { - for (Value v : jcrValues) { - Element xmlValue = ValueUtil.valueToXml(v, document); - elem.appendChild(xmlValue); - } - } catch (RepositoryException e) { - log.error("Unexpected Error while converting jcr value to String: " + e.getMessage()); - } - return elem; - } -} Property changes on: jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/property/ValuesProperty.java ___________________________________________________________________ Deleted: svn Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/search/SearchResourceImpl.java =================================================================== --- jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/search/SearchResourceImpl.java (revision 1907912) +++ jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/search/SearchResourceImpl.java (nonexistent) @@ -1,403 +0,0 @@ -/* - * 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.webdav.jcr.search; - -import org.apache.jackrabbit.JcrConstants; -import org.apache.jackrabbit.webdav.DavException; -import org.apache.jackrabbit.webdav.DavResourceLocator; -import org.apache.jackrabbit.webdav.DavServletResponse; -import org.apache.jackrabbit.webdav.MultiStatus; -import org.apache.jackrabbit.webdav.MultiStatusResponse; -import org.apache.jackrabbit.webdav.jcr.ItemResourceConstants; -import org.apache.jackrabbit.webdav.jcr.JcrDavException; -import org.apache.jackrabbit.webdav.jcr.JcrDavSession; -import org.apache.jackrabbit.webdav.search.QueryGrammerSet; -import org.apache.jackrabbit.webdav.search.SearchInfo; -import org.apache.jackrabbit.webdav.search.SearchResource; -import org.apache.jackrabbit.webdav.xml.Namespace; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.apache.jackrabbit.util.ISO9075; - -import javax.jcr.Node; -import javax.jcr.RepositoryException; -import javax.jcr.Session; -import javax.jcr.Value; -import javax.jcr.NamespaceRegistry; -import javax.jcr.ValueFactory; -import javax.jcr.PropertyType; -import javax.jcr.query.InvalidQueryException; -import javax.jcr.query.Query; -import javax.jcr.query.QueryManager; -import javax.jcr.query.QueryResult; -import javax.jcr.query.Row; -import javax.jcr.query.RowIterator; - -import java.util.Map; -import java.util.List; -import java.util.ArrayList; - -/** - * SearchResourceImpl... - */ -public class SearchResourceImpl implements SearchResource { - - private static Logger log = LoggerFactory.getLogger(SearchResourceImpl.class); - - private final JcrDavSession session; - private final DavResourceLocator locator; - - public SearchResourceImpl(DavResourceLocator locator, JcrDavSession session) { - this.session = session; - this.locator = locator; - } - - //-------------------------------------------< SearchResource interface >--- - /** - * @see SearchResource#getQueryGrammerSet() - */ - public QueryGrammerSet getQueryGrammerSet() { - QueryGrammerSet qgs = new QueryGrammerSet(); - try { - QueryManager qMgr = getRepositorySession().getWorkspace().getQueryManager(); - String[] langs = qMgr.getSupportedQueryLanguages(); - for (String lang : langs) { - // Note: Existing clients already assume that the - // query languages returned in the DASL header are - // not prefixed with any namespace, so we probably - // shouldn't use an explicit namespace here. - qgs.addQueryLanguage(lang, Namespace.EMPTY_NAMESPACE); - } - } catch (RepositoryException e) { - log.debug(e.getMessage()); - } - return qgs; - } - - /** - * Execute the query defined by the given sInfo. - * - * @see SearchResource#search(org.apache.jackrabbit.webdav.search.SearchInfo) - */ - public MultiStatus search(SearchInfo sInfo) throws DavException { - try { - QueryResult result = getQuery(sInfo).execute(); - - MultiStatus ms = new MultiStatus(); - - if (ItemResourceConstants.NAMESPACE.equals( - sInfo.getLanguageNameSpace())) { - ms.setResponseDescription( - "Columns: " + encode(result.getColumnNames()) - + "\nSelectors: " + encode(result.getSelectorNames())); - } else { - ms.setResponseDescription(encode(result.getColumnNames())); - } - - queryResultToMultiStatus(result, ms); - - return ms; - } catch (RepositoryException e) { - throw new JcrDavException(e); - } - } - - /** - * Create a query from the information present in the sInfo - * object.
The following JCR specific logic is applied: - *
    - *
  • If the requested resource represents a node with nodetype nt:query, the - * request body is ignored and the query defined with the node is executed - * instead.
  • - *
  • If the requested resource does not represent an existing item, the - * specified query is persisted by calling {@link Query#storeAsNode(String)}.
  • - *
- * @param sInfo defining the query to be executed - * @return Query object. - * @throws javax.jcr.query.InvalidQueryException if the query defined by sInfo is invalid - * @throws RepositoryException the query manager cannot be accessed or if - * another error occurs. - * @throws DavException if sInfo is null and - * the underlying repository item is not an nt:query node or if an error - * occurs when calling {@link Query#storeAsNode(String)}/ - */ - private Query getQuery(SearchInfo sInfo) - throws InvalidQueryException, RepositoryException, DavException { - - Session session = getRepositorySession(); - NamespaceRegistry nsReg = session.getWorkspace().getNamespaceRegistry(); - Node rootNode = session.getRootNode(); - QueryManager qMgr = getRepositorySession().getWorkspace().getQueryManager(); - - // test if query is defined by requested repository node - String itemPath = locator.getRepositoryPath(); - if (itemPath != null && !rootNode.getPath().equals(itemPath)) { - String qNodeRelPath = itemPath.substring(1); - if (rootNode.hasNode(qNodeRelPath)) { - Node qNode = rootNode.getNode(qNodeRelPath); - if (qNode.isNodeType(JcrConstants.NT_QUERY)) { - return qMgr.getQuery(qNode); - } - } - } - - Query q; - if (sInfo != null) { - // apply namespace mappings to session - Map namespaces = sInfo.getNamespaces(); - try { - for (Map.Entry entry : namespaces.entrySet()) { - String prefix = entry.getKey(); - String uri = entry.getValue(); - session.setNamespacePrefix(prefix, uri); - } - q = qMgr.createQuery(sInfo.getQuery(), sInfo.getLanguageName()); - - if (SearchInfo.NRESULTS_UNDEFINED != sInfo.getNumberResults()) { - q.setLimit(sInfo.getNumberResults()); - } - if (SearchInfo.OFFSET_UNDEFINED != sInfo.getOffset()) { - q.setOffset(sInfo.getOffset()); - } - } finally { - // reset namespace mappings - for (String uri : namespaces.values()) { - try { - session.setNamespacePrefix(nsReg.getPrefix(uri), uri); - } catch (RepositoryException e) { - log.warn("Unable to reset mapping of namespace: " + uri); - } - } - } - } else { - throw new DavException(DavServletResponse.SC_BAD_REQUEST, locator.getResourcePath() + " is not a nt:query node -> searchRequest body required."); - } - - /* test if resource path does not exist -> thus indicating that - the query must be made persistent by calling Query.save(String) */ - if (itemPath != null && !getRepositorySession().itemExists(itemPath)) { - try { - q.storeAsNode(itemPath); - } catch (RepositoryException e) { - // ItemExistsException should never occur. - throw new JcrDavException(e); - } - } - return q; - } - - /** - * Build a MultiStatus object from the specified query result. - * - * @param query the query to execute. - * @return MultiStatus object listing the query result in - * Webdav compatible form. - * @throws RepositoryException if an error occurs. - */ - private void queryResultToMultiStatus(QueryResult result, MultiStatus ms) - throws RepositoryException { - List columnNames = new ArrayList(); - - ValueFactory vf = getRepositorySession().getValueFactory(); - List descr = new ArrayList(); - for (String columnName : result.getColumnNames()) { - if (!isPathOrScore(columnName)) { - columnNames.add(columnName); - descr.add(new PlainValue(columnName, null, vf)); - } - } - - // add path and score for each selector - String[] sns = result.getSelectorNames(); - boolean join = sns.length > 1; - for (String selectorName : sns) { - descr.add(new PathValue(JcrConstants.JCR_PATH, selectorName, vf)); - columnNames.add(JcrConstants.JCR_PATH); - descr.add(new ScoreValue(JcrConstants.JCR_SCORE, selectorName, vf)); - columnNames.add(JcrConstants.JCR_SCORE); - } - - int n = 0; - String root = getHref("/"); - String[] selectorNames = createSelectorNames(descr); - String[] colNames = columnNames.toArray(new String[columnNames.size()]); - RowIterator rowIter = result.getRows(); - while (rowIter.hasNext()) { - Row row = rowIter.nextRow(); - List values = new ArrayList(); - for (RowValue rv : descr) { - values.add(rv.getValue(row)); - } - - // create a new ms-response for this row of the result set - String href; - if (join) { - // We need a distinct href for each join result row to - // allow the MultiStatus response to keep them separate - href = root + "?" + n++; - } else { - href = getHref(row.getPath()); - } - MultiStatusResponse resp = new MultiStatusResponse(href, null); - - // build the s-r-property - SearchResultProperty srp = new SearchResultProperty(colNames, - selectorNames, values.toArray(new Value[values.size()])); - resp.add(srp); - ms.addResponse(resp); - } - } - - /** - * Returns the resource location of the given query result row. - * The result rows of join queries have no meaningful single resource - * location, so we'll just default to the root node for all such rows. - * - * @param row query result row - * @param join flag to indicate a join query - * @return resource location of the row - */ - private String getHref(String path) throws RepositoryException { - DavResourceLocator l = locator.getFactory().createResourceLocator( - locator.getPrefix(), locator.getWorkspacePath(), path, false); - return l.getHref(true); - } - - private String encode(String[] names) { - StringBuilder builder = new StringBuilder(); - String delim = ""; - for (String name : names) { - builder.append(delim); - builder.append(ISO9075.encode(name)); - delim = " "; - } - return builder.toString(); - } - - private static String[] createSelectorNames(Iterable rows) - throws RepositoryException { - List sn = new ArrayList(); - for (RowValue rv : rows) { - sn.add(rv.getSelectorName()); - } - return sn.toArray(new String[sn.size()]); - } - - /** - * @param columnName a column name. - * @return true if columnName is either - * jcr:path or jcr:score; - * false otherwise. - */ - private static boolean isPathOrScore(String columnName) { - return JcrConstants.JCR_PATH.equals(columnName) - || JcrConstants.JCR_SCORE.equals(columnName); - } - - /** - * @return the session associated with this resource. - */ - private Session getRepositorySession() { - return session.getRepositorySession(); - } - - private interface RowValue { - - public Value getValue(Row row) throws RepositoryException; - - public String getColumnName() throws RepositoryException; - - public String getSelectorName() throws RepositoryException; - } - - private static final class PlainValue extends SelectorValue { - - public PlainValue(String columnName, - String selectorName, - ValueFactory vf) { - super(columnName, selectorName, vf); - } - - public Value getValue(Row row) throws RepositoryException { - return row.getValue(columnName); - } - } - - private static abstract class SelectorValue implements RowValue { - - protected final String columnName; - - protected final String selectorName; - - protected final ValueFactory vf; - - public SelectorValue(String columnName, - String selectorName, - ValueFactory vf) { - this.columnName = columnName; - this.selectorName = selectorName; - this.vf = vf; - } - - public String getColumnName() throws RepositoryException { - return columnName; - } - - public String getSelectorName() throws RepositoryException { - return selectorName; - } - } - - private static final class ScoreValue extends SelectorValue { - - public ScoreValue(String columnName, - String selectorName, - ValueFactory vf) { - super(columnName, selectorName, vf); - } - - public Value getValue(Row row) throws RepositoryException { - double score; - if (selectorName != null) { - score = row.getScore(selectorName); - } else { - score = row.getScore(); - } - return vf.createValue(score); - } - } - - private static final class PathValue extends SelectorValue { - - public PathValue(String columnName, - String selectorName, - ValueFactory vf) { - super(columnName, selectorName, vf); - } - - public Value getValue(Row row) throws RepositoryException { - String path; - if (selectorName != null) { - path = row.getPath(selectorName); - } else { - path = row.getPath(); - } - return (path == null) ? null : vf.createValue(path, PropertyType.PATH); - } - } - -} \ No newline at end of file Property changes on: jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/search/SearchResourceImpl.java ___________________________________________________________________ Deleted: svn Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/search/SearchResultProperty.java =================================================================== --- jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/search/SearchResultProperty.java (revision 1907912) +++ jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/search/SearchResultProperty.java (nonexistent) @@ -1,201 +0,0 @@ -/* - * 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.webdav.jcr.search; - -import org.apache.jackrabbit.commons.webdav.QueryUtil; -import org.apache.jackrabbit.value.ValueHelper; -import org.apache.jackrabbit.webdav.jcr.ItemResourceConstants; -import org.apache.jackrabbit.webdav.property.AbstractDavProperty; -import org.apache.jackrabbit.webdav.property.DavProperty; -import org.apache.jackrabbit.webdav.property.DavPropertyName; -import org.apache.jackrabbit.webdav.xml.DomUtil; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.w3c.dom.Document; -import org.w3c.dom.Element; - -import javax.jcr.PropertyType; -import javax.jcr.RepositoryException; -import javax.jcr.Value; -import javax.jcr.ValueFactory; -import java.util.ArrayList; -import java.util.List; - -/** - * SearchResultProperty... - */ -// todo: find proper solution for transporting search results... -public class SearchResultProperty extends AbstractDavProperty implements ItemResourceConstants { - - private static Logger log = LoggerFactory.getLogger(SearchResultProperty.class); - - private static final DavPropertyName SEARCH_RESULT_PROPERTY = DavPropertyName.create(JCR_QUERY_RESULT_LN, ItemResourceConstants.NAMESPACE); - - private final String[] columnNames; - private final String[] selectorNames; - private final Value[] values; - - /** - * Creates a new SearchResultProperty. - * - * @param columnNames the column names of the search row represented by - * this dav property. - * @param selectorNames the selector names of the row represented by this - * dav property. - * @param values the values present in the columns - */ - public SearchResultProperty(String[] columnNames, - String[] selectorNames, - Value[] values) { - super(SEARCH_RESULT_PROPERTY, true); - this.columnNames = columnNames; - this.selectorNames = selectorNames; - this.values = values; - } - - /** - * Wrap the specified DavProperty in a new SearchResultProperty. - * - * @param property - * @param valueFactory factory used to deserialize the xml value to a JCR value. - * @throws RepositoryException if an error occurs while build the property value - * @throws IllegalArgumentException if the specified property does have the - * required form. - * @see #getValues() - */ - public SearchResultProperty(DavProperty property, ValueFactory valueFactory) throws RepositoryException { - super(property.getName(), true); - if (!SEARCH_RESULT_PROPERTY.equals(getName())) { - throw new IllegalArgumentException("SearchResultProperty may only be created from a property named " + SEARCH_RESULT_PROPERTY.toString()); - } - - List colList = new ArrayList(); - List selList = new ArrayList(); - List valList = new ArrayList(); - - QueryUtil.parseResultPropertyValue(property.getValue(), colList, selList, valList, valueFactory); - - columnNames = colList.toArray(new String[colList.size()]); - selectorNames = selList.toArray(new String[selList.size()]); - values = valList.toArray(new Value[valList.size()]); - } - - /** - * Return the column names representing the names of the properties present - * in the {@link #getValues() values}. - * - * @return columnNames - */ - public String[] getColumnNames() { - return columnNames; - } - - /** - * @return the selector name for each of the columns in the result property. - */ - public String[] getSelectorNames() { - return selectorNames; - } - - /** - * Return the values representing the values of that row in the search - * result table. - * - * @return values - * @see javax.jcr.query.Row#getValues() - */ - public Value[] getValues() { - return values; - } - - - /** - * Same as {@link #getValues()} - * - * @return Array of JCR Value object - */ - public Value[] getValue() { - return values; - } - - /** - * Return the xml representation of this webdav property. For every value in - * the query result row a dcr:name, dcr:value, dcr:type and an optional - * dcr:selectorName element is created. - * Example: - *
-     * -----------------------------------------------------------
-     *   col-name  |   bla   |   bli   |  jcr:path  |  jcr:score
-     * -----------------------------------------------------------
-     *   value     |   xxx   |   111   |  /aNode    |    1
-     *   type      |    1    |    3    |     8      |    3
-     *   sel-name  |         |         |     S      |    S
-     * -----------------------------------------------------------
-     * 
- * results in: - *
-     * <dcr:search-result-property xmlns:dcr="http://www.day.com/jcr/webdav/1.0">
-     *    <dcr:column>
-     *       <dcr:name>bla<dcr:name/>
-     *       <dcr:value dcr:type="String">xxx<dcr:value/>
-     *    </dcr:column>
-     *    <dcr:column>
-     *       <dcr:name>bli<dcr:name/>
-     *       <dcr:value dcr:type="Long">111<dcr:value/>
-     *    </dcr:column>
-     *    <dcr:column>
-     *       <dcr:name>jcr:path<dcr:name/>
-     *       <dcr:value dcr:type="Path">/aNode<dcr:value/>
-     *       <dcr:selectorName>S<dcr:selectorName/>
-     *    </dcr:column>
-     *    <dcr:column>
-     *       <dcr:name>jcr:score<dcr:name/>
-     *       <dcr:value dcr:type="Long">1<dcr:value/>
-     *       <dcr:selectorName>S<dcr:selectorName/>
-     *    </dcr:column>
-     * </dcr:search-result-property>
-     * 
- * - * @see org.apache.jackrabbit.webdav.xml.XmlSerializable#toXml(org.w3c.dom.Document) - */ - @Override - public Element toXml(Document document) { - Element elem = getName().toXml(document); - for (int i = 0; i < columnNames.length; i++) { - String propertyName = columnNames[i]; - String selectorName = selectorNames[i]; - Value propertyValue = values[i]; - - Element columnEl = DomUtil.addChildElement(elem, XML_QUERY_RESULT_COLUMN, ItemResourceConstants.NAMESPACE); - DomUtil.addChildElement(columnEl, JCR_NAME.getName(), JCR_NAME.getNamespace(), propertyName); - if (propertyValue != null) { - try { - String serializedValue = ValueHelper.serialize(propertyValue, true); - Element xmlValue = DomUtil.addChildElement(columnEl, XML_VALUE, ItemResourceConstants.NAMESPACE, serializedValue); - String type = PropertyType.nameFromValue(propertyValue.getType()); - DomUtil.setAttribute(xmlValue, ATTR_VALUE_TYPE, ItemResourceConstants.NAMESPACE, type); - } catch (RepositoryException e) { - log.error(e.toString()); - } - } - if (selectorName != null) { - DomUtil.addChildElement(columnEl, JCR_SELECTOR_NAME.getName(), JCR_SELECTOR_NAME.getNamespace(), selectorName); - } - } - return elem; - } -} Property changes on: jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/search/SearchResultProperty.java ___________________________________________________________________ Deleted: svn Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/security/JcrSupportedPrivilegesProperty.java =================================================================== --- jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/security/JcrSupportedPrivilegesProperty.java (revision 1907912) +++ jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/security/JcrSupportedPrivilegesProperty.java (nonexistent) @@ -1,122 +0,0 @@ -/* - * 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.webdav.jcr.security; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; -import javax.jcr.RepositoryException; -import javax.jcr.Session; -import javax.jcr.security.AccessControlManager; -import javax.jcr.security.Privilege; - -import org.apache.jackrabbit.util.Text; -import org.apache.jackrabbit.webdav.security.SupportedPrivilege; -import org.apache.jackrabbit.webdav.security.SupportedPrivilegeSetProperty; -import org.apache.jackrabbit.webdav.xml.Namespace; - -/** - * JcrSupportedPrivilegesProperty... - */ -public class JcrSupportedPrivilegesProperty { - - private final Session session; - private final String absPath; - private final Set privileges = new HashSet(); - - private final Map supportedPrivileges = new HashMap(); - private final HashSet aggregated = new HashSet(); - - /** - * Build supported privileges for the jcr:all privilege. - * - * @param session The reading session - */ - public JcrSupportedPrivilegesProperty(Session session) throws RepositoryException { - this.session = session; - this.absPath = null; - AccessControlManager acMgr = session.getAccessControlManager(); - Privilege jcrAll = acMgr.privilegeFromName(Privilege.JCR_ALL); - privileges.add(jcrAll); - } - - /** - * @param session The reading session - * @param absPath An absolute path to an existing JCR node or {@code null}. - */ - public JcrSupportedPrivilegesProperty(Session session, String absPath) { - this.session = session; - this.absPath = absPath; - } - - /** - * Calculated the supported privileges at {@code absPath} and build a - * {@link org.apache.jackrabbit.webdav.security.SupportedPrivilegeSetProperty} - * from the result. - * - * @return a new {@code SupportedPrivilegeSetProperty} property. - * @throws RepositoryException - */ - public SupportedPrivilegeSetProperty asDavProperty() throws RepositoryException { - if (privileges.isEmpty()) { - AccessControlManager acMgr = session.getAccessControlManager(); - privileges.addAll(Arrays.asList(acMgr.getSupportedPrivileges(absPath))); - } - for (Privilege p : privileges) { - if (!aggregated.contains(p.getName())) { - createSupportedPrivilege(p); - } - } - return new SupportedPrivilegeSetProperty(supportedPrivileges.values().toArray(new SupportedPrivilege[supportedPrivileges.size()])); - } - - private SupportedPrivilege createSupportedPrivilege(Privilege privilege) throws RepositoryException { - String privilegeName = privilege.getName(); - - String localName = Text.getLocalName(privilegeName); - String prefix = Text.getNamespacePrefix(privilegeName); - Namespace ns = (prefix.isEmpty()) ? Namespace.EMPTY_NAMESPACE : Namespace.getNamespace(prefix, session.getNamespaceURI(prefix)); - org.apache.jackrabbit.webdav.security.Privilege davPrivilege = org.apache.jackrabbit.webdav.security.Privilege.getPrivilege(localName, ns); - - SupportedPrivilege[] aggregates = (privilege.isAggregate()) ? getDeclaredAggregates(privilege) : null; - - SupportedPrivilege sp = new SupportedPrivilege(davPrivilege, null, null, privilege.isAbstract(), aggregates); - if (!aggregated.contains(privilegeName)) { - supportedPrivileges.put(privilegeName, sp); - } - return sp; - } - - private SupportedPrivilege[] getDeclaredAggregates(Privilege privilege) throws RepositoryException { - List declAggr = new ArrayList(); - for (Privilege decl : privilege.getDeclaredAggregatePrivileges()) { - String name = decl.getName(); - if (aggregated.add(name)) { - if (supportedPrivileges.containsKey(name)) { - declAggr.add(supportedPrivileges.remove(name)); - } else { - declAggr.add(createSupportedPrivilege(decl)); - } - } - } - return declAggr.toArray(new SupportedPrivilege[declAggr.size()]); - } -} \ No newline at end of file Property changes on: jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/security/JcrSupportedPrivilegesProperty.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/security/JcrUserPrivilegesProperty.java =================================================================== --- jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/security/JcrUserPrivilegesProperty.java (revision 1907912) +++ jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/security/JcrUserPrivilegesProperty.java (nonexistent) @@ -1,58 +0,0 @@ -/* - * 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.webdav.jcr.security; - -import java.util.ArrayList; -import java.util.List; -import javax.jcr.RepositoryException; -import javax.jcr.Session; - -import org.apache.jackrabbit.util.Text; -import org.apache.jackrabbit.webdav.security.CurrentUserPrivilegeSetProperty; -import org.apache.jackrabbit.webdav.security.Privilege; -import org.apache.jackrabbit.webdav.xml.Namespace; - -/** - * JcrPrivilegesProperty... - */ -public class JcrUserPrivilegesProperty { - - private final Session session; - private final String absPath; - - /** - * @param session The reading session - * @param absPath An absolute path to an existing JCR node or {@code null}. - */ - public JcrUserPrivilegesProperty(Session session, String absPath) throws RepositoryException { - this.session = session; - this.absPath = absPath; - } - - public CurrentUserPrivilegeSetProperty asDavProperty() throws RepositoryException { - List davPrivs = new ArrayList(); - for (javax.jcr.security.Privilege privilege : session.getAccessControlManager().getPrivileges(absPath)) { - String privilegeName = privilege.getName(); - - String prefix = Text.getNamespacePrefix(privilegeName); - Namespace ns = (prefix.isEmpty()) ? Namespace.EMPTY_NAMESPACE : Namespace.getNamespace(prefix, session.getNamespaceURI(prefix)); - davPrivs.add(Privilege.getPrivilege(Text.getLocalName(privilegeName), ns)); - } - - return new CurrentUserPrivilegeSetProperty(davPrivs.toArray(new Privilege[davPrivs.size()])); - } -} \ No newline at end of file Property changes on: jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/security/JcrUserPrivilegesProperty.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/security/SecurityUtils.java =================================================================== --- jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/security/SecurityUtils.java (revision 1907912) +++ jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/security/SecurityUtils.java (nonexistent) @@ -1,30 +0,0 @@ -/* - * 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.webdav.jcr.security; - -import javax.jcr.Repository; -import javax.jcr.Session; - -public final class SecurityUtils { - - private SecurityUtils() {} - - public static boolean supportsAccessControl(Session session) { - String desc = session.getRepository().getDescriptor(Repository.OPTION_ACCESS_CONTROL_SUPPORTED); - return Boolean.valueOf(desc); - } -} \ No newline at end of file Property changes on: jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/security/SecurityUtils.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/transaction/TransactionListener.java =================================================================== --- jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/transaction/TransactionListener.java (revision 1907912) +++ jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/transaction/TransactionListener.java (nonexistent) @@ -1,43 +0,0 @@ -/* - * 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.webdav.jcr.transaction; - -import org.apache.jackrabbit.webdav.transaction.TransactionResource; - -/** - * TransactionListener provides callbacks when a transaction - * is committed. - */ -public interface TransactionListener { - - /** - * This method is called right before a transaction is committed. - * - * @param resource the transaction resource which will be committed. - * @param lockToken the lock token - */ - public void beforeCommit(TransactionResource resource, String lockToken); - - /** - * This method is called after the commit has been executed. - * - * @param resource the transaction resource which had been committed. - * @param lockToken the lock token. - * @param success if the commit was successful. - */ - public void afterCommit(TransactionResource resource, String lockToken, boolean success); -} Property changes on: jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/transaction/TransactionListener.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/transaction/TxLockManagerImpl.java =================================================================== --- jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/transaction/TxLockManagerImpl.java (revision 1907912) +++ jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/transaction/TxLockManagerImpl.java (nonexistent) @@ -1,796 +0,0 @@ -/* - * 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.webdav.jcr.transaction; - -import org.apache.jackrabbit.util.Text; -import org.apache.jackrabbit.webdav.DavConstants; -import org.apache.jackrabbit.webdav.DavException; -import org.apache.jackrabbit.webdav.DavResource; -import org.apache.jackrabbit.webdav.DavResourceLocator; -import org.apache.jackrabbit.webdav.DavServletResponse; -import org.apache.jackrabbit.webdav.WebdavResponse; -import org.apache.jackrabbit.webdav.jcr.JcrDavException; -import org.apache.jackrabbit.webdav.jcr.JcrDavSession; -import org.apache.jackrabbit.webdav.lock.ActiveLock; -import org.apache.jackrabbit.webdav.lock.LockInfo; -import org.apache.jackrabbit.webdav.lock.LockManager; -import org.apache.jackrabbit.webdav.lock.Scope; -import org.apache.jackrabbit.webdav.lock.Type; -import org.apache.jackrabbit.webdav.transaction.TransactionConstants; -import org.apache.jackrabbit.webdav.transaction.TransactionInfo; -import org.apache.jackrabbit.webdav.transaction.TransactionResource; -import org.apache.jackrabbit.webdav.transaction.TxActiveLock; -import org.apache.jackrabbit.webdav.transaction.TxLockManager; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import javax.jcr.Item; -import javax.jcr.PathNotFoundException; -import javax.jcr.RepositoryException; -import javax.jcr.Session; -import javax.transaction.xa.XAException; -import javax.transaction.xa.XAResource; -import javax.transaction.xa.Xid; -import java.util.HashMap; -import java.util.Iterator; -import java.util.IdentityHashMap; -import java.util.Map; - -/** - * TxLockManagerImpl manages locks with locktype - * '{@link TransactionConstants#TRANSACTION dcr:transaction}'. - *

- */ - //todo: removing all expired locks - //todo: 'local' and 'global' are not accurate terms in the given context > replace - /*todo: the usage of the 'global' transaction is not according to the JTA specification, - which explicitly requires any transaction present on a servlet to be completed before - the service method returns. Starting/completing transactions on the session object, - which is possible with the jackrabbit implementation is a hack.*/ - /*todo: review of this transaction part is therefore required. Is there a use-case - for those 'global' transactions at all...*/ -public class TxLockManagerImpl implements TxLockManager { - - private static Logger log = LoggerFactory.getLogger(TxLockManagerImpl.class); - - private final TransactionMap map = new TransactionMap(); - - private final Map listeners = new IdentityHashMap(); - - /** - * Create a new lock. - * - * @param lockInfo as present in the request body. - * @param resource - * @return the lock - * @throws DavException if the lock could not be obtained. - * @throws IllegalArgumentException if the resource is null or - * does not implement {@link TransactionResource} interface. - * @see LockManager#createLock(org.apache.jackrabbit.webdav.lock.LockInfo, org.apache.jackrabbit.webdav.DavResource) - */ - public ActiveLock createLock(LockInfo lockInfo, DavResource resource) - throws DavException { - if (resource == null || !(resource instanceof TransactionResource)) { - throw new IllegalArgumentException("Invalid resource"); - } - return createLock(lockInfo, (TransactionResource) resource); - } - - /** - * Create a new lock. - * - * @param lockInfo - * @param resource - * @return the lock - * @throws DavException if the request lock has the wrong lock type or if - * the lock could not be obtained for any reason. - */ - private synchronized ActiveLock createLock(LockInfo lockInfo, TransactionResource resource) - throws DavException { - if (!lockInfo.isDeep() || !TransactionConstants.TRANSACTION.equals(lockInfo.getType())) { - throw new DavException(DavServletResponse.SC_PRECONDITION_FAILED); - } - - ActiveLock existing = getLock(lockInfo.getType(), lockInfo.getScope(), resource); - if (existing != null) { - throw new DavException(DavServletResponse.SC_LOCKED); - } - // TODO: check for locks on member resources is required as well for lock is always deep! - - Transaction tx = createTransaction(resource.getLocator(), lockInfo); - tx.start(resource); - - // keep references to this lock - addReferences(tx, getMap(resource), resource); - - return tx.getLock(); - } - - /** - * Build the transaction object associated by the lock. - * - * @param locator - * @param lockInfo - * @return - */ - private Transaction createTransaction(DavResourceLocator locator, LockInfo lockInfo) { - if (TransactionConstants.GLOBAL.equals(lockInfo.getScope())) { - return new GlobalTransaction(locator, new TxActiveLock(lockInfo)); - } else { - return new LocalTransaction(locator, new TxActiveLock(lockInfo)); - } - } - - /** - * Refresh the lock identified by the given lock token. - * - * @param lockInfo - * @param lockToken - * @param resource - * @return the lock - * @throws DavException - * @throws IllegalArgumentException if the resource is null or - * does not implement {@link TransactionResource} interface. - * @see LockManager#refreshLock(org.apache.jackrabbit.webdav.lock.LockInfo, String, org.apache.jackrabbit.webdav.DavResource) - */ - public ActiveLock refreshLock(LockInfo lockInfo, String lockToken, - DavResource resource) throws DavException { - if (resource == null || !(resource instanceof TransactionResource)) { - throw new IllegalArgumentException("Invalid resource"); - } - return refreshLock(lockInfo, lockToken, (TransactionResource) resource); - } - - /** - * Reset the timeout of the lock identified by the given lock token. - * - * @param lockInfo - * @param lockToken - * @param resource - * @return - * @throws DavException if the lock did not exist or is expired. - */ - private synchronized ActiveLock refreshLock(LockInfo lockInfo, String lockToken, - TransactionResource resource) throws DavException { - - TransactionMap responsibleMap = getMap(resource); - Transaction tx = responsibleMap.get(lockToken); - if (tx == null) { - throw new DavException(DavServletResponse.SC_PRECONDITION_FAILED, "No valid transaction lock found for resource '" + resource.getResourcePath() + "'"); - } else if (tx.getLock().isExpired()) { - removeExpired(tx, responsibleMap, resource); - throw new DavException(DavServletResponse.SC_PRECONDITION_FAILED, "Transaction lock for resource '" + resource.getResourcePath() + "' was already expired."); - } else { - tx.getLock().setTimeout(lockInfo.getTimeout()); - } - return tx.getLock(); - } - - /** - * Throws UnsupportedOperationException. - * - * @param lockToken - * @param resource - * @throws DavException - * @see LockManager#releaseLock(String, org.apache.jackrabbit.webdav.DavResource) - */ - public void releaseLock(String lockToken, DavResource resource) - throws DavException { - throw new UnsupportedOperationException("A transaction lock can only be release with a TransactionInfo object and a lock token."); - } - - /** - * Release the lock identified by the given lock token. - * - * @param lockInfo - * @param lockToken - * @param resource - * @throws DavException - */ - public synchronized void releaseLock(TransactionInfo lockInfo, String lockToken, - TransactionResource resource) throws DavException { - if (resource == null) { - throw new IllegalArgumentException("Resource must not be null."); - } - TransactionMap responsibleMap = getMap(resource); - Transaction tx = responsibleMap.get(lockToken); - - if (tx == null) { - throw new DavException(DavServletResponse.SC_PRECONDITION_FAILED, "No transaction lock found for resource '" + resource.getResourcePath() + "'"); - } else if (tx.getLock().isExpired()) { - removeExpired(tx, responsibleMap, resource); - throw new DavException(DavServletResponse.SC_PRECONDITION_FAILED, "Transaction lock for resource '" + resource.getResourcePath() + "' was already expired."); - } else { - if (lockInfo.isCommit()) { - TransactionListener[] txListeners; - synchronized (listeners) { - txListeners = listeners.values().toArray(new TransactionListener[listeners.values().size()]); - } - for (TransactionListener txListener : txListeners) { - txListener.beforeCommit(resource, lockToken); - } - DavException ex = null; - try { - tx.commit(resource); - } catch (DavException e) { - ex = e; - } - for (TransactionListener txListener : txListeners) { - txListener.afterCommit(resource, lockToken, ex == null); - } - if (ex != null) { - throw ex; - } - } else { - tx.rollback(resource); - } - removeReferences(tx, responsibleMap, resource); - } - } - - /** - * Always returns null - * - * @param type - * @param scope - * @param resource - * @return null - * @see #getLock(Type, Scope, TransactionResource) - * @see LockManager#getLock(org.apache.jackrabbit.webdav.lock.Type, org.apache.jackrabbit.webdav.lock.Scope, org.apache.jackrabbit.webdav.DavResource) - */ - public ActiveLock getLock(Type type, Scope scope, DavResource resource) { - return null; - } - - /** - * Returns true if the given lock token belongs to a lock that applies to - * the given resource, false otherwise. The token may either be retrieved - * from the {@link DavConstants#HEADER_LOCK_TOKEN Lock-Token header} or - * from the {@link TransactionConstants#HEADER_TRANSACTIONID TransactionId header}. - * - * @param token - * @param resource - * @return - * @see LockManager#hasLock(String token, DavResource resource) - */ - public boolean hasLock(String token, DavResource resource) { - return getLock(token, null, resource) != null; - } - - /** - * Return the lock applied to the given resource or null - * - * @param type - * @param scope - * @param resource - * @return lock applied to the given resource or null - * @see LockManager#getLock(Type, Scope, DavResource) - * todo: is it correct to return one that specific lock, the current session is token-holder of? - */ - public ActiveLock getLock(Type type, Scope scope, TransactionResource resource) { - ActiveLock lock = null; - if (TransactionConstants.TRANSACTION.equals(type)) { - String[] sessionTokens = resource.getSession().getLockTokens(); - int i = 0; - while (lock == null && i < sessionTokens.length) { - String lockToken = sessionTokens[i]; - lock = getLock(lockToken, scope, resource); - i++; - } - } - return lock; - } - - //-----------------------------< listener support >------------------------- - - /** - * Adds a transaction listener to this TxLockManager. - * @param listener the listener to add. - */ - public void addTransactionListener(TransactionListener listener) { - synchronized (listeners) { - listeners.put(listener, listener); - } - } - - /** - * Removes a transaction listener from this TxLockManager. - * @param listener the listener to remove. - */ - public void removeTransactionListener(TransactionListener listener) { - synchronized (listeners) { - listeners.remove(listener); - } - } - - /** - * @param lockToken - * @param resource - * @return - */ - private ActiveLock getLock(String lockToken, Scope scope, DavResource resource) { - if (!(resource instanceof TransactionResource)) { - log.warn("TransactionResource expected"); - return null; - } - - ActiveLock lock = null; - Transaction tx = null; - TransactionMap m = map; - // check if main-map contains that txId - if (m.containsKey(lockToken)) { - tx = m.get(lockToken); - } else { - // look through all the nested tx-maps (i.e. global txs) for the given txId - Iterator it = m.values().iterator(); - while (it.hasNext() && tx == null) { - Transaction txMap = it.next(); - if (!txMap.isLocal()) { - m = (TransactionMap) txMap; - if (m.containsKey(lockToken)) { - tx = ((TransactionMap) txMap).get(lockToken); - } - } - } - } - - if (tx != null) { - if (tx.getLock().isExpired()) { - removeExpired(tx, m, (TransactionResource) resource); - } else if (tx.appliesToResource(resource) && (scope == null || tx.getLock().getScope().equals(scope))) { - lock = tx.getLock(); - } - } - return lock; - } - - /** - * Return the map that may contain a transaction lock for the given resource. - * In case the resource provides a transactionId, the map must be a - * repository transaction that is identified by the given id and which in - * turn can act as map. - * - * @param resource - * @return responsible map. - * @throws DavException if no map could be retrieved. - */ - private TransactionMap getMap(TransactionResource resource) - throws DavException { - - String txKey = resource.getTransactionId(); - if (txKey == null) { - return map; - } else { - if (!map.containsKey(txKey)) { - throw new DavException(DavServletResponse.SC_PRECONDITION_FAILED, "Transaction map '" + map + " does not contain a transaction with TransactionId '" + txKey + "'."); - } - Transaction tx = map.get(txKey); - if (tx.isLocal()) { - throw new DavException(DavServletResponse.SC_PRECONDITION_FAILED, "TransactionId '" + txKey + "' points to a local transaction, that cannot act as transaction map"); - } else if (tx.getLock() != null && tx.getLock().isExpired()) { - removeExpired(tx, map, resource); - throw new DavException(DavServletResponse.SC_PRECONDITION_FAILED, "Attempt to retrieve an expired global transaction."); - } - // tx is a global transaction that acts as map as well. - return (TransactionMap) tx; - } - } - - /** - * Rollbacks the specified transaction and releases the lock. This includes - * the removal of all references. - * - * @param tx - * @param responsibleMap - * @param resource - */ - private static void removeExpired(Transaction tx, TransactionMap responsibleMap, - TransactionResource resource) { - log.debug("Removing expired transaction lock " + tx); - try { - tx.rollback(resource); - removeReferences(tx, responsibleMap, resource); - } catch (DavException e) { - log.error("Error while removing expired transaction lock: " + e.getMessage()); - } - } - - /** - * Create the required references to the new transaction specified by tx. - * - * @param tx - * @param responsibleMap - * @param resource - * @throws DavException - */ - private static void addReferences(Transaction tx, TransactionMap responsibleMap, - TransactionResource resource) { - log.debug("Adding transactionId '" + tx.getId() + "' as session lock token."); - resource.getSession().addLockToken(tx.getId()); - - responsibleMap.put(tx.getId(), tx); - resource.getSession().addReference(tx.getId()); - } - - /** - * Remove all references to the specified transaction. - * - * @param tx - * @param responsibleMap - * @param resource - */ - private static void removeReferences(Transaction tx, TransactionMap responsibleMap, - TransactionResource resource) { - log.debug("Removing transactionId '" + tx.getId() + "' from session lock tokens."); - resource.getSession().removeLockToken(tx.getId()); - - responsibleMap.remove(tx.getId()); - resource.getSession().removeReference(tx.getId()); - } - - /** - * @param resource - * @return JCR session - */ - private static Session getRepositorySession(TransactionResource resource) throws DavException { - return JcrDavSession.getRepositorySession(resource.getSession()); - } - - //------------------------------------------< inner classes, interfaces >--- - /** - * Internal Transaction interface - */ - private interface Transaction { - - TxActiveLock getLock(); - - /** - * @return the id of this transaction. - */ - String getId(); - - /** - * @return path of the lock holding resource - */ - String getResourcePath(); - - /** - * @param resource - * @return true if the lock defined by this transaction applies to the - * given resource, either due to the resource holding that lock or due - * to a deep lock hold by any ancestor resource. - */ - boolean appliesToResource(DavResource resource); - - /** - * @return true if this transaction is used to allow for transient changes - * on the underlying repository, that may be persisted with the final - * UNLOCK request only. - */ - boolean isLocal(); - - /** - * Start this transaction. - * - * @param resource - * @throws DavException if an error occurs. - */ - void start(TransactionResource resource) throws DavException; - - /** - * Commit this transaction - * - * @param resource - * @throws DavException if an error occurs. - */ - void commit(TransactionResource resource) throws DavException; - - /** - * Rollback this transaction. - * - * @param resource - * @throws DavException if an error occurs. - */ - void rollback(TransactionResource resource) throws DavException; - } - - /** - * Abstract transaction covering functionally to both implementations. - */ - private abstract static class AbstractTransaction extends TransactionMap implements Transaction { - - private final DavResourceLocator locator; - private final TxActiveLock lock; - - private AbstractTransaction(DavResourceLocator locator, TxActiveLock lock) { - this.locator = locator; - this.lock = lock; - } - - //----------------------------------------------------< Transaction >--- - /** - * @see #getLock() - */ - public TxActiveLock getLock() { - return lock; - } - - /** - * @see #getId() - */ - public String getId() { - return lock.getToken(); - } - - /** - * @see #getResourcePath() - */ - public String getResourcePath() { - return locator.getResourcePath(); - } - - /** - * @see #appliesToResource(DavResource) - */ - public boolean appliesToResource(DavResource resource) { - if (locator.isSameWorkspace(resource.getLocator())) { - String lockResourcePath = getResourcePath(); - String resPath = resource.getResourcePath(); - - while (!"".equals(resPath)) { - if (lockResourcePath.equals(resPath)) { - return true; - } - resPath = Text.getRelativeParent(resPath, 1); - } - } - return false; - } - } - - /** - * Local transaction - */ - private final static class LocalTransaction extends AbstractTransaction { - - private LocalTransaction(DavResourceLocator locator, TxActiveLock lock) { - super(locator, lock); - } - - //----------------------------------------------------< Transaction >--- - /** - * @see org.apache.jackrabbit.webdav.jcr.transaction.TxLockManagerImpl.Transaction#isLocal() - */ - public boolean isLocal() { - return true; - } - - /** - * @see org.apache.jackrabbit.webdav.jcr.transaction.TxLockManagerImpl.Transaction#start(TransactionResource) - */ - public void start(TransactionResource resource) throws DavException { - try { - // make sure, the given resource represents an existing repository item - if (!getRepositorySession(resource).itemExists(resource.getLocator().getRepositoryPath())) { - throw new DavException(DavServletResponse.SC_CONFLICT, "Unable to start local transaction: no repository item present at " + getResourcePath()); - } - } catch (RepositoryException e) { - log.error("Unexpected error: " + e.getMessage()); - throw new JcrDavException(e); - } - } - - /** - * @see org.apache.jackrabbit.webdav.jcr.transaction.TxLockManagerImpl.Transaction#commit(TransactionResource) - */ - public void commit(TransactionResource resource) throws DavException { - try { - getItem(resource).save(); - } catch (RepositoryException e) { - throw new JcrDavException(e); - } - } - - /** - * @see org.apache.jackrabbit.webdav.jcr.transaction.TxLockManagerImpl.Transaction#rollback(TransactionResource) - */ - public void rollback(TransactionResource resource) throws DavException { - try { - getItem(resource).refresh(false); - } catch (RepositoryException e) { - throw new JcrDavException(e); - } - } - - //-------------------------------------------------< TransactionMap >--- - /** - * Always throws DavException. - * - * @see TransactionMap#putTransaction(String, org.apache.jackrabbit.webdav.jcr.transaction.TxLockManagerImpl.Transaction) - */ - @Override - public Transaction putTransaction(String key, Transaction value) throws DavException { - throw new DavException(WebdavResponse.SC_PRECONDITION_FAILED, "Attempt to nest a new transaction into a local one."); - } - - //--------------------------------------------------------< private >--- - /** - * Retrieve the repository item from the given transaction resource. - * - * @param resource - * @return - * @throws PathNotFoundException - * @throws RepositoryException - * @throws DavException - */ - private Item getItem(TransactionResource resource) throws PathNotFoundException, RepositoryException, DavException { - String itemPath = resource.getLocator().getRepositoryPath(); - return getRepositorySession(resource).getItem(itemPath); - } - } - - /** - * Global transaction - */ - private static class GlobalTransaction extends AbstractTransaction { - - private Xid xid; - - private GlobalTransaction(DavResourceLocator locator, TxActiveLock lock) { - super(locator, lock); - xid = new XidImpl(lock.getToken()); - } - - //----------------------------------------------------< Transaction >--- - /** - * @see org.apache.jackrabbit.webdav.jcr.transaction.TxLockManagerImpl.Transaction#isLocal() - */ - public boolean isLocal() { - return false; - } - - /** - * @see org.apache.jackrabbit.webdav.jcr.transaction.TxLockManagerImpl.Transaction#start(TransactionResource) - */ - public void start(TransactionResource resource) throws DavException { - XAResource xaRes = getXAResource(resource); - try { - xaRes.setTransactionTimeout((int) getLock().getTimeout() / 1000); - xaRes.start(xid, XAResource.TMNOFLAGS); - } catch (XAException e) { - throw new DavException(DavServletResponse.SC_FORBIDDEN, e.getMessage()); - } - } - - /** - * @see org.apache.jackrabbit.webdav.jcr.transaction.TxLockManagerImpl.Transaction#commit(TransactionResource) - */ - public void commit(TransactionResource resource) throws DavException { - XAResource xaRes = getXAResource(resource); - try { - xaRes.commit(xid, false); - removeLocalTxReferences(resource); - } catch (XAException e) { - throw new DavException(DavServletResponse.SC_FORBIDDEN, e.getMessage()); - } - } - - /** - * @see org.apache.jackrabbit.webdav.jcr.transaction.TxLockManagerImpl.Transaction#rollback(TransactionResource) - */ - public void rollback(TransactionResource resource) throws DavException { - XAResource xaRes = getXAResource(resource); - try { - xaRes.rollback(xid); - removeLocalTxReferences(resource); - } catch (XAException e) { - throw new DavException(DavServletResponse.SC_FORBIDDEN, e.getMessage()); - } - } - - //-------------------------------------------------< TransactionMap >--- - @Override - public Transaction putTransaction(String key, Transaction value) throws DavException { - if (!(value instanceof LocalTransaction)) { - throw new DavException(WebdavResponse.SC_PRECONDITION_FAILED, "Attempt to nest global transaction into a global one."); - } - return super.put(key, value); - } - - //--------------------------------------------------------< private >--- - private XAResource getXAResource(TransactionResource resource) throws DavException { - /* - // commented, since server should be jackrabbit independent - Session session = resource.getSession().getRepositorySession(); - if (session instanceof XASession) { - return ((XASession)session).getXAResource(); - } else { - throw new DavException(DavServletResponse.SC_FORBIDDEN); - } - */ - throw new DavException(DavServletResponse.SC_FORBIDDEN); - } - - private void removeLocalTxReferences(TransactionResource resource) { - for (Object o : values()) { - Transaction tx = (Transaction) o; - removeReferences(tx, this, resource); - } - } - } - - /** - * - */ - private static class TransactionMap extends HashMap { - - public Transaction get(String key) { - Transaction tx = null; - if (containsKey(key)) { - tx = super.get(key); - } - return tx; - } - - public Transaction putTransaction(String key, Transaction value) throws DavException { - // any global and local transactions allowed. - return super.put(key, value); - } - } - - /** - * Private class implementing Xid interface. - */ - private static class XidImpl implements Xid { - - private final String id; - - /** - * Create a new Xid - * - * @param id - */ - private XidImpl(String id) { - this.id = id; - } - - /** - * @return 1 - * @see javax.transaction.xa.Xid#getFormatId() - */ - public int getFormatId() { - // todo: define reasonable format id - return 1; - } - - /** - * @return an empty byte array. - * @see javax.transaction.xa.Xid#getBranchQualifier() - */ - public byte[] getBranchQualifier() { - return new byte[0]; - } - - /** - * @return id as byte array - * @see javax.transaction.xa.Xid#getGlobalTransactionId() - */ - public byte[] getGlobalTransactionId() { - return id.getBytes(); - } - } -} Property changes on: jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/transaction/TxLockManagerImpl.java ___________________________________________________________________ Deleted: svn Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/version/VersionHistoryItemCollection.java =================================================================== --- jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/version/VersionHistoryItemCollection.java (revision 1907912) +++ jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/version/VersionHistoryItemCollection.java (nonexistent) @@ -1,178 +0,0 @@ -/* - * 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.webdav.jcr.version; - -import org.apache.jackrabbit.webdav.DavException; -import org.apache.jackrabbit.webdav.DavResource; -import org.apache.jackrabbit.webdav.DavResourceFactory; -import org.apache.jackrabbit.webdav.DavResourceLocator; -import org.apache.jackrabbit.webdav.DavServletResponse; -import org.apache.jackrabbit.webdav.jcr.DefaultItemCollection; -import org.apache.jackrabbit.webdav.jcr.ItemResourceConstants; -import org.apache.jackrabbit.webdav.jcr.JcrDavException; -import org.apache.jackrabbit.webdav.jcr.JcrDavSession; -import org.apache.jackrabbit.webdav.jcr.property.JcrDavPropertyNameSet; -import org.apache.jackrabbit.webdav.property.DavProperty; -import org.apache.jackrabbit.webdav.property.DavPropertyName; -import org.apache.jackrabbit.webdav.property.DefaultDavProperty; -import org.apache.jackrabbit.webdav.property.HrefProperty; -import org.apache.jackrabbit.webdav.property.ResourceType; -import org.apache.jackrabbit.webdav.version.VersionHistoryResource; -import org.apache.jackrabbit.webdav.version.VersionResource; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import javax.jcr.Item; -import javax.jcr.RepositoryException; -import javax.jcr.version.VersionHistory; -import javax.jcr.version.VersionIterator; -import java.util.ArrayList; - -/** - * VersionHistoryItemCollection represents a JCR version history. - * - * @see VersionHistory - */ -public class VersionHistoryItemCollection extends DefaultItemCollection - implements VersionHistoryResource { - - private static Logger log = LoggerFactory.getLogger(VersionHistoryItemCollection.class); - - /** - * Create a new VersionHistoryItemCollection resource. - * - * @param resourcePath - * @param session - * @param factory - */ - public VersionHistoryItemCollection(DavResourceLocator resourcePath, - JcrDavSession session, - DavResourceFactory factory, - Item item) { - super(resourcePath, session, factory, item); - if (item == null || !(item instanceof VersionHistory)) { - throw new IllegalArgumentException("VersionHistory item expected."); - } - } - - //----------------------------------------------< DavResource interface >--- - /** - * @see org.apache.jackrabbit.webdav.DavResource#getSupportedMethods() - */ - @Override - public String getSupportedMethods() { - StringBuffer sb = new StringBuffer(ItemResourceConstants.METHODS); - sb.append(", ").append(VersionHistoryResource.METHODS); - return sb.toString(); - } - - @Override - public DavProperty getProperty(DavPropertyName name) { - DavProperty prop = super.getProperty(name); - if (prop == null) { - // required, protected version-set property for version-history resource - try { - if (ROOT_VERSION.equals(name)) { - // required root-version property for version-history resource - String rootVersionHref = getLocatorFromItem(((VersionHistory)item).getRootVersion()).getHref(true); - prop = new HrefProperty(ROOT_VERSION, rootVersionHref, true); - } else if (VERSION_SET.equals(name)) { - VersionIterator vIter = ((VersionHistory) item).getAllVersions(); - prop = getHrefProperty(VERSION_SET, vIter, true); - } - } catch (RepositoryException e) { - log.error(e.getMessage()); - } - } - - return prop; - } - - /** - * Removing a version resource is achieved by calling removeVersion - * on the versionhistory item this version belongs to. - * - * @throws DavException if the version does not exist or if an error occurs - * while deleting. - * @see DavResource#removeMember(org.apache.jackrabbit.webdav.DavResource) - */ - @Override - public void removeMember(DavResource member) throws DavException { - if (exists()) { - VersionHistory versionHistory = (VersionHistory) item; - try { - versionHistory.removeVersion(getItemName(member.getLocator().getRepositoryPath())); - } catch (RepositoryException e) { - throw new JcrDavException(e); - } - } else { - throw new DavException(DavServletResponse.SC_NOT_FOUND); - } - } - //-----------------------------------< VersionHistoryResource interface >--- - /** - * Return an array of {@link VersionResource}s representing all versions - * present in the underlying JCR version history. - * - * @return array of {@link VersionResource}s representing all versions - * present in the underlying JCR version history. - * @throws DavException - * @see org.apache.jackrabbit.webdav.version.VersionHistoryResource#getVersions() - */ - public VersionResource[] getVersions() throws DavException { - try { - VersionIterator vIter = ((VersionHistory)item).getAllVersions(); - ArrayList l = new ArrayList(); - while (vIter.hasNext()) { - DavResourceLocator versionLoc = getLocatorFromItem(vIter.nextVersion()); - VersionResource vr = (VersionResource) createResourceFromLocator(versionLoc); - l.add(vr); - } - return l.toArray(new VersionResource[l.size()]); - } catch (RepositoryException e) { - throw new JcrDavException(e); - } - } - - //-------------------------------------------------------------------------- - @Override - protected void initPropertyNames() { - super.initPropertyNames(); - - if (exists()) { - names.addAll(JcrDavPropertyNameSet.VERSIONHISTORY_SET); - } - } - - /** - * Fill the property set for this resource. - */ - @Override - protected void initProperties() { - super.initProperties(); - - // change resource type defined by default item collection - properties.add(new ResourceType(ResourceType.VERSION_HISTORY)); - - // jcr specific property pointing to the node this history belongs to - try { - properties.add(new DefaultDavProperty(JCR_VERSIONABLEUUID, ((VersionHistory)item).getVersionableIdentifier())); - } catch (RepositoryException e) { - log.error(e.getMessage()); - } - } -} Property changes on: jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/version/VersionHistoryItemCollection.java ___________________________________________________________________ Deleted: svn Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/version/VersionItemCollection.java =================================================================== --- jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/version/VersionItemCollection.java (revision 1907912) +++ jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/version/VersionItemCollection.java (nonexistent) @@ -1,240 +0,0 @@ -/* - * 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.webdav.jcr.version; - -import org.apache.jackrabbit.JcrConstants; -import org.apache.jackrabbit.webdav.DavException; -import org.apache.jackrabbit.webdav.DavResourceFactory; -import org.apache.jackrabbit.webdav.DavResourceLocator; -import org.apache.jackrabbit.webdav.DavServletResponse; -import org.apache.jackrabbit.webdav.jcr.property.JcrDavPropertyNameSet; -import org.apache.jackrabbit.webdav.property.DavProperty; -import org.apache.jackrabbit.webdav.util.HttpDateFormat; -import org.apache.jackrabbit.webdav.jcr.DefaultItemCollection; -import org.apache.jackrabbit.webdav.jcr.ItemResourceConstants; -import org.apache.jackrabbit.webdav.jcr.JcrDavException; -import org.apache.jackrabbit.webdav.jcr.JcrDavSession; -import org.apache.jackrabbit.webdav.property.DavPropertyName; -import org.apache.jackrabbit.webdav.property.DefaultDavProperty; -import org.apache.jackrabbit.webdav.property.HrefProperty; -import org.apache.jackrabbit.webdav.version.LabelInfo; -import org.apache.jackrabbit.webdav.version.LabelSetProperty; -import org.apache.jackrabbit.webdav.version.VersionHistoryResource; -import org.apache.jackrabbit.webdav.version.VersionResource; -import org.apache.jackrabbit.webdav.version.report.ReportType; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import javax.jcr.Item; -import javax.jcr.Node; -import javax.jcr.Property; -import javax.jcr.PropertyIterator; -import javax.jcr.RepositoryException; -import javax.jcr.version.Version; -import javax.jcr.version.VersionHistory; -import java.util.ArrayList; -import java.util.List; - -/** - * VersionItemCollection represents a JCR version. - * - * @see Version - */ -public class VersionItemCollection extends DefaultItemCollection - implements VersionResource { - - private static Logger log = LoggerFactory.getLogger(VersionItemCollection.class); - - /** - * Create a new VersionItemCollection. - * - * @param locator - * @param session - * @param factory - */ - public VersionItemCollection(DavResourceLocator locator, - JcrDavSession session, - DavResourceFactory factory, Item item) { - super(locator, session, factory, item); - if (item == null || !(item instanceof Version)) { - throw new IllegalArgumentException("Version item expected."); - } - } - - @Override - public DavProperty getProperty(DavPropertyName name) { - DavProperty prop = super.getProperty(name); - if (prop == null && exists()) { - Version v = (Version) item; - try { - if (VERSION_NAME.equals(name)) { - // required, protected DAV:version-name property - prop = new DefaultDavProperty(VERSION_NAME, v.getName(), true); - } else if (VERSION_HISTORY.equals(name)) { - // required DAV:version-history (computed) property - String vhHref = getLocatorFromItem(getVersionHistoryItem()).getHref(true); - prop = new HrefProperty(VERSION_HISTORY, vhHref, true); - } else if (PREDECESSOR_SET.equals(name)) { - // required DAV:predecessor-set (protected) property - prop = getHrefProperty(VersionResource.PREDECESSOR_SET, v.getPredecessors(), true); - } else if (SUCCESSOR_SET.equals(name)) { - // required DAV:successor-set (computed) property - prop = getHrefProperty(SUCCESSOR_SET, v.getSuccessors(), true); - } else if (LABEL_NAME_SET.equals(name)) { - // required, protected DAV:label-name-set property - String[] labels = getVersionHistoryItem().getVersionLabels(v); - prop = new LabelSetProperty(labels); - } else if (CHECKOUT_SET.equals(name)) { - // required DAV:checkout-set (computed) property - PropertyIterator it = v.getReferences(); - List nodeList = new ArrayList(); - while (it.hasNext()) { - Property p = it.nextProperty(); - if (JcrConstants.JCR_BASEVERSION.equals(p.getName())) { - Node n = p.getParent(); - if (n.isCheckedOut()) { - nodeList.add(n); - } - } - } - prop = getHrefProperty(CHECKOUT_SET, nodeList.toArray(new Node[nodeList.size()]), true); - } - } catch (RepositoryException e) { - log.error(e.getMessage()); - } - } - - return prop; - } - - //----------------------------------------------< DavResource interface >--- - /** - * @see org.apache.jackrabbit.webdav.DavResource#getSupportedMethods() - */ - @Override - public String getSupportedMethods() { - StringBuffer sb = new StringBuffer(ItemResourceConstants.METHODS); - sb.append(", ").append(VersionResource.METHODS); - return sb.toString(); - } - - //------------------------------------------< VersionResource interface >--- - /** - * Modify the labels defined for the underlying repository version. - * - * @param labelInfo - * @throws org.apache.jackrabbit.webdav.DavException - * @see VersionResource#label(org.apache.jackrabbit.webdav.version.LabelInfo) - * @see VersionHistory#addVersionLabel(String, String, boolean) - * @see VersionHistory#removeVersionLabel(String) - */ - public void label(LabelInfo labelInfo) throws DavException { - if (labelInfo == null) { - throw new DavException(DavServletResponse.SC_BAD_REQUEST, "Valid label request body required."); - } - if (!exists()) { - throw new DavException(DavServletResponse.SC_NOT_FOUND); - } - try { - VersionHistory vh = getVersionHistoryItem(); - if (labelInfo.getType() == LabelInfo.TYPE_REMOVE) { - vh.removeVersionLabel(labelInfo.getLabelName()); - } else if (labelInfo.getType() == LabelInfo.TYPE_ADD) { - // ADD: only add if not yet existing - vh.addVersionLabel(item.getName(), labelInfo.getLabelName(), false); - } else { - // SET: move label if already existing - vh.addVersionLabel(item.getName(), labelInfo.getLabelName(), true); - } - } catch (RepositoryException e) { - throw new JcrDavException(e); - } - } - - /** - * Returns the {@link VersionHistory} associated with the repository version. - * Note: in contrast to a versionable node, the version history of a version - * item is always represented by its nearest ancestor. - * - * @return the {@link VersionHistoryResource} associated with this resource. - * @throws org.apache.jackrabbit.webdav.DavException - * @see org.apache.jackrabbit.webdav.version.VersionResource#getVersionHistory() - * @see javax.jcr.Item#getParent() - */ - public VersionHistoryResource getVersionHistory() throws DavException { - if (!exists()) { - throw new DavException(DavServletResponse.SC_NOT_FOUND); - } - - try { - VersionHistory vh = getVersionHistoryItem(); - DavResourceLocator loc = getLocatorFromItem(vh); - return (VersionHistoryResource) createResourceFromLocator(loc); - } catch (RepositoryException e) { - throw new JcrDavException(e); - } - } - - /** - * Return versionhistory that contains this version item - * - * @return versionhistory that contains this version item - * @throws RepositoryException - * @see javax.jcr.version.Version#getContainingHistory() - */ - private VersionHistory getVersionHistoryItem() throws RepositoryException { - return ((Version)item).getContainingHistory(); - } - - //-------------------------------------------------------------------------- - /** - * Define the set of reports supported by this resource. - * - * @see org.apache.jackrabbit.webdav.version.report.SupportedReportSetProperty - */ - @Override - protected void initSupportedReports() { - super.initSupportedReports(); - if (exists()) { - supportedReports.addReportType(ReportType.VERSION_TREE); - } - } - - @Override - protected void initPropertyNames() { - super.initPropertyNames(); - - if (exists()) { - names.addAll(JcrDavPropertyNameSet.VERSION_SET); - } - } - - @Override - protected String getCreationDate() { - if (exists()) { - Version v = (Version) item; - try { - return HttpDateFormat.creationDateFormat().format(v.getCreated().getTime()); - } catch (RepositoryException e) { - log.error(e.getMessage()); - } - } - - // fallback - return super.getCreationDate(); - } -} Property changes on: jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/version/VersionItemCollection.java ___________________________________________________________________ Deleted: svn Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/version/report/AbstractJcrReport.java =================================================================== --- jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/version/report/AbstractJcrReport.java (revision 1907912) +++ jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/version/report/AbstractJcrReport.java (nonexistent) @@ -1,84 +0,0 @@ -/* - * 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.webdav.jcr.version.report; - -import javax.jcr.Session; - -import org.apache.jackrabbit.webdav.DavConstants; -import org.apache.jackrabbit.webdav.DavException; -import org.apache.jackrabbit.webdav.DavResource; -import org.apache.jackrabbit.webdav.DavServletResponse; -import org.apache.jackrabbit.webdav.DavSession; -import org.apache.jackrabbit.webdav.jcr.JcrDavSession; -import org.apache.jackrabbit.webdav.version.report.AbstractReport; -import org.apache.jackrabbit.webdav.version.report.Report; -import org.apache.jackrabbit.webdav.version.report.ReportInfo; - -/** - * AbstractJcrReport... - */ -public abstract class AbstractJcrReport extends AbstractReport { - - private Session session; - private ReportInfo reportInfo; - - /** - * Performs basic validation checks common to all JCR specific reports. - * - * @param resource - * @param info - * @throws DavException - * @see Report#init(DavResource, ReportInfo) - */ - public void init(DavResource resource, ReportInfo info) throws DavException { - if (resource == null || info == null) { - throw new DavException(DavServletResponse.SC_BAD_REQUEST, "Unable to run report: WebDAV Resource and ReportInfo must not be null."); - } - if (!getType().isRequestedReportType(info)) { - throw new DavException(DavServletResponse.SC_BAD_REQUEST, "Expected report type: '" + getType().getReportName() + "', found: '" + info.getReportName() + ";" + "'."); - } - if (info.getDepth() > DavConstants.DEPTH_0) { - throw new DavException(DavServletResponse.SC_BAD_REQUEST, "Invalid Depth header: " + info.getDepth()); - } - - DavSession davSession = resource.getSession(); - if (davSession == null) { - throw new DavException(DavServletResponse.SC_BAD_REQUEST, "The resource must provide a non-null session object in order to create '" + getType().getReportName()+ "' report."); - } - session = JcrDavSession.getRepositorySession(resource.getSession()); - if (session == null) { - throw new DavException(DavServletResponse.SC_INTERNAL_SERVER_ERROR, "Internal error: Unable to access repository session."); - } - reportInfo = info; - } - - //-----------------------------------------------------< implementation >--- - /** - * @return session Session object as obtained from the {@link DavSession}. - */ - Session getRepositorySession() { - return session; - } - - /** - * @return reportInfo the ReportInfo specifying the requested - * report details. - */ - ReportInfo getReportInfo() { - return reportInfo; - } -} Property changes on: jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/version/report/AbstractJcrReport.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Deleted: svn:keywords ## -1 +0,0 ## -author date id revision url \ No newline at end of property Index: jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/version/report/ExportViewReport.java =================================================================== --- jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/version/report/ExportViewReport.java (revision 1907912) +++ jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/version/report/ExportViewReport.java (nonexistent) @@ -1,159 +0,0 @@ -/* - * 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.webdav.jcr.version.report; - -import org.apache.jackrabbit.commons.webdav.JcrRemotingConstants; -import org.apache.jackrabbit.util.Text; -import org.apache.jackrabbit.webdav.DavException; -import org.apache.jackrabbit.webdav.DavResource; -import org.apache.jackrabbit.webdav.jcr.ItemResourceConstants; -import org.apache.jackrabbit.webdav.jcr.JcrDavException; -import org.apache.jackrabbit.webdav.version.report.Report; -import org.apache.jackrabbit.webdav.version.report.ReportInfo; -import org.apache.jackrabbit.webdav.version.report.ReportType; -import org.apache.jackrabbit.webdav.xml.DomUtil; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.w3c.dom.Document; -import org.w3c.dom.Element; -import org.xml.sax.SAXException; - -import javax.jcr.PathNotFoundException; -import javax.jcr.RepositoryException; -import javax.jcr.Session; -import javax.xml.parsers.ParserConfigurationException; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.FileOutputStream; -import java.io.IOException; - -/** - * ExportViewReport handles REPORT requests for the 'exportview' - * report. The 'exportview' report is used to export - * {@link Session#exportDocumentView(String, java.io.OutputStream, boolean, boolean) DocView} - * and {@link Session#exportSystemView(String, java.io.OutputStream, boolean, boolean) SysView} - * of the {@link javax.jcr.Item item} represented by the requested resource. - *

- * The request body must contain a {@link ItemResourceConstants#NAMESPACE dcr}:exportview - * element: - *

- * <!ELEMENT exportview  ( (sysview | docview)?, skipbinary?, norecurse ) >
- * <!ELEMENT sysview EMPTY >
- * <!ELEMENT docview EMPTY >
- * <!ELEMENT skipbinary EMPTY >
- * <!ELEMENT norecurse EMPTY >
- * 
- * If no view type is specified the DocView is generated. - */ -public class ExportViewReport extends AbstractJcrReport { - - private static Logger log = LoggerFactory.getLogger(ExportViewReport.class); - - /** - * The exportview report type - */ - public static final ReportType EXPORTVIEW_REPORT = ReportType.register(JcrRemotingConstants.REPORT_EXPORT_VIEW, ItemResourceConstants.NAMESPACE, ExportViewReport.class); - - private String absNodePath; - - /** - * Returns {@link #EXPORTVIEW_REPORT} report type. - * - * @return {@link #EXPORTVIEW_REPORT} - * @see org.apache.jackrabbit.webdav.version.report.Report#getType() - */ - public ReportType getType() { - return EXPORTVIEW_REPORT; - } - - /** - * Always returns false. - * - * @return false - */ - public boolean isMultiStatusReport() { - return false; - } - - /** - * @see Report#init(DavResource, ReportInfo) - */ - @Override - public void init(DavResource resource, ReportInfo info) throws DavException { - // delegate validation to super class - super.init(resource, info); - // report specific validation: resource must represent an existing - // repository node - absNodePath = resource.getLocator().getRepositoryPath(); - try { - if (!(getRepositorySession().itemExists(absNodePath) && getRepositorySession().getItem(absNodePath).isNode())) { - throw new JcrDavException(new PathNotFoundException(absNodePath + " does not exist.")); - } - } catch (RepositoryException e) { - throw new JcrDavException(e); - } - - } - - /** - * Creates a Xml document from the generated view. - * - * @param document - * @return Xml element representing the output of the specified view. - * @see org.apache.jackrabbit.webdav.xml.XmlSerializable#toXml(Document) - */ - public Element toXml(Document document) { - boolean skipBinary = getReportInfo().containsContentElement("skipbinary", ItemResourceConstants.NAMESPACE); - boolean noRecurse = getReportInfo().containsContentElement("norecurse", ItemResourceConstants.NAMESPACE); - // todo improve... - try { - // create tmpFile in default system-tmp directory - String prefix = "_tmp_" + Text.getName(absNodePath); - File tmpfile = File.createTempFile(prefix, null, null); - tmpfile.deleteOnExit(); - - FileOutputStream out = new FileOutputStream(tmpfile); - if (getReportInfo().containsContentElement("sysview", ItemResourceConstants.NAMESPACE)) { - getRepositorySession().exportSystemView(absNodePath, out, skipBinary, noRecurse); - } else { - // default is docview - getRepositorySession().exportDocumentView(absNodePath, out, skipBinary, noRecurse); - } - out.close(); - - Document tmpDoc = - DomUtil.parseDocument(new FileInputStream(tmpfile)); - - // import the root node of the generated xml to the given document. - Element rootElem = (Element)document.importNode(tmpDoc.getDocumentElement(), true); - return rootElem; - - } catch (RepositoryException e) { - log.error(e.getMessage()); - } catch (FileNotFoundException e) { - log.error(e.getMessage()); - } catch (IOException e) { - log.error(e.getMessage()); - } catch (ParserConfigurationException e) { - log.error(e.getMessage()); - } catch (SAXException e) { - log.error(e.getMessage()); - } - return null; - } -} Property changes on: jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/version/report/ExportViewReport.java ___________________________________________________________________ Deleted: svn Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/version/report/JcrPrivilegeReport.java =================================================================== --- jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/version/report/JcrPrivilegeReport.java (revision 1907912) +++ jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/version/report/JcrPrivilegeReport.java (nonexistent) @@ -1,162 +0,0 @@ -/* - * 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.webdav.jcr.version.report; - -import org.apache.jackrabbit.commons.webdav.JcrRemotingConstants; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.apache.jackrabbit.webdav.version.report.Report; -import org.apache.jackrabbit.webdav.version.report.ReportType; -import org.apache.jackrabbit.webdav.version.report.ReportInfo; -import org.apache.jackrabbit.webdav.jcr.ItemResourceConstants; -import org.apache.jackrabbit.webdav.MultiStatus; -import org.apache.jackrabbit.webdav.DavResource; -import org.apache.jackrabbit.webdav.DavException; -import org.apache.jackrabbit.webdav.DavConstants; -import org.apache.jackrabbit.webdav.MultiStatusResponse; -import org.apache.jackrabbit.webdav.DavServletResponse; -import org.apache.jackrabbit.webdav.DavResourceLocator; -import org.apache.jackrabbit.webdav.xml.DomUtil; -import org.apache.jackrabbit.webdav.security.Privilege; -import org.apache.jackrabbit.webdav.security.CurrentUserPrivilegeSetProperty; -import org.w3c.dom.Element; -import org.w3c.dom.Document; - -import javax.jcr.RepositoryException; -import java.util.List; -import java.util.ArrayList; - -/** - *

Report to retrieve the permissions granted to the reading session as defined - * by {@link javax.jcr.Session#hasPermission(String, String)}.

- * - *

NOTE: the name of this report and the names of the privileges are - * misleading as they rather correspond to the actions defined by - * {@link javax.jcr.Session}; while the JCR privileges s.str. have only been - * specified as of JSR 283 in the {@link javax.jcr.security.Privilege} interface. - * A better name would have been JcrActionReport

- * - * @see org.apache.jackrabbit.webdav.jcr.security.JcrUserPrivilegesProperty for - * the webdav correspondence to {@link javax.jcr.security.AccessControlManager#getPrivileges(String)} - * mapped to the {@link org.apache.jackrabbit.webdav.security.CurrentUserPrivilegeSetProperty}. - */ -public class JcrPrivilegeReport extends AbstractJcrReport { - - private static Logger log = LoggerFactory.getLogger(JcrPrivilegeReport.class); - - /** - * The exportview report type - */ - public static final ReportType PRIVILEGES_REPORT = ReportType.register(JcrRemotingConstants.REPORT_PRIVILEGES, ItemResourceConstants.NAMESPACE, JcrPrivilegeReport.class); - - private static final Privilege[] PRIVS = new Privilege[] { - ItemResourceConstants.PRIVILEGE_JCR_READ, - ItemResourceConstants.PRIVILEGE_JCR_ADD_NODE, - ItemResourceConstants.PRIVILEGE_JCR_SET_PROPERTY, - ItemResourceConstants.PRIVILEGE_JCR_REMOVE}; - - private final MultiStatus ms = new MultiStatus(); - - /** - * Returns {@link #PRIVILEGES_REPORT} report type. - * - * @return {@link #PRIVILEGES_REPORT} - * @see org.apache.jackrabbit.webdav.version.report.Report#getType() - */ - @Override - public ReportType getType() { - return PRIVILEGES_REPORT; - } - - /** - * Always returns true. - * - * @return true - * @see org.apache.jackrabbit.webdav.version.report.Report#isMultiStatusReport() - */ - @Override - public boolean isMultiStatusReport() { - return true; - } - - /** - * @see Report#init(DavResource, ReportInfo) - */ - @Override - public void init(DavResource resource, ReportInfo info) throws DavException { - // delegate basic validation to super class - super.init(resource, info); - // make also sure, the info contains a DAV:href child element - if (!info.containsContentElement(DavConstants.XML_HREF, DavConstants.NAMESPACE)) { - throw new DavException(DavServletResponse.SC_BAD_REQUEST, "dcr:privileges element must at least contain a single DAV:href child."); - } - // immediately build the final multistatus element - Element hrefElem = info.getContentElement(DavConstants.XML_HREF, DavConstants.NAMESPACE); - String href = DomUtil.getTextTrim(hrefElem); - href = normalizeResourceHref(obtainAbsolutePathFromUri(href)); // TODO: we should check whether the authority component matches - DavResourceLocator resourceLoc = resource.getLocator(); - DavResourceLocator loc = resourceLoc.getFactory().createResourceLocator(resourceLoc.getPrefix(), href); - // immediately build the final multistatus element - addResponses(loc); - } - - /** - * Creates a Xml document from the generated view. - * - * @param document - * @return Xml element representing the output of the specified view. - * @see org.apache.jackrabbit.webdav.xml.XmlSerializable#toXml(Document) - */ - @Override - public Element toXml(Document document) { - return ms.toXml(document); - } - - private void addResponses(DavResourceLocator locator) { - String repositoryPath = locator.getRepositoryPath(); - MultiStatusResponse resp = new MultiStatusResponse(locator.getHref(false), null); - List currentPrivs = new ArrayList(); - for (Privilege priv : PRIVS) { - try { - if (getRepositorySession().hasPermission(repositoryPath, priv.getName())) { - currentPrivs.add(priv); - } - } catch (RepositoryException e) { - // ignore - log.debug(e.toString()); - } - } - resp.add(new CurrentUserPrivilegeSetProperty(currentPrivs.toArray(new Privilege[currentPrivs.size()]))); - ms.addResponse(resp); - } - - private static String obtainAbsolutePathFromUri(String uri) { - try { - java.net.URI u = new java.net.URI(uri); - StringBuilder sb = new StringBuilder(); - sb.append(u.getRawPath()); - if (u.getRawQuery() != null) { - sb.append("?").append(u.getRawQuery()); - } - return sb.toString(); - } - catch (java.net.URISyntaxException ex) { - log.warn("parsing " + uri, ex); - return uri; - } - } -} Property changes on: jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/version/report/JcrPrivilegeReport.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Deleted: svn:keywords ## -1 +0,0 ## -author date id revision url \ No newline at end of property Index: jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/version/report/LocateByUuidReport.java =================================================================== --- jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/version/report/LocateByUuidReport.java (revision 1907912) +++ jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/version/report/LocateByUuidReport.java (nonexistent) @@ -1,117 +0,0 @@ -/* - * 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.webdav.jcr.version.report; - -import org.apache.jackrabbit.commons.webdav.JcrRemotingConstants; -import org.apache.jackrabbit.webdav.DavConstants; -import org.apache.jackrabbit.webdav.DavException; -import org.apache.jackrabbit.webdav.DavResource; -import org.apache.jackrabbit.webdav.DavResourceLocator; -import org.apache.jackrabbit.webdav.DavServletResponse; -import org.apache.jackrabbit.webdav.MultiStatus; -import org.apache.jackrabbit.webdav.jcr.ItemResourceConstants; -import org.apache.jackrabbit.webdav.jcr.JcrDavException; -import org.apache.jackrabbit.webdav.version.report.Report; -import org.apache.jackrabbit.webdav.version.report.ReportInfo; -import org.apache.jackrabbit.webdav.version.report.ReportType; -import org.apache.jackrabbit.webdav.xml.DomUtil; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.w3c.dom.Document; -import org.w3c.dom.Element; - -import javax.jcr.Node; -import javax.jcr.RepositoryException; - -/** - * LocateByUuidReport handles REPORT requests for the 'locate-by-uuid' - * report. - *

- * The request body must be a 'dcr:locate-by-uuid' XML element: - *

- * <!ELEMENT locate-by-uuid ( href , prop? ) >
- * 
- * The response to a successful report request will be a Multi-Status response. - */ -public class LocateByUuidReport extends AbstractJcrReport { - - private static Logger log = LoggerFactory.getLogger(LocateByUuidReport.class); - - /** - * The exportview report type - */ - public static final ReportType LOCATE_BY_UUID_REPORT = ReportType.register(JcrRemotingConstants.REPORT_LOCATE_BY_UUID, ItemResourceConstants.NAMESPACE, LocateByUuidReport.class); - - private MultiStatus ms; - - /** - * Returns {@link #LOCATE_BY_UUID_REPORT} report type. - * - * @return {@link #LOCATE_BY_UUID_REPORT} - * @see org.apache.jackrabbit.webdav.version.report.Report#getType() - */ - public ReportType getType() { - return LOCATE_BY_UUID_REPORT; - } - - /** - * Always returns true. - * - * @return true - * @see org.apache.jackrabbit.webdav.version.report.Report#isMultiStatusReport() - */ - public boolean isMultiStatusReport() { - return true; - } - - /** - * @see Report#init(DavResource, ReportInfo) - */ - @Override - public void init(DavResource resource, ReportInfo info) throws DavException { - // delegate basic validation to super class - super.init(resource, info); - // make also sure, the info contains a DAV:href child element - if (!info.containsContentElement(DavConstants.XML_HREF, DavConstants.NAMESPACE)) { - throw new DavException(DavServletResponse.SC_BAD_REQUEST, "dcr:locate-by-uuid element must at least contain a single DAV:href child."); - } - // immediately build the final multistatus element - try { - Element hrefElem = info.getContentElement(DavConstants.XML_HREF, DavConstants.NAMESPACE); - String uuid = DomUtil.getTextTrim(hrefElem); - DavResourceLocator resourceLoc = resource.getLocator(); - Node n = getRepositorySession().getNodeByUUID(uuid); - DavResourceLocator loc = resourceLoc.getFactory().createResourceLocator(resourceLoc.getPrefix(), resourceLoc.getWorkspacePath(), n.getPath(), false); - DavResource locatedResource = resource.getFactory().createResource(loc, resource.getSession()); - ms = new MultiStatus(); - ms.addResourceProperties(locatedResource, info.getPropertyNameSet(), info.getDepth()); - } catch (RepositoryException e) { - throw new JcrDavException(e); - } - } - - /** - * Creates a Xml document from the generated view. - * - * @param document - * @return Xml element representing the output of the specified view. - * @see org.apache.jackrabbit.webdav.xml.XmlSerializable#toXml(Document) - */ - public Element toXml(Document document) { - return ms.toXml(document); - } -} Property changes on: jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/version/report/LocateByUuidReport.java ___________________________________________________________________ Deleted: svn Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/version/report/LocateCorrespondingNodeReport.java =================================================================== --- jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/version/report/LocateCorrespondingNodeReport.java (revision 1907912) +++ jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/version/report/LocateCorrespondingNodeReport.java (nonexistent) @@ -1,151 +0,0 @@ -/* - * 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.webdav.jcr.version.report; - -import org.apache.jackrabbit.commons.webdav.JcrRemotingConstants; -import org.apache.jackrabbit.webdav.DavConstants; -import org.apache.jackrabbit.webdav.DavException; -import org.apache.jackrabbit.webdav.DavResource; -import org.apache.jackrabbit.webdav.DavResourceLocator; -import org.apache.jackrabbit.webdav.DavServletResponse; -import org.apache.jackrabbit.webdav.jcr.ItemResourceConstants; -import org.apache.jackrabbit.webdav.jcr.JcrDavException; -import org.apache.jackrabbit.webdav.version.DeltaVConstants; -import org.apache.jackrabbit.webdav.version.report.Report; -import org.apache.jackrabbit.webdav.version.report.ReportInfo; -import org.apache.jackrabbit.webdav.version.report.ReportType; -import org.apache.jackrabbit.webdav.xml.DomUtil; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.w3c.dom.Document; -import org.w3c.dom.Element; - -import javax.jcr.Item; -import javax.jcr.Node; -import javax.jcr.PathNotFoundException; -import javax.jcr.RepositoryException; -import javax.jcr.Session; - -/** - * LocateCorrespondingNodeReport is used to identify the resource that - * represents the corresponding node in another workspace. - * - *

- * The request body must be a 'dcr:locate-corresponding-node' XML element, that - * contains the href of the source workspace, where the corresponding node should - * be searched: - *

- * <!ELEMENT locate-corresponding-node ( workspace ) >
- * <!ELEMENT workspace ( href ) >  (as defined by RFC 3253)
- * 
- * The response to a successful report request must be a 'dcr:locate-corresponding-node-report' - * element that contains the href of the corresponding node in the given source - * workspace: - * - *
- * <!ELEMENT locate-corresponding-node-report ( href ) >
- * 
- * - * @see javax.jcr.Node#getCorrespondingNodePath(String) - */ -public class LocateCorrespondingNodeReport extends AbstractJcrReport { - - private static Logger log = LoggerFactory.getLogger(LocateCorrespondingNodeReport.class); - - private String correspHref; - - /** - * The corresponding-node report type - */ - public static final ReportType LOCATE_CORRESPONDING_NODE_REPORT = ReportType.register(JcrRemotingConstants.REPORT_LOCATE_CORRESPONDING_NODE, ItemResourceConstants.NAMESPACE, LocateByUuidReport.class); - - /** - * Returns {@link #LOCATE_CORRESPONDING_NODE_REPORT} - * - * @return always returns {@link #LOCATE_CORRESPONDING_NODE_REPORT} - * @see org.apache.jackrabbit.webdav.version.report.Report#getType() - */ - public ReportType getType() { - return LOCATE_CORRESPONDING_NODE_REPORT; - } - - /** - * Always returns false. - * - * @return false - * @see org.apache.jackrabbit.webdav.version.report.Report#isMultiStatusReport() - */ - public boolean isMultiStatusReport() { - return false; - } - - /** - * @see Report#init(DavResource, ReportInfo) - */ - @Override - public void init(DavResource resource, ReportInfo info) throws DavException { - // general validation checks - super.init(resource, info); - // specific for this report: a workspace href must be provided - Element workspace = info.getContentElement(DeltaVConstants.WORKSPACE.getName(), DeltaVConstants.WORKSPACE.getNamespace()); - String workspaceHref = normalizeResourceHref(DomUtil.getChildTextTrim(workspace, DavConstants.XML_HREF, DavConstants.NAMESPACE)); - if (workspaceHref == null || "".equals(workspaceHref)) { - throw new DavException(DavServletResponse.SC_BAD_REQUEST, "Request body must define the href of a source workspace"); - } - // retrieve href of the corresponding resource in the other workspace - try { - this.correspHref = getCorrespondingResourceHref(resource, getRepositorySession(), workspaceHref); - } catch (RepositoryException e) { - throw new JcrDavException(e); - } - } - - /** - * @see org.apache.jackrabbit.webdav.xml.XmlSerializable#toXml(Document) - */ - public Element toXml(Document document) { - Element elem = DomUtil.createElement(document, "locate-corresponding-node-report", ItemResourceConstants.NAMESPACE); - if (correspHref != null) { - elem.appendChild(DomUtil.hrefToXml(correspHref, document)); - } - return elem; - } - - /** - * Retrieve the href of the corresponding resource in the indicated workspace. - * - * @param resource - * @param session Session object used to access the {@link Node} object - * represented by the given resource. - * @param workspaceHref - * @return - * @throws RepositoryException - */ - private static String getCorrespondingResourceHref(DavResource resource, Session session, String workspaceHref) throws RepositoryException { - DavResourceLocator rLoc = resource.getLocator(); - String itemPath = rLoc.getRepositoryPath(); - Item item = session.getItem(itemPath); - if (item.isNode()) { - String workspaceName = rLoc.getFactory().createResourceLocator(rLoc.getPrefix(), workspaceHref).getWorkspaceName(); - String corrPath = ((Node)item).getCorrespondingNodePath(workspaceName); - DavResourceLocator corrLoc = rLoc.getFactory().createResourceLocator(rLoc.getPrefix(), "/" + workspaceName, corrPath, false); - return corrLoc.getHref(true); - } else { - throw new PathNotFoundException("Node with path " + itemPath + " does not exist."); - } - } -} Property changes on: jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/version/report/LocateCorrespondingNodeReport.java ___________________________________________________________________ Deleted: svn Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/version/report/NodeTypesReport.java =================================================================== --- jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/version/report/NodeTypesReport.java (revision 1907912) +++ jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/version/report/NodeTypesReport.java (nonexistent) @@ -1,202 +0,0 @@ -/* - * 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.webdav.jcr.version.report; - -import org.apache.jackrabbit.commons.iterator.NodeTypeIteratorAdapter; -import org.apache.jackrabbit.commons.webdav.JcrRemotingConstants; -import org.apache.jackrabbit.commons.webdav.NodeTypeConstants; -import org.apache.jackrabbit.webdav.DavException; -import org.apache.jackrabbit.webdav.DavResource; -import org.apache.jackrabbit.webdav.DavServletResponse; -import org.apache.jackrabbit.webdav.jcr.ItemResourceConstants; -import org.apache.jackrabbit.webdav.jcr.JcrDavException; -import org.apache.jackrabbit.webdav.jcr.nodetype.NodeDefinitionImpl; -import org.apache.jackrabbit.webdav.jcr.nodetype.PropertyDefinitionImpl; -import org.apache.jackrabbit.webdav.version.report.Report; -import org.apache.jackrabbit.webdav.version.report.ReportInfo; -import org.apache.jackrabbit.webdav.version.report.ReportType; -import org.apache.jackrabbit.webdav.xml.DomUtil; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.w3c.dom.Document; -import org.w3c.dom.Element; - -import javax.jcr.RepositoryException; -import javax.jcr.Session; -import javax.jcr.nodetype.NodeDefinition; -import javax.jcr.nodetype.NodeType; -import javax.jcr.nodetype.NodeTypeIterator; -import javax.jcr.nodetype.NodeTypeManager; -import javax.jcr.nodetype.PropertyDefinition; -import java.util.ArrayList; -import java.util.List; - -/** - * NodeTypesReport allows to retrieve the definition of a single - * or multiple node types. The request body must be a 'dcr:nodetypes' element: - *
- * <!ELEMENT nodetypes ( nodetype+ | all-nodetypes | mixin-nodetypes | primary-nodetypes ) >
- *
- * <!ELEMENT nodetype ( nodetypename ) >
- * <!ELEMENT nodetypename (#PCDATA) >
- *
- * <!ELEMENT all-nodetypes EMPTY >
- * <!ELEMENT mixin-nodetypes EMPTY >
- * <!ELEMENT primary-nodetypes EMPTY >
- * 
- */ -//todo: currently the nodetype report is not consistent with the general way of representing nodetype names (with NodetypeElement) in order to be compatible with the jackrabbit nodetype registry... -//todo: for the same reason, not the complete nodetype-definition, but only the nodetype def as stored is represented. -//todo: no namespace definition with response (> jackrabbit)... and nodetype element has same name as the one used with dav-properties -public class NodeTypesReport extends AbstractJcrReport implements NodeTypeConstants { - - private static Logger log = LoggerFactory.getLogger(NodeTypesReport.class); - - /** - * The registered type of this report. - */ - public static final ReportType NODETYPES_REPORT = ReportType.register(JcrRemotingConstants.REPORT_NODETYPES, ItemResourceConstants.NAMESPACE, NodeTypesReport.class); - - private NodeTypeIterator ntIter; - - /** - * Returns {@link #NODETYPES_REPORT} type. - * @return {@link #NODETYPES_REPORT} - * @see org.apache.jackrabbit.webdav.version.report.Report#getType() - */ - public ReportType getType() { - return NODETYPES_REPORT; - } - - /** - * Always returns false. - * - * @return false - * @see org.apache.jackrabbit.webdav.version.report.Report#isMultiStatusReport() - */ - public boolean isMultiStatusReport() { - return false; - } - - /** - * @see Report#init(DavResource, ReportInfo) - */ - @Override - public void init(DavResource resource, ReportInfo info) throws DavException { - // delegate basic validation to super class - super.init(resource, info); - // report specific validation and preparation for xml serialization - try { - ntIter = getNodeTypes(getRepositorySession(), info); - } catch (RepositoryException e) { - throw new JcrDavException(e); - } - if (ntIter == null) { - throw new DavException(DavServletResponse.SC_INTERNAL_SERVER_ERROR); - } - } - - /** - * Returns a Xml representation of the node type definition(s) according - * to the info object. - * - * @param document - * @return Xml representation of the node type definition(s) - * @see org.apache.jackrabbit.webdav.xml.XmlSerializable#toXml(Document) - */ - public Element toXml(Document document) { - Element report = document.createElement(NODETYPES_ELEMENT); - // loop over the nodetypes to be returned in the report - while (ntIter.hasNext()) { - NodeType nt = ntIter.nextNodeType(); - Element ntDef = document.createElement(NODETYPE_ELEMENT); - ntDef.setAttribute(NAME_ATTRIBUTE, nt.getName()); - ntDef.setAttribute(ISMIXIN_ATTRIBUTE, Boolean.toString(nt.isMixin())); - ntDef.setAttribute(HASORDERABLECHILDNODES_ATTRIBUTE, Boolean.toString(nt.hasOrderableChildNodes())); - // JCR 2.0 extension - ntDef.setAttribute(ISABSTRACT_ATTRIBUTE, Boolean.toString(nt.isAbstract())); - // JCR 2.0 extension - ntDef.setAttribute(ISQUERYABLE_ATTRIBUTE, Boolean.toString(nt.isQueryable())); - - // declared supertypes - Element supertypes = DomUtil.addChildElement(ntDef, SUPERTYPES_ELEMENT, null); - for (NodeType snt : nt.getDeclaredSupertypes()) { - DomUtil.addChildElement(supertypes, SUPERTYPE_ELEMENT, null, snt.getName()); - } - - // declared child node definitions - for (NodeDefinition aCnd : nt.getChildNodeDefinitions()) { - if (aCnd.getDeclaringNodeType().getName().equals(nt.getName())) { - ntDef.appendChild(NodeDefinitionImpl.create(aCnd).toXml(document)); - } - } - - // declared property definitions - for (PropertyDefinition aPd : nt.getPropertyDefinitions()) { - if (aPd.getDeclaringNodeType().getName().equals(nt.getName())) { - ntDef.appendChild(PropertyDefinitionImpl.create(aPd).toXml(document)); - } - } - - String primaryItemName = nt.getPrimaryItemName(); - if (primaryItemName != null) { - ntDef.setAttribute(PRIMARYITEMNAME_ATTRIBUTE, primaryItemName); - } - report.appendChild(ntDef); - } - return report; - } - - /** - * Parse the Xml element in the info object an return an interator over - * the specified node types. - * - * @return - * @throws RepositoryException - * @throws DavException - */ - private static NodeTypeIterator getNodeTypes(Session session, ReportInfo info) throws RepositoryException, DavException { - NodeTypeManager ntMgr = session.getWorkspace().getNodeTypeManager(); - - // check the simple types first... - if (info.containsContentElement(XML_REPORT_ALLNODETYPES, ItemResourceConstants.NAMESPACE)) { - return ntMgr.getAllNodeTypes(); - } else if (info.containsContentElement(XML_REPORT_MIXINNODETYPES, ItemResourceConstants.NAMESPACE)) { - return ntMgr.getMixinNodeTypes(); - } else if (info.containsContentElement(XML_REPORT_PRIMARYNODETYPES, ItemResourceConstants.NAMESPACE)) { - return ntMgr.getPrimaryNodeTypes(); - } else { - // None of the simple types. test if a report for individual - // nodetype was request. If not, the request body is not valid. - List elemList = info.getContentElements(XML_NODETYPE, ItemResourceConstants.NAMESPACE); - if (elemList.isEmpty()) { - // throw exception if the request body does not contain a single nodetype element - throw new DavException(DavServletResponse.SC_BAD_REQUEST, "NodeTypes report: request body has invalid format."); - } - - // todo: find better solution... - List ntList = new ArrayList(); - for (Element el : elemList) { - String nodetypeName = DomUtil.getChildTextTrim(el, XML_NODETYPENAME, ItemResourceConstants.NAMESPACE); - if (nodetypeName != null) { - ntList.add(ntMgr.getNodeType(nodetypeName)); - } - } - return new NodeTypeIteratorAdapter(ntList); - } - } -} Property changes on: jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/version/report/NodeTypesReport.java ___________________________________________________________________ Deleted: svn Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/version/report/RegisteredNamespacesReport.java =================================================================== --- jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/version/report/RegisteredNamespacesReport.java (revision 1907912) +++ jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/version/report/RegisteredNamespacesReport.java (nonexistent) @@ -1,121 +0,0 @@ -/* - * 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.webdav.jcr.version.report; - -import org.apache.jackrabbit.webdav.DavException; -import org.apache.jackrabbit.webdav.DavResource; -import org.apache.jackrabbit.webdav.DavServletResponse; -import org.apache.jackrabbit.webdav.jcr.ItemResourceConstants; -import org.apache.jackrabbit.webdav.version.report.Report; -import org.apache.jackrabbit.webdav.version.report.ReportInfo; -import org.apache.jackrabbit.webdav.version.report.ReportType; -import org.apache.jackrabbit.webdav.xml.DomUtil; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.w3c.dom.Document; -import org.w3c.dom.Element; - -import javax.jcr.NamespaceRegistry; -import javax.jcr.RepositoryException; - -/** - * RegisteredNamespacesReport let the client retrieve the namespaces - * registered on the repository. - *

- * Request body: - *

- * <!ELEMENT registerednamespaces EMPTY >
- * 
- * - * Response body: - *
- * <!ELEMENT registerednamespaces-report (namespace)* >
- * <!ELEMENT namespace (prefix, uri) >
- * <!ELEMENT prefix (#PCDATA) >
- * <!ELEMENT uri (#PCDATA) >
- * 
- * - * @see javax.jcr.Workspace#getNamespaceRegistry() - */ -public class RegisteredNamespacesReport extends AbstractJcrReport implements ItemResourceConstants { - - private static Logger log = LoggerFactory.getLogger(RegisteredNamespacesReport.class); - - /** - * The registered type of this report. - */ - public static final ReportType REGISTERED_NAMESPACES_REPORT = ReportType.register(REPORT_REGISTERED_NAMESPACES, ItemResourceConstants.NAMESPACE, RegisteredNamespacesReport.class); - - private NamespaceRegistry nsReg; - - /** - * Returns {@link #REGISTERED_NAMESPACES_REPORT} type. - * @return {@link #REGISTERED_NAMESPACES_REPORT} - * @see org.apache.jackrabbit.webdav.version.report.Report#getType() - */ - public ReportType getType() { - return REGISTERED_NAMESPACES_REPORT; - } - - /** - * Always returns false. - * - * @return false - * @see org.apache.jackrabbit.webdav.version.report.Report#isMultiStatusReport() - */ - public boolean isMultiStatusReport() { - return false; - } - - /** - * @see Report#init(DavResource, ReportInfo) - */ - @Override - public void init(DavResource resource, ReportInfo info) throws DavException { - // delegate validation to abstract super class - super.init(resource, info); - try { - nsReg = getRepositorySession().getWorkspace().getNamespaceRegistry(); - } catch (RepositoryException e) { - throw new DavException(DavServletResponse.SC_INTERNAL_SERVER_ERROR); - } - } - - /** - * Returns a Xml representation of the registered namespace(s). - * - * @return Xml representation of the registered namespace(s) - * error occurs while retrieving the namespaces. - * @see org.apache.jackrabbit.webdav.xml.XmlSerializable#toXml(Document) - * @param document - */ - public Element toXml(Document document) { - Element report = DomUtil.createElement(document, "registerednamespaces-report", NAMESPACE); - try { - for (String prefix : nsReg.getPrefixes()) { - Element elem = DomUtil.addChildElement(report, XML_NAMESPACE, NAMESPACE); - DomUtil.addChildElement(elem, XML_PREFIX, NAMESPACE, prefix); - DomUtil.addChildElement(elem, XML_URI, NAMESPACE, nsReg.getURI(prefix)); - } - } catch (RepositoryException e) { - // should not occur. - log.error(e.getMessage()); - } - return report; - } - -} Property changes on: jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/version/report/RegisteredNamespacesReport.java ___________________________________________________________________ Deleted: svn Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/version/report/RepositoryDescriptorsReport.java =================================================================== --- jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/version/report/RepositoryDescriptorsReport.java (revision 1907912) +++ jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/version/report/RepositoryDescriptorsReport.java (nonexistent) @@ -1,128 +0,0 @@ -/* - * 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.webdav.jcr.version.report; - -import org.apache.jackrabbit.webdav.DavException; -import org.apache.jackrabbit.webdav.DavResource; -import org.apache.jackrabbit.webdav.jcr.ItemResourceConstants; -import org.apache.jackrabbit.webdav.version.report.Report; -import org.apache.jackrabbit.webdav.version.report.ReportInfo; -import org.apache.jackrabbit.webdav.version.report.ReportType; -import org.apache.jackrabbit.webdav.xml.DomUtil; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.w3c.dom.Document; -import org.w3c.dom.Element; - -import javax.jcr.Repository; -import javax.jcr.Value; -import javax.jcr.RepositoryException; -import javax.jcr.PropertyType; - -/** - * RepositoryDescriptorsReport allows to retrieve the repository - * descriptors. The request body must be an empty 'dcr:repositorydescriptors' element: - *
- * <!ELEMENT repositorydescriptors EMPTY >
- * 
- *
- * The response body must match the following format - * - *
- * <!ELEMENT repositorydescriptors-report ( descriptor )* >
- * <!ELEMENT descriptor ( descriptorkey, descriptorvalue+ ) >
- * <!ELEMENT descriptorkey (#PCDATA) >
- * <!ELEMENT descriptorvalue (#PCDATA) >
- * <!ATTLIST descriptorvalue
- *      type ( Reference | Path | Name | Boolean | String | Date | Double |
-               Long | Binary | WeakReference | URI | Decimal )
-   >
- * 
- * - * @see javax.jcr.Repository#getDescriptorKeys() - * @see javax.jcr.Repository#getDescriptor(String) - * @see javax.jcr.Repository#getDescriptorValue(String) - * @see javax.jcr.Repository#getDescriptorValues(String) - */ -public class RepositoryDescriptorsReport extends AbstractJcrReport implements ItemResourceConstants { - - private static Logger log = LoggerFactory.getLogger(RepositoryDescriptorsReport.class); - - /** - * The registered type of this report. - */ - public static final ReportType REPOSITORY_DESCRIPTORS_REPORT = ReportType.register(REPORT_REPOSITORY_DESCRIPTORS, ItemResourceConstants.NAMESPACE, RepositoryDescriptorsReport.class); - - /** - * Returns {@link #REPOSITORY_DESCRIPTORS_REPORT} type. - * @return {@link #REPOSITORY_DESCRIPTORS_REPORT} - * @see org.apache.jackrabbit.webdav.version.report.Report#getType() - */ - public ReportType getType() { - return REPOSITORY_DESCRIPTORS_REPORT; - } - - /** - * Always returns false. - * - * @return false - * @see org.apache.jackrabbit.webdav.version.report.Report#isMultiStatusReport() - */ - public boolean isMultiStatusReport() { - return false; - } - - /** - * @see Report#init(DavResource, ReportInfo) - */ - @Override - public void init(DavResource resource, ReportInfo info) throws DavException { - // delegate validation to abstract super class - super.init(resource, info); - } - - /** - * Returns a Xml representation of the repository descriptors according - * to the info object. - * - * @return Xml representation of the repository descriptors - * @see org.apache.jackrabbit.webdav.xml.XmlSerializable#toXml(Document) - * @param document - */ - public Element toXml(Document document) { - Repository repository = getRepositorySession().getRepository(); - Element report = DomUtil.createElement(document, "repositorydescriptors-report", NAMESPACE); - for (String key : repository.getDescriptorKeys()) { - Element elem = DomUtil.addChildElement(report, XML_DESCRIPTOR, NAMESPACE); - DomUtil.addChildElement(elem, XML_DESCRIPTORKEY, NAMESPACE, key); - for (Value v : repository.getDescriptorValues(key)) { - String value; - try { - value = v.getString(); - } catch (RepositoryException e) { - log.error("Internal error while reading descriptor value: ", e); - value = repository.getDescriptor(key); - } - Element child = DomUtil.addChildElement(elem, XML_DESCRIPTORVALUE, NAMESPACE, value); - if (PropertyType.STRING != v.getType()) { - child.setAttribute(ATTR_VALUE_TYPE, PropertyType.nameFromValue(v.getType())); - } - } - } - return report; - } -} Property changes on: jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/version/report/RepositoryDescriptorsReport.java ___________________________________________________________________ Deleted: svn Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/simple/DavResourceImpl.java =================================================================== --- jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/simple/DavResourceImpl.java (revision 1907912) +++ jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/simple/DavResourceImpl.java (nonexistent) @@ -1,1128 +0,0 @@ -/* - * 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.webdav.simple; - -import org.apache.jackrabbit.JcrConstants; -import org.apache.jackrabbit.server.io.AbstractExportContext; -import org.apache.jackrabbit.server.io.CopyMoveContextImpl; -import org.apache.jackrabbit.server.io.DefaultIOListener; -import org.apache.jackrabbit.server.io.DeleteContextImpl; -import org.apache.jackrabbit.server.io.DeleteManager; -import org.apache.jackrabbit.server.io.ExportContext; -import org.apache.jackrabbit.server.io.ExportContextImpl; -import org.apache.jackrabbit.server.io.IOListener; -import org.apache.jackrabbit.server.io.IOManager; -import org.apache.jackrabbit.server.io.IOUtil; -import org.apache.jackrabbit.server.io.ImportContext; -import org.apache.jackrabbit.server.io.ImportContextImpl; -import org.apache.jackrabbit.server.io.PropertyExportContext; -import org.apache.jackrabbit.server.io.PropertyImportContext; -import org.apache.jackrabbit.util.Text; -import org.apache.jackrabbit.webdav.DavCompliance; -import org.apache.jackrabbit.webdav.DavException; -import org.apache.jackrabbit.webdav.DavResource; -import org.apache.jackrabbit.webdav.DavResourceFactory; -import org.apache.jackrabbit.webdav.DavResourceIterator; -import org.apache.jackrabbit.webdav.DavResourceIteratorImpl; -import org.apache.jackrabbit.webdav.DavResourceLocator; -import org.apache.jackrabbit.webdav.DavServletResponse; -import org.apache.jackrabbit.webdav.DavSession; -import org.apache.jackrabbit.webdav.MultiStatusResponse; -import org.apache.jackrabbit.webdav.bind.BindConstants; -import org.apache.jackrabbit.webdav.bind.BindableResource; -import org.apache.jackrabbit.webdav.bind.ParentElement; -import org.apache.jackrabbit.webdav.bind.ParentSet; -import org.apache.jackrabbit.webdav.io.InputContext; -import org.apache.jackrabbit.webdav.io.OutputContext; -import org.apache.jackrabbit.webdav.jcr.JcrDavException; -import org.apache.jackrabbit.webdav.jcr.JcrDavSession; -import org.apache.jackrabbit.webdav.jcr.lock.JcrActiveLock; -import org.apache.jackrabbit.webdav.lock.ActiveLock; -import org.apache.jackrabbit.webdav.lock.LockDiscovery; -import org.apache.jackrabbit.webdav.lock.LockInfo; -import org.apache.jackrabbit.webdav.lock.LockManager; -import org.apache.jackrabbit.webdav.lock.Scope; -import org.apache.jackrabbit.webdav.lock.SupportedLock; -import org.apache.jackrabbit.webdav.lock.Type; -import org.apache.jackrabbit.webdav.property.DavProperty; -import org.apache.jackrabbit.webdav.property.DavPropertyName; -import org.apache.jackrabbit.webdav.property.DavPropertySet; -import org.apache.jackrabbit.webdav.property.DefaultDavProperty; -import org.apache.jackrabbit.webdav.property.HrefProperty; -import org.apache.jackrabbit.webdav.property.ResourceType; -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.RepositoryException; -import javax.jcr.Session; -import javax.jcr.UnsupportedRepositoryOperationException; -import javax.jcr.Workspace; -import javax.jcr.lock.Lock; -import java.io.IOException; -import java.io.OutputStream; -import java.util.ArrayList; -import java.util.Collections; -import java.util.Date; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.UUID; - -/** - * DavResourceImpl implements a DavResource. - */ -public class DavResourceImpl implements DavResource, BindableResource, JcrConstants { - - /** - * the default logger - */ - private static final Logger log = LoggerFactory.getLogger(DavResourceImpl.class); - - public static final String METHODS = DavResource.METHODS + ", " + BindConstants.METHODS; - - public static final String COMPLIANCE_CLASSES = DavCompliance.concatComplianceClasses( - new String[] { - DavCompliance._1_, - DavCompliance._2_, - DavCompliance._3_, - DavCompliance.BIND - } - ); - - private DavResourceFactory factory; - private LockManager lockManager; - private JcrDavSession session; - private Node node; - private DavResourceLocator locator; - - protected DavPropertySet properties = new DavPropertySet(); - protected boolean propsInitialized = false; - private boolean isCollection = true; - private String rfc4122Uri; - - private ResourceConfig config; - private long modificationTime = IOUtil.UNDEFINED_TIME; - - /** - * Create a new {@link DavResource}. - * - * @param locator - * @param factory - * @param session - * @param config - * @param isCollection - * @throws DavException - */ - public DavResourceImpl(DavResourceLocator locator, DavResourceFactory factory, - DavSession session, ResourceConfig config, - boolean isCollection) throws DavException { - this(locator, factory, session, config, null); - this.isCollection = isCollection; - } - - /** - * Create a new {@link DavResource}. - * - * @param locator - * @param factory - * @param session - * @param config - * @param node - * @throws DavException - */ - public DavResourceImpl(DavResourceLocator locator, DavResourceFactory factory, - DavSession session, ResourceConfig config, Node node) throws DavException { - if (locator == null || session == null || config == null) { - throw new IllegalArgumentException(); - } - JcrDavSession.checkImplementation(session); - this.session = (JcrDavSession)session; - this.factory = factory; - this.locator = locator; - this.config = config; - - if (locator.getResourcePath() != null) { - if (node != null) { - this.node = node; - // define what is a collection in webdav - isCollection = config.isCollectionResource(node); - initRfc4122Uri(); - } - } else { - throw new DavException(DavServletResponse.SC_NOT_FOUND); - } - } - - /** - * If the Node associated with this DavResource has a UUID that allows for the creation of a rfc4122 compliant - * URI, we use it as the value of the protected DAV property DAV:resource-id, which is defined by the BIND - * specification. - */ - private void initRfc4122Uri() { - try { - if (node.isNodeType(MIX_REFERENCEABLE)) { - String uuid = node.getUUID(); - try { - UUID.fromString(uuid); - rfc4122Uri = "urn:uuid:" + uuid; - } catch (IllegalArgumentException e) { - //no, this is not a UUID - } - } - } catch (RepositoryException e) { - log.warn("Error while detecting UUID", e); - } - } - - /** - * @see org.apache.jackrabbit.webdav.DavResource#getComplianceClass() - */ - public String getComplianceClass() { - return COMPLIANCE_CLASSES; - } - - /** - * @return DavResource#METHODS - * @see org.apache.jackrabbit.webdav.DavResource#getSupportedMethods() - */ - public String getSupportedMethods() { - return METHODS; - } - - /** - * @see DavResource#exists() ) - */ - public boolean exists() { - return node != null; - } - - /** - * @see DavResource#isCollection() - */ - public boolean isCollection() { - return isCollection; - } - - /** - * @see org.apache.jackrabbit.webdav.DavResource#getLocator() - */ - public DavResourceLocator getLocator() { - return locator; - } - - /** - * @see DavResource#getResourcePath() - */ - public String getResourcePath() { - return locator.getResourcePath(); - } - - /** - * @see DavResource#getHref() - */ - public String getHref() { - return locator.getHref(isCollection()); - } - - /** - * Returns the the last segment of the resource path.

- * Note that this must not correspond to the name of the underlying - * repository item for two reasons:

    - *
  • SameNameSiblings have an index appended to their item name.
  • - *
  • the resource path may differ from the item path.
  • - *
- * Using the item name as DAV:displayname caused problems with XP built-in - * client in case of resources representing SameNameSibling nodes. - * - * @see DavResource#getDisplayName() - */ - public String getDisplayName() { - String resPath = getResourcePath(); - return (resPath != null) ? Text.getName(resPath) : resPath; - } - - /** - * @see org.apache.jackrabbit.webdav.DavResource#getModificationTime() - */ - public long getModificationTime() { - initProperties(); - return modificationTime; - } - - /** - * If this resource exists and the specified context is not null - * this implementation build a new {@link ExportContext} based on the specified - * context and forwards the export to its IOManager. If the - * {@link IOManager#exportContent(ExportContext, DavResource)} fails, - * an IOException is thrown. - * - * @see DavResource#spool(OutputContext) - * @see ResourceConfig#getIOManager() - * @throws IOException if the export fails. - */ - public void spool(OutputContext outputContext) throws IOException { - if (exists() && outputContext != null) { - ExportContext exportCtx = getExportContext(outputContext); - if (!config.getIOManager().exportContent(exportCtx, this)) { - throw new IOException("Unexpected Error while spooling resource."); - } - } - } - - /** - * @see DavResource#getProperty(org.apache.jackrabbit.webdav.property.DavPropertyName) - */ - public DavProperty getProperty(DavPropertyName name) { - initProperties(); - return properties.get(name); - } - - /** - * @see DavResource#getProperties() - */ - public DavPropertySet getProperties() { - initProperties(); - return properties; - } - - /** - * @see DavResource#getPropertyNames() - */ - public DavPropertyName[] getPropertyNames() { - return getProperties().getPropertyNames(); - } - - /** - * Fill the set of properties - */ - protected void initProperties() { - if (!exists() || propsInitialized) { - return; - } - - try { - config.getPropertyManager().exportProperties(getPropertyExportContext(), isCollection()); - } catch (RepositoryException e) { - log.warn("Error while accessing resource properties", e); - } - - // set (or reset) fundamental properties - if (getDisplayName() != null) { - properties.add(new DefaultDavProperty(DavPropertyName.DISPLAYNAME, getDisplayName())); - } - if (isCollection()) { - properties.add(new ResourceType(ResourceType.COLLECTION)); - // Windows XP support - properties.add(new DefaultDavProperty(DavPropertyName.ISCOLLECTION, "1")); - } else { - properties.add(new ResourceType(ResourceType.DEFAULT_RESOURCE)); - // Windows XP support - properties.add(new DefaultDavProperty(DavPropertyName.ISCOLLECTION, "0")); - } - - if (rfc4122Uri != null) { - properties.add(new HrefProperty(BindConstants.RESOURCEID, rfc4122Uri, true)); - } - - Set parentElements = getParentElements(); - if (!parentElements.isEmpty()) { - properties.add(new ParentSet(parentElements)); - } - - /* set current lock information. If no lock is set to this resource, - an empty lock discovery will be returned in the response. */ - properties.add(new LockDiscovery(getLock(Type.WRITE, Scope.EXCLUSIVE))); - - /* lock support information: all locks are lockable. */ - SupportedLock supportedLock = new SupportedLock(); - supportedLock.addEntry(Type.WRITE, Scope.EXCLUSIVE); - properties.add(supportedLock); - - propsInitialized = true; - } - - /** - * @param property - * @throws DavException - * @see DavResource#setProperty(org.apache.jackrabbit.webdav.property.DavProperty) - */ - public void setProperty(DavProperty property) throws DavException { - alterProperty(property); - } - - /** - * @param propertyName - * @throws DavException - * @see DavResource#removeProperty(org.apache.jackrabbit.webdav.property.DavPropertyName) - */ - public void removeProperty(DavPropertyName propertyName) throws DavException { - alterProperty(propertyName); - } - - private void alterProperty(PropEntry prop) throws DavException { - if (isLocked(this)) { - throw new DavException(DavServletResponse.SC_LOCKED); - } - if (!exists()) { - throw new DavException(DavServletResponse.SC_NOT_FOUND); - } - try { - List list = Collections.singletonList(prop); - alterProperties(list); - Map failure = config.getPropertyManager().alterProperties(getPropertyImportContext(list), isCollection()); - if (failure.isEmpty()) { - node.save(); - } else { - node.refresh(false); - // TODO: retrieve specific error from failure-map - throw new DavException(DavServletResponse.SC_INTERNAL_SERVER_ERROR); - } - } catch (RepositoryException e) { - // revert any changes made so far - JcrDavException je = new JcrDavException(e); - try { - node.refresh(false); - } catch (RepositoryException re) { - // should not happen... - } - throw je; - } - } - - public MultiStatusResponse alterProperties(List changeList) throws DavException { - if (isLocked(this)) { - throw new DavException(DavServletResponse.SC_LOCKED); - } - if (!exists()) { - throw new DavException(DavServletResponse.SC_NOT_FOUND); - } - MultiStatusResponse msr = new MultiStatusResponse(getHref(), null); - try { - Map failures = config.getPropertyManager().alterProperties(getPropertyImportContext(changeList), isCollection()); - if (failures.isEmpty()) { - // save all changes together (reverted in case this fails) - node.save(); - } else { - // set/remove of at least a single prop failed: undo modifications. - node.refresh(false); - } - /* loop over list of properties/names that were successfully altered - and them to the multistatus response respecting the result of the - complete action. in case of failure set the status to 'failed-dependency' - in order to indicate, that altering those names/properties would - have succeeded, if no other error occured.*/ - for (PropEntry propEntry : changeList) { - int statusCode; - if (failures.containsKey(propEntry)) { - Object error = failures.get(propEntry); - statusCode = (error instanceof RepositoryException) - ? new JcrDavException((RepositoryException) error).getErrorCode() - : DavServletResponse.SC_INTERNAL_SERVER_ERROR; - } else { - statusCode = (failures.isEmpty()) ? DavServletResponse.SC_OK : DavServletResponse.SC_FAILED_DEPENDENCY; - } - if (propEntry instanceof DavProperty) { - msr.add(((DavProperty) propEntry).getName(), statusCode); - } else { - msr.add((DavPropertyName) propEntry, statusCode); - } - } - return msr; - } catch (RepositoryException e) { - // revert any changes made so far an throw exception - try { - node.refresh(false); - } catch (RepositoryException re) { - // should not happen - } - throw new JcrDavException(e); - } - } - - /** - * @see DavResource#getCollection() - */ - public DavResource getCollection() { - DavResource parent = null; - if (getResourcePath() != null && !getResourcePath().equals("/")) { - String parentPath = Text.getRelativeParent(getResourcePath(), 1); - if (parentPath.equals("")) { - parentPath = "/"; - } - DavResourceLocator parentloc = locator.getFactory().createResourceLocator(locator.getPrefix(), locator.getWorkspacePath(), parentPath); - try { - parent = factory.createResource(parentloc, session); - } catch (DavException e) { - // should not occur - } - } - return parent; - } - - /** - * @see DavResource#getMembers() - */ - public DavResourceIterator getMembers() { - ArrayList list = new ArrayList(); - if (exists() && isCollection()) { - try { - NodeIterator it = node.getNodes(); - while (it.hasNext()) { - Node n = it.nextNode(); - if (!isFilteredItem(n)) { - DavResourceLocator resourceLocator = locator.getFactory().createResourceLocator(locator.getPrefix(), locator.getWorkspacePath(), n.getPath(), false); - DavResource childRes = factory.createResource(resourceLocator, session); - list.add(childRes); - } else { - log.debug("Filtered resource '" + n.getName() + "'."); - } - } - } catch (RepositoryException e) { - // should not occur - } catch (DavException e) { - // should not occur - } - } - return new DavResourceIteratorImpl(list); - } - - /** - * Adds a new member to this resource. - * - * @see DavResource#addMember(DavResource, org.apache.jackrabbit.webdav.io.InputContext) - */ - public void addMember(DavResource member, InputContext inputContext) throws DavException { - if (!exists()) { - throw new DavException(DavServletResponse.SC_CONFLICT); - } - if (isLocked(this) || isLocked(member)) { - throw new DavException(DavServletResponse.SC_LOCKED); - } - try { - // don't allow creation of nodes if this resource represents a protected - // item or if the new resource would be filtered out - if (isFilteredResource(member) || node.getDefinition().isProtected()) { - log.debug("Forbidden to add member: " + member.getDisplayName()); - throw new DavException(DavServletResponse.SC_FORBIDDEN); - } - - String memberName = Text.getName(member.getLocator().getRepositoryPath()); - ImportContext ctx = getImportContext(inputContext, memberName); - if (!config.getIOManager().importContent(ctx, member)) { - // any changes should have been reverted in the importer - throw new DavException(DavServletResponse.SC_UNSUPPORTED_MEDIA_TYPE); - } - // persist changes after successful import - node.save(); - } catch (RepositoryException e) { - log.error("Error while importing resource: " + e.toString()); - throw new JcrDavException(e); - } catch (IOException e) { - log.error("Error while importing resource: " + e.toString()); - throw new DavException(DavServletResponse.SC_INTERNAL_SERVER_ERROR, e.getMessage()); - } - } - - /** - * @see DavResource#removeMember(DavResource) - */ - public void removeMember(DavResource member) throws DavException { - if (!exists() || !member.exists()) { - throw new DavException(DavServletResponse.SC_NOT_FOUND); - } - if (isLocked(this) || isLocked(member)) { - throw new DavException(DavServletResponse.SC_LOCKED); - } - - // don't allow removal of nodes, that would be filtered out - if (isFilteredResource(member)) { - log.debug("Avoid removal of filtered resource: " + member.getDisplayName()); - throw new DavException(DavServletResponse.SC_FORBIDDEN); - } - - DeleteManager dm = config.getDeleteManager(); - dm.delete(new DeleteContextImpl(getJcrSession()), member); - - // make sure, non-jcr locks are removed, once the removal is completed - try { - if (!isJcrLockable()) { - ActiveLock lock = getLock(Type.WRITE, Scope.EXCLUSIVE); - if (lock != null) { - lockManager.releaseLock(lock.getToken(), member); - } - } - } catch (DavException e) { - // since check for 'locked' exception has been performed before - // ignore any error here - } - } - - /** - * @see DavResource#move(DavResource) - */ - public void move(DavResource destination) throws DavException { - if (!exists()) { - throw new DavException(DavServletResponse.SC_NOT_FOUND); - } - if (isLocked(this)) { - throw new DavException(DavServletResponse.SC_LOCKED); - } - if (isFilteredResource(destination)) { - throw new DavException(DavServletResponse.SC_FORBIDDEN); - } - // make sure, that src and destination belong to the same workspace - checkSameWorkspace(destination.getLocator()); - if (!config.getCopyMoveManager().move(new CopyMoveContextImpl(getJcrSession()), this, destination)) { - throw new DavException(DavServletResponse.SC_UNSUPPORTED_MEDIA_TYPE); - } - } - - /** - * @see DavResource#copy(DavResource, boolean) - */ - public void copy(DavResource destination, boolean shallow) throws DavException { - if (!exists()) { - throw new DavException(DavServletResponse.SC_NOT_FOUND); - } - if (isLocked(destination)) { - throw new DavException(DavServletResponse.SC_LOCKED); - } - if (isFilteredResource(destination)) { - throw new DavException(DavServletResponse.SC_FORBIDDEN); - } - // make sure, that src and destination belong to the same workspace - checkSameWorkspace(destination.getLocator()); - if (!config.getCopyMoveManager().copy(new CopyMoveContextImpl(getJcrSession(), shallow), this, destination)) { - throw new DavException(DavServletResponse.SC_UNSUPPORTED_MEDIA_TYPE); - } - } - - /** - * @param type - * @param scope - * @return true if type is {@link Type#WRITE} and scope is {@link Scope#EXCLUSIVE} - * @see DavResource#isLockable(org.apache.jackrabbit.webdav.lock.Type, org.apache.jackrabbit.webdav.lock.Scope) - */ - public boolean isLockable(Type type, Scope scope) { - return Type.WRITE.equals(type) && Scope.EXCLUSIVE.equals(scope); - } - - /** - * @see DavResource#hasLock(org.apache.jackrabbit.webdav.lock.Type, org.apache.jackrabbit.webdav.lock.Scope) - */ - public boolean hasLock(Type type, Scope scope) { - return getLock(type, scope) != null; - } - - /** - * @see DavResource#getLock(Type, Scope) - */ - public ActiveLock getLock(Type type, Scope scope) { - ActiveLock lock = null; - if (exists() && Type.WRITE.equals(type) && Scope.EXCLUSIVE.equals(scope)) { - // try to retrieve the repository lock information first - try { - if (node.isLocked()) { - Lock jcrLock = node.getLock(); - if (jcrLock != null && jcrLock.isLive()) { - lock = new JcrActiveLock(jcrLock); - String lockroot = locator - .getFactory() - .createResourceLocator(locator.getPrefix(), locator.getWorkspacePath(), - jcrLock.getNode().getPath(), false).getHref(false); - lock.setLockroot(lockroot); - } - } - } catch (RepositoryException e) { - // LockException (no lock applies) >> should never occur - // RepositoryException, AccessDeniedException or another error >> ignore - } - - // could not retrieve a jcr-lock. test if a simple webdav lock is present. - if (lock == null) { - lock = lockManager.getLock(type, scope, this); - } - } - return lock; - } - - /** - * @see org.apache.jackrabbit.webdav.DavResource#getLocks() - */ - public ActiveLock[] getLocks() { - ActiveLock writeLock = getLock(Type.WRITE, Scope.EXCLUSIVE); - return (writeLock != null) ? new ActiveLock[]{writeLock} : new ActiveLock[0]; - } - - /** - * @see DavResource#lock(LockInfo) - */ - public ActiveLock lock(LockInfo lockInfo) throws DavException { - ActiveLock lock = null; - if (isLockable(lockInfo.getType(), lockInfo.getScope())) { - // TODO: deal with existing locks, that may have been created, before the node was jcr-lockable... - if (isJcrLockable()) { - try { - javax.jcr.lock.LockManager lockMgr = node.getSession().getWorkspace().getLockManager(); - long timeout = lockInfo.getTimeout(); - if (timeout == LockInfo.INFINITE_TIMEOUT) { - timeout = Long.MAX_VALUE; - } else { - timeout = timeout / 1000; - } - // try to execute the lock operation - Lock jcrLock = lockMgr.lock(node.getPath(), lockInfo.isDeep(), false, timeout, lockInfo.getOwner()); - if (jcrLock != null) { - lock = new JcrActiveLock(jcrLock); - } - } catch (RepositoryException e) { - throw new JcrDavException(e); - } - } else { - // create a new webdav lock - lock = lockManager.createLock(lockInfo, this); - } - } else { - throw new DavException(DavServletResponse.SC_PRECONDITION_FAILED, "Unsupported lock type or scope."); - } - return lock; - } - - /** - * @see DavResource#refreshLock(LockInfo, String) - */ - public ActiveLock refreshLock(LockInfo lockInfo, String lockToken) throws DavException { - if (!exists()) { - throw new DavException(DavServletResponse.SC_NOT_FOUND); - } - ActiveLock lock = getLock(lockInfo.getType(), lockInfo.getScope()); - if (lock == null) { - throw new DavException(DavServletResponse.SC_PRECONDITION_FAILED, "No lock with the given type/scope present on resource " + getResourcePath()); - } - - if (lock instanceof JcrActiveLock) { - try { - // refresh JCR lock and return the original lock object. - node.getLock().refresh(); - } catch (RepositoryException e) { - throw new JcrDavException(e); - } - } else { - lock = lockManager.refreshLock(lockInfo, lockToken, this); - } - /* since lock has infinite lock (simple) or undefined timeout (jcr) - return the lock as retrieved from getLock. */ - return lock; - } - - /** - * @see DavResource#unlock(String) - */ - public void unlock(String lockToken) throws DavException { - ActiveLock lock = getLock(Type.WRITE, Scope.EXCLUSIVE); - if (lock == null) { - throw new DavException(DavServletResponse.SC_PRECONDITION_FAILED); - } else if (lock.isLockedByToken(lockToken)) { - if (lock instanceof JcrActiveLock) { - try { - node.unlock(); - } catch (RepositoryException e) { - throw new JcrDavException(e); - } - } else { - lockManager.releaseLock(lockToken, this); - } - } else { - throw new DavException(DavServletResponse.SC_LOCKED); - } - } - - /** - * @see DavResource#addLockManager(org.apache.jackrabbit.webdav.lock.LockManager) - */ - public void addLockManager(LockManager lockMgr) { - this.lockManager = lockMgr; - } - - /** - * @see org.apache.jackrabbit.webdav.DavResource#getFactory() - */ - public DavResourceFactory getFactory() { - return factory; - } - - /** - * @see org.apache.jackrabbit.webdav.DavResource#getSession() - */ - public DavSession getSession() { - return session; - } - - - /** - * @see BindableResource#rebind(DavResource, DavResource) - */ - public void bind(DavResource collection, DavResource newBinding) throws DavException { - if (!exists()) { - //DAV:bind-source-exists - throw new DavException(DavServletResponse.SC_PRECONDITION_FAILED); - } - if (isLocked(collection)) { - //DAV:locked-update-allowed? - throw new DavException(DavServletResponse.SC_LOCKED); - } - if (isFilteredResource(newBinding)) { - throw new DavException(DavServletResponse.SC_FORBIDDEN); - } - checkSameWorkspace(collection.getLocator()); - try { - if (!node.isNodeType(MIX_SHAREABLE)) { - if (!node.canAddMixin(MIX_SHAREABLE)) { - //DAV:binding-allowed - throw new DavException(DavServletResponse.SC_PRECONDITION_FAILED); - } - node.addMixin(MIX_SHAREABLE); - node.save(); - } - Workspace workspace = session.getRepositorySession().getWorkspace(); - workspace.clone(workspace.getName(), node.getPath(), newBinding.getLocator().getRepositoryPath(), false); - - } catch (RepositoryException e) { - throw new JcrDavException(e); - } - - } - - /** - * @see BindableResource#rebind(DavResource, DavResource) - */ - public void rebind(DavResource collection, DavResource newBinding) throws DavException { - if (!exists()) { - //DAV:rebind-source-exists - throw new DavException(DavServletResponse.SC_PRECONDITION_FAILED); - } - if (isLocked(this)) { - //DAV:protected-source-url-deletion.allowed - throw new DavException(DavServletResponse.SC_PRECONDITION_FAILED); - } - if (isLocked(collection)) { - //DAV:locked-update-allowed? - throw new DavException(DavServletResponse.SC_LOCKED); - } - if (isFilteredResource(newBinding)) { - throw new DavException(DavServletResponse.SC_FORBIDDEN); - } - checkSameWorkspace(collection.getLocator()); - try { - if (!node.isNodeType(MIX_REFERENCEABLE)) { - throw new DavException(node.canAddMixin(MIX_REFERENCEABLE)? - DavServletResponse.SC_CONFLICT : DavServletResponse.SC_METHOD_NOT_ALLOWED); - } - getJcrSession().getWorkspace().move(locator.getRepositoryPath(), newBinding.getLocator().getRepositoryPath()); - } catch (RepositoryException e) { - throw new JcrDavException(e); - } - } - - /** - * @see org.apache.jackrabbit.webdav.bind.BindableResource#getParentElements() - */ - public Set getParentElements() { - try { - if (node.getDepth() > 0) { - Set ps = new HashSet(); - NodeIterator sharedSetIterator = node.getSharedSet(); - while (sharedSetIterator.hasNext()) { - Node sharednode = sharedSetIterator.nextNode(); - DavResourceLocator loc = locator.getFactory().createResourceLocator( - locator.getPrefix(), locator.getWorkspacePath(), sharednode.getParent().getPath(), false); - ps.add(new ParentElement(loc.getHref(true), sharednode.getName())); - } - return ps; - } - } catch (UnsupportedRepositoryOperationException e) { - log.debug("unable to calculate parent set", e); - } catch (RepositoryException e) { - log.warn("unable to calculate parent set", e); - } - return Collections.emptySet(); - } - - /** - * Returns the node that is wrapped by this resource. - * - * @return The underlying JCR node instance. - */ - protected Node getNode() { - return node; - } - - /** - * Returns a new ImportContext - * - * @param inputCtx - * @param systemId - * @return a new ImportContext - * @throws IOException - */ - protected ImportContext getImportContext(InputContext inputCtx, String systemId) throws IOException { - return new ImportContextImpl( - node, systemId, inputCtx, - (inputCtx != null) ? inputCtx.getInputStream() : null, - new DefaultIOListener(log), config.getDetector()); - } - - /** - * Returns a new ExportContext - * - * @param outputCtx - * @return a new ExportContext - * @throws IOException - */ - protected ExportContext getExportContext(OutputContext outputCtx) throws IOException { - return new ExportContextImpl(node, outputCtx); - } - - /** - * Returns a new PropertyImportContext. - * - * @param changeList - * @return a new PropertyImportContext. - */ - protected PropertyImportContext getPropertyImportContext(List changeList) { - return new PropertyImportCtx(changeList); - } - - /** - * Returns a new PropertyExportContext. - * - * @return a new PropertyExportContext - */ - protected PropertyExportContext getPropertyExportContext() { - return new PropertyExportCtx(); - } - - /** - * Returns true, if the underlying node is nodetype jcr:lockable, - * without checking its current lock status. If the node is not jcr-lockable - * an attempt is made to add the mix:lockable mixin type. - * - * @return true if this resource is lockable. - */ - private boolean isJcrLockable() { - boolean lockable = false; - if (exists()) { - try { - lockable = node.isNodeType(MIX_LOCKABLE); - // not jcr-lockable: try to make the node jcr-lockable - if (!lockable && node.canAddMixin(MIX_LOCKABLE)) { - node.addMixin(MIX_LOCKABLE); - node.save(); - lockable = true; - } - } catch (RepositoryException e) { - // -> node is definitely not jcr-lockable. - } - } - return lockable; - } - - /** - * Return true if this resource cannot be modified due to a write lock - * that is not owned by the given session. - * - * @return true if this resource cannot be modified due to a write lock - */ - private boolean isLocked(DavResource res) { - ActiveLock lock = res.getLock(Type.WRITE, Scope.EXCLUSIVE); - if (lock == null) { - return false; - } else { - for (String sLockToken : session.getLockTokens()) { - if (sLockToken.equals(lock.getToken())) { - return false; - } - } - return true; - } - } - - private Session getJcrSession() { - return session.getRepositorySession(); - } - - private boolean isFilteredResource(DavResource resource) { - // TODO: filtered nodetypes should be checked as well in order to prevent problems. - ItemFilter filter = config.getItemFilter(); - return filter != null && filter.isFilteredItem(resource.getDisplayName(), getJcrSession()); - } - - private boolean isFilteredItem(Item item) { - ItemFilter filter = config.getItemFilter(); - return filter != null && filter.isFilteredItem(item); - } - - private void checkSameWorkspace(DavResourceLocator otherLoc) throws DavException { - String wspname = getJcrSession().getWorkspace().getName(); - if (!wspname.equals(otherLoc.getWorkspaceName())) { - throw new DavException(DavServletResponse.SC_FORBIDDEN, "Workspace mismatch: expected '" + wspname + "'; found: '" + otherLoc.getWorkspaceName() + "'"); - } - } - - //--------------------------------------------------------< inner class >--- - /** - * ExportContext that writes the properties of this DavResource - * and provides not stream. - */ - private class PropertyExportCtx extends AbstractExportContext implements PropertyExportContext { - - private PropertyExportCtx() { - super(node, false, null); - // set defaults: - setCreationTime(IOUtil.UNDEFINED_TIME); - setModificationTime(IOUtil.UNDEFINED_TIME); - } - - public OutputStream getOutputStream() { - return null; - } - - public void setContentLanguage(String contentLanguage) { - if (contentLanguage != null) { - properties.add(new DefaultDavProperty(DavPropertyName.GETCONTENTLANGUAGE, contentLanguage)); - } - } - - public void setContentLength(long contentLength) { - if (contentLength > IOUtil.UNDEFINED_LENGTH) { - properties.add(new DefaultDavProperty(DavPropertyName.GETCONTENTLENGTH, contentLength + "")); - } - } - - public void setContentType(String mimeType, String encoding) { - String contentType = IOUtil.buildContentType(mimeType, encoding); - if (contentType != null) { - properties.add(new DefaultDavProperty(DavPropertyName.GETCONTENTTYPE, contentType)); - } - } - - public void setCreationTime(long creationTime) { - String created = IOUtil.getCreated(creationTime); - properties.add(new DefaultDavProperty(DavPropertyName.CREATIONDATE, created)); - } - - public void setModificationTime(long modTime) { - if (modTime <= IOUtil.UNDEFINED_TIME) { - modificationTime = new Date().getTime(); - } else { - modificationTime = modTime; - } - String lastModified = IOUtil.getLastModified(modificationTime); - properties.add(new DefaultDavProperty(DavPropertyName.GETLASTMODIFIED, lastModified)); - } - - public void setETag(String etag) { - if (etag != null) { - properties.add(new DefaultDavProperty(DavPropertyName.GETETAG, etag)); - } - } - - public void setProperty(Object propertyName, Object propertyValue) { - if (propertyValue == null) { - log.warn("Ignore 'setProperty' for " + propertyName + "with null value."); - return; - } - - if (propertyValue instanceof DavProperty) { - properties.add((DavProperty)propertyValue); - } else { - DavPropertyName pName; - if (propertyName instanceof DavPropertyName) { - pName = (DavPropertyName)propertyName; - } else { - // create property name with default DAV: namespace - pName = DavPropertyName.create(propertyName.toString()); - } - properties.add(new DefaultDavProperty(pName, propertyValue)); - } - } - } - - private class PropertyImportCtx implements PropertyImportContext { - - private final IOListener ioListener = new DefaultIOListener(log); - private final List changeList; - private boolean completed; - - private PropertyImportCtx(List changeList) { - this.changeList = changeList; - } - - /** - * @see PropertyImportContext#getImportRoot() - */ - public Item getImportRoot() { - return node; - } - - /** - * @see PropertyImportContext#getChangeList() - */ - public List getChangeList() { - return Collections.unmodifiableList(changeList); - } - - public IOListener getIOListener() { - return ioListener; - } - - public boolean hasStream() { - return false; - } - - /** - * @see PropertyImportContext#informCompleted(boolean) - */ - public void informCompleted(boolean success) { - checkCompleted(); - completed = true; - } - - /** - * @see PropertyImportContext#isCompleted() - */ - public boolean isCompleted() { - return completed; - } - - /** - * @throws IllegalStateException if the context is already completed. - * @see #isCompleted() - * @see #informCompleted(boolean) - */ - private void checkCompleted() { - if (completed) { - throw new IllegalStateException("PropertyImportContext has already been consumed."); - } - } - } -} Property changes on: jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/simple/DavResourceImpl.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/simple/DavSessionImpl.java =================================================================== --- jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/simple/DavSessionImpl.java (revision 1907912) +++ jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/simple/DavSessionImpl.java (nonexistent) @@ -1,81 +0,0 @@ -/* - * 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.webdav.simple; - -import org.apache.jackrabbit.webdav.DavSession; -import org.apache.jackrabbit.webdav.jcr.JcrDavSession; - -import javax.jcr.Session; -import java.util.HashSet; - -/** - * Simple implementation of the {@link DavSession} interface. Stores - * lock tokens but does not yet store references. - */ -public class DavSessionImpl extends JcrDavSession { - - /** the lock tokens of this session */ - private final HashSet lockTokens = new HashSet(); - - /** - * Creates a new DavSession based on a jcr session - * @param session - */ - public DavSessionImpl(Session session) { - super(session); - } - - /** - * @see DavSession#addReference(Object) - */ - public void addReference(Object reference) { - throw new UnsupportedOperationException("No yet implemented."); - } - - /** - * @see DavSession#removeReference(Object) - */ - public void removeReference(Object reference) { - throw new UnsupportedOperationException("No yet implemented."); - } - - /** - * @see DavSession#addLockToken(String) - */ - @Override - public void addLockToken(String token) { - super.addLockToken(token); - lockTokens.add(token); - } - - /** - * @see DavSession#getLockTokens() - */ - @Override - public String[] getLockTokens() { - return lockTokens.toArray(new String[lockTokens.size()]); - } - - /** - * @see DavSession#removeLockToken(String) - */ - @Override - public void removeLockToken(String token) { - super.removeLockToken(token); - lockTokens.remove(token); - } -} Property changes on: jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/simple/DavSessionImpl.java ___________________________________________________________________ Deleted: svn Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/simple/DavSessionProviderImpl.java =================================================================== --- jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/simple/DavSessionProviderImpl.java (revision 1907912) +++ jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/simple/DavSessionProviderImpl.java (nonexistent) @@ -1,127 +0,0 @@ -/* - * 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.webdav.simple; - -import org.apache.jackrabbit.server.CredentialsProvider; -import org.apache.jackrabbit.server.SessionProvider; -import org.apache.jackrabbit.webdav.DavException; -import org.apache.jackrabbit.webdav.DavServletResponse; -import org.apache.jackrabbit.webdav.DavSession; -import org.apache.jackrabbit.webdav.DavSessionProvider; -import org.apache.jackrabbit.webdav.WebdavRequest; -import org.apache.jackrabbit.webdav.jcr.JcrDavException; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import javax.jcr.NoSuchWorkspaceException; -import javax.jcr.Repository; -import javax.jcr.RepositoryException; -import javax.jcr.Session; -import javax.servlet.ServletException; - -/** - * Simple implementation of the {@link org.apache.jackrabbit.webdav.DavSessionProvider} - * interface that uses a {@link CredentialsProvider} to locate - * credentials in the request, log into the respository, and provide - * a {@link org.apache.jackrabbit.webdav.DavSession} to the request. - */ -public class DavSessionProviderImpl implements DavSessionProvider { - - private static Logger log = LoggerFactory.getLogger(DavSessionProviderImpl.class); - - /** - * the repository - */ - private final Repository repository; - - /** - * the credentials provider - */ - private final SessionProvider sesProvider; - - /** - * Creates a new DavSessionProviderImpl - * @param rep - * @param sesProvider - */ - public DavSessionProviderImpl(Repository rep, SessionProvider sesProvider) { - this.repository = rep; - this.sesProvider = sesProvider; - } - - /** - * Acquires a DavSession. Upon success, the WebdavRequest will - * reference that session. - * - * A session will not be available if an exception is thrown. - * - * @param request - * @throws org.apache.jackrabbit.webdav.DavException if a problem occurred while obtaining the session - * @see DavSessionProvider#attachSession(org.apache.jackrabbit.webdav.WebdavRequest) - */ - public boolean attachSession(WebdavRequest request) throws DavException { - try { - // retrieve the workspace name - String workspaceName = request.getRequestLocator().getWorkspaceName(); - // empty workspaceName rather means default -> must be 'null' - if (workspaceName != null && "".equals(workspaceName)) { - workspaceName = null; - } - // login to repository - Session repSession = sesProvider.getSession(request, repository, workspaceName); - if (repSession == null) { - log.debug("Could not to retrieve a repository session."); - return false; - } - DavSession ds = new DavSessionImpl(repSession); - log.debug("Attaching session '"+ ds + "' to request '" + request + "'"); - request.setDavSession(ds); - return true; - } catch (NoSuchWorkspaceException e) { - // the default error-code for NoSuchWorkspaceException is 409 conflict - // which seems not appropriate here - throw new JcrDavException(e, DavServletResponse.SC_NOT_FOUND); - } catch (RepositoryException e) { - throw new JcrDavException(e); - } catch (ServletException e) { - throw new DavException(DavServletResponse.SC_INTERNAL_SERVER_ERROR, e.getMessage()); - } - } - - /** - * Only removes the DavSession object from the given request object. - * and remove all the lock tokens from the underlying repository session - * in order make sure they can be reset when attaching a session to the - * next request. Finally the session provider is informed, that the - * session is no longer used. - * - * @param request - * @see DavSessionProvider#releaseSession(org.apache.jackrabbit.webdav.WebdavRequest) - */ - public void releaseSession(WebdavRequest request) { - DavSession ds = request.getDavSession(); - if (ds != null && ds instanceof DavSessionImpl) { - Session repSession = ((DavSessionImpl)ds).getRepositorySession(); - for (String lockToken : repSession.getLockTokens()) { - repSession.removeLockToken(lockToken); - } - sesProvider.releaseSession(repSession); - log.debug("Releasing session '"+ ds + "' from request '" + request + "'"); - } // else : session is null. nothing to be done. - request.setDavSession(null); - } -} Property changes on: jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/simple/DavSessionProviderImpl.java ___________________________________________________________________ Deleted: svn Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/simple/DefaultItemFilter.java =================================================================== --- jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/simple/DefaultItemFilter.java (revision 1907912) +++ jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/simple/DefaultItemFilter.java (nonexistent) @@ -1,158 +0,0 @@ -/* - * 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.webdav.simple; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import javax.jcr.Item; -import javax.jcr.Node; -import javax.jcr.Property; -import javax.jcr.RepositoryException; -import javax.jcr.Session; -import java.util.ArrayList; -import java.util.List; - -/** - * DefaultItemFilter... - */ -public class DefaultItemFilter implements ItemFilter { - - private static Logger log = LoggerFactory.getLogger(DefaultItemFilter.class); - - private List prefixFilter = new ArrayList(); - private List uriFilter = new ArrayList(); - private List nodetypeFilter = new ArrayList(); - - public DefaultItemFilter() { - } - - /** - * @see ItemFilter#setFilteredURIs(String[]) - */ - public void setFilteredURIs(String[] uris) { - if (uris != null) { - for (String uri : uris) { - uriFilter.add(uri); - } - } - } - - /** - * @see ItemFilter#setFilteredPrefixes(String[]) - */ - public void setFilteredPrefixes(String[] prefixes) { - if (prefixes != null) { - for (String prefix : prefixes) { - prefixFilter.add(prefix); - } - } - } - - /** - * @see ItemFilter#setFilteredNodetypes(String[]) - */ - public void setFilteredNodetypes(String[] nodetypeNames) { - if (nodetypeNames != null) { - for (String nodetypeName : nodetypeNames) { - nodetypeFilter.add(nodetypeName); - } - } - } - - /** - * Returns true if the given item matches either one of the namespace or - * of the the nodetype filters specified. - * - * @see ItemFilter#isFilteredItem(Item) - */ - public boolean isFilteredItem(Item item) { - return isFilteredNamespace(item) || isFilteredNodeType(item); - } - - /** - * @see ItemFilter#isFilteredItem(String, Session) - */ - public boolean isFilteredItem(String displayName, Session session) { - return isFilteredNamespace(displayName, session); - } - - /** - * - * @param name - * @param session - * @return - */ - private boolean isFilteredNamespace(String name, Session session) { - // shortcut - if (prefixFilter.isEmpty() && uriFilter.isEmpty()) { - return false; - } - int pos = name.indexOf(':'); - if (pos < 0) { - // no namespace info present - return false; - } - try { - String prefix = name.substring(0, pos); - String uri = session.getNamespaceURI(prefix); - return prefixFilter.contains(prefix) || uriFilter.contains(uri); - } catch (RepositoryException e) { - log.warn(e.getMessage()); - } - return false; - } - - /** - * - * @param item - * @return - */ - private boolean isFilteredNamespace(Item item) { - try { - return isFilteredNamespace(item.getName(), item.getSession()); - } catch (RepositoryException e) { - log.warn(e.getMessage()); - } - return false; - } - - /** - * - * @param item - * @return - */ - private boolean isFilteredNodeType(Item item) { - // shortcut - if (nodetypeFilter.isEmpty()) { - return false; - } - try { - String ntName; - if (item.isNode()) { - ntName = ((Node) item).getDefinition().getDeclaringNodeType().getName(); - } else { - ntName = ((Property) item).getDefinition().getDeclaringNodeType().getName(); - } - return nodetypeFilter.contains(ntName); - } catch (RepositoryException e) { - log.warn(e.getMessage()); - } - // nodetype info could not be retrieved - return false; - } -} Property changes on: jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/simple/DefaultItemFilter.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Deleted: svn:keywords ## -1 +0,0 ## -author date id revision url \ No newline at end of property Index: jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/simple/DeltaVResourceImpl.java =================================================================== --- jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/simple/DeltaVResourceImpl.java (revision 1907912) +++ jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/simple/DeltaVResourceImpl.java (nonexistent) @@ -1,274 +0,0 @@ -/* - * 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.webdav.simple; - -import java.util.ArrayList; -import java.util.List; - -import javax.jcr.Item; -import javax.jcr.Node; -import javax.jcr.RepositoryException; -import javax.jcr.Property; -import javax.xml.parsers.ParserConfigurationException; - -import org.apache.jackrabbit.JcrConstants; -import org.apache.jackrabbit.webdav.DavCompliance; -import org.apache.jackrabbit.webdav.DavException; -import org.apache.jackrabbit.webdav.DavLocatorFactory; -import org.apache.jackrabbit.webdav.DavResource; -import org.apache.jackrabbit.webdav.DavResourceFactory; -import org.apache.jackrabbit.webdav.DavResourceLocator; -import org.apache.jackrabbit.webdav.DavServletResponse; -import org.apache.jackrabbit.webdav.DavSession; -import org.apache.jackrabbit.webdav.property.DavProperty; -import org.apache.jackrabbit.webdav.property.DavPropertyName; -import org.apache.jackrabbit.webdav.property.HrefProperty; -import org.apache.jackrabbit.webdav.property.DefaultDavProperty; -import org.apache.jackrabbit.webdav.version.DeltaVConstants; -import org.apache.jackrabbit.webdav.version.DeltaVResource; -import org.apache.jackrabbit.webdav.version.OptionsInfo; -import org.apache.jackrabbit.webdav.version.OptionsResponse; -import org.apache.jackrabbit.webdav.version.report.Report; -import org.apache.jackrabbit.webdav.version.report.ReportInfo; -import org.apache.jackrabbit.webdav.version.report.ReportType; -import org.apache.jackrabbit.webdav.version.report.SupportedReportSetProperty; -import org.apache.jackrabbit.webdav.xml.DomUtil; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.w3c.dom.Element; - -/** - * The DeltaVResourceImpl encapsulates the functionality common to all - * DeltaV compliant resources. - */ -public class DeltaVResourceImpl extends DavResourceImpl implements DeltaVResource { - - protected SupportedReportSetProperty supportedReports = new SupportedReportSetProperty(); - private static final Logger log = LoggerFactory.getLogger(DeltaVResourceImpl.class); - - private static final String DELTAV_COMPLIANCE_CLASSES = DavCompliance.concatComplianceClasses( - new String[] { - DavResourceImpl.COMPLIANCE_CLASSES, - DavCompliance.BIND, - } - ); - - public DeltaVResourceImpl(DavResourceLocator locator, DavResourceFactory factory, DavSession session, ResourceConfig config, Item item) throws DavException { - super(locator, factory, session, config, (Node)item); - initSupportedReports(); - } - - public DeltaVResourceImpl(DavResourceLocator locator, DavResourceFactory factory, DavSession session, ResourceConfig config, boolean isCollection) throws DavException { - super(locator, factory, session, config, isCollection); - initSupportedReports(); - } - - //---------------------------------------------------------< DavResource>--- - /** - * @see org.apache.jackrabbit.webdav.DavResource#getComplianceClass() - */ - @Override - public String getComplianceClass() { - return DELTAV_COMPLIANCE_CLASSES; - } - - //------------------------------------------------------< DeltaVResource>--- - /** - * @param optionsInfo - * @return object to be used in the OPTIONS response body or null - * @see DeltaVResource#getOptionResponse(org.apache.jackrabbit.webdav.version.OptionsInfo) - */ - public OptionsResponse getOptionResponse(OptionsInfo optionsInfo) { - OptionsResponse oR = null; - if (optionsInfo != null) { - oR = new OptionsResponse(); - // currently only DAV:version-history-collection-set is supported - if (optionsInfo.containsElement(DeltaVConstants.XML_VH_COLLECTION_SET, DeltaVConstants.NAMESPACE)) { - String[] hrefs = new String[] { - getLocatorFromNodePath("/"+JcrConstants.JCR_SYSTEM+"/"+JcrConstants.JCR_VERSIONSTORAGE).getHref(true) - }; - oR.addEntry(DeltaVConstants.XML_VH_COLLECTION_SET, DeltaVConstants.NAMESPACE, hrefs); - } - } - return oR; - } - - /** - * @param reportInfo - * @return the requested report - * @throws DavException - * @see DeltaVResource#getReport(org.apache.jackrabbit.webdav.version.report.ReportInfo) - */ - public Report getReport(ReportInfo reportInfo) throws DavException { - if (reportInfo == null) { - throw new DavException(DavServletResponse.SC_BAD_REQUEST, "A REPORT request must provide a valid XML request body."); - } - if (!exists()) { - throw new DavException(DavServletResponse.SC_NOT_FOUND); - } - - if (!supportedReports.isSupportedReport(reportInfo)) { - Element condition = null; - try { - condition = DomUtil.createDocument().createElementNS("DAV:", "supported-report"); - } catch (ParserConfigurationException ex) { - // we don't care THAT much - } - throw new DavException(DavServletResponse.SC_CONFLICT, - "Unknown report '" + reportInfo.getReportName() + "' requested.", null, condition); - } - return ReportType.getType(reportInfo).createReport(this, reportInfo); - } - - /** - * The JCR api does not provide methods to create new workspaces. Calling - * addWorkspace on this resource will always fail. - * - * @param workspace - * @throws DavException Always throws. - * @see DeltaVResource#addWorkspace(org.apache.jackrabbit.webdav.DavResource) - */ - public void addWorkspace(DavResource workspace) throws DavException { - throw new DavException(DavServletResponse.SC_FORBIDDEN); - } - - /** - * Return an array of DavResource objects that are referenced - * by the property with the specified name. - * - * @param hrefPropertyName - * @return array of DavResources - * @throws DavException - * @see DeltaVResource#getReferenceResources(org.apache.jackrabbit.webdav.property.DavPropertyName) - */ - public DavResource[] getReferenceResources(DavPropertyName hrefPropertyName) throws DavException { - DavProperty prop = getProperty(hrefPropertyName); - List resources = new ArrayList(); - if (prop != null && prop instanceof HrefProperty) { - HrefProperty hp = (HrefProperty)prop; - // process list of hrefs - for (String href : hp.getHrefs()) { - DavResourceLocator locator = getLocator().getFactory().createResourceLocator(getLocator().getPrefix(), href); - resources.add(createResourceFromLocator(locator)); - } - } else { - throw new DavException(DavServletResponse.SC_INTERNAL_SERVER_ERROR); - } - return resources.toArray(new DavResource[resources.size()]); - } - - /** - * Build a DavResourceLocator from the given nodePath path. - * - * @param nodePath - * @return a new DavResourceLocator - * @see DavLocatorFactory#createResourceLocator(String, String, String) - */ - protected DavResourceLocator getLocatorFromNodePath(String nodePath) { - DavResourceLocator loc = getLocator().getFactory().createResourceLocator(getLocator().getPrefix(), getLocator().getWorkspacePath(), nodePath, false); - return loc; - } - - - /** - * Build a new {@link DavResourceLocator} from the given repository node. - * - * @param repositoryNode - * @return a new locator for the specified node. - * @see #getLocatorFromNodePath(String) - */ - protected DavResourceLocator getLocatorFromNode(Node repositoryNode) { - String nodePath = null; - try { - if (repositoryNode != null) { - nodePath = repositoryNode.getPath(); - } - } catch (RepositoryException e) { - // ignore: should not occur - log.warn(e.getMessage()); - } - return getLocatorFromNodePath(nodePath); - } - - /** - * Create a new DavResource from the given locator. - * @param loc - * @return new DavResource - */ - protected DavResource createResourceFromLocator(DavResourceLocator loc) - throws DavException { - DavResource res = getFactory().createResource(loc, getSession()); - return res; - } - - /** - * Returns a {@link org.apache.jackrabbit.webdav.property.HrefProperty} with the - * specified property name and values. Each node present in the specified - * array is referenced in the resulting property. - * - * @param name - * @param values - * @param isProtected - * @return HrefProperty - */ - protected HrefProperty getHrefProperty(DavPropertyName name, Node[] values, - boolean isProtected, boolean isCollection) { - if (values == null) { - return null; - } - String[] pHref = new String[values.length]; - for (int i = 0; i < values.length; i++) { - pHref[i] = getLocatorFromNode(values[i]).getHref(isCollection); - } - return new HrefProperty(name, pHref, isProtected); - } - - /** - * Initialize the supported reports field - */ - protected void initSupportedReports() { - if (exists()) { - supportedReports.addReportType(ReportType.EXPAND_PROPERTY); - if (isCollection()) { - supportedReports.addReportType(ReportType.LOCATE_BY_HISTORY); - } - } - } - - /** - * Fill the property set for this resource. - */ - @Override - protected void initProperties() { - if (!propsInitialized) { - super.initProperties(); - if (exists()) { - properties.add(supportedReports); - - // DAV:creator-displayname -> use jcr:createBy if present. - Node n = getNode(); - try { - if (n.hasProperty(Property.JCR_CREATED_BY)) { - String createdBy = n.getProperty(Property.JCR_CREATED_BY).getString(); - properties.add(new DefaultDavProperty(DeltaVConstants.CREATOR_DISPLAYNAME, createdBy, true)); - } - } catch (RepositoryException e) { - log.debug("Error while accessing jcr:createdBy property"); - } - } - } - } -} Property changes on: jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/simple/DeltaVResourceImpl.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Deleted: svn:keywords ## -1 +0,0 ## -author date id revision url \ No newline at end of property Index: jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/simple/ItemFilter.java =================================================================== --- jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/simple/ItemFilter.java (revision 1907912) +++ jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/simple/ItemFilter.java (nonexistent) @@ -1,68 +0,0 @@ -/* - * 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.webdav.simple; - -import javax.jcr.Item; -import javax.jcr.Session; - -/** - * ItemFilter - */ -public interface ItemFilter { - - /** - * Define the URIs that should be filtered out if present in the prefix - * of an items name. - * - * @param uris - */ - public void setFilteredURIs(String[] uris); - - /** - * Define the namespace prefixes that should be filtered if present in - * the prefix of an items name. - * - * @param prefixes - */ - public void setFilteredPrefixes(String[] prefixes); - - /** - * Set the nodetype names that should be used if a given item should be - * filtered. Note that not the nodetype(s) defined for a given item - * is relevant but rather the nodetype that defined the definition of the item. - * - * @param nodetypeNames - */ - public void setFilteredNodetypes(String[] nodetypeNames); - - /** - * Returns true if the given item should be filtered. - * - * @param item to be tested - * @return true if the given item should be filtered. - */ - public boolean isFilteredItem(Item item); - - /** - * Returns true if the resouce with the given name should be filtered. - * - * @param name to be tested for a filtered namespace prefix - * @param session used for looking up namespace mappings - * @return true if the given resource should be filtered. - */ - public boolean isFilteredItem(String name, Session session); -} \ No newline at end of file Property changes on: jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/simple/ItemFilter.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Deleted: svn:keywords ## -1 +0,0 ## -author date id revision url \ No newline at end of property Index: jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/simple/LocatorFactoryImpl.java =================================================================== --- jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/simple/LocatorFactoryImpl.java (revision 1907912) +++ jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/simple/LocatorFactoryImpl.java (nonexistent) @@ -1,165 +0,0 @@ -/* - * 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.webdav.simple; - -import org.apache.jackrabbit.util.Text; -import org.apache.jackrabbit.webdav.DavLocatorFactory; -import org.apache.jackrabbit.webdav.DavResourceLocator; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * ResourceFactoryImpl implements a simple DavLocatorFactory - */ -// todo improve special handling of root item.... -public class LocatorFactoryImpl implements DavLocatorFactory { - - /** the default logger */ - private static final Logger log = LoggerFactory.getLogger(LocatorFactoryImpl.class); - - private final String repositoryPrefix; - - public LocatorFactoryImpl(String repositoryPrefix) { - this.repositoryPrefix = repositoryPrefix; - } - - public DavResourceLocator createResourceLocator(String prefix, String href) { - // build prefix string and remove all prefixes from the given href. - StringBuffer b = new StringBuffer(""); - if (prefix != null && prefix.length() > 0) { - b.append(prefix); - if (href.startsWith(prefix)) { - href = href.substring(prefix.length()); - } - } - if (repositoryPrefix != null && repositoryPrefix.length() > 0 && !prefix.endsWith(repositoryPrefix)) { - b.append(repositoryPrefix); - if (href.startsWith(repositoryPrefix)) { - href = href.substring(repositoryPrefix.length()); - } - } - - // special treatment for root item, that has no name but '/' path. - if (href == null || "".equals(href)) { - href = "/"; - } - return new Locator(b.toString(), Text.unescape(href), this); - } - - public DavResourceLocator createResourceLocator(String prefix, String workspacePath, String resourcePath) { - return createResourceLocator(prefix, workspacePath, resourcePath, true); - } - - public DavResourceLocator createResourceLocator(String prefix, String workspacePath, String path, boolean isResourcePath) { - return new Locator(prefix, path, this); - } - - //-------------------------------------------------------------------------- - private static class Locator implements DavResourceLocator { - - private final String prefix; - private final String resourcePath; - private final DavLocatorFactory factory; - private final String href; - - private Locator(String prefix, String resourcePath, DavLocatorFactory factory) { - this.prefix = prefix; - this.factory = factory; - // remove trailing '/' that is not part of the resourcePath except for the root item. - if (resourcePath.endsWith("/") && !"/".equals(resourcePath)) { - resourcePath = resourcePath.substring(0, resourcePath.length()-1); - } - this.resourcePath = resourcePath; - href = prefix + Text.escapePath(resourcePath); - } - - public String getPrefix() { - return prefix; - } - - public String getResourcePath() { - return resourcePath; - } - - public String getWorkspacePath() { - return ""; - } - - public String getWorkspaceName() { - return ""; - } - - public boolean isSameWorkspace(DavResourceLocator locator) { - return isSameWorkspace(locator.getWorkspaceName()); - } - - public boolean isSameWorkspace(String workspaceName) { - return getWorkspaceName().equals(workspaceName); - } - - public String getHref(boolean isCollection) { - // avoid doubled trailing '/' for the root item - String suffix = (isCollection && !isRootLocation()) ? "/" : ""; - return href + suffix; - } - - public boolean isRootLocation() { - return "/".equals(resourcePath); - } - - public DavLocatorFactory getFactory() { - return factory; - } - - /** - * Returns the same as {@link #getResourcePath()}. No encoding is performed - * at all. - * @see DavResourceLocator#getRepositoryPath() - */ - public String getRepositoryPath() { - return getResourcePath(); - } - - /** - * Computes the hash code from the href, which is built using the final - * fields prefix and resourcePath. - * - * @return the hash code - */ - @Override - public int hashCode() { - return href.hashCode(); - } - - /** - * Equality of path is achieved if the specified object is a DavResourceLocator - * object with the same hash code. - * - * @param obj the object to compare to - * @return true if the 2 objects are equal; - * false otherwise - */ - @Override - public boolean equals(Object obj) { - if (obj instanceof DavResourceLocator) { - DavResourceLocator other = (DavResourceLocator) obj; - return hashCode() == other.hashCode(); - } - return false; - } - } -} Property changes on: jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/simple/LocatorFactoryImpl.java ___________________________________________________________________ Deleted: svn Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/simple/LocatorFactoryImplEx.java =================================================================== --- jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/simple/LocatorFactoryImplEx.java (revision 1907912) +++ jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/simple/LocatorFactoryImplEx.java (nonexistent) @@ -1,77 +0,0 @@ -/* - * 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.webdav.simple; - -import org.apache.jackrabbit.webdav.AbstractLocatorFactory; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * LocatorFactoryImplEx... - */ -public class LocatorFactoryImplEx extends AbstractLocatorFactory { - - private static Logger log = LoggerFactory.getLogger(LocatorFactoryImplEx.class); - - /** - * Create a new factory - * - * @param pathPrefix Prefix, that needs to be removed in order to retrieve - * the path of the repository item from a given DavResourceLocator. - */ - public LocatorFactoryImplEx(String pathPrefix) { - super(pathPrefix); - } - - /** - * - * @see AbstractLocatorFactory#getRepositoryPath(String, String) - */ - @Override - protected String getRepositoryPath(String resourcePath, String wspPath) { - if (resourcePath == null) { - return resourcePath; - } - - if (resourcePath.equals(wspPath) || startsWithWorkspace(resourcePath, wspPath)) { - String repositoryPath = resourcePath.substring(wspPath.length()); - return (repositoryPath.length() == 0) ? "/" : repositoryPath; - } else { - throw new IllegalArgumentException("Unexpected format of resource path: " + resourcePath + " (workspace: " + wspPath + ")"); - } - } - - /** - * - * @see AbstractLocatorFactory#getResourcePath(String, String) - */ - @Override - protected String getResourcePath(String repositoryPath, String wspPath) { - if (repositoryPath == null) { - throw new IllegalArgumentException("Cannot build resource path from 'null' repository path"); - } - return wspPath + repositoryPath; - } - - private boolean startsWithWorkspace(String repositoryPath, String wspPath) { - if (wspPath == null) { - return true; - } else { - return repositoryPath.startsWith(wspPath + "/"); - } - } -} Property changes on: jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/simple/LocatorFactoryImplEx.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Deleted: svn:keywords ## -1 +0,0 ## -author date id revision url \ No newline at end of property Index: jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/simple/ResourceConfig.java =================================================================== --- jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/simple/ResourceConfig.java (revision 1907912) +++ jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/simple/ResourceConfig.java (nonexistent) @@ -1,543 +0,0 @@ -/* - * 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.webdav.simple; - -import java.io.IOException; -import java.io.InputStream; -import java.lang.reflect.Method; -import java.lang.reflect.Modifier; -import java.net.URL; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import javax.jcr.Item; -import javax.jcr.Node; -import javax.jcr.RepositoryException; -import javax.xml.parsers.ParserConfigurationException; - -import org.apache.jackrabbit.server.io.CopyMoveHandler; -import org.apache.jackrabbit.server.io.CopyMoveManager; -import org.apache.jackrabbit.server.io.CopyMoveManagerImpl; -import org.apache.jackrabbit.server.io.DefaultIOManager; -import org.apache.jackrabbit.server.io.DeleteManager; -import org.apache.jackrabbit.server.io.DeleteManagerImpl; -import org.apache.jackrabbit.server.io.IOHandler; -import org.apache.jackrabbit.server.io.IOManager; -import org.apache.jackrabbit.server.io.PropertyHandler; -import org.apache.jackrabbit.server.io.PropertyManager; -import org.apache.jackrabbit.server.io.PropertyManagerImpl; -import org.apache.jackrabbit.webdav.xml.DomUtil; -import org.apache.jackrabbit.webdav.xml.ElementIterator; -import org.apache.jackrabbit.webdav.xml.Namespace; -import org.apache.tika.detect.Detector; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.w3c.dom.Element; -import org.xml.sax.SAXException; - -/** - * ResourceConfig... - */ -public class ResourceConfig { - - private static Logger log = LoggerFactory.getLogger(ResourceConfig.class); - - private static final String ELEMENT_IOMANAGER = "iomanager"; - private static final String ELEMENT_IOHANDLER = "iohandler"; - - private static final String ELEMENT_PROPERTYMANAGER = "propertymanager"; - private static final String ELEMENT_PROPERTYHANDLER = "propertyhandler"; - - private static final String ELEMENT_COPYMOVEMANAGER = "copymovemanager"; - private static final String ELEMENT_COPYMOVEHANDLER = "copymovehandler"; - - private static final String ELEMENT_CLASS = "class"; - - private static final String ELEMENT_PARAM = "param"; - private static final String ATTR_NAME = "name"; - private static final String ATTR_VALUE = "value"; - - /** - * Content type detector. - */ - private final Detector detector; - - private ItemFilter itemFilter; - private IOManager ioManager; - private CopyMoveManager cmManager; - private PropertyManager propManager; - private DeleteManager deleteManager; - private String[] nodetypeNames = new String[0]; - private boolean collectionNames = false; - - public ResourceConfig(Detector detector) { - this.detector = detector; - } - - /** - * Tries to parse the given xml configuration file. - * The xml must match the following structure:
- *
-     * <!ELEMENT config (iomanager, propertymanager, (collection | noncollection)?, filter?, mimetypeproperties?) >
-     * <!ELEMENT iomanager (class, iohandler*) >
-     * <!ELEMENT iohandler (class) >
-     * <!ELEMENT propertymanager (class, propertyhandler*) >
-     * <!ELEMENT propertyhandler (class) >
-     * <!ELEMENT collection (nodetypes) >
-     * <!ELEMENT noncollection (nodetypes) >
-     * <!ELEMENT filter (class, namespaces?, nodetypes?) >
-     * <!ELEMENT class >
-     *    <!ATTLIST class
-     *      name  CDATA #REQUIRED
-     *    >
-     * <!ELEMENT namespaces (prefix|uri)* >
-     * <!ELEMENT prefix (CDATA) >
-     * <!ELEMENT uri (CDATA) >
-     * <!ELEMENT nodetypes (nodetype)* >
-     * <!ELEMENT nodetype (CDATA) >
-     * <!ELEMENT mimetypeproperties (mimemapping*, defaultmimetype) >
-     * <!ELEMENT mimemapping >
-     *    <!ATTLIST mimemapping
-     *      extension  CDATA #REQUIRED
-     *      mimetype  CDATA #REQUIRED
-     *    >
-     * <!ELEMENT defaultmimetype (CDATA) >
-     * 
- *

- * The <mimetypeproperties/> settings have been deprecated and will - * be ignored with a warning. Instead you can use the - * {@link SimpleWebdavServlet#INIT_PARAM_MIME_INFO mime-info} - * servlet initialization parameter to customize the media type settings. - * - * @param configURL - */ - public void parse(URL configURL) { - try { - parse(configURL.openStream()); - } catch (IOException e) { - log.debug("Invalid resource configuration: " + e.getMessage()); - } - } - - /** - * Parses the given input stream into the xml configuration file. - * The xml must match the following structure:
- *

-     * <!ELEMENT config (iomanager, propertymanager, (collection | noncollection)?, filter?, mimetypeproperties?) >
-     * <!ELEMENT iomanager (class, iohandler*) >
-     * <!ELEMENT iohandler (class) >
-     * <!ELEMENT propertymanager (class, propertyhandler*) >
-     * <!ELEMENT propertyhandler (class) >
-     * <!ELEMENT collection (nodetypes) >
-     * <!ELEMENT noncollection (nodetypes) >
-     * <!ELEMENT filter (class, namespaces?, nodetypes?) >
-     * <!ELEMENT class >
-     *    <!ATTLIST class
-     *      name  CDATA #REQUIRED
-     *    >
-     * <!ELEMENT namespaces (prefix|uri)* >
-     * <!ELEMENT prefix (CDATA) >
-     * <!ELEMENT uri (CDATA) >
-     * <!ELEMENT nodetypes (nodetype)* >
-     * <!ELEMENT nodetype (CDATA) >
-     * <!ELEMENT mimetypeproperties (mimemapping*, defaultmimetype) >
-     * <!ELEMENT mimemapping >
-     *    <!ATTLIST mimemapping
-     *      extension  CDATA #REQUIRED
-     *      mimetype  CDATA #REQUIRED
-     *    >
-     * <!ELEMENT defaultmimetype (CDATA) >
-     * 
- *

- * The <mimetypeproperties/> settings have been deprecated and will - * be ignored with a warning. Instead you can use the - * {@link SimpleWebdavServlet#INIT_PARAM_MIME_INFO mime-info} - * servlet initialization parameter to customize the media type settings. - * - * @param stream - */ - public void parse(InputStream stream) { - try { - Element config = DomUtil.parseDocument(stream).getDocumentElement(); - if (config == null) { - log.warn("Mandatory 'config' element is missing."); - return; - } - - // iomanager config entry - Element el = DomUtil.getChildElement(config, ELEMENT_IOMANAGER, null); - if (el != null) { - Object inst = buildClassFromConfig(el); - if (inst != null && inst instanceof IOManager) { - ioManager = (IOManager)inst; - ioManager.setDetector(detector); - // get optional 'iohandler' child elements and populate the - // ioManager with the instances - ElementIterator iohElements = DomUtil.getChildren(el, ELEMENT_IOHANDLER, null); - while (iohElements.hasNext()) { - Element iohEl = iohElements.nextElement(); - inst = buildClassFromConfig(iohEl); - if (inst != null && inst instanceof IOHandler) { - IOHandler handler = (IOHandler) inst; - setParameters(handler, iohEl); - ioManager.addIOHandler(handler); - } else { - log.warn("Not a valid IOHandler : " + getClassName(iohEl)); - } - } - } else { - log.warn("'iomanager' element does not define a valid IOManager."); - } - } else { - log.warn("'iomanager' element is missing."); - } - - // propertymanager config entry - el = DomUtil.getChildElement(config, ELEMENT_PROPERTYMANAGER, null); - if (el != null) { - Object inst = buildClassFromConfig(el); - if (inst != null && inst instanceof PropertyManager) { - propManager = (PropertyManager)inst; - // get optional 'iohandler' child elements and populate the - // ioManager with the instances - ElementIterator iohElements = DomUtil.getChildren(el, ELEMENT_PROPERTYHANDLER, null); - while (iohElements.hasNext()) { - Element iohEl = iohElements.nextElement(); - inst = buildClassFromConfig(iohEl); - if (inst != null && inst instanceof PropertyHandler) { - PropertyHandler handler = (PropertyHandler) inst; - setParameters(handler, iohEl); - propManager.addPropertyHandler(handler); - } else { - log.warn("Not a valid PropertyHandler : " + getClassName(iohEl)); - } - } - } else { - log.warn("'propertymanager' element does not define a valid PropertyManager."); - } - } else { - log.debug("'propertymanager' element is missing."); - } - - // copymovemanager config entry - el = DomUtil.getChildElement(config, ELEMENT_COPYMOVEMANAGER, null); - if (el != null) { - Object inst = buildClassFromConfig(el); - if (inst != null && inst instanceof CopyMoveManager) { - cmManager = (CopyMoveManager) inst; - // get optional 'copymovehandler' child elements and populate - // the copy move manager with the instances - ElementIterator iohElements = DomUtil.getChildren(el, ELEMENT_COPYMOVEHANDLER, null); - while (iohElements.hasNext()) { - Element iohEl = iohElements.nextElement(); - inst = buildClassFromConfig(iohEl); - if (inst != null && inst instanceof CopyMoveHandler) { - CopyMoveHandler handler = (CopyMoveHandler) inst; - setParameters(handler, iohEl); - cmManager.addCopyMoveHandler(handler); - } else { - log.warn("Not a valid CopyMoveHandler : " + getClassName(iohEl)); - } - } - } else { - log.warn("'copymovemanager' element does not define a valid CopyMoveManager."); - } - } else { - log.debug("'copymovemanager' element is missing."); - } - - // collection/non-collection config entry - el = DomUtil.getChildElement(config, "collection", null); - if (el != null) { - nodetypeNames = parseNodeTypesEntry(el); - collectionNames = true; - } else if ((el = DomUtil.getChildElement(config, "noncollection", null)) != null) { - nodetypeNames = parseNodeTypesEntry(el); - collectionNames = false; - } - // todo: should check if both 'noncollection' and 'collection' are present and write a warning - - // filter config entry - el = DomUtil.getChildElement(config, "filter", null); - if (el != null) { - Object inst = buildClassFromConfig(el); - if (inst != null && inst instanceof ItemFilter) { - itemFilter = (ItemFilter)inst; - } - if (itemFilter != null) { - itemFilter.setFilteredNodetypes(parseNodeTypesEntry(el)); - parseNamespacesEntry(el); - } - } else { - log.debug("No 'filter' element specified."); - } - - el = DomUtil.getChildElement(config, "mimetypeproperties", null); - if (el != null) { - log.warn("Ignoring deprecated mimetypeproperties settings"); - } - } catch (IOException e) { - log.debug("Invalid resource configuration: " + e.getMessage()); - } catch (ParserConfigurationException e) { - log.warn("Failed to parse resource configuration: " + e.getMessage()); - } catch (SAXException e) { - log.warn("Failed to parse resource configuration: " + e.getMessage()); - } - } - - private void parseNamespacesEntry(Element parent) { - Element namespaces = DomUtil.getChildElement(parent, "namespaces", null); - if (namespaces != null) { - List l = new ArrayList(); - // retrieve prefix child elements - ElementIterator it = DomUtil.getChildren(namespaces, "prefix", null); - while (it.hasNext()) { - Element e = it.nextElement(); - l.add(DomUtil.getText(e)); - } - String[] prefixes = l.toArray(new String[l.size()]); - l.clear(); - // retrieve uri child elements - it = DomUtil.getChildren(namespaces, "uri", null); - while (it.hasNext()) { - Element e = it.nextElement(); - l.add(DomUtil.getText(e)); - } - String[] uris = l.toArray(new String[l.size()]); - itemFilter.setFilteredPrefixes(prefixes); - itemFilter.setFilteredURIs(uris); - } - } - - private static String[] parseNodeTypesEntry(Element parent) { - String[] ntNames; - Element nodetypes = DomUtil.getChildElement(parent, "nodetypes", null); - if (nodetypes != null) { - List l = new ArrayList(); - ElementIterator it = DomUtil.getChildren(nodetypes, "nodetype", null); - while (it.hasNext()) { - Element e = it.nextElement(); - l.add(DomUtil.getText(e)); - } - ntNames = l.toArray(new String[l.size()]); - } else { - ntNames = new String[0]; - } - return ntNames; - } - - private static Object buildClassFromConfig(Element parent) { - Object instance = null; - Element classElem = DomUtil.getChildElement(parent, "class", null); - if (classElem != null) { - // contains a 'class' child node - try { - String className = DomUtil.getAttribute(classElem, "name", null); - if (className != null) { - Class c = Class.forName(className); - instance = c.newInstance(); - } else { - log.error("Invalid configuration: missing 'class' element"); - } - } catch (Exception e) { - log.error("Error while create class instance: " + e.getMessage()); - } - } - return instance; - } - - private static String getClassName(Element parent) { - String className = null; - Element classElem = DomUtil.getChildElement(parent, "class", null); - if (classElem != null) { - className = DomUtil.getAttribute(classElem, "name", null); - } - return (className == null) ? "" : className; - } - - /** - * Retrieve 'param' elements for the specified xmlElement and - * use the public setter methods of the given instance to set - * the corresponding instance fields. - * - * @param instance - * @param xmlElement - */ - private static void setParameters(Object instance, Element xmlElement) { - ElementIterator paramElems = DomUtil.getChildren(xmlElement, ELEMENT_PARAM, Namespace.EMPTY_NAMESPACE); - if (paramElems.hasNext()) { - Map setters = getSetters(instance.getClass()); - if (!setters.isEmpty()) { - while (paramElems.hasNext()) { - Element parameter = paramElems.next(); - String name = DomUtil.getAttribute(parameter, ATTR_NAME, null); - String value = DomUtil.getAttribute(parameter, ATTR_VALUE, null); - if (name == null || value == null) { - log.error("Parameter name or value missing -> ignore."); - continue; - } - Method setter = setters.get(name); - if (setter != null) { - Class type = setter.getParameterTypes()[0]; - try { - if (type.isAssignableFrom(String.class) - || type.isAssignableFrom(Object.class)) { - setter.invoke(instance, value); - } else if (type.isAssignableFrom(Boolean.TYPE) - || type.isAssignableFrom(Boolean.class)) { - setter.invoke(instance, Boolean.valueOf(value)); - } else if (type.isAssignableFrom(Integer.TYPE) - || type.isAssignableFrom(Integer.class)) { - setter.invoke(instance, Integer.valueOf(value)); - } else if (type.isAssignableFrom(Long.TYPE) - || type.isAssignableFrom(Long.class)) { - setter.invoke(instance, Long.valueOf(value)); - } else if (type.isAssignableFrom(Double.TYPE) - || type.isAssignableFrom(Double.class)) { - setter.invoke(instance, Double.valueOf(value)); - } else { - log.error("Cannot set configuration property " + name); - } - } catch (Exception e) { - log.error("Invalid format (" + value + ") for property " + name + " of class " + instance.getClass().getName(), e); - } - } - } - } - } - } - - private static Map getSetters(Class cl) { - Map methods = new HashMap(); - for (Method method : cl.getMethods()) { - String name = method.getName(); - if (name.startsWith("set") && name.length() > 3 - && Modifier.isPublic(method.getModifiers()) - && !Modifier.isStatic(method.getModifiers()) - && Void.TYPE.equals(method.getReturnType()) - && method.getParameterTypes().length == 1) { - methods.put(name.substring(3, 4).toLowerCase() + name.substring(4), method); - } - } - return methods; - } - - /** - * - * @return - */ - public IOManager getIOManager() { - if (ioManager == null) { - log.debug("Missing io-manager > building DefaultIOManager "); - ioManager = new DefaultIOManager(); - ioManager.setDetector(detector); - } - return ioManager; - } - - /** - * - * @return - */ - public PropertyManager getPropertyManager() { - if (propManager == null) { - log.debug("Missing property-manager > building default."); - propManager = PropertyManagerImpl.getDefaultManager(); - } - return propManager; - } - - /** - * - * @return - */ - public CopyMoveManager getCopyMoveManager() { - if (cmManager == null) { - log.debug("Missing copymove-manager > building default."); - cmManager = CopyMoveManagerImpl.getDefaultManager(); - } - return cmManager; - } - - /** - * Returns the delete manager. - * @return the delete manager - */ - public DeleteManager getDeleteManager() { - if (deleteManager == null) { - log.debug("Missing delete-manager > building default."); - deleteManager = DeleteManagerImpl.getDefaultManager(); - } - return deleteManager; - } - - /** - * Returns true, if the given item represents a {@link Node node} that is - * either any of the nodetypes specified to represent a collection or - * none of the nodetypes specified to represent a non-collection, respectively. - * If no valid configuration entry is present, this method returns true - * for node items. For items which are not a node, this method always - * returns false. - * - * @param item - * @return true if the given item is a node that represents a webdav - * collection, false otherwise. - */ - public boolean isCollectionResource(Item item) { - if (item.isNode()) { - boolean isCollection = true; - Node n = (Node)item; - try { - for (int i = 0; i < nodetypeNames.length && isCollection; i++) { - isCollection = collectionNames ? n.isNodeType(nodetypeNames[i]) : !n.isNodeType(nodetypeNames[i]); - } - } catch (RepositoryException e) { - log.warn(e.getMessage()); - } - return isCollection; - } else { - return false; - } - } - - /** - * Returns the item filter specified with the configuration or {@link DefaultItemFilter} - * if the configuration was missing the corresponding entry or the parser failed - * to build a ItemFilter instance from the configuration. - * - * @return item filter as defined by the config or {@link DefaultItemFilter} - */ - public ItemFilter getItemFilter() { - if (itemFilter == null) { - log.debug("Missing resource filter > building DefaultItemFilter "); - itemFilter = new DefaultItemFilter(); - } - return itemFilter; - } - - /** - * Returns the configured content type detector. - * - * @return content type detector - */ - public Detector getDetector() { - return detector; - } - -} Property changes on: jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/simple/ResourceConfig.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Deleted: svn:keywords ## -1 +0,0 ## -author date id revision \ No newline at end of property Index: jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/simple/ResourceFactoryImpl.java =================================================================== --- jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/simple/ResourceFactoryImpl.java (revision 1907912) +++ jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/simple/ResourceFactoryImpl.java (nonexistent) @@ -1,208 +0,0 @@ -/* - * 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.webdav.simple; - -import org.apache.jackrabbit.webdav.DavException; -import org.apache.jackrabbit.webdav.DavMethods; -import org.apache.jackrabbit.webdav.DavResource; -import org.apache.jackrabbit.webdav.DavResourceFactory; -import org.apache.jackrabbit.webdav.DavResourceLocator; -import org.apache.jackrabbit.webdav.DavServletRequest; -import org.apache.jackrabbit.webdav.DavServletResponse; -import org.apache.jackrabbit.webdav.DavSession; -import org.apache.jackrabbit.webdav.jcr.JcrDavSession; -import org.apache.jackrabbit.webdav.lock.LockManager; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import javax.jcr.Item; -import javax.jcr.Node; -import javax.jcr.PathNotFoundException; -import javax.jcr.RepositoryException; -import javax.jcr.Repository; -import javax.jcr.Session; -import javax.jcr.version.Version; -import javax.jcr.version.VersionHistory; - -/** - * ResourceFactoryImpl implements a simple DavResourceFactory - */ -public class ResourceFactoryImpl implements DavResourceFactory { - - private static Logger log =LoggerFactory.getLogger(ResourceFactoryImpl.class); - - private final LockManager lockMgr; - private final ResourceConfig resourceConfig; - - /** - * Create a new ResourceFactory that uses the given lock - * manager and resource filter. - * - * @param lockMgr - * @param resourceConfig - */ - public ResourceFactoryImpl(LockManager lockMgr, ResourceConfig resourceConfig) { - this.lockMgr = lockMgr; - this.resourceConfig = resourceConfig; - } - - /** - * Create a new DavResource from the given locator and - * request. - * - * @param locator - * @param request - * @param response - * @return DavResource - * @throws DavException - * @see DavResourceFactory#createResource(DavResourceLocator, - * DavServletRequest, DavServletResponse) - */ - public DavResource createResource(DavResourceLocator locator, DavServletRequest request, - DavServletResponse response) throws DavException { - try { - Node node = getNode(request.getDavSession(), locator); - DavResource resource; - if (node == null) { - log.debug("Creating resource for non-existing repository node."); - boolean isCollection = DavMethods.isCreateCollectionRequest(request); - resource = createNullResource(locator, request.getDavSession(), isCollection); - } else { - resource = createResource(node, locator, request.getDavSession()); - } - resource.addLockManager(lockMgr); - return resource; - } catch (RepositoryException e) { - throw new DavException(DavServletResponse.SC_INTERNAL_SERVER_ERROR, e); - } - } - - /** - * Create a new DavResource from the given locator and webdav - * session. - * - * @param locator - * @param session - * @return - * @throws DavException - * @see DavResourceFactory#createResource(DavResourceLocator, DavSession) - */ - public DavResource createResource(DavResourceLocator locator, DavSession session) throws DavException { - try { - Node node = getNode(session, locator); - DavResource resource = createResource(node, locator, session); - resource.addLockManager(lockMgr); - return resource; - } catch (RepositoryException e) { - throw new DavException(DavServletResponse.SC_INTERNAL_SERVER_ERROR, e); - } - } - - /** - * Returns the Node corresponding to the given locator or - * null if it does not exist or if the existing item represents - * a Property. - * - * @param sessionImpl - * @param locator - * @return - * @throws RepositoryException - */ - private Node getNode(DavSession sessionImpl, DavResourceLocator locator) - throws RepositoryException { - Node node = null; - try { - String repoPath = locator.getRepositoryPath(); - if (repoPath != null) { - Session session = ((JcrDavSession)sessionImpl).getRepositorySession(); - Item item = session.getItem(repoPath); - if (item instanceof Node) { - node = (Node)item; - } // else: item is a property -> return null - } - } catch (PathNotFoundException e) { - // item does not exist (yet). return null -> create null-resource - } - return node; - } - - /** - * Create a 'null resource' - * - * @param locator - * @param session - * @param isCollection - * @return - * @throws DavException - */ - private DavResource createNullResource(DavResourceLocator locator, - DavSession session, - boolean isCollection) throws DavException { - JcrDavSession.checkImplementation(session); - JcrDavSession sessionImpl = (JcrDavSession)session; - - DavResource resource; - if (versioningSupported(sessionImpl.getRepositorySession())) { - resource = new VersionControlledResourceImpl(locator, this, sessionImpl, resourceConfig, isCollection); - } else { - resource = new DavResourceImpl(locator, this, sessionImpl, resourceConfig, isCollection); - } - return resource; - } - - /** - * Tries to retrieve the repository item defined by the locator's resource - * path and build the corresponding WebDAV resource. If the repository - * supports the versioning option different resources are created for - * version, versionhistory and common nodes. - * - * @param node - * @param locator - * @param session - * @return - * @throws DavException - */ - private DavResource createResource(Node node, DavResourceLocator locator, - DavSession session) throws DavException { - JcrDavSession.checkImplementation(session); - JcrDavSession sessionImpl = (JcrDavSession)session; - - DavResource resource; - if (versioningSupported(sessionImpl.getRepositorySession())) { - // create special resources for Version and VersionHistory - if (node instanceof Version) { - resource = new VersionResourceImpl(locator, this, sessionImpl, resourceConfig, node); - } else if (node instanceof VersionHistory) { - resource = new VersionHistoryResourceImpl(locator, this, sessionImpl, resourceConfig, node); - } else { - resource = new VersionControlledResourceImpl(locator, this, sessionImpl, resourceConfig, node); - } - } else { - resource = new DavResourceImpl(locator, this, session, resourceConfig, node); - } - return resource; - } - - /** - * @param repoSession - * @return true if the JCR repository supports versioning. - */ - private static boolean versioningSupported(Session repoSession) { - String desc = repoSession.getRepository().getDescriptor(Repository.OPTION_VERSIONING_SUPPORTED); - return Boolean.valueOf(desc); - } -} Property changes on: jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/simple/ResourceFactoryImpl.java ___________________________________________________________________ Deleted: svn Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/simple/SimpleWebdavServlet.java =================================================================== --- jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/simple/SimpleWebdavServlet.java (revision 1907912) +++ jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/simple/SimpleWebdavServlet.java (nonexistent) @@ -1,411 +0,0 @@ -/* - * 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.webdav.simple; - -import org.apache.jackrabbit.server.BasicCredentialsProvider; -import org.apache.jackrabbit.server.CredentialsProvider; -import org.apache.jackrabbit.server.SessionProvider; -import org.apache.jackrabbit.server.SessionProviderImpl; -import org.apache.jackrabbit.webdav.DavLocatorFactory; -import org.apache.jackrabbit.webdav.DavResource; -import org.apache.jackrabbit.webdav.DavResourceFactory; -import org.apache.jackrabbit.webdav.DavSessionProvider; -import org.apache.jackrabbit.webdav.WebdavRequest; -import org.apache.jackrabbit.webdav.lock.LockManager; -import org.apache.jackrabbit.webdav.lock.SimpleLockManager; -import org.apache.jackrabbit.webdav.server.AbstractWebdavServlet; -import org.apache.jackrabbit.webdav.util.HttpDateTimeFormatter; -import org.apache.tika.detect.Detector; -import org.apache.tika.mime.MimeTypeException; -import org.apache.tika.mime.MimeTypesFactory; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import javax.jcr.Repository; -import javax.servlet.ServletContext; -import javax.servlet.ServletException; - -import java.io.IOException; -import java.net.MalformedURLException; -import java.net.URL; -import java.time.format.DateTimeParseException; - -/** - * WebdavServlet provides WebDAV support (level - * {@link org.apache.jackrabbit.webdav.DavCompliance#_1_ 1}, - * {@link org.apache.jackrabbit.webdav.DavCompliance#_2_ 2}, - * {@link org.apache.jackrabbit.webdav.DavCompliance#_3_ 3} and - * {@link org.apache.jackrabbit.webdav.DavCompliance#BIND bind} compliant) for - * repository resources. - *

- * Implementations of this abstract class must implement the - * {@link #getRepository()} method to access the repository. - */ -public abstract class SimpleWebdavServlet extends AbstractWebdavServlet { - - /** - * the default logger - */ - private static final Logger log = LoggerFactory.getLogger(SimpleWebdavServlet.class); - - /** - * init param name of the repository prefix - */ - public static final String INIT_PARAM_RESOURCE_PATH_PREFIX = "resource-path-prefix"; - - /** - * Name of the init parameter that specify a separate configuration used - * for filtering the resources displayed. - */ - public static final String INIT_PARAM_RESOURCE_CONFIG = "resource-config"; - - /** - * Name of the parameter that specifies the servlet resource path of - * a custom <mime-info/> configuration file. The default setting - * is to use the MIME media type database included in Apache Tika. - */ - public static final String INIT_PARAM_MIME_INFO = "mime-info"; - - /** - * Servlet context attribute used to store the path prefix instead of - * having a static field with this servlet. The latter causes problems - * when running multiple - */ - public static final String CTX_ATTR_RESOURCE_PATH_PREFIX = "jackrabbit.webdav.simple.resourcepath"; - - /** - * the resource path prefix - */ - private String resourcePathPrefix; - - /** - * Map used to remember any webdav lock created without being reflected - * in the underlying repository. - * This is needed because some clients rely on a successful locking - * mechanism in order to perform properly (e.g. mac OSX built-in dav client) - */ - private LockManager lockManager; - - /** - * the resource factory - */ - private DavResourceFactory resourceFactory; - - /** - * the locator factory - */ - private DavLocatorFactory locatorFactory; - - /** - * the webdav session provider - */ - private DavSessionProvider davSessionProvider; - - /** - * the repository session provider - */ - private SessionProvider sessionProvider; - - /** - * The config - */ - private ResourceConfig config; - - /** - * Init this servlet - * - * @throws ServletException - */ - @Override - public void init() throws ServletException { - super.init(); - - resourcePathPrefix = getInitParameter(INIT_PARAM_RESOURCE_PATH_PREFIX); - if (resourcePathPrefix == null) { - log.debug("Missing path prefix > setting to empty string."); - resourcePathPrefix = ""; - } else if (resourcePathPrefix.endsWith("/")) { - log.debug("Path prefix ends with '/' > removing trailing slash."); - resourcePathPrefix = resourcePathPrefix.substring(0, resourcePathPrefix.length() - 1); - } - getServletContext().setAttribute(CTX_ATTR_RESOURCE_PATH_PREFIX, resourcePathPrefix); - log.info(INIT_PARAM_RESOURCE_PATH_PREFIX + " = '" + resourcePathPrefix + "'"); - - config = new ResourceConfig(getDetector()); - String configParam = getInitParameter(INIT_PARAM_RESOURCE_CONFIG); - if (configParam != null) { - try { - config.parse(getServletContext().getResource(configParam)); - } catch (MalformedURLException e) { - log.debug("Unable to build resource filter provider", e); - } - } - } - - /** - * Reads and returns the configured <mime-info/> database. - * - * @see #INIT_PARAM_MIME_INFO - * @return MIME media type database - * @throws ServletException if the database is invalid or can not be read - */ - private Detector getDetector() throws ServletException { - URL url; - - String mimeInfo = getInitParameter(INIT_PARAM_MIME_INFO); - if (mimeInfo != null) { - try { - url = getServletContext().getResource(mimeInfo); - } catch (MalformedURLException e) { - throw new ServletException( - "Invalid " + INIT_PARAM_MIME_INFO - + " configuration setting: " + mimeInfo, e); - } - } else { - url = MimeTypesFactory.class.getResource("tika-mimetypes.xml"); - } - - try { - return MimeTypesFactory.create(url); - } catch (MimeTypeException e) { - throw new ServletException( - "Invalid MIME media type database: " + url, e); - } catch (IOException e) { - throw new ServletException( - "Unable to read MIME media type database: " + url, e); - } - } - - /** - * {@inheritDoc} - */ - @Override - protected boolean isPreconditionValid(WebdavRequest request, - DavResource resource) { - - long ifUnmodifiedSince = UNDEFINED_TIME; - try { - // will throw if multiple field lines present - String value = AbstractWebdavServlet.getSingletonField(request, "If-Unmodified-Since"); - if (value != null) { - ifUnmodifiedSince = HttpDateTimeFormatter.parse(value); - } - } catch (IllegalArgumentException | DateTimeParseException ex) { - log.debug("illegal value for if-unmodified-since ignored: " + ex.getMessage()); - } - - if (ifUnmodifiedSince > UNDEFINED_TIME && resource.exists()) { - if (resource.getModificationTime() / 1000 > ifUnmodifiedSince / 1000) { - return false; - } - } - - return !resource.exists() || request.matchesIfHeader(resource); - } - - /** - * Returns the configured path prefix - * - * @return resourcePathPrefix - * @see #INIT_PARAM_RESOURCE_PATH_PREFIX - */ - public String getPathPrefix() { - return resourcePathPrefix; - } - - /** - * Returns the configured path prefix - * - * @param ctx The servlet context. - * @return resourcePathPrefix - * @see #INIT_PARAM_RESOURCE_PATH_PREFIX - */ - public static String getPathPrefix(ServletContext ctx) { - return (String) ctx.getAttribute(CTX_ATTR_RESOURCE_PATH_PREFIX); - } - - /** - * Returns the DavLocatorFactory. If no locator factory has - * been set or created a new instance of {@link org.apache.jackrabbit.webdav.simple.LocatorFactoryImpl} is - * returned. - * - * @return the locator factory - * @see AbstractWebdavServlet#getLocatorFactory() - */ - @Override - public DavLocatorFactory getLocatorFactory() { - if (locatorFactory == null) { - locatorFactory = new LocatorFactoryImplEx(resourcePathPrefix); - } - return locatorFactory; - } - - /** - * Sets the DavLocatorFactory. - * - * @param locatorFactory The DavLocatorFactory to use. - * @see AbstractWebdavServlet#setLocatorFactory(DavLocatorFactory) - */ - @Override - public void setLocatorFactory(DavLocatorFactory locatorFactory) { - this.locatorFactory = locatorFactory; - } - - /** - * Returns the LockManager. If no lock manager has - * been set or created a new instance of {@link SimpleLockManager} is - * returned. - * - * @return the lock manager - */ - public LockManager getLockManager() { - if (lockManager == null) { - lockManager = new SimpleLockManager(); - } - return lockManager; - } - - /** - * Sets the LockManager. - * - * @param lockManager The LockManager to be used. - */ - public void setLockManager(LockManager lockManager) { - this.lockManager = lockManager; - } - - /** - * Returns the DavResourceFactory. If no request factory has - * been set or created a new instance of {@link ResourceFactoryImpl} is - * returned. - * - * @return the resource factory - * @see AbstractWebdavServlet#getResourceFactory() - */ - @Override - public DavResourceFactory getResourceFactory() { - if (resourceFactory == null) { - resourceFactory = new ResourceFactoryImpl(getLockManager(), getResourceConfig()); - } - return resourceFactory; - } - - /** - * Sets the DavResourceFactory. - * - * @param resourceFactory The DavResourceFactory to use. - * @see AbstractWebdavServlet#setResourceFactory(org.apache.jackrabbit.webdav.DavResourceFactory) - */ - @Override - public void setResourceFactory(DavResourceFactory resourceFactory) { - this.resourceFactory = resourceFactory; - } - - /** - * Returns the SessionProvider. If no session provider has been - * set or created a new instance of {@link SessionProviderImpl} that extracts - * credentials from the Authorization request header is - * returned. - * - * @return the session provider - */ - public synchronized SessionProvider getSessionProvider() { - if (sessionProvider == null) { - sessionProvider = new SessionProviderImpl(getCredentialsProvider()); - } - return sessionProvider; - } - - /** - * Factory method for creating the credentials provider to be used for - * accessing the credentials associated with a request. The default - * implementation returns a {@link BasicCredentialsProvider} instance, - * but subclasses can override this method to add support for other - * types of credentials. - * - * @return the credentials provider - * @since 1.3 - */ - protected CredentialsProvider getCredentialsProvider() { - return new BasicCredentialsProvider(getInitParameter(INIT_PARAM_MISSING_AUTH_MAPPING)); - } - - /** - * Sets the SessionProvider. - * - * @param sessionProvider The SessionProvider to use. - */ - public synchronized void setSessionProvider(SessionProvider sessionProvider) { - this.sessionProvider = sessionProvider; - } - - /** - * Returns the DavSessionProvider. If no session provider has - * been set or created a new instance of {@link DavSessionProviderImpl} - * is returned. - * - * @return the session provider - * @see AbstractWebdavServlet#getDavSessionProvider() - */ - @Override - public synchronized DavSessionProvider getDavSessionProvider() { - if (davSessionProvider == null) { - davSessionProvider = - new DavSessionProviderImpl(getRepository(), getSessionProvider()); - } - return davSessionProvider; - } - - /** - * Sets the DavSessionProvider. - * - * @param sessionProvider The DavSessionProvider to use. - * @see AbstractWebdavServlet#setDavSessionProvider(org.apache.jackrabbit.webdav.DavSessionProvider) - */ - @Override - public synchronized void setDavSessionProvider(DavSessionProvider sessionProvider) { - this.davSessionProvider = sessionProvider; - } - - /** - * Returns the resource configuration to be applied - * - * @return the resource configuration. - */ - public ResourceConfig getResourceConfig() { - return config; - } - - /** - * Set the resource configuration - * - * @param config The resource configuration. - */ - public void setResourceConfig(ResourceConfig config) { - this.config = config; - } - - /** - * Returns the Repository. If no repository has been set or - * created the repository initialized by RepositoryAccessServlet - * is returned. - * - * @return repository - */ - public abstract Repository getRepository(); - -} Property changes on: jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/simple/SimpleWebdavServlet.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/simple/VersionControlledResourceImpl.java =================================================================== --- jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/simple/VersionControlledResourceImpl.java (revision 1907912) +++ jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/simple/VersionControlledResourceImpl.java (nonexistent) @@ -1,379 +0,0 @@ -/* - * 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.webdav.simple; - -import javax.jcr.Item; -import javax.jcr.Node; -import javax.jcr.RepositoryException; -import javax.jcr.Value; -import javax.jcr.version.Version; -import javax.jcr.version.VersionHistory; - -import org.apache.jackrabbit.JcrConstants; -import org.apache.jackrabbit.webdav.DavException; -import org.apache.jackrabbit.webdav.DavResource; -import org.apache.jackrabbit.webdav.DavResourceFactory; -import org.apache.jackrabbit.webdav.DavResourceLocator; -import org.apache.jackrabbit.webdav.DavServletResponse; -import org.apache.jackrabbit.webdav.DavSession; -import org.apache.jackrabbit.webdav.MultiStatus; -import org.apache.jackrabbit.webdav.DavMethods; -import org.apache.jackrabbit.webdav.jcr.JcrDavException; -import org.apache.jackrabbit.webdav.property.DefaultDavProperty; -import org.apache.jackrabbit.webdav.property.HrefProperty; -import org.apache.jackrabbit.webdav.version.LabelInfo; -import org.apache.jackrabbit.webdav.version.MergeInfo; -import org.apache.jackrabbit.webdav.version.UpdateInfo; -import org.apache.jackrabbit.webdav.version.VersionControlledResource; -import org.apache.jackrabbit.webdav.version.VersionHistoryResource; -import org.apache.jackrabbit.webdav.version.VersionResource; -import org.apache.jackrabbit.webdav.version.VersionableResource; -import org.apache.jackrabbit.webdav.version.report.ReportType; -import org.apache.jackrabbit.webdav.version.report.SupportedReportSetProperty; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - - - -/** - * VersionControlledResourceImpl represents a JCR node item and - * covers all functionality related to versioning of {@link Node}s. - * - * @see Node - */ -public class VersionControlledResourceImpl extends DeltaVResourceImpl - implements VersionControlledResource { - - private static final Logger log = LoggerFactory.getLogger(VersionControlledResourceImpl.class); - - /** - * Create a new {@link org.apache.jackrabbit.webdav.DavResource}. - * - * @param locator - * @param factory - * @param session - * @param config - * @param item - * @throws DavException - */ - public VersionControlledResourceImpl(DavResourceLocator locator, DavResourceFactory factory, DavSession session, ResourceConfig config, Item item) throws DavException { - super(locator, factory, session, config, item); - initSupportedReports(); - } - - /** - * Create a new {@link org.apache.jackrabbit.webdav.DavResource}. - * - * @param locator - * @param factory - * @param session - * @param config - * @param isCollection - * @throws DavException - */ - public VersionControlledResourceImpl(DavResourceLocator locator, DavResourceFactory factory, DavSession session, ResourceConfig config, boolean isCollection) throws DavException { - super(locator, factory, session, config, isCollection); - initSupportedReports(); - } - - //--------------------------------------------------------< DavResource >--- - /** - * Return a comma separated string listing the supported method names. - * - * @return the supported method names. - * @see org.apache.jackrabbit.webdav.DavResource#getSupportedMethods() - */ - @Override - public String getSupportedMethods() { - StringBuffer sb = new StringBuffer(super.getSupportedMethods()); - // Versioning support - sb.append(", ").append(VersionableResource.METHODS); - if (isVersionControlled()) { - try { - if (getNode().isCheckedOut()) { - sb.append(", ").append(DavMethods.METHOD_CHECKIN); - } else { - sb.append(", ").append(DavMethods.METHOD_CHECKOUT); - sb.append(", ").append(DavMethods.METHOD_LABEL); - } - } catch (RepositoryException e) { - // should not occur. - log.error(e.getMessage()); - } - } - return sb.toString(); - } - - //------------------------------------------< VersionControlledResource >--- - /** - * Adds version control to this resource. If the resource is already under - * version control, this method has no effect. If this resource is a Collection - * resource this method fails with {@link DavServletResponse#SC_METHOD_NOT_ALLOWED}. - * - * @throws org.apache.jackrabbit.webdav.DavException if this resource does not - * exist yet, is a collection or if an error occurs while making the - * underlying node versionable. - * @see org.apache.jackrabbit.webdav.version.VersionableResource#addVersionControl() - */ - public void addVersionControl() throws DavException { - if (!exists()) { - throw new DavException(DavServletResponse.SC_NOT_FOUND); - } - if (isCollection()) { - // since the version-controlled-collection feature is not supported - // collections may not be put under dav version control even if - // the underlying node was / could be made jcr versionable. - throw new DavException(DavServletResponse.SC_METHOD_NOT_ALLOWED); - } - if (!isVersionControlled()) { - Node item = getNode(); - try { - item.addMixin(JcrConstants.MIX_VERSIONABLE); - item.save(); - } catch (RepositoryException e) { - throw new JcrDavException(e); - } - } // else: is already version controlled -> ignore - } - - /** - * Calls {@link javax.jcr.Node#checkin()} on the underlying repository node. - * - * @throws org.apache.jackrabbit.webdav.DavException - * @see org.apache.jackrabbit.webdav.version.VersionControlledResource#checkin() - */ - public String checkin() throws DavException { - if (!exists()) { - throw new DavException(DavServletResponse.SC_NOT_FOUND); - } - if (!isVersionControlled()) { - throw new DavException(DavServletResponse.SC_METHOD_NOT_ALLOWED); - } - try { - Version v = getNode().checkin(); - String versionHref = getLocatorFromNode(v).getHref(false); - return versionHref; - } catch (RepositoryException e) { - // UnsupportedRepositoryException should not occur - throw new JcrDavException(e); - } - } - - /** - * Calls {@link javax.jcr.Node#checkout()} on the underlying repository node. - * - * @throws org.apache.jackrabbit.webdav.DavException - * @see org.apache.jackrabbit.webdav.version.VersionControlledResource#checkout() - */ - public void checkout() throws DavException { - if (!exists()) { - throw new DavException(DavServletResponse.SC_NOT_FOUND); - } - if (!isVersionControlled()) { - throw new DavException(DavServletResponse.SC_METHOD_NOT_ALLOWED); - } - try { - getNode().checkout(); - } catch (RepositoryException e) { - // UnsupportedRepositoryException should not occur - throw new JcrDavException(e); - } - } - - - /** - * UNCHECKOUT cannot be implemented on top of JSR 170 repository. - * Therefore this methods always throws a DavException with error code - * {@link org.apache.jackrabbit.webdav.DavServletResponse#SC_NOT_IMPLEMENTED}. - * - * @throws org.apache.jackrabbit.webdav.DavException - * @see org.apache.jackrabbit.webdav.version.VersionControlledResource#uncheckout() - */ - public void uncheckout() throws DavException { - throw new DavException(DavServletResponse.SC_NOT_IMPLEMENTED); - } - - /** - * UPDATE feature is not (yet) supported. This method allows fails with - * {@link DavServletResponse#SC_NOT_IMPLEMENTED}. - * - * @param updateInfo - * @return - * @throws DavException - * @see VersionControlledResource#update(UpdateInfo) - */ - public MultiStatus update(UpdateInfo updateInfo) throws DavException { - throw new DavException(DavServletResponse.SC_NOT_IMPLEMENTED); - } - - /** - * MERGE feature is not (yet) supported. This method allows fails with - * {@link DavServletResponse#SC_NOT_IMPLEMENTED}. - * - * @param mergeInfo - * @return - * @throws DavException - * @see VersionControlledResource#merge(MergeInfo) - */ - public MultiStatus merge(MergeInfo mergeInfo) throws DavException { - throw new DavException(DavServletResponse.SC_NOT_IMPLEMENTED); - } - - /** - * Modify the labels present with the versions of this resource. - * - * @param labelInfo - * @throws DavException - * @see VersionControlledResource#label(LabelInfo) - * @see javax.jcr.version.VersionHistory#addVersionLabel(String, String, boolean) - * @see javax.jcr.version.VersionHistory#removeVersionLabel(String) - */ - public void label(LabelInfo labelInfo) throws DavException { - if (labelInfo == null) { - throw new DavException(DavServletResponse.SC_BAD_REQUEST, "Valid label request body required."); - } - if (!exists()) { - throw new DavException(DavServletResponse.SC_NOT_FOUND); - } - - try { - if (!isVersionControlled() || getNode().isCheckedOut()) { - throw new DavException(DavServletResponse.SC_PRECONDITION_FAILED, "A LABEL request may only be applied to a version-controlled, checked-in resource."); - } - DavResource[] resArr = this.getReferenceResources(CHECKED_IN); - if (resArr.length == 1 && resArr[0] instanceof VersionResource) { - ((VersionResource)resArr[0]).label(labelInfo); - } else { - throw new DavException(DavServletResponse.SC_INTERNAL_SERVER_ERROR, "DAV:checked-in property on '" + getHref() + "' did not point to a single VersionResource."); - } - } catch (RepositoryException e) { - throw new JcrDavException(e); - } - } - - /** - * Returns the {@link javax.jcr.version.VersionHistory} associated with the repository node. - * If the node is not versionable an exception is thrown. - * - * @return the {@link VersionHistoryResource} associated with this resource. - * @throws org.apache.jackrabbit.webdav.DavException - * @see org.apache.jackrabbit.webdav.version.VersionControlledResource#getVersionHistory() - * @see javax.jcr.Node#getVersionHistory() - */ - public VersionHistoryResource getVersionHistory() throws DavException { - if (!exists()) { - throw new DavException(DavServletResponse.SC_NOT_FOUND); - } - if (!isVersionControlled()) { - throw new DavException(DavServletResponse.SC_FORBIDDEN); - } - try { - VersionHistory vh = getNode().getVersionHistory(); - DavResourceLocator loc = getLocatorFromNode(vh); - DavResource vhr = createResourceFromLocator(loc); - if (vhr instanceof VersionHistoryResource) { - return (VersionHistoryResource)vhr; - } else { - // severe error since resource factory doesn't behave correctly. - throw new DavException(DavServletResponse.SC_INTERNAL_SERVER_ERROR); - } - } catch (RepositoryException e) { - throw new JcrDavException(e); - } - } - - //-------------------------------------------------------------------------- - /** - * Define the set of reports supported by this resource. - * - * @see SupportedReportSetProperty - * @see DeltaVResourceImpl#initSupportedReports() - */ - @Override - protected void initSupportedReports() { - super.initSupportedReports(); - if (exists()) { - supportedReports.addReportType(ReportType.LOCATE_BY_HISTORY); - if (isVersionControlled()) { - supportedReports.addReportType(ReportType.VERSION_TREE); - } - } - } - - /** - * Fill the property set for this resource. - * @see DavResourceImpl#initProperties() - */ - @Override - protected void initProperties() { - if (!propsInitialized) { - super.initProperties(); - if (isVersionControlled()) { - Node n = getNode(); - // properties defined by RFC 3253 for version-controlled resources - try { - // DAV:version-history (computed) - String vhHref = getLocatorFromNode(n.getVersionHistory()).getHref(true); - properties.add(new HrefProperty(VERSION_HISTORY, vhHref, true)); - - // DAV:auto-version property: there is no auto version, explicit CHECKOUT is required. - properties.add(new DefaultDavProperty(AUTO_VERSION, null, true)); - - // baseVersion -> used for DAV:checked-out or DAV:checked-in - String baseVHref = getLocatorFromNode(n.getBaseVersion()).getHref(false); - if (n.isCheckedOut()) { - // DAV:predecessors property - if (n.hasProperty(JcrConstants.JCR_PREDECESSORS)) { - Value[] pv = n.getProperty(JcrConstants.JCR_PREDECESSORS).getValues(); - Node[] predecessors = new Node[pv.length]; - for (int i = 0; i < pv.length; i++) { - predecessors[i] = n.getSession().getNodeByIdentifier(pv[i].getString()); - } - properties.add(getHrefProperty(VersionResource.PREDECESSOR_SET, predecessors, true, false)); - } - // DAV:checked-out property (protected) - properties.add(new HrefProperty(CHECKED_OUT, baseVHref, true)); - } else { - // DAV:checked-in property (protected) - properties.add(new HrefProperty(CHECKED_IN, baseVHref, true)); - } - } catch (RepositoryException e) { - log.error(e.getMessage()); - } - } - } - } - - /** - * @return true, if this resource is a non-collection resource and represents - * an existing repository node that has the mixin nodetype 'mix:versionable' set. - */ - private boolean isVersionControlled() { - boolean vc = false; - // since the version-controlled-collection feature is not supported - // all collection are excluded from version-control even if the - // underlying node was JCR versionable. - if (exists() && !isCollection()) { - Node item = getNode(); - try { - vc = item.isNodeType(JcrConstants.MIX_VERSIONABLE); - } catch (RepositoryException e) { - log.warn(e.getMessage()); - } - } - return vc; - } -} Property changes on: jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/simple/VersionControlledResourceImpl.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Deleted: svn:keywords ## -1 +0,0 ## -author date id revision url \ No newline at end of property Index: jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/simple/VersionHistoryResourceImpl.java =================================================================== --- jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/simple/VersionHistoryResourceImpl.java (revision 1907912) +++ jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/simple/VersionHistoryResourceImpl.java (nonexistent) @@ -1,235 +0,0 @@ -/* - * 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.webdav.simple; - -import org.apache.jackrabbit.util.Text; -import org.apache.jackrabbit.webdav.DavException; -import org.apache.jackrabbit.webdav.DavResource; -import org.apache.jackrabbit.webdav.DavResourceFactory; -import org.apache.jackrabbit.webdav.DavResourceLocator; -import org.apache.jackrabbit.webdav.DavServletResponse; -import org.apache.jackrabbit.webdav.DavSession; -import org.apache.jackrabbit.webdav.DavResourceIterator; -import org.apache.jackrabbit.webdav.DavResourceIteratorImpl; -import org.apache.jackrabbit.webdav.MultiStatusResponse; -import org.apache.jackrabbit.webdav.io.InputContext; -import org.apache.jackrabbit.webdav.jcr.JcrDavException; -import org.apache.jackrabbit.webdav.property.HrefProperty; -import org.apache.jackrabbit.webdav.property.ResourceType; -import org.apache.jackrabbit.webdav.property.DavProperty; -import org.apache.jackrabbit.webdav.property.DavPropertyName; -import org.apache.jackrabbit.webdav.property.PropEntry; -import org.apache.jackrabbit.webdav.version.VersionHistoryResource; -import org.apache.jackrabbit.webdav.version.VersionResource; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import javax.jcr.Item; -import javax.jcr.RepositoryException; -import javax.jcr.version.VersionHistory; -import javax.jcr.version.VersionIterator; -import javax.jcr.version.Version; - -import java.util.ArrayList; -import java.util.List; - -/** - * VersionHistoryResourceImpl represents a JCR version history. - * - * @see VersionHistory - */ -public class VersionHistoryResourceImpl extends DeltaVResourceImpl implements VersionHistoryResource { - - private static final Logger log = LoggerFactory.getLogger(VersionHistoryResourceImpl.class); - - public VersionHistoryResourceImpl(DavResourceLocator locator, DavResourceFactory factory, DavSession session, ResourceConfig config, Item item) throws DavException { - super(locator, factory, session, config, item); - if (getNode() == null || !(getNode() instanceof VersionHistory)) { - throw new IllegalArgumentException("VersionHistory item expected."); - } - } - - //--------------------------------------------------------< DavResource >--- - /** - * Show all versions of this history as members. - * - * @return - * @see DavResource#getMembers() - */ - @Override - public DavResourceIterator getMembers() { - ArrayList list = new ArrayList(); - if (exists() && isCollection()) { - try { - // only display versions as members of the vh. the jcr:versionLabels - // node is an internal structure. - VersionIterator it = ((VersionHistory) getNode()).getAllVersions(); - while (it.hasNext()) { - // omit item filter here. if the version history is visible - // its versions should be visible as well. - Version v = it.nextVersion(); - DavResourceLocator vhLocator = getLocator(); - DavResourceLocator resourceLocator = vhLocator.getFactory().createResourceLocator(vhLocator.getPrefix(), vhLocator.getWorkspacePath(), v.getPath(), false); - DavResource childRes = getFactory().createResource(resourceLocator, getSession()); - list.add(childRes); - } - } catch (RepositoryException e) { - // should not occur - log.error("Unexpected error",e); - } catch (DavException e) { - // should not occur - log.error("Unexpected error",e); - } - } - return new DavResourceIteratorImpl(list); - } - - /** - * The version storage is read-only -> fails with 403. - * - * @see DavResource#addMember(DavResource, InputContext) - */ - @Override - public void addMember(DavResource member, InputContext inputContext) throws DavException { - throw new DavException(DavServletResponse.SC_FORBIDDEN); - } - - /** - * Removing a version resource is achieved by calling removeVersion - * on the versionhistory item this version belongs to. - * - * @throws DavException if the version does not exist or if an error occurs - * while deleting. - * @see DavResource#removeMember(org.apache.jackrabbit.webdav.DavResource) - */ - @Override - public void removeMember(DavResource member) throws DavException { - if (exists()) { - VersionHistory versionHistory = (VersionHistory) getNode(); - try { - String itemPath = member.getLocator().getRepositoryPath(); - // Retrieve the last segment of the given path and removes the index if present. - if (itemPath == null) { - throw new IllegalArgumentException("Cannot retrieve name from a 'null' item path."); - } - String name = Text.getName(itemPath); - // remove index - if (name.endsWith("]")) { - name = name.substring(0, name.lastIndexOf('[')); - } - versionHistory.removeVersion(name); - } catch (RepositoryException e) { - throw new JcrDavException(e); - } - } else { - throw new DavException(DavServletResponse.SC_NOT_FOUND); - } - } - - /** - * Version storage is read-only -> fails with 403. - * - * @see DavResource#setProperty(DavProperty) - */ - @Override - public void setProperty(DavProperty property) throws DavException { - throw new DavException(DavServletResponse.SC_FORBIDDEN); - } - - /** - * Version storage is read-only -> fails with 403. - * - * @see DavResource#removeProperty(DavPropertyName) - */ - @Override - public void removeProperty(DavPropertyName propertyName) throws DavException { - throw new DavException(DavServletResponse.SC_FORBIDDEN); - } - - /** - * Version storage is read-only -> fails with 403. - * - * @see DavResource#alterProperties(List) - */ - @Override - public MultiStatusResponse alterProperties(List changeList) throws DavException { - throw new DavException(DavServletResponse.SC_FORBIDDEN); - } - - //---------------------------------------------< VersionHistoryResource >--- - /** - * Return an array of {@link org.apache.jackrabbit.webdav.version.VersionResource}s representing all versions - * present in the underlying JCR version history. - * - * @return array of {@link org.apache.jackrabbit.webdav.version.VersionResource}s representing all versions - * present in the underlying JCR version history. - * @throws org.apache.jackrabbit.webdav.DavException - * @see org.apache.jackrabbit.webdav.version.VersionHistoryResource#getVersions() - */ - public VersionResource[] getVersions() throws DavException { - try { - VersionIterator vIter = ((VersionHistory)getNode()).getAllVersions(); - ArrayList l = new ArrayList(); - while (vIter.hasNext()) { - DavResourceLocator versionLoc = getLocatorFromNode(vIter.nextVersion()); - DavResource vr = createResourceFromLocator(versionLoc); - if (vr instanceof VersionResource) { - l.add((VersionResource) vr); - } else { - // severe error since resource factory doesn't behave correctly. - throw new DavException(DavServletResponse.SC_INTERNAL_SERVER_ERROR); - } - } - return l.toArray(new VersionResource[l.size()]); - } catch (RepositoryException e) { - throw new JcrDavException(e); - } - } - - //-------------------------------------------------------------------------- - /** - * Fill the property set for this resource. - */ - @Override - protected void initProperties() { - if (!propsInitialized) { - super.initProperties(); - - // change resource type defined by default item collection - properties.add(new ResourceType(new int[] {ResourceType.COLLECTION, ResourceType.VERSION_HISTORY})); - - // required root-version property for version-history resource - try { - String rootVersionHref = getLocatorFromNode(((VersionHistory)getNode()).getRootVersion()).getHref(false); - properties.add(new HrefProperty(VersionHistoryResource.ROOT_VERSION, rootVersionHref, false)); - } catch (RepositoryException e) { - log.error(e.getMessage()); - } - - // required, protected version-set property for version-history resource - try { - VersionIterator vIter = ((VersionHistory)getNode()).getAllVersions(); - ArrayList l = new ArrayList(); - while (vIter.hasNext()) { - l.add(vIter.nextVersion()); - } - properties.add(getHrefProperty(VersionHistoryResource.VERSION_SET, l.toArray(new Version[l.size()]), true, false)); - } catch (RepositoryException e) { - log.error(e.getMessage()); - } - } - } -} Property changes on: jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/simple/VersionHistoryResourceImpl.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Deleted: svn:keywords ## -1 +0,0 ## -author date id revision url \ No newline at end of property Index: jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/simple/VersionResourceImpl.java =================================================================== --- jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/simple/VersionResourceImpl.java (revision 1907912) +++ jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/simple/VersionResourceImpl.java (nonexistent) @@ -1,287 +0,0 @@ -/* - * 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.webdav.simple; - -import org.apache.jackrabbit.JcrConstants; -import org.apache.jackrabbit.webdav.DavException; -import org.apache.jackrabbit.webdav.DavResource; -import org.apache.jackrabbit.webdav.DavResourceFactory; -import org.apache.jackrabbit.webdav.DavResourceLocator; -import org.apache.jackrabbit.webdav.DavServletResponse; -import org.apache.jackrabbit.webdav.DavSession; -import org.apache.jackrabbit.webdav.DavResourceIterator; -import org.apache.jackrabbit.webdav.DavResourceIteratorImpl; -import org.apache.jackrabbit.webdav.MultiStatusResponse; -import org.apache.jackrabbit.webdav.util.HttpDateFormat; -import org.apache.jackrabbit.webdav.io.InputContext; -import org.apache.jackrabbit.webdav.jcr.JcrDavException; -import org.apache.jackrabbit.webdav.property.DavPropertyName; -import org.apache.jackrabbit.webdav.property.DefaultDavProperty; -import org.apache.jackrabbit.webdav.property.HrefProperty; -import org.apache.jackrabbit.webdav.property.DavProperty; -import org.apache.jackrabbit.webdav.property.PropEntry; -import org.apache.jackrabbit.webdav.version.LabelInfo; -import org.apache.jackrabbit.webdav.version.LabelSetProperty; -import org.apache.jackrabbit.webdav.version.VersionHistoryResource; -import org.apache.jackrabbit.webdav.version.VersionResource; -import org.apache.jackrabbit.webdav.version.report.ReportType; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import javax.jcr.Item; -import javax.jcr.Node; -import javax.jcr.Property; -import javax.jcr.PropertyIterator; -import javax.jcr.RepositoryException; -import javax.jcr.version.Version; -import javax.jcr.version.VersionHistory; - -import java.util.ArrayList; -import java.util.List; - -/** - * VersionResourceImpl represents a JCR version. - * - * @see Version - */ -public class VersionResourceImpl extends DeltaVResourceImpl implements VersionResource { - - private static final Logger log = LoggerFactory.getLogger(VersionResourceImpl.class); - - /** - * Create a new {@link org.apache.jackrabbit.webdav.DavResource}. - * @param locator - * @param factory - * @param session - * @param config - * @param item - * @throws DavException - * - */ - public VersionResourceImpl(DavResourceLocator locator, DavResourceFactory factory, DavSession session, ResourceConfig config, Item item) throws DavException { - super(locator, factory, session, config, item); - if (getNode() == null || !(getNode() instanceof Version)) { - throw new IllegalArgumentException("Version item expected."); - } - } - - //--------------------------------------------------------< DavResource >--- - /** - * Since this implementation of VersionResource never is a - * version belonging to a version controlled collection, this method always - * returns false not respecting the configuration. - * - * @return always false - */ - @Override - public boolean isCollection() { - return false; - } - - /** - * @return An empty DavResourceIterator - */ - @Override - public DavResourceIterator getMembers() { - return DavResourceIteratorImpl.EMPTY; - } - - /** - * The version storage is read-only -> fails with 403. - * - * @see DavResource#addMember(DavResource, InputContext) - */ - @Override - public void addMember(DavResource member, InputContext inputContext) throws DavException { - throw new DavException(DavServletResponse.SC_FORBIDDEN); - } - - /** - * The version storage is read-only -> fails with 403. - * - * @see DavResource#removeMember(DavResource) - */ - @Override - public void removeMember(DavResource member) throws DavException { - throw new DavException(DavServletResponse.SC_FORBIDDEN); - } - - /** - * Version storage is read-only -> fails with 403. - * - * @see DavResource#setProperty(DavProperty) - */ - @Override - public void setProperty(DavProperty property) throws DavException { - throw new DavException(DavServletResponse.SC_FORBIDDEN); - } - - /** - * Version storage is read-only -> fails with 403. - * - * @see DavResource#removeProperty(DavPropertyName) - */ - @Override - public void removeProperty(DavPropertyName propertyName) throws DavException { - throw new DavException(DavServletResponse.SC_FORBIDDEN); - } - - /** - * Version storage is read-only -> fails with 403. - * - * @see DavResource#alterProperties(List) - */ - @Override - public MultiStatusResponse alterProperties(List changeList) throws DavException { - throw new DavException(DavServletResponse.SC_FORBIDDEN); - } - - //----------------------------------------------------< VersionResource >--- - /** - * Modify the labels defined for the underlying repository version. - * - * @param labelInfo - * @throws org.apache.jackrabbit.webdav.DavException - * @see VersionResource#label(org.apache.jackrabbit.webdav.version.LabelInfo) - * @see javax.jcr.version.VersionHistory#addVersionLabel(String, String, boolean) - * @see javax.jcr.version.VersionHistory#removeVersionLabel(String) - */ - public void label(LabelInfo labelInfo) throws DavException { - if (labelInfo == null) { - throw new DavException(DavServletResponse.SC_BAD_REQUEST, "Valid label request body required."); - } - if (!exists()) { - throw new DavException(DavServletResponse.SC_NOT_FOUND); - } - try { - VersionHistory vh = getVersionHistoryItem(); - if (labelInfo.getType() == LabelInfo.TYPE_REMOVE) { - vh.removeVersionLabel(labelInfo.getLabelName()); - } else if (labelInfo.getType() == LabelInfo.TYPE_ADD) { - // ADD: only add if not yet existing - vh.addVersionLabel(getNode().getName(), labelInfo.getLabelName(), false); - } else { - // SET: move label if already existing - vh.addVersionLabel(getNode().getName(), labelInfo.getLabelName(), true); - } - } catch (RepositoryException e) { - throw new JcrDavException(e); - } - } - - /** - * Returns the {@link VersionHistory} associated with the repository version. - * Note: in contrast to a versionable node, the version history of a version - * item is always represented by its nearest ancestor. - * - * @return the {@link org.apache.jackrabbit.webdav.version.VersionHistoryResource} associated with this resource. - * @throws org.apache.jackrabbit.webdav.DavException - * @see org.apache.jackrabbit.webdav.version.VersionResource#getVersionHistory() - * @see javax.jcr.Item#getParent() - */ - public VersionHistoryResource getVersionHistory() throws DavException { - if (!exists()) { - throw new DavException(DavServletResponse.SC_NOT_FOUND); - } - - try { - VersionHistory vh = getVersionHistoryItem(); - DavResourceLocator loc = getLocatorFromNode(vh); - DavResource vhr = createResourceFromLocator(loc); - if (vhr instanceof VersionHistoryResource) { - return (VersionHistoryResource)vhr; - } else { - // severe error since resource factory doesn't behave correctly. - throw new DavException(DavServletResponse.SC_INTERNAL_SERVER_ERROR); - } - } catch (RepositoryException e) { - throw new JcrDavException(e); - } - } - - /** - * Return versionhistory that contains this version item - * - * @return versionhistory that contains this version item - * @throws RepositoryException - * @see javax.jcr.version.Version#getContainingHistory() - */ - private VersionHistory getVersionHistoryItem() throws RepositoryException { - return ((Version)getNode()).getContainingHistory(); - } - - //-------------------------------------------------------------------------- - /** - * Define the set of reports supported by this resource. - * - * @see org.apache.jackrabbit.webdav.version.report.SupportedReportSetProperty - */ - @Override - protected void initSupportedReports() { - super.initSupportedReports(); - if (exists()) { - supportedReports.addReportType(ReportType.VERSION_TREE); - } - } - - /** - * Fill the property set for this resource. - */ - @Override - protected void initProperties() { - if (!propsInitialized) { - super.initProperties(); - Version v = (Version) getNode(); - try { - String creationDate = HttpDateFormat.creationDateFormat().format(v.getCreated().getTime()); - // replace dummy creation date from default collection - properties.add(new DefaultDavProperty(DavPropertyName.CREATIONDATE, creationDate)); - - // required, protected DAV:version-name property - properties.add(new DefaultDavProperty(VERSION_NAME, v.getName(), true)); - - // required, protected DAV:label-name-set property - String[] labels = getVersionHistoryItem().getVersionLabels(v); - properties.add(new LabelSetProperty(labels)); - - // required DAV:predecessor-set (protected) and DAV:successor-set (computed) properties - properties.add(getHrefProperty(VersionResource.PREDECESSOR_SET, v.getPredecessors(), true, false)); - properties.add(getHrefProperty(SUCCESSOR_SET, v.getSuccessors(), true, false)); - - // required DAV:version-history (computed) property - String vhHref = getLocatorFromNode(getVersionHistoryItem()).getHref(true); - properties.add(new HrefProperty(VersionResource.VERSION_HISTORY, vhHref, true)); - - // required DAV:checkout-set (computed) property - PropertyIterator it = v.getReferences(); - List nodeList = new ArrayList(); - while (it.hasNext()) { - Property p = it.nextProperty(); - if (JcrConstants.JCR_BASEVERSION.equals(p.getName())) { - Node n = p.getParent(); - if (n.isCheckedOut()) { - nodeList.add(n); - } - } - } - properties.add(getHrefProperty(CHECKOUT_SET, nodeList.toArray(new Node[nodeList.size()]), true, false)); - - } catch (RepositoryException e) { - log.error(e.getMessage()); - } - } - } -} Property changes on: jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/simple/VersionResourceImpl.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Deleted: svn:keywords ## -1 +0,0 ## -author date id revision url \ No newline at end of property Index: jackrabbit-jcr-server/src/main/javadoc/org/apache/jackrabbit/server/io/package.html =================================================================== --- jackrabbit-jcr-server/src/main/javadoc/org/apache/jackrabbit/server/io/package.html (revision 1907912) +++ jackrabbit-jcr-server/src/main/javadoc/org/apache/jackrabbit/server/io/package.html (nonexistent) @@ -1,21 +0,0 @@ - - -The jackrabbit webdav server uses the classes defined in this package in order -to perform import and export operations in order to respond to PUT, MKCOL, PROPPATCH -and PROPFIND, GET, HEAD requests, respectively. - Property changes on: jackrabbit-jcr-server/src/main/javadoc/org/apache/jackrabbit/server/io/package.html ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-jcr-server/src/main/javadoc/org/apache/jackrabbit/webdav/jcr/package.html =================================================================== --- jackrabbit-jcr-server/src/main/javadoc/org/apache/jackrabbit/webdav/jcr/package.html (revision 1907912) +++ jackrabbit-jcr-server/src/main/javadoc/org/apache/jackrabbit/webdav/jcr/package.html (nonexistent) @@ -1,19 +0,0 @@ - - -Contains JCR specific implementations. - Property changes on: jackrabbit-jcr-server/src/main/javadoc/org/apache/jackrabbit/webdav/jcr/package.html ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-jcr-server/src/main/javadoc/org/apache/jackrabbit/webdav/jcr/version/package.html =================================================================== --- jackrabbit-jcr-server/src/main/javadoc/org/apache/jackrabbit/webdav/jcr/version/package.html (revision 1907912) +++ jackrabbit-jcr-server/src/main/javadoc/org/apache/jackrabbit/webdav/jcr/version/package.html (nonexistent) @@ -1,25 +0,0 @@ - - -Contains JCR specific implementations for the following interfaces: -

    -
  • VersionableResource
  • -
  • VersionControlledResource
  • -
  • VersionResource
  • -
  • VersionHistoryResource
  • -
- Property changes on: jackrabbit-jcr-server/src/main/javadoc/org/apache/jackrabbit/webdav/jcr/version/package.html ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-jcr-server/src/main/javadoc/org/apache/jackrabbit/webdav/jcr/version/report/package.html =================================================================== --- jackrabbit-jcr-server/src/main/javadoc/org/apache/jackrabbit/webdav/jcr/version/report/package.html (revision 1907912) +++ jackrabbit-jcr-server/src/main/javadoc/org/apache/jackrabbit/webdav/jcr/version/report/package.html (nonexistent) @@ -1,19 +0,0 @@ - - -Contains JCR specific reports. - Property changes on: jackrabbit-jcr-server/src/main/javadoc/org/apache/jackrabbit/webdav/jcr/version/report/package.html ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-jcr-server/src/main/resources/OSGI-INF/l10n/metatype.properties =================================================================== --- jackrabbit-jcr-server/src/main/resources/OSGI-INF/l10n/metatype.properties (revision 1907912) +++ jackrabbit-jcr-server/src/main/resources/OSGI-INF/l10n/metatype.properties (nonexistent) @@ -1,58 +0,0 @@ -# -# 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. -# - - -# -# This file contains localization strings for configuration labels and -# descriptions as used in the metatype.xml descriptor generated by the -# the SCR plugin - -dav.name = Apache Jackrabbit DavEx Servlet -dav.description = The DavEx Servlet allows direct access to the \ - complete Repository. - -alias.name = Root Path -alias.description = The root path at which the DavEx Servlet is \ - accessible. The default value is "/server". - -missing-auth-mapping.name = Missing Credentials Handling -missing-auth-mapping.description = Defines how a missing authorization \ - header should be handled. If this property is missing, a 401 response \ - is generated. This is suiteable for clients (eg. webdav clients) for \ - which sending a proper authorization header is not possible if the \ - server never sent a 401. If this property is present with an empty \ - value, null-credentials are returned, thus forcing an null login \ - on the repository. If this propert is present with the value \ - 'guestcredentials' java.jcr.GuestCredentials are used to login to the \ - repository. If this property has a 'user:password' value, the \ - respective simple credentials are generated. - -authenticate-header.name = Realm> -authenticate-header.description = Defines the value of the \ - 'WWW-Authenticate' header. Default is 'Basic realm="Jackrabbit Webdav Server"'. - -csrf-protection.name = CSRF Protection -csrf-protection.description = Configuration of referrer based CSRF \ - protection. If config is not configured or empty string the default \ - behaviour is to allow only requests with an empty referrer header or a \ - referrer host equal to the server host. A comma separated list of \ - additional allowed referrer hosts which are valid in addition to default \ - behaviour (see above). The value "disabled" may be used to disable the \ - referrer checking altogether. The default is "disabled" assuming that \ - a site-wide CSRF protection filter is installed. Index: jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/server/BasicCredentialsProviderTest.java =================================================================== --- jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/server/BasicCredentialsProviderTest.java (revision 1907912) +++ jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/server/BasicCredentialsProviderTest.java (nonexistent) @@ -1,385 +0,0 @@ -/* - * 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 junit.framework.TestCase; - -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import javax.servlet.http.Cookie; -import javax.servlet.http.HttpSession; -import javax.servlet.http.HttpUpgradeHandler; -import javax.servlet.http.Part; -import javax.servlet.ServletInputStream; -import javax.servlet.ServletRequest; -import javax.servlet.ServletResponse; -import javax.servlet.AsyncContext; -import javax.servlet.DispatcherType; -import javax.servlet.RequestDispatcher; -import javax.servlet.ServletContext; -import javax.servlet.ServletException; -import javax.jcr.LoginException; -import javax.jcr.Credentials; -import javax.jcr.SimpleCredentials; -import javax.jcr.GuestCredentials; - -import java.util.Collection; -import java.util.Enumeration; -import java.util.Map; -import java.util.Locale; -import java.util.HashMap; -import java.security.Principal; -import java.io.UnsupportedEncodingException; -import java.io.IOException; -import java.io.BufferedReader; - -/** - * BasicCredentialsProviderTest... - */ -public class BasicCredentialsProviderTest extends TestCase { - - public void testMissingDefaultHeader() throws ServletException { - CredentialsProvider cb = new BasicCredentialsProvider(null); - try { - Credentials creds = cb.getCredentials(new RequestImpl(null)); - fail("LoginException expected"); - } catch (LoginException e) { - // ok - } - } - - public void testGuestCredentialsDefaultHeader() throws ServletException, LoginException { - CredentialsProvider cb = new BasicCredentialsProvider(BasicCredentialsProvider.GUEST_DEFAULT_HEADER_VALUE); - Credentials creds = cb.getCredentials(new RequestImpl(null)); - - assertTrue(creds instanceof GuestCredentials); - } - - public void testEmptyDefaultHeader() throws ServletException, LoginException { - CredentialsProvider cb = new BasicCredentialsProvider(BasicCredentialsProvider.EMPTY_DEFAULT_HEADER_VALUE); - Credentials creds = cb.getCredentials(new RequestImpl(null)); - - assertNull(creds); - } - - public void testDefaultPassword() throws ServletException, LoginException { - Map m = new HashMap(); - m.put("userId", new char[0]); - m.put("userId:", new char[0]); - m.put("userId:pw", "pw".toCharArray()); - - for (String uid : m.keySet()) { - char[] pw = m.get(uid); - - CredentialsProvider cb = new BasicCredentialsProvider(uid); - Credentials creds = cb.getCredentials(new RequestImpl(null)); - - assertNotNull(creds); - assertTrue(creds instanceof SimpleCredentials); - assertEquals("userId", ((SimpleCredentials) creds).getUserID()); - if (pw.length == 0) { - assertEquals(0, ((SimpleCredentials) creds).getPassword().length); - } else { - assertEquals(new String(pw), new String(((SimpleCredentials) creds).getPassword())); - } - } - } - - - - - private class RequestImpl implements HttpServletRequest { - - private final String authHeader; - - private RequestImpl(String authHeader) { - this.authHeader = authHeader; - } - - public String getAuthType() { - return null; - } - - public Cookie[] getCookies() { - return new Cookie[0]; - } - - public long getDateHeader(String name) { - return 0; - } - - public String getHeader(String name) { - return authHeader; - } - - public Enumeration getHeaders(String name) { - return null; - } - - public Enumeration getHeaderNames() { - return null; - } - - public int getIntHeader(String name) { - return 0; - } - - public String getMethod() { - return null; - } - - public String getPathInfo() { - return null; - } - - public String getPathTranslated() { - return null; - } - - public String getContextPath() { - return null; - } - - public String getQueryString() { - return null; - } - - public String getRemoteUser() { - return null; - } - - public boolean isUserInRole(String role) { - return false; - } - - public Principal getUserPrincipal() { - return null; - } - - public String getRequestedSessionId() { - return null; - } - - public String getRequestURI() { - return null; - } - - public StringBuffer getRequestURL() { - return null; - } - - public String getServletPath() { - return null; - } - - public HttpSession getSession(boolean create) { - return null; - } - - public HttpSession getSession() { - return null; - } - - public boolean isRequestedSessionIdValid() { - return false; - } - - public boolean isRequestedSessionIdFromCookie() { - return false; - } - - public boolean isRequestedSessionIdFromURL() { - return false; - } - - public boolean isRequestedSessionIdFromUrl() { - return false; - } - - public Object getAttribute(String name) { - return null; - } - - public Enumeration getAttributeNames() { - return null; - } - - public String getCharacterEncoding() { - return null; - } - - public void setCharacterEncoding(String s) throws UnsupportedEncodingException { - } - - public int getContentLength() { - return 0; - } - - public String getContentType() { - return null; - } - - public ServletInputStream getInputStream() throws IOException { - return null; - } - - public String getParameter(String name) { - return null; - } - - public Enumeration getParameterNames() { - return null; - } - - public String[] getParameterValues(String name) { - return new String[0]; - } - - public Map getParameterMap() { - return null; - } - - public String getProtocol() { - return null; - } - - public String getScheme() { - return null; - } - - public String getServerName() { - return null; - } - - public int getServerPort() { - return 0; - } - - public BufferedReader getReader() throws IOException { - return null; - } - - public String getRemoteAddr() { - return null; - } - - public String getRemoteHost() { - return null; - } - - public void setAttribute(String name, Object o) { - } - - public void removeAttribute(String name) { - } - - public Locale getLocale() { - return null; - } - - public Enumeration getLocales() { - return null; - } - - public boolean isSecure() { - return false; - } - - public RequestDispatcher getRequestDispatcher(String path) { - return null; - } - - public String getRealPath(String path) { - return null; - } - - public int getRemotePort() { - return 0; - } - - public String getLocalName() { - return null; - } - - public String getLocalAddr() { - return null; - } - - public int getLocalPort() { - return 0; - } - - public long getContentLengthLong() { - return 0; - } - - public ServletContext getServletContext() { - return null; - } - - public AsyncContext startAsync() throws IllegalStateException { - return null; - } - - public AsyncContext startAsync(ServletRequest servletRequest, ServletResponse servletResponse) - throws IllegalStateException { - return null; - } - - public boolean isAsyncStarted() { - return false; - } - - public boolean isAsyncSupported() { - return false; - } - - public AsyncContext getAsyncContext() { - return null; - } - - public DispatcherType getDispatcherType() { - return null; - } - - public String changeSessionId() { - return null; - } - - public boolean authenticate(HttpServletResponse response) throws IOException, ServletException { - return false; - } - - public void login(String username, String password) throws ServletException { - } - - public void logout() throws ServletException { - } - - public Collection getParts() throws IOException, ServletException { - return null; - } - - public Part getPart(String name) throws IOException, ServletException { - return null; - } - - public T upgrade(Class handlerClass) throws IOException, ServletException { - return null; - } - } -} Property changes on: jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/server/BasicCredentialsProviderTest.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Deleted: svn:keywords ## -1 +0,0 ## -author date id revision url \ No newline at end of property Index: jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/server/TestAll.java =================================================================== --- jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/server/TestAll.java (revision 1907912) +++ jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/server/TestAll.java (nonexistent) @@ -1,39 +0,0 @@ -/* - * 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 junit.framework.Test; -import junit.framework.TestCase; -import junit.framework.TestSuite; - -/** - * Test suite that includes all testcases for package org.apache.jackrabbit.server. - */ -public class TestAll extends TestCase { - - /** - * Returns a Test suite that executes all tests inside this - * package. - */ - public static Test suite() { - TestSuite suite = new TestSuite("org.apache.jackrabbit.server tests"); - - suite.addTestSuite(BasicCredentialsProviderTest.class); - - return suite; - } -} Property changes on: jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/server/TestAll.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Deleted: svn:keywords ## -1 +0,0 ## -author date id revision url \ No newline at end of property Index: jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/server/remoting/davex/BatchReadConfigTest.java =================================================================== --- jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/server/remoting/davex/BatchReadConfigTest.java (revision 1907912) +++ jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/server/remoting/davex/BatchReadConfigTest.java (nonexistent) @@ -1,86 +0,0 @@ -/* - * 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.remoting.davex; - -import junit.framework.TestCase; - -import java.util.Properties; - -/** - * BatchReadConfigTest... - */ -public class BatchReadConfigTest extends TestCase { - - public void testDefaultDepth() { - BatchReadConfig cnf = new BatchReadConfig(); - - assertEquals(BatchReadConfig.DEPTH_DEFAULT, cnf.getDefaultDepth()); - assertEquals(cnf.getDefaultDepth(), cnf.getDepth("nt:base")); - - cnf.setDefaultDepth(5); - assertEquals(5, cnf.getDefaultDepth()); - assertEquals(cnf.getDefaultDepth(), cnf.getDepth("nt:base")); - - cnf.setDefaultDepth(BatchReadConfig.DEPTH_INFINITE); - assertEquals(BatchReadConfig.DEPTH_INFINITE, cnf.getDefaultDepth()); - assertEquals(cnf.getDefaultDepth(), cnf.getDepth("nt:base")); - - try { - cnf.setDefaultDepth(-12); - fail("Invalid depth"); - } catch (IllegalArgumentException e) { - //ok - } - } - - public void testDepth() { - BatchReadConfig cnf = new BatchReadConfig(); - - cnf.setDepth("nt:file", 15); - assertEquals(15, cnf.getDepth("nt:file")); - assertEquals(cnf.getDefaultDepth(), cnf.getDepth("nt:base")); - - cnf.setDepth("nt:file", BatchReadConfig.DEPTH_INFINITE); - assertEquals(BatchReadConfig.DEPTH_INFINITE, cnf.getDepth("nt:file")); - assertEquals(cnf.getDefaultDepth(), cnf.getDepth("nt:base")); - - try { - cnf.setDepth("nt:file",-12); - fail("Invalid depth"); - } catch (IllegalArgumentException e) { - //ok - } - } - - public void testAdd() { - Properties props = new Properties(); - props.setProperty("nt:file", "15"); - props.setProperty("default", "-1"); - - BatchReadConfig cnf = new BatchReadConfig(); - cnf.add(props); - - assertEquals(15, cnf.getDepth("nt:file")); - assertEquals(BatchReadConfig.DEPTH_INFINITE, cnf.getDefaultDepth()); - assertEquals(cnf.getDefaultDepth(), cnf.getDepth("nt:base")); - - cnf.setDefaultDepth(BatchReadConfig.DEPTH_DEFAULT); - assertEquals(15, cnf.getDepth("nt:file")); - assertEquals(BatchReadConfig.DEPTH_DEFAULT, cnf.getDefaultDepth()); - assertEquals(cnf.getDefaultDepth(), cnf.getDepth("nt:base")); - } -} \ No newline at end of file Property changes on: jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/server/remoting/davex/BatchReadConfigTest.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Deleted: svn:keywords ## -1 +0,0 ## -author date id revision url \ No newline at end of property Index: jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/server/remoting/davex/DiffParserTest.java =================================================================== --- jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/server/remoting/davex/DiffParserTest.java (revision 1907912) +++ jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/server/remoting/davex/DiffParserTest.java (nonexistent) @@ -1,385 +0,0 @@ -/* - * 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.remoting.davex; - -import junit.framework.TestCase; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.List; - -/** DiffParserTest... */ -public class DiffParserTest extends TestCase { - - public void testSetProperty() throws IOException, DiffException { - ArrayList l = new ArrayList(); - l.add("\"simple string\""); - l.add("2345"); - l.add("true"); - l.add("false"); - l.add("234.3455"); - l.add("null"); - - for (final String value : l) { - String diff = "^/a/prop : " + value; - - DummyDiffHandler handler = new DummyDiffHandler() { - @Override - public void setProperty(String targetPath, String diffValue) { - assertEquals(targetPath, "/a/prop"); - assertEquals(value, diffValue); - } - }; - DiffParser parser = new DiffParser(handler); - parser.parse(diff); - } - } - - public void testSetPropertyMissing() throws IOException, - DiffException { - ArrayList l = new ArrayList(); - l.add(""); - l.add(null); - - for (String value : l) { - String diff = "^/a/prop : " + ((value == null) ? "" : value); - - DummyDiffHandler handler = new DummyDiffHandler() { - @Override - public void setProperty(String targetPath, String diffValue) { - assertEquals(targetPath, "/a/prop"); - assertTrue(diffValue == null || "".equals(diffValue)); - } - }; - DiffParser parser = new DiffParser(handler); - parser.parse(diff); - } - } - - public void testSetPropertyWithUnicodeChars() throws IOException, - DiffException { - final String value = "\"String value containing \u2355\u8723 unicode chars.\""; - String diff = "^/a/prop : " + value; - - DiffHandler handler = new DummyDiffHandler() { - @Override - public void setProperty(String targetPath, String diffValue) { - assertEquals(targetPath, "/a/prop"); - assertEquals(value, diffValue); - } - }; - - DiffParser parser = new DiffParser(handler); - parser.parse(diff); - } - - public void testSetPropertyWithTrailingLineSep() throws IOException, - DiffException { - final String value = "\"String value ending with \r\r\n\n\r\n.\""; - String diff = "^/a/prop : " + value; - - DiffHandler handler = new DummyDiffHandler() { - @Override - public void setProperty(String targetPath, String diffValue) { - assertEquals(targetPath, "/a/prop"); - assertEquals(value, diffValue); - } - }; - - DiffParser parser = new DiffParser(handler); - parser.parse(diff); - } - - public void testSetPropertyWithSpecialChar() throws IOException, DiffException { - final String value = "+abc \\r+ \\n-ab >c \r\\r\\n+"; - String diff = "^/a/prop : " + value; - - DiffHandler handler = new DummyDiffHandler() { - @Override - public void setProperty(String targetPath, String diffValue) { - assertEquals(targetPath, "/a/prop"); - assertEquals(value, diffValue); - } - }; - - DiffParser parser = new DiffParser(handler); - parser.parse(diff); - } - - public void testSetPropertyUnterminatedString() throws IOException, - DiffException { - final String value = "\"String value ending with \r\r\n\n\r\n."; - String diff = "^/a/prop : " + value; - - DiffHandler handler = new DummyDiffHandler() { - @Override - public void setProperty(String targetPath, String diffValue) { - assertEquals(targetPath, "/a/prop"); - assertEquals(value, diffValue); - } - }; - DiffParser parser = new DiffParser(handler); - parser.parse(diff); - } - - public void testSetPropertyWithUnescapedAction() throws IOException, - DiffException { - String diff = "^abc : \r+def : \n-ghi : \r\n^jkl : \n\r>mno : \n"; - - DiffHandler handler = new DummyDiffHandler() { - @Override - public void addNode(String targetPath, String diffValue) { - assertEquals("def", targetPath); - assertEquals("", diffValue); - } - @Override - public void setProperty(String targetPath, String diffValue) { - assertTrue("abc".equals(targetPath) || "jkl".equals(targetPath)); - assertEquals("", diffValue); - } - @Override - public void remove(String targetPath, String diffValue) { - assertEquals("ghi", targetPath); - assertEquals("", diffValue); - } - - @Override - public void move(String targetPath, String diffValue) { - assertEquals("mno", targetPath); - assertEquals("\n", diffValue); - } - }; - - DiffParser parser = new DiffParser(handler); - parser.parse(diff); - } - - public void testValidDiffs() throws IOException, DiffException { - List l = new ArrayList(); - // unquoted string value - l.add(new String[] {"+/a/b : 134", "/a/b","134"}); - l.add(new String[] {"+/a/b : 2.3", "/a/b","2.3"}); - l.add(new String[] {"+/a/b : true", "/a/b","true"}); - // quoted string value - l.add(new String[] {"+/a/b : \"true\"", "/a/b","\"true\""}); - l.add(new String[] {"+/a/b : \"string value containing \u3456 unicode char.\"", "/a/b","\"string value containing \u3456unicode char.\""}); - // value consisting of quotes - l.add(new String[] {"+/a/b : \"", "/a/b","\""}); - l.add(new String[] {"+/a/b : \"\"", "/a/b","\"\""}); - // value consisting of single - l.add(new String[] {"+/a/b : '", "/a/b","'"}); - l.add(new String[] {"+/a/b : ''''", "/a/b","''''"}); - // value consisting of space(s) only - l.add(new String[] {"+/a/b : ", "/a/b"," "}); - l.add(new String[] {"+/a/b : ", "/a/b"," "}); - // value consisting of line separators only - l.add(new String[] {"+/a/b : \n", "/a/b","\n"}); - l.add(new String[] {"+/a/b : \r", "/a/b","\r"}); - l.add(new String[] {"+/a/b : \r\n", "/a/b","\r\n"}); - l.add(new String[] {"+/a/b : \r\n\n\r", "/a/b","\r\n\n\r"}); - // path containing white space - l.add(new String[] {"+/a /b : 123", "/a /b","123"}); - l.add(new String[] {"+/a\r\t/b : 123", "/a\r\t/b","123"}); - // path having trailing white space - l.add(new String[] {"+/a/b : 123", "/a/b","123"}); - l.add(new String[] {"+/a/b\r : 123", "/a/b\r","123"}); - l.add(new String[] {"+/a/b\r\n\n\r\n: 123", "/a/b\r\n\n\r\n","123"}); - // path containing reserved characters - l.add(new String[] {"++abc+ : val", "+abc+","val"}); - l.add(new String[] {"++++++ : val", "+++++","val"}); - // value containing reserved characters - l.add(new String[] {"+/a/b : +", "/a/b","+"}); - l.add(new String[] {"+/a/b : +->+-", "/a/b","+->+-"}); - l.add(new String[] {"+/a/b : \"+->+-\"", "/a/b","\"+->+-\""}); - // other white space than ' ' used as key-value separator - l.add(new String[] {"+/a/b :\r123", "/a/b","123"}); - l.add(new String[] {"+/a/b\r: 123", "/a/b","123"}); - l.add(new String[] {"+/a/b\r:\r123", "/a/b","123"}); - l.add(new String[] {"+/a/b\r:\n123", "/a/b","123"}); - l.add(new String[] {"+/a/b\t:\r123", "/a/b","123"}); - l.add(new String[] {"+/a/b\t:\t123", "/a/b","123"}); - // path containing colon - l.add(new String[] {"+/a:b/c:d : 123", "/a:b/c:d","123"}); - // value starting with colon -> ok - l.add(new String[] {"+/a/b : : val", "/a/b",": val"}); - // missing value - l.add(new String[] {"+/a/b : ", "/a/b", ""}); - l.add(new String[] {"+/a/b :\n", "/a/b", ""}); - - for (final String[] strs : l) { - DiffHandler hndl = new DummyDiffHandler() { - @Override - public void setProperty(String targetPath, String diffValue) { - assertEquals(strs[1], targetPath); - assertEquals(strs[2], diffValue); - } - }; - DiffParser parser = new DiffParser(hndl); - parser.parse(strs[0]); - } - - List l2 = new ArrayList(); - // multiple commands - l2.add("+abc :\n\n+def : val"); - l2.add("+abc :\n\n+def : val\n"); - l2.add("+abc : \r+def : val"); - l2.add("+/a/b : val\r+abc : \r "); - l2.add("+/a/b : val\r+abc :\n\n "); - // missing value in the last action. - l2.add("+/a/b : \r+abc :\n"); - l2.add("+/a/b : \\r+abc : abc\r\r+abc :\r"); - l2.add("+abc :\n\n+def : val\r\r>abc : "); - - for (String diff : l2) { - final List li = new ArrayList(); - DiffHandler dh = new DummyDiffHandler() { - @Override - public void addNode(String targetPath, String diffValue) { - li.add(diffValue); - } - }; - - DiffParser parser = new DiffParser(dh); - parser.parse(diff); - assertEquals(2, li.size()); - } - } - - public void testSeparatorLines() throws IOException, DiffException { - String diff = "+abc :\n\n+val : val"; - DiffHandler dh = new DummyDiffHandler() { - @Override - public void addNode(String targetPath, String diffValue) { - if ("abc".equals(targetPath)) { - assertEquals("", diffValue); - } else { - assertEquals("val", diffValue); - } - } - }; - new DiffParser(dh).parse(diff); - - diff = "+abc :\n+val : val"; - dh = new DummyDiffHandler() { - @Override - public void addNode(String targetPath, String diffValue) { - assertEquals("+val : val", diffValue); - } - }; - new DiffParser(dh).parse(diff); - - // TODO: check again: currently all line separation chars before an diff-char are ignored unless they are escaped in way the handler understands (e.g. JSON does: \\r for \r). - diff = "+abc :\r\r\r+def : val"; - dh = new DummyDiffHandler() { - @Override - public void addNode(String targetPath, String diffValue) { - if ("abc".equals(targetPath)) { - assertEquals("", diffValue); - } else { - assertEquals("val", diffValue); - } - } - }; - new DiffParser(dh).parse(diff); - - diff = "+abc : val\r+def :\n\n "; - dh = new DummyDiffHandler() { - @Override - public void addNode(String targetPath, String diffValue) { - if ("abc".equals(targetPath)) { - assertEquals("val", diffValue); - } else { - assertEquals("\n ", diffValue); - } - } - }; - new DiffParser(dh).parse(diff); - } - - public void testUnicodeLineSep() throws IOException, DiffException { - String diff = "+abc : val" + new String(new byte[] {Character.LINE_SEPARATOR}, "utf-8") + "+abc : val"; - DiffHandler dh = new DummyDiffHandler() { - @Override - public void addNode(String targetPath, String diffValue) { - assertEquals("abc", targetPath); - assertEquals("val", diffValue); - } - }; - new DiffParser(dh).parse(diff); - } - - public void testInvalidDiff() throws IOException, DiffException { - List l = new ArrayList(); - l.add(""); - // path, separator and value missing - l.add("+"); - l.add("+/a/b : val\r+"); - // path starting with white space, separator and value missing - l.add("+\n"); - // separator and value missing - l.add("+/a/b"); - l.add("+/a/b : val\r+abc\n"); - l.add("+/a/b :"); - // invalid for separator and value are missing (all : and white space - // is interpreted as part of the path. - l.add("+/a/b:"); - l.add("+/a/b:val"); - l.add("+/a/b: val"); - l.add("+/a/b:\rval"); - l.add("+/a/b :: val"); - // diff starting with white space - l.add(" +/a/b: val"); - l.add("\r\r\r\r\r\r+/a/b: val"); - // key starting with white space - l.add("+\r/a/b : 123"); - l.add("+ /a/b : 123"); - // key starting with colon - l.add("+:/a/b : 123"); - - for (String diff : l) { - try { - DiffParser parser = new DiffParser(new DummyDiffHandler()); - parser.parse(diff); - fail(diff + " is not a valid diff string -> should throw DiffException."); - } catch (DiffException e) { - // ok - } - } - } - - private class DummyDiffHandler implements DiffHandler { - - public void addNode(String targetPath, String diffValue) - throws DiffException { - // does nothing - } - - public void setProperty(String targetPath, String diffValue) - throws DiffException { - // does nothing - } - - public void remove(String targetPath, String diffValue) - throws DiffException { - // does nothing - } - - public void move(String targetPath, String diffValue) throws DiffException { - // does nothing - } - } -} Property changes on: jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/server/remoting/davex/DiffParserTest.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Deleted: svn:keywords ## -1 +0,0 ## -author date id revision url \ No newline at end of property Index: jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/server/remoting/davex/JsonDiffHandlerImportTest.java =================================================================== --- jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/server/remoting/davex/JsonDiffHandlerImportTest.java (revision 1907912) +++ jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/server/remoting/davex/JsonDiffHandlerImportTest.java (nonexistent) @@ -1,176 +0,0 @@ -/* - * 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.remoting.davex; - -import java.util.ArrayList; -import java.util.List; -import javax.jcr.Node; -import javax.jcr.RepositoryException; -import javax.jcr.security.AccessControlEntry; -import javax.jcr.security.AccessControlList; -import javax.jcr.security.AccessControlManager; -import javax.jcr.security.AccessControlPolicy; -import javax.jcr.security.Privilege; - -import org.apache.jackrabbit.api.security.JackrabbitAccessControlEntry; -import org.apache.jackrabbit.api.security.JackrabbitAccessControlList; -import org.apache.jackrabbit.commons.jackrabbit.authorization.AccessControlUtils; -import org.apache.jackrabbit.core.security.principal.EveryonePrincipal; -import org.apache.jackrabbit.test.AbstractJCRTest; - -/** - * Tests for {@code JsonDiffHandler} that trigger the import mode. - */ -public class JsonDiffHandlerImportTest extends AbstractJCRTest { - - private static final String JSOP_POLICY_TREE = "+rep:policy : {" - + "\"jcr:primaryType\" : \"rep:ACL\"," - + "\"allow\" : {" + "\"jcr:primaryType\" : \"rep:GrantACE\"," - + "\"rep:principalName\" : \"everyone\"," - + "\"rep:privileges\" : [\"jcr:write\"]" + "}" + "}"; - - private static final List ADD_NODES = new ArrayList(); - static { - ADD_NODES.add( - "+node1 : {" - +"\"jcr:primaryType\" : \"nt:file\"," - + "\"jcr:mixinTypes\" : [\"rep:AccessControllable\"]," - +"\"jcr:uuid\" : \"0a0ca2e9-ab98-4433-a12b-d57283765207\"," - +"\"rep:policy\" : {" - +"\"jcr:primaryType\" : \"rep:ACL\"," - +"\"deny0\" : {" - +"\"jcr:primaryType\" : \"rep:DenyACE\"," - +"\"rep:principalName\" : \"everyone\"," - +"\"rep:privileges\" : [\"jcr:read\"]" - +"}"+"}"+"}"); - ADD_NODES.add( - "+node2 : {" - +"\"jcr:primaryType\" : \"nt:unstructured\"," - + "\"jcr:mixinTypes\" : [\"rep:AccessControllable\"]," - +"\"rep:policy\" : {" - +"\"jcr:primaryType\" : \"rep:ACL\"," - +"\"allow\" : {" - +"\"jcr:primaryType\" : \"rep:GrantACE\"," - +"\"rep:principalName\" : \"everyone\"," - +"\"rep:privileges\" : [\"jcr:read\"]" - +"}," - +"\"deny\" : {" - +"\"jcr:primaryType\" : \"rep:DenyACE\"," - +"\"rep:principalName\" : \"everyone\"," - +"\"rep:privileges\" : [\"jcr:write\"]" - +"}" - +"}"+"}"); - - } - - private AccessControlManager acMgr; - - @Override - protected void setUp() throws Exception { - super.setUp(); - acMgr = superuser.getAccessControlManager(); - } - - private static void assertPolicy(AccessControlManager acMgr, Node targetNode, int noACEs) throws RepositoryException { - AccessControlPolicy[] policies = acMgr.getPolicies(targetNode.getPath()); - assertEquals(policies.length, 1); - - AccessControlPolicy acl = policies[0]; - assertTrue(acl instanceof JackrabbitAccessControlList); - AccessControlEntry[] entries = ((JackrabbitAccessControlList) acl).getAccessControlEntries(); - assertEquals(noACEs, entries.length); - } - - /** - * Test two subsequent DIFF strings with policies, thus multiple addNode operations. - */ - public void testMultipleAddNodeOperations() throws Exception { - for(String jsonString : ADD_NODES) { - JsonDiffHandler h = new JsonDiffHandler(superuser, testRoot, null); - new DiffParser(h).parse(jsonString); - } - - assertPolicy(acMgr, testRootNode.getNode("node1"), 1); - assertPolicy(acMgr, testRootNode.getNode("node2"), 2); - } - - /** - * Test adding 'rep:policy' policy node as a child node of /testroot without - * intermediate node. - */ - public void testAllPolicyNode() throws Exception { - try { - testRootNode.addMixin("rep:AccessControllable"); - - JsonDiffHandler handler = new JsonDiffHandler(superuser, testRoot, null); - new DiffParser(handler).parse(JSOP_POLICY_TREE); - - assertTrue(testRootNode.hasNode("rep:policy")); - assertTrue(testRootNode.getNode("rep:policy").getDefinition().isProtected()); - - assertTrue(testRootNode.getNode("rep:policy").getPrimaryNodeType() - .getName().equals("rep:ACL")); - - assertPolicy(acMgr, testRootNode, 1); - - AccessControlEntry entry = ((AccessControlList) acMgr.getPolicies(testRoot)[0]).getAccessControlEntries()[0]; - assertEquals(EveryonePrincipal.NAME, entry.getPrincipal().getName()); - assertEquals(1, entry.getPrivileges().length); - assertEquals(acMgr.privilegeFromName(Privilege.JCR_WRITE), entry.getPrivileges()[0]); - - if (entry instanceof JackrabbitAccessControlEntry) { - assertTrue(((JackrabbitAccessControlEntry) entry).isAllow()); - } - - } finally { - superuser.refresh(false); - } - } - - /** - * Test adding 'rep:policy' policy node as a child node of /testroot without - * intermediate node. - */ - public void testUpdatePolicyNode() throws Exception { - try { - AccessControlUtils.addAccessControlEntry(superuser, testRoot, EveryonePrincipal.getInstance(), new String[] {Privilege.JCR_READ}, false); - - JsonDiffHandler handler = new JsonDiffHandler(superuser, testRoot, null); - new DiffParser(handler).parse(JSOP_POLICY_TREE); - - assertTrue(testRootNode.hasNode("rep:policy")); - assertTrue(testRootNode.getNode("rep:policy").getDefinition().isProtected()); - - assertTrue(testRootNode.getNode("rep:policy").getPrimaryNodeType() - .getName().equals("rep:ACL")); - - assertPolicy(acMgr, testRootNode, 1); - - AccessControlEntry entry = ((AccessControlList) acMgr.getPolicies(testRoot)[0]).getAccessControlEntries()[0]; - assertEquals(EveryonePrincipal.NAME, entry.getPrincipal().getName()); - assertEquals(1, entry.getPrivileges().length); - assertEquals(acMgr.privilegeFromName(Privilege.JCR_WRITE), entry.getPrivileges()[0]); - - if (entry instanceof JackrabbitAccessControlEntry) { - assertTrue(((JackrabbitAccessControlEntry) entry).isAllow()); - } - - } finally { - superuser.refresh(false); - } - } -} \ No newline at end of file Property changes on: jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/server/remoting/davex/JsonDiffHandlerImportTest.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/server/remoting/davex/JsonDiffHandlerTest.java =================================================================== --- jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/server/remoting/davex/JsonDiffHandlerTest.java (revision 1907912) +++ jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/server/remoting/davex/JsonDiffHandlerTest.java (nonexistent) @@ -1,267 +0,0 @@ -/* - * 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.remoting.davex; - -import junit.framework.TestCase; -import org.xml.sax.ContentHandler; - -import javax.jcr.Credentials; -import javax.jcr.Item; -import javax.jcr.Node; -import javax.jcr.Property; -import javax.jcr.Repository; -import javax.jcr.Session; -import javax.jcr.ValueFactory; -import javax.jcr.Workspace; -import javax.jcr.retention.RetentionManager; -import javax.jcr.security.AccessControlManager; -import java.io.InputStream; -import java.io.OutputStream; -import java.security.AccessControlException; -import java.util.HashMap; -import java.util.Map; - -/** - * JsonDiffHandlerTest... - */ -public class JsonDiffHandlerTest extends TestCase { - - public void testGetItemPath() throws Exception { - Map m = new HashMap(); - m.put("abc", "/reqPath/abc"); - m.put("abc/def/ghi", "/reqPath/abc/def/ghi"); - m.put("/abc", "/abc"); - m.put("/abc/def/ghi", "/abc/def/ghi"); - m.put(".", "/reqPath"); - m.put("./abc", "/reqPath/abc"); - m.put("abc/./def", "/reqPath/abc/def"); - m.put("/abc/./def", "/abc/def"); - m.put("..", "/"); - m.put("../abc/def", "/abc/def"); - m.put("abc/../def/.", "/reqPath/def"); - m.put("abc/../def/..", "/reqPath"); - m.put("abc/../def/..", "/reqPath"); - m.put("abc/../def/..", "/reqPath"); - m.put("abc/../def/..", "/reqPath"); - m.put("abc/../def/..", "/reqPath"); - m.put("abc/../def/..", "/reqPath"); - m.put("./././././", "/reqPath"); - m.put("/./././././", "/"); - m.put("/./abc/def/../ghi", "/abc/ghi"); - - JsonDiffHandler handler = new JsonDiffHandler(new DummySession(), "/reqPath", null); - for (String targetPath : m.keySet()) { - String expItemPath = m.get(targetPath); - assertEquals(expItemPath, handler.getItemPath(targetPath)); - } - } - - private final class DummySession implements Session { - - @Override - public Repository getRepository() { - return null; - } - - @Override - public String getUserID() { - return null; - } - - @Override - public Object getAttribute(String name) { - return null; - } - - @Override - public String[] getAttributeNames() { - return new String[0]; - } - - @Override - public Workspace getWorkspace() { - return null; - } - - @Override - public Session impersonate(Credentials credentials) { - return null; - } - - @Override - public Node getRootNode() { - return null; - } - - @Override - public Node getNodeByUUID(String uuid) { - return null; - } - - @Override - public Item getItem(String absPath) { - return null; - } - - @Override - public boolean itemExists(String absPath) { - return false; - } - - @Override - public void move(String srcAbsPath, String destAbsPath) { - } - - @Override - public void save() { - } - - @Override - public void refresh(boolean keepChanges) { - } - - @Override - public boolean hasPendingChanges() { - return false; - } - - @Override - public ValueFactory getValueFactory() { - return null; - } - - @Override - public void checkPermission(String absPath, String actions) throws AccessControlException { - } - - @Override - public ContentHandler getImportContentHandler(String parentAbsPath, int uuidBehavior) { - return null; - } - - @Override - public void importXML(String parentAbsPath, InputStream in, int uuidBehavior) { - } - - @Override - public void exportSystemView(String absPath, ContentHandler contentHandler, boolean skipBinary, boolean noRecurse) { - } - - @Override - public void exportSystemView(String absPath, OutputStream out, boolean skipBinary, boolean noRecurse) { - } - - @Override - public void exportDocumentView(String absPath, ContentHandler contentHandler, boolean skipBinary, boolean noRecurse) { - } - - @Override - public void exportDocumentView(String absPath, OutputStream out, boolean skipBinary, boolean noRecurse) { - } - - @Override - public void setNamespacePrefix(String prefix, String uri) { - } - - @Override - public String[] getNamespacePrefixes() { - return new String[0]; - } - - @Override - public String getNamespaceURI(String prefix) { - return null; - } - - @Override - public String getNamespacePrefix(String uri) { - return null; - } - - @Override - public void logout() { - } - - @Override - public boolean isLive() { - return false; - } - - @Override - public void addLockToken(String lt) { - } - - @Override - public String[] getLockTokens() { - return new String[0]; - } - - @Override - public void removeLockToken(String lt) { - } - - @Override - public AccessControlManager getAccessControlManager() { - return null; - } - - @Override - public Node getNode(String arg0) { - return null; - } - - @Override - public Node getNodeByIdentifier(String arg0) { - return null; - } - - @Override - public Property getProperty(String arg0) { - return null; - } - - @Override - public RetentionManager getRetentionManager() { - return null; - } - - @Override - public boolean hasCapability(String arg0, Object arg1, Object[] arg2) { - return false; - } - - @Override - public boolean hasPermission(String arg0, String arg1) { - return false; - } - - @Override - public boolean nodeExists(String arg0) { - return false; - } - - @Override - public boolean propertyExists(String arg0) { - return false; - } - - @Override - public void removeItem(String arg0) { - - } - } -} Property changes on: jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/server/remoting/davex/JsonDiffHandlerTest.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Deleted: svn:keywords ## -1 +0,0 ## -author date id revision url \ No newline at end of property Index: jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/server/remoting/davex/JsonWriterTest.java =================================================================== --- jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/server/remoting/davex/JsonWriterTest.java (revision 1907912) +++ jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/server/remoting/davex/JsonWriterTest.java (nonexistent) @@ -1,96 +0,0 @@ -/* - * 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.remoting.davex; - -import org.apache.jackrabbit.commons.iterator.NodeIteratorAdapter; -import org.apache.jackrabbit.commons.iterator.PropertyIteratorAdapter; -import org.easymock.EasyMockSupport; -import org.easymock.IAnswer; -import org.junit.Test; - -import javax.jcr.Node; -import javax.jcr.NodeIterator; -import javax.jcr.Property; -import javax.jcr.PropertyIterator; -import javax.jcr.PropertyType; -import javax.jcr.Value; -import java.io.StringWriter; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - -import static org.junit.Assert.*; -import static org.easymock.EasyMock.*; - -public class JsonWriterTest extends EasyMockSupport { - - @Test - public void testDoubleOutput() throws Exception { - StringWriter writer = new StringWriter(); - JsonWriter jsonWriter = new JsonWriter(writer); - - Node parent = createMock(Node.class); - Property doubleProperty = createMock(Property.class); - Value doublePropertyValue = createMock(Value.class); - expect(doubleProperty.getType()).andReturn(PropertyType.DOUBLE).anyTimes(); - expect(doubleProperty.getName()).andReturn("singleValued").anyTimes(); - expect(doubleProperty.isMultiple()).andReturn(false).anyTimes(); - expect(doubleProperty.getValue()).andReturn(doublePropertyValue).anyTimes(); - expect(doublePropertyValue.getType()).andReturn(PropertyType.DOUBLE).anyTimes(); - expect(doublePropertyValue.getDouble()).andReturn(5d).anyTimes(); - expect(doublePropertyValue.getString()).andReturn("5").anyTimes(); - - Property mvDoubleProperty = createMock(Property.class); - Value mvDoublePropertyValue1 = createMock(Value.class); - Value mvDoublePropertyValue2 = createMock(Value.class); - expect(mvDoubleProperty.getType()).andReturn(PropertyType.DOUBLE).anyTimes(); - expect(mvDoubleProperty.getName()).andReturn("multiValued").anyTimes(); - expect(mvDoubleProperty.isMultiple()).andReturn(true).anyTimes(); - expect(mvDoubleProperty.getValues()).andReturn(new Value[] { mvDoublePropertyValue1, mvDoublePropertyValue2}).anyTimes(); - expect(mvDoublePropertyValue1.getType()).andReturn(PropertyType.DOUBLE).anyTimes(); - expect(mvDoublePropertyValue1.getDouble()).andReturn(42d).anyTimes(); - expect(mvDoublePropertyValue1.getString()).andReturn("42").anyTimes(); - expect(mvDoublePropertyValue2.getType()).andReturn(PropertyType.DOUBLE).anyTimes(); - expect(mvDoublePropertyValue2.getDouble()).andReturn(98.6).anyTimes(); - expect(mvDoublePropertyValue2.getString()).andReturn("98.6").anyTimes(); - - final List properties = new ArrayList(); - properties.add(doubleProperty); - properties.add(mvDoubleProperty); - expect(parent.getProperties()).andAnswer(new IAnswer() { - @Override - public PropertyIterator answer() throws Throwable { - return new PropertyIteratorAdapter(properties.iterator()); - } - }); - expect(parent.getNodes()).andAnswer(new IAnswer() { - @Override - public NodeIterator answer() throws Throwable { - return new NodeIteratorAdapter(Collections.emptyIterator()); - } - }); - replayAll(); - - jsonWriter.write(parent, 1); - - assertEquals("{\":singleValued\":\"Double\",\"singleValued\":5,\":multiValued\":\"Double\",\"multiValued\":[42,98.6],\"::NodeIteratorSize\":0}", - writer.toString()); - - verifyAll(); - } - -} \ No newline at end of file Property changes on: jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/server/remoting/davex/JsonWriterTest.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Deleted: svn:executable ## -1 +0,0 ## -* \ No newline at end of property Index: jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/server/remoting/davex/TestAll.java =================================================================== --- jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/server/remoting/davex/TestAll.java (revision 1907912) +++ jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/server/remoting/davex/TestAll.java (nonexistent) @@ -1,42 +0,0 @@ -/* - * 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.remoting.davex; - -import junit.framework.Test; -import junit.framework.TestCase; -import junit.framework.TestSuite; - -/** - * Test suite that includes all testcases for package org.apache.jackrabbit.server.remoting.davex. - */ -public class TestAll extends TestCase { - - /** - * Returns a Test suite that executes all tests inside this - * package. - */ - public static Test suite() { - TestSuite suite = new TestSuite("org.apache.jackrabbit.server.remoting.davex tests"); - - suite.addTestSuite(DiffParserTest.class); - suite.addTestSuite(JsonDiffHandlerImportTest.class); - suite.addTestSuite(JsonDiffHandlerTest.class); - suite.addTestSuite(BatchReadConfigTest.class); - - return suite; - } -} Property changes on: jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/server/remoting/davex/TestAll.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Deleted: svn:keywords ## -1 +0,0 ## -author date id revision url \ No newline at end of property Index: jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/jcr/JcrDavExceptionTest.java =================================================================== --- jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/jcr/JcrDavExceptionTest.java (revision 1907912) +++ jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/jcr/JcrDavExceptionTest.java (nonexistent) @@ -1,54 +0,0 @@ -/* - * 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.webdav.jcr; - -import junit.framework.TestCase; - -import javax.jcr.lock.LockException; -import javax.jcr.RepositoryException; - -/** JcrDavExceptionTest... */ -public class JcrDavExceptionTest extends TestCase { - - public void testDerivedException() { - RepositoryException re = new DerievedRepositoryException(); - - // creating JcrDavException from the derived exception must not throw - // NPE (see issue https://issues.apache.org/jira/browse/JCR-1678) - JcrDavException jde = new JcrDavException(re); - - // error code must be the same as for LockException - assertEquals(new JcrDavException(new LockException()).getErrorCode(), - jde.getErrorCode()); - } - - public void testNullException() { - try { - new JcrDavException(null); - fail("Should throw NPE"); - } catch (NullPointerException e) { - // as documented in the javadoc - } - } - - /** - * Derived exception that does not extend from RepositoryException, which - * returns the 'default' error code. - */ - private static final class DerievedRepositoryException extends LockException { - } -} \ No newline at end of file Property changes on: jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/jcr/JcrDavExceptionTest.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Deleted: svn:keywords ## -1 +0,0 ## -author date id revision url \ No newline at end of property Index: jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/jcr/JcrValueTypeTest.java =================================================================== --- jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/jcr/JcrValueTypeTest.java (revision 1907912) +++ jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/jcr/JcrValueTypeTest.java (nonexistent) @@ -1,50 +0,0 @@ -/* - * 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.webdav.jcr; - -import junit.framework.TestCase; - -import javax.jcr.PropertyType; - -import org.apache.jackrabbit.commons.webdav.JcrValueType; - -/** - * JcrValueTypeTest... - */ -public class JcrValueTypeTest extends TestCase { - - public void testTypeFromContentType() { - for (int i = PropertyType.UNDEFINED; i <= PropertyType.DECIMAL; i++) { - String ct = JcrValueType.contentTypeFromType(i); - assertEquals(i, JcrValueType.typeFromContentType(ct)); - } - } - - public void testTypeFromContentTypeIncludingCharSet() { - for (int i = PropertyType.UNDEFINED; i <= PropertyType.DECIMAL; i++) { - String ct = JcrValueType.contentTypeFromType(i) + "; charset=UTF-8"; - assertEquals(i, JcrValueType.typeFromContentType(ct)); - } - } - public void testTypeFromInvalidContentType() { - String[] invalids = new String[] {null, "", "jcr-value/invalid", "invalid/as-well"}; - - for (String invalid : invalids) { - assertEquals(PropertyType.UNDEFINED, JcrValueType.typeFromContentType(invalid)); - } - } -} \ No newline at end of file Property changes on: jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/jcr/JcrValueTypeTest.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Deleted: svn:keywords ## -1 +0,0 ## -Author Date Id Revision Rev URL \ No newline at end of property Index: jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/jcr/LockTimeOutFormatTest.java =================================================================== --- jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/jcr/LockTimeOutFormatTest.java (revision 1907912) +++ jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/jcr/LockTimeOutFormatTest.java (nonexistent) @@ -1,124 +0,0 @@ -/* - * 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.webdav.jcr; - -import java.net.URISyntaxException; - -import javax.jcr.Node; -import javax.jcr.RepositoryException; -import javax.jcr.lock.Lock; -import javax.jcr.lock.LockException; -import javax.xml.parsers.ParserConfigurationException; - -import junit.framework.TestCase; - -import org.apache.jackrabbit.webdav.jcr.lock.JcrActiveLock; -import org.apache.jackrabbit.webdav.xml.DomUtil; -import org.w3c.dom.Document; -import org.w3c.dom.Element; -import org.w3c.dom.NodeList; - -/** - * LockTimeOutFormatTest... - */ -public class LockTimeOutFormatTest extends TestCase { - - public void testOneSec() throws RepositoryException, URISyntaxException, ParserConfigurationException { - testfmt(1, "Second-1"); - } - - public void testInf() throws RepositoryException, URISyntaxException, ParserConfigurationException { - testfmt(Long.MAX_VALUE, "Infinite"); - } - - public void testTooLong() throws RepositoryException, URISyntaxException, ParserConfigurationException { - testfmt(Integer.MAX_VALUE + 100000L, "Infinite"); - } - - public void testNeg() throws RepositoryException, URISyntaxException, ParserConfigurationException { - // expired - testfmt(-1, null); - } - - private void testfmt(long jcrtimeout, String expectedString) throws RepositoryException, URISyntaxException, ParserConfigurationException { - - Lock l = new TestLock(jcrtimeout); - JcrActiveLock al = new JcrActiveLock(l); - - Document d = DomUtil.createDocument(); - Element activeLock = al.toXml(d); - assertEquals("activelock", activeLock.getLocalName()); - NodeList nl = activeLock.getElementsByTagNameNS("DAV:", "timeout"); - - if (expectedString == null) { - assertEquals(0, nl.getLength()); - } - else { - assertEquals(1, nl.getLength()); - Element timeout = (Element)nl.item(0); - String t = DomUtil.getText(timeout); - assertEquals(expectedString, t); - } - } - - /** - * Minimal Lock impl for tests above - */ - private static class TestLock implements Lock { - - private final long timeout; - - public TestLock(long timeout) { - this.timeout = timeout; - } - - public String getLockOwner() { - return null; - } - - public boolean isDeep() { - return false; - } - - public Node getNode() { - return null; - } - - public String getLockToken() { - return "foo"; - } - - public long getSecondsRemaining() throws RepositoryException { - return timeout; - } - - public boolean isLive() throws RepositoryException { - return timeout >= 0; - } - - public boolean isSessionScoped() { - return false; - } - - public boolean isLockOwningSession() { - return false; - } - - public void refresh() throws LockException, RepositoryException { - } - } -} Property changes on: jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/jcr/LockTimeOutFormatTest.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/jcr/LockTokenMappingTest.java =================================================================== --- jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/jcr/LockTokenMappingTest.java (revision 1907912) +++ jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/jcr/LockTokenMappingTest.java (nonexistent) @@ -1,107 +0,0 @@ -/* - * 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.webdav.jcr; - -import java.net.URI; -import java.net.URISyntaxException; -import java.util.UUID; - -import javax.jcr.Node; -import javax.jcr.RepositoryException; -import javax.jcr.lock.Lock; -import javax.jcr.lock.LockException; - -import org.apache.jackrabbit.webdav.jcr.lock.LockTokenMapper; - -import junit.framework.TestCase; - -/** - * LockTokenMappingTest... - */ -public class LockTokenMappingTest extends TestCase { - - // test lock with a lock token similar to the ones assigned by Jackrabbit - public void testOpenScopedJcr() throws RepositoryException, URISyntaxException { - testRoundtrip(UUID.randomUUID().toString() + "-X"); - } - - // test a fancy lock string - public void testOpenScopedFancy() throws RepositoryException, URISyntaxException { - testRoundtrip("\n\u00c4 \u20ac"); - } - - private void testRoundtrip(String token) throws RepositoryException, URISyntaxException { - - Lock l = new TestLock(token); - String davtoken = LockTokenMapper.getDavLocktoken(l); - - // valid URI? - URI u = new URI(davtoken); - assertTrue("lock token must be absolute URI", u.isAbsolute()); - assertEquals("lock token URI must be all-ASCII", u.toASCIIString(), u.toString()); - - String jcrtoken = LockTokenMapper.getJcrLockToken(davtoken); - assertEquals(jcrtoken, l.getLockToken()); - } - - /** - * Minimal Lock impl for tests above - */ - private static class TestLock implements Lock { - - private final String token; - - public TestLock(String token) { - this.token = token; - } - - public String getLockOwner() { - return null; - } - - public boolean isDeep() { - return false; - } - - public Node getNode() { - return null; - } - - public String getLockToken() { - return token; - } - - public long getSecondsRemaining() throws RepositoryException { - return 0; - } - - public boolean isLive() throws RepositoryException { - return false; - } - - public boolean isSessionScoped() { - return false; - } - - public boolean isLockOwningSession() { - return false; - } - - public void refresh() throws LockException, RepositoryException { - } - } -} Property changes on: jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/jcr/LockTokenMappingTest.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/jcr/observation/InfoMapTest.java =================================================================== --- jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/jcr/observation/InfoMapTest.java (revision 1907912) +++ jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/jcr/observation/InfoMapTest.java (nonexistent) @@ -1,71 +0,0 @@ -/* - * 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.webdav.jcr.observation; - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.util.HashMap; -import java.util.Map; - -import javax.jcr.RepositoryException; -import javax.jcr.Session; -import javax.xml.parsers.ParserConfigurationException; -import javax.xml.transform.TransformerException; - -import org.apache.jackrabbit.webdav.observation.ObservationConstants; -import org.apache.jackrabbit.webdav.xml.DomUtil; -import org.apache.jackrabbit.webdav.xml.Namespace; -import org.mockito.Mockito; -import org.w3c.dom.Document; -import org.w3c.dom.Element; -import org.xml.sax.SAXException; - -import junit.framework.TestCase; - -public class InfoMapTest extends TestCase { - - public void testInfoMap() - throws ParserConfigurationException, TransformerException, SAXException, IOException, RepositoryException { - - Session s = Mockito.mock(Session.class); - Mockito.when(s.getNamespaceURI("jcr")).thenReturn("http://www.jcp.org/jcr/1.0"); - - Map map = new HashMap(); - // mandated by JCR 2.0 - map.put("srcChildRelPath", "/x"); - // OAK extension, see https://issues.apache.org/jira/browse/OAK-1669 - map.put("jcr:primaryType", "nt:unstructured"); - Document doc = DomUtil.createDocument(); - Element container = DomUtil.createElement(doc, "x", null); - doc.appendChild(container); - SubscriptionImpl.serializeInfoMap(container, s, map); - ByteArrayOutputStream xml = new ByteArrayOutputStream(); - DomUtil.transformDocument(doc, xml); - - // reparse - Document tripped = DomUtil.parseDocument(new ByteArrayInputStream(xml.toByteArray())); - Element top = tripped.getDocumentElement(); - assertEquals("x", top.getLocalName()); - Element emap = DomUtil.getChildElement(top, ObservationConstants.N_EVENTINFO); - assertNotNull(emap); - Element path = DomUtil.getChildElement(emap, "srcChildRelPath", null); - assertNotNull(path); - Element type = DomUtil.getChildElement(emap, "primaryType", Namespace.getNamespace("http://www.jcp.org/jcr/1.0")); - assertNotNull(type); - } -} Property changes on: jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/jcr/observation/InfoMapTest.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Deleted: svn:executable ## -1 +0,0 ## -* \ No newline at end of property Index: jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/jcr/security/AbstractSecurityTest.java =================================================================== --- jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/jcr/security/AbstractSecurityTest.java (revision 1907912) +++ jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/jcr/security/AbstractSecurityTest.java (nonexistent) @@ -1,40 +0,0 @@ -/* - * 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.webdav.jcr.security; - -import javax.jcr.Repository; -import javax.jcr.security.AccessControlManager; - -import org.apache.jackrabbit.test.AbstractJCRTest; -import org.apache.jackrabbit.test.NotExecutableException; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public abstract class AbstractSecurityTest extends AbstractJCRTest { - - protected AccessControlManager acMgr; - - @Override - protected void setUp() throws Exception { - super.setUp(); - if (isSupported(Repository.OPTION_ACCESS_CONTROL_SUPPORTED)) { - acMgr = superuser.getAccessControlManager(); - } else { - throw new NotExecutableException(); - } - } -} \ No newline at end of file Property changes on: jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/jcr/security/AbstractSecurityTest.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/jcr/security/JcrSupportedPrivilegePropertyTest.java =================================================================== --- jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/jcr/security/JcrSupportedPrivilegePropertyTest.java (revision 1907912) +++ jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/jcr/security/JcrSupportedPrivilegePropertyTest.java (nonexistent) @@ -1,46 +0,0 @@ -/* - * 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.webdav.jcr.security; - -import java.util.Arrays; -import java.util.HashSet; -import java.util.List; -import java.util.Set; -import javax.jcr.RepositoryException; -import javax.jcr.security.Privilege; - -import org.apache.jackrabbit.webdav.security.SupportedPrivilege; - -public class JcrSupportedPrivilegePropertyTest extends AbstractSecurityTest { - - public void testSupportedPrivileges() throws RepositoryException { - Set privs = new HashSet(Arrays.asList(acMgr.getSupportedPrivileges(testRoot))); - JcrSupportedPrivilegesProperty prop = new JcrSupportedPrivilegesProperty(superuser, testRoot); - List value = prop.asDavProperty().getValue(); - - if (privs.contains(acMgr.privilegeFromName(Privilege.JCR_ALL))) { - assertEquals(1, value.size()); - } - } - - public void testJcrAllPrivilege() throws RepositoryException { - JcrSupportedPrivilegesProperty prop = new JcrSupportedPrivilegesProperty(superuser); - List value = prop.asDavProperty().getValue(); - - assertEquals(1, value.size()); - } -} \ No newline at end of file Property changes on: jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/jcr/security/JcrSupportedPrivilegePropertyTest.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/jcr/security/JcrUserPrivilegesPropertyTest.java =================================================================== --- jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/jcr/security/JcrUserPrivilegesPropertyTest.java (revision 1907912) +++ jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/jcr/security/JcrUserPrivilegesPropertyTest.java (nonexistent) @@ -1,69 +0,0 @@ -/* - * 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.webdav.jcr.security; - -import java.util.Collection; -import java.util.HashSet; -import java.util.Set; -import javax.jcr.RepositoryException; -import javax.jcr.Session; -import javax.jcr.security.AccessControlManager; - -import org.apache.jackrabbit.util.Text; -import org.apache.jackrabbit.webdav.security.Privilege; -import org.apache.jackrabbit.webdav.xml.Namespace; - -public class JcrUserPrivilegesPropertyTest extends AbstractSecurityTest { - - private Set getExpected(AccessControlManager acMgr, Session s) throws RepositoryException { - Set expected = new HashSet(); - for (javax.jcr.security.Privilege p : acMgr.getPrivileges(testRoot)) { - String localName = Text.getLocalName(p.getName()); - String prefix = Text.getNamespacePrefix(p.getName()); - Namespace ns = (prefix.isEmpty()) ? Namespace.EMPTY_NAMESPACE : Namespace.getNamespace(prefix, s.getNamespaceURI(prefix)); - expected.add(Privilege.getPrivilege(localName, ns)); - } - return expected; - } - - public void testAdminPrivileges() throws RepositoryException { - Set expected = getExpected(acMgr, superuser); - - JcrUserPrivilegesProperty upp = new JcrUserPrivilegesProperty(superuser, testRoot); - Collection davPrivs = upp.asDavProperty().getValue(); - - assertEquals(expected.size(), davPrivs.size()); - assertTrue(davPrivs.containsAll(expected)); - } - - public void testReadOnlyPrivileges() throws RepositoryException { - Session readOnly = getHelper().getReadOnlySession(); - try { - Set expected = getExpected(readOnly.getAccessControlManager(), readOnly); - - JcrUserPrivilegesProperty upp = new JcrUserPrivilegesProperty(readOnly, testRoot); - Collection davPrivs = upp.asDavProperty().getValue(); - - assertEquals(expected.size(), davPrivs.size()); - assertTrue(davPrivs.containsAll(expected)); - } finally { - if (readOnly != null) { - readOnly.logout(); - } - } - } -} \ No newline at end of file Property changes on: jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/jcr/security/JcrUserPrivilegesPropertyTest.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/server/BindTest.java =================================================================== --- jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/server/BindTest.java (revision 1907912) +++ jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/server/BindTest.java (nonexistent) @@ -1,603 +0,0 @@ -/* - * 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.webdav.server; - -import java.io.IOException; -import java.net.URI; -import java.net.URISyntaxException; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.Set; - -import org.apache.http.HttpResponse; -import org.apache.http.client.methods.HttpGet; -import org.apache.http.client.methods.HttpHead; -import org.apache.http.client.methods.HttpPut; -import org.apache.http.entity.ContentType; -import org.apache.http.entity.StringEntity; -import org.apache.http.util.EntityUtils; -import org.apache.jackrabbit.webdav.DavException; -import org.apache.jackrabbit.webdav.MultiStatus; -import org.apache.jackrabbit.webdav.MultiStatusResponse; -import org.apache.jackrabbit.webdav.bind.BindConstants; -import org.apache.jackrabbit.webdav.bind.BindInfo; -import org.apache.jackrabbit.webdav.bind.ParentElement; -import org.apache.jackrabbit.webdav.bind.RebindInfo; -import org.apache.jackrabbit.webdav.bind.UnbindInfo; -import org.apache.jackrabbit.webdav.client.methods.HttpBind; -import org.apache.jackrabbit.webdav.client.methods.HttpMkcol; -import org.apache.jackrabbit.webdav.client.methods.HttpMove; -import org.apache.jackrabbit.webdav.client.methods.HttpOptions; -import org.apache.jackrabbit.webdav.client.methods.HttpPropfind; -import org.apache.jackrabbit.webdav.client.methods.HttpRebind; -import org.apache.jackrabbit.webdav.client.methods.HttpUnbind; -import org.apache.jackrabbit.webdav.client.methods.HttpVersionControl; -import org.apache.jackrabbit.webdav.property.DavProperty; -import org.apache.jackrabbit.webdav.property.DavPropertyNameSet; -import org.w3c.dom.Element; -import org.w3c.dom.Node; - -/** - * Test cases for WebDAV BIND functionality (see RFC 5842 - */ -public class BindTest extends WebDAVTestBase { - - // http://greenbytes.de/tech/webdav/rfc5842.html#rfc.section.8.1 - public void testOptions() throws IOException { - HttpOptions options = new HttpOptions(this.uri); - HttpResponse response = this.client.execute(options, this.context); - int status = response.getStatusLine().getStatusCode(); - assertEquals(200, status); - Set allow = options.getAllowedMethods(response); - Set complianceClasses = options.getDavComplianceClasses(response); - assertTrue("DAV header should include 'bind' feature", complianceClasses.contains("bind")); - assertTrue("Allow header should include BIND method", allow.contains("BIND")); - assertTrue("Allow header should include REBIND method", allow.contains("REBIND")); - assertTrue("Allow header should include UNBIND method", allow.contains("UNBIND")); - } - - // create test resource, make it referenceable, check resource id, move resource, check again - public void testResourceId() throws IOException, DavException, URISyntaxException { - - String testcol = this.root + "testResourceId/"; - String testuri1 = testcol + "bindtest1"; - String testuri2 = testcol + "bindtest2"; - int status; - try { - HttpMkcol mkcol = new HttpMkcol(testcol); - status = this.client.execute(mkcol, this.context).getStatusLine().getStatusCode(); - assertEquals(201, status); - - HttpPut put = new HttpPut(testuri1); - put.setEntity(new StringEntity("foo", ContentType.create("text/plain", "UTF-8"))); - status = this.client.execute(put, this.context).getStatusLine().getStatusCode(); - assertEquals(201, status); - - // enabling version control always makes the resource referenceable - HttpVersionControl versioncontrol = new HttpVersionControl(testuri1); - status = this.client.execute(versioncontrol, this.context).getStatusLine().getStatusCode(); - assertTrue("status: " + status, status == 200 || status == 201); - - URI resourceId = getResourceId(testuri1); - - HttpMove move = new HttpMove(testuri1, testuri2, true); - status = this.client.execute(move, this.context).getStatusLine().getStatusCode(); - assertEquals(201, status); - - URI resourceId2 = getResourceId(testuri2); - assertEquals(resourceId, resourceId2); - } finally { - delete(testcol); - } - } - - // utility methods - - // see http://greenbytes.de/tech/webdav/rfc5842.html#rfc.section.3.1 - private URI getResourceId(String uri) throws IOException, DavException, URISyntaxException { - DavPropertyNameSet names = new DavPropertyNameSet(); - names.add(BindConstants.RESOURCEID); - HttpPropfind propfind = new HttpPropfind(uri, names, 0); - HttpResponse response = this.client.execute(propfind, this.context); - int status = response.getStatusLine().getStatusCode(); - assertEquals(207, status); - MultiStatus multistatus = propfind.getResponseBodyAsMultiStatus(response); - MultiStatusResponse[] responses = multistatus.getResponses(); - assertEquals(1, responses.length); - DavProperty resourceId = responses[0].getProperties(200).get(BindConstants.RESOURCEID); - assertNotNull(resourceId); - assertTrue(resourceId.getValue() instanceof Element); - Element href = (Element)resourceId.getValue(); - assertEquals("href", href.getLocalName()); - String text = getUri(href); - URI resid = new URI(text); - return resid; - } - - private DavProperty getParentSet(String uri) throws IOException, DavException, URISyntaxException { - DavPropertyNameSet names = new DavPropertyNameSet(); - names.add(BindConstants.PARENTSET); - HttpPropfind propfind = new HttpPropfind(uri, names, 0); - HttpResponse response = this.client.execute(propfind, this.context); - int status = response.getStatusLine().getStatusCode(); - assertEquals(207, status); - MultiStatus multistatus = propfind.getResponseBodyAsMultiStatus(response); - MultiStatusResponse[] responses = multistatus.getResponses(); - assertEquals(1, responses.length); - DavProperty parentset = responses[0].getProperties(200).get(BindConstants.PARENTSET); - assertNotNull(parentset); - return parentset; - } - - public void testSimpleBind() throws Exception { - String testcol = this.root + "testSimpleBind/"; - String subcol1 = testcol + "bindtest1/"; - String testres1 = subcol1 + "res1"; - String subcol2 = testcol + "bindtest2/"; - String testres2 = subcol2 + "res2"; - int status; - try { - HttpMkcol mkcol = new HttpMkcol(testcol); - status = this.client.execute(mkcol, this.context).getStatusLine().getStatusCode(); - assertEquals(201, status); - mkcol = new HttpMkcol(subcol1); - status = this.client.execute(mkcol, this.context).getStatusLine().getStatusCode(); - assertEquals(201, status); - mkcol = new HttpMkcol(subcol2); - status = this.client.execute(mkcol, this.context).getStatusLine().getStatusCode(); - assertEquals(201, status); - - //create new resource R with path bindtest1/res1 - HttpPut put = new HttpPut(testres1); - put.setEntity(new StringEntity("foo", ContentType.create("text/plain", "UTF-8"))); - status = this.client.execute(put, this.context).getStatusLine().getStatusCode(); - assertEquals(201, status); - - //create new binding of R with path bindtest2/res2 - HttpBind bind = new HttpBind(subcol2, new BindInfo(testres1, "res2")); - status = this.client.execute(bind, this.context).getStatusLine().getStatusCode(); - assertEquals(201, status); - //check if both bindings report the same DAV:resource-id - assertEquals(this.getResourceId(testres1), this.getResourceId(testres2)); - - //compare representations retrieved with both paths - HttpGet get = new HttpGet(testres1); - HttpResponse resp = this.client.execute(get, this.context); - status = resp.getStatusLine().getStatusCode(); - assertEquals(200, status); - assertEquals("foo", EntityUtils.toString(resp.getEntity())); - resp = this.client.execute(get, this.context); - status = resp.getStatusLine().getStatusCode(); - assertEquals(200, status); - assertEquals("foo", EntityUtils.toString(resp.getEntity())); - - //modify R using the new path - put = new HttpPut(testres2); - put.setEntity(new StringEntity("bar", ContentType.create("text/plain", "UTF-8"))); - status = this.client.execute(put, this.context).getStatusLine().getStatusCode(); - assertTrue("status: " + status, status == 200 || status == 204); - - //compare representations retrieved with both paths - get = new HttpGet(testres1); - resp = this.client.execute(get, this.context); - status = resp.getStatusLine().getStatusCode(); - assertEquals(200, status); - assertEquals("bar", EntityUtils.toString(resp.getEntity())); - get = new HttpGet(testres2); - resp = this.client.execute(get, this.context); - status = resp.getStatusLine().getStatusCode(); - assertEquals(200, status); - assertEquals("bar", EntityUtils.toString(resp.getEntity())); - } finally { - delete(testcol); - } - } - - public void testRebind() throws Exception { - String testcol = this.root + "testRebind/"; - String subcol1 = testcol + "bindtest1/"; - String testres1 = subcol1 + "res1"; - String subcol2 = testcol + "bindtest2/"; - String testres2 = subcol2 + "res2"; - int status; - try { - HttpMkcol mkcol = new HttpMkcol(testcol); - status = this.client.execute(mkcol, this.context).getStatusLine().getStatusCode(); - assertEquals(201, status); - mkcol = new HttpMkcol(subcol1); - status = this.client.execute(mkcol, this.context).getStatusLine().getStatusCode(); - assertEquals(201, status); - mkcol = new HttpMkcol(subcol2); - status = this.client.execute(mkcol, this.context).getStatusLine().getStatusCode(); - assertEquals(201, status); - - //create new resource R with path bindtest1/res1 - HttpPut put = new HttpPut(testres1); - put.setEntity(new StringEntity("foo", ContentType.create("text/plain", "UTF-8"))); - status = this.client.execute(put, this.context).getStatusLine().getStatusCode(); - assertEquals(201, status); - - // enabling version control always makes the resource referenceable - HttpVersionControl versioncontrol = new HttpVersionControl(testres1); - status = this.client.execute(versioncontrol, this.context).getStatusLine().getStatusCode(); - assertTrue("status: " + status, status == 200 || status == 201); - - URI r1 = this.getResourceId(testres1); - - HttpGet get = new HttpGet(testres1); - HttpResponse resp = this.client.execute(get, this.context); - status = resp.getStatusLine().getStatusCode(); - assertEquals(200, status); - assertEquals("foo", EntityUtils.toString(resp.getEntity())); - - //rebind R with path bindtest2/res2 - HttpRebind rebind = new HttpRebind(subcol2, new RebindInfo(testres1, "res2")); - status = this.client.execute(rebind, this.context).getStatusLine().getStatusCode(); - assertEquals(201, status); - - URI r2 = this.getResourceId(testres2); - - get = new HttpGet(testres2); - resp = this.client.execute(get, this.context); - status = resp.getStatusLine().getStatusCode(); - assertEquals(200, status); - assertEquals("foo", EntityUtils.toString(resp.getEntity())); - - //make sure that rebind did not change the resource-id - assertEquals(r1, r2); - - //verify that the initial binding is gone - HttpHead head = new HttpHead(testres1); - status = this.client.execute(head, this.context).getStatusLine().getStatusCode(); - assertEquals(404, status); - } finally { - delete(testcol); - } - } - - public void testBindOverwrite() throws Exception { - String testcol = this.root + "testSimpleBind/"; - String subcol1 = testcol + "bindtest1/"; - String testres1 = subcol1 + "res1"; - String subcol2 = testcol + "bindtest2/"; - String testres2 = subcol2 + "res2"; - int status; - try { - HttpMkcol mkcol = new HttpMkcol(testcol); - status = this.client.execute(mkcol, this.context).getStatusLine().getStatusCode(); - assertEquals(201, status); - mkcol = new HttpMkcol(subcol1); - status = this.client.execute(mkcol, this.context).getStatusLine().getStatusCode(); - assertEquals(201, status); - mkcol = new HttpMkcol(subcol2); - status = this.client.execute(mkcol, this.context).getStatusLine().getStatusCode(); - assertEquals(201, status); - - //create new resource R with path bindtest1/res1 - HttpPut put = new HttpPut(testres1); - put.setEntity(new StringEntity("foo", ContentType.create("text/plain", "UTF-8"))); - status = this.client.execute(put, this.context).getStatusLine().getStatusCode(); - assertEquals(201, status); - - //create new resource R' with path bindtest2/res2 - put = new HttpPut(testres2); - put.setEntity(new StringEntity("bar", ContentType.create("text/plain", "UTF-8"))); - status = this.client.execute(put, this.context).getStatusLine().getStatusCode(); - assertEquals(201, status); - - //try to create new binding of R with path bindtest2/res2 and Overwrite:F - HttpBind bind = new HttpBind(subcol2, new BindInfo(testres1, "res2")); - bind.addHeader("Overwrite", "F"); - status = this.client.execute(bind, this.context).getStatusLine().getStatusCode(); - assertEquals(412, status); - - //verify that bindtest2/res2 still points to R' - HttpGet get = new HttpGet(testres2); - HttpResponse resp = this.client.execute(get, this.context); - status = resp.getStatusLine().getStatusCode(); - assertEquals(200, status); - assertEquals("bar", EntityUtils.toString(resp.getEntity())); - - //create new binding of R with path bindtest2/res2 - bind = new HttpBind(subcol2, new BindInfo(testres1, "res2")); - status = this.client.execute(bind, this.context).getStatusLine().getStatusCode(); - assertTrue("status: " + status, status == 200 || status == 204); - - //verify that bindtest2/res2 now points to R - get = new HttpGet(testres2); - resp = this.client.execute(get, this.context); - status = resp.getStatusLine().getStatusCode(); - assertEquals(200, status); - assertEquals("foo", EntityUtils.toString(resp.getEntity())); - - //verify that the initial binding is still there - HttpHead head = new HttpHead(testres1); - status = this.client.execute(head, this.context).getStatusLine().getStatusCode(); - assertEquals(200, status); - } finally { - delete(testcol); - } - } - - public void testRebindOverwrite() throws Exception { - String testcol = this.root + "testSimpleBind/"; - String subcol1 = testcol + "bindtest1/"; - String testres1 = subcol1 + "res1"; - String subcol2 = testcol + "bindtest2/"; - String testres2 = subcol2 + "res2"; - int status; - try { - HttpMkcol mkcol = new HttpMkcol(testcol); - status = this.client.execute(mkcol, this.context).getStatusLine().getStatusCode(); - assertEquals(201, status); - mkcol = new HttpMkcol(subcol1); - status = this.client.execute(mkcol, this.context).getStatusLine().getStatusCode(); - assertEquals(201, status); - mkcol = new HttpMkcol(subcol2); - status = this.client.execute(mkcol, this.context).getStatusLine().getStatusCode(); - assertEquals(201, status); - - //create new resource R with path testSimpleBind/bindtest1/res1 - HttpPut put = new HttpPut(testres1); - put.setEntity(new StringEntity("foo", ContentType.create("text/plain", "UTF-8"))); - status = this.client.execute(put, this.context).getStatusLine().getStatusCode(); - assertEquals(201, status); - - // enabling version control always makes the resource referenceable - HttpVersionControl versioncontrol = new HttpVersionControl(testres1); - status = this.client.execute(versioncontrol, this.context).getStatusLine().getStatusCode(); - assertTrue("status: " + status, status == 200 || status == 201); - - //create new resource R' with path testSimpleBind/bindtest2/res2 - put = new HttpPut(testres2); - put.setEntity(new StringEntity("bar", ContentType.create("text/plain", "UTF-8"))); - status = this.client.execute(put, this.context).getStatusLine().getStatusCode(); - assertEquals(201, status); - - //try rebind R with path testSimpleBind/bindtest2/res2 and Overwrite:F - HttpRebind rebind = new HttpRebind(subcol2, new RebindInfo(testres1, "res2")); - rebind.addHeader("Overwrite", "F"); - status = this.client.execute(rebind, this.context).getStatusLine().getStatusCode(); - assertEquals(412, status); - - //verify that testSimpleBind/bindtest2/res2 still points to R' - HttpGet get = new HttpGet(testres2); - HttpResponse resp = this.client.execute(get, this.context); - status = resp.getStatusLine().getStatusCode(); - assertEquals(200, status); - assertEquals("bar", EntityUtils.toString(resp.getEntity())); - - //rebind R with path testSimpleBind/bindtest2/res2 - rebind = new HttpRebind(subcol2, new RebindInfo(testres1, "res2")); - status = this.client.execute(rebind, this.context).getStatusLine().getStatusCode(); - assertTrue("status: " + status, status == 200 || status == 204); - - //verify that testSimpleBind/bindtest2/res2 now points to R - get = new HttpGet(testres2); - resp = this.client.execute(get, this.context); - status = resp.getStatusLine().getStatusCode(); - assertEquals(200, status); - assertEquals("foo", EntityUtils.toString(resp.getEntity())); - - //verify that the initial binding is gone - HttpHead head = new HttpHead(testres1); - status = this.client.execute(head, this.context).getStatusLine().getStatusCode(); - assertEquals(404, status); - } finally { - delete(testcol); - } - } - - public void testParentSet() throws Exception { - String testcol = this.root + "testParentSet/"; - String subcol1 = testcol + "bindtest1/"; - String testres1 = subcol1 + "res1"; - String subcol2 = testcol + "bindtest2/"; - String testres2 = subcol2 + "res2"; - int status; - try { - HttpMkcol mkcol = new HttpMkcol(testcol); - status = this.client.execute(mkcol, this.context).getStatusLine().getStatusCode(); - assertEquals(201, status); - mkcol = new HttpMkcol(subcol1); - status = this.client.execute(mkcol, this.context).getStatusLine().getStatusCode(); - assertEquals(201, status); - mkcol = new HttpMkcol(subcol2); - status = this.client.execute(mkcol, this.context).getStatusLine().getStatusCode(); - assertEquals(201, status); - - //create new resource R with path testSimpleBind/bindtest1/res1 - HttpPut put = new HttpPut(testres1); - put.setEntity(new StringEntity("foo", ContentType.create("text/plain", "UTF-8"))); - status = this.client.execute(put, this.context).getStatusLine().getStatusCode(); - assertEquals(201, status); - - //create new binding of R with path testSimpleBind/bindtest2/res2 - HttpBind bind = new HttpBind(subcol2, new BindInfo(testres1, "res2")); - status = this.client.execute(bind, this.context).getStatusLine().getStatusCode(); - assertEquals(201, status); - //check if both bindings report the same DAV:resource-id - assertEquals(this.getResourceId(testres1), this.getResourceId(testres2)); - - //verify values of parent-set properties - List hrefs1 = new ArrayList(); - List segments1 = new ArrayList(); - List hrefs2 = new ArrayList(); - List segments2 = new ArrayList(); - Object ps1 = this.getParentSet(testres1).getValue(); - Object ps2 = this.getParentSet(testres2).getValue(); - assertTrue(ps1 instanceof List); - assertTrue(ps2 instanceof List); - List plist1 = (List) ps1; - List plist2 = (List) ps2; - assertEquals(2, plist1.size()); - assertEquals(2, plist2.size()); - for (int k = 0; k < 2; k++) { - Object pObj1 = plist1.get(k); - Object pObj2 = plist2.get(k); - assertTrue(pObj1 instanceof Element); - assertTrue(pObj2 instanceof Element); - ParentElement p1 = ParentElement.createFromXml((Element) pObj1); - ParentElement p2 = ParentElement.createFromXml((Element) pObj2); - hrefs1.add(p1.getHref()); - hrefs2.add(p2.getHref()); - segments1.add(p1.getSegment()); - segments2.add(p2.getSegment()); - } - Collections.sort(hrefs1); - Collections.sort(hrefs2); - Collections.sort(segments1); - Collections.sort(segments2); - assertEquals(hrefs1, hrefs2); - assertEquals(segments1, segments2); - } finally { - delete(testcol); - } - } - - public void testBindCollections() throws Exception { - String testcol = this.root + "testBindCollections/"; - String a1 = testcol + "a1/"; - String b1 = a1 + "b1/"; - String c1 = b1 + "c1/"; - String x1 = c1 + "x1"; - String a2 = testcol + "a2/"; - String b2 = a2 + "b2/"; - String c2 = b2 + "c2/"; - String x2 = c2 + "x2"; - int status; - try { - HttpMkcol mkcol = new HttpMkcol(testcol); - status = this.client.execute(mkcol, this.context).getStatusLine().getStatusCode(); - assertEquals(201, status); - mkcol = new HttpMkcol(a1); - status = this.client.execute(mkcol, this.context).getStatusLine().getStatusCode(); - assertEquals(201, status); - mkcol = new HttpMkcol(a2); - status = this.client.execute(mkcol, this.context).getStatusLine().getStatusCode(); - assertEquals(201, status); - - //create collection resource C - mkcol = new HttpMkcol(b1); - status = this.client.execute(mkcol, this.context).getStatusLine().getStatusCode(); - assertEquals(201, status); - mkcol = new HttpMkcol(c1); - status = this.client.execute(mkcol, this.context).getStatusLine().getStatusCode(); - assertEquals(201, status); - - //create plain resource R - HttpPut put = new HttpPut(x1); - put.setEntity(new StringEntity("foo", ContentType.create("text/plain", "UTF-8"))); - status = this.client.execute(put, this.context).getStatusLine().getStatusCode(); - assertEquals(201, status); - - //create new binding of C with path a2/b2 - HttpBind bind = new HttpBind(a2, new BindInfo(b1, "b2")); - status = this.client.execute(bind, this.context).getStatusLine().getStatusCode(); - assertEquals(201, status); - //check if both bindings report the same DAV:resource-id - assertEquals(this.getResourceId(b1), this.getResourceId(b2)); - - mkcol = new HttpMkcol(c2); - status = this.client.execute(mkcol, this.context).getStatusLine().getStatusCode(); - assertEquals(201, status); - - //create new binding of R with path a2/b2/c2/r2 - bind = new HttpBind(c2, new BindInfo(x1, "x2")); - status = this.client.execute(bind, this.context).getStatusLine().getStatusCode(); - assertEquals(201, status); - //check if both bindings report the same DAV:resource-id - assertEquals(this.getResourceId(x1), this.getResourceId(x2)); - - //verify different path alternatives - URI rid = this.getResourceId(x1); - assertEquals(rid, this.getResourceId(x2)); - assertEquals(rid, this.getResourceId(testcol + "a2/b2/c1/x1")); - assertEquals(rid, this.getResourceId(testcol + "a1/b1/c2/x2")); - Object ps = this.getParentSet(x1).getValue(); - assertTrue(ps instanceof List); - assertEquals(2, ((List) ps).size()); - ps = this.getParentSet(x2).getValue(); - assertTrue(ps instanceof List); - assertEquals(2, ((List) ps).size()); - } finally { - delete(testcol); - } - } - - //will fail until is fixed - public void testUnbind() throws Exception { - String testcol = this.root + "testUnbind/"; - String subcol1 = testcol + "bindtest1/"; - String testres1 = subcol1 + "res1"; - String subcol2 = testcol + "bindtest2/"; - String testres2 = subcol2 + "res2"; - int status; - try { - HttpMkcol mkcol = new HttpMkcol(testcol); - status = this.client.execute(mkcol, this.context).getStatusLine().getStatusCode(); - assertEquals(201, status); - mkcol = new HttpMkcol(subcol1); - status = this.client.execute(mkcol, this.context).getStatusLine().getStatusCode(); - assertEquals(201, status); - mkcol = new HttpMkcol(subcol2); - status = this.client.execute(mkcol, this.context).getStatusLine().getStatusCode(); - assertEquals(201, status); - - //create new resource R with path testSimpleBind/bindtest1/res1 - HttpPut put = new HttpPut(testres1); - put.setEntity(new StringEntity("foo", ContentType.create("text/plain", "UTF-8"))); - status = this.client.execute(put, this.context).getStatusLine().getStatusCode(); - assertEquals(201, status); - - //create new binding of R with path testSimpleBind/bindtest2/res2 - HttpBind bind = new HttpBind(subcol2, new BindInfo(testres1, "res2")); - status = this.client.execute(bind, this.context).getStatusLine().getStatusCode(); - assertEquals(201, status); - //check if both bindings report the same DAV:resource-id - assertEquals(this.getResourceId(testres1), this.getResourceId(testres2)); - - //remove new path - HttpUnbind unbind = new HttpUnbind(subcol2, new UnbindInfo("res2")); - status = this.client.execute(unbind, this.context).getStatusLine().getStatusCode(); - assertTrue("status: " + status, status == 200 || status == 204); - - //verify that the new binding is gone - HttpHead head = new HttpHead(testres2); - status = this.client.execute(head, this.context).getStatusLine().getStatusCode(); - assertEquals(404, status); - - //verify that the initial binding is still there - head = new HttpHead(testres1); - status = this.client.execute(head, this.context).getStatusLine().getStatusCode(); - assertEquals(200, status); - } finally { - delete(testcol); - } - } - - private String getUri(Element href) { - String s = ""; - for (Node c = href.getFirstChild(); c != null; c = c.getNextSibling()) { - if (c.getNodeType() == Node.TEXT_NODE) { - s += c.getNodeValue(); - } - } - return s; - } -} Property changes on: jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/server/BindTest.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/server/ConditionalsTest.java =================================================================== --- jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/server/ConditionalsTest.java (revision 1907912) +++ jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/server/ConditionalsTest.java (nonexistent) @@ -1,177 +0,0 @@ -/* - * 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.webdav.server; - -import java.io.IOException; -import java.text.ParseException; - -import org.apache.http.Header; -import org.apache.http.HttpResponse; -import org.apache.http.client.methods.HttpGet; -import org.apache.http.client.methods.HttpHead; -import org.apache.http.client.methods.HttpPut; -import org.apache.http.entity.StringEntity; -import org.apache.http.util.EntityUtils; - -public class ConditionalsTest extends WebDAVTestBase { - - // private DateFormat HTTPDATEFORMAT = new SimpleDateFormat("EEE, dd MMM - // yyyy HH:mm:ss ZZZ", Locale.ENGLISH); - - public void testPutCheckLastModified() throws IOException, ParseException { - String testUri = this.uri.toString() + (this.uri.toString().endsWith("/") ? "" : "/") + "testPutCheckLastModified"; - try { - // create test resource - { - HttpPut put = new HttpPut(testUri); - put.setEntity(new StringEntity("foobar")); - HttpResponse response = this.client.execute(put, this.context); - int status = response.getStatusLine().getStatusCode(); - assertEquals(201, status); - } - - long created = System.currentTimeMillis(); - - // get last modified date - Header etag = null; - Header lm = null; - { - HttpHead head = new HttpHead(testUri); - HttpResponse response = this.client.execute(head, this.context); - int status = response.getStatusLine().getStatusCode(); - assertEquals(200, status); - lm = response.getFirstHeader("last-modified"); - assertNotNull(lm); - etag = response.getFirstHeader("etag"); - } - - // Date created = HTTPDATEFORMAT.parse(lm.getValue()); - - // conditional GET - { - HttpGet get = new HttpGet(testUri); - get.setHeader("If-Modified-Since", lm.getValue()); - HttpResponse response = this.client.execute(get, this.context); - int status = response.getStatusLine().getStatusCode(); - assertEquals(304, status); - if (etag != null) { - Header newetag = response.getFirstHeader("etag"); - assertNotNull(newetag); - assertEquals(etag.getValue(), newetag.getValue()); - } - } - - // conditional HEAD - { - HttpHead head = new HttpHead(testUri); - head.setHeader("If-Modified-Since", lm.getValue()); - HttpResponse response = this.client.execute(head, this.context); - int status = response.getStatusLine().getStatusCode(); - assertEquals(304, status); - if (etag != null) { - Header newetag = response.getFirstHeader("etag"); - assertNotNull(newetag); - assertEquals(etag.getValue(), newetag.getValue()); - } - } - - // conditional HEAD with broken date (MUST ignore header field) - { - HttpHead head = new HttpHead(testUri); - head.setHeader("If-Modified-Since", "broken"); - HttpResponse response = this.client.execute(head, this.context); - int status = response.getStatusLine().getStatusCode(); - assertEquals(200, status); - } - - // conditional GET with broken date (MUST ignore header field) - { - HttpGet req = new HttpGet(testUri); - req.addHeader("If-Modified-Since", lm.getValue()); - req.addHeader("If-Modified-Since", "foo"); - HttpResponse response = this.client.execute(req, this.context); - int status = response.getStatusLine().getStatusCode(); - assertEquals(200, status); - EntityUtils.consume(response.getEntity()); - } - - // let one sec elapse - while (System.currentTimeMillis() < created + 1000) { - try { - Thread.sleep(100); - } catch (InterruptedException ignored) { - } - } - - // verify last modified did not change - { - HttpHead head = new HttpHead(testUri); - HttpResponse response = this.client.execute(head, this.context); - int status = response.getStatusLine().getStatusCode(); - assertEquals(200, status); - Header newlm = response.getFirstHeader("last-modified"); - assertNotNull(newlm); - assertEquals(lm.getValue(), newlm.getValue()); - } - - // conditional PUT - { - HttpPut put = new HttpPut(testUri); - put.setHeader("If-Unmodified-Since", lm.getValue()); - put.setEntity(new StringEntity("qux")); - HttpResponse response = this.client.execute(put, this.context); - int status = response.getStatusLine().getStatusCode(); - assertEquals(204, status); - } - - // conditional PUT once more should fail - { - HttpPut put = new HttpPut(testUri); - put.setHeader("If-Unmodified-Since", lm.getValue()); - put.setEntity(new StringEntity("lazydog")); - HttpResponse response = this.client.execute(put, this.context); - int status = response.getStatusLine().getStatusCode(); - assertEquals(412, status); - } - - // conditional PUT with broken If-Unmodified-Since should pass - { - HttpPut put = new HttpPut(testUri); - put.addHeader("If-Unmodified-Since", lm.getValue()); - put.addHeader("If-Unmodified-Since", "foo"); - put.setEntity(new StringEntity("qux")); - HttpResponse response = this.client.execute(put, this.context); - int status = response.getStatusLine().getStatusCode(); - assertEquals(204, status); - } - } finally { - delete(testUri); - } - } - - public void testGetCollectionEtag() throws IOException, ParseException { - String testUri = this.uri.toString() + (this.uri.toString().endsWith("/") ? "" : "/"); - HttpGet get = new HttpGet(testUri); - HttpResponse response = this.client.execute(get, this.context); - int status = response.getStatusLine().getStatusCode(); - assertEquals(200, status); - Header etag = response.getFirstHeader("etag"); - if (etag != null) { - assertFalse("etag must not be empty", "".equals(etag.getValue())); - } - } -} Property changes on: jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/server/ConditionalsTest.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Deleted: svn:executable ## -1 +0,0 ## -* \ No newline at end of property Index: jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/server/ContentCodingTest.java =================================================================== --- jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/server/ContentCodingTest.java (revision 1907912) +++ jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/server/ContentCodingTest.java (nonexistent) @@ -1,232 +0,0 @@ -/* - * 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.webdav.server; - -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.OutputStream; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.Locale; -import java.util.zip.DeflaterOutputStream; -import java.util.zip.GZIPOutputStream; - -import org.apache.http.Header; -import org.apache.http.HttpResponse; -import org.apache.http.client.methods.HttpHead; -import org.apache.http.client.methods.HttpPut; -import org.apache.http.entity.ByteArrayEntity; -import org.apache.http.entity.StringEntity; -import org.apache.http.message.BasicHeader; -import org.apache.jackrabbit.webdav.DavConstants; -import org.apache.jackrabbit.webdav.DavException; -import org.apache.jackrabbit.webdav.MultiStatusResponse; -import org.apache.jackrabbit.webdav.client.methods.HttpPropfind; - -public class ContentCodingTest extends WebDAVTestBase { - - public void testPutNoContentCoding() throws IOException { - String testUri = this.uri.toString() + (this.uri.toString().endsWith("/") ? "" : "/") + "testPutNoContentCoding"; - try { - HttpPut put = new HttpPut(testUri); - put.setEntity(new StringEntity("foobar")); - int status = this.client.execute(put, this.context).getStatusLine().getStatusCode(); - assertEquals(201, status); - } finally { - delete(testUri); - } - } - - public void testPutUnknownContentCoding() throws IOException { - String testUri = this.uri.toString() + (this.uri.toString().endsWith("/") ? "" : "/") + "testPutUnkownContentCoding"; - int status = -1; - try { - HttpPut put = new HttpPut(testUri); - StringEntity entity = new StringEntity("foobarfoobarfoobar"); - entity.setContentEncoding(new BasicHeader("Content-Encoding", "qux")); - put.setEntity(entity); - status = this.client.execute(put, this.context).getStatusLine().getStatusCode(); - assertTrue("server must signal error for unknown content coding, got: " + status, status == 415); - } finally { - if (status / 2 == 100) { - delete(testUri); - } - } - } - - public void testPutGzipContentCoding() throws IOException { - String testUri = this.uri.toString() + (this.uri.toString().endsWith("/") ? "" : "/") + "testPutGzipContentCoding"; - int status = -1; - try { - byte bytes[] = "foobarfoobarfoobar".getBytes("UTF-8"); - HttpPut put = new HttpPut(testUri); - byte gzbytes[] = asGzipOctets(bytes); - assertTrue(gzbytes.length != bytes.length); - ByteArrayEntity entity = new ByteArrayEntity(gzbytes); - entity.setContentEncoding(new BasicHeader("Content-Encoding", "gzip")); - put.setEntity(entity); - status = this.client.execute(put, this.context).getStatusLine().getStatusCode(); - assertTrue("server create or signal error, got: " + status, status == 201 || status == 415); - if (status / 2 == 100) { - // check length - HttpHead head = new HttpHead(testUri); - HttpResponse response = this.client.execute(head, this.context); - assertEquals(200, response.getStatusLine().getStatusCode()); - assertEquals(bytes.length, Integer.parseInt(response.getFirstHeader("Content-Length").getValue())); - } - } finally { - if (status / 2 == 100) { - delete(testUri); - } - } - } - - public void testPropfindNoContentCoding() throws IOException, DavException { - HttpPropfind propfind = new HttpPropfind(uri, DavConstants.PROPFIND_BY_PROPERTY, 0); - HttpResponse response = this.client.execute(propfind, this.context); - int status = response.getStatusLine().getStatusCode(); - assertEquals(207, status); - List encodings = getContentCodings(response); - assertTrue("Accept should list 'gzip' but did not: " + encodings, encodings.contains("gzip")); - assertTrue("Accept should list 'deflate' but did not: " + encodings, encodings.contains("deflate")); - } - - public void testPropfindAcceptReponseEncoding() throws IOException, DavException { - HttpPropfind propfind = new HttpPropfind(uri, DavConstants.PROPFIND_BY_PROPERTY, 0); - propfind.setHeader(new BasicHeader("Accept-Encoding", "gzip;q=0.555")); - HttpResponse response = this.client.execute(propfind, this.context); - int status = response.getStatusLine().getStatusCode(); - assertEquals(207, status); - MultiStatusResponse[] responses = propfind.getResponseBodyAsMultiStatus(response).getResponses(); - assertEquals(1, responses.length); - } - - private static String PF = ""; - - public void testPropfindUnknownContentCoding() throws IOException { - HttpPropfind propfind = new HttpPropfind(uri, DavConstants.PROPFIND_BY_PROPERTY, 0); - StringEntity entity = new StringEntity(PF); - entity.setContentEncoding(new BasicHeader("Content-Encoding", "qux")); - propfind.setEntity(entity); - HttpResponse response = this.client.execute(propfind, this.context); - int status = response.getStatusLine().getStatusCode(); - assertTrue("server must signal error for unknown content coding, got: " + status, status == 415); - List encodings = getContentCodings(response); - assertTrue("Accept should list 'gzip' but did not: " + encodings, encodings.contains("gzip")); - assertTrue("Accept should list 'deflate' but did not: " + encodings, encodings.contains("deflate")); - } - - public void testPropfindGzipContentCoding() throws IOException { - HttpPropfind propfind = new HttpPropfind(uri, DavConstants.PROPFIND_BY_PROPERTY, 0); - ByteArrayEntity entity = new ByteArrayEntity(asGzipOctets(PF)); - entity.setContentEncoding(new BasicHeader("Content-Encoding", "gzip")); - propfind.setEntity(entity); - int status = this.client.execute(propfind, this.context).getStatusLine().getStatusCode(); - assertEquals(207, status); - } - - // double encoded, empty list member in field value, mixed upper/lower in - // coding name - public void testPropfindGzipContentCodingTwice() throws IOException { - HttpPropfind propfind = new HttpPropfind(uri, DavConstants.PROPFIND_BY_PROPERTY, 0); - ByteArrayEntity entity = new ByteArrayEntity(asGzipOctets(asGzipOctets(PF))); - entity.setContentEncoding(new BasicHeader("Content-Encoding", "gziP,, Gzip")); - propfind.setEntity(entity); - int status = this.client.execute(propfind, this.context).getStatusLine().getStatusCode(); - assertEquals(207, status); - } - - // double encoded, but only when encoding in header field - public void testPropfindGzipContentCodingBadSpec() throws IOException { - HttpPropfind propfind = new HttpPropfind(uri, DavConstants.PROPFIND_BY_PROPERTY, 0); - ByteArrayEntity entity = new ByteArrayEntity(asGzipOctets(asGzipOctets(PF))); - entity.setContentEncoding(new BasicHeader("Content-Encoding", "gzip")); - propfind.setEntity(entity); - int status = this.client.execute(propfind, this.context).getStatusLine().getStatusCode(); - assertEquals(400, status); - } - - public void testPropfindDeflateContentCoding() throws IOException { - HttpPropfind propfind = new HttpPropfind(uri, DavConstants.PROPFIND_BY_PROPERTY, 0); - ByteArrayEntity entity = new ByteArrayEntity(asDeflateOctets(PF)); - entity.setContentEncoding(new BasicHeader("Content-Encoding", "deflate")); - propfind.setEntity(entity); - int status = this.client.execute(propfind, this.context).getStatusLine().getStatusCode(); - assertEquals(207, status); - } - - public void testPropfindGzipDeflateContentCoding() throws IOException { - HttpPropfind propfind = new HttpPropfind(uri, DavConstants.PROPFIND_BY_PROPERTY, 0); - ByteArrayEntity entity = new ByteArrayEntity(asDeflateOctets(asGzipOctets(PF))); - entity.setContentEncoding(new BasicHeader("Content-Encoding", "gzip, deflate")); - propfind.setEntity(entity); - int status = this.client.execute(propfind, this.context).getStatusLine().getStatusCode(); - assertEquals(207, status); - } - - public void testPropfindGzipDeflateContentCodingMislabeled() throws IOException { - HttpPropfind propfind = new HttpPropfind(uri, DavConstants.PROPFIND_BY_PROPERTY, 0); - ByteArrayEntity entity = new ByteArrayEntity(asDeflateOctets(asGzipOctets(PF))); - entity.setContentEncoding(new BasicHeader("Content-Encoding", "deflate, gzip")); - propfind.setEntity(entity); - int status = this.client.execute(propfind, this.context).getStatusLine().getStatusCode(); - assertEquals(400, status); - } - - private static byte[] asGzipOctets(String input) throws IOException { - return asGzipOctets(input.getBytes("UTF-8")); - } - - private static byte[] asGzipOctets(byte[] input) throws IOException { - ByteArrayOutputStream bos = new ByteArrayOutputStream(); - OutputStream gos = new GZIPOutputStream(bos); - gos.write(input); - gos.flush(); - gos.close(); - return bos.toByteArray(); - } - - private static byte[] asDeflateOctets(String input) throws IOException { - return asDeflateOctets(input.getBytes("UTF-8")); - } - - private static byte[] asDeflateOctets(byte[] input) throws IOException { - ByteArrayOutputStream bos = new ByteArrayOutputStream(); - OutputStream gos = new DeflaterOutputStream(bos); - gos.write(input); - gos.flush(); - gos.close(); - return bos.toByteArray(); - } - - private static List getContentCodings(HttpResponse response) { - List result = Collections.emptyList(); - for (Header l : response.getHeaders("Accept-Encoding")) { - for (String h : l.getValue().split(",")) { - if (!h.trim().isEmpty()) { - if (result.isEmpty()) { - result = new ArrayList(); - } - result.add(h.trim().toLowerCase(Locale.ENGLISH)); - } - } - } - - return result; - } -} Property changes on: jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/server/ContentCodingTest.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/server/HttpsSelfSignedTest.java =================================================================== --- jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/server/HttpsSelfSignedTest.java (revision 1907912) +++ jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/server/HttpsSelfSignedTest.java (nonexistent) @@ -1,42 +0,0 @@ -/* - * 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.webdav.server; - -import java.io.IOException; -import java.text.ParseException; - -import javax.net.ssl.SSLHandshakeException; - -import org.apache.http.HttpResponse; -import org.apache.http.client.methods.HttpPut; -import org.apache.http.entity.StringEntity; - -public class HttpsSelfSignedTest extends WebDAVTestBase { - - // check that by default, the client will fail connecting to HTTPS due to - // self-signed certificate - public void testPutCheckLastModified() throws IOException, ParseException { - try { - String testUri = this.httpsUri.toString(); - HttpPut put = new HttpPut(testUri); - put.setEntity(new StringEntity("foobar")); - HttpResponse response = this.client.execute(put, this.context); - fail("should failt with SSLHandshakeException, but got: " + response); - } catch (SSLHandshakeException expected) { - } - } -} Property changes on: jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/server/HttpsSelfSignedTest.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/server/ProppatchTest.java =================================================================== --- jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/server/ProppatchTest.java (revision 1907912) +++ jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/server/ProppatchTest.java (nonexistent) @@ -1,79 +0,0 @@ -/* - * 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.webdav.server; - -import java.io.IOException; - -import org.apache.http.HttpResponse; -import org.apache.http.client.methods.HttpPut; -import org.apache.http.entity.StringEntity; -import org.apache.http.util.EntityUtils; -import org.apache.jackrabbit.webdav.DavException; -import org.apache.jackrabbit.webdav.MultiStatusResponse; -import org.apache.jackrabbit.webdav.client.methods.HttpPropfind; -import org.apache.jackrabbit.webdav.client.methods.HttpProppatch; -import org.apache.jackrabbit.webdav.property.DavProperty; -import org.apache.jackrabbit.webdav.property.DavPropertyName; -import org.apache.jackrabbit.webdav.property.DavPropertyNameSet; -import org.apache.jackrabbit.webdav.property.DavPropertySet; -import org.apache.jackrabbit.webdav.property.DefaultDavProperty; -import org.apache.jackrabbit.webdav.xml.Namespace; - -public class ProppatchTest extends WebDAVTestBase { - - public void testPropPatchSurrogate() throws IOException, DavException { - - String testuri = this.root + "ppsurrogate"; - - try { - int status; - - HttpPut put = new HttpPut(testuri); - put.setEntity(new StringEntity("1")); - status = this.client.execute(put, this.context).getStatusLine().getStatusCode(); - assertEquals("status: " + status, 201, status); - - DavPropertyName name = DavPropertyName.create("foobar", Namespace.EMPTY_NAMESPACE); - DavPropertySet props = new DavPropertySet(); - DavProperty foobar = new DefaultDavProperty<>(name, "\uD83D\uDCA9"); - props.add(foobar); - HttpProppatch proppatch = new HttpProppatch(testuri, props, new DavPropertyNameSet()); - HttpResponse resp = this.client.execute(proppatch, this.context); - status = resp.getStatusLine().getStatusCode(); - assertEquals(207, status); - EntityUtils.consume(resp.getEntity()); - - DavPropertyNameSet names = new DavPropertyNameSet(); - names.add(name); - HttpPropfind propfind = new HttpPropfind(testuri, names, 0); - resp = this.client.execute(propfind, this.context); - status = resp.getStatusLine().getStatusCode(); - assertEquals(207, status); - MultiStatusResponse[] responses = propfind.getResponseBodyAsMultiStatus(resp).getResponses(); - assertEquals(1, responses.length); - - MultiStatusResponse response = responses[0]; - DavPropertySet found = response.getProperties(200); - - DavProperty f = found.get(name); - assertEquals("\uD83D\uDCA9", f.getValue()); - } finally { - delete(testuri); - } - } - -} Property changes on: jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/server/ProppatchTest.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Deleted: svn:executable ## -1 +0,0 ## -* \ No newline at end of property Index: jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/server/PutTest.java =================================================================== --- jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/server/PutTest.java (revision 1907912) +++ jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/server/PutTest.java (nonexistent) @@ -1,40 +0,0 @@ -/* - * 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.webdav.server; - -import java.io.IOException; -import java.text.ParseException; - -import org.apache.http.HttpResponse; -import org.apache.http.client.methods.HttpPut; -import org.apache.http.entity.StringEntity; - -/** - * Test cases for HTTP PUT method - */ -public class PutTest extends WebDAVTestBase { - - public void testPutWithContentRange() throws IOException, ParseException { - String testUri = this.uri.toString() + (this.uri.toString().endsWith("/") ? "" : "/") + "testPutWithContentRange"; - HttpPut put = new HttpPut(testUri); - put.addHeader("Content-Range", "bytes 0-5/6"); - put.setEntity(new StringEntity("foobar")); - HttpResponse response = this.client.execute(put, this.context); - int status = response.getStatusLine().getStatusCode(); - assertEquals(400, status); - } -} Property changes on: jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/server/PutTest.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/server/RFC4918DestinationHeaderTest.java =================================================================== --- jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/server/RFC4918DestinationHeaderTest.java (revision 1907912) +++ jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/server/RFC4918DestinationHeaderTest.java (nonexistent) @@ -1,87 +0,0 @@ -/* - * 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.webdav.server; - -import java.io.IOException; -import java.net.URI; -import java.net.URISyntaxException; - -import org.apache.http.client.methods.HttpDelete; -import org.apache.http.client.methods.HttpHead; -import org.apache.http.client.methods.HttpPut; -import org.apache.http.client.methods.HttpRequestBase; -import org.apache.jackrabbit.webdav.client.methods.HttpMove; - -/** - * Test cases for RFC 4918 Destination header functionality - * (see RFC 4918, Section 10.3 - */ -public class RFC4918DestinationHeaderTest extends WebDAVTestBase { - - public void testMove() throws IOException, URISyntaxException { - - String testuri = this.root + "movetest"; - String destinationuri = testuri + "2"; - String destinationpath = new URI(destinationuri).getRawPath(); - // make sure the scheme is removed - assertFalse(destinationpath.contains(":")); - - HttpRequestBase requestBase = null; - try { - requestBase = new HttpPut(testuri); - int status = this.client.execute(requestBase, this.context).getStatusLine().getStatusCode(); - assertTrue("status: " + status, status == 200 || status == 201 || status == 204); - requestBase.releaseConnection(); - - // try to move outside the servlet's name space - requestBase = new HttpMove(testuri, "/foobar", true); - status = this.client.execute(requestBase, this.context).getStatusLine().getStatusCode(); - assertTrue("status: " + status, status == 502); - requestBase.releaseConnection(); - - // try a relative path - requestBase = new HttpMove(testuri, "foobar", true); - status = this.client.execute(requestBase, this.context).getStatusLine().getStatusCode(); - assertTrue("status: " + status, status == 400); - requestBase.releaseConnection(); - - requestBase = new HttpMove(testuri, destinationpath, true); - status = this.client.execute(requestBase, this.context).getStatusLine().getStatusCode(); - assertTrue("status: " + status, status == 200 || status == 201 || status == 204); - requestBase.releaseConnection(); - - requestBase = new HttpHead(destinationuri); - status = this.client.execute(requestBase, this.context).getStatusLine().getStatusCode(); - assertTrue("status: " + status, status == 200); - requestBase.releaseConnection(); - - requestBase = new HttpHead(testuri); - status = this.client.execute(requestBase, this.context).getStatusLine().getStatusCode(); - assertTrue("status: " + status, status == 404); - } finally { - requestBase.releaseConnection(); - requestBase = new HttpDelete(testuri); - int status = this.client.execute(requestBase, this.context).getStatusLine().getStatusCode(); - assertTrue("status: " + status, status == 200 || status == 204 || status == 404); - requestBase.releaseConnection(); - requestBase = new HttpDelete(destinationuri); - status = this.client.execute(requestBase, this.context).getStatusLine().getStatusCode(); - assertTrue("status: " + status, status == 200 || status == 204 || status == 404); - requestBase.releaseConnection(); - } - } -} Property changes on: jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/server/RFC4918DestinationHeaderTest.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/server/RFC4918IfHeaderTest.java =================================================================== --- jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/server/RFC4918IfHeaderTest.java (revision 1907912) +++ jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/server/RFC4918IfHeaderTest.java (nonexistent) @@ -1,143 +0,0 @@ -/* - * 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.webdav.server; - -import java.io.IOException; -import java.net.URI; -import java.net.URISyntaxException; - -import org.apache.http.HttpResponse; -import org.apache.http.client.methods.HttpDelete; -import org.apache.http.client.methods.HttpPut; -import org.apache.http.client.methods.HttpRequestBase; -import org.apache.http.entity.StringEntity; -import org.apache.jackrabbit.webdav.client.methods.HttpLock; -import org.apache.jackrabbit.webdav.lock.LockInfo; -import org.apache.jackrabbit.webdav.lock.Scope; -import org.apache.jackrabbit.webdav.lock.Type; - -/** - * Test cases for RFC 4918 If header functionality - * (see RFC 4918, Section 10.4 - */ - -public class RFC4918IfHeaderTest extends WebDAVTestBase { - - public void testPutIfEtag() throws IOException { - - String testuri = this.root + "iftest"; - HttpPut put = new HttpPut(testuri); - try { - put = new HttpPut(testuri); - String condition = "<" + testuri + "> ([" + "\"an-etag-this-testcase-invented\"" + "])"; - put.setEntity(new StringEntity("1")); - put.setHeader("If", condition); - int status = this.client.execute(put, this.context).getStatusLine().getStatusCode(); - assertEquals("status: " + status, 412, status); - put.releaseConnection(); - - } - finally { - put.releaseConnection(); - HttpDelete delete = new HttpDelete(testuri); - int status = this.client.execute(delete, this.context).getStatusLine().getStatusCode(); - assertTrue("status: " + status, status == 200 || status == 204 || status == 404); - delete.releaseConnection(); - } - } - - public void testPutIfLockToken() throws IOException, URISyntaxException { - - String testuri = this.root + "iflocktest"; - String locktoken = null; - - HttpRequestBase requestBase = null; - try { - requestBase = new HttpPut(testuri); - ((HttpPut)requestBase).setEntity(new StringEntity("1")); - int status = this.client.execute(requestBase, this.context).getStatusLine().getStatusCode(); - assertTrue("status: " + status, status == 200 || status == 201 || status == 204); - requestBase.releaseConnection(); - - requestBase = new HttpLock(testuri, new LockInfo( - Scope.EXCLUSIVE, Type.WRITE, "testcase", 10000, true)); - HttpResponse response = this.client.execute(requestBase, this.context); - status = response.getStatusLine().getStatusCode(); - assertEquals("status", 200, status); - locktoken = ((HttpLock)requestBase).getLockToken(response); - assertNotNull(locktoken); - requestBase.releaseConnection(); - - // try to overwrite without lock token - requestBase = new HttpPut(testuri); - ((HttpPut)requestBase).setEntity(new StringEntity("2")); - status = this.client.execute(requestBase, this.context).getStatusLine().getStatusCode(); - assertEquals("status: " + status, 423, status); - requestBase.releaseConnection(); - - // try to overwrite using bad lock token - requestBase = new HttpPut(testuri); - ((HttpPut)requestBase).setEntity(new StringEntity("2")); - requestBase.setHeader("If", "(<" + "DAV:foobar" + ">)"); - status = this.client.execute(requestBase, this.context).getStatusLine().getStatusCode(); - assertEquals("status: " + status, 412, status); - requestBase.releaseConnection(); - - // try to overwrite using correct lock token, using No-Tag-list format - requestBase = new HttpPut(testuri); - ((HttpPut)requestBase).setEntity(new StringEntity("2")); - requestBase.setHeader("If", "(<" + locktoken + ">)"); - status = this.client.execute(requestBase, this.context).getStatusLine().getStatusCode(); - assertTrue("status: " + status, status == 200 || status == 204); - requestBase.releaseConnection(); - - // try to overwrite using correct lock token, using Tagged-list format - // and full URI - requestBase = new HttpPut(testuri); - ((HttpPut)requestBase).setEntity(new StringEntity("3")); - requestBase.setHeader("If", "<" + testuri + ">" + "(<" + locktoken + ">)"); - status = this.client.execute(requestBase, this.context).getStatusLine().getStatusCode(); - assertTrue("status: " + status, status == 200 || status == 204); - requestBase.releaseConnection(); - - // try to overwrite using correct lock token, using Tagged-list format - // and absolute path only - requestBase = new HttpPut(testuri); - ((HttpPut)requestBase).setEntity(new StringEntity("4")); - requestBase.setHeader("If", "<" + new URI(testuri).getRawPath() + ">" + "(<" + locktoken + ">)"); - status = this.client.execute(requestBase, this.context).getStatusLine().getStatusCode(); - assertTrue("status: " + status, status == 200 || status == 204); - requestBase.releaseConnection(); - - // try to overwrite using correct lock token, using Tagged-list format - // and bad path - requestBase = new HttpPut(testuri); - ((HttpPut)requestBase).setEntity(new StringEntity("5")); - requestBase.setHeader("If", "" + "(<" + locktoken + ">)"); - status = this.client.execute(requestBase, this.context).getStatusLine().getStatusCode(); - assertTrue("status: " + status, status == 404 || status == 412); - } finally { - requestBase.releaseConnection(); - requestBase = new HttpDelete(testuri); - if (locktoken != null) { - requestBase.setHeader("If", "(<" + locktoken + ">)"); - } - int status = this.client.execute(requestBase, this.context).getStatusLine().getStatusCode(); - assertTrue("status: " + status, status == 200 || status == 204 || status == 404); - } - } -} Property changes on: jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/server/RFC4918IfHeaderTest.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/server/RFC4918PropfindTest.java =================================================================== --- jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/server/RFC4918PropfindTest.java (revision 1907912) +++ jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/server/RFC4918PropfindTest.java (nonexistent) @@ -1,78 +0,0 @@ -/* - * 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.webdav.server; - -import java.io.IOException; - -import org.apache.http.HttpResponse; -import org.apache.http.client.methods.HttpPut; -import org.apache.http.entity.StringEntity; -import org.apache.jackrabbit.webdav.DavConstants; -import org.apache.jackrabbit.webdav.DavException; -import org.apache.jackrabbit.webdav.MultiStatus; -import org.apache.jackrabbit.webdav.MultiStatusResponse; -import org.apache.jackrabbit.webdav.client.methods.HttpOptions; -import org.apache.jackrabbit.webdav.client.methods.HttpPropfind; -import org.apache.jackrabbit.webdav.property.DavPropertyNameSet; -import org.apache.jackrabbit.webdav.property.DavPropertySet; -import org.apache.jackrabbit.webdav.version.DeltaVConstants; - -/** - * Test cases for RFC 4918 PROPFIND functionality - * (see RFC 4918, Section 9.1 - */ - -public class RFC4918PropfindTest extends WebDAVTestBase { - - public void testOptions() throws IOException { - HttpOptions options = new HttpOptions(this.root); - HttpResponse response = this.client.execute(options, this.context); - assertTrue(options.getDavComplianceClasses(response).contains("3")); - } - - public void testPropfindInclude() throws IOException, DavException { - - String testuri = this.root + "iftest"; - - int status; - try { - HttpPut put = new HttpPut(testuri); - put.setEntity(new StringEntity("1")); - status = this.client.execute(put, this.context).getStatusLine().getStatusCode(); - assertEquals("status: " + status, 201, status); - - DavPropertyNameSet names = new DavPropertyNameSet(); - names.add(DeltaVConstants.COMMENT); - HttpPropfind propfind = new HttpPropfind(testuri, DavConstants.PROPFIND_ALL_PROP_INCLUDE, names, 0); - HttpResponse resp = this.client.execute(propfind, this.context); - status = resp.getStatusLine().getStatusCode(); - assertEquals(207, status); - - MultiStatus multistatus = propfind.getResponseBodyAsMultiStatus(resp); - MultiStatusResponse[] responses = multistatus.getResponses(); - assertEquals(1, responses.length); - - MultiStatusResponse response = responses[0]; - DavPropertySet found = response.getProperties(200); - DavPropertySet notfound = response.getProperties(404); - - assertTrue(found.contains(DeltaVConstants.COMMENT) || notfound.contains(DeltaVConstants.COMMENT)); - } finally { - delete(testuri); - } - } -} Property changes on: jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/server/RFC4918PropfindTest.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/server/RemotingTest.java =================================================================== --- jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/server/RemotingTest.java (revision 1907912) +++ jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/server/RemotingTest.java (nonexistent) @@ -1,60 +0,0 @@ -/* - * 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.webdav.server; - -import java.io.IOException; - -import org.apache.http.HttpResponse; -import org.apache.jackrabbit.webdav.DavConstants; -import org.apache.jackrabbit.webdav.DavException; -import org.apache.jackrabbit.webdav.MultiStatus; -import org.apache.jackrabbit.webdav.MultiStatusResponse; -import org.apache.jackrabbit.webdav.client.methods.HttpPropfind; -import org.apache.jackrabbit.webdav.observation.ObservationConstants; -import org.apache.jackrabbit.webdav.property.DavProperty; -import org.apache.jackrabbit.webdav.property.DavPropertyName; -import org.apache.jackrabbit.webdav.property.DavPropertyNameSet; -import org.apache.jackrabbit.webdav.property.DavPropertySet; -import org.apache.jackrabbit.webdav.xml.DomUtil; -import org.w3c.dom.Element; - -public class RemotingTest extends WebDAVTestBase { - - // simple test the verifies that we are indeed talking to the remoting - // servlet - public void testRoot() throws IOException, DavException { - String testuri = this.remotingUri.toASCIIString() + "default/jcr:root"; - DavPropertyName pntn = DavPropertyName.create("primarynodetype", ObservationConstants.NAMESPACE); - DavPropertyNameSet names = new DavPropertyNameSet(); - names.add(pntn); - - HttpPropfind propfind = new HttpPropfind(testuri, DavConstants.PROPFIND_BY_PROPERTY, names, 0); - HttpResponse resp = this.client.execute(propfind, this.context); - int status = resp.getStatusLine().getStatusCode(); - assertEquals(207, status); - - MultiStatus multistatus = propfind.getResponseBodyAsMultiStatus(resp); - MultiStatusResponse[] responses = multistatus.getResponses(); - assertEquals(1, responses.length); - - MultiStatusResponse response = responses[0]; - DavPropertySet found = response.getProperties(200); - DavProperty pnt = found.get(pntn); - Element el = (Element) pnt.getValue(); - assertEquals("rep:root", DomUtil.getText((Element) (el.getFirstChild()))); - } -} Property changes on: jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/server/RemotingTest.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/server/WebDAVTestBase.java =================================================================== --- jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/server/WebDAVTestBase.java (revision 1907912) +++ jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/server/WebDAVTestBase.java (nonexistent) @@ -1,238 +0,0 @@ -/* - * 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.webdav.server; - -import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.net.URI; - -import javax.jcr.Repository; -import javax.servlet.ServletException; - -import org.apache.commons.io.IOUtils; -import org.apache.http.HttpHost; -import org.apache.http.auth.AuthScope; -import org.apache.http.auth.UsernamePasswordCredentials; -import org.apache.http.client.AuthCache; -import org.apache.http.client.CredentialsProvider; -import org.apache.http.client.HttpClient; -import org.apache.http.client.methods.HttpDelete; -import org.apache.http.client.protocol.HttpClientContext; -import org.apache.http.impl.auth.BasicScheme; -import org.apache.http.impl.client.BasicAuthCache; -import org.apache.http.impl.client.BasicCredentialsProvider; -import org.apache.http.impl.client.HttpClients; -import org.apache.http.impl.conn.PoolingHttpClientConnectionManager; -import org.apache.jackrabbit.core.RepositoryContext; -import org.apache.jackrabbit.core.config.RepositoryConfig; -import org.apache.jackrabbit.server.remoting.davex.JcrRemotingServlet; -import org.apache.jackrabbit.test.AbstractJCRTest; -import org.apache.jackrabbit.test.RepositoryStubException; -import org.apache.jackrabbit.webdav.simple.SimpleWebdavServlet; -import org.eclipse.jetty.http.HttpVersion; -import org.eclipse.jetty.server.HttpConfiguration; -import org.eclipse.jetty.server.HttpConnectionFactory; -import org.eclipse.jetty.server.Server; -import org.eclipse.jetty.server.ServerConnector; -import org.eclipse.jetty.server.SslConnectionFactory; -import org.eclipse.jetty.servlet.ServletContextHandler; -import org.eclipse.jetty.servlet.ServletHolder; -import org.eclipse.jetty.util.resource.Resource; -import org.eclipse.jetty.util.ssl.SslContextFactory; - -import junit.framework.TestResult; - -/** - * Base class for WebDAV tests. - */ -public class WebDAVTestBase extends AbstractJCRTest { - - private static final String SIMPLE_WEBDAV_SERVLET_PATH_MAPPING = "/*"; - private static final String REMOTING_PREFIX = "/remoting"; - private static final String REMOTING_WEBDAV_SERVLET_PATH_MAPPING = REMOTING_PREFIX + "/*"; - - private static ServerConnector httpConnector; - private static ServerConnector httpsConnector; - private static Server server; - private static RepositoryContext repoContext; - - public URI uri; - public URI httpsUri; - public String root; - - // URI for remoting servlet, does not include workspace name - public URI remotingUri; - - public HttpClient client; - public HttpClientContext context; - - private static final String KEYSTORE = "keystore"; - private static final String KEYSTOREPW = "geheimer"; - - protected void setUp() throws Exception { - super.setUp(); - - File home = new File("target/jackrabbit-repository"); - if (!home.exists()) { - home.mkdirs(); - } - - File config = new File(home, "repository.xml"); - if (!config.exists()) { - createDefaultConfiguration(config); - } - - File keystore = new File(home, KEYSTORE); - if (!keystore.exists()) { - createKeystore(keystore); - } - - if (repoContext == null) { - repoContext = RepositoryContext.create(RepositoryConfig.create(config.toURI(), home.getPath())); - } - - if (server == null) { - server = new Server(); - - ServletHolder simple = new ServletHolder(new SimpleWebdavServlet() { - private static final long serialVersionUID = 8638589328461138178L; - - public Repository getRepository() { - return repoContext.getRepository(); - } - }); - simple.setInitParameter(SimpleWebdavServlet.INIT_PARAM_RESOURCE_CONFIG, "/config.xml"); - - ServletHolder remoting = new ServletHolder(new JcrRemotingServlet() { - private static final long serialVersionUID = -2969534124090379387L; - - public Repository getRepository() { - return repoContext.getRepository(); - } - }); - remoting.setInitParameter(JcrRemotingServlet.INIT_PARAM_RESOURCE_PATH_PREFIX, "/remoting"); - - ServletContextHandler schandler = new ServletContextHandler(server, "/"); - schandler.addServlet(simple, SIMPLE_WEBDAV_SERVLET_PATH_MAPPING); - schandler.addServlet(remoting, REMOTING_WEBDAV_SERVLET_PATH_MAPPING); - schandler.setBaseResource(Resource.newClassPathResource("/")); - - server.setHandler(schandler); - } - - if (httpConnector == null) { - httpConnector = new ServerConnector(server); - httpConnector.setHost("localhost"); - httpConnector.setPort(0); - server.addConnector(httpConnector); - } - - if (httpsConnector == null) { - SslContextFactory sslContextFactory = new SslContextFactory(); - sslContextFactory.setKeyStorePath(keystore.getPath()); - sslContextFactory.setKeyStorePassword(KEYSTOREPW); - sslContextFactory.setKeyManagerPassword(KEYSTOREPW); - sslContextFactory.setTrustStorePath(keystore.getPath()); - sslContextFactory.setTrustStorePassword(KEYSTOREPW); - SslConnectionFactory cfac = new SslConnectionFactory(sslContextFactory, HttpVersion.HTTP_1_1.asString()); - httpsConnector = new ServerConnector(server, cfac, new HttpConnectionFactory(new HttpConfiguration())); - httpsConnector.setHost("localhost"); - httpsConnector.setPort(0); - server.addConnector(httpsConnector); - } - - if (!server.isStarted()) { - try { - server.start(); - } catch (Exception e) { - throw new RepositoryStubException(e); - } - } - - this.uri = new URI("http", null, "localhost", httpConnector.getLocalPort(), "/default/", null, null); - this.remotingUri = new URI("http", null, "localhost", httpConnector.getLocalPort(), REMOTING_PREFIX + "/", null, null); - this.httpsUri = new URI("https", null, "localhost", httpsConnector.getLocalPort(), "/default/", null, null); - this.root = this.uri.toASCIIString(); - - PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager(); - //cm.setMaxTotal(100); - HttpHost targetHost = new HttpHost(uri.getHost(), uri.getPort()); - - CredentialsProvider credsProvider = new BasicCredentialsProvider(); - credsProvider.setCredentials( - new AuthScope(targetHost.getHostName(), targetHost.getPort()), - new UsernamePasswordCredentials("admin", "admin")); - - AuthCache authCache = new BasicAuthCache(); - // Generate BASIC scheme object and add it to the local auth cache - BasicScheme basicAuth = new BasicScheme(); - authCache.put(targetHost, basicAuth); - - // Add AuthCache to the execution context - this.context = HttpClientContext.create(); - this.context.setCredentialsProvider(credsProvider); - this.context.setAuthCache(authCache); - - this.client = HttpClients.custom().setConnectionManager(cm).build(); - - super.setUp(); - } - - protected void delete(String uri) throws IOException { - HttpDelete delete = new HttpDelete(uri); - int status = this.client.execute(delete, this.context).getStatusLine().getStatusCode(); - assertTrue("status: " + status, status == 200 || status == 204); - } - - public static Server getServer() { - return server; - } - - /** - * 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); - InputStream input = WebDAVTestBase.class.getResourceAsStream("/repository.xml")) { - IOUtils.copy(input, output); - } catch (IOException e) { - throw new ServletException("Failed to copy default configuration: " + config, e); - } - } - - private void createKeystore(File keystore) throws ServletException { - try (OutputStream output = new FileOutputStream(keystore); - InputStream input = WebDAVTestBase.class.getResourceAsStream("/" + KEYSTORE)) { - IOUtils.copy(input, output); - } catch (IOException e) { - throw new ServletException("Failed to copy keystore: " + keystore, e); - } - } - - @Override - public void run(TestResult testResult) { - if (Boolean.getBoolean("jackrabbit.test.integration")) { - super.run(testResult); - } - } -} Property changes on: jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/server/WebDAVTestBase.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/simple/LitmusTest.java =================================================================== --- jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/simple/LitmusTest.java (revision 1907912) +++ jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/simple/LitmusTest.java (nonexistent) @@ -1,130 +0,0 @@ -/* - * 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.webdav.simple; - -import java.io.ByteArrayOutputStream; -import java.io.File; - -import javax.jcr.Repository; -import javax.jcr.Session; - -import junit.framework.TestCase; - -import org.apache.commons.io.IOUtils; -import org.apache.jackrabbit.commons.JcrUtils; -import org.apache.jackrabbit.util.Text; -import org.eclipse.jetty.server.Server; -import org.eclipse.jetty.server.ServerConnector; -import org.eclipse.jetty.servlet.ServletContextHandler; -import org.eclipse.jetty.servlet.ServletHolder; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public class LitmusTest extends TestCase { - - /** - * Logger instance. - */ - private static final Logger log = LoggerFactory.getLogger(LitmusTest.class); - - public void testLitmus() throws Exception { - File dir = new File("target", "litmus"); - String litmus = System.getProperty("litmus", "litmus"); - - if (Boolean.getBoolean("jackrabbit.test.integration") - && isLitmusAvailable(litmus)) { - final Repository repository = JcrUtils.getRepository( - "jcr-jackrabbit://" + Text.escapePath(dir.getCanonicalPath())); - Session session = repository.login(); // for the TransientRepository - try { - Server server = new Server(); - - ServerConnector connector = new ServerConnector(server); - connector.setHost("localhost"); - connector.setPort(Integer.getInteger("litmus.port", 0)); - - server.addConnector(connector); - - ServletHolder holder = new ServletHolder( - new SimpleWebdavServlet() { - @Override - public Repository getRepository() { - return repository; - } - }); - holder.setInitParameter("resource-config", "/config.xml"); - - ServletContextHandler schandler = new ServletContextHandler(server, "/"); - schandler.addServlet(holder, "/*"); - - server.start(); - try { - int port = connector.getLocalPort(); - String url = "http://localhost:" + port + "/default"; - - ProcessBuilder builder = - new ProcessBuilder(litmus, url, "admin", "admin"); - builder.directory(dir); - builder.redirectErrorStream(); - - assertLitmus(builder, "basic", 0); - - assertLitmus(builder, "http", 0); - - assertLitmus(builder, "props", 0); - - // FIXME: JCR-2637: WebDAV shallow copy test failure - assertLitmus(builder, "copymove", 1); - - // FIXME: JCR-2638: Litmus locks test failures - assertLitmus(builder, "locks", 1); - } finally { - server.stop(); - } - } finally { - session.logout(); - } - } - } - - private void assertLitmus( - ProcessBuilder builder, String tests, int exit) throws Exception { - builder.environment().put("TESTS", tests); - Process process = builder.start(); - IOUtils.copy(process.getInputStream(), System.out); - assertEquals(exit, process.waitFor()); - } - - private static boolean isLitmusAvailable(String litmus) { - try { - ProcessBuilder builder = new ProcessBuilder(litmus, "--version"); - builder.redirectErrorStream(); - Process process = builder.start(); - - ByteArrayOutputStream buffer = new ByteArrayOutputStream(); - IOUtils.copy(process.getInputStream(), buffer); - int rv = process.waitFor(); - log.info("litmus version: {}", buffer.toString("US-ASCII").trim()); - - return rv == 0; - } catch (Exception e) { - log.warn("litmus is not available: " + litmus, e); - return false; - } - } - -} Property changes on: jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/simple/LitmusTest.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/simple/LocatorFactoryImplExTest.java =================================================================== --- jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/simple/LocatorFactoryImplExTest.java (revision 1907912) +++ jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/simple/LocatorFactoryImplExTest.java (nonexistent) @@ -1,53 +0,0 @@ -/* - * 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.webdav.simple; - -import junit.framework.TestCase; -import org.apache.jackrabbit.webdav.DavLocatorFactory; -import org.apache.jackrabbit.webdav.DavResourceLocator; - -/** LocatorFactoryImplExTest... */ -public class LocatorFactoryImplExTest extends TestCase { - - private DavLocatorFactory factory; - - @Override - protected void setUp() throws Exception { - super.setUp(); - // for simplicity (not yet used) ignore the path prefix. - factory = new LocatorFactoryImplEx(null); - } - - /** - * Test for issue https://issues.apache.org/jira/browse/JCR-1679: An top - * level resource (node directly below the root) whose name equals the - * workspace name results in wrong collection behaviour (garbeled locator - * of child resources). - */ - public void testCollectionNameEqualsWorkspaceName() { - String prefix = "http://localhost:8080/jackrabbit/repository"; - String workspacePath = "/default"; - String nodePath = "/default/another"; - - DavResourceLocator locator = factory.createResourceLocator(prefix, workspacePath, nodePath, false); - assertTrue(locator.getHref(true).indexOf("/default/default") > 0); - - DavResourceLocator locator2 = factory.createResourceLocator(locator.getPrefix(), locator.getWorkspacePath(), locator.getResourcePath()); - assertEquals(locator, locator2); - assertEquals(nodePath, locator2.getRepositoryPath()); - } -} Property changes on: jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/simple/LocatorFactoryImplExTest.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Deleted: svn:keywords ## -1 +0,0 ## -author date id revision url \ No newline at end of property Index: jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/simple/ResourceConfigTest.java =================================================================== --- jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/simple/ResourceConfigTest.java (revision 1907912) +++ jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/simple/ResourceConfigTest.java (nonexistent) @@ -1,114 +0,0 @@ -/* - * 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.webdav.simple; - -import junit.framework.TestCase; -import org.apache.jackrabbit.server.io.DefaultHandler; -import org.apache.jackrabbit.server.io.IOHandler; -import org.apache.jackrabbit.server.io.IOManager; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.ByteArrayInputStream; -import java.io.InputStream; - -/** - * ResourceConfigTest... - */ -public class ResourceConfigTest extends TestCase { - - /** - * logger instance - */ - private static final Logger log = LoggerFactory.getLogger(ResourceConfigTest.class); - - public void testIOManagerConfig() throws Exception { - InputStream in = new ByteArrayInputStream(CONFIG_1.getBytes("UTF-8")); - - ResourceConfig config = new ResourceConfig(null); - config.parse(in); - - IOManager ioMgr = config.getIOManager(); - assertNotNull(ioMgr); - assertEquals("org.apache.jackrabbit.server.io.IOManagerImpl", ioMgr.getClass().getName()); - - IOHandler[] handlers = ioMgr.getIOHandlers(); - assertNotNull(handlers); - assertEquals(1, handlers.length); - assertEquals("org.apache.jackrabbit.server.io.DefaultHandler", handlers[0].getName()); - } - - public void testIOManagerConfigWithParam() throws Exception { - InputStream in = new ByteArrayInputStream(CONFIG_2.getBytes("UTF-8")); - - ResourceConfig config = new ResourceConfig(null); - config.parse(in); - - IOManager ioMgr = config.getIOManager(); - assertNotNull(ioMgr); - assertEquals("org.apache.jackrabbit.server.io.IOManagerImpl", ioMgr.getClass().getName()); - - IOHandler[] handlers = ioMgr.getIOHandlers(); - assertNotNull(handlers); - assertEquals(1, handlers.length); - assertEquals("org.apache.jackrabbit.server.io.DefaultHandler", handlers[0].getName()); - DefaultHandler dh = (DefaultHandler) handlers[0]; - assertEquals("nt:unstructured", dh.getCollectionNodeType()); - assertEquals("nt:unstructured", dh.getNodeType()); - assertEquals("nt:resource", dh.getContentNodeType()); - } - - - private static final String CONFIG_1 = "\n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " " + - ""; - - private static final String CONFIG_2 = "\n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " " + - ""; -} \ No newline at end of file Property changes on: jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/simple/ResourceConfigTest.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Deleted: svn:keywords ## -1 +0,0 ## -Author Date Id Revision Rev URL \ No newline at end of property Index: jackrabbit-jcr-server/src/test/resources/config.xml =================================================================== --- jackrabbit-jcr-server/src/test/resources/config.xml (revision 1907912) +++ jackrabbit-jcr-server/src/test/resources/config.xml (nonexistent) @@ -1,184 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - nt:file - nt:resource - - - - - - - - - - - - - rep - jcr - - - - - - Property changes on: jackrabbit-jcr-server/src/test/resources/config.xml ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-jcr-server/src/test/resources/keystore =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Property changes on: jackrabbit-jcr-server/src/test/resources/keystore ___________________________________________________________________ Deleted: svn:executable ## -1 +0,0 ## -* \ No newline at end of property Deleted: svn:mime-type ## -1 +0,0 ## -application/octet-stream \ No newline at end of property Index: jackrabbit-jcr-server/src/test/resources/logback-test.xml =================================================================== --- jackrabbit-jcr-server/src/test/resources/logback-test.xml (revision 1907912) +++ jackrabbit-jcr-server/src/test/resources/logback-test.xml (nonexistent) @@ -1,31 +0,0 @@ - - - - - - target/jcr.log - - %date{HH:mm:ss.SSS} %-5level %-40([%thread] %F:%L) %msg%n - - - - - - - - Property changes on: jackrabbit-jcr-server/src/test/resources/logback-test.xml ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-jcr-server/src/test/resources/protectedHandlers.properties =================================================================== --- jackrabbit-jcr-server/src/test/resources/protectedHandlers.properties (revision 1907912) +++ jackrabbit-jcr-server/src/test/resources/protectedHandlers.properties (nonexistent) @@ -1,17 +0,0 @@ -# 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. - -# ProtectedItemRemoveHandler implementation class -javax.jcr.tck.access.control.list.handler=org.apache.jackrabbit.server.remoting.davex.AclRemoveHandler Index: jackrabbit-jcr-server/src/test/resources/protectedHandlersConfig.xml =================================================================== --- jackrabbit-jcr-server/src/test/resources/protectedHandlersConfig.xml (revision 1907912) +++ jackrabbit-jcr-server/src/test/resources/protectedHandlersConfig.xml (nonexistent) @@ -1,26 +0,0 @@ - - - - - - - - Property changes on: jackrabbit-jcr-server/src/test/resources/protectedHandlersConfig.xml ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-jcr-server/src/test/resources/repository.xml =================================================================== --- jackrabbit-jcr-server/src/test/resources/repository.xml (revision 1907912) +++ jackrabbit-jcr-server/src/test/resources/repository.xml (nonexistent) @@ -1,166 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Property changes on: jackrabbit-jcr-server/src/test/resources/repository.xml ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-jcr-server/src/test/resources/repositoryStubImpl.properties =================================================================== --- jackrabbit-jcr-server/src/test/resources/repositoryStubImpl.properties (revision 1907912) +++ jackrabbit-jcr-server/src/test/resources/repositoryStubImpl.properties (nonexistent) @@ -1,23 +0,0 @@ -# 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. - -# Stub implementation class -javax.jcr.tck.repository_stub_impl=org.apache.jackrabbit.core.JackrabbitRepositoryStub - -# the repository home -org.apache.jackrabbit.repository.home=target/repository - -# the repository configuration -org.apache.jackrabbit.repository.config=target/test-classes/repository.xml Property changes on: jackrabbit-jcr-server/src/test/resources/repositoryStubImpl.properties ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-jcr-server =================================================================== --- jackrabbit-jcr-server (revision 1907912) +++ jackrabbit-jcr-server (nonexistent) Property changes on: jackrabbit-jcr-server ___________________________________________________________________ Deleted: svn:ignore ## -1,5 +0,0 ## -*.iml -*.ipr -*.iws -target -.* Index: jackrabbit-jcr-servlet-project/jackrabbit-jcr-servlet-jakarta/pom.xml =================================================================== --- jackrabbit-jcr-servlet-project/jackrabbit-jcr-servlet-jakarta/pom.xml (nonexistent) +++ jackrabbit-jcr-servlet-project/jackrabbit-jcr-servlet-jakarta/pom.xml (working copy) @@ -0,0 +1,83 @@ + + 4.0.0 + + org.apache.jackrabbit + jackrabbit-jcr-servlet-project + 2.21.16-SNAPSHOT + + jackrabbit-jcr-servlet-jakarta + + + + org.eclipse.transformer + transformer-maven-plugin + 0.5.0 + true + + + true + + + + + default-jar + + jar + + + + org.apache.jackrabbit + jackrabbit-jcr-servlet + ${project.version} + + + + + + + + + + apache-release + + + + org.eclipse.transformer + transformer-maven-plugin + 0.5.0 + true + + + true + + + + + source-jar + + jar + + + + org.apache.jackrabbit + jackrabbit-jcr-servlet + ${project.version} + sources + + + + + + + + + + + + jakarta.servlet + jakarta.servlet-api + 5.0.0 + provided + + + \ No newline at end of file Index: pom.xml =================================================================== --- pom.xml (revision 1907912) +++ pom.xml (working copy) @@ -43,11 +43,11 @@ jackrabbit-aws-ext jackrabbit-vfs-ext jackrabbit-core - jackrabbit-webdav - jackrabbit-jcr-server + jackrabbit-webdav-project + jackrabbit-jcr-server-project jackrabbit-jcr-rmi - jackrabbit-jcr-servlet - jackrabbit-webapp + jackrabbit-jcr-servlet-project + jackrabbit-webapp-project jackrabbit-jca jackrabbit-spi jackrabbit-spi-commons Index: jackrabbit-webapp-project/jackrabbit-webapp-jakarta/.classpath =================================================================== --- jackrabbit-webapp-project/jackrabbit-webapp-jakarta/.classpath (nonexistent) +++ jackrabbit-webapp-project/jackrabbit-webapp-jakarta/.classpath (working copy) @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Index: jackrabbit-webapp-project/jackrabbit-webapp-jakarta/.project =================================================================== --- jackrabbit-webapp-project/jackrabbit-webapp-jakarta/.project (nonexistent) +++ jackrabbit-webapp-project/jackrabbit-webapp-jakarta/.project (working copy) @@ -0,0 +1,23 @@ + + + jackrabbit-webapp-jakarta + + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.m2e.core.maven2Builder + + + + + + org.eclipse.jdt.core.javanature + org.eclipse.m2e.core.maven2Nature + + Index: jackrabbit-webapp-project/jackrabbit-webapp-jakarta/.settings/org.eclipse.core.resources.prefs =================================================================== --- jackrabbit-webapp-project/jackrabbit-webapp-jakarta/.settings/org.eclipse.core.resources.prefs (nonexistent) +++ jackrabbit-webapp-project/jackrabbit-webapp-jakarta/.settings/org.eclipse.core.resources.prefs (working copy) @@ -0,0 +1,6 @@ +eclipse.preferences.version=1 +encoding//src/main/java=UTF-8 +encoding//src/main/resources=UTF-8 +encoding//src/test/java=UTF-8 +encoding//src/test/resources=UTF-8 +encoding/=UTF-8 Index: jackrabbit-webapp-project/jackrabbit-webapp-jakarta/.settings/org.eclipse.jdt.core.prefs =================================================================== --- jackrabbit-webapp-project/jackrabbit-webapp-jakarta/.settings/org.eclipse.jdt.core.prefs (nonexistent) +++ jackrabbit-webapp-project/jackrabbit-webapp-jakarta/.settings/org.eclipse.jdt.core.prefs (working copy) @@ -0,0 +1,8 @@ +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 +org.eclipse.jdt.core.compiler.compliance=1.8 +org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled +org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning +org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=ignore +org.eclipse.jdt.core.compiler.release=disabled +org.eclipse.jdt.core.compiler.source=1.8 Index: jackrabbit-webapp-project/jackrabbit-webapp-jakarta/.settings/org.eclipse.m2e.core.prefs =================================================================== --- jackrabbit-webapp-project/jackrabbit-webapp-jakarta/.settings/org.eclipse.m2e.core.prefs (nonexistent) +++ jackrabbit-webapp-project/jackrabbit-webapp-jakarta/.settings/org.eclipse.m2e.core.prefs (working copy) @@ -0,0 +1,4 @@ +activeProfiles= +eclipse.preferences.version=1 +resolveWorkspaceProjects=true +version=1 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-webapp-project/jackrabbit-webapp-jakarta/target/.plxarc =================================================================== --- jackrabbit-webapp-project/jackrabbit-webapp-jakarta/target/.plxarc (nonexistent) +++ jackrabbit-webapp-project/jackrabbit-webapp-jakarta/target/.plxarc (working copy) @@ -0,0 +1 @@ +maven-shared-archive-resources \ No newline at end of file Index: jackrabbit-webapp-project/jackrabbit-webapp-jakarta/target/classes/META-INF/DEPENDENCIES =================================================================== --- jackrabbit-webapp-project/jackrabbit-webapp-jakarta/target/classes/META-INF/DEPENDENCIES (nonexistent) +++ jackrabbit-webapp-project/jackrabbit-webapp-jakarta/target/classes/META-INF/DEPENDENCIES (working copy) @@ -0,0 +1,253 @@ +// ------------------------------------------------------------------ +// Transitive dependencies of this project determined from the +// maven pom organized by organization. +// ------------------------------------------------------------------ + +jackrabbit-webapp-jakarta + + +From: 'an unknown organization' + - parso (https://github.com/epam/parso) com.epam:parso:jar:2.0.14 + License: Apache License v2 (http://www.apache.org/licenses/LICENSE-2.0.html) + - Java Unrar (https://github.com/junrar/junrar) com.github.junrar:junrar:jar:7.5.2 + License: UnRar License (https://github.com/junrar/junrar/LICENSE.md) + - curvesapi (https://github.com/virtuald/curvesapi) com.github.virtuald:curvesapi:jar:1.07 + License: BSD License (http://opensource.org/licenses/BSD-3-Clause) + - juniversalchardet (http://juniversalchardet.googlecode.com/) com.googlecode.juniversalchardet:juniversalchardet:jar:1.0.3 + License: Mozilla Public License 1.1 (MPL 1.1) (http://www.mozilla.org/MPL/MPL-1.1.html) + - dd-plist (http://www.github.com/3breadt/dd-plist) com.googlecode.plist:dd-plist:jar:1.23 + License: MIT License (http://opensource.org/licenses/mit) + - java-libpst (https://github.com/rjohnsondev/java-libpst) com.pff:java-libpst:jar:0.9.3 + License: The Apache Software License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt) + - rome (http://rometools.com/rome) com.rometools:rome:jar:1.18.0 + License: The Apache Software License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt) + - rome-utils (http://rometools.com/rome-utils) com.rometools:rome-utils:jar:1.18.0 + License: The Apache Software License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt) + - Bouncy Castle S/MIME API (https://www.bouncycastle.org/java.html) org.bouncycastle:bcmail-jdk15on:jar:1.70 + License: Bouncy Castle Licence (https://www.bouncycastle.org/licence.html) + - Bouncy Castle PKIX, CMS, EAC, TSP, PKCS, OCSP, CMP, and CRMF APIs (https://www.bouncycastle.org/java.html) org.bouncycastle:bcpkix-jdk15on:jar:1.70 + License: Bouncy Castle Licence (https://www.bouncycastle.org/licence.html) + - Bouncy Castle Provider (https://www.bouncycastle.org/java.html) org.bouncycastle:bcprov-jdk15on:jar:1.70 + License: Bouncy Castle Licence (https://www.bouncycastle.org/licence.html) + - Bouncy Castle ASN.1 Extension and Utility APIs (https://www.bouncycastle.org/java.html) org.bouncycastle:bcutil-jdk15on:jar:1.70 + License: Bouncy Castle Licence (https://www.bouncycastle.org/licence.html) + - org.brotli:dec (http://brotli.org/dec) org.brotli:dec:jar:0.1.2 + License: MIT License (http://www.opensource.org/licenses/mit-license.php) + - TagSoup (http://home.ccil.org/~cowan/XML/tagsoup/) org.ccil.cowan.tagsoup:tagsoup:jar:1.2.1 + License: Apache License 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt) + - JHighlight (https://github.com/codelibs/jhighlight) org.codelibs:jhighlight:jar:1.1.0 + License: CDDL, v1.0 (http://www.opensource.org/licenses/cddl1.php) License: LGPL, v2.1 or later (http://www.opensource.org/licenses/lgpl-license.php) + - Ogg and Vorbis for Java, Core (https://github.com/Gagravarr/VorbisJava) org.gagravarr:vorbis-java-core:jar:0.8 + License: The Apache Software License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Tika plugin for Ogg, Vorbis and FLAC (https://github.com/Gagravarr/VorbisJava) org.gagravarr:vorbis-java-tika:jar:0.8 + License: The Apache Software License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt) + - jwarc (https://github.com/iipc/jwarc) org.netpreserve:jwarc:jar:0.18.1 + License: Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt) + - JMatIO (https://github.com/tballison/jmatio) org.tallison:jmatio:jar:1.5 + License: BSD (http://www.linfo.org/bsdlicense.html) + - XZ for Java (https://tukaani.org/xz/java.html) org.tukaani:xz:jar:1.9 + License: Public Domain + - Xerces2-j (https://xerces.apache.org/xerces2-j/) xerces:xercesImpl:jar:2.12.2 + License: The Apache Software License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt) + - XML Commons External Components XML APIs (http://xml.apache.org/commons/components/external/) xml-apis:xml-apis:jar:1.4.01 + License: The Apache Software License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt) License: The SAX License (http://www.saxproject.org/copying.html) License: The W3C License (http://www.w3.org/TR/2004/REC-DOM-Level-3-Core-20040407/java-binding.zip) + +From: 'Apache Software Foundation' (http://db.apache.org/) + - Apache Derby Database Engine and Embedded JDBC Driver (http://db.apache.org/derby/) org.apache.derby:derby:jar:10.14.2.0 + License: Apache 2 (http://www.apache.org/licenses/LICENSE-2.0.txt) + +From: 'Apache Software Foundation' (http://www.apache.org/) + - Apache POI - Common (https://poi.apache.org/) org.apache.poi:poi:jar:5.2.2 + License: Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache POI - API based on OPC and OOXML schemas (https://poi.apache.org/) org.apache.poi:poi-ooxml:jar:5.2.2 + License: Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache POI (https://poi.apache.org/) org.apache.poi:poi-ooxml-lite:jar:5.2.2 + License: Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache POI (https://poi.apache.org/) org.apache.poi:poi-scratchpad:jar:5.2.2 + License: Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt) + +From: 'Day Software' (http://www.day.com) + - Content Repository for JavaTM Technology API (http://www.jcp.org/en/jsr/detail?id=283) javax.jcr:jcr:jar:2.0 + License: Day Specification License (http://www.day.com/dam/day/downloads/jsr283/day-spec-license.htm) License: Day Specification License addendum (http://www.day.com/content/dam/day/downloads/jsr283/LICENSE.txt) + +From: 'Dough Lea' (http://gee.cs.oswego.edu/dl/classes/EDU/oswego/cs/dl/util/concurrent/intro.html) + - Dough Lea's util.concurrent package concurrent:concurrent:jar:1.3.4 + License: Public domain, Sun Microsoystems (>http://gee.cs.oswego.edu/dl/classes/EDU/oswego/cs/dl/util/concurrent/intro.html) + +From: 'Eclipse Foundation' (https://www.eclipse.org) + - Jakarta Activation (https://github.com/eclipse-ee4j/jaf/jakarta.activation) com.sun.activation:jakarta.activation:jar:1.2.2 + License: EDL 1.0 (http://www.eclipse.org/org/documents/edl-v10.php) + - istack common utility code runtime (https://projects.eclipse.org/projects/ee4j/istack-commons/istack-commons-runtime) com.sun.istack:istack-commons-runtime:jar:3.0.12 + License: Eclipse Distribution License - v 1.0 (http://www.eclipse.org/org/documents/edl-v10.php) + - Jakarta XML Binding API (https://github.com/eclipse-ee4j/jaxb-api/jakarta.xml.bind-api) jakarta.xml.bind:jakarta.xml.bind-api:jar:2.3.3 + License: Eclipse Distribution License - v 1.0 (http://www.eclipse.org/org/documents/edl-v10.php) + - JAXB Runtime (https://eclipse-ee4j.github.io/jaxb-ri/) org.glassfish.jaxb:jaxb-runtime:jar:2.3.6 + License: Eclipse Distribution License - v 1.0 (http://www.eclipse.org/org/documents/edl-v10.php) + - TXW2 Runtime (https://eclipse-ee4j.github.io/jaxb-ri/) org.glassfish.jaxb:txw2:jar:2.3.6 + License: Eclipse Distribution License - v 1.0 (http://www.eclipse.org/org/documents/edl-v10.php) + +From: 'jai-imageio GitHub group' (https://github.com/jai-imageio/) + - Java Advanced Imaging Image I/O Tools API core (standalone) (https://github.com/jai-imageio/jai-imageio-core) com.github.jai-imageio:jai-imageio-core:bundle:1.4.0 + License: BSD 3-clause License w/nuclear disclaimer (LICENSE.txt) + +From: 'JDOM' (http://www.jdom.org) + - JDOM (http://www.jdom.org) org.jdom:jdom2:jar:2.0.6.1 + License: Similar to Apache License but with the acknowledgment clause removed (https://raw.github.com/hunterhacker/jdom/master/LICENSE.txt) + +From: 'OpenHMS' (https://openhms.sourceforge.io/) + - Jackcess (https://jackcess.sourceforge.io) com.healthmarketscience.jackcess:jackcess:jar:4.0.1 + License: Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt) + - Jackcess Encrypt (http://jackcessencrypt.sf.net) com.healthmarketscience.jackcess:jackcess-encrypt:jar:4.0.1 + License: Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt) + +From: 'OW2' (http://www.ow2.org/) + - asm (http://asm.ow2.io/) org.ow2.asm:asm:jar:9.3 + License: BSD-3-Clause (https://asm.ow2.io/license.html) + +From: 'QOS.ch' (http://www.qos.ch) + - Logback Classic Module (http://logback.qos.ch/logback-classic) ch.qos.logback:logback-classic:jar:1.2.11 + License: Eclipse Public License - v 1.0 (http://www.eclipse.org/legal/epl-v10.html) License: GNU Lesser General Public License (http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html) + - Logback Core Module (http://logback.qos.ch/logback-core) ch.qos.logback:logback-core:jar:1.2.11 + License: Eclipse Public License - v 1.0 (http://www.eclipse.org/legal/epl-v10.html) License: GNU Lesser General Public License (http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html) + - JCL 1.2 implemented over SLF4J (http://www.slf4j.org) org.slf4j:jcl-over-slf4j:jar:1.7.36 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - SLF4J API Module (http://www.slf4j.org) org.slf4j:slf4j-api:jar:1.7.36 + License: MIT License (http://www.opensource.org/licenses/mit-license.php) + +From: 'The Apache Software Foundation' (http://pdfbox.apache.org) + - Apache FontBox (http://pdfbox.apache.org/) org.apache.pdfbox:fontbox:bundle:2.0.26 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - PDFBox JBIG2 ImageIO plugin (https://www.apache.org/jbig2-imageio/) org.apache.pdfbox:jbig2-imageio:jar:3.0.4 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache JempBox (http://www.apache.org/pdfbox-parent/jempbox/) org.apache.pdfbox:jempbox:bundle:1.8.16 + License: Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache PDFBox (https://www.apache.org/pdfbox-parent/pdfbox/) org.apache.pdfbox:pdfbox:bundle:2.0.26 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache PDFBox Debugger (https://www.apache.org/pdfbox-parent/pdfbox-debugger/) org.apache.pdfbox:pdfbox-debugger:jar:2.0.26 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache PDFBox tools (https://www.apache.org/pdfbox-parent/pdfbox-tools/) org.apache.pdfbox:pdfbox-tools:jar:2.0.26 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache XmpBox (https://www.apache.org/pdfbox-parent/xmpbox/) org.apache.pdfbox:xmpbox:bundle:2.0.26 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + +From: 'The Apache Software Foundation' (http://www.apache.org) + - Apache Tika core (https://tika.apache.org/) org.apache.tika:tika-core:bundle:2.4.1 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + +From: 'The Apache Software Foundation' (http://www.apache.org/) + - Apache Commons Collections (http://commons.apache.org/collections/) commons-collections:commons-collections:jar:3.2.2 + License: Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt) + - Commons DBCP (http://commons.apache.org/dbcp/) commons-dbcp:commons-dbcp:jar:1.4 + License: The Apache Software License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Commons Logging (http://commons.apache.org/proper/commons-logging/) commons-logging:commons-logging:jar:1.2 + License: The Apache Software License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt) + - Commons Pool (http://commons.apache.org/pool/) commons-pool:commons-pool:jar:1.5.4 + License: The Apache Software License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Commons Exec (http://commons.apache.org/proper/commons-exec/) org.apache.commons:commons-exec:jar:1.3 + License: Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Commons Math (http://commons.apache.org/proper/commons-math/) org.apache.commons:commons-math3:jar:3.6.1 + License: Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache HttpClient (http://hc.apache.org/httpcomponents-client-ga) org.apache.httpcomponents:httpclient:jar:4.5.14 + License: Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache HttpCore (http://hc.apache.org/httpcomponents-core-ga) org.apache.httpcomponents:httpcore:jar:4.4.16 + License: Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt) + - Lucene Core (http://lucene.apache.org/java/lucene-parent/lucene-core) org.apache.lucene:lucene-core:jar:3.6.0 + License: Apache 2 (http://www.apache.org/licenses/LICENSE-2.0.txt) + +From: 'The Apache Software Foundation' (https://www.apache.org/) + - Apache Commons BeanUtils (https://commons.apache.org/proper/commons-beanutils/) commons-beanutils:commons-beanutils:jar:1.9.4 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Commons Codec (https://commons.apache.org/proper/commons-codec/) commons-codec:commons-codec:jar:1.15 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Commons FileUpload (https://commons.apache.org/proper/commons-fileupload/) commons-fileupload:commons-fileupload:jar:1.5 + License: Apache-2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Commons IO (https://commons.apache.org/proper/commons-io/) commons-io:commons-io:jar:2.11.0 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Commons Collections (https://commons.apache.org/proper/commons-collections/) org.apache.commons:commons-collections4:jar:4.4 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Commons CSV (https://commons.apache.org/proper/commons-csv/) org.apache.commons:commons-csv:jar:1.9.0 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Commons Lang (https://commons.apache.org/proper/commons-lang/) org.apache.commons:commons-lang3:jar:3.12.0 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Jackrabbit Core (http://jackrabbit.apache.org/jackrabbit-core/) org.apache.jackrabbit:jackrabbit-core:jar:2.21.16-SNAPSHOT + License: Apache-2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Jackrabbit Data (http://jackrabbit.apache.org/jackrabbit-data/) org.apache.jackrabbit:jackrabbit-data:bundle:2.21.16-SNAPSHOT + License: Apache-2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Jackrabbit JCR Commons (http://jackrabbit.apache.org/jackrabbit-jcr-commons/) org.apache.jackrabbit:jackrabbit-jcr-commons:bundle:2.21.16-SNAPSHOT + License: Apache-2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Jackrabbit JCR-RMI (http://jackrabbit.apache.org/jackrabbit-jcr-rmi/) org.apache.jackrabbit:jackrabbit-jcr-rmi:bundle:2.21.16-SNAPSHOT + License: Apache-2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - jackrabbit-jcr-server-jakarta (http://jackrabbit.apache.org/jackrabbit-jcr-server-project/jackrabbit-jcr-server-jakarta/) org.apache.jackrabbit:jackrabbit-jcr-server-jakarta:jar:2.21.16-SNAPSHOT + License: Apache-2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - jackrabbit-jcr-servlet-jakarta (http://jackrabbit.apache.org/jackrabbit-jcr-servlet-project/jackrabbit-jcr-servlet-jakarta/) org.apache.jackrabbit:jackrabbit-jcr-servlet-jakarta:jar:2.21.16-SNAPSHOT + License: Apache-2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Jackrabbit SPI (http://jackrabbit.apache.org/jackrabbit-spi/) org.apache.jackrabbit:jackrabbit-spi:bundle:2.21.16-SNAPSHOT + License: Apache-2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Jackrabbit SPI Commons (http://jackrabbit.apache.org/jackrabbit-spi-commons/) org.apache.jackrabbit:jackrabbit-spi-commons:bundle:2.21.16-SNAPSHOT + License: Apache-2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - jackrabbit-webdav-jakarta (http://jackrabbit.apache.org/jackrabbit-webdav-project/jackrabbit-webdav-jakarta/) org.apache.jackrabbit:jackrabbit-webdav-jakarta:jar:2.21.16-SNAPSHOT + License: Apache-2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Jackrabbit API (http://jackrabbit.apache.org/oak-jackrabbit-api/) org.apache.jackrabbit:oak-jackrabbit-api:bundle:1.48.0 + License: Apache-2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Log4j API (https://logging.apache.org/log4j/2.x/log4j-api/) org.apache.logging.log4j:log4j-api:jar:2.17.2 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Tika Apple parser module (https://tika.apache.org/tika-parser-apple-module/) org.apache.tika:tika-parser-apple-module:jar:2.4.1 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Tika audiovideo parser module (https://tika.apache.org/tika-parser-audiovideo-module/) org.apache.tika:tika-parser-audiovideo-module:jar:2.4.1 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Tika cad parser module (https://tika.apache.org/tika-parser-cad-module/) org.apache.tika:tika-parser-cad-module:jar:2.4.1 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Tika code parser module (https://tika.apache.org/tika-parser-code-module/) org.apache.tika:tika-parser-code-module:jar:2.4.1 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Tika crypto parser module (https://tika.apache.org/tika-parser-crypto-module/) org.apache.tika:tika-parser-crypto-module:jar:2.4.1 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Tika digest commons (https://tika.apache.org/tika-parser-digest-commons/) org.apache.tika:tika-parser-digest-commons:jar:2.4.1 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Tika font parser module (https://tika.apache.org/tika-parser-font-module/) org.apache.tika:tika-parser-font-module:jar:2.4.1 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Tika html commons (https://tika.apache.org/tika-parser-html-commons/) org.apache.tika:tika-parser-html-commons:jar:2.4.1 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Tika html parser module (https://tika.apache.org/tika-parser-html-module/) org.apache.tika:tika-parser-html-module:jar:2.4.1 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Tika image parser module (https://tika.apache.org/tika-parser-image-module/) org.apache.tika:tika-parser-image-module:jar:2.4.1 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Tika mail commons (https://tika.apache.org/tika-parser-mail-commons/) org.apache.tika:tika-parser-mail-commons:jar:2.4.1 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Tika mail parser module (https://tika.apache.org/tika-parser-mail-module/) org.apache.tika:tika-parser-mail-module:jar:2.4.1 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Tika Microsoft parser module (https://tika.apache.org/tika-parser-microsoft-module/) org.apache.tika:tika-parser-microsoft-module:jar:2.4.1 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Tika miscellaneous office format parser module (https://tika.apache.org/tika-parser-miscoffice-module/) org.apache.tika:tika-parser-miscoffice-module:jar:2.4.1 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Tika news parser module (https://tika.apache.org/tika-parser-news-module/) org.apache.tika:tika-parser-news-module:jar:2.4.1 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Tika OCR parser module (https://tika.apache.org/tika-parser-ocr-module/) org.apache.tika:tika-parser-ocr-module:jar:2.4.1 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Tika PDF parser module (https://tika.apache.org/tika-parser-pdf-module/) org.apache.tika:tika-parser-pdf-module:jar:2.4.1 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Tika package parser module (https://tika.apache.org/tika-parser-pkg-module/) org.apache.tika:tika-parser-pkg-module:jar:2.4.1 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Tika text parser module (https://tika.apache.org/tika-parser-text-module/) org.apache.tika:tika-parser-text-module:jar:2.4.1 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Tika WARC parser module (https://tika.apache.org/tika-parser-webarchive-module/) org.apache.tika:tika-parser-webarchive-module:jar:2.4.1 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Tika XML parser module (https://tika.apache.org/tika-parser-xml-module/) org.apache.tika:tika-parser-xml-module:jar:2.4.1 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Tika XMP commons (https://tika.apache.org/tika-parser-xmp-commons/) org.apache.tika:tika-parser-xmp-commons:jar:2.4.1 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Tika ZIP commons (https://tika.apache.org/tika-parser-zip-commons/) org.apache.tika:tika-parser-zip-commons:jar:2.4.1 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Tika standard parser package (https://tika.apache.org/tika-parsers/tika-parsers-standard/tika-parsers-standard-package/) org.apache.tika:tika-parsers-standard-package:jar:2.4.1 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + +From: 'XmlBeans' (https://xmlbeans.apache.org/) + - XmlBeans (https://xmlbeans.apache.org/) org.apache.xmlbeans:xmlbeans:jar:5.0.3 + License: The Apache Software License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt) + +From: 'Zaxxer.com' (https://github.com/brettwooldridge/SparseBitSet) + - SparseBitSet (https://github.com/brettwooldridge/SparseBitSet) com.zaxxer:SparseBitSet:jar:1.2 + License: The Apache Software License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt) + + + + Index: jackrabbit-webapp-project/jackrabbit-webapp-jakarta/target/classes/META-INF/LICENSE =================================================================== --- jackrabbit-webapp-project/jackrabbit-webapp-jakarta/target/classes/META-INF/LICENSE (nonexistent) +++ jackrabbit-webapp-project/jackrabbit-webapp-jakarta/target/classes/META-INF/LICENSE (working copy) @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed 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. Index: jackrabbit-webapp-project/jackrabbit-webapp-jakarta/target/classes/META-INF/NOTICE =================================================================== --- jackrabbit-webapp-project/jackrabbit-webapp-jakarta/target/classes/META-INF/NOTICE (nonexistent) +++ jackrabbit-webapp-project/jackrabbit-webapp-jakarta/target/classes/META-INF/NOTICE (working copy) @@ -0,0 +1,8 @@ + +jackrabbit-webapp-jakarta +Copyright 2004-1970 The Apache Software Foundation + +This product includes software developed at +The Apache Software Foundation (http://www.apache.org/). + + Index: jackrabbit-webapp-project/jackrabbit-webapp-jakarta/target/classes/META-INF/maven/org.apache.jackrabbit/jackrabbit-webapp-jakarta/pom.properties =================================================================== --- jackrabbit-webapp-project/jackrabbit-webapp-jakarta/target/classes/META-INF/maven/org.apache.jackrabbit/jackrabbit-webapp-jakarta/pom.properties (nonexistent) +++ jackrabbit-webapp-project/jackrabbit-webapp-jakarta/target/classes/META-INF/maven/org.apache.jackrabbit/jackrabbit-webapp-jakarta/pom.properties (working copy) @@ -0,0 +1,7 @@ +#Generated by Maven Integration for Eclipse +#Wed Mar 01 12:30:08 CET 2023 +m2e.projectLocation=C\:\\Development\\JackRabbit\\trunk\\jackrabbit-webapp-project\\jackrabbit-webapp-jakarta +m2e.projectName=jackrabbit-webapp-jakarta +groupId=org.apache.jackrabbit +artifactId=jackrabbit-webapp-jakarta +version=2.21.16-SNAPSHOT Index: jackrabbit-webapp-project/jackrabbit-webapp-jakarta/target/classes/META-INF/maven/org.apache.jackrabbit/jackrabbit-webapp-jakarta/pom.xml =================================================================== --- jackrabbit-webapp-project/jackrabbit-webapp-jakarta/target/classes/META-INF/maven/org.apache.jackrabbit/jackrabbit-webapp-jakarta/pom.xml (nonexistent) +++ jackrabbit-webapp-project/jackrabbit-webapp-jakarta/target/classes/META-INF/maven/org.apache.jackrabbit/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-webapp-project/jackrabbit-webapp-jakarta/target/jackrabbit-webapp-jakarta-2.21.16-SNAPSHOT.jar =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Property changes on: jackrabbit-webapp-project/jackrabbit-webapp-jakarta/target/jackrabbit-webapp-jakarta-2.21.16-SNAPSHOT.jar ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: jackrabbit-webapp-project/jackrabbit-webapp-jakarta/target/maven-shared-archive-resources/META-INF/DEPENDENCIES =================================================================== --- jackrabbit-webapp-project/jackrabbit-webapp-jakarta/target/maven-shared-archive-resources/META-INF/DEPENDENCIES (nonexistent) +++ jackrabbit-webapp-project/jackrabbit-webapp-jakarta/target/maven-shared-archive-resources/META-INF/DEPENDENCIES (working copy) @@ -0,0 +1,253 @@ +// ------------------------------------------------------------------ +// Transitive dependencies of this project determined from the +// maven pom organized by organization. +// ------------------------------------------------------------------ + +jackrabbit-webapp-jakarta + + +From: 'an unknown organization' + - parso (https://github.com/epam/parso) com.epam:parso:jar:2.0.14 + License: Apache License v2 (http://www.apache.org/licenses/LICENSE-2.0.html) + - Java Unrar (https://github.com/junrar/junrar) com.github.junrar:junrar:jar:7.5.2 + License: UnRar License (https://github.com/junrar/junrar/LICENSE.md) + - curvesapi (https://github.com/virtuald/curvesapi) com.github.virtuald:curvesapi:jar:1.07 + License: BSD License (http://opensource.org/licenses/BSD-3-Clause) + - juniversalchardet (http://juniversalchardet.googlecode.com/) com.googlecode.juniversalchardet:juniversalchardet:jar:1.0.3 + License: Mozilla Public License 1.1 (MPL 1.1) (http://www.mozilla.org/MPL/MPL-1.1.html) + - dd-plist (http://www.github.com/3breadt/dd-plist) com.googlecode.plist:dd-plist:jar:1.23 + License: MIT License (http://opensource.org/licenses/mit) + - java-libpst (https://github.com/rjohnsondev/java-libpst) com.pff:java-libpst:jar:0.9.3 + License: The Apache Software License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt) + - rome (http://rometools.com/rome) com.rometools:rome:jar:1.18.0 + License: The Apache Software License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt) + - rome-utils (http://rometools.com/rome-utils) com.rometools:rome-utils:jar:1.18.0 + License: The Apache Software License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt) + - Bouncy Castle S/MIME API (https://www.bouncycastle.org/java.html) org.bouncycastle:bcmail-jdk15on:jar:1.70 + License: Bouncy Castle Licence (https://www.bouncycastle.org/licence.html) + - Bouncy Castle PKIX, CMS, EAC, TSP, PKCS, OCSP, CMP, and CRMF APIs (https://www.bouncycastle.org/java.html) org.bouncycastle:bcpkix-jdk15on:jar:1.70 + License: Bouncy Castle Licence (https://www.bouncycastle.org/licence.html) + - Bouncy Castle Provider (https://www.bouncycastle.org/java.html) org.bouncycastle:bcprov-jdk15on:jar:1.70 + License: Bouncy Castle Licence (https://www.bouncycastle.org/licence.html) + - Bouncy Castle ASN.1 Extension and Utility APIs (https://www.bouncycastle.org/java.html) org.bouncycastle:bcutil-jdk15on:jar:1.70 + License: Bouncy Castle Licence (https://www.bouncycastle.org/licence.html) + - org.brotli:dec (http://brotli.org/dec) org.brotli:dec:jar:0.1.2 + License: MIT License (http://www.opensource.org/licenses/mit-license.php) + - TagSoup (http://home.ccil.org/~cowan/XML/tagsoup/) org.ccil.cowan.tagsoup:tagsoup:jar:1.2.1 + License: Apache License 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt) + - JHighlight (https://github.com/codelibs/jhighlight) org.codelibs:jhighlight:jar:1.1.0 + License: CDDL, v1.0 (http://www.opensource.org/licenses/cddl1.php) License: LGPL, v2.1 or later (http://www.opensource.org/licenses/lgpl-license.php) + - Ogg and Vorbis for Java, Core (https://github.com/Gagravarr/VorbisJava) org.gagravarr:vorbis-java-core:jar:0.8 + License: The Apache Software License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Tika plugin for Ogg, Vorbis and FLAC (https://github.com/Gagravarr/VorbisJava) org.gagravarr:vorbis-java-tika:jar:0.8 + License: The Apache Software License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt) + - jwarc (https://github.com/iipc/jwarc) org.netpreserve:jwarc:jar:0.18.1 + License: Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt) + - JMatIO (https://github.com/tballison/jmatio) org.tallison:jmatio:jar:1.5 + License: BSD (http://www.linfo.org/bsdlicense.html) + - XZ for Java (https://tukaani.org/xz/java.html) org.tukaani:xz:jar:1.9 + License: Public Domain + - Xerces2-j (https://xerces.apache.org/xerces2-j/) xerces:xercesImpl:jar:2.12.2 + License: The Apache Software License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt) + - XML Commons External Components XML APIs (http://xml.apache.org/commons/components/external/) xml-apis:xml-apis:jar:1.4.01 + License: The Apache Software License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt) License: The SAX License (http://www.saxproject.org/copying.html) License: The W3C License (http://www.w3.org/TR/2004/REC-DOM-Level-3-Core-20040407/java-binding.zip) + +From: 'Apache Software Foundation' (http://db.apache.org/) + - Apache Derby Database Engine and Embedded JDBC Driver (http://db.apache.org/derby/) org.apache.derby:derby:jar:10.14.2.0 + License: Apache 2 (http://www.apache.org/licenses/LICENSE-2.0.txt) + +From: 'Apache Software Foundation' (http://www.apache.org/) + - Apache POI - Common (https://poi.apache.org/) org.apache.poi:poi:jar:5.2.2 + License: Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache POI - API based on OPC and OOXML schemas (https://poi.apache.org/) org.apache.poi:poi-ooxml:jar:5.2.2 + License: Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache POI (https://poi.apache.org/) org.apache.poi:poi-ooxml-lite:jar:5.2.2 + License: Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache POI (https://poi.apache.org/) org.apache.poi:poi-scratchpad:jar:5.2.2 + License: Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt) + +From: 'Day Software' (http://www.day.com) + - Content Repository for JavaTM Technology API (http://www.jcp.org/en/jsr/detail?id=283) javax.jcr:jcr:jar:2.0 + License: Day Specification License (http://www.day.com/dam/day/downloads/jsr283/day-spec-license.htm) License: Day Specification License addendum (http://www.day.com/content/dam/day/downloads/jsr283/LICENSE.txt) + +From: 'Dough Lea' (http://gee.cs.oswego.edu/dl/classes/EDU/oswego/cs/dl/util/concurrent/intro.html) + - Dough Lea's util.concurrent package concurrent:concurrent:jar:1.3.4 + License: Public domain, Sun Microsoystems (>http://gee.cs.oswego.edu/dl/classes/EDU/oswego/cs/dl/util/concurrent/intro.html) + +From: 'Eclipse Foundation' (https://www.eclipse.org) + - Jakarta Activation (https://github.com/eclipse-ee4j/jaf/jakarta.activation) com.sun.activation:jakarta.activation:jar:1.2.2 + License: EDL 1.0 (http://www.eclipse.org/org/documents/edl-v10.php) + - istack common utility code runtime (https://projects.eclipse.org/projects/ee4j/istack-commons/istack-commons-runtime) com.sun.istack:istack-commons-runtime:jar:3.0.12 + License: Eclipse Distribution License - v 1.0 (http://www.eclipse.org/org/documents/edl-v10.php) + - Jakarta XML Binding API (https://github.com/eclipse-ee4j/jaxb-api/jakarta.xml.bind-api) jakarta.xml.bind:jakarta.xml.bind-api:jar:2.3.3 + License: Eclipse Distribution License - v 1.0 (http://www.eclipse.org/org/documents/edl-v10.php) + - JAXB Runtime (https://eclipse-ee4j.github.io/jaxb-ri/) org.glassfish.jaxb:jaxb-runtime:jar:2.3.6 + License: Eclipse Distribution License - v 1.0 (http://www.eclipse.org/org/documents/edl-v10.php) + - TXW2 Runtime (https://eclipse-ee4j.github.io/jaxb-ri/) org.glassfish.jaxb:txw2:jar:2.3.6 + License: Eclipse Distribution License - v 1.0 (http://www.eclipse.org/org/documents/edl-v10.php) + +From: 'jai-imageio GitHub group' (https://github.com/jai-imageio/) + - Java Advanced Imaging Image I/O Tools API core (standalone) (https://github.com/jai-imageio/jai-imageio-core) com.github.jai-imageio:jai-imageio-core:bundle:1.4.0 + License: BSD 3-clause License w/nuclear disclaimer (LICENSE.txt) + +From: 'JDOM' (http://www.jdom.org) + - JDOM (http://www.jdom.org) org.jdom:jdom2:jar:2.0.6.1 + License: Similar to Apache License but with the acknowledgment clause removed (https://raw.github.com/hunterhacker/jdom/master/LICENSE.txt) + +From: 'OpenHMS' (https://openhms.sourceforge.io/) + - Jackcess (https://jackcess.sourceforge.io) com.healthmarketscience.jackcess:jackcess:jar:4.0.1 + License: Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt) + - Jackcess Encrypt (http://jackcessencrypt.sf.net) com.healthmarketscience.jackcess:jackcess-encrypt:jar:4.0.1 + License: Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt) + +From: 'OW2' (http://www.ow2.org/) + - asm (http://asm.ow2.io/) org.ow2.asm:asm:jar:9.3 + License: BSD-3-Clause (https://asm.ow2.io/license.html) + +From: 'QOS.ch' (http://www.qos.ch) + - Logback Classic Module (http://logback.qos.ch/logback-classic) ch.qos.logback:logback-classic:jar:1.2.11 + License: Eclipse Public License - v 1.0 (http://www.eclipse.org/legal/epl-v10.html) License: GNU Lesser General Public License (http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html) + - Logback Core Module (http://logback.qos.ch/logback-core) ch.qos.logback:logback-core:jar:1.2.11 + License: Eclipse Public License - v 1.0 (http://www.eclipse.org/legal/epl-v10.html) License: GNU Lesser General Public License (http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html) + - JCL 1.2 implemented over SLF4J (http://www.slf4j.org) org.slf4j:jcl-over-slf4j:jar:1.7.36 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - SLF4J API Module (http://www.slf4j.org) org.slf4j:slf4j-api:jar:1.7.36 + License: MIT License (http://www.opensource.org/licenses/mit-license.php) + +From: 'The Apache Software Foundation' (http://pdfbox.apache.org) + - Apache FontBox (http://pdfbox.apache.org/) org.apache.pdfbox:fontbox:bundle:2.0.26 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - PDFBox JBIG2 ImageIO plugin (https://www.apache.org/jbig2-imageio/) org.apache.pdfbox:jbig2-imageio:jar:3.0.4 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache JempBox (http://www.apache.org/pdfbox-parent/jempbox/) org.apache.pdfbox:jempbox:bundle:1.8.16 + License: Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache PDFBox (https://www.apache.org/pdfbox-parent/pdfbox/) org.apache.pdfbox:pdfbox:bundle:2.0.26 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache PDFBox Debugger (https://www.apache.org/pdfbox-parent/pdfbox-debugger/) org.apache.pdfbox:pdfbox-debugger:jar:2.0.26 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache PDFBox tools (https://www.apache.org/pdfbox-parent/pdfbox-tools/) org.apache.pdfbox:pdfbox-tools:jar:2.0.26 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache XmpBox (https://www.apache.org/pdfbox-parent/xmpbox/) org.apache.pdfbox:xmpbox:bundle:2.0.26 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + +From: 'The Apache Software Foundation' (http://www.apache.org) + - Apache Tika core (https://tika.apache.org/) org.apache.tika:tika-core:bundle:2.4.1 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + +From: 'The Apache Software Foundation' (http://www.apache.org/) + - Apache Commons Collections (http://commons.apache.org/collections/) commons-collections:commons-collections:jar:3.2.2 + License: Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt) + - Commons DBCP (http://commons.apache.org/dbcp/) commons-dbcp:commons-dbcp:jar:1.4 + License: The Apache Software License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Commons Logging (http://commons.apache.org/proper/commons-logging/) commons-logging:commons-logging:jar:1.2 + License: The Apache Software License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt) + - Commons Pool (http://commons.apache.org/pool/) commons-pool:commons-pool:jar:1.5.4 + License: The Apache Software License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Commons Exec (http://commons.apache.org/proper/commons-exec/) org.apache.commons:commons-exec:jar:1.3 + License: Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Commons Math (http://commons.apache.org/proper/commons-math/) org.apache.commons:commons-math3:jar:3.6.1 + License: Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache HttpClient (http://hc.apache.org/httpcomponents-client-ga) org.apache.httpcomponents:httpclient:jar:4.5.14 + License: Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache HttpCore (http://hc.apache.org/httpcomponents-core-ga) org.apache.httpcomponents:httpcore:jar:4.4.16 + License: Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt) + - Lucene Core (http://lucene.apache.org/java/lucene-parent/lucene-core) org.apache.lucene:lucene-core:jar:3.6.0 + License: Apache 2 (http://www.apache.org/licenses/LICENSE-2.0.txt) + +From: 'The Apache Software Foundation' (https://www.apache.org/) + - Apache Commons BeanUtils (https://commons.apache.org/proper/commons-beanutils/) commons-beanutils:commons-beanutils:jar:1.9.4 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Commons Codec (https://commons.apache.org/proper/commons-codec/) commons-codec:commons-codec:jar:1.15 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Commons FileUpload (https://commons.apache.org/proper/commons-fileupload/) commons-fileupload:commons-fileupload:jar:1.5 + License: Apache-2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Commons IO (https://commons.apache.org/proper/commons-io/) commons-io:commons-io:jar:2.11.0 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Commons Collections (https://commons.apache.org/proper/commons-collections/) org.apache.commons:commons-collections4:jar:4.4 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Commons CSV (https://commons.apache.org/proper/commons-csv/) org.apache.commons:commons-csv:jar:1.9.0 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Commons Lang (https://commons.apache.org/proper/commons-lang/) org.apache.commons:commons-lang3:jar:3.12.0 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Jackrabbit Core (http://jackrabbit.apache.org/jackrabbit-core/) org.apache.jackrabbit:jackrabbit-core:jar:2.21.16-SNAPSHOT + License: Apache-2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Jackrabbit Data (http://jackrabbit.apache.org/jackrabbit-data/) org.apache.jackrabbit:jackrabbit-data:bundle:2.21.16-SNAPSHOT + License: Apache-2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Jackrabbit JCR Commons (http://jackrabbit.apache.org/jackrabbit-jcr-commons/) org.apache.jackrabbit:jackrabbit-jcr-commons:bundle:2.21.16-SNAPSHOT + License: Apache-2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Jackrabbit JCR-RMI (http://jackrabbit.apache.org/jackrabbit-jcr-rmi/) org.apache.jackrabbit:jackrabbit-jcr-rmi:bundle:2.21.16-SNAPSHOT + License: Apache-2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - jackrabbit-jcr-server-jakarta (http://jackrabbit.apache.org/jackrabbit-jcr-server-project/jackrabbit-jcr-server-jakarta/) org.apache.jackrabbit:jackrabbit-jcr-server-jakarta:jar:2.21.16-SNAPSHOT + License: Apache-2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - jackrabbit-jcr-servlet-jakarta (http://jackrabbit.apache.org/jackrabbit-jcr-servlet-project/jackrabbit-jcr-servlet-jakarta/) org.apache.jackrabbit:jackrabbit-jcr-servlet-jakarta:jar:2.21.16-SNAPSHOT + License: Apache-2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Jackrabbit SPI (http://jackrabbit.apache.org/jackrabbit-spi/) org.apache.jackrabbit:jackrabbit-spi:bundle:2.21.16-SNAPSHOT + License: Apache-2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Jackrabbit SPI Commons (http://jackrabbit.apache.org/jackrabbit-spi-commons/) org.apache.jackrabbit:jackrabbit-spi-commons:bundle:2.21.16-SNAPSHOT + License: Apache-2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - jackrabbit-webdav-jakarta (http://jackrabbit.apache.org/jackrabbit-webdav-project/jackrabbit-webdav-jakarta/) org.apache.jackrabbit:jackrabbit-webdav-jakarta:jar:2.21.16-SNAPSHOT + License: Apache-2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Jackrabbit API (http://jackrabbit.apache.org/oak-jackrabbit-api/) org.apache.jackrabbit:oak-jackrabbit-api:bundle:1.48.0 + License: Apache-2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Log4j API (https://logging.apache.org/log4j/2.x/log4j-api/) org.apache.logging.log4j:log4j-api:jar:2.17.2 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Tika Apple parser module (https://tika.apache.org/tika-parser-apple-module/) org.apache.tika:tika-parser-apple-module:jar:2.4.1 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Tika audiovideo parser module (https://tika.apache.org/tika-parser-audiovideo-module/) org.apache.tika:tika-parser-audiovideo-module:jar:2.4.1 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Tika cad parser module (https://tika.apache.org/tika-parser-cad-module/) org.apache.tika:tika-parser-cad-module:jar:2.4.1 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Tika code parser module (https://tika.apache.org/tika-parser-code-module/) org.apache.tika:tika-parser-code-module:jar:2.4.1 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Tika crypto parser module (https://tika.apache.org/tika-parser-crypto-module/) org.apache.tika:tika-parser-crypto-module:jar:2.4.1 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Tika digest commons (https://tika.apache.org/tika-parser-digest-commons/) org.apache.tika:tika-parser-digest-commons:jar:2.4.1 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Tika font parser module (https://tika.apache.org/tika-parser-font-module/) org.apache.tika:tika-parser-font-module:jar:2.4.1 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Tika html commons (https://tika.apache.org/tika-parser-html-commons/) org.apache.tika:tika-parser-html-commons:jar:2.4.1 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Tika html parser module (https://tika.apache.org/tika-parser-html-module/) org.apache.tika:tika-parser-html-module:jar:2.4.1 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Tika image parser module (https://tika.apache.org/tika-parser-image-module/) org.apache.tika:tika-parser-image-module:jar:2.4.1 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Tika mail commons (https://tika.apache.org/tika-parser-mail-commons/) org.apache.tika:tika-parser-mail-commons:jar:2.4.1 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Tika mail parser module (https://tika.apache.org/tika-parser-mail-module/) org.apache.tika:tika-parser-mail-module:jar:2.4.1 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Tika Microsoft parser module (https://tika.apache.org/tika-parser-microsoft-module/) org.apache.tika:tika-parser-microsoft-module:jar:2.4.1 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Tika miscellaneous office format parser module (https://tika.apache.org/tika-parser-miscoffice-module/) org.apache.tika:tika-parser-miscoffice-module:jar:2.4.1 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Tika news parser module (https://tika.apache.org/tika-parser-news-module/) org.apache.tika:tika-parser-news-module:jar:2.4.1 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Tika OCR parser module (https://tika.apache.org/tika-parser-ocr-module/) org.apache.tika:tika-parser-ocr-module:jar:2.4.1 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Tika PDF parser module (https://tika.apache.org/tika-parser-pdf-module/) org.apache.tika:tika-parser-pdf-module:jar:2.4.1 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Tika package parser module (https://tika.apache.org/tika-parser-pkg-module/) org.apache.tika:tika-parser-pkg-module:jar:2.4.1 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Tika text parser module (https://tika.apache.org/tika-parser-text-module/) org.apache.tika:tika-parser-text-module:jar:2.4.1 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Tika WARC parser module (https://tika.apache.org/tika-parser-webarchive-module/) org.apache.tika:tika-parser-webarchive-module:jar:2.4.1 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Tika XML parser module (https://tika.apache.org/tika-parser-xml-module/) org.apache.tika:tika-parser-xml-module:jar:2.4.1 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Tika XMP commons (https://tika.apache.org/tika-parser-xmp-commons/) org.apache.tika:tika-parser-xmp-commons:jar:2.4.1 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Tika ZIP commons (https://tika.apache.org/tika-parser-zip-commons/) org.apache.tika:tika-parser-zip-commons:jar:2.4.1 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Tika standard parser package (https://tika.apache.org/tika-parsers/tika-parsers-standard/tika-parsers-standard-package/) org.apache.tika:tika-parsers-standard-package:jar:2.4.1 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + +From: 'XmlBeans' (https://xmlbeans.apache.org/) + - XmlBeans (https://xmlbeans.apache.org/) org.apache.xmlbeans:xmlbeans:jar:5.0.3 + License: The Apache Software License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt) + +From: 'Zaxxer.com' (https://github.com/brettwooldridge/SparseBitSet) + - SparseBitSet (https://github.com/brettwooldridge/SparseBitSet) com.zaxxer:SparseBitSet:jar:1.2 + License: The Apache Software License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt) + + + + Index: jackrabbit-webapp-project/jackrabbit-webapp-jakarta/target/maven-shared-archive-resources/META-INF/LICENSE =================================================================== --- jackrabbit-webapp-project/jackrabbit-webapp-jakarta/target/maven-shared-archive-resources/META-INF/LICENSE (nonexistent) +++ jackrabbit-webapp-project/jackrabbit-webapp-jakarta/target/maven-shared-archive-resources/META-INF/LICENSE (working copy) @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed 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. Index: jackrabbit-webapp-project/jackrabbit-webapp-jakarta/target/maven-shared-archive-resources/META-INF/NOTICE =================================================================== --- jackrabbit-webapp-project/jackrabbit-webapp-jakarta/target/maven-shared-archive-resources/META-INF/NOTICE (nonexistent) +++ jackrabbit-webapp-project/jackrabbit-webapp-jakarta/target/maven-shared-archive-resources/META-INF/NOTICE (working copy) @@ -0,0 +1,8 @@ + +jackrabbit-webapp-jakarta +Copyright 2004-1970 The Apache Software Foundation + +This product includes software developed at +The Apache Software Foundation (http://www.apache.org/). + + Index: jackrabbit-webapp-project/jackrabbit-webapp-jakarta/target/maven-status/maven-compiler-plugin/compile/default-compile/createdFiles.lst =================================================================== Index: jackrabbit-webapp-project/jackrabbit-webapp-jakarta/target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst =================================================================== Index: jackrabbit-webapp-project/jackrabbit-webapp-jakarta/target/maven-status/maven-compiler-plugin/testCompile/default-testCompile/createdFiles.lst =================================================================== Index: jackrabbit-webapp-project/jackrabbit-webapp-jakarta/target/maven-status/maven-compiler-plugin/testCompile/default-testCompile/inputFiles.lst =================================================================== Index: jackrabbit-webapp-project/jackrabbit-webapp-jakarta/target/test-classes/META-INF/DEPENDENCIES =================================================================== --- jackrabbit-webapp-project/jackrabbit-webapp-jakarta/target/test-classes/META-INF/DEPENDENCIES (nonexistent) +++ jackrabbit-webapp-project/jackrabbit-webapp-jakarta/target/test-classes/META-INF/DEPENDENCIES (working copy) @@ -0,0 +1,253 @@ +// ------------------------------------------------------------------ +// Transitive dependencies of this project determined from the +// maven pom organized by organization. +// ------------------------------------------------------------------ + +jackrabbit-webapp-jakarta + + +From: 'an unknown organization' + - parso (https://github.com/epam/parso) com.epam:parso:jar:2.0.14 + License: Apache License v2 (http://www.apache.org/licenses/LICENSE-2.0.html) + - Java Unrar (https://github.com/junrar/junrar) com.github.junrar:junrar:jar:7.5.2 + License: UnRar License (https://github.com/junrar/junrar/LICENSE.md) + - curvesapi (https://github.com/virtuald/curvesapi) com.github.virtuald:curvesapi:jar:1.07 + License: BSD License (http://opensource.org/licenses/BSD-3-Clause) + - juniversalchardet (http://juniversalchardet.googlecode.com/) com.googlecode.juniversalchardet:juniversalchardet:jar:1.0.3 + License: Mozilla Public License 1.1 (MPL 1.1) (http://www.mozilla.org/MPL/MPL-1.1.html) + - dd-plist (http://www.github.com/3breadt/dd-plist) com.googlecode.plist:dd-plist:jar:1.23 + License: MIT License (http://opensource.org/licenses/mit) + - java-libpst (https://github.com/rjohnsondev/java-libpst) com.pff:java-libpst:jar:0.9.3 + License: The Apache Software License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt) + - rome (http://rometools.com/rome) com.rometools:rome:jar:1.18.0 + License: The Apache Software License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt) + - rome-utils (http://rometools.com/rome-utils) com.rometools:rome-utils:jar:1.18.0 + License: The Apache Software License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt) + - Bouncy Castle S/MIME API (https://www.bouncycastle.org/java.html) org.bouncycastle:bcmail-jdk15on:jar:1.70 + License: Bouncy Castle Licence (https://www.bouncycastle.org/licence.html) + - Bouncy Castle PKIX, CMS, EAC, TSP, PKCS, OCSP, CMP, and CRMF APIs (https://www.bouncycastle.org/java.html) org.bouncycastle:bcpkix-jdk15on:jar:1.70 + License: Bouncy Castle Licence (https://www.bouncycastle.org/licence.html) + - Bouncy Castle Provider (https://www.bouncycastle.org/java.html) org.bouncycastle:bcprov-jdk15on:jar:1.70 + License: Bouncy Castle Licence (https://www.bouncycastle.org/licence.html) + - Bouncy Castle ASN.1 Extension and Utility APIs (https://www.bouncycastle.org/java.html) org.bouncycastle:bcutil-jdk15on:jar:1.70 + License: Bouncy Castle Licence (https://www.bouncycastle.org/licence.html) + - org.brotli:dec (http://brotli.org/dec) org.brotli:dec:jar:0.1.2 + License: MIT License (http://www.opensource.org/licenses/mit-license.php) + - TagSoup (http://home.ccil.org/~cowan/XML/tagsoup/) org.ccil.cowan.tagsoup:tagsoup:jar:1.2.1 + License: Apache License 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt) + - JHighlight (https://github.com/codelibs/jhighlight) org.codelibs:jhighlight:jar:1.1.0 + License: CDDL, v1.0 (http://www.opensource.org/licenses/cddl1.php) License: LGPL, v2.1 or later (http://www.opensource.org/licenses/lgpl-license.php) + - Ogg and Vorbis for Java, Core (https://github.com/Gagravarr/VorbisJava) org.gagravarr:vorbis-java-core:jar:0.8 + License: The Apache Software License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Tika plugin for Ogg, Vorbis and FLAC (https://github.com/Gagravarr/VorbisJava) org.gagravarr:vorbis-java-tika:jar:0.8 + License: The Apache Software License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt) + - jwarc (https://github.com/iipc/jwarc) org.netpreserve:jwarc:jar:0.18.1 + License: Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt) + - JMatIO (https://github.com/tballison/jmatio) org.tallison:jmatio:jar:1.5 + License: BSD (http://www.linfo.org/bsdlicense.html) + - XZ for Java (https://tukaani.org/xz/java.html) org.tukaani:xz:jar:1.9 + License: Public Domain + - Xerces2-j (https://xerces.apache.org/xerces2-j/) xerces:xercesImpl:jar:2.12.2 + License: The Apache Software License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt) + - XML Commons External Components XML APIs (http://xml.apache.org/commons/components/external/) xml-apis:xml-apis:jar:1.4.01 + License: The Apache Software License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt) License: The SAX License (http://www.saxproject.org/copying.html) License: The W3C License (http://www.w3.org/TR/2004/REC-DOM-Level-3-Core-20040407/java-binding.zip) + +From: 'Apache Software Foundation' (http://db.apache.org/) + - Apache Derby Database Engine and Embedded JDBC Driver (http://db.apache.org/derby/) org.apache.derby:derby:jar:10.14.2.0 + License: Apache 2 (http://www.apache.org/licenses/LICENSE-2.0.txt) + +From: 'Apache Software Foundation' (http://www.apache.org/) + - Apache POI - Common (https://poi.apache.org/) org.apache.poi:poi:jar:5.2.2 + License: Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache POI - API based on OPC and OOXML schemas (https://poi.apache.org/) org.apache.poi:poi-ooxml:jar:5.2.2 + License: Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache POI (https://poi.apache.org/) org.apache.poi:poi-ooxml-lite:jar:5.2.2 + License: Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache POI (https://poi.apache.org/) org.apache.poi:poi-scratchpad:jar:5.2.2 + License: Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt) + +From: 'Day Software' (http://www.day.com) + - Content Repository for JavaTM Technology API (http://www.jcp.org/en/jsr/detail?id=283) javax.jcr:jcr:jar:2.0 + License: Day Specification License (http://www.day.com/dam/day/downloads/jsr283/day-spec-license.htm) License: Day Specification License addendum (http://www.day.com/content/dam/day/downloads/jsr283/LICENSE.txt) + +From: 'Dough Lea' (http://gee.cs.oswego.edu/dl/classes/EDU/oswego/cs/dl/util/concurrent/intro.html) + - Dough Lea's util.concurrent package concurrent:concurrent:jar:1.3.4 + License: Public domain, Sun Microsoystems (>http://gee.cs.oswego.edu/dl/classes/EDU/oswego/cs/dl/util/concurrent/intro.html) + +From: 'Eclipse Foundation' (https://www.eclipse.org) + - Jakarta Activation (https://github.com/eclipse-ee4j/jaf/jakarta.activation) com.sun.activation:jakarta.activation:jar:1.2.2 + License: EDL 1.0 (http://www.eclipse.org/org/documents/edl-v10.php) + - istack common utility code runtime (https://projects.eclipse.org/projects/ee4j/istack-commons/istack-commons-runtime) com.sun.istack:istack-commons-runtime:jar:3.0.12 + License: Eclipse Distribution License - v 1.0 (http://www.eclipse.org/org/documents/edl-v10.php) + - Jakarta XML Binding API (https://github.com/eclipse-ee4j/jaxb-api/jakarta.xml.bind-api) jakarta.xml.bind:jakarta.xml.bind-api:jar:2.3.3 + License: Eclipse Distribution License - v 1.0 (http://www.eclipse.org/org/documents/edl-v10.php) + - JAXB Runtime (https://eclipse-ee4j.github.io/jaxb-ri/) org.glassfish.jaxb:jaxb-runtime:jar:2.3.6 + License: Eclipse Distribution License - v 1.0 (http://www.eclipse.org/org/documents/edl-v10.php) + - TXW2 Runtime (https://eclipse-ee4j.github.io/jaxb-ri/) org.glassfish.jaxb:txw2:jar:2.3.6 + License: Eclipse Distribution License - v 1.0 (http://www.eclipse.org/org/documents/edl-v10.php) + +From: 'jai-imageio GitHub group' (https://github.com/jai-imageio/) + - Java Advanced Imaging Image I/O Tools API core (standalone) (https://github.com/jai-imageio/jai-imageio-core) com.github.jai-imageio:jai-imageio-core:bundle:1.4.0 + License: BSD 3-clause License w/nuclear disclaimer (LICENSE.txt) + +From: 'JDOM' (http://www.jdom.org) + - JDOM (http://www.jdom.org) org.jdom:jdom2:jar:2.0.6.1 + License: Similar to Apache License but with the acknowledgment clause removed (https://raw.github.com/hunterhacker/jdom/master/LICENSE.txt) + +From: 'OpenHMS' (https://openhms.sourceforge.io/) + - Jackcess (https://jackcess.sourceforge.io) com.healthmarketscience.jackcess:jackcess:jar:4.0.1 + License: Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt) + - Jackcess Encrypt (http://jackcessencrypt.sf.net) com.healthmarketscience.jackcess:jackcess-encrypt:jar:4.0.1 + License: Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt) + +From: 'OW2' (http://www.ow2.org/) + - asm (http://asm.ow2.io/) org.ow2.asm:asm:jar:9.3 + License: BSD-3-Clause (https://asm.ow2.io/license.html) + +From: 'QOS.ch' (http://www.qos.ch) + - Logback Classic Module (http://logback.qos.ch/logback-classic) ch.qos.logback:logback-classic:jar:1.2.11 + License: Eclipse Public License - v 1.0 (http://www.eclipse.org/legal/epl-v10.html) License: GNU Lesser General Public License (http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html) + - Logback Core Module (http://logback.qos.ch/logback-core) ch.qos.logback:logback-core:jar:1.2.11 + License: Eclipse Public License - v 1.0 (http://www.eclipse.org/legal/epl-v10.html) License: GNU Lesser General Public License (http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html) + - JCL 1.2 implemented over SLF4J (http://www.slf4j.org) org.slf4j:jcl-over-slf4j:jar:1.7.36 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - SLF4J API Module (http://www.slf4j.org) org.slf4j:slf4j-api:jar:1.7.36 + License: MIT License (http://www.opensource.org/licenses/mit-license.php) + +From: 'The Apache Software Foundation' (http://pdfbox.apache.org) + - Apache FontBox (http://pdfbox.apache.org/) org.apache.pdfbox:fontbox:bundle:2.0.26 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - PDFBox JBIG2 ImageIO plugin (https://www.apache.org/jbig2-imageio/) org.apache.pdfbox:jbig2-imageio:jar:3.0.4 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache JempBox (http://www.apache.org/pdfbox-parent/jempbox/) org.apache.pdfbox:jempbox:bundle:1.8.16 + License: Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache PDFBox (https://www.apache.org/pdfbox-parent/pdfbox/) org.apache.pdfbox:pdfbox:bundle:2.0.26 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache PDFBox Debugger (https://www.apache.org/pdfbox-parent/pdfbox-debugger/) org.apache.pdfbox:pdfbox-debugger:jar:2.0.26 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache PDFBox tools (https://www.apache.org/pdfbox-parent/pdfbox-tools/) org.apache.pdfbox:pdfbox-tools:jar:2.0.26 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache XmpBox (https://www.apache.org/pdfbox-parent/xmpbox/) org.apache.pdfbox:xmpbox:bundle:2.0.26 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + +From: 'The Apache Software Foundation' (http://www.apache.org) + - Apache Tika core (https://tika.apache.org/) org.apache.tika:tika-core:bundle:2.4.1 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + +From: 'The Apache Software Foundation' (http://www.apache.org/) + - Apache Commons Collections (http://commons.apache.org/collections/) commons-collections:commons-collections:jar:3.2.2 + License: Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt) + - Commons DBCP (http://commons.apache.org/dbcp/) commons-dbcp:commons-dbcp:jar:1.4 + License: The Apache Software License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Commons Logging (http://commons.apache.org/proper/commons-logging/) commons-logging:commons-logging:jar:1.2 + License: The Apache Software License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt) + - Commons Pool (http://commons.apache.org/pool/) commons-pool:commons-pool:jar:1.5.4 + License: The Apache Software License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Commons Exec (http://commons.apache.org/proper/commons-exec/) org.apache.commons:commons-exec:jar:1.3 + License: Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Commons Math (http://commons.apache.org/proper/commons-math/) org.apache.commons:commons-math3:jar:3.6.1 + License: Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache HttpClient (http://hc.apache.org/httpcomponents-client-ga) org.apache.httpcomponents:httpclient:jar:4.5.14 + License: Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache HttpCore (http://hc.apache.org/httpcomponents-core-ga) org.apache.httpcomponents:httpcore:jar:4.4.16 + License: Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt) + - Lucene Core (http://lucene.apache.org/java/lucene-parent/lucene-core) org.apache.lucene:lucene-core:jar:3.6.0 + License: Apache 2 (http://www.apache.org/licenses/LICENSE-2.0.txt) + +From: 'The Apache Software Foundation' (https://www.apache.org/) + - Apache Commons BeanUtils (https://commons.apache.org/proper/commons-beanutils/) commons-beanutils:commons-beanutils:jar:1.9.4 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Commons Codec (https://commons.apache.org/proper/commons-codec/) commons-codec:commons-codec:jar:1.15 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Commons FileUpload (https://commons.apache.org/proper/commons-fileupload/) commons-fileupload:commons-fileupload:jar:1.5 + License: Apache-2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Commons IO (https://commons.apache.org/proper/commons-io/) commons-io:commons-io:jar:2.11.0 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Commons Collections (https://commons.apache.org/proper/commons-collections/) org.apache.commons:commons-collections4:jar:4.4 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Commons CSV (https://commons.apache.org/proper/commons-csv/) org.apache.commons:commons-csv:jar:1.9.0 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Commons Lang (https://commons.apache.org/proper/commons-lang/) org.apache.commons:commons-lang3:jar:3.12.0 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Jackrabbit Core (http://jackrabbit.apache.org/jackrabbit-core/) org.apache.jackrabbit:jackrabbit-core:jar:2.21.16-SNAPSHOT + License: Apache-2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Jackrabbit Data (http://jackrabbit.apache.org/jackrabbit-data/) org.apache.jackrabbit:jackrabbit-data:bundle:2.21.16-SNAPSHOT + License: Apache-2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Jackrabbit JCR Commons (http://jackrabbit.apache.org/jackrabbit-jcr-commons/) org.apache.jackrabbit:jackrabbit-jcr-commons:bundle:2.21.16-SNAPSHOT + License: Apache-2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Jackrabbit JCR-RMI (http://jackrabbit.apache.org/jackrabbit-jcr-rmi/) org.apache.jackrabbit:jackrabbit-jcr-rmi:bundle:2.21.16-SNAPSHOT + License: Apache-2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - jackrabbit-jcr-server-jakarta (http://jackrabbit.apache.org/jackrabbit-jcr-server-project/jackrabbit-jcr-server-jakarta/) org.apache.jackrabbit:jackrabbit-jcr-server-jakarta:jar:2.21.16-SNAPSHOT + License: Apache-2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - jackrabbit-jcr-servlet-jakarta (http://jackrabbit.apache.org/jackrabbit-jcr-servlet-project/jackrabbit-jcr-servlet-jakarta/) org.apache.jackrabbit:jackrabbit-jcr-servlet-jakarta:jar:2.21.16-SNAPSHOT + License: Apache-2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Jackrabbit SPI (http://jackrabbit.apache.org/jackrabbit-spi/) org.apache.jackrabbit:jackrabbit-spi:bundle:2.21.16-SNAPSHOT + License: Apache-2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Jackrabbit SPI Commons (http://jackrabbit.apache.org/jackrabbit-spi-commons/) org.apache.jackrabbit:jackrabbit-spi-commons:bundle:2.21.16-SNAPSHOT + License: Apache-2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - jackrabbit-webdav-jakarta (http://jackrabbit.apache.org/jackrabbit-webdav-project/jackrabbit-webdav-jakarta/) org.apache.jackrabbit:jackrabbit-webdav-jakarta:jar:2.21.16-SNAPSHOT + License: Apache-2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Jackrabbit API (http://jackrabbit.apache.org/oak-jackrabbit-api/) org.apache.jackrabbit:oak-jackrabbit-api:bundle:1.48.0 + License: Apache-2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Log4j API (https://logging.apache.org/log4j/2.x/log4j-api/) org.apache.logging.log4j:log4j-api:jar:2.17.2 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Tika Apple parser module (https://tika.apache.org/tika-parser-apple-module/) org.apache.tika:tika-parser-apple-module:jar:2.4.1 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Tika audiovideo parser module (https://tika.apache.org/tika-parser-audiovideo-module/) org.apache.tika:tika-parser-audiovideo-module:jar:2.4.1 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Tika cad parser module (https://tika.apache.org/tika-parser-cad-module/) org.apache.tika:tika-parser-cad-module:jar:2.4.1 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Tika code parser module (https://tika.apache.org/tika-parser-code-module/) org.apache.tika:tika-parser-code-module:jar:2.4.1 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Tika crypto parser module (https://tika.apache.org/tika-parser-crypto-module/) org.apache.tika:tika-parser-crypto-module:jar:2.4.1 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Tika digest commons (https://tika.apache.org/tika-parser-digest-commons/) org.apache.tika:tika-parser-digest-commons:jar:2.4.1 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Tika font parser module (https://tika.apache.org/tika-parser-font-module/) org.apache.tika:tika-parser-font-module:jar:2.4.1 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Tika html commons (https://tika.apache.org/tika-parser-html-commons/) org.apache.tika:tika-parser-html-commons:jar:2.4.1 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Tika html parser module (https://tika.apache.org/tika-parser-html-module/) org.apache.tika:tika-parser-html-module:jar:2.4.1 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Tika image parser module (https://tika.apache.org/tika-parser-image-module/) org.apache.tika:tika-parser-image-module:jar:2.4.1 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Tika mail commons (https://tika.apache.org/tika-parser-mail-commons/) org.apache.tika:tika-parser-mail-commons:jar:2.4.1 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Tika mail parser module (https://tika.apache.org/tika-parser-mail-module/) org.apache.tika:tika-parser-mail-module:jar:2.4.1 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Tika Microsoft parser module (https://tika.apache.org/tika-parser-microsoft-module/) org.apache.tika:tika-parser-microsoft-module:jar:2.4.1 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Tika miscellaneous office format parser module (https://tika.apache.org/tika-parser-miscoffice-module/) org.apache.tika:tika-parser-miscoffice-module:jar:2.4.1 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Tika news parser module (https://tika.apache.org/tika-parser-news-module/) org.apache.tika:tika-parser-news-module:jar:2.4.1 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Tika OCR parser module (https://tika.apache.org/tika-parser-ocr-module/) org.apache.tika:tika-parser-ocr-module:jar:2.4.1 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Tika PDF parser module (https://tika.apache.org/tika-parser-pdf-module/) org.apache.tika:tika-parser-pdf-module:jar:2.4.1 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Tika package parser module (https://tika.apache.org/tika-parser-pkg-module/) org.apache.tika:tika-parser-pkg-module:jar:2.4.1 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Tika text parser module (https://tika.apache.org/tika-parser-text-module/) org.apache.tika:tika-parser-text-module:jar:2.4.1 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Tika WARC parser module (https://tika.apache.org/tika-parser-webarchive-module/) org.apache.tika:tika-parser-webarchive-module:jar:2.4.1 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Tika XML parser module (https://tika.apache.org/tika-parser-xml-module/) org.apache.tika:tika-parser-xml-module:jar:2.4.1 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Tika XMP commons (https://tika.apache.org/tika-parser-xmp-commons/) org.apache.tika:tika-parser-xmp-commons:jar:2.4.1 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Tika ZIP commons (https://tika.apache.org/tika-parser-zip-commons/) org.apache.tika:tika-parser-zip-commons:jar:2.4.1 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Tika standard parser package (https://tika.apache.org/tika-parsers/tika-parsers-standard/tika-parsers-standard-package/) org.apache.tika:tika-parsers-standard-package:jar:2.4.1 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + +From: 'XmlBeans' (https://xmlbeans.apache.org/) + - XmlBeans (https://xmlbeans.apache.org/) org.apache.xmlbeans:xmlbeans:jar:5.0.3 + License: The Apache Software License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt) + +From: 'Zaxxer.com' (https://github.com/brettwooldridge/SparseBitSet) + - SparseBitSet (https://github.com/brettwooldridge/SparseBitSet) com.zaxxer:SparseBitSet:jar:1.2 + License: The Apache Software License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt) + + + + Index: jackrabbit-webapp-project/jackrabbit-webapp-jakarta/target/test-classes/META-INF/LICENSE =================================================================== --- jackrabbit-webapp-project/jackrabbit-webapp-jakarta/target/test-classes/META-INF/LICENSE (nonexistent) +++ jackrabbit-webapp-project/jackrabbit-webapp-jakarta/target/test-classes/META-INF/LICENSE (working copy) @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed 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. Index: jackrabbit-webapp-project/jackrabbit-webapp-jakarta/target/test-classes/META-INF/NOTICE =================================================================== --- jackrabbit-webapp-project/jackrabbit-webapp-jakarta/target/test-classes/META-INF/NOTICE (nonexistent) +++ jackrabbit-webapp-project/jackrabbit-webapp-jakarta/target/test-classes/META-INF/NOTICE (working copy) @@ -0,0 +1,8 @@ + +jackrabbit-webapp-jakarta +Copyright 2004-1970 The Apache Software Foundation + +This product includes software developed at +The Apache Software Foundation (http://www.apache.org/). + + Index: jackrabbit-webapp-project/pom.xml =================================================================== --- jackrabbit-webapp-project/pom.xml (nonexistent) +++ jackrabbit-webapp-project/pom.xml (working copy) @@ -0,0 +1,108 @@ + + 4.0.0 + + org.apache.jackrabbit + jackrabbit-parent + 2.21.16-SNAPSHOT + ../jackrabbit-parent/pom.xml + + jackrabbit-webapp-project + pom + + jackrabbit-webapp + jackrabbit-webapp-jakarta + + + 8.5.86 + + + + javax.jcr + jcr + compile + + + org.apache.jackrabbit + jackrabbit-core + ${project.version} + + + org.apache.tika + tika-parsers-standard-package + + + org.slf4j + jcl-over-slf4j + + + org.apache.jackrabbit + jackrabbit-jcr-rmi + ${project.version} + + + ch.qos.logback + logback-classic + + + commons-beanutils + commons-beanutils + + + org.apache.tomcat + tomcat-servlet-api + ${tomcat.version} + provided + + + junit + junit + test + + + org.apache.tomcat + tomcat-catalina + ${tomcat.version} + test + + + org.apache.tomcat + tomcat-coyote + ${tomcat.version} + test + + + org.apache.tomcat + tomcat-jasper + ${tomcat.version} + test + + + net.sourceforge.htmlunit + htmlunit + 2.67.0 + test + + + commons-logging + commons-logging + + + + + org.slf4j + jul-to-slf4j + ${slf4j.version} + test + + + com.google.guava + guava + 31.1-jre + test + + + org.apache.derby + derby + + + \ No newline at end of file Index: jackrabbit-webdav-project/jackrabbit-webdav-jakarta/.classpath =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav-jakarta/.classpath (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav-jakarta/.classpath (working copy) @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Index: jackrabbit-webdav-project/jackrabbit-webdav-jakarta/.project =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav-jakarta/.project (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav-jakarta/.project (working copy) @@ -0,0 +1,23 @@ + + + jackrabbit-webdav-jakarta + + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.m2e.core.maven2Builder + + + + + + org.eclipse.jdt.core.javanature + org.eclipse.m2e.core.maven2Nature + + Index: jackrabbit-webdav-project/jackrabbit-webdav-jakarta/.settings/org.eclipse.core.resources.prefs =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav-jakarta/.settings/org.eclipse.core.resources.prefs (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav-jakarta/.settings/org.eclipse.core.resources.prefs (working copy) @@ -0,0 +1,6 @@ +eclipse.preferences.version=1 +encoding//src/main/java=UTF-8 +encoding//src/main/resources=UTF-8 +encoding//src/test/java=UTF-8 +encoding//src/test/resources=UTF-8 +encoding/=UTF-8 Index: jackrabbit-webdav-project/jackrabbit-webdav-jakarta/.settings/org.eclipse.jdt.core.prefs =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav-jakarta/.settings/org.eclipse.jdt.core.prefs (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav-jakarta/.settings/org.eclipse.jdt.core.prefs (working copy) @@ -0,0 +1,8 @@ +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 +org.eclipse.jdt.core.compiler.compliance=1.8 +org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled +org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning +org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=ignore +org.eclipse.jdt.core.compiler.release=disabled +org.eclipse.jdt.core.compiler.source=1.8 Index: jackrabbit-webdav-project/jackrabbit-webdav-jakarta/.settings/org.eclipse.m2e.core.prefs =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav-jakarta/.settings/org.eclipse.m2e.core.prefs (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav-jakarta/.settings/org.eclipse.m2e.core.prefs (working copy) @@ -0,0 +1,4 @@ +activeProfiles= +eclipse.preferences.version=1 +resolveWorkspaceProjects=true +version=1 Index: jackrabbit-webdav-project/jackrabbit-webdav-jakarta/pom.xml =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav-jakarta/pom.xml (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav-jakarta/pom.xml (working copy) @@ -0,0 +1,83 @@ + + 4.0.0 + + org.apache.jackrabbit + jackrabbit-webdav-project + 2.21.16-SNAPSHOT + + jackrabbit-webdav-jakarta + + + + org.eclipse.transformer + transformer-maven-plugin + 0.5.0 + true + + + true + + + + + default-jar + + jar + + + + org.apache.jackrabbit + jackrabbit-webdav + ${project.version} + + + + + + + + + + apache-release + + + + org.eclipse.transformer + transformer-maven-plugin + 0.5.0 + true + + + true + + + + + source-jar + + jar + + + + org.apache.jackrabbit + jackrabbit-webdav + ${project.version} + sources + + + + + + + + + + + + jakarta.servlet + jakarta.servlet-api + 5.0.0 + provided + + + \ No newline at end of file Index: jackrabbit-webdav-project/jackrabbit-webdav-jakarta/target/.plxarc =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav-jakarta/target/.plxarc (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav-jakarta/target/.plxarc (working copy) @@ -0,0 +1 @@ +maven-shared-archive-resources \ No newline at end of file Index: jackrabbit-webdav-project/jackrabbit-webdav-jakarta/target/classes/META-INF/DEPENDENCIES =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav-jakarta/target/classes/META-INF/DEPENDENCIES (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav-jakarta/target/classes/META-INF/DEPENDENCIES (working copy) @@ -0,0 +1,29 @@ +// ------------------------------------------------------------------ +// Transitive dependencies of this project determined from the +// maven pom organized by organization. +// ------------------------------------------------------------------ + +jackrabbit-webdav-jakarta + + +From: 'QOS.ch' (http://www.qos.ch) + - JCL 1.2 implemented over SLF4J (http://www.slf4j.org) org.slf4j:jcl-over-slf4j:jar:1.7.36 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - SLF4J API Module (http://www.slf4j.org) org.slf4j:slf4j-api:jar:1.7.36 + License: MIT License (http://www.opensource.org/licenses/mit-license.php) + +From: 'The Apache Software Foundation' (http://www.apache.org/) + - Apache Commons Logging (http://commons.apache.org/proper/commons-logging/) commons-logging:commons-logging:jar:1.2 + License: The Apache Software License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache HttpClient (http://hc.apache.org/httpcomponents-client-ga) org.apache.httpcomponents:httpclient:jar:4.5.14 + License: Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache HttpCore (http://hc.apache.org/httpcomponents-core-ga) org.apache.httpcomponents:httpcore:jar:4.4.16 + License: Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt) + +From: 'The Apache Software Foundation' (https://www.apache.org/) + - Apache Commons Codec (http://commons.apache.org/proper/commons-codec/) commons-codec:commons-codec:jar:1.11 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + + + + Index: jackrabbit-webdav-project/jackrabbit-webdav-jakarta/target/classes/META-INF/LICENSE =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav-jakarta/target/classes/META-INF/LICENSE (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav-jakarta/target/classes/META-INF/LICENSE (working copy) @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed 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. Index: jackrabbit-webdav-project/jackrabbit-webdav-jakarta/target/classes/META-INF/NOTICE =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav-jakarta/target/classes/META-INF/NOTICE (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav-jakarta/target/classes/META-INF/NOTICE (working copy) @@ -0,0 +1,8 @@ + +jackrabbit-webdav-jakarta +Copyright 2004-1970 The Apache Software Foundation + +This product includes software developed at +The Apache Software Foundation (http://www.apache.org/). + + Index: jackrabbit-webdav-project/jackrabbit-webdav-jakarta/target/classes/META-INF/maven/org.apache.jackrabbit/jackrabbit-webdav-jakarta/pom.properties =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav-jakarta/target/classes/META-INF/maven/org.apache.jackrabbit/jackrabbit-webdav-jakarta/pom.properties (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav-jakarta/target/classes/META-INF/maven/org.apache.jackrabbit/jackrabbit-webdav-jakarta/pom.properties (working copy) @@ -0,0 +1,7 @@ +#Generated by Maven Integration for Eclipse +#Wed Mar 01 12:33:47 CET 2023 +m2e.projectLocation=C\:\\Development\\JackRabbit\\trunk\\jackrabbit-webdav-project\\jackrabbit-webdav-jakarta +m2e.projectName=jackrabbit-webdav-jakarta +groupId=org.apache.jackrabbit +artifactId=jackrabbit-webdav-jakarta +version=2.21.16-SNAPSHOT Index: jackrabbit-webdav-project/jackrabbit-webdav-jakarta/target/classes/META-INF/maven/org.apache.jackrabbit/jackrabbit-webdav-jakarta/pom.xml =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav-jakarta/target/classes/META-INF/maven/org.apache.jackrabbit/jackrabbit-webdav-jakarta/pom.xml (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav-jakarta/target/classes/META-INF/maven/org.apache.jackrabbit/jackrabbit-webdav-jakarta/pom.xml (working copy) @@ -0,0 +1,83 @@ + + 4.0.0 + + org.apache.jackrabbit + jackrabbit-webdav-project + 2.21.16-SNAPSHOT + + jackrabbit-webdav-jakarta + + + + org.eclipse.transformer + transformer-maven-plugin + 0.5.0 + true + + + true + + + + + default-jar + + jar + + + + org.apache.jackrabbit + jackrabbit-webdav + ${project.version} + + + + + + + + + + apache-release + + + + org.eclipse.transformer + transformer-maven-plugin + 0.5.0 + true + + + true + + + + + source-jar + + jar + + + + org.apache.jackrabbit + jackrabbit-webdav + ${project.version} + sources + + + + + + + + + + + + jakarta.servlet + jakarta.servlet-api + 5.0.0 + provided + + + \ No newline at end of file Index: jackrabbit-webdav-project/jackrabbit-webdav-jakarta/target/jackrabbit-webdav-jakarta-2.21.16-SNAPSHOT.jar =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Property changes on: jackrabbit-webdav-project/jackrabbit-webdav-jakarta/target/jackrabbit-webdav-jakarta-2.21.16-SNAPSHOT.jar ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav-jakarta/target/maven-shared-archive-resources/META-INF/DEPENDENCIES =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav-jakarta/target/maven-shared-archive-resources/META-INF/DEPENDENCIES (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav-jakarta/target/maven-shared-archive-resources/META-INF/DEPENDENCIES (working copy) @@ -0,0 +1,29 @@ +// ------------------------------------------------------------------ +// Transitive dependencies of this project determined from the +// maven pom organized by organization. +// ------------------------------------------------------------------ + +jackrabbit-webdav-jakarta + + +From: 'QOS.ch' (http://www.qos.ch) + - JCL 1.2 implemented over SLF4J (http://www.slf4j.org) org.slf4j:jcl-over-slf4j:jar:1.7.36 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - SLF4J API Module (http://www.slf4j.org) org.slf4j:slf4j-api:jar:1.7.36 + License: MIT License (http://www.opensource.org/licenses/mit-license.php) + +From: 'The Apache Software Foundation' (http://www.apache.org/) + - Apache Commons Logging (http://commons.apache.org/proper/commons-logging/) commons-logging:commons-logging:jar:1.2 + License: The Apache Software License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache HttpClient (http://hc.apache.org/httpcomponents-client-ga) org.apache.httpcomponents:httpclient:jar:4.5.14 + License: Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache HttpCore (http://hc.apache.org/httpcomponents-core-ga) org.apache.httpcomponents:httpcore:jar:4.4.16 + License: Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt) + +From: 'The Apache Software Foundation' (https://www.apache.org/) + - Apache Commons Codec (http://commons.apache.org/proper/commons-codec/) commons-codec:commons-codec:jar:1.11 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + + + + Index: jackrabbit-webdav-project/jackrabbit-webdav-jakarta/target/maven-shared-archive-resources/META-INF/LICENSE =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav-jakarta/target/maven-shared-archive-resources/META-INF/LICENSE (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav-jakarta/target/maven-shared-archive-resources/META-INF/LICENSE (working copy) @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed 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. Index: jackrabbit-webdav-project/jackrabbit-webdav-jakarta/target/maven-shared-archive-resources/META-INF/NOTICE =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav-jakarta/target/maven-shared-archive-resources/META-INF/NOTICE (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav-jakarta/target/maven-shared-archive-resources/META-INF/NOTICE (working copy) @@ -0,0 +1,8 @@ + +jackrabbit-webdav-jakarta +Copyright 2004-1970 The Apache Software Foundation + +This product includes software developed at +The Apache Software Foundation (http://www.apache.org/). + + Index: jackrabbit-webdav-project/jackrabbit-webdav-jakarta/target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst =================================================================== Index: jackrabbit-webdav-project/jackrabbit-webdav-jakarta/target/maven-status/maven-compiler-plugin/testCompile/default-testCompile/inputFiles.lst =================================================================== Index: jackrabbit-webdav-project/jackrabbit-webdav-jakarta/target/test-classes/META-INF/DEPENDENCIES =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav-jakarta/target/test-classes/META-INF/DEPENDENCIES (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav-jakarta/target/test-classes/META-INF/DEPENDENCIES (working copy) @@ -0,0 +1,29 @@ +// ------------------------------------------------------------------ +// Transitive dependencies of this project determined from the +// maven pom organized by organization. +// ------------------------------------------------------------------ + +jackrabbit-webdav-jakarta + + +From: 'QOS.ch' (http://www.qos.ch) + - JCL 1.2 implemented over SLF4J (http://www.slf4j.org) org.slf4j:jcl-over-slf4j:jar:1.7.36 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - SLF4J API Module (http://www.slf4j.org) org.slf4j:slf4j-api:jar:1.7.36 + License: MIT License (http://www.opensource.org/licenses/mit-license.php) + +From: 'The Apache Software Foundation' (http://www.apache.org/) + - Apache Commons Logging (http://commons.apache.org/proper/commons-logging/) commons-logging:commons-logging:jar:1.2 + License: The Apache Software License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache HttpClient (http://hc.apache.org/httpcomponents-client-ga) org.apache.httpcomponents:httpclient:jar:4.5.14 + License: Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache HttpCore (http://hc.apache.org/httpcomponents-core-ga) org.apache.httpcomponents:httpcore:jar:4.4.16 + License: Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt) + +From: 'The Apache Software Foundation' (https://www.apache.org/) + - Apache Commons Codec (http://commons.apache.org/proper/commons-codec/) commons-codec:commons-codec:jar:1.11 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + + + + Index: jackrabbit-webdav-project/jackrabbit-webdav-jakarta/target/test-classes/META-INF/LICENSE =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav-jakarta/target/test-classes/META-INF/LICENSE (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav-jakarta/target/test-classes/META-INF/LICENSE (working copy) @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed 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. Index: jackrabbit-webdav-project/jackrabbit-webdav-jakarta/target/test-classes/META-INF/NOTICE =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav-jakarta/target/test-classes/META-INF/NOTICE (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav-jakarta/target/test-classes/META-INF/NOTICE (working copy) @@ -0,0 +1,8 @@ + +jackrabbit-webdav-jakarta +Copyright 2004-1970 The Apache Software Foundation + +This product includes software developed at +The Apache Software Foundation (http://www.apache.org/). + + Index: jackrabbit-jcr-server-project/pom.xml =================================================================== --- jackrabbit-jcr-server-project/pom.xml (nonexistent) +++ jackrabbit-jcr-server-project/pom.xml (working copy) @@ -0,0 +1,110 @@ + + 4.0.0 + + org.apache.jackrabbit + jackrabbit-parent + 2.21.16-SNAPSHOT + ../jackrabbit-parent/pom.xml + + jackrabbit-jcr-server-project + pom + + jackrabbit-jcr-server + jackrabbit-jcr-server-jakarta + + + + javax.jcr + jcr + + + org.apache.jackrabbit + jackrabbit-spi-commons + ${project.version} + + + org.apache.jackrabbit + jackrabbit-jcr-commons + ${project.version} + + + org.apache.tika + tika-core + + + org.slf4j + slf4j-api + + + commons-fileupload + commons-fileupload + + + + + org.osgi + org.osgi.compendium + 5.0.0 + provided + + + org.apache.felix + org.apache.felix.scr.annotations + 1.12.0 + provided + + + org.osgi + org.osgi.annotation + provided + + + + junit + junit + test + + + org.easymock + easymock + test + + + org.apache.jackrabbit + jackrabbit-core + ${project.version} + test + + + org.apache.jackrabbit + jackrabbit-jcr-tests + ${project.version} + test + + + org.eclipse.jetty + jetty-server + test + + + org.eclipse.jetty + jetty-servlet + test + + + ch.qos.logback + logback-classic + test + + + org.mockito + mockito-core + test + + + org.apache.derby + derby + test + + + \ No newline at end of file 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-servlet/README.txt =================================================================== --- jackrabbit-jcr-servlet/README.txt (revision 1907912) +++ jackrabbit-jcr-servlet/README.txt (nonexistent) @@ -1,8 +0,0 @@ -======================================================= -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/README.txt ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-jcr-servlet/pom.xml =================================================================== --- jackrabbit-jcr-servlet/pom.xml (revision 1907912) +++ jackrabbit-jcr-servlet/pom.xml (nonexistent) @@ -1,66 +0,0 @@ - - - - - - 4.0.0 - - org.apache.jackrabbit - jackrabbit-parent - 2.21.16-SNAPSHOT - ../jackrabbit-parent/pom.xml - - - jackrabbit-jcr-servlet - - Jackrabbit JCR Servlets - - Servlets and related classes for easy use of JCR content repositories - in web applications. - - - - - javax.jcr - jcr - - - javax.servlet - javax.servlet-api - provided - - - 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 - - - - Property changes on: jackrabbit-jcr-servlet/pom.xml ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-jcr-servlet/src/main/java/org/apache/jackrabbit/servlet/AbstractRepositoryServlet.java =================================================================== --- jackrabbit-jcr-servlet/src/main/java/org/apache/jackrabbit/servlet/AbstractRepositoryServlet.java (revision 1907912) +++ jackrabbit-jcr-servlet/src/main/java/org/apache/jackrabbit/servlet/AbstractRepositoryServlet.java (nonexistent) @@ -1,196 +0,0 @@ -/* - * 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: - *

-     * <servlet-mapping>
-     *   <servlet-name>Repository</servlet-name>
-     *   <url-pattern>/repository/*</url-pattern>
-     * </servlet-mapping>
-     * 
- *

- * 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/src/main/java/org/apache/jackrabbit/servlet/AbstractRepositoryServlet.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-jcr-servlet/src/main/java/org/apache/jackrabbit/servlet/ContextRepositoryServlet.java =================================================================== --- jackrabbit-jcr-servlet/src/main/java/org/apache/jackrabbit/servlet/ContextRepositoryServlet.java (revision 1907912) +++ jackrabbit-jcr-servlet/src/main/java/org/apache/jackrabbit/servlet/ContextRepositoryServlet.java (nonexistent) @@ -1,106 +0,0 @@ -/* - * 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/src/main/java/org/apache/jackrabbit/servlet/ContextRepositoryServlet.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-jcr-servlet/src/main/java/org/apache/jackrabbit/servlet/FilterRepositoryFactory.java =================================================================== --- jackrabbit-jcr-servlet/src/main/java/org/apache/jackrabbit/servlet/FilterRepositoryFactory.java (revision 1907912) +++ jackrabbit-jcr-servlet/src/main/java/org/apache/jackrabbit/servlet/FilterRepositoryFactory.java (nonexistent) @@ -1,95 +0,0 @@ -/* - * 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/src/main/java/org/apache/jackrabbit/servlet/FilterRepositoryFactory.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-jcr-servlet/src/main/java/org/apache/jackrabbit/servlet/JNDIBindingServlet.java =================================================================== --- jackrabbit-jcr-servlet/src/main/java/org/apache/jackrabbit/servlet/JNDIBindingServlet.java (revision 1907912) +++ jackrabbit-jcr-servlet/src/main/java/org/apache/jackrabbit/servlet/JNDIBindingServlet.java (nonexistent) @@ -1,107 +0,0 @@ -/* - * 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/src/main/java/org/apache/jackrabbit/servlet/JNDIBindingServlet.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-jcr-servlet/src/main/java/org/apache/jackrabbit/servlet/JNDIRepositoryServlet.java =================================================================== --- jackrabbit-jcr-servlet/src/main/java/org/apache/jackrabbit/servlet/JNDIRepositoryServlet.java (revision 1907912) +++ jackrabbit-jcr-servlet/src/main/java/org/apache/jackrabbit/servlet/JNDIRepositoryServlet.java (nonexistent) @@ -1,90 +0,0 @@ -/* - * 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/src/main/java/org/apache/jackrabbit/servlet/JNDIRepositoryServlet.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-jcr-servlet/src/main/java/org/apache/jackrabbit/servlet/ServletRepository.java =================================================================== --- jackrabbit-jcr-servlet/src/main/java/org/apache/jackrabbit/servlet/ServletRepository.java (revision 1907912) +++ jackrabbit-jcr-servlet/src/main/java/org/apache/jackrabbit/servlet/ServletRepository.java (nonexistent) @@ -1,98 +0,0 @@ -/* - * 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. - *

- * A typical way to use this class would be: - *

- * public class MyServlet extends HttpServlet {
- *
- *     private final Repository repository = new ServletRepository(this);
- *
- *     protected void doGet(
- *             HttpServletRequest request, HttpServletResponse response)
- *             throws ServletException, IOException {
- *          try {
- *              Session session = repository.login();
- *              try {
- *                  ...;
- *              } finally {
- *                  session.logout();
- *              }
- *          } catch (RepositoryException e) {
- *              throw new ServletException(e);
- *          }
- *      }
- *
- * }
- * 
- *

- * Starting with version 1.6 this class can also be used by a servlet filter: - *

- * public class MyFilter implements Filter {
- *
- *     private Repository repository;
- *
- *     public void init(FilterConfig config) {
- *         repository = new ServletRepository(config);
- *     }
- *
- *     // ...
- *
- * }
- * 
- - * - * @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/src/main/java/org/apache/jackrabbit/servlet/ServletRepository.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-jcr-servlet/src/main/java/org/apache/jackrabbit/servlet/ServletRepositoryFactory.java =================================================================== --- jackrabbit-jcr-servlet/src/main/java/org/apache/jackrabbit/servlet/ServletRepositoryFactory.java (revision 1907912) +++ jackrabbit-jcr-servlet/src/main/java/org/apache/jackrabbit/servlet/ServletRepositoryFactory.java (nonexistent) @@ -1,95 +0,0 @@ -/* - * 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/src/main/java/org/apache/jackrabbit/servlet/ServletRepositoryFactory.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-jcr-servlet/src/main/java/org/apache/jackrabbit/servlet/jackrabbit/JackrabbitRepositoryServlet.java =================================================================== --- jackrabbit-jcr-servlet/src/main/java/org/apache/jackrabbit/servlet/jackrabbit/JackrabbitRepositoryServlet.java (revision 1907912) +++ jackrabbit-jcr-servlet/src/main/java/org/apache/jackrabbit/servlet/jackrabbit/JackrabbitRepositoryServlet.java (nonexistent) @@ -1,172 +0,0 @@ -/* - * 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/src/main/java/org/apache/jackrabbit/servlet/jackrabbit/JackrabbitRepositoryServlet.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-jcr-servlet/src/main/java/org/apache/jackrabbit/servlet/jackrabbit/StatisticsServlet.java =================================================================== --- jackrabbit-jcr-servlet/src/main/java/org/apache/jackrabbit/servlet/jackrabbit/StatisticsServlet.java (revision 1907912) +++ jackrabbit-jcr-servlet/src/main/java/org/apache/jackrabbit/servlet/jackrabbit/StatisticsServlet.java (nonexistent) @@ -1,108 +0,0 @@ -/* - * 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/src/main/java/org/apache/jackrabbit/servlet/jackrabbit/StatisticsServlet.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-jcr-servlet/src/main/java/org/apache/jackrabbit/servlet/login/AbstractLoginFilter.java =================================================================== --- jackrabbit-jcr-servlet/src/main/java/org/apache/jackrabbit/servlet/login/AbstractLoginFilter.java (revision 1907912) +++ jackrabbit-jcr-servlet/src/main/java/org/apache/jackrabbit/servlet/login/AbstractLoginFilter.java (nonexistent) @@ -1,113 +0,0 @@ -/* - * 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/src/main/java/org/apache/jackrabbit/servlet/login/AbstractLoginFilter.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-jcr-servlet/src/main/java/org/apache/jackrabbit/servlet/login/BasicLoginFilter.java =================================================================== --- jackrabbit-jcr-servlet/src/main/java/org/apache/jackrabbit/servlet/login/BasicLoginFilter.java (revision 1907912) +++ jackrabbit-jcr-servlet/src/main/java/org/apache/jackrabbit/servlet/login/BasicLoginFilter.java (nonexistent) @@ -1,38 +0,0 @@ -/* - * 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/src/main/java/org/apache/jackrabbit/servlet/login/BasicLoginFilter.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-jcr-servlet/src/main/java/org/apache/jackrabbit/servlet/login/ContainerLoginFilter.java =================================================================== --- jackrabbit-jcr-servlet/src/main/java/org/apache/jackrabbit/servlet/login/ContainerLoginFilter.java (revision 1907912) +++ jackrabbit-jcr-servlet/src/main/java/org/apache/jackrabbit/servlet/login/ContainerLoginFilter.java (nonexistent) @@ -1,64 +0,0 @@ -/* - * 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/src/main/java/org/apache/jackrabbit/servlet/login/ContainerLoginFilter.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-jcr-servlet/src/main/java/org/apache/jackrabbit/servlet/login/NullLoginFilter.java =================================================================== --- jackrabbit-jcr-servlet/src/main/java/org/apache/jackrabbit/servlet/login/NullLoginFilter.java (revision 1907912) +++ jackrabbit-jcr-servlet/src/main/java/org/apache/jackrabbit/servlet/login/NullLoginFilter.java (nonexistent) @@ -1,43 +0,0 @@ -/* - * 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/src/main/java/org/apache/jackrabbit/servlet/login/NullLoginFilter.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-jcr-servlet/src/main/java/org/apache/jackrabbit/servlet/remote/JNDIRemoteBindingServlet.java =================================================================== --- jackrabbit-jcr-servlet/src/main/java/org/apache/jackrabbit/servlet/remote/JNDIRemoteBindingServlet.java (revision 1907912) +++ jackrabbit-jcr-servlet/src/main/java/org/apache/jackrabbit/servlet/remote/JNDIRemoteBindingServlet.java (nonexistent) @@ -1,118 +0,0 @@ -/* - * 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". - *
- *
org.apache.jackrabbit.rmi.server.RemoteAdapterFactory
- *
- * 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/src/main/java/org/apache/jackrabbit/servlet/remote/JNDIRemoteBindingServlet.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-jcr-servlet/src/main/java/org/apache/jackrabbit/servlet/remote/JNDIRemoteRepositoryServlet.java =================================================================== --- jackrabbit-jcr-servlet/src/main/java/org/apache/jackrabbit/servlet/remote/JNDIRemoteRepositoryServlet.java (revision 1907912) +++ jackrabbit-jcr-servlet/src/main/java/org/apache/jackrabbit/servlet/remote/JNDIRemoteRepositoryServlet.java (nonexistent) @@ -1,107 +0,0 @@ -/* - * 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". - *
- *
org.apache.jackrabbit.rmi.client.LocalAdapterFactory
- *
- * 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/src/main/java/org/apache/jackrabbit/servlet/remote/JNDIRemoteRepositoryServlet.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-jcr-servlet/src/main/java/org/apache/jackrabbit/servlet/remote/RMIRemoteBindingServlet.java =================================================================== --- jackrabbit-jcr-servlet/src/main/java/org/apache/jackrabbit/servlet/remote/RMIRemoteBindingServlet.java (revision 1907912) +++ jackrabbit-jcr-servlet/src/main/java/org/apache/jackrabbit/servlet/remote/RMIRemoteBindingServlet.java (nonexistent) @@ -1,97 +0,0 @@ -/* - * 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". - *
- *
org.apache.jackrabbit.rmi.server.RemoteAdapterFactory
- *
- * 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/src/main/java/org/apache/jackrabbit/servlet/remote/RMIRemoteBindingServlet.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-jcr-servlet/src/main/java/org/apache/jackrabbit/servlet/remote/RMIRemoteRepositoryServlet.java =================================================================== --- jackrabbit-jcr-servlet/src/main/java/org/apache/jackrabbit/servlet/remote/RMIRemoteRepositoryServlet.java (revision 1907912) +++ jackrabbit-jcr-servlet/src/main/java/org/apache/jackrabbit/servlet/remote/RMIRemoteRepositoryServlet.java (nonexistent) @@ -1,76 +0,0 @@ -/* - * 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". - *
- *
org.apache.jackrabbit.rmi.client.LocalAdapterFactory
- *
- * 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/src/main/java/org/apache/jackrabbit/servlet/remote/RMIRemoteRepositoryServlet.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-jcr-servlet/src/main/java/org/apache/jackrabbit/servlet/remote/RemoteBindingServlet.java =================================================================== --- jackrabbit-jcr-servlet/src/main/java/org/apache/jackrabbit/servlet/remote/RemoteBindingServlet.java (revision 1907912) +++ jackrabbit-jcr-servlet/src/main/java/org/apache/jackrabbit/servlet/remote/RemoteBindingServlet.java (nonexistent) @@ -1,139 +0,0 @@ -/* - * 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". - *
- *
org.apache.jackrabbit.rmi.server.RemoteAdapterFactory
- *
- * 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/src/main/java/org/apache/jackrabbit/servlet/remote/RemoteBindingServlet.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-jcr-servlet/src/main/java/org/apache/jackrabbit/servlet/remote/RemoteRepositoryServlet.java =================================================================== --- jackrabbit-jcr-servlet/src/main/java/org/apache/jackrabbit/servlet/remote/RemoteRepositoryServlet.java (revision 1907912) +++ jackrabbit-jcr-servlet/src/main/java/org/apache/jackrabbit/servlet/remote/RemoteRepositoryServlet.java (nonexistent) @@ -1,81 +0,0 @@ -/* - * 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". - *
- *
org.apache.jackrabbit.rmi.client.LocalAdapterFactory
- *
- * 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/src/main/java/org/apache/jackrabbit/servlet/remote/RemoteRepositoryServlet.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-jcr-servlet/src/main/java/org/apache/jackrabbit/servlet/remote/URLRemoteBindingServlet.java =================================================================== --- jackrabbit-jcr-servlet/src/main/java/org/apache/jackrabbit/servlet/remote/URLRemoteBindingServlet.java (revision 1907912) +++ jackrabbit-jcr-servlet/src/main/java/org/apache/jackrabbit/servlet/remote/URLRemoteBindingServlet.java (nonexistent) @@ -1,84 +0,0 @@ -/* - * 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". - *
- *
org.apache.jackrabbit.rmi.server.RemoteAdapterFactory
- *
- * 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/src/main/java/org/apache/jackrabbit/servlet/remote/URLRemoteBindingServlet.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-jcr-servlet/src/main/java/org/apache/jackrabbit/servlet/remote/URLRemoteRepositoryServlet.java =================================================================== --- jackrabbit-jcr-servlet/src/main/java/org/apache/jackrabbit/servlet/remote/URLRemoteRepositoryServlet.java (revision 1907912) +++ jackrabbit-jcr-servlet/src/main/java/org/apache/jackrabbit/servlet/remote/URLRemoteRepositoryServlet.java (nonexistent) @@ -1,84 +0,0 @@ -/* - * 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". - *
- *
org.apache.jackrabbit.rmi.client.LocalAdapterFactory
- *
- * 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/src/main/java/org/apache/jackrabbit/servlet/remote/URLRemoteRepositoryServlet.java ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Index: jackrabbit-jcr-servlet =================================================================== --- jackrabbit-jcr-servlet (revision 1907912) +++ jackrabbit-jcr-servlet (nonexistent) Property changes on: jackrabbit-jcr-servlet ___________________________________________________________________ Deleted: svn:ignore ## -1,5 +0,0 ## -target -.* -*.iml -*.ipr -*.iws Index: jackrabbit-webapp-project/jackrabbit-webapp/pom.xml =================================================================== --- jackrabbit-webapp-project/jackrabbit-webapp/pom.xml (nonexistent) +++ jackrabbit-webapp-project/jackrabbit-webapp/pom.xml (working copy) @@ -0,0 +1,117 @@ + + + + + + 4.0.0 + + + + + + org.apache.jackrabbit + jackrabbit-webapp-project + 2.21.16-SNAPSHOT + + jackrabbit-webapp + war + Jackrabbit Web Application + Web application that hosts and serves a Jackrabbit content repository + + + + org.apache.jackrabbit + jackrabbit-jcr-server + ${project.version} + + + org.apache.jackrabbit + jackrabbit-jcr-servlet + ${project.version} + + + + + + + + maven-antrun-plugin + + + package + + + + + + + run + + + + + + + org.codehaus.mojo + build-helper-maven-plugin + + + attach-artifacts + package + + attach-artifact + + + + + ${project.build.directory}/jackrabbit-webapp-${project.version}.jar + jar + + + + + + + + org.apache.rat + apache-rat-plugin + + + src/main/webapp/WEB-INF/log4j.dtd + + + + + + + + maven-failsafe-plugin + + + + derby.stream.error.file + target/derby.log + + + + + + + + + Property changes on: jackrabbit-webapp-project/jackrabbit-webapp/pom.xml ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-jcr-server-project/jackrabbit-jcr-server-jakarta/pom.xml =================================================================== --- jackrabbit-jcr-server-project/jackrabbit-jcr-server-jakarta/pom.xml (nonexistent) +++ jackrabbit-jcr-server-project/jackrabbit-jcr-server-jakarta/pom.xml (working copy) @@ -0,0 +1,88 @@ + + 4.0.0 + + org.apache.jackrabbit + jackrabbit-jcr-server-project + 2.21.16-SNAPSHOT + + jackrabbit-jcr-server-jakarta + + + + org.eclipse.transformer + transformer-maven-plugin + 0.5.0 + true + + + true + + + + + default-jar + + jar + + + + org.apache.jackrabbit + jackrabbit-jcr-server + ${project.version} + + + + + + + + + + apache-release + + + + org.eclipse.transformer + transformer-maven-plugin + 0.5.0 + true + + + true + + + + + source-jar + + jar + + + + org.apache.jackrabbit + jackrabbit-jcr-server + ${project.version} + sources + + + + + + + + + + + + org.apache.jackrabbit + jackrabbit-webdav-jakarta + ${project.version} + + + jakarta.servlet + jakarta.servlet-api + 5.0.0 + provided + + + \ No newline at end of file Index: jackrabbit-webdav-project/jackrabbit-webdav/README.txt =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/README.txt (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/README.txt (working copy) @@ -0,0 +1,81 @@ +==================================== +Welcome to Jackrabbit WebDAV Library +==================================== + +This is the WebDAV Library component of the Apache Jackrabbit project. +This component provides interfaces and common utility classes used for +building a WebDAV server or client. The following RFC have been integrated: + + * RFC 2518 (WebDAV - HTTP Extensions for Distributed Authoring) + * RFC 3253 (DeltaV - Versioning Extensions to WebDAV) + * RFC 3648 (Ordered Collections Protocol) + * RFC 3744 (Access Control Protocol) + * DAV Searching and Locating (DASL) + * Binding Extensions to Web Distributed Authoring and Versioning (WebDAV) (experimental) + +In addition this library defines (unspecified) + + * Observation + * Bundling multiple request with extensions to locking + +Common Questions +================ + +Q: Which WebDAV features are supported? +A: DAV 1, 2, DeltaV, Ordering, Access Control, Search, Bind + +Q: This this WebDAV library provide a full dav server? +A: This library only defines interfaces, utilities and common + classes used for a dav server/client. + A JCR specific implementation can be found in the 'jcr-server' + and the 'webapp' project. + +Q: How do a get a deployable Jackrabbit installation with WebDAV and + optional RMI support? +A: The 'webdav' project only serves as library. In order to access + a Jackrabbit repository please follow the instructions present + with the 'webapp' project. + +Q: Does the WebDAV library has dependency to JSR170 +A: No, the library can be used as generic webdav library in any + other project. There exists a dependency to the jackrabbit-commons + library for utility classes only. + +Things to do +============ + +------------------------------------------------------------------- +todo webdav/version +------------------------------------------------------------------- + +- review: compliance to deltaV +- reconsider feature-sets (see also JCR-394) +- CHECKOUT may contain request body (working-resource, activity, checkout-in-place) +- CHECKIN may contain request body (working-resource, checkout-in-place) +- VERSION-CONTROL may contain request body (workspace f.) +- BASELINE: creation of Baseline resources is not yet supported + (TODO within AbstractWebDAVServlet) + +------------------------------------------------------------------- +todo webdav/ordering +------------------------------------------------------------------- + +- respect Position header with creation of new collection members by + PUT, COPY, MKCOL requests + +------------------------------------------------------------------- +todo webdav/search +------------------------------------------------------------------- + +- SearchResource should extend DavResource +- Library misses support for the DAV:basicsearch + +------------------------------------------------------------------- +todo webdav/transaction +------------------------------------------------------------------- + +- review naming of the lock scopes. 'global','local' are not correct in + this context. +- j2ee explicitely requires any usertransaction to be completed + upon the end of the servletes service method. + general review necessary. Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/README.txt ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +author date id revision \ No newline at end of property 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-webdav-project/jackrabbit-webdav/src/main/appended-resources/META-INF/NOTICE =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/appended-resources/META-INF/NOTICE (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/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-webdav-project/jackrabbit-webdav/src/main/appended-resources/META-INF/NOTICE ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +author date id revision \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/AbstractLocatorFactory.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/AbstractLocatorFactory.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/AbstractLocatorFactory.java (working copy) @@ -0,0 +1,403 @@ +/* + * 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.webdav; + +import org.apache.jackrabbit.webdav.util.EncodeUtil; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * {@code AbstractLocatorFactory} is an implementation of the DavLocatorFactory + * interface that defines how a given URI is split to workspace path and + * resource path and how it's implementation of {@code DavResourceLocator} + * builds the href. In contrast, the conversion from repository path to + * resource path and vice versa is left to subclasses. + */ +public abstract class AbstractLocatorFactory implements DavLocatorFactory { + + private static Logger log = LoggerFactory.getLogger(AbstractLocatorFactory.class); + + private final String pathPrefix; + + /** + * Create a new factory + * + * @param pathPrefix Prefix, that needs to be removed in order to retrieve + * the path of the repository item from a given {@code DavResourceLocator}. + */ + public AbstractLocatorFactory(String pathPrefix) { + this.pathPrefix = pathPrefix; + } + + //--------------------------------------------------< DavLocatorFactory >--- + /** + * Create a new {@code DavResourceLocator}. Any leading prefix and + * path-prefix (as defined with the constructor) are removed from the + * given request handle. The same applies for trailing '/'. The remaining + * String is called the 'resource handle' and it's first segment is treated + * as workspace name. If resource handle (and therefore workspace name) + * are missing, both values are set to {@code null}. + *

+ * Examples: + * + *

+     * http://www.foo.bar/ (path prefix missing)
+     * -> workspace path = null
+     * -> resource path  = null
+     * -> href           = http://www.foo.bar/pathPrefix/
+     *
+     * http://www.foo.bar/pathPrefix/
+     * -> workspace path = null
+     * -> resource path  = null
+     * -> href           = http://www.foo.bar/pathPrefix/
+     *
+     * http://www.foo.bar/pathPrefix/wspName
+     * -> workspace path = /wspName
+     * -> resource path  = /wspName
+     * -> href           = http://www.foo.bar/pathPrefix/wspName
+     *
+     * http://www.foo.bar/pathPrefix/wspName/anypath
+     * -> workspace path = /wspName
+     * -> resource path  = /wspName/anypath
+     * -> href           = http://www.foo.bar/pathPrefix/wspName/anypath
+     * 
+ * + * NOTE: If the given href is an absolute URI it must start with the + * specified prefix. + * + * @param prefix + * @param href + * @return a new {@code DavResourceLocator} + * @throws IllegalArgumentException if the given href is {@code null} + */ + public DavResourceLocator createResourceLocator(String prefix, String href) { + if (href == null) { + throw new IllegalArgumentException("Request handle must not be null."); + } + + // build prefix string and remove all prefixes from the given href. + StringBuffer b = new StringBuffer(""); + if (prefix != null && prefix.length() > 0) { + b.append(prefix); + if (href.startsWith(prefix)) { + href = href.substring(prefix.length()); + } + } + if (pathPrefix != null && pathPrefix.length() > 0) { + if (!b.toString().endsWith(pathPrefix)) { + b.append(pathPrefix); + } + if (href.startsWith(pathPrefix)) { + href = href.substring(pathPrefix.length()); + } + } + + // remove trailing "/" that is present with collections + if (href.endsWith("/")) { + href = href.substring(0, href.length() - 1); + } + + String resourcePath; + String workspacePath; + + // an empty requestHandle (after removal of the "/") signifies a request + // to the root that does not represent a repository item. + if ("".equals(href)) { + resourcePath = null; + workspacePath = null; + } else { + resourcePath = EncodeUtil.unescape(href); + // retrieve wspPath: look for the first slash ignoring the leading one + int pos = href.indexOf('/', 1); + if (pos == -1) { + // request to a 'workspace' resource + workspacePath = resourcePath; + } else { + // separate the workspace path from the resource path. + workspacePath = EncodeUtil.unescape(href.substring(0, pos)); + } + } + + log.trace("createResourceLocator: prefix='" + prefix + "' href='" + href + "' -> prefix='" + b.toString() + + "' workspacePath='" + workspacePath + "' resourcePath='" + resourcePath + "'"); + return new DavResourceLocatorImpl(b.toString(), workspacePath, resourcePath, this); + } + + /** + * Like {@link #createResourceLocator(String, String)}, but by setting + * {@code forDestination} to {@code true} any special processing of URI + * suffixes can be disabled. + */ + public DavResourceLocator createResourceLocator(String prefix, String href, boolean forDestination) { + return createResourceLocator(prefix, href); + } + + /** + * Create a new {@code DavResourceLocator} from the specified prefix, + * workspace path and resource path, without modifying the specified Strings. + * Note, that it is expected that the resource path starts with the + * given workspace path unless both values are {@code null}. + * + * @param prefix + * @param workspacePath path or the workspace containing this resource or + * {@code null}. + * @param resourcePath Path of the resource or {@code null}. Any non + * null value must start with the specified workspace path. + * @return a new {@code DavResourceLocator} + * @see DavLocatorFactory#createResourceLocator(String, String, String) + */ + public DavResourceLocator createResourceLocator(String prefix, String workspacePath, String resourcePath) { + return createResourceLocator(prefix, workspacePath, resourcePath, true); + } + + /** + * Create a new {@code DavResourceLocator} from the specified prefix, + * workspace path and resource path. If {@code isResourcePath} is set + * to {@code false}, the given 'resourcePath' is converted by calling + * {@link #getResourcePath(String, String)}. Otherwise the same restriction + * applies as for {@link #createResourceLocator(String, String, String)}. + * + * @param prefix + * @param workspacePath + * @param path + * @param isResourcePath + * @return + * @see DavLocatorFactory#createResourceLocator(String, String, String, boolean) + */ + public DavResourceLocator createResourceLocator(String prefix, String workspacePath, String path, boolean isResourcePath) { + String resourcePath = (isResourcePath) ? path : getResourcePath(path, workspacePath); + return new DavResourceLocatorImpl(prefix, workspacePath, resourcePath, this); + } + + //-------------------------------------------------------------------------- + /** + * Subclasses must defined how the repository path is built from the given + * resource and workspace path. + * + * @param resourcePath + * @param wspPath + * @return + */ + protected abstract String getRepositoryPath(String resourcePath, String wspPath); + + /** + * Subclasses must defined how the resource path is built from the given + * repository and workspace path. + * + * @param repositoryPath + * @param wspPath + * @return + */ + protected abstract String getResourcePath(String repositoryPath, String wspPath); + + //--------------------------------------------------------< DavResource >--- + /** + * Private inner class {@code DavResourceLocatorImpl} implementing + * the {@code DavResourceLocator} interface. + */ + private class DavResourceLocatorImpl implements DavResourceLocator { + + private final String prefix; + private final String workspacePath; + private final String resourcePath; + private final AbstractLocatorFactory factory; + + private final String href; + + /** + * Create a new {@code DavResourceLocatorImpl}. + * + * @param prefix + * @param workspacePath + * @param resourcePath + */ + private DavResourceLocatorImpl(String prefix, String workspacePath, String resourcePath, AbstractLocatorFactory factory) { + + this.prefix = prefix; + this.workspacePath = workspacePath; + this.resourcePath = resourcePath; + this.factory = factory; + + StringBuffer buf = new StringBuffer(prefix); + // NOTE: no need to append the workspace path, since it must + // be part of the resource path. + if (resourcePath != null && resourcePath.length() > 0) { + // check if condition is really met + if (!resourcePath.startsWith(workspacePath)) { + throw new IllegalArgumentException("Resource path '" + resourcePath + "' does not start with workspace path '" + workspacePath + "'."); + } + buf.append(EncodeUtil.escapePath(resourcePath)); + } + int length = buf.length(); + if (length == 0 || (length > 0 && buf.charAt(length - 1) != '/')) { + buf.append("/"); + } + this.href = buf.toString(); + } + + /** + * Return the prefix used to build the href String. This includes the initial + * hrefPrefix as well a the path prefix. + * + * @return prefix String used to build the href. + */ + public String getPrefix() { + return prefix; + } + + /** + * Returns the resource path which always starts with the workspace + * path, if a workspace resource exists. For the top most resource + * (request handle '/'), {@code null} is returned. + * + * @return resource path or {@code null} + * @see org.apache.jackrabbit.webdav.DavResourceLocator#getResourcePath() + */ + public String getResourcePath() { + return resourcePath; + } + + /** + * Return the workspace path or {@code null} if this locator object + * represents the '/' request handle. + * + * @return workspace path or {@code null} + * @see org.apache.jackrabbit.webdav.DavResourceLocator#getWorkspacePath() + */ + public String getWorkspacePath() { + return workspacePath; + } + + /** + * Return the workspace name or {@code null} if this locator object + * represents the '/' request handle, which does not contain a workspace + * path. + * + * @return workspace name or {@code null} + * @see org.apache.jackrabbit.webdav.DavResourceLocator#getWorkspaceName() + */ + public String getWorkspaceName() { + if (workspacePath != null && workspacePath.length() > 0) { + return workspacePath.substring(1); + } + return null; + } + + /** + * Returns true if the specified locator object refers to a resource within + * the same workspace. + * + * @param locator + * @return true if the workspace name obtained from the given locator + * refers to the same workspace as the workspace name of this locator. + * @see DavResourceLocator#isSameWorkspace(org.apache.jackrabbit.webdav.DavResourceLocator) + */ + public boolean isSameWorkspace(DavResourceLocator locator) { + return (locator == null) ? false : isSameWorkspace(locator.getWorkspaceName()); + } + + /** + * Returns true if the specified string equals to this workspace name or + * if both names are null. + * + * @param workspaceName + * @return true if the workspace name is equal to this workspace name. + * @see DavResourceLocator#isSameWorkspace(String) + */ + public boolean isSameWorkspace(String workspaceName) { + String thisWspName = getWorkspaceName(); + return (thisWspName == null) ? workspaceName == null : thisWspName.equals(workspaceName); + } + + /** + * Returns an 'href' consisting of prefix and resource path (which starts + * with the workspace path). It assures a trailing '/' in case the href + * is used for collection. Note, that the resource path is + * {@link org.apache.jackrabbit.webdav.util.EncodeUtil#escapePath(String) escaped}. + * + * @param isCollection + * @return href String representing the text of the href element + * @see org.apache.jackrabbit.webdav.DavConstants#XML_HREF + * @see DavResourceLocator#getHref(boolean) + */ + public String getHref(boolean isCollection) { + return (isCollection) ? href : href.substring(0, href.length() - 1); + } + + /** + * Returns true if the 'workspacePath' field is {@code null}. + * + * @return true if the 'workspacePath' field is {@code null}. + * @see org.apache.jackrabbit.webdav.DavResourceLocator#isRootLocation() + */ + public boolean isRootLocation() { + return getWorkspacePath() == null; + } + + /** + * Return the factory that created this locator. + * + * @return factory + * @see org.apache.jackrabbit.webdav.DavResourceLocator#getFactory() + */ + public DavLocatorFactory getFactory() { + return factory; + } + + /** + * Uses {@link AbstractLocatorFactory#getRepositoryPath(String, String)} + * to build the repository path. + * + * @see DavResourceLocator#getRepositoryPath() + */ + public String getRepositoryPath() { + return factory.getRepositoryPath(getResourcePath(), getWorkspacePath()); + } + + /** + * Computes the hash code from the href, that is built from the prefix, + * the workspace name and the resource path all of them representing + * final instance fields. + * + * @return the hash code + */ + @Override + public int hashCode() { + return href.hashCode(); + } + + /** + * Returns true, if the given object is a {@code DavResourceLocatorImpl} + * with the same hash code. + * + * @param obj the object to compare to + * @return {@code true} if the 2 objects are equal; + * {@code false} otherwise + */ + @Override + public boolean equals(Object obj) { + if (obj == this) { + return true; + } + if (obj instanceof DavResourceLocatorImpl) { + DavResourceLocatorImpl other = (DavResourceLocatorImpl) obj; + return hashCode() == other.hashCode(); + } + return false; + } + } +} Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/AbstractLocatorFactory.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-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/ContentCodingAwareRequest.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/ContentCodingAwareRequest.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/ContentCodingAwareRequest.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.webdav; + +import java.util.List; + +import javax.xml.namespace.QName; + +public interface ContentCodingAwareRequest { + + /** + * Element name for signaling "must be supported content coding" + */ + public final QName PRECONDITION_SUPPORTED = new QName("http://www.day.com/jcr/webdav/1.0", "supported-content-coding", "dcr"); + + /** + * @return value suitable for Accept response field + */ + public String getAcceptableCodings(); + + /** + * @return content codings used in request + */ + public List getRequestContentCodings(); +} Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/ContentCodingAwareRequest.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/DavCompliance.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/DavCompliance.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/DavCompliance.java (working copy) @@ -0,0 +1,72 @@ +/* + * 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.webdav; + +/** + * DavCompliance defines constants for the various compliance + * classes defined RFC 2518, RFC 4918 and it's extensions. + */ +public final class DavCompliance { + + /** + * Avoid instantiation + */ + private DavCompliance() {} + + // RFC 2518 + public static final String _1_ = "1"; + public static final String _2_ = "2"; + + // RFC 4918 + public static final String _3_ = "3"; + + // RFC 3253 + public static final String ACTIVITY = "activity"; + public static final String BASELINE = "baseline"; + public static final String CHECKOUT_IN_PLACE = "checkout-in-place"; + public static final String LABEL = "label"; + public static final String MERGE = "merge"; + public static final String UPDATE = "update"; + public static final String VERSION_CONTROL = "version-control"; + public static final String VERSION_CONTROLLED_COLLECTION = "version-controlled-collection"; + public static final String VERSION_HISTORY = "version-history"; + public static final String WORKING_RESOURCE = "working-resource"; + public static final String WORKSPACE = "workspace"; + + // RFC 3648 + public static final String ORDERED_COLLECTIONS = "ordered-collections"; + + // RFC 3744 + public static final String ACCESS_CONTROL = "access-control"; + + // RFC 5842 + public static final String BIND = "bind"; + + // no RFC + public static final String OBSERVATION = "observation"; + + public static String concatComplianceClasses(String[] complianceClasses) { + StringBuffer b = new StringBuffer(); + for (int i = 0; i < complianceClasses.length; i++) { + if (i > 0) { + b.append(","); + } + b.append(complianceClasses[i]); + } + return b.toString(); + } +} \ No newline at end of file Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/DavCompliance.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-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/DavConstants.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/DavConstants.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/DavConstants.java (working copy) @@ -0,0 +1,154 @@ +/* + * 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.webdav; + +import org.apache.jackrabbit.webdav.util.HttpDateFormat; +import org.apache.jackrabbit.webdav.xml.Namespace; + +import java.text.DateFormat; + +/** + * DavConstants provide constants for request and response + * headers, XML elements and property names defined by + * RFC 2518. In addition, + * common date formats (creation date and modification time) are included. + */ +public interface DavConstants { + + /** + * Default Namespace constant + */ + public static final Namespace NAMESPACE = Namespace.getNamespace("D", "DAV:"); + + //--------------------------------< Headers (Names and Value Constants) >--- + public static final String HEADER_DAV = "DAV"; + public static final String HEADER_DESTINATION = "Destination"; + public static final String HEADER_IF = "If"; + public static final String HEADER_AUTHORIZATION = "Authorization"; + public static final String HEADER_CONTENT_TYPE = "Content-Type"; + public static final String HEADER_CONTENT_LENGTH = "Content-Length"; + public static final String HEADER_CONTENT_LANGUAGE = "Content-Language"; + public static final String HEADER_ETAG = "ETag"; + public static final String HEADER_LAST_MODIFIED = "Last-Modified"; + + //--------------------------------------------------< Lock-Token Header >--- + public static final String HEADER_LOCK_TOKEN = "Lock-Token"; + public static final String OPAQUE_LOCK_TOKEN_PREFIX = "opaquelocktoken:"; + + //-----------------------------------------------------< Timeout Header >--- + public static final String HEADER_TIMEOUT = "Timeout"; + public static final String TIMEOUT_INFINITE = "Infinite"; + // RFC 2518: timeout value for TimeType "Second" MUST NOT be greater than 2^32-1 + public static final long INFINITE_TIMEOUT = Integer.MAX_VALUE; + public static final long UNDEFINED_TIMEOUT = Integer.MIN_VALUE; + + //---------------------------------------------------< Overwrite Header >--- + public static final String HEADER_OVERWRITE = "Overwrite"; + + //-------------------------------------------------------< Depth Header >--- + public static final String HEADER_DEPTH = "Depth"; + public static final String DEPTH_INFINITY_S = "infinity"; + public static final int DEPTH_INFINITY = Integer.MAX_VALUE; + public static final int DEPTH_0 = 0; + public static final int DEPTH_1 = 1; + + //---< XML Element, Attribute Names >--------------------------------------- + public static final String XML_ALLPROP = "allprop"; + public static final String XML_COLLECTION = "collection"; + public static final String XML_DST = "dst"; + public static final String XML_HREF = "href"; + public static final String XML_INCLUDE = "include"; + public static final String XML_KEEPALIVE = "keepalive"; + public static final String XML_LINK = "link"; + public static final String XML_MULTISTATUS = "multistatus"; + public static final String XML_OMIT = "omit"; + public static final String XML_PROP = "prop"; + public static final String XML_PROPERTYBEHAVIOR = "propertybehavior"; + public static final String XML_PROPERTYUPDATE = "propertyupdate"; + public static final String XML_PROPFIND = "propfind"; + public static final String XML_PROPNAME = "propname"; + public static final String XML_PROPSTAT = "propstat"; + public static final String XML_REMOVE = "remove"; + public static final String XML_RESPONSE = "response"; + public static final String XML_RESPONSEDESCRIPTION = "responsedescription"; + public static final String XML_SET = "set"; + public static final String XML_SOURCE = "source"; + public static final String XML_STATUS = "status"; + + //------------------------------------------------------------< locking >--- + public static final String XML_ACTIVELOCK = "activelock"; + public static final String XML_DEPTH = "depth"; + public static final String XML_LOCKTOKEN = "locktoken"; + public static final String XML_TIMEOUT = "timeout"; + public static final String XML_LOCKSCOPE = "lockscope"; + public static final String XML_EXCLUSIVE = "exclusive"; + public static final String XML_SHARED = "shared"; + public static final String XML_LOCKENTRY = "lockentry"; + public static final String XML_LOCKINFO = "lockinfo"; + public static final String XML_LOCKTYPE = "locktype"; + public static final String XML_WRITE = "write"; + public static final String XML_OWNER = "owner"; + /** + * The lockroot XML element + * @see RFC 4918 + */ + public static final String XML_LOCKROOT = "lockroot"; + + //-----------------------------------------------------< Property Names >--- + /* + * Webdav property names as defined by RFC 2518
+ * Note: Microsoft webdav clients as well as Webdrive request additional + * property (e.g. href, name, owner, isRootLocation, isCollection) within the + * default namespace, which are are ignored by this implementation, except + * for the 'isCollection' property, needed for XP built-in clients. + */ + public static final String PROPERTY_CREATIONDATE = "creationdate"; + public static final String PROPERTY_DISPLAYNAME = "displayname"; + public static final String PROPERTY_GETCONTENTLANGUAGE = "getcontentlanguage"; + public static final String PROPERTY_GETCONTENTLENGTH = "getcontentlength"; + public static final String PROPERTY_GETCONTENTTYPE = "getcontenttype"; + public static final String PROPERTY_GETETAG = "getetag"; + public static final String PROPERTY_GETLASTMODIFIED = "getlastmodified"; + public static final String PROPERTY_LOCKDISCOVERY = "lockdiscovery"; + public static final String PROPERTY_RESOURCETYPE = "resourcetype"; + public static final String PROPERTY_SOURCE = "source"; + public static final String PROPERTY_SUPPORTEDLOCK = "supportedlock"; + + //-------------------------------------------------< PropFind Constants >--- + public static final int PROPFIND_BY_PROPERTY = 0; + public static final int PROPFIND_ALL_PROP = 1; + public static final int PROPFIND_PROPERTY_NAMES = 2; + public static final int PROPFIND_ALL_PROP_INCLUDE = 3; // RFC 4918, Section 9.1 + + //----------------------------------------------< Date Format Constants >--- + /** + * Marker for undefined modification or creation time. + */ + public static long UNDEFINED_TIME = -1; + + /** + * modificationDate date format per RFC 1123.
+ * NOTE: Access to DateFormat isn't thread save. + */ + public static DateFormat modificationDateFormat = HttpDateFormat.modificationDateFormat(); + + /** + * Simple date format for the creation date ISO representation (partial).
+ * NOTE: Access to DateFormat isn't thread save. + */ + public static DateFormat creationDateFormat = HttpDateFormat.creationDateFormat(); +} Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/DavConstants.java ___________________________________________________________________ Added: svn Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/DavException.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/DavException.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/DavException.java (working copy) @@ -0,0 +1,175 @@ +/* + * 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.webdav; + +import org.apache.jackrabbit.webdav.xml.DomUtil; +import org.apache.jackrabbit.webdav.xml.XmlSerializable; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +import java.io.IOException; +import java.util.Properties; + +/** + * DavException extends the {@link Exception} class in order + * to simplify handling of exceptional situations occurring during processing + * of WebDAV requests and provides possibility to retrieve an Xml representation + * of the error. + */ +public class DavException extends Exception implements XmlSerializable { + + private static Logger log = LoggerFactory.getLogger(DavException.class); + private static Properties statusPhrases = new Properties(); + static { + try { + statusPhrases.load(DavException.class.getResourceAsStream("statuscode.properties")); + } catch (IOException e) { + log.error("Failed to load status properties: " + e.getMessage()); + } + } + + public static final String XML_ERROR = "error"; + + private int errorCode = DavServletResponse.SC_INTERNAL_SERVER_ERROR; + private Element errorCondition; + + /** + * Create a new DavException. + * + * @param errorCode integer specifying any of the status codes defined by + * {@link DavServletResponse}. + * @param message Human readable error message. + * @see DavException#DavException(int, String, Throwable, Element) + */ + public DavException(int errorCode, String message) { + this(errorCode, message, null, null); + } + + /** + * Create a new DavException. + * + * @param errorCode integer specifying any of the status codes defined by + * {@link DavServletResponse}. + * @param cause Cause of this DavException + * @see DavException#DavException(int, String, Throwable, Element) + */ + public DavException(int errorCode, Throwable cause) { + this(errorCode, null, cause, null); + } + + /** + * Create a new DavException. + * + * @param errorCode integer specifying any of the status codes defined by + * {@link DavServletResponse}. + * @see DavException#DavException(int, String, Throwable, Element) + */ + public DavException(int errorCode) { + this(errorCode, statusPhrases.getProperty(String.valueOf(errorCode)), null, null); + } + + /** + * Create a new DavException. + * + * @param errorCode integer specifying any of the status codes defined by + * {@link DavServletResponse}. + * @param message Human readable error message. + * @param cause Cause of this DavException. + * @param errorCondition Xml element providing detailed information about + * the error. If the condition is not null, {@link #toXml(Document)} + */ + public DavException(int errorCode, String message, Throwable cause, Element errorCondition) { + super(message, cause); + this.errorCode = errorCode; + this.errorCondition = errorCondition; + log.debug("DavException: (" + errorCode + ") " + message); + } + + /** + * Return the error code attached to this DavException. + * + * @return errorCode + */ + public int getErrorCode() { + return errorCode; + } + + /** + * Return the status phrase corresponding to the error code attached to + * this DavException. + * + * @return status phrase corresponding to the error code. + * @see #getErrorCode() + */ + public String getStatusPhrase() { + return getStatusPhrase(errorCode); + } + + /** + * Returns the status phrase for the given error code. + * + * @param errorCode + * @return status phrase corresponding to the given error code. + */ + public static String getStatusPhrase(int errorCode) { + return statusPhrases.getProperty(errorCode + ""); + } + + /** + * @return true if a error condition has been specified, false otherwise. + */ + public boolean hasErrorCondition() { + return errorCondition != null; + } + + /** + * Return the error condition attached to this DavException. + * + * @return errorCondition + */ + public Element getErrorCondition() { + return errorCondition; + } + + /** + * Returns a DAV:error element containing the error condition or + * null if no specific condition is available. See + * RFC 3253 + * Section 1.6 "Method Preconditions and Postconditions" for additional + * information. + * + * @param document + * @return A DAV:error element indicating the error cause or null. + * @see org.apache.jackrabbit.webdav.xml.XmlSerializable#toXml(Document) + */ + public Element toXml(Document document) { + if (hasErrorCondition()) { + Element error; + if (DomUtil.matches(errorCondition, XML_ERROR, DavConstants.NAMESPACE)) { + error = (Element) document.importNode(errorCondition, true); + } else { + error = DomUtil.createElement(document, XML_ERROR, DavConstants.NAMESPACE); + error.appendChild(document.importNode(errorCondition, true)); + } + return error; + } else { + return null; + } + } +} Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/DavException.java ___________________________________________________________________ Added: svn Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/DavLocatorFactory.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/DavLocatorFactory.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/DavLocatorFactory.java (working copy) @@ -0,0 +1,72 @@ +/* + * 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.webdav; + +/** + * DavLocatorFactory... + */ +public interface DavLocatorFactory { + + /** + * Create a new DavResourceLocator. + * + * @param prefix String consisting of [scheme:][//authority][path] where + * path defines the (imaginary) path to the {@link DavResourceLocator#isRootLocation root location}. + * @param href of the resource to be created. The given string may start with + * the 'prefix'. Please note, that in contrast to + * {@link DavLocatorFactory#createResourceLocator(String, String, String)} the + * href is expected to be URL encoded. + * @return a new resource locator. + */ + public DavResourceLocator createResourceLocator(String prefix, String href); + + /** + * Create a new DavResourceLocator. This methods corresponds to + * {@link DavLocatorFactory#createResourceLocator(String, String, String, boolean)} + * with the flag set to true. + * + * @param prefix String consisting of [scheme:][//authority][path] where + * path defines the path to the {@link DavResourceLocator#isRootLocation root location}. + * @param workspacePath the first segment of the URIs path indicating the + * workspace. The implementation may allow a empty String if workspaces + * are not supported. + * @param resourcePath the URL decoded resource path. + * @return a new resource locator. + */ + public DavResourceLocator createResourceLocator(String prefix, String workspacePath, String resourcePath); + + /** + * + * @param prefix String consisting of [scheme:][//authority][path] where + * path defines the path to the {@link DavResourceLocator#isRootLocation root location}. + * @param workspacePath the first segment of the URIs path indicating the + * workspace. The implementation may allow a empty String if workspaces + * are not supported. + * @param path the URL decoded path. + * @param isResourcePath If true this method returns the same as + * {@link DavLocatorFactory#createResourceLocator(String, String, String)}, + * otherwise the given path is treated as internal repository path. + * The implementation may choose to implement a conversion of the repository + * path to a valid resource path, e.g. (un)escaping of certain characters, due + * to incompatibility with the URI definition (or vice versa). Note that + * {@link DavResourceLocator#getRepositoryPath()} should in this case implement + * the reverse operation. + * @return a new resource locator. + * @see DavResourceLocator#getRepositoryPath() + */ + public DavResourceLocator createResourceLocator(String prefix, String workspacePath, String path, boolean isResourcePath); +} \ No newline at end of file Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/DavLocatorFactory.java ___________________________________________________________________ Added: svn Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/DavMethods.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/DavMethods.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/DavMethods.java (working copy) @@ -0,0 +1,409 @@ +/* + * 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.webdav; + +import java.util.HashMap; +import java.util.Map; + +/** + * DavMethods defines constants for the WebDAV METHODS. + */ +public final class DavMethods { + + /** + * Avoid instantiation + */ + private DavMethods() {} + + /** + * A map of WebDAV METHODS + */ + private static Map methodMap = new HashMap(); + + /** + * An array of method codes that are affected by a Label header + * @see org.apache.jackrabbit.webdav.version.DeltaVConstants#HEADER_LABEL + */ + private static int[] labelMethods; + + /** + * An array of method codes defined by RFC 3253 (deltaV) + */ + private static int[] deltaVMethods; + + /** + * The webdav OPTIONS method and public constant + */ + public static final int DAV_OPTIONS = 1; + public static final String METHOD_OPTIONS = "OPTIONS"; + + /** + * The webdav GET method and public constant + */ + public static final int DAV_GET = DAV_OPTIONS + 1; + public static final String METHOD_GET = "GET"; + + /** + * The webdav HEAD method and public constant + */ + public static final int DAV_HEAD = DAV_GET + 1; + public static final String METHOD_HEAD = "HEAD"; + + + /** + * The webdav POST method and public constant + */ + public static final int DAV_POST = DAV_HEAD + 1; + public static final String METHOD_POST = "POST"; + + + /** The webdav DELETE method and public constant */ + public static final int DAV_DELETE = DAV_POST + 1; + public static final String METHOD_DELETE = "DELETE"; + + + /** The webdav PUT method and public constant */ + public static final int DAV_PUT = DAV_DELETE + 1; + public static final String METHOD_PUT = "PUT"; + + + /** + * The webdav PROPFIND method and public constant as defined by + * RFC 2518. + */ + public static final int DAV_PROPFIND = DAV_PUT + 1; + public static final String METHOD_PROPFIND = "PROPFIND"; + + + /** + * The webdav PROPPATCH method and public constant as defined by + * RFC 2518 + */ + public static final int DAV_PROPPATCH = DAV_PROPFIND + 1; + public static final String METHOD_PROPPATCH = "PROPPATCH"; + + + /** + * The webdav MKCOL (make collection) method and public constant as defined by + * RFC 2518 + */ + public static final int DAV_MKCOL = DAV_PROPPATCH + 1; + public static final String METHOD_MKCOL = "MKCOL"; + + + /** + * The webdav COPY method and public constant as defined by + * RFC 2518 + */ + public static final int DAV_COPY = DAV_MKCOL + 1; + public static final String METHOD_COPY = "COPY"; + + + /** + * The webdav MOVE method and public constant as defined by + * RFC 2518 + */ + public static final int DAV_MOVE = DAV_COPY + 1; + public static final String METHOD_MOVE = "MOVE"; + + + /** + * The webdav LOCK method and public constant as defined by + * RFC 2518 + */ + public static final int DAV_LOCK = DAV_MOVE + 1; + public static final String METHOD_LOCK = "LOCK"; + + + /** + * The webdav UNLOCK method and public constant as defined by + * RFC 2518 + */ + public static final int DAV_UNLOCK = DAV_LOCK + 1; + public static final String METHOD_UNLOCK = "UNLOCK"; + + + /** + * The webdav ORDERPATCH method and public constant + * defined by RFC 3648. + */ + public static final int DAV_ORDERPATCH = DAV_UNLOCK + 1; + public static final String METHOD_ORDERPATCH = "ORDERPATCH"; + + + /** + * The webdav SUBSCRIBE method and public constant.
+ * NOTE: This method is not defined by any of the Webdav RFCs + */ + public static final int DAV_SUBSCRIBE = DAV_ORDERPATCH + 1; + public static final String METHOD_SUBSCRIBE = "SUBSCRIBE"; + + + /** + * The webdav UNSUBSCRIBE method and public constant
+ * NOTE: This method is not defined by any of the Webdav RFCs + */ + public static final int DAV_UNSUBSCRIBE = DAV_SUBSCRIBE + 1; + public static final String METHOD_UNSUBSCRIBE = "UNSUBSCRIBE"; + + + /** + * The webdav POLL method and public constant
+ * NOTE: This method is not defined by any of the Webdav RFCs + */ + public static final int DAV_POLL = DAV_UNSUBSCRIBE + 1; + public static final String METHOD_POLL = "POLL"; + + + /** + * The webdav SEARCH method and public constant as defined by the + * Webdav Search internet draft. + */ + public static final int DAV_SEARCH = DAV_POLL + 1; + public static final String METHOD_SEARCH = "SEARCH"; + + + /** + * The webdav REPORT method and public constant defined by + * RFC 3253 + */ + public static final int DAV_REPORT = DAV_SEARCH + 1; + public static final String METHOD_REPORT = "REPORT"; + + + /** + * The webdav VERSION-CONTROL method and public constant defined by + * RFC 3253 + */ + public static final int DAV_VERSION_CONTROL = DAV_REPORT + 1; + public static final String METHOD_VERSION_CONTROL = "VERSION-CONTROL"; + + /** + * The webdav CHECKIN method and public constant defined by + * RFC 3253 + */ + public static final int DAV_CHECKIN = DAV_VERSION_CONTROL + 1; + public static final String METHOD_CHECKIN = "CHECKIN"; + + /** + * The webdav CHECKOUT method and public constant defined by + * RFC 3253 + */ + public static final int DAV_CHECKOUT = DAV_CHECKIN + 1; + public static final String METHOD_CHECKOUT = "CHECKOUT"; + + /** + * The webdav UNCHECKOUT method and public constant defined by + * RFC 3253 + */ + public static final int DAV_UNCHECKOUT = DAV_CHECKOUT + 1; + public static final String METHOD_UNCHECKOUT = "UNCHECKOUT"; + + /** + * The webdav LABEL method and public constant defined by + * RFC 3253 + */ + public static final int DAV_LABEL = DAV_UNCHECKOUT + 1; + public static final String METHOD_LABEL = "LABEL"; + + /** + * The webdav MERGE method and public constant defined by + * RFC 3253 + */ + public static final int DAV_MERGE = DAV_LABEL + 1; + public static final String METHOD_MERGE = "MERGE"; + + /** + * The webdav UPDATE method and public constant defined by + * RFC 3253 + */ + public static final int DAV_UPDATE = DAV_MERGE + 1; + public static final String METHOD_UPDATE = "UPDATE"; + + /** + * The webdav MKWORKSPACE method and public constant defined by + * RFC 3253 + */ + public static final int DAV_MKWORKSPACE = DAV_UPDATE + 1; + public static final String METHOD_MKWORKSPACE = "MKWORKSPACE"; + + /** + * The webdav BASELINE-CONTROL method and public constant defined by + * RFC 3253 + */ + public static final int DAV_BASELINE_CONTROL = DAV_MKWORKSPACE + 1; + public static final String METHOD_BASELINE_CONTROL = "BASELINE-CONTROL"; + + /** + * The webdav MKACTIVITY method and public constant defined by + * RFC 3253 + */ + public static final int DAV_MKACTIVITY = DAV_BASELINE_CONTROL + 1; + public static final String METHOD_MKACTIVITY = "MKACTIVITY"; + + /** + * The webdav ACL method and public constant defined by + * RFC 3744 + */ + public static final int DAV_ACL = DAV_MKACTIVITY + 1; + public static final String METHOD_ACL = "ACL"; + + /** + * The webdav REBIND method and public constant defined by + * the BIND specification + */ + public static final int DAV_REBIND = DAV_ACL + 1; + public static final String METHOD_REBIND = "REBIND"; + + /** + * The webdav UNBIND method and public constant defined by + * the BIND specification + */ + public static final int DAV_UNBIND = DAV_REBIND + 1; + public static final String METHOD_UNBIND = "UNBIND"; + + /** + * The webdav BIND method and public constant defined by + * the BIND specification + */ + public static final int DAV_BIND = DAV_UNBIND + 1; + public static final String METHOD_BIND = "BIND"; + + /** + * Returns webdav method type code, error result <= 0 + * Valid type codes > 0 + */ + public static int getMethodCode(String method) { + Integer code = methodMap.get(method.toUpperCase()); + if (code != null) { + return code; + } + return 0; + } + + /** + * Static initializer for methodTable map + */ + private static void addMethodCode(String method, int code) { + methodMap.put(method, code); + } + + /** + * Webdav Method table + */ + static { + addMethodCode(METHOD_OPTIONS, DAV_OPTIONS); + addMethodCode(METHOD_GET, DAV_GET); + addMethodCode(METHOD_HEAD, DAV_HEAD); + addMethodCode(METHOD_POST, DAV_POST); + addMethodCode(METHOD_PUT, DAV_PUT); + addMethodCode(METHOD_DELETE, DAV_DELETE); + addMethodCode(METHOD_PROPFIND, DAV_PROPFIND); + addMethodCode(METHOD_PROPPATCH, DAV_PROPPATCH); + addMethodCode(METHOD_MKCOL, DAV_MKCOL); + addMethodCode(METHOD_COPY, DAV_COPY); + addMethodCode(METHOD_MOVE, DAV_MOVE); + addMethodCode(METHOD_LOCK, DAV_LOCK); + addMethodCode(METHOD_UNLOCK, DAV_UNLOCK); + addMethodCode(METHOD_ORDERPATCH, DAV_ORDERPATCH); + addMethodCode(METHOD_SUBSCRIBE, DAV_SUBSCRIBE); + addMethodCode(METHOD_UNSUBSCRIBE, DAV_UNSUBSCRIBE); + addMethodCode(METHOD_POLL, DAV_POLL); + addMethodCode(METHOD_SEARCH, DAV_SEARCH); + addMethodCode(METHOD_REPORT, DAV_REPORT); + addMethodCode(METHOD_VERSION_CONTROL, DAV_VERSION_CONTROL); + addMethodCode(METHOD_CHECKIN, DAV_CHECKIN); + addMethodCode(METHOD_CHECKOUT, DAV_CHECKOUT); + addMethodCode(METHOD_UNCHECKOUT, DAV_UNCHECKOUT); + addMethodCode(METHOD_LABEL, DAV_LABEL); + addMethodCode(METHOD_MERGE, DAV_MERGE); + addMethodCode(METHOD_UPDATE, DAV_UPDATE); + addMethodCode(METHOD_MKWORKSPACE, DAV_MKWORKSPACE); + addMethodCode(METHOD_BASELINE_CONTROL, DAV_BASELINE_CONTROL); + addMethodCode(METHOD_MKACTIVITY, DAV_MKACTIVITY); + addMethodCode(METHOD_ACL, DAV_ACL); + addMethodCode(METHOD_REBIND, DAV_REBIND); + addMethodCode(METHOD_UNBIND, DAV_UNBIND); + addMethodCode(METHOD_BIND, DAV_BIND); + + labelMethods = new int[] { DAV_GET, DAV_HEAD, DAV_OPTIONS, DAV_PROPFIND, + DAV_LABEL, DAV_COPY }; + + deltaVMethods = new int[] { DAV_REPORT, DAV_VERSION_CONTROL, DAV_CHECKIN, + DAV_CHECKOUT, DAV_UNCHECKOUT, DAV_LABEL, + DAV_MERGE, DAV_UPDATE, DAV_MKWORKSPACE, + DAV_BASELINE_CONTROL, DAV_MKACTIVITY }; + } + + /** + * Returns true if the request is to create a resource. + * True for PUT, POST, MKCOL + * and MKWORKSPACE requests. + * + * @return true if request method is to create (or replace) a resource + */ + public static boolean isCreateRequest(DavServletRequest request) { + int methodCode = getMethodCode(request.getMethod()); + return ( methodCode == DAV_PUT || + methodCode == DAV_POST || + methodCode == DAV_MKCOL || + methodCode == DAV_MKWORKSPACE); + } + + /** + * Returns true if the request is to create a collection resource. + * True for MKCOL and MKWORKSPACE requests. + * + * @return true if request method is to create a new collection resource + */ + public static boolean isCreateCollectionRequest(DavServletRequest request) { + int methodCode = getMethodCode(request.getMethod()); + return (methodCode == DAV_MKCOL || methodCode == DAV_MKWORKSPACE); + } + + /** + * Returns true, if the specified method is affected by a Label header + * + * @param request + * @return + */ + public static boolean isMethodAffectedByLabel(DavServletRequest request) { + int code = getMethodCode(request.getMethod()); + for (int labelMethod : labelMethods) { + if (code == labelMethod) { + return true; + } + } + return false; + } + + /** + * Returns true, if the specified method is defined by RFC 3253 + * + * @param request + * @return true, if the specified method is defined by RFC 3253 + */ + public static boolean isDeltaVMethod(DavServletRequest request) { + int code = getMethodCode(request.getMethod()); + for (int deltaVMethod : deltaVMethods) { + if (code == deltaVMethod) { + return true; + } + } + return false; + } +} Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/DavMethods.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/DavResource.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/DavResource.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/DavResource.java (working copy) @@ -0,0 +1,334 @@ +/* + * 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.webdav; + +import org.apache.jackrabbit.webdav.io.InputContext; +import org.apache.jackrabbit.webdav.io.OutputContext; +import org.apache.jackrabbit.webdav.lock.ActiveLock; +import org.apache.jackrabbit.webdav.lock.LockInfo; +import org.apache.jackrabbit.webdav.lock.LockManager; +import org.apache.jackrabbit.webdav.lock.Scope; +import org.apache.jackrabbit.webdav.lock.Type; +import org.apache.jackrabbit.webdav.property.DavProperty; +import org.apache.jackrabbit.webdav.property.DavPropertyName; +import org.apache.jackrabbit.webdav.property.DavPropertySet; +import org.apache.jackrabbit.webdav.property.PropEntry; + +import java.io.IOException; +import java.util.List; + +/** + * DavResource provides standard WebDAV functionality as specified + * by RFC 2518. + */ +public interface DavResource { + + /** + * String constant representing the WebDAV 1 and 2 method set. + */ + public static final String METHODS = "OPTIONS, GET, HEAD, TRACE, PROPFIND, PROPPATCH, MKCOL, COPY, PUT, DELETE, MOVE, LOCK, UNLOCK"; + + /** + * Returns a comma separated list of all compliance classes the given + * resource is fulfilling. + * + * @return compliance classes + */ + public String getComplianceClass(); + + /** + * Returns a comma separated list of all METHODS supported by the given + * resource. + * + * @return METHODS supported by this resource. + */ + public String getSupportedMethods(); + + /** + * Returns true if this webdav resource represents an existing repository item. + * + * @return true, if the resource represents an existing repository item. + */ + public boolean exists(); + + /** + * Returns true if this webdav resource has the resourcetype 'collection'. + * + * @return true if the resource represents a collection resource. + */ + public boolean isCollection(); + + /** + * Returns the display name of this resource. + * + * @return display name. + */ + public String getDisplayName(); + + /** + * Returns the {@link DavResourceLocator locator} object for this webdav resource, + * which encapsulates the information for building the complete 'href'. + * + * @return the locator for this resource. + * @see #getResourcePath() + * @see #getHref() + */ + public DavResourceLocator getLocator(); + + /** + * Returns the path of the hierarchy element defined by this DavResource. + * This method is a shortcut for DavResource.getLocator().getResourcePath(). + * + * @return path of the element defined by this DavResource. + */ + public String getResourcePath(); + + /** + * Returns the absolute href of this resource as returned in the + * multistatus response body. + * + * @return href + */ + public String getHref(); + + /** + * Return the time of the last modification or -1 if the modification time + * could not be retrieved. + * + * @return time of last modification or -1. + */ + public long getModificationTime(); + + /** + * Spools the resource properties and ev. content to the specified context + * (e.g. to respond to a 'GET' or 'HEAD' request). The context could e.g. + * wrap the servlet response. + * + * @param outputContext The output context. + * @throws IOException If an error occurs. + */ + public void spool(OutputContext outputContext) throws IOException; + + /** + * Returns an array of all {@link DavPropertyName property names} available + * on this resource. + * + * @return an array of property names. + */ + public DavPropertyName[] getPropertyNames(); + + /** + * Return the webdav property with the specified name. + * + * @param name name of the webdav property + * @return the {@link DavProperty} with the given name or null + * if the property does not exist. + */ + public DavProperty getProperty(DavPropertyName name); + + /** + * Returns all webdav properties present on this resource that will be + * return upon a {@link DavConstants#PROPFIND_ALL_PROP} request. The + * implementation may in addition expose other (protected or calculated) + * properties which should be marked accordingly (see also + * {@link org.apache.jackrabbit.webdav.property.DavProperty#isInvisibleInAllprop()}. + * + * @return a {@link DavPropertySet} containing at least all properties + * of this resource that are exposed in 'allprop' PROPFIND request. + */ + public DavPropertySet getProperties(); + + /** + * Add/Set the specified property on this resource. + * + * @param property + * @throws DavException if an error occurs + */ + public void setProperty(DavProperty property) throws DavException; + + /** + * Remove the specified property from this resource. + * + * @param propertyName + * @throws DavException if an error occurs + */ + public void removeProperty(DavPropertyName propertyName) throws DavException; + + /** + * Set/add and remove the specified properties from this resource. + * + * @param changeList list containing {@link DavPropertyName} objects (for + * properties to be removed) and {@link DavProperty} objects (for + * properties to be added/set). + * @return multistatus response listing the status resulting from + * setting and/or removing the specified properties, in order to allow a + * detailed multistatus response. + * @throws DavException if an error occurred. This may be the case if the + * general state of the resource prevents any properties to be set or removed + * (e.g. due to a lock). + */ + public MultiStatusResponse alterProperties(List changeList) throws DavException; + + /** + * Retrieve the resource this resource is internal member of. + * + * @return resource this resource is an internal member of. In case this resource + * is the root null is returned. + */ + public DavResource getCollection(); + + /** + * Add the given resource as an internal member to this resource. + * + * @param resource {@link DavResource} to be added as internal member. + * @param inputContext Context providing the properties and content for the + * internal member to be created or replaced. + * @throws DavException + */ + public void addMember(DavResource resource, InputContext inputContext) throws DavException; + + /** + * Returns an iterator over all internal members. + * + * @return a {@link DavResourceIterator} over all internal members. + */ + public DavResourceIterator getMembers(); + + /** + * Removes the specified member from this resource. + * + * @throws DavException + */ + public void removeMember(DavResource member) throws DavException; + + /** + * Move this DavResource to the given destination resource + * + * @param destination + * @throws DavException + */ + public void move(DavResource destination) throws DavException; + + /** + * Copy this DavResource to the given destination resource + * + * @param destination + * @param shallow + * @throws DavException + */ + public void copy(DavResource destination, boolean shallow) throws DavException; + + /** + * Returns true, if the this resource allows locking. NOTE, that this method + * does not define, whether a lock/unlock can be successfully executed. + * + * @return true, if this resource supports any locking. + * @param type + * @param scope + */ + public boolean isLockable(Type type, Scope scope); + + /** + * Returns true if a lock applies to this resource. This may be either a + * lock on this resource itself or a deep lock inherited from a collection + * above this resource.
+ * Note, that true is returned whenever a lock applies to that resource even + * if the lock is expired or not effective due to the fact that the request + * provides the proper lock token. + * + * @return true if a lock applies to this resource. + * @param type + */ + public boolean hasLock(Type type, Scope scope); + + /** + * Return the lock present on this webdav resource or null + * if the resource is either not locked or not lockable at all. Note, that + * a resource may have a lock that is inherited by a deep lock enforced on + * one of its 'parent' resources. + * + * @return lock information of this resource or null if this + * resource has no lock applying it. If an error occurs while retrieving the + * lock information null is returned as well. + * @param type + */ + public ActiveLock getLock(Type type, Scope scope) ; + + /** + * Returns an array of all locks applied to the given resource. + * + * @return array of locks. The array is empty if there are no locks applied + * to this resource. + */ + public ActiveLock[] getLocks(); + + /** + * Lock this webdav resource with the information retrieve from the request + * and return the resulting lockdiscovery object. + * + * @param reqLockInfo lock info as retrieved from the request. + * @return lockdiscovery object to be returned in the response. If the lock + * could not be obtained a DavException is thrown. + * @throws DavException if the lock could not be obtained. + */ + public ActiveLock lock(LockInfo reqLockInfo) throws DavException; + + /** + * Refresh an existing lock by resetting the timeout. + * + * @param reqLockInfo lock info as retrieved from the request. + * @param lockToken identifying the lock to be refreshed. + * @return lockdiscovery object to be returned in the response body. If the lock + * could not be refreshed a DavException is thrown. + * @throws DavException if the lock could not be refreshed. + */ + public ActiveLock refreshLock(LockInfo reqLockInfo, String lockToken) throws DavException; + + /** + * Remove the lock identified by the included lock token from this resource. + * This method will return false if the unlocking did not succeed. + * + * @param lockToken identifying the lock to be removed. + * @throws DavException if the lock could not be removed. + */ + public void unlock(String lockToken) throws DavException; + + /** + * Add an external {@link LockManager} to this resource. This method may + * throw {@link UnsupportedOperationException} if the resource does handle + * locking itself. + * + * @param lockmgr + * @see LockManager + */ + public void addLockManager(LockManager lockmgr); + + /** + * Return the DavResourceFactory that created this resource. + * + * @return the factory that created this resource. + */ + public DavResourceFactory getFactory(); + + /** + * Retrieve the DavSession associated with this resource. + * + * @return session object associated with this resource. + */ + public DavSession getSession(); +} + Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/DavResource.java ___________________________________________________________________ Added: svn Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/DavResourceFactory.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/DavResourceFactory.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/DavResourceFactory.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.webdav; + +/** + * DavResourceFactory interface defines a single method for creating + * {@link DavResource} objects. + */ +public interface DavResourceFactory { + + /** + * Create a {@link DavResource} object from the given locator, request and response + * objects. + * + * @param locator locator of the resource + * @param request + * @param response + * @return a new DavResource object. + * @throws DavException + */ + public DavResource createResource(DavResourceLocator locator, DavServletRequest request, DavServletResponse response) throws DavException; + + /** + * Create a new {@link DavResource} object from the given locator and session. + * + * @param locator + * @param session + * @return a new DavResource object. + * @throws DavException + */ + public DavResource createResource(DavResourceLocator locator, DavSession session) throws DavException; +} \ No newline at end of file Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/DavResourceFactory.java ___________________________________________________________________ Added: svn Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/DavResourceIterator.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/DavResourceIterator.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/DavResourceIterator.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.webdav; + +import java.util.Iterator; + +/** + * DavResourceIterator extends the Iterator interface. Additional + * METHODS allow to retrieve the next {@link DavResource} from the iterator + * and the iterators size. + */ +public interface DavResourceIterator extends Iterator { + + /** + * Returns the next {@link DavResource} in the iterator + * @return the next {@link DavResource} + */ + public DavResource nextResource(); + + /** + * Return the number of {@link DavResource}s in the iterator. + * @return number of elements in the iterator. + */ + public int size(); +} Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/DavResourceIterator.java ___________________________________________________________________ Added: svn Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/DavResourceIteratorImpl.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/DavResourceIteratorImpl.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/DavResourceIteratorImpl.java (working copy) @@ -0,0 +1,85 @@ +/* + * 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.webdav; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.Iterator; +import java.util.List; +import java.util.Collections; + +/** + * DavResourceIteratorImpl implementation of the {@link DavResourceIterator} + * interface.
+ * NOTE: {@link #remove()} is not implemented. + */ +public class DavResourceIteratorImpl implements DavResourceIterator { + + private static Logger log = LoggerFactory.getLogger(DavResourceIteratorImpl.class); + + public static final DavResourceIterator EMPTY = new DavResourceIteratorImpl(Collections.emptyList()); + + private Iterator it; + private int size; + + /** + * Create a new DavResourceIterator from the specified list. + * @param list + */ + public DavResourceIteratorImpl(List list) { + it = list.iterator(); + size = list.size(); + } + + /** + * @see DavResourceIterator#hasNext() + */ + public boolean hasNext() { + return it.hasNext(); + } + + /** + * @see DavResourceIterator#next() + */ + public DavResource next() { + return it.next(); + } + + /** + * @see DavResourceIterator#nextResource() + */ + public DavResource nextResource() { + return next(); + } + + /** + * Returns the size of the initial list. + * + * @see DavResourceIterator#size() + */ + public int size() { + return size; + } + + /** + * @see DavResourceIterator#remove() + */ + public void remove() { + throw new UnsupportedOperationException("Remove not allowed with DavResourceIteratorImpl"); + } +} Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/DavResourceIteratorImpl.java ___________________________________________________________________ Added: svn Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/DavResourceLocator.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/DavResourceLocator.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/DavResourceLocator.java (working copy) @@ -0,0 +1,115 @@ +/* + * 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.webdav; + +/** + * DavResourceLocator... + */ +public interface DavResourceLocator { + + /** + * Return the prefix used to build the complete href of the resource as + * required for the {@link DavConstants#XML_HREF href Xml} element. + * This includes scheme and host information as well as constant prefixes. + * However, this must not include workspace prefix. + * + * @return prefix needed in order to build the href from a resource path. + * @see #getResourcePath() + */ + public String getPrefix(); + + /** + * Return the resource path. + * + * @return resource path + */ + public String getResourcePath(); + + /** + * Return the path of the workspace the resource identified by this + * locator is member of. + * + * @return path of the workspace + */ + public String getWorkspacePath(); + + /** + * Return the name of the workspace the resource identified by this + * locator is member of. + * + * @return workspace name + */ + public String getWorkspaceName(); + + /** + * Returns true if the specified locator refers to a resource within the + * same workspace. + * + * @param locator + * @return true if both paths are in the same workspace. + */ + public boolean isSameWorkspace(DavResourceLocator locator); + + /** + * Returns true if the specified workspace name equals to the workspace + * name defined with this locator. + * + * @param workspaceName + * @return true if workspace names are equal. + */ + public boolean isSameWorkspace(String workspaceName); + + /** + * Return the 'href' representation of this locator object. The implementation + * should perform an URL encoding of the resource path. + * + * @param isCollection + * @return 'href' representation of this path + * @see DavConstants#XML_HREF + * @see DavResource#getHref() + */ + public String getHref(boolean isCollection); + + /** + * Returns true if this DavResourceLocator represents the root + * locator that would be requested with 'hrefPrefix'+'pathPrefix' with or + * without a trailing '/'. + * + * @return true if this locator object belongs to the root resource. + */ + public boolean isRootLocation(); + + /** + * Return the locator factory that created this locator. + * + * @return the locator factory + */ + public DavLocatorFactory getFactory(); + + /** + * An implementation may choose to circumvent the incompatibility of a + * repository path with the URI path by applying an appropriate conversion. + * This utility method allows to retrieve this transformed repository path. + * By default this method should return the same as {@link #getResourcePath()} + * + * @return a repository compatible form if the resource path. + * @see DavLocatorFactory#createResourceLocator(String, String, String, boolean) + * that allows to build a valid DavResourceLocator from a given + * repository path. + */ + public String getRepositoryPath(); +} \ No newline at end of file Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/DavResourceLocator.java ___________________________________________________________________ Added: svn Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/DavServletRequest.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/DavServletRequest.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/DavServletRequest.java (working copy) @@ -0,0 +1,199 @@ +/* + * 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.webdav; + +import org.apache.jackrabbit.webdav.lock.LockInfo; +import org.apache.jackrabbit.webdav.property.DavPropertyNameSet; +import org.apache.jackrabbit.webdav.property.DavProperty; +import org.apache.jackrabbit.webdav.property.DavPropertyName; +import org.apache.jackrabbit.webdav.property.PropEntry; +import org.w3c.dom.Document; + +import javax.servlet.http.HttpServletRequest; +import java.util.List; + +/** + * DavServletRequest extends the HttpServletRequest by Webdav + * specific METHODS. + */ +public interface DavServletRequest extends HttpServletRequest { + + /** + * Sets the DavSession to this request. + * + * @param session + */ + public void setDavSession(DavSession session); + + /** + * Returns the {@link DavSession} created for this request. + * + * @return session for this resource + */ + public DavSession getDavSession(); + + /** + * Return the locator of the requested {@link DavResource resource}. + * + * @return locator of the requested {@link DavResource resource}. + */ + public DavResourceLocator getRequestLocator(); + + /** + * Parse the {@link DavConstants#HEADER_DESTINATION Destination header} + * and return the locator of the corresponding {@link DavResource resource}. + * + * @return locator of the resource specified with the Destination header. + * @see DavConstants#HEADER_DESTINATION + */ + public DavResourceLocator getDestinationLocator() throws DavException; + + /** + * Returns true if the {@link DavConstants#HEADER_OVERWRITE Overwrite header} + * is set to 'T' thus instructing the server to overwrite the state of a + * non-null destination resource during a COPY or MOVE. A Overwrite header + * value of 'F' will return false. + * + * @return true if the Overwrite header is set to 'T', false if it is set + * to 'F'. + * @see DavConstants#HEADER_OVERWRITE + */ + public boolean isOverwrite(); + + /** + * Return the integer representation of the given {@link DavConstants#HEADER_DEPTH + * Depth header}. 'Infinity' is represented by {@link DavConstants#DEPTH_INFINITY}. + * + * @return integer representation of the {@link DavConstants#HEADER_DEPTH + * Depth header}. + * @see DavConstants#HEADER_DEPTH + */ + public int getDepth(); + + /** + * Returns the integer representation of the {@link DavConstants#HEADER_DEPTH + * Depth header} or the given defaultValue, if the Depth header is missing. + * + * @param defaultValue to be returned if no Depth header is present. + * @return integer representation of the {@link DavConstants#HEADER_DEPTH + * Depth header} or the given defaultValue. + * @see DavConstants#HEADER_DEPTH + */ + public int getDepth(int defaultValue); + + /** + * Returns the token present in the {@link DavConstants#HEADER_LOCK_TOKEN + * Lock-Token Header} or null if no such header is available.
+ * Note: The 'Lock-Token' header is sent with UNLOCK requests and with + * lock responses only. For any other request that may be affected by a lock + * the 'If' header field is responsible. + * + * @return the token present in the Lock-Token header. + * @see DavConstants#HEADER_LOCK_TOKEN + */ + public String getLockToken(); + + /** + * Return the timeout requested in the {@link DavConstants#HEADER_TIMEOUT + * Timeout header} as long. The representation of the + * 'Infinite' timeout is left to the implementation. + * + * @return long value representation of the Timeout header. + * @see DavConstants#HEADER_TIMEOUT + * @see DavConstants#TIMEOUT_INFINITE + */ + public long getTimeout(); + + /** + * Parse the Xml request body and return a {@link org.w3c.dom.Document}. + * + * @return Document representing the Xml request body or null + * if no request body is present. + * @throws DavException If the request body cannot be parsed into an Xml + * Document. + */ + public Document getRequestDocument() throws DavException; + + /** + * Return the type of PROPFIND request as indicated by the PROPFIND request + * body. + * + * @return type of PROPFIND request + * @see DavConstants#PROPFIND_ALL_PROP + * @see DavConstants#PROPFIND_BY_PROPERTY + * @see DavConstants#PROPFIND_PROPERTY_NAMES + * @see DavConstants#PROPFIND_ALL_PROP_INCLUDE + * @throws DavException If the propfind type could not be determined due to + * an invalid request body. + */ + public int getPropFindType() throws DavException; + + /** + * Return the set of properties the client requested with a PROPFIND request + * or an empty set if the type of PROPFIND request was {@link DavConstants#PROPFIND_ALL_PROP} + * or {@link DavConstants#PROPFIND_PROPERTY_NAMES}. + * + * @return set of properties the client requested with a PROPFIND request + * @throws DavException In case of invalid request body + */ + public DavPropertyNameSet getPropFindProperties() throws DavException; + + /** + * Return a {@link List} of property change operations. Each entry + * is either of type {@link DavPropertyName}, indicating a <remove> + * operation, or of type {@link DavProperty}, indicating a <set> + * operation. Note that ordering is significant here. + * + * @return {@link List} of property change operations + * @throws DavException In case of invalid request body + */ + public List getPropPatchChangeList() throws DavException; + + /** + * Return the parsed 'lockinfo' request body, the {@link DavConstants#HEADER_TIMEOUT + * Timeout header} and the {@link DavConstants#HEADER_DEPTH Depth header} + * of a LOCK request as LockInfo object. + * + * @return LockInfo object encapsulating the information + * present in the LOCK request. + * @see DavConstants#HEADER_TIMEOUT + * @see DavConstants#HEADER_DEPTH + * @see DavConstants#XML_LOCKINFO + * @throws DavException + */ + public LockInfo getLockInfo() throws DavException; + + /** + * Returns true, if the {@link DavConstants#HEADER_IF If header} present + * with the request matches the given resource. + * + * @param resource + * @return true, if the test is successful, false otherwise. + */ + public boolean matchesIfHeader(DavResource resource); + + /** + * Returns true, if the {@link DavConstants#HEADER_IF If header} present + * with the request matches to the given href, token and eTag. + * + * @param href + * @param token + * @param eTag + * @return true, if the test is successful, false otherwise. + */ + public boolean matchesIfHeader(String href, String token, String eTag); +} Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/DavServletRequest.java ___________________________________________________________________ Added: svn Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/DavServletResponse.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/DavServletResponse.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/DavServletResponse.java (working copy) @@ -0,0 +1,149 @@ +/* + * 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.webdav; + +import org.apache.jackrabbit.webdav.lock.ActiveLock; +import org.apache.jackrabbit.webdav.xml.XmlSerializable; + +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.util.List; + +/** + * WebdavResponse extends the HttpServletResponse by + * Webdav specific status codes and METHODS. + */ +public interface DavServletResponse extends HttpServletResponse { + + /** + * The 102 (Processing) status code is an interim response used to + * inform the client that the server has accepted the complete request, + * but has not yet completed it. + */ + int SC_PROCESSING = 102; + + /** + * Status code (207) indicating that the response requires + * providing status for multiple independent operations. + */ + int SC_MULTI_STATUS = 207; + + /** + * The 422 (Unprocessable Entity) status code means the server understands + * the content type of the request entity (hence a 415(Unsupported Media Type) + * status code is inappropriate), and the syntax of the request entity is + * correct (thus a 400 (Bad Request) status code is inappropriate) but was + * unable to process the contained instructions. For example, this error + * condition may occur if an XML request body contains well-formed (i.e., + * syntactically correct), but semantically erroneous XML instructions. + */ + int SC_UNPROCESSABLE_ENTITY = 422; + + /** + * Status code (423) indicating the destination resource of a + * method is locked, and either the request did not contain a + * valid Lock-Info header, or the Lock-Info header identifies + * a lock held by another principal. + */ + int SC_LOCKED = 423; + + /** + * Status code (424) indicating that the method could not be + * performed on the resource, because the requested action depended + * on another action which failed. + */ + int SC_FAILED_DEPENDENCY = 424; + + /** + * Status code (507) indicating that the resource does not have + * sufficient space to record the state of the resource after the + * execution of this method. + */ + int SC_INSUFFICIENT_SPACE_ON_RESOURCE = 507; + + /** + * Send a response body given more detailed information about the error + * occurred. + * + * @param error + * @throws IOException + */ + public void sendError(DavException error) throws IOException; + + /** + * Send the multistatus response to the client. A multistatus response + * is returned in response to a successful PROPFIND and PROPPATCH request. + * In addition multistatus response is required response in case a COPY, + * MOVE, DELETE, LOCK or PROPPATCH request fails. + * + * @param multistatus + * @throws IOException + * @see #SC_MULTI_STATUS + */ + public void sendMultiStatus(MultiStatus multistatus) throws IOException; + + /** + * Send the multistatus response to the client. A multistatus response + * is returned in response to a successful PROPFIND and PROPPATCH request. + * In addition multistatus response is required response in case a COPY, + * MOVE, DELETE, LOCK or PROPPATCH request fails. + * + * @param multistatus + * @param acceptableContentCodings content codings accepted by the client + * @throws IOException + * @see #SC_MULTI_STATUS + */ + default void sendMultiStatus(MultiStatus multistatus, List acceptableContentCodings) throws IOException { + sendMultiStatus(multistatus); + } + + /** + * Send the lock response for a successful LOCK request, that was intended + * to refresh an existing lock. The locks array must contain at least + * a single element; the ActiveLock objects are then + * included in the lockdiscovery property of the response body as required + * by RFC 2518. + * + * @param locks + * @throws IOException + * @see DavConstants#PROPERTY_LOCKDISCOVERY + */ + public void sendRefreshLockResponse(ActiveLock[] locks) throws IOException; + + /** + * Generic method to return an Xml response body. + * + * @param serializable object that can be converted to the root Xml element + * of the document to be sent as response body. + * @param status Status code to be used with {@link #setStatus(int)}. + * @throws IOException + */ + public void sendXmlResponse(XmlSerializable serializable, int status) throws IOException; + + /** + * Generic method to return an Xml response body. + * + * @param serializable object that can be converted to the root Xml element + * of the document to be sent as response body. + * @param status Status code to be used with {@link #setStatus(int)}. + * @param acceptableContentCodings content codings accepted by the client + * @throws IOException + */ + default void sendXmlResponse(XmlSerializable serializable, int status, List acceptableContentCodings) throws IOException { + sendXmlResponse(serializable, status); + } +} \ No newline at end of file Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/DavServletResponse.java ___________________________________________________________________ Added: svn Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/DavSession.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/DavSession.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/DavSession.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.webdav; + +/** + * DavSession allows to pass session information between request, + * response and resource(s). + */ +public interface DavSession { + + /** + * Adds a reference to this DavSession indicating that this + * session must not be discarded after completion of the current request. + * + * @param reference to be added. + */ + public void addReference(Object reference); + + /** + * Releasing a reference to this DavSession. If no more + * references are present, this session may be discarded. + * + * @param reference to be removed. + */ + public void removeReference(Object reference); + + /** + * Adds a lock token to this DavSession. + * + * @param token + */ + public void addLockToken(String token); + + /** + * Returns the lock tokens of this DavSession. + * + * @return + */ + public String[] getLockTokens(); + + /** + * Removes a lock token from this DavSession. + * + * @param token + */ + public void removeLockToken(String token); + +} \ No newline at end of file Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/DavSession.java ___________________________________________________________________ Added: svn Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/DavSessionProvider.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/DavSessionProvider.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/DavSessionProvider.java (working copy) @@ -0,0 +1,48 @@ +/* + * 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.webdav; + +/** + * DavSessionProvider is an interface for components that + * can initiate and complete {@link DavSession}s. A provider is + * responsible for supplying references from a {@link WebdavRequest} + * to a {@link DavSession} when acquired and removing the references + * when released. + + */ +public interface DavSessionProvider { + + /** + * Acquires a DavSession. Upon success, the WebdavRequest will + * reference that session. + * + * A session will not be available if an exception is thrown. + * + * @param request + * @return true if the session was attached to the request; + * false otherwise. + * @throws DavException if a problem occurred while obtaining the session + */ + public boolean attachSession(WebdavRequest request) throws DavException; + + /** + * Releases the reference from the request to the session. + * + * @param request + */ + public void releaseSession(WebdavRequest request); +} Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/DavSessionProvider.java ___________________________________________________________________ Added: svn Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/MultiStatus.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/MultiStatus.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/MultiStatus.java (working copy) @@ -0,0 +1,193 @@ +/* + * 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.webdav; + +import org.apache.jackrabbit.webdav.property.DavPropertyNameSet; +import org.apache.jackrabbit.webdav.xml.DomUtil; +import org.apache.jackrabbit.webdav.xml.ElementIterator; +import org.apache.jackrabbit.webdav.xml.XmlSerializable; +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +import java.util.LinkedHashMap; +import java.util.Map; + +/** + * MultiStatus representing the content of a multistatus response body and + * allows to retrieve the Xml representation. + */ +public class MultiStatus implements DavConstants, XmlSerializable { + + /** + * Map collecting the responses for this multistatus, where every href must + * only occur one single time. + */ + private Map responses = new LinkedHashMap(); + + /** + * A general response description at the multistatus top level is used to + * provide a general message describing the overarching nature of the response. + * If this value is available an application may use it instead of + * presenting the individual response descriptions contained within the + * responses. + */ + private String responseDescription; + + /** + * Add response(s) to this multistatus, in order to build a multistatus for + * responding to a PROPFIND request. + * + * @param resource The resource to add property from + * @param propNameSet The requested property names of the PROPFIND request + * @param propFindType + * @param depth + */ + public void addResourceProperties(DavResource resource, DavPropertyNameSet propNameSet, + int propFindType, int depth) { + addResponse(new MultiStatusResponse(resource, propNameSet, propFindType)); + if (depth > 0 && resource.isCollection()) { + DavResourceIterator iter = resource.getMembers(); + while (iter.hasNext()) { + addResourceProperties(iter.nextResource(), propNameSet, propFindType, depth-1); + } + } + } + + /** + * Add response(s) to this multistatus, in order to build a multistatus e.g. + * in order to respond to a PROPFIND request. Please note, that in terms + * of PROPFIND, this method would correspond to a + * {@link DavConstants#PROPFIND_BY_PROPERTY} propfind type. + * + * @param resource The resource to add property from + * @param propNameSet The requested property names of the PROPFIND request + * @param depth + * @see #addResourceProperties(DavResource, DavPropertyNameSet, int, int) for + * the corresponding method that allows to specify the type. + */ + public void addResourceProperties(DavResource resource, DavPropertyNameSet propNameSet, + int depth) { + addResourceProperties(resource, propNameSet, PROPFIND_BY_PROPERTY, depth); + } + + /** + * Add response(s) to this multistatus, in order to build a multistatus + * as returned for COPY, MOVE, LOCK or DELETE requests resulting in an error + * with a resource other than the resource identified in the Request-URI. + * + * @param resource + * @param status + * @param depth + */ + public void addResourceStatus(DavResource resource, int status, int depth) { + addResponse(new MultiStatusResponse(resource.getHref(), status)); + if (depth > 0 && resource.isCollection()) { + DavResourceIterator iter = resource.getMembers(); + while (iter.hasNext()) { + addResourceStatus(iter.nextResource(), status, depth-1); + } + } + } + + /** + * Add a MultiStatusResponse element to this MultiStatus + *

+ * This method is synchronized to avoid the problem described in + * JCR-2755. + * + * @param response + */ + public synchronized void addResponse(MultiStatusResponse response) { + responses.put(response.getHref(), response); + } + + /** + * Returns the multistatus responses present as array. + *

+ * This method is synchronized to avoid the problem described in + * JCR-2755. + * + * @return array of all {@link MultiStatusResponse responses} present in this + * multistatus. + */ + public synchronized MultiStatusResponse[] getResponses() { + return responses.values().toArray(new MultiStatusResponse[responses.size()]); + } + + /** + * Set the response description. + * + * @param responseDescription + */ + public void setResponseDescription(String responseDescription) { + this.responseDescription = responseDescription; + } + + /** + * Returns the response description. + * + * @return responseDescription + */ + public String getResponseDescription() { + return responseDescription; + } + + /** + * Return the Xml representation of this MultiStatus. + * + * @return Xml document + * @param document + */ + public Element toXml(Document document) { + Element multistatus = DomUtil.createElement(document, XML_MULTISTATUS, NAMESPACE); + for (MultiStatusResponse resp : getResponses()) { + multistatus.appendChild(resp.toXml(document)); + } + if (responseDescription != null) { + Element respDesc = DomUtil.createElement(document, XML_RESPONSEDESCRIPTION, NAMESPACE, responseDescription); + multistatus.appendChild(respDesc); + } + return multistatus; + } + + /** + * Build a MultiStatus from the specified xml element. + * + * @param multistatusElement + * @return new MultiStatus instance. + * @throws IllegalArgumentException if the given document is null + * or does not provide the required element. + */ + public static MultiStatus createFromXml(Element multistatusElement) { + if (!DomUtil.matches(multistatusElement, XML_MULTISTATUS, NAMESPACE)) { + throw new IllegalArgumentException("DAV:multistatus element expected."); + } + + MultiStatus multistatus = new MultiStatus(); + + ElementIterator it = DomUtil.getChildren(multistatusElement, XML_RESPONSE, NAMESPACE); + while (it.hasNext()) { + Element respElem = it.nextElement(); + MultiStatusResponse response = MultiStatusResponse.createFromXml(respElem); + multistatus.addResponse(response); + } + + // optional response description on the multistatus element + multistatus.setResponseDescription(DomUtil.getChildText(multistatusElement, XML_RESPONSEDESCRIPTION, NAMESPACE)); + return multistatus; + } +} Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/MultiStatus.java ___________________________________________________________________ Added: svn Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/MultiStatusResponse.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/MultiStatusResponse.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/MultiStatusResponse.java (working copy) @@ -0,0 +1,486 @@ +/* + * 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.webdav; + +import org.apache.jackrabbit.webdav.property.DavProperty; +import org.apache.jackrabbit.webdav.property.DavPropertyName; +import org.apache.jackrabbit.webdav.property.DavPropertyNameSet; +import org.apache.jackrabbit.webdav.property.DavPropertySet; +import org.apache.jackrabbit.webdav.property.DefaultDavProperty; +import org.apache.jackrabbit.webdav.property.PropContainer; +import org.apache.jackrabbit.webdav.xml.DomUtil; +import org.apache.jackrabbit.webdav.xml.ElementIterator; +import org.apache.jackrabbit.webdav.xml.XmlSerializable; +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.Set; + +/** + * MultiStatusResponse represents the DAV:multistatus element defined + * by RFC 2518: + *

+ * <!ELEMENT response (href, ((href*, status)|(propstat+)), responsedescription?) >
+ * <!ELEMENT status (#PCDATA) >
+ * <!ELEMENT propstat (prop, status, responsedescription?) >
+ * <!ELEMENT responsedescription (#PCDATA) >
+ * <!ELEMENT prop ANY >
+ * 
+ */ +public class MultiStatusResponse implements XmlSerializable, DavConstants { + + private static final int TYPE_PROPSTAT = 0; + private static final int TYPE_HREFSTATUS = 1; + + /** + * The type of MultiStatusResponse + */ + private final int type; + + /** + * The content the 'href' element for this response + */ + private final String href; + + /** + * An optional response description. + */ + private final String responseDescription; + + /** + * Type of MultiStatus response: Href + Status + */ + private Status status; + + /** + * Type of MultiStatus response: PropStat Hashmap containing all status + */ + private HashMap statusMap = new HashMap(); + + private MultiStatusResponse(String href, String responseDescription, int type) { + if (!isValidHref(href)) { + throw new IllegalArgumentException("Invalid href ('" + href + "')"); + } + this.href = href; + this.responseDescription = responseDescription; + this.type = type; + } + + /** + * Constructs an WebDAV multistatus response + * + * @param href + * @param status + * @param responseDescription + */ + public MultiStatusResponse(String href, Status status, String responseDescription) { + this(href, responseDescription, TYPE_HREFSTATUS); + if (status == null) { + throw new IllegalArgumentException("Status must not be null in case of a multistatus reponse that consists of href + status only."); + } + this.status = status; + } + + /** + * Constructs an WebDAV multistatus response for a given resource. This + * would be used by COPY, MOVE, DELETE, LOCK that require a multistatus in + * case of error with a resource other than the resource identified in the + * Request-URI.
+ * The response description is set to null. + * + * @param href + * @param statusCode + */ + public MultiStatusResponse(String href, int statusCode) { + this(href, statusCode, null); + } + + /** + * Constructs an WebDAV multistatus response for a given resource. This + * would be used by COPY, MOVE, DELETE, LOCK that require a multistatus in + * case of error with a resource other than the resource identified in the + * Request-URI. + * + * @param href + * @param statusCode + * @param responseDescription + */ + public MultiStatusResponse(String href, int statusCode, String responseDescription) { + this(href, new Status(statusCode), responseDescription); + } + + /** + * Constructs an empty WebDAV multistatus response of type 'PropStat' + */ + public MultiStatusResponse(String href, String responseDescription) { + this(href, responseDescription, TYPE_PROPSTAT); + } + + /** + * Constructs a WebDAV multistatus response and retrieves the resource + * properties according to the given DavPropertyNameSet. + * + * @param resource + * @param propNameSet + */ + public MultiStatusResponse(DavResource resource, DavPropertyNameSet propNameSet) { + this(resource, propNameSet, PROPFIND_BY_PROPERTY); + } + + /** + * Constructs a WebDAV multistatus response and retrieves the resource + * properties according to the given DavPropertyNameSet. It + * adds all known property to the '200' set, while unknown properties are + * added to the '404' set. + *

+ * Note, that the set of property names is ignored in case of a {@link + * #PROPFIND_ALL_PROP} and {@link #PROPFIND_PROPERTY_NAMES} propFindType. + * + * @param resource The resource to retrieve the property from + * @param propNameSet The property name set as obtained from the request + * body. + * @param propFindType any of the following values: {@link + * #PROPFIND_ALL_PROP}, {@link #PROPFIND_BY_PROPERTY}, {@link + * #PROPFIND_PROPERTY_NAMES}, {@link #PROPFIND_ALL_PROP_INCLUDE} + */ + public MultiStatusResponse( + DavResource resource, DavPropertyNameSet propNameSet, + int propFindType) { + this(resource.getHref(), null, TYPE_PROPSTAT); + + if (propFindType == PROPFIND_PROPERTY_NAMES) { + // only property names requested + PropContainer status200 = getPropContainer(DavServletResponse.SC_OK, true); + for (DavPropertyName propName : resource.getPropertyNames()) { + status200.addContent(propName); + } + } else { + // all or a specified set of property and their values requested. + PropContainer status200 = getPropContainer(DavServletResponse.SC_OK, false); + + // Collection of missing property names for 404 responses + Set missing = new HashSet(propNameSet.getContent()); + + // Add requested properties or all non-protected properties, + // or non-protected properties plus requested properties (allprop/include) + if (propFindType == PROPFIND_BY_PROPERTY) { + // add explicitly requested properties (proptected or non-protected) + for (DavPropertyName propName : propNameSet) { + DavProperty prop = resource.getProperty(propName); + if (prop != null) { + status200.addContent(prop); + missing.remove(propName); + } + } + } else { + // add all non-protected properties + for (DavProperty property : resource.getProperties()) { + boolean allDeadPlusRfc4918LiveProperties = + propFindType == PROPFIND_ALL_PROP + || propFindType == PROPFIND_ALL_PROP_INCLUDE; + boolean wasRequested = missing.remove(property.getName()); + + if ((allDeadPlusRfc4918LiveProperties + && !property.isInvisibleInAllprop()) + || wasRequested) { + status200.addContent(property); + } + } + + // try if missing properties specified in the include section + // can be obtained using resource.getProperty + if (propFindType == PROPFIND_ALL_PROP_INCLUDE && !missing.isEmpty()) { + for (DavPropertyName propName : new HashSet(missing)) { + DavProperty prop = resource.getProperty(propName); + if (prop != null) { + status200.addContent(prop); + missing.remove(propName); + } + } + } + } + + if (!missing.isEmpty() && propFindType != PROPFIND_ALL_PROP) { + PropContainer status404 = getPropContainer(DavServletResponse.SC_NOT_FOUND, true); + for (DavPropertyName propName : missing) { + status404.addContent(propName); + } + } + } + } + + /** + * Returns the href + * + * @return href + * @see MultiStatusResponse#getHref() + */ + public String getHref() { + return href; + } + + /** + * @return responseDescription + * @see MultiStatusResponse#getResponseDescription() + */ + public String getResponseDescription() { + return responseDescription; + } + + /** + * Return an array listing all 'status' available is this response object. + * Note, that a the array contains a single element if this + * MultiStatusResponse defines an response consisting of + * href and status elements. + * + * @return + */ + public Status[] getStatus() { + Status[] sts; + if (type == TYPE_PROPSTAT) { + sts = new Status[statusMap.size()]; + Iterator iter = statusMap.keySet().iterator(); + for (int i = 0; iter.hasNext(); i++) { + Integer statusKey = iter.next(); + sts[i] = new Status(statusKey); + } + } else { + sts = new Status[] {status}; + } + return sts; + } + + /** + * @return {@code true} if the response is of type "propstat" (containing information about individual properties) + */ + public boolean isPropStat() { + return this.type == TYPE_PROPSTAT; + } + + /** + * @param document + * @see org.apache.jackrabbit.webdav.xml.XmlSerializable#toXml(org.w3c.dom.Document) + */ + public Element toXml(Document document) { + Element response = DomUtil.createElement(document, XML_RESPONSE, NAMESPACE); + // add '' + response.appendChild(DomUtil.hrefToXml(getHref(), document)); + if (type == TYPE_PROPSTAT) { + // add '' elements + for (Integer statusKey : statusMap.keySet()) { + Status st = new Status(statusKey); + PropContainer propCont = statusMap.get(statusKey); + if (!propCont.isEmpty()) { + Element propstat = DomUtil.createElement(document, XML_PROPSTAT, NAMESPACE); + propstat.appendChild(propCont.toXml(document)); + propstat.appendChild(st.toXml(document)); + response.appendChild(propstat); + } + } + } else { + // add a single '' element + // NOTE: a href+status response cannot be created with 'null' status + response.appendChild(status.toXml(document)); + } + // add the optional '' element + String description = getResponseDescription(); + if (description != null) { + Element desc = DomUtil.createElement(document, XML_RESPONSEDESCRIPTION, NAMESPACE); + DomUtil.setText(desc, description); + response.appendChild(desc); + } + return response; + } + //----------------------------------------------< type specific methods >--- + /** + * Adds a property to this response '200' propstat set. + * + * @param property the property to add + */ + public void add(DavProperty property) { + checkType(TYPE_PROPSTAT); + PropContainer status200 = getPropContainer(DavServletResponse.SC_OK, false); + status200.addContent(property); + } + + /** + * Adds a property name to this response '200' propstat set. + * + * @param propertyName the property name to add + */ + public void add(DavPropertyName propertyName) { + checkType(TYPE_PROPSTAT); + PropContainer status200 = getPropContainer(DavServletResponse.SC_OK, true); + status200.addContent(propertyName); + } + + /** + * Adds a property to this response + * + * @param property the property to add + * @param status the status of the response set to select + */ + public void add(DavProperty property, int status) { + checkType(TYPE_PROPSTAT); + PropContainer propCont = getPropContainer(status, false); + propCont.addContent(property); + } + + /** + * Adds a property name to this response + * + * @param propertyName the property name to add + * @param status the status of the response set to select + */ + public void add(DavPropertyName propertyName, int status) { + checkType(TYPE_PROPSTAT); + PropContainer propCont = getPropContainer(status, true); + propCont.addContent(propertyName); + } + + /** + * @param status + * @return + */ + private PropContainer getPropContainer(int status, boolean forNames) { + PropContainer propContainer = statusMap.get(status); + if (propContainer == null) { + if (forNames) { + propContainer = new DavPropertyNameSet(); + } else { + propContainer = new DavPropertySet(); + } + statusMap.put(status, propContainer); + } + return propContainer; + } + + private void checkType(int type) { + if (this.type != type) { + throw new IllegalStateException("The given MultiStatusResponse is not of the required type."); + } + } + + /** + * Get properties present in this response for the given status code. In + * case this MultiStatusResponse does not represent a 'propstat' response, + * always an empty {@link DavPropertySet} will be returned. + * + * @param status + * @return property set + */ + public DavPropertySet getProperties(int status) { + if (statusMap.containsKey(status)) { + PropContainer mapEntry = statusMap.get(status); + if (mapEntry != null && mapEntry instanceof DavPropertySet) { + return (DavPropertySet) mapEntry; + } + } + return new DavPropertySet(); + } + + /** + * Get property names present in this response for the given status code. In + * case this MultiStatusResponse does not represent a 'propstat' response, + * always an empty {@link DavPropertyNameSet} will be returned. + * + * @param status + * @return property names + */ + public DavPropertyNameSet getPropertyNames(int status) { + if (statusMap.containsKey(status)) { + PropContainer mapEntry = statusMap.get(status); + if (mapEntry != null) { + if (mapEntry instanceof DavPropertySet) { + DavPropertyNameSet set = new DavPropertyNameSet(); + for (DavPropertyName name : ((DavPropertySet) mapEntry).getPropertyNames()) { + set.add(name); + } + return set; + } else { + // is already a DavPropertyNameSet + return (DavPropertyNameSet) mapEntry; + } + } + } + return new DavPropertyNameSet(); + } + + /** + * Build a new response object from the given xml element. + * + * @param responseElement + * @return new MultiStatusResponse instance + * @throws IllegalArgumentException if the specified element is + * null or not a DAV:response element or if the mandatory + * DAV:href child is missing. + */ + public static MultiStatusResponse createFromXml(Element responseElement) { + if (!DomUtil.matches(responseElement, XML_RESPONSE, NAMESPACE)) { + throw new IllegalArgumentException("DAV:response element required."); + } + String href = DomUtil.getChildTextTrim(responseElement, XML_HREF, NAMESPACE); + if (href == null) { + throw new IllegalArgumentException("DAV:response element must contain a DAV:href element expected."); + } + String statusLine = DomUtil.getChildText(responseElement, XML_STATUS, NAMESPACE); + String responseDescription = DomUtil.getChildText(responseElement, XML_RESPONSEDESCRIPTION, NAMESPACE); + + MultiStatusResponse response; + if (statusLine != null) { + Status status = Status.parse(statusLine); + response = new MultiStatusResponse(href, status, responseDescription); + } else { + response = new MultiStatusResponse(href, responseDescription, TYPE_PROPSTAT); + // read propstat elements + ElementIterator it = DomUtil.getChildren(responseElement, XML_PROPSTAT, NAMESPACE); + while (it.hasNext()) { + Element propstat = it.nextElement(); + String propstatus = DomUtil.getChildText(propstat, XML_STATUS, NAMESPACE); + Element prop = DomUtil.getChildElement(propstat, XML_PROP, NAMESPACE); + if (propstatus != null && prop != null) { + int statusCode = Status.parse(propstatus).getStatusCode(); + ElementIterator propIt = DomUtil.getChildren(prop); + while (propIt.hasNext()) { + Element el = propIt.nextElement(); + /* + always build dav property from the given element, since + distinction between prop-names and properties not having + a value is not possible. + retrieval of the set of 'property names' is possible from + the given prop-set by calling DavPropertySet#getPropertyNameSet() + */ + DavProperty property = DefaultDavProperty.createFromXml(el); + response.add(property, statusCode); + } + } + } + } + return response; + } + + /** + * @param href + * @return false if the given href is null or empty string. + */ + private static boolean isValidHref(String href) { + return href != null && !"".equals(href); + } +} Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/MultiStatusResponse.java ___________________________________________________________________ Added: svn Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/Status.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/Status.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/Status.java (working copy) @@ -0,0 +1,123 @@ +/* + * 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.webdav; + +import org.apache.jackrabbit.webdav.xml.DomUtil; +import org.apache.jackrabbit.webdav.xml.XmlSerializable; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +/** + * Status encapsulating the 'status' present in multistatus + * responses. + */ +public class Status implements DavConstants, XmlSerializable{ + + private static Logger log = LoggerFactory.getLogger(Status.class); + + private final String version; + private final int code; + private final String phrase; + + public Status(int code) { + version = "HTTP/1.1"; + this.code = code; + phrase = DavException.getStatusPhrase(code); + } + + public Status(String version, int code, String phrase) { + this.version = version; + this.code = code; + this.phrase = phrase; + } + + public int getStatusCode() { + return code; + } + + /** + * @see XmlSerializable#toXml(Document) + */ + public Element toXml(Document document) { + String statusLine = version + " " + code + " " + phrase; + Element e = DomUtil.createElement(document, XML_STATUS, NAMESPACE); + DomUtil.setText(e, statusLine); + return e; + } + + /** + * Parse the given status line and return a new Status object. + * + * @param statusLine + * @return a new Status + */ + public static Status parse(String statusLine) { + if (statusLine == null) { + throw new IllegalArgumentException("Unable to parse status line from null xml element."); + } + Status status; + + // code copied from org.apache.commons.httpclient.StatusLine + int length = statusLine.length(); + int at = 0; + int start = 0; + try { + while (Character.isWhitespace(statusLine.charAt(at))) { + ++at; + ++start; + } + if (!"HTTP".equals(statusLine.substring(at, at += 4))) { + log.warn("Status-Line '" + statusLine + "' does not start with HTTP"); + } + //handle the HTTP-Version + at = statusLine.indexOf(' ', at); + if (at <= 0) { + log.warn("Unable to parse HTTP-Version from the status line: '" + statusLine + "'"); + } + String version = (statusLine.substring(start, at)).toUpperCase(); + //advance through spaces + while (statusLine.charAt(at) == ' ') { + at++; + } + //handle the Status-Code + int code; + int to = statusLine.indexOf(' ', at); + if (to < 0) { + to = length; + } + try { + code = Integer.parseInt(statusLine.substring(at, to)); + } catch (NumberFormatException e) { + throw new IllegalArgumentException("Unable to parse status code from status line: '" + statusLine + "'"); + } + //handle the Reason-Phrase + String phrase = ""; + at = to + 1; + if (at < length) { + phrase = statusLine.substring(at).trim(); + } + + status = new Status(version, code, phrase); + + } catch (StringIndexOutOfBoundsException e) { + throw new IllegalArgumentException("Status-Line '" + statusLine + "' is not valid"); + } + return status; + } +} \ No newline at end of file Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/Status.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-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/WebdavRequest.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/WebdavRequest.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/WebdavRequest.java (working copy) @@ -0,0 +1,36 @@ +/* + * 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.webdav; + +import org.apache.jackrabbit.webdav.observation.ObservationDavServletRequest; +import org.apache.jackrabbit.webdav.ordering.OrderingDavServletRequest; +import org.apache.jackrabbit.webdav.transaction.TransactionDavServletRequest; +import org.apache.jackrabbit.webdav.version.DeltaVServletRequest; +import org.apache.jackrabbit.webdav.bind.BindServletRequest; + +/** + * The empty WebdavRequest interface collects the functionality + * defined by {@link org.apache.jackrabbit.webdav.DavServletRequest} encapsulating + * the core Webdav specification (RFC 2518) as well as the various extensions + * used for observation and transaction support, ordering of collections, search + * and versioning. + */ +public interface WebdavRequest extends DavServletRequest, + ObservationDavServletRequest, OrderingDavServletRequest, + TransactionDavServletRequest, DeltaVServletRequest, + BindServletRequest { +} Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/WebdavRequest.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/WebdavRequestContext.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/WebdavRequestContext.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/WebdavRequestContext.java (working copy) @@ -0,0 +1,30 @@ +/* + * 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.webdav; + +/** + * Interface providing the minimum WebDAV request information associated with the current thread of execution. + */ +public interface WebdavRequestContext { + + /** + * Return the current {@link WebdavRequest} instance associated with the current thread of execution. + * @return the current {@link WebdavRequest} instance associated with the current thread of execution + */ + public WebdavRequest getRequest(); + +} Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/WebdavRequestContext.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/WebdavRequestImpl.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/WebdavRequestImpl.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/WebdavRequestImpl.java (working copy) @@ -0,0 +1,1312 @@ +/* + * 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.webdav; + +import java.io.BufferedInputStream; +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.UnsupportedEncodingException; +import java.net.URI; +import java.net.URISyntaxException; +import java.security.Principal; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Enumeration; +import java.util.Iterator; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.zip.GZIPInputStream; +import java.util.zip.InflaterInputStream; + +import javax.servlet.AsyncContext; +import javax.servlet.DispatcherType; +import javax.servlet.ReadListener; +import javax.servlet.RequestDispatcher; +import javax.servlet.ServletContext; +import javax.servlet.ServletException; +import javax.servlet.ServletInputStream; +import javax.servlet.ServletRequest; +import javax.servlet.ServletResponse; +import javax.servlet.http.Cookie; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.servlet.http.HttpSession; +import javax.servlet.http.HttpUpgradeHandler; +import javax.servlet.http.Part; +import javax.xml.parsers.ParserConfigurationException; + +import org.apache.jackrabbit.webdav.bind.BindInfo; +import org.apache.jackrabbit.webdav.bind.RebindInfo; +import org.apache.jackrabbit.webdav.bind.UnbindInfo; +import org.apache.jackrabbit.webdav.header.CodedUrlHeader; +import org.apache.jackrabbit.webdav.header.DepthHeader; +import org.apache.jackrabbit.webdav.header.IfHeader; +import org.apache.jackrabbit.webdav.header.LabelHeader; +import org.apache.jackrabbit.webdav.header.OverwriteHeader; +import org.apache.jackrabbit.webdav.header.PollTimeoutHeader; +import org.apache.jackrabbit.webdav.header.TimeoutHeader; +import org.apache.jackrabbit.webdav.lock.LockInfo; +import org.apache.jackrabbit.webdav.lock.Scope; +import org.apache.jackrabbit.webdav.lock.Type; +import org.apache.jackrabbit.webdav.observation.ObservationConstants; +import org.apache.jackrabbit.webdav.observation.SubscriptionInfo; +import org.apache.jackrabbit.webdav.ordering.OrderPatch; +import org.apache.jackrabbit.webdav.ordering.OrderingConstants; +import org.apache.jackrabbit.webdav.ordering.Position; +import org.apache.jackrabbit.webdav.property.DavProperty; +import org.apache.jackrabbit.webdav.property.DavPropertyName; +import org.apache.jackrabbit.webdav.property.DavPropertyNameSet; +import org.apache.jackrabbit.webdav.property.DavPropertySet; +import org.apache.jackrabbit.webdav.property.DefaultDavProperty; +import org.apache.jackrabbit.webdav.property.PropEntry; +import org.apache.jackrabbit.webdav.server.AbstractWebdavServlet; +import org.apache.jackrabbit.webdav.transaction.TransactionConstants; +import org.apache.jackrabbit.webdav.transaction.TransactionInfo; +import org.apache.jackrabbit.webdav.version.LabelInfo; +import org.apache.jackrabbit.webdav.version.MergeInfo; +import org.apache.jackrabbit.webdav.version.OptionsInfo; +import org.apache.jackrabbit.webdav.version.UpdateInfo; +import org.apache.jackrabbit.webdav.version.report.ReportInfo; +import org.apache.jackrabbit.webdav.xml.DomUtil; +import org.apache.jackrabbit.webdav.xml.ElementIterator; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.xml.sax.SAXException; + +/** + * WebdavRequestImpl... + */ +public class WebdavRequestImpl implements WebdavRequest, DavConstants, ContentCodingAwareRequest { + + private static Logger log = LoggerFactory.getLogger(WebdavRequestImpl.class); + + private final HttpServletRequest httpRequest; + private final DavLocatorFactory factory; + private final IfHeader ifHeader; + private final String hrefPrefix; + + private DavSession session; + + private int propfindType = PROPFIND_ALL_PROP; + private DavPropertyNameSet propfindProps; + private DavPropertySet proppatchSet; + private List proppatchList; + + /** + * Creates a new DavServletRequest with the given parameters. + */ + public WebdavRequestImpl(HttpServletRequest httpRequest, DavLocatorFactory factory) { + this(httpRequest, factory, true); + } + + /** + * Creates a new DavServletRequest with the given parameters. + * + * @param httpRequest + * @param factory + * @param createAbsoluteURI defines if we must create a absolute URI. if false a absolute path will be created + */ + public WebdavRequestImpl(HttpServletRequest httpRequest, DavLocatorFactory factory, boolean createAbsoluteURI) { + this.httpRequest = httpRequest; + this.factory = factory; + this.ifHeader = new IfHeader(httpRequest); + + String host = getHeader("Host"); + String scheme = getScheme(); + String uriPrefix = scheme + "://" + host + getContextPath(); + this.hrefPrefix = createAbsoluteURI ? uriPrefix : getContextPath(); + } + + /** + * Sets the session field and adds all lock tokens present with either the + * Lock-Token header or the If header to the given session object. + * + * @param session + * @see DavServletRequest#setDavSession(DavSession) + */ + public void setDavSession(DavSession session) { + this.session = session; + // set lock-tokens from header to the current session + if (session != null) { + String lt = getLockToken(); + if (lt != null) { + session.addLockToken(lt); + } + // add all token present in the the If header to the session as well. + Iterator it = ifHeader.getAllTokens(); + while (it.hasNext()) { + String ifHeaderToken = it.next(); + session.addLockToken(ifHeaderToken); + } + } + } + + /** + * @see DavServletRequest#getDavSession() + */ + public DavSession getDavSession() { + return session; + } + + /** + * Return a DavResourceLocator representing the request handle. + * + * @return locator of the requested resource + * @see DavServletRequest#getRequestLocator() + */ + public DavResourceLocator getRequestLocator() { + String path = getRequestURI(); + String ctx = getContextPath(); + if (path.startsWith(ctx)) { + path = path.substring(ctx.length()); + } + return factory.createResourceLocator(hrefPrefix, path); + } + + /** + * Parse the destination header field and return the path of the destination + * resource. + * + * @return path of the destination resource. + * @throws DavException + * @see #HEADER_DESTINATION + * @see DavServletRequest#getDestinationLocator + */ + public DavResourceLocator getDestinationLocator() throws DavException { + return getHrefLocator(httpRequest.getHeader(HEADER_DESTINATION), true); + } + + private DavResourceLocator getHrefLocator(String href, boolean forDestination) throws DavException { + String ref = href; + if (ref != null) { + //href should be a Simple-ref production as defined in RFC4918, so it is either an absolute URI + //or an absolute path + try { + URI uri = new URI(ref).normalize(); // normalize path (see JCR-3174) + String auth = uri.getAuthority(); + ref = uri.getRawPath(); + if (auth == null) { + //verify that href is an absolute path + if (ref.startsWith("//") || !ref.startsWith("/")) { + log.warn("expected absolute path but found " + ref); + throw new DavException(DavServletResponse.SC_BAD_REQUEST); + } + } else if (!auth.equals(httpRequest.getHeader("Host"))) { + //this looks like an unsupported cross-server operation, but of course a reverse-proxy + //might have rewritten the Host header. Since we can't find out, we have to reject anyway. + //Better use absolute paths in DAV:href elements! + throw new DavException(DavServletResponse.SC_FORBIDDEN); + } + } catch (URISyntaxException e) { + log.warn("malformed uri: " + href, e); + throw new DavException(DavServletResponse.SC_BAD_REQUEST); + } + // cut off the context path + String contextPath = httpRequest.getContextPath(); + if (ref.startsWith(contextPath)) { + ref = ref.substring(contextPath.length()); + } else { + //absolute path has to start with context path + throw new DavException(DavServletResponse.SC_FORBIDDEN); + } + } + if (factory instanceof AbstractLocatorFactory) { + return ((AbstractLocatorFactory)factory).createResourceLocator(hrefPrefix, ref, forDestination); + } + else { + return factory.createResourceLocator(hrefPrefix, ref); + } + } + + /** + * Parse a href and return the path of the resource. + * + * @return path of the resource identified by the href. + * @see org.apache.jackrabbit.webdav.bind.BindServletRequest#getHrefLocator + */ + public DavResourceLocator getHrefLocator(String href) throws DavException { + return getHrefLocator(href, false); + } + + /** + * Returns the path of the member resource of the request resource which is identified by the segment parameter. + * + * @return path of internal member resource. + */ + public DavResourceLocator getMemberLocator(String segment) { + String path = (this.getRequestLocator().getHref(true) + segment).substring(hrefPrefix.length()); + return factory.createResourceLocator(hrefPrefix, path); + } + + /** + * Return true if the overwrite header does not inhibit overwriting. + * + * @return true if the overwrite header requests 'overwriting' + * @see #HEADER_OVERWRITE + * @see DavServletRequest#isOverwrite() + */ + public boolean isOverwrite() { + return new OverwriteHeader(httpRequest).isOverwrite(); + } + + /** + * @see DavServletRequest#getDepth(int) + */ + public int getDepth(int defaultValue) { + return DepthHeader.parse(httpRequest, defaultValue).getDepth(); + } + + /** + * @see DavServletRequest#getDepth() + */ + public int getDepth() { + return getDepth(DEPTH_INFINITY); + } + + /** + * Parse the Timeout header and return a long representing the value. + * {@link #UNDEFINED_TIMEOUT} is used as default value if no header + * is available or if the parsing fails. + * + * @return milliseconds indicating length of the timeout. + * @see DavServletRequest#getTimeout() + * @see TimeoutHeader#parse(javax.servlet.http.HttpServletRequest, long) + */ + public long getTimeout() { + return TimeoutHeader.parse(httpRequest, UNDEFINED_TIMEOUT).getTimeout(); + } + + /** + * Retrieve the lock token from the 'Lock-Token' header. + * + * @return String representing the lock token sent in the Lock-Token header. + * @throws IllegalArgumentException If the value has not the correct format. + * @see #HEADER_LOCK_TOKEN + * @see DavServletRequest#getLockToken() + */ + public String getLockToken() { + return CodedUrlHeader.parse(httpRequest, HEADER_LOCK_TOKEN).getCodedUrl(); + } + + /** + * @see DavServletRequest#getRequestDocument() + */ + public Document getRequestDocument() throws DavException { + Document requestDocument = null; + /* + Don't attempt to parse the body if the content length header is 0. + NOTE: a value of -1 indicates that the length is unknown, thus we have + to parse the body. Note that http1.1 request using chunked transfer + coding will therefore not be detected here. + */ + if (httpRequest.getContentLength() == 0) { + return requestDocument; + } + // try to parse the request body + try { + InputStream in = getDecodedInputStream(); + if (in != null) { + // use a buffered input stream to find out whether there actually + // is a request body + InputStream bin = new BufferedInputStream(in); + bin.mark(1); + boolean isEmpty = -1 == bin.read(); + bin.reset(); + if (!isEmpty) { + requestDocument = DomUtil.parseDocument(bin); + } + } + } catch (IOException e) { + if (log.isDebugEnabled()) { + log.debug("Unable to build an XML Document from the request body: " + e.getMessage()); + } + Throwable cause = e.getCause(); + throw (cause instanceof DavException) ? (DavException) cause : new DavException(DavServletResponse.SC_BAD_REQUEST); + } catch (ParserConfigurationException e) { + if (log.isDebugEnabled()) { + log.debug("Unable to build an XML Document from the request body: " + e.getMessage()); + } + throw new DavException(DavServletResponse.SC_INTERNAL_SERVER_ERROR); + } catch (SAXException e) { + if (log.isDebugEnabled()) { + log.debug("Unable to build an XML Document from the request body: " + e.getMessage()); + } + throw new DavException(DavServletResponse.SC_BAD_REQUEST); + } + return requestDocument; + } + + /** + * Returns the type of PROPFIND as indicated by the request body. + * + * @return type of the PROPFIND request. Default value is {@link #PROPFIND_ALL_PROP allprops} + * @see DavServletRequest#getPropFindType() + */ + public int getPropFindType() throws DavException { + if (propfindProps == null) { + parsePropFindRequest(); + } + return propfindType; + } + + /** + * Returns the set of properties requested by the PROPFIND body or an + * empty set if the {@link #getPropFindType type} is either 'allprop' or + * 'propname'. + * + * @return set of properties requested by the PROPFIND body or an empty set. + * @see DavServletRequest#getPropFindProperties() + */ + public DavPropertyNameSet getPropFindProperties() throws DavException { + if (propfindProps == null) { + parsePropFindRequest(); + } + return propfindProps; + } + + private InputStream getDecodedInputStream() throws IOException { + List contentCodings = getRequestContentCodings(); + int len = contentCodings.size(); + + log.trace("content codings: " + contentCodings); + InputStream result = httpRequest.getInputStream(); + + for (int i = 1; i <= len; i++) { + String s = contentCodings.get(len - i); + log.trace("decoding: " + s); + if ("gzip".equals(s)) { + result = new GZIPInputStream(result); + } else if ("deflate".equals(s)) { + result = new InflaterInputStream(result); + } else { + String message = "Unsupported content coding: " + s; + try { + Element condition = DomUtil.createElement(DomUtil.createDocument(), PRECONDITION_SUPPORTED); + throw new IOException( + new DavException(HttpServletResponse.SC_UNSUPPORTED_MEDIA_TYPE, message, null, condition)); + } catch (ParserConfigurationException ex) { + throw new IOException(message); + } + } + } + + return result; + } + + private List requestContentCodings = null; + + @Override + public List getRequestContentCodings() { + if (requestContentCodings == null) { + requestContentCodings = AbstractWebdavServlet.getContentCodings(httpRequest); + } + + return requestContentCodings; + } + + @Override + public String getAcceptableCodings() { + return "deflate, gzip"; + } + + /** + * Parse the propfind request body in order to determine the type of the propfind + * and the set of requested property. + * NOTE: An empty 'propfind' request body will be treated as request for all + * property according to the specification. + */ + private void parsePropFindRequest() throws DavException { + propfindProps = new DavPropertyNameSet(); + Document requestDocument = getRequestDocument(); + // propfind httpRequest with empty body >> retrieve all property + if (requestDocument == null) { + return; + } + + // propfind httpRequest with invalid body + Element root = requestDocument.getDocumentElement(); + if (!XML_PROPFIND.equals(root.getLocalName())) { + log.info("PropFind-Request has no tag."); + throw new DavException(DavServletResponse.SC_BAD_REQUEST, "PropFind-Request has no tag."); + } + + DavPropertyNameSet include = null; + + ElementIterator it = DomUtil.getChildren(root); + int propfindTypeFound = 0; + + while (it.hasNext()) { + Element child = it.nextElement(); + String nodeName = child.getLocalName(); + if (NAMESPACE.getURI().equals(child.getNamespaceURI())) { + if (XML_PROP.equals(nodeName)) { + propfindType = PROPFIND_BY_PROPERTY; + propfindProps = new DavPropertyNameSet(child); + propfindTypeFound += 1; + } + else if (XML_PROPNAME.equals(nodeName)) { + propfindType = PROPFIND_PROPERTY_NAMES; + propfindTypeFound += 1; + } + else if (XML_ALLPROP.equals(nodeName)) { + propfindType = PROPFIND_ALL_PROP; + propfindTypeFound += 1; + } + else if (XML_INCLUDE.equals(nodeName)) { + include = new DavPropertyNameSet(); + ElementIterator pit = DomUtil.getChildren(child); + while (pit.hasNext()) { + include.add(DavPropertyName.createFromXml(pit.nextElement())); + } + } + } + } + + if (propfindTypeFound > 1) { + log.info("Multiple top-level propfind instructions"); + throw new DavException(DavServletResponse.SC_BAD_REQUEST, "Multiple top-level propfind instructions"); + } + + if (include != null) { + if (propfindType == PROPFIND_ALL_PROP) { + // special case: allprop with include extension + propfindType = PROPFIND_ALL_PROP_INCLUDE; + propfindProps = include; + } + else { + throw new DavException(DavServletResponse.SC_BAD_REQUEST, " goes only with "); + + } + } + } + + /** + * Return a {@link List} of property change operations. Each entry + * is either of type {@link DavPropertyName}, indicating a <remove> + * operation, or of type {@link DavProperty}, indicating a <set> + * operation. Note that ordering is significant here. + * + * @return the list of change operations entries in the PROPPATCH request body + * @see DavServletRequest#getPropPatchChangeList() + */ + public List getPropPatchChangeList() throws DavException { + if (proppatchList == null) { + parsePropPatchRequest(); + } + return proppatchList; + } + + /** + * Parse the PROPPATCH request body. + */ + private void parsePropPatchRequest() throws DavException { + + proppatchSet = new DavPropertySet(); + proppatchList = new ArrayList(); + + Document requestDocument = getRequestDocument(); + + if (requestDocument == null) { + throw new DavException(DavServletResponse.SC_BAD_REQUEST, "Invalid request body."); + } + + Element root = requestDocument.getDocumentElement(); + if (!DomUtil.matches(root, XML_PROPERTYUPDATE, NAMESPACE)) { + log.warn("PropPatch-Request has no tag."); + throw new DavException(DavServletResponse.SC_BAD_REQUEST, "PropPatch-Request has no tag."); + } + + ElementIterator it = DomUtil.getChildren(root); + while (it.hasNext()) { + Element el = it.nextElement(); + if (DomUtil.matches(el, XML_SET, NAMESPACE)) { + Element propEl = DomUtil.getChildElement(el, XML_PROP, NAMESPACE); + if (propEl != null) { + ElementIterator properties = DomUtil.getChildren(propEl); + while (properties.hasNext()) { + DavProperty davProp = DefaultDavProperty.createFromXml(properties.nextElement()); + proppatchSet.add(davProp); + proppatchList.add(davProp); + } + } + } else if (DomUtil.matches(el, XML_REMOVE, NAMESPACE)) { + Element propEl = DomUtil.getChildElement(el, XML_PROP, NAMESPACE); + if (propEl != null) { + ElementIterator properties = DomUtil.getChildren(propEl); + while (properties.hasNext()) { + DavProperty davProp = DefaultDavProperty.createFromXml(properties.nextElement()); + proppatchSet.add(davProp); + proppatchList.add(davProp.getName()); + } + } + } else { + log.debug("Unknown element in DAV:propertyupdate: " + el.getNodeName()); + // unknown child elements are ignored + } + } + } + + /** + * {@link LockInfo} object encapsulating the information passed with a LOCK + * request if the LOCK request body was valid. If the request body is + * missing a 'refresh lock' request is assumed. The {@link LockInfo} + * then only provides timeout and isDeep property and returns true on + * {@link org.apache.jackrabbit.webdav.lock.LockInfo#isRefreshLock()} + * + * @return lock info object or null if an error occurred while + * parsing the request body. + * @throws DavException throws a 400 (Bad Request) DavException if a request + * body is present but does not start with a DAV:lockinfo element. Note however, + * that a non-existing request body is a valid request used to refresh + * an existing lock. + * @see DavServletRequest#getLockInfo() + */ + public LockInfo getLockInfo() throws DavException { + LockInfo lockInfo; + boolean isDeep = (getDepth(DEPTH_INFINITY) == DEPTH_INFINITY); + Document requestDocument = getRequestDocument(); + // check if XML request body is present. It SHOULD have one for + // 'create Lock' request and missing for a 'refresh Lock' request + if (requestDocument != null) { + Element root = requestDocument.getDocumentElement(); + if (root.getLocalName().equals(XML_LOCKINFO)) { + lockInfo = new LockInfo(root, getTimeout(), isDeep); + } else { + log.debug("Lock request body must start with a DAV:lockinfo element."); + throw new DavException(DavServletResponse.SC_BAD_REQUEST); + } + } else { + lockInfo = new LockInfo(null, getTimeout(), isDeep); + } + return lockInfo; + } + + /** + * Test if the if header matches the given resource. The comparison is + * made with the {@link DavResource#getHref() + * resource href} and the token returned from an exclusive write lock present on + * the resource.
+ * NOTE: If either the If header or the resource is null or if + * the resource has not applied an exclusive write lock the preconditions are met. + * If in contrast the lock applied to the given resource returns a + * null lock token (e.g. for security reasons) or a lock token + * that does not match, the method will return false. + * + * @param resource Webdav resources being operated on + * @return true if the test is successful and the preconditions for the + * request processing are fulfilled. + * @see DavServletRequest#matchesIfHeader(DavResource) + * @see IfHeader#matches(String, String, String) + * @see DavResource#hasLock(org.apache.jackrabbit.webdav.lock.Type, org.apache.jackrabbit.webdav.lock.Scope) + * @see org.apache.jackrabbit.webdav.lock.ActiveLock#getToken() + */ + public boolean matchesIfHeader(DavResource resource) { + // no ifheader, no resource or no write lock on resource + // >> preconditions ok so far + if (!ifHeader.hasValue() || resource == null || !resource.hasLock(Type.WRITE, Scope.EXCLUSIVE)) { + return true; + } + + boolean isMatching = false; + String lockToken = resource.getLock(Type.WRITE, Scope.EXCLUSIVE).getToken(); + if (lockToken != null) { + isMatching = matchesIfHeader(resource.getHref(), lockToken, getStrongETag(resource)); + } // else: lockToken is null >> the if-header will not match. + + return isMatching; + } + + /** + * @see DavServletRequest#matchesIfHeader(String, String, String) + * @see IfHeader#matches(String, String, String) + */ + public boolean matchesIfHeader(String href, String token, String eTag) { + return ifHeader.matches(href, token, isStrongETag(eTag) ? eTag : ""); + } + + /** + * Returns the strong etag present on the given resource or empty string + * if either the resource does not provide any etag or if the etag is weak. + * + * @param resource + * @return strong etag or empty string. + */ + private String getStrongETag(DavResource resource) { + DavProperty prop = resource.getProperty(DavPropertyName.GETETAG); + if (prop != null && prop.getValue() != null) { + String etag = prop.getValue().toString(); + if (isStrongETag(etag)) { + return etag; + } + } + // no strong etag available + return ""; + } + + /** + * Returns true if the given string represents a strong etag. + * + * @param eTag + * @return true, if its a strong etag + */ + private static boolean isStrongETag(String eTag) { + return eTag != null && eTag.length() > 0 && !eTag.startsWith("W\\"); + } + + //-----------------------------< TransactionDavServletRequest Interface >--- + /** + * @see org.apache.jackrabbit.webdav.transaction.TransactionDavServletRequest#getTransactionId() + */ + public String getTransactionId() { + return CodedUrlHeader.parse(httpRequest, TransactionConstants.HEADER_TRANSACTIONID).getCodedUrl(); + } + + /** + * @see org.apache.jackrabbit.webdav.transaction.TransactionDavServletRequest#getTransactionInfo() + */ + public TransactionInfo getTransactionInfo() throws DavException { + Document requestDocument = getRequestDocument(); + if (requestDocument != null) { + return new TransactionInfo(requestDocument.getDocumentElement()); + } + return null; + } + + //-----------------------------< ObservationDavServletRequest Interface >--- + /** + * @see org.apache.jackrabbit.webdav.observation.ObservationDavServletRequest#getSubscriptionId() + */ + public String getSubscriptionId() { + return CodedUrlHeader.parse(httpRequest, ObservationConstants.HEADER_SUBSCRIPTIONID).getCodedUrl(); + } + + /** + * @see org.apache.jackrabbit.webdav.observation.ObservationDavServletRequest#getPollTimeout() + */ + public long getPollTimeout() { + return PollTimeoutHeader.parseHeader(httpRequest, 0).getTimeout(); + } + + /** + * @see org.apache.jackrabbit.webdav.observation.ObservationDavServletRequest#getSubscriptionInfo() + */ + public SubscriptionInfo getSubscriptionInfo() throws DavException { + Document requestDocument = getRequestDocument(); + if (requestDocument != null) { + Element root = requestDocument.getDocumentElement(); + if (ObservationConstants.XML_SUBSCRIPTIONINFO.equals(root.getLocalName())) { + int depth = getDepth(DEPTH_0); + return new SubscriptionInfo(root, getTimeout(), depth == DEPTH_INFINITY); + } + } + return null; + } + + //--------------------------------< OrderingDavServletRequest Interface >--- + /** + * @see org.apache.jackrabbit.webdav.ordering.OrderingDavServletRequest#getOrderingType() + */ + public String getOrderingType() { + return getHeader(OrderingConstants.HEADER_ORDERING_TYPE); + } + + /** + * @see org.apache.jackrabbit.webdav.ordering.OrderingDavServletRequest#getPosition() + */ + public Position getPosition() { + String h = getHeader(OrderingConstants.HEADER_POSITION); + Position pos = null; + if (h != null) { + String[] typeNSegment = h.split("\\s"); + if (typeNSegment.length == 2) { + try { + pos = new Position(typeNSegment[0], typeNSegment[1]); + } catch (IllegalArgumentException e) { + log.error("Cannot parse Position header: " + e.getMessage()); + } + } + } + return pos; + } + + /** + * @return OrderPatch object representing the orderpatch request + * body or null if the + * @see org.apache.jackrabbit.webdav.ordering.OrderingDavServletRequest#getOrderPatch() + */ + public OrderPatch getOrderPatch() throws DavException { + OrderPatch op = null; + Document requestDocument = getRequestDocument(); + if (requestDocument != null) { + Element root = requestDocument.getDocumentElement(); + op = OrderPatch.createFromXml(root); + } else { + log.error("Error while building xml document from ORDERPATH request body."); + } + return op; + } + + //-------------------------------------< DeltaVServletRequest interface >--- + /** + * @see org.apache.jackrabbit.webdav.version.DeltaVServletRequest#getLabel() + */ + public String getLabel() { + LabelHeader label = LabelHeader.parse(this); + if (label != null) { + return label.getLabel(); + } + return null; + } + + /** + * @see org.apache.jackrabbit.webdav.version.DeltaVServletRequest#getLabelInfo() + */ + public LabelInfo getLabelInfo() throws DavException { + LabelInfo lInfo = null; + Document requestDocument = getRequestDocument(); + if (requestDocument != null) { + Element root = requestDocument.getDocumentElement(); + int depth = getDepth(DEPTH_0); + lInfo = new LabelInfo(root, depth); + } + return lInfo; + } + + /** + * @see org.apache.jackrabbit.webdav.version.DeltaVServletRequest#getMergeInfo() + */ + public MergeInfo getMergeInfo() throws DavException { + MergeInfo mInfo = null; + Document requestDocument = getRequestDocument(); + if (requestDocument != null) { + mInfo = new MergeInfo(requestDocument.getDocumentElement()); + } + return mInfo; + } + + /** + * @see org.apache.jackrabbit.webdav.version.DeltaVServletRequest#getUpdateInfo() + */ + public UpdateInfo getUpdateInfo() throws DavException { + UpdateInfo uInfo = null; + Document requestDocument = getRequestDocument(); + if (requestDocument != null) { + uInfo = new UpdateInfo(requestDocument.getDocumentElement()); + } + return uInfo; + } + + /** + * @see org.apache.jackrabbit.webdav.version.DeltaVServletRequest#getReportInfo() + */ + public ReportInfo getReportInfo() throws DavException { + ReportInfo rInfo = null; + Document requestDocument = getRequestDocument(); + if (requestDocument != null) { + rInfo = new ReportInfo(requestDocument.getDocumentElement(), getDepth(DEPTH_0)); + } + return rInfo; + } + + /** + * @see org.apache.jackrabbit.webdav.version.DeltaVServletRequest#getOptionsInfo() + */ + public OptionsInfo getOptionsInfo() throws DavException { + OptionsInfo info = null; + Document requestDocument = getRequestDocument(); + if (requestDocument != null) { + info = OptionsInfo.createFromXml(requestDocument.getDocumentElement()); + } + return info; + } + + /** + * @see org.apache.jackrabbit.webdav.bind.BindServletRequest#getRebindInfo() + */ + public RebindInfo getRebindInfo() throws DavException { + RebindInfo info = null; + Document requestDocument = getRequestDocument(); + if (requestDocument != null) { + info = RebindInfo.createFromXml(requestDocument.getDocumentElement()); + } + return info; + } + + /** + * @see org.apache.jackrabbit.webdav.bind.BindServletRequest#getUnbindInfo() + */ + public UnbindInfo getUnbindInfo() throws DavException { + UnbindInfo info = null; + Document requestDocument = getRequestDocument(); + if (requestDocument != null) { + info = UnbindInfo.createFromXml(requestDocument.getDocumentElement()); + } + return info; + } + + /** + * @see org.apache.jackrabbit.webdav.bind.BindServletRequest#getBindInfo() + */ + public BindInfo getBindInfo() throws DavException { + BindInfo info = null; + Document requestDocument = getRequestDocument(); + if (requestDocument != null) { + info = BindInfo.createFromXml(requestDocument.getDocumentElement()); + } + return info; + } + + //---------------------------------------< HttpServletRequest interface >--- + + @Override + public String getAuthType() { + return httpRequest.getAuthType(); + } + + @Override + public Cookie[] getCookies() { + return httpRequest.getCookies(); + } + + @Override + public long getDateHeader(String s) { + return httpRequest.getDateHeader(s); + } + + @Override + public String getHeader(String s) { + return httpRequest.getHeader(s); + } + + @Override + public Enumeration getHeaders(String s) { + return httpRequest.getHeaders(s); + } + + @Override + public Enumeration getHeaderNames() { + return httpRequest.getHeaderNames(); + } + + @Override + public int getIntHeader(String s) { + return httpRequest.getIntHeader(s); + } + + @Override + public String getMethod() { + return httpRequest.getMethod(); + } + + @Override + public String getPathInfo() { + return httpRequest.getPathInfo(); + } + + @Override + public String getPathTranslated() { + return httpRequest.getPathTranslated(); + } + + @Override + public String getContextPath() { + return httpRequest.getContextPath(); + } + + @Override + public String getQueryString() { + return httpRequest.getQueryString(); + } + + @Override + public String getRemoteUser() { + return httpRequest.getRemoteUser(); + } + + @Override + public boolean isUserInRole(String s) { + return httpRequest.isUserInRole(s); + } + + @Override + public Principal getUserPrincipal() { + return httpRequest.getUserPrincipal(); + } + + @Override + public String getRequestedSessionId() { + return httpRequest.getRequestedSessionId(); + } + + @Override + public String getRequestURI() { + return httpRequest.getRequestURI(); + } + + @Override + public StringBuffer getRequestURL() { + return httpRequest.getRequestURL(); + } + + @Override + public String getServletPath() { + return httpRequest.getServletPath(); + } + + @Override + public HttpSession getSession(boolean b) { + return httpRequest.getSession(b); + } + + @Override + public HttpSession getSession() { + return httpRequest.getSession(); + } + + @Override + public boolean isRequestedSessionIdValid() { + return httpRequest.isRequestedSessionIdValid(); + } + + @Override + public boolean isRequestedSessionIdFromCookie() { + return httpRequest.isRequestedSessionIdFromCookie(); + } + + @Override + public boolean isRequestedSessionIdFromURL() { + return httpRequest.isRequestedSessionIdFromURL(); + } + + @Override + public boolean isRequestedSessionIdFromUrl() { + return httpRequest.isRequestedSessionIdFromUrl(); + } + + @Override + public Object getAttribute(String s) { + return httpRequest.getAttribute(s); + } + + @Override + public Enumeration getAttributeNames() { + return httpRequest.getAttributeNames(); + } + + @Override + public String getCharacterEncoding() { + return httpRequest.getCharacterEncoding(); + } + + @Override + public void setCharacterEncoding(String s) throws UnsupportedEncodingException { + httpRequest.setCharacterEncoding(s); + } + + @Override + public int getContentLength() { + return httpRequest.getContentLength(); + } + + @Override + public String getContentType() { + return httpRequest.getContentType(); + } + + @Override + public ServletInputStream getInputStream() throws IOException { + return new MyServletInputStream(getDecodedInputStream()); + } + + @Override + public String getParameter(String s) { + return httpRequest.getParameter(s); + } + + @Override + public Enumeration getParameterNames() { + return httpRequest.getParameterNames(); + } + + @Override + public String[] getParameterValues(String s) { + return httpRequest.getParameterValues(s); + } + + @Override + public Map getParameterMap() { + return httpRequest.getParameterMap(); + } + + @Override + public String getProtocol() { + return httpRequest.getProtocol(); + } + + @Override + public String getScheme() { + return httpRequest.getScheme(); + } + + @Override + public String getServerName() { + return httpRequest.getServerName(); + } + + @Override + public int getServerPort() { + return httpRequest.getServerPort(); + } + + @Override + public BufferedReader getReader() throws IOException { + return httpRequest.getReader(); + } + + @Override + public String getRemoteAddr() { + return httpRequest.getRemoteAddr(); + } + + @Override + public String getRemoteHost() { + return httpRequest.getRemoteHost(); + } + + @Override + public void setAttribute(String s, Object o) { + httpRequest.setAttribute(s, o); + } + + @Override + public void removeAttribute(String s) { + httpRequest.removeAttribute(s); + } + + @Override + public Locale getLocale() { + return httpRequest.getLocale(); + } + + @Override + public Enumeration getLocales() { + return httpRequest.getLocales(); + } + + @Override + public boolean isSecure() { + return httpRequest.isSecure(); + } + + @Override + public RequestDispatcher getRequestDispatcher(String s) { + return httpRequest.getRequestDispatcher(s); + } + + @Override + public String getRealPath(String s) { + return httpRequest.getRealPath(s); + } + + @Override + public int getRemotePort() { + return httpRequest.getRemotePort(); + } + + @Override + public String getLocalName() { + return httpRequest.getLocalName(); + } + + @Override + public String getLocalAddr() { + return httpRequest.getLocalAddr(); + } + + @Override + public int getLocalPort() { + return httpRequest.getLocalPort(); + } + + @Override + public String changeSessionId() { + return httpRequest.changeSessionId(); + } + + @Override + public boolean authenticate(HttpServletResponse response) throws IOException, ServletException { + return httpRequest.authenticate(response); + } + + @Override + public void login(String username, String password) throws ServletException { + httpRequest.login(username, password); + } + + @Override + public void logout() throws ServletException { + httpRequest.logout(); + } + + @Override + public Collection getParts() throws IOException, ServletException { + return httpRequest.getParts(); + } + + @Override + public Part getPart(String name) throws IOException, ServletException { + return httpRequest.getPart(name); + } + + @Override + public T upgrade(Class handlerClass) throws IOException, ServletException { + return httpRequest.upgrade(handlerClass); + } + + @Override + public long getContentLengthLong() { + return httpRequest.getContentLengthLong(); + } + + @Override + public ServletContext getServletContext() { + return httpRequest.getServletContext(); + } + + @Override + public AsyncContext startAsync() throws IllegalStateException { + return httpRequest.startAsync(); + } + + @Override + public AsyncContext startAsync(ServletRequest servletRequest, ServletResponse servletResponse) throws IllegalStateException { + return httpRequest.startAsync(servletRequest, servletResponse); + } + + @Override + public boolean isAsyncStarted() { + return httpRequest.isAsyncStarted(); + } + + @Override + public boolean isAsyncSupported() { + return httpRequest.isAsyncSupported(); + } + + @Override + public AsyncContext getAsyncContext() { + return httpRequest.getAsyncContext(); + } + + @Override + public DispatcherType getDispatcherType() { + return httpRequest.getDispatcherType(); + } + + private static class MyServletInputStream extends ServletInputStream { + + private final InputStream delegate; + + public MyServletInputStream(InputStream delegate) { + this.delegate = delegate; + } + + @Override + public int available() throws IOException { + return delegate.available(); + } + + @Override + public void close() throws IOException { + delegate.close(); + } + + @Override + public boolean equals(Object other) { + return delegate.equals(other); + } + + @Override + public int hashCode() { + return delegate.hashCode(); + } + + @Override + public void mark(int readlimit) { + delegate.mark(readlimit); + } + + @Override + public boolean markSupported() { + return delegate.markSupported(); + } + + @Override + public int read() throws IOException { + return delegate.read(); + } + + @Override + public int read(byte[] b, int off, int len) throws IOException { + return delegate.read(b, off, len); + } + + @Override + public int read(byte[] b) throws IOException { + return delegate.read(b); + } + + @Override + public int readLine(byte[] b, int off, int len) throws IOException { + throw new UnsupportedOperationException(); + } + + @Override + public void reset() throws IOException { + delegate.reset(); + } + + @Override + public long skip(long n) throws IOException { + return delegate.skip(n); + } + + @Override + public String toString() { + return delegate.toString(); + } + + @Override + public boolean isFinished() { + throw new UnsupportedOperationException(); + } + + @Override + public boolean isReady() { + throw new UnsupportedOperationException(); + } + + @Override + public void setReadListener(ReadListener readListener) { + throw new UnsupportedOperationException(); + } + } +} Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/WebdavRequestImpl.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/WebdavResponse.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/WebdavResponse.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/WebdavResponse.java (working copy) @@ -0,0 +1,42 @@ +/* + * 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.webdav; + +import java.util.Map; +import java.util.function.Supplier; + +import org.apache.jackrabbit.webdav.observation.ObservationDavServletResponse; + +/** + * The empty WebdavResponse interface collects the functionality + * defined by {@link org.apache.jackrabbit.webdav.DavServletResponse} + * encapsulating for the core WebDAV specification (RFC 2518) as well as the + * various extensions used for observation and transaction support, ordering of + * collections, search and versioning. + */ +public interface WebdavResponse extends DavServletResponse, ObservationDavServletResponse { + + // can be removed when we move to Servlet API 4.0 + public default void setTrailerFields(Supplier> supplier) { + // nop + } + + // can be removed when we move to Servlet API 4.0 + public default Supplier> getTrailerFields() { + return null; + } +} \ No newline at end of file Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/WebdavResponse.java ___________________________________________________________________ Added: svn Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/WebdavResponseImpl.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/WebdavResponseImpl.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/WebdavResponseImpl.java (working copy) @@ -0,0 +1,407 @@ +/* + * 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.webdav; + +import org.apache.jackrabbit.webdav.header.CodedUrlHeader; +import org.apache.jackrabbit.webdav.header.Header; +import org.apache.jackrabbit.webdav.lock.ActiveLock; +import org.apache.jackrabbit.webdav.lock.LockDiscovery; +import org.apache.jackrabbit.webdav.observation.EventDiscovery; +import org.apache.jackrabbit.webdav.observation.ObservationConstants; +import org.apache.jackrabbit.webdav.observation.Subscription; +import org.apache.jackrabbit.webdav.observation.SubscriptionDiscovery; +import org.apache.jackrabbit.webdav.property.DavPropertySet; +import org.apache.jackrabbit.webdav.xml.DomUtil; +import org.apache.jackrabbit.webdav.xml.XmlSerializable; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.w3c.dom.Document; +import org.xml.sax.SAXException; + +import javax.servlet.ServletOutputStream; +import javax.servlet.http.Cookie; +import javax.servlet.http.HttpServletResponse; +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.transform.TransformerException; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.io.PrintWriter; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.function.Supplier; +import java.util.zip.GZIPOutputStream; + +/** + * WebdavResponseImpl implements the WebdavResponse interface. + */ +public class WebdavResponseImpl implements WebdavResponse { + + private static Logger log = LoggerFactory.getLogger(WebdavResponseImpl.class); + + private HttpServletResponse httpResponse; + + /** + * Create a new WebdavResponse + * + * @param httpResponse + */ + public WebdavResponseImpl(HttpServletResponse httpResponse) { + this(httpResponse, false); + } + + /** + * Create a new WebdavResponse + * + * @param httpResponse + * @param noCache + */ + public WebdavResponseImpl(HttpServletResponse httpResponse, boolean noCache) { + this.httpResponse = httpResponse; + if (noCache) { + /* set cache control headers */ + addHeader("Pragma", "No-cache"); // http1.0 + addHeader("Cache-Control", "no-cache"); // http1.1 + } + } + + /** + * If the specifid exception provides an error condition an Xml response body + * is sent providing more detailed information about the error. Otherwise only + * the error code and status phrase is sent back. + * + * @param exception + * @throws IOException + * @see DavServletResponse#sendError(org.apache.jackrabbit.webdav.DavException) + * @see #sendError(int, String) + * @see #sendXmlResponse(XmlSerializable, int) + */ + public void sendError(DavException exception) throws IOException { + if (!exception.hasErrorCondition()) { + httpResponse.sendError(exception.getErrorCode(), exception.getStatusPhrase()); + } else { + sendXmlResponse(exception, exception.getErrorCode()); + } + } + + @Override + public void sendMultiStatus(MultiStatus multistatus) throws IOException { + sendXmlResponse(multistatus, SC_MULTI_STATUS); + } + + @Override + public void sendMultiStatus(MultiStatus multistatus, List acceptableContentCodings) throws IOException { + sendXmlResponse(multistatus, SC_MULTI_STATUS, acceptableContentCodings); + } + + /** + * Send response body for a lock request that was intended to refresh one + * or several locks. + * + * @param locks + * @throws java.io.IOException + * @see DavServletResponse#sendRefreshLockResponse(org.apache.jackrabbit.webdav.lock.ActiveLock[]) + */ + public void sendRefreshLockResponse(ActiveLock[] locks) throws IOException { + DavPropertySet propSet = new DavPropertySet(); + propSet.add(new LockDiscovery(locks)); + sendXmlResponse(propSet, SC_OK); + } + + @Override + public void sendXmlResponse(XmlSerializable serializable, int status) throws IOException { + sendXmlResponse(serializable, status, Collections.emptyList()); + } + + @Override + public void sendXmlResponse(XmlSerializable serializable, int status, List acceptableContentCodings) throws IOException { + httpResponse.setStatus(status); + + if (serializable != null) { + try { + ByteArrayOutputStream out = new ByteArrayOutputStream(); + Document doc = DomUtil.createDocument(); + doc.appendChild(serializable.toXml(doc)); + DomUtil.transformDocument(doc, out); + out.close(); + + httpResponse.setContentType("text/xml; charset=UTF-8"); + + // use GZIP iff accepted by client and content size >= 256 octets + if (out.size() < 256 || !acceptableContentCodings.contains("gzip")) { + httpResponse.setContentLength(out.size()); + out.writeTo(httpResponse.getOutputStream()); + } else { + httpResponse.setHeader("Content-Encoding", "gzip"); + try (OutputStream os = new GZIPOutputStream(httpResponse.getOutputStream())) { + out.writeTo(os); + } + } + } catch (ParserConfigurationException e) { + log.error(e.getMessage()); + throw new IOException(e.getMessage()); + } catch (TransformerException e) { + log.error(e.getMessage()); + throw new IOException(e.getMessage()); + } catch (SAXException e) { + log.error(e.getMessage()); + throw new IOException(e.getMessage()); + } + } + } + + //----------------------------< ObservationDavServletResponse Interface >--- + /** + * + * @param subscription + * @throws IOException + * @see org.apache.jackrabbit.webdav.observation.ObservationDavServletResponse#sendSubscriptionResponse(org.apache.jackrabbit.webdav.observation.Subscription) + */ + public void sendSubscriptionResponse(Subscription subscription) throws IOException { + String id = subscription.getSubscriptionId(); + if (id != null) { + Header h = new CodedUrlHeader(ObservationConstants.HEADER_SUBSCRIPTIONID, id); + httpResponse.setHeader(h.getHeaderName(), h.getHeaderValue()); + } + DavPropertySet propSet = new DavPropertySet(); + propSet.add(new SubscriptionDiscovery(subscription)); + sendXmlResponse(propSet, SC_OK); + } + + /** + * + * @param eventDiscovery + * @throws IOException + * @see org.apache.jackrabbit.webdav.observation.ObservationDavServletResponse#sendPollResponse(org.apache.jackrabbit.webdav.observation.EventDiscovery) + */ + public void sendPollResponse(EventDiscovery eventDiscovery) throws IOException { + sendXmlResponse(eventDiscovery, SC_OK); + } + + //--------------------------------------< HttpServletResponse interface >--- + + @Override + public void addCookie(Cookie cookie) { + httpResponse.addCookie(cookie); + } + + @Override + public boolean containsHeader(String s) { + return httpResponse.containsHeader(s); + } + + @Override + public String encodeURL(String s) { + return httpResponse.encodeRedirectURL(s); + } + + @Override + public String encodeRedirectURL(String s) { + return httpResponse.encodeRedirectURL(s); + } + + @Override + public String encodeUrl(String s) { + return httpResponse.encodeUrl(s); + } + + @Override + public String encodeRedirectUrl(String s) { + return httpResponse.encodeRedirectURL(s); + } + + @Override + public void sendError(int i, String s) throws IOException { + httpResponse.sendError(i, s); + } + + @Override + public void sendError(int i) throws IOException { + httpResponse.sendError(i); + } + + @Override + public void sendRedirect(String s) throws IOException { + httpResponse.sendRedirect(s); + } + + @Override + public void setDateHeader(String s, long l) { + httpResponse.setDateHeader(s, l); + } + + @Override + public void addDateHeader(String s, long l) { + httpResponse.addDateHeader(s, l); + } + + @Override + public void setHeader(String s, String s1) { + httpResponse.setHeader(s, s1); + } + + @Override + public void addHeader(String s, String s1) { + httpResponse.addHeader(s, s1); + } + + @Override + public void setIntHeader(String s, int i) { + httpResponse.setIntHeader(s, i); + } + + @Override + public void addIntHeader(String s, int i) { + httpResponse.addIntHeader(s, i); + } + + @Override + public void setStatus(int i) { + httpResponse.setStatus(i); + } + + @Override + public void setStatus(int i, String s) { + httpResponse.setStatus(i, s); + } + + @Override + public String getCharacterEncoding() { + return httpResponse.getCharacterEncoding(); + } + + @Override + public ServletOutputStream getOutputStream() throws IOException { + return httpResponse.getOutputStream(); + } + + @Override + public PrintWriter getWriter() throws IOException { + return httpResponse.getWriter(); + } + + @Override + public void setContentLength(int i) { + httpResponse.setContentLength(i); + } + + @Override + public void setContentType(String s) { + httpResponse.setContentType(s); + } + + @Override + public void setBufferSize(int i) { + httpResponse.setBufferSize(i); + } + + @Override + public int getBufferSize() { + return httpResponse.getBufferSize(); + } + + @Override + public void flushBuffer() throws IOException { + httpResponse.flushBuffer(); + } + + @Override + public void resetBuffer() { + httpResponse.resetBuffer(); + } + + @Override + public boolean isCommitted() { + return httpResponse.isCommitted(); + } + + @Override + public void reset() { + httpResponse.reset(); + } + + @Override + public void setLocale(Locale locale) { + httpResponse.setLocale(locale); + } + + @Override + public Locale getLocale() { + return httpResponse.getLocale(); + } + + @Override + public String getContentType() { + return httpResponse.getContentType(); + } + + @Override + public void setCharacterEncoding(String charset) { + httpResponse.setCharacterEncoding(charset); + } + + @Override + public int getStatus() { + return httpResponse.getStatus(); + } + + @Override + public String getHeader(String name) { + return httpResponse.getHeader(name); + } + + @Override + public Collection getHeaders(String name) { + return httpResponse.getHeaders(name); + } + + @Override + public Collection getHeaderNames() { + return httpResponse.getHeaderNames(); + } + + @Override + public void setContentLengthLong(long len) { + httpResponse.setContentLengthLong(len); + } + + // Servlet 4.0 API support for trailers, for now using reflection + + public void setTrailerFields(Supplier> supplier) { + try { + java.lang.reflect.Method stf = httpResponse.getClass().getDeclaredMethod("setTrailerFields", Supplier.class); + stf.invoke(httpResponse, supplier); + } catch (IllegalAccessException | java.lang.reflect.InvocationTargetException | NoSuchMethodException + | SecurityException ex) { + throw new UnsupportedOperationException("no servlet 4.0 support on: " + httpResponse.getClass(), ex); + } + } + + @SuppressWarnings("unchecked") + public Supplier> getTrailerFields() { + try { + java.lang.reflect.Method stf = httpResponse.getClass().getDeclaredMethod("getTrailerFields"); + return (Supplier>) stf.invoke(httpResponse); + } catch (IllegalAccessException | java.lang.reflect.InvocationTargetException | NoSuchMethodException + | SecurityException ex) { + throw new UnsupportedOperationException("no servlet 4.0 support on: " + httpResponse.getClass(), ex); + } + } +} Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/WebdavResponseImpl.java ___________________________________________________________________ Added: svn Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/bind/BindConstants.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/bind/BindConstants.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/bind/BindConstants.java (working copy) @@ -0,0 +1,52 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.jackrabbit.webdav.bind; + +import org.apache.jackrabbit.webdav.xml.Namespace; +import org.apache.jackrabbit.webdav.DavConstants; +import org.apache.jackrabbit.webdav.property.DavPropertyName; + +/** + * BindConstants provide constants for request and response + * headers, Xml elements and property names defined by + * the BIND specification. + */ +public interface BindConstants { + + /** + * The namespace + */ + public static final Namespace NAMESPACE = DavConstants.NAMESPACE; + + /** + * local names of XML elements used in the request bodies of the methods BIND, REBIND and UNBIND. + */ + public static final String XML_BIND = "bind"; + public static final String XML_REBIND = "rebind"; + public static final String XML_UNBIND = "unbind"; + public static final String XML_SEGMENT = "segment"; + public static final String XML_HREF = "href"; + public static final String XML_PARENT = "parent"; + + public static final String METHODS = "BIND, REBIND, UNBIND"; + + /* + * Webdav properties defined by the BIND specification. + */ + public static final DavPropertyName RESOURCEID = DavPropertyName.create("resource-id"); + public static final DavPropertyName PARENTSET = DavPropertyName.create("parent-set"); +} Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/bind/BindConstants.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/bind/BindInfo.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/bind/BindInfo.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/bind/BindInfo.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.webdav.bind; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.apache.jackrabbit.webdav.DavServletResponse; +import org.apache.jackrabbit.webdav.DavException; +import org.apache.jackrabbit.webdav.xml.DomUtil; +import org.apache.jackrabbit.webdav.xml.ElementIterator; +import org.apache.jackrabbit.webdav.xml.XmlSerializable; +import org.w3c.dom.Element; +import org.w3c.dom.Document; + +public class BindInfo implements XmlSerializable { + + private static Logger log = LoggerFactory.getLogger(BindInfo.class); + + private String segment; + private String href; + + public BindInfo(String href, String segment) { + this.href = href; + this.segment = segment; + } + + public String getHref() { + return this.href; + } + + public String getSegment() { + return this.segment; + } + + /** + * Build an BindInfo object from the root element present + * in the request body. + * + * @param root the root element of the request body + * @return a BindInfo object containing segment and href + * @throws org.apache.jackrabbit.webdav.DavException if the BIND request is malformed + */ + public static BindInfo createFromXml(Element root) throws DavException { + if (!DomUtil.matches(root, BindConstants.XML_BIND, BindConstants.NAMESPACE)) { + log.warn("DAV:bind element expected"); + throw new DavException(DavServletResponse.SC_BAD_REQUEST); + } + String href = null; + String segment = null; + ElementIterator it = DomUtil.getChildren(root); + while (it.hasNext()) { + Element elt = it.nextElement(); + if (DomUtil.matches(elt, BindConstants.XML_SEGMENT, BindConstants.NAMESPACE)) { + if (segment == null) { + segment = DomUtil.getText(elt); + } else { + log.warn("unexpected multiple occurrence of DAV:segment element"); + throw new DavException(DavServletResponse.SC_BAD_REQUEST); + } + } else if (DomUtil.matches(elt, BindConstants.XML_HREF, BindConstants.NAMESPACE)) { + if (href == null) { + href = DomUtil.getText(elt); + } else { + log.warn("unexpected multiple occurrence of DAV:href element"); + throw new DavException(DavServletResponse.SC_BAD_REQUEST); + } + } else { + log.warn("unexpected element " + elt.getLocalName()); + throw new DavException(DavServletResponse.SC_BAD_REQUEST); + } + } + if (href == null) { + log.warn("DAV:href element expected"); + throw new DavException(DavServletResponse.SC_BAD_REQUEST); + } + if (segment == null) { + log.warn("DAV:segment element expected"); + throw new DavException(DavServletResponse.SC_BAD_REQUEST); + } + return new BindInfo(href, segment); + } + + /** + * @see org.apache.jackrabbit.webdav.xml.XmlSerializable#toXml(org.w3c.dom.Document) + */ + public Element toXml(Document document) { + Element bindElt = DomUtil.createElement(document, BindConstants.XML_BIND, BindConstants.NAMESPACE); + Element hrefElt = DomUtil.createElement(document, BindConstants.XML_HREF, BindConstants.NAMESPACE, this.href); + Element segElt = DomUtil.createElement(document, BindConstants.XML_SEGMENT, BindConstants.NAMESPACE, this.segment); + bindElt.appendChild(hrefElt); + bindElt.appendChild(segElt); + return bindElt; + } +} Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/bind/BindInfo.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/bind/BindServletRequest.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/bind/BindServletRequest.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/bind/BindServletRequest.java (working copy) @@ -0,0 +1,65 @@ +/* + * 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.webdav.bind; + +import org.apache.jackrabbit.webdav.DavException; +import org.apache.jackrabbit.webdav.DavResourceLocator; + +/** + * BindServletRequest provides extension useful for functionality + * related to BIND specification. + */ +public interface BindServletRequest { + + /** + * Returns the {@link RebindInfo} present with the request + * + * @return {@link RebindInfo} object + * @throws org.apache.jackrabbit.webdav.DavException in case of an invalid or missing request body + */ + public RebindInfo getRebindInfo() throws DavException; + + /** + * Returns the {@link UnbindInfo} present with the request + * + * @return {@link UnbindInfo} object + * @throws org.apache.jackrabbit.webdav.DavException in case of an invalid or missing request body + */ + public UnbindInfo getUnbindInfo() throws DavException; + + /** + * Returns the {@link BindInfo} present with the request + * + * @return {@link BindInfo} object + * @throws org.apache.jackrabbit.webdav.DavException in case of an invalid or missing request body + */ + public BindInfo getBindInfo() throws DavException; + + /** + * Parses a href and returns the path of the resource. + * + * @return path of the resource identified by the href. + */ + public DavResourceLocator getHrefLocator(String href) throws DavException; + + /** + * Returns the path of the member resource of the request resource which is identified by the segment parameter. + * + * @return path of internal member resource. + */ + public DavResourceLocator getMemberLocator(String segment); +} Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/bind/BindServletRequest.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/bind/BindableResource.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/bind/BindableResource.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/bind/BindableResource.java (working copy) @@ -0,0 +1,50 @@ +/* + * 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.webdav.bind; + +import java.util.Set; + +import org.apache.jackrabbit.webdav.DavException; +import org.apache.jackrabbit.webdav.DavResource; + +public interface BindableResource { + + /** + * Will add a new binding to the given collection referencing this resource. + * + * @param collection the collection to create the new binding in. + * @param newBinding the new binding + */ + public void bind(DavResource collection, DavResource newBinding) throws DavException; + + /** + * Will rebind the resource to the given collection. By definition, this is + * an atomic move operation. + * + * @param collection the collection to create the new binding in. + * @param newBinding the new binding + */ + public void rebind(DavResource collection, DavResource newBinding) throws DavException; + + /** + * Will retrieve a collection of parent elements of the bindable resource + * representing the parent set. + * + * @return newBinding the new binding + */ + public Set getParentElements(); +} Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/bind/BindableResource.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/bind/ParentElement.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/bind/ParentElement.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/bind/ParentElement.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.webdav.bind; + +import org.apache.jackrabbit.webdav.xml.XmlSerializable; +import org.apache.jackrabbit.webdav.xml.DomUtil; +import org.apache.jackrabbit.webdav.xml.ElementIterator; +import org.apache.jackrabbit.webdav.DavException; +import org.apache.jackrabbit.webdav.DavServletResponse; +import org.w3c.dom.Element; +import org.w3c.dom.Document; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * ParentElement wraps en element of the parent set of a resource. A java.util.Set of + * ParentElement objects may serve as the value object of the ParentSet DavProperty. + */ +public class ParentElement implements XmlSerializable { + + private static Logger log = LoggerFactory.getLogger(ParentElement.class); + + private final String href; + private final String segment; + + public ParentElement(String href, String segment) { + this.href = href; + this.segment = segment; + } + + public String getHref() { + return this.href; + } + + public String getSegment() { + return this.segment; + } + + /** + * Build an ParentElement object from an XML element DAV:parent + * + * @param root the DAV:parent element + * @return a ParentElement object + * @throws org.apache.jackrabbit.webdav.DavException if the DAV:parent element is malformed + */ + public static ParentElement createFromXml(Element root) throws DavException { + if (!DomUtil.matches(root, BindConstants.XML_PARENT, BindConstants.NAMESPACE)) { + log.warn("DAV:paret element expected"); + throw new DavException(DavServletResponse.SC_BAD_REQUEST); + } + String href = null; + String segment = null; + ElementIterator it = DomUtil.getChildren(root); + while (it.hasNext()) { + Element elt = it.nextElement(); + if (DomUtil.matches(elt, BindConstants.XML_SEGMENT, BindConstants.NAMESPACE)) { + if (segment == null) { + segment = DomUtil.getText(elt); + } else { + log.warn("unexpected multiple occurrence of DAV:segment element"); + throw new DavException(DavServletResponse.SC_BAD_REQUEST); + } + } else if (DomUtil.matches(elt, BindConstants.XML_HREF, BindConstants.NAMESPACE)) { + if (href == null) { + href = DomUtil.getText(elt); + } else { + log.warn("unexpected multiple occurrence of DAV:href element"); + throw new DavException(DavServletResponse.SC_BAD_REQUEST); + } + } else { + log.warn("unexpected element " + elt.getLocalName()); + throw new DavException(DavServletResponse.SC_BAD_REQUEST); + } + } + if (href == null) { + log.warn("DAV:href element expected"); + throw new DavException(DavServletResponse.SC_BAD_REQUEST); + } + if (segment == null) { + log.warn("DAV:segment element expected"); + throw new DavException(DavServletResponse.SC_BAD_REQUEST); + } + return new ParentElement(href, segment); + } + + /** + * @see org.apache.jackrabbit.webdav.xml.XmlSerializable#toXml(org.w3c.dom.Document) + */ + public Element toXml(Document document) { + Element parentElt = DomUtil.createElement(document, BindConstants.XML_PARENT, BindConstants.NAMESPACE); + Element hrefElt = DomUtil.createElement(document, BindConstants.XML_HREF, BindConstants.NAMESPACE, this.href); + Element segElt = DomUtil.createElement(document, BindConstants.XML_SEGMENT, BindConstants.NAMESPACE, this.segment); + parentElt.appendChild(hrefElt); + parentElt.appendChild(segElt); + return parentElt; + } +} Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/bind/ParentElement.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/bind/ParentSet.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/bind/ParentSet.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/bind/ParentSet.java (working copy) @@ -0,0 +1,45 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.jackrabbit.webdav.bind; + +import org.apache.jackrabbit.webdav.property.AbstractDavProperty; + +import java.util.Collection; + +/** + * ParentSet represents a DAV:parent-set property. + */ +public class ParentSet extends AbstractDavProperty> { + + private final Collection parents; + + /** + * Creates a new ParentSet from a collection of ParentElement objects. + * @param parents + */ + public ParentSet(Collection parents) { + super(BindConstants.PARENTSET, true); + this.parents = parents; + } + + /** + * @see org.apache.jackrabbit.webdav.property.AbstractDavProperty#getValue() + */ + public Collection getValue() { + return this.parents; + } +} Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/bind/ParentSet.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/bind/RebindInfo.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/bind/RebindInfo.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/bind/RebindInfo.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.webdav.bind; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.apache.jackrabbit.webdav.DavServletResponse; +import org.apache.jackrabbit.webdav.DavException; +import org.apache.jackrabbit.webdav.xml.DomUtil; +import org.apache.jackrabbit.webdav.xml.ElementIterator; +import org.apache.jackrabbit.webdav.xml.XmlSerializable; +import org.w3c.dom.Element; +import org.w3c.dom.Document; + +public class RebindInfo implements XmlSerializable { + + private static Logger log = LoggerFactory.getLogger(RebindInfo.class); + + private String segment; + private String href; + + public RebindInfo(String href, String segment) { + this.href = href; + this.segment = segment; + } + + public String getHref() { + return this.href; + } + + public String getSegment() { + return this.segment; + } + + /** + * Build an RebindInfo object from the root element present + * in the request body. + * + * @param root the root element of the request body + * @return a RebindInfo object containing segment and href + * @throws org.apache.jackrabbit.webdav.DavException if the REBIND request is malformed + */ + public static RebindInfo createFromXml(Element root) throws DavException { + if (!DomUtil.matches(root, BindConstants.XML_REBIND, BindConstants.NAMESPACE)) { + log.warn("DAV:rebind element expected"); + throw new DavException(DavServletResponse.SC_BAD_REQUEST); + } + String href = null; + String segment = null; + ElementIterator it = DomUtil.getChildren(root); + while (it.hasNext()) { + Element elt = it.nextElement(); + if (DomUtil.matches(elt, BindConstants.XML_SEGMENT, BindConstants.NAMESPACE)) { + if (segment == null) { + segment = DomUtil.getText(elt); + } else { + log.warn("unexpected multiple occurrence of DAV:segment element"); + throw new DavException(DavServletResponse.SC_BAD_REQUEST); + } + } else if (DomUtil.matches(elt, BindConstants.XML_HREF, BindConstants.NAMESPACE)) { + if (href == null) { + href = DomUtil.getText(elt); + } else { + log.warn("unexpected multiple occurrence of DAV:href element"); + throw new DavException(DavServletResponse.SC_BAD_REQUEST); + } + } else { + log.warn("unexpected element " + elt.getLocalName()); + throw new DavException(DavServletResponse.SC_BAD_REQUEST); + } + } + if (href == null) { + log.warn("DAV:href element expected"); + throw new DavException(DavServletResponse.SC_BAD_REQUEST); + } + if (segment == null) { + log.warn("DAV:segment element expected"); + throw new DavException(DavServletResponse.SC_BAD_REQUEST); + } + return new RebindInfo(href, segment); + } + + /** + * @see org.apache.jackrabbit.webdav.xml.XmlSerializable#toXml(org.w3c.dom.Document) + */ + public Element toXml(Document document) { + Element rebindElt = DomUtil.createElement(document, BindConstants.XML_REBIND, BindConstants.NAMESPACE); + Element hrefElt = DomUtil.createElement(document, BindConstants.XML_HREF, BindConstants.NAMESPACE, this.href); + Element segElt = DomUtil.createElement(document, BindConstants.XML_SEGMENT, BindConstants.NAMESPACE, this.segment); + rebindElt.appendChild(hrefElt); + rebindElt.appendChild(segElt); + return rebindElt; + } +} Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/bind/RebindInfo.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/bind/UnbindInfo.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/bind/UnbindInfo.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/bind/UnbindInfo.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.webdav.bind; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.apache.jackrabbit.webdav.DavServletResponse; +import org.apache.jackrabbit.webdav.DavException; +import org.apache.jackrabbit.webdav.xml.DomUtil; +import org.apache.jackrabbit.webdav.xml.ElementIterator; +import org.apache.jackrabbit.webdav.xml.XmlSerializable; +import org.w3c.dom.Element; +import org.w3c.dom.Document; + +public class UnbindInfo implements XmlSerializable { + + private static Logger log = LoggerFactory.getLogger(UnbindInfo.class); + + private String segment; + + private UnbindInfo() {} + + public UnbindInfo(String segment) { + this.segment = segment; + } + + public String getSegment() { + return this.segment; + } + + /** + * Build an UnbindInfo object from the root element present + * in the request body. + * + * @param root the root element of the request body + * @return a UnbindInfo object containing a segment identifier + * @throws org.apache.jackrabbit.webdav.DavException if the UNBIND request is malformed + */ + public static UnbindInfo createFromXml(Element root) throws DavException { + if (!DomUtil.matches(root, BindConstants.XML_UNBIND, BindConstants.NAMESPACE)) { + log.warn("DAV:unbind element expected"); + throw new DavException(DavServletResponse.SC_BAD_REQUEST); + } + String segment = null; + ElementIterator it = DomUtil.getChildren(root); + while (it.hasNext()) { + Element elt = it.nextElement(); + if (DomUtil.matches(elt, BindConstants.XML_SEGMENT, BindConstants.NAMESPACE)) { + if (segment == null) { + segment = DomUtil.getText(elt); + } else { + log.warn("unexpected multiple occurrence of DAV:segment element"); + throw new DavException(DavServletResponse.SC_BAD_REQUEST); + } + } else { + log.warn("unexpected element " + elt.getLocalName()); + throw new DavException(DavServletResponse.SC_BAD_REQUEST); + } + } + if (segment == null) { + log.warn("DAV:segment element expected"); + throw new DavException(DavServletResponse.SC_BAD_REQUEST); + } + return new UnbindInfo(segment); + } + + /** + * @see org.apache.jackrabbit.webdav.xml.XmlSerializable#toXml(org.w3c.dom.Document) + */ + public Element toXml(Document document) { + Element unbindElt = DomUtil.createElement(document, BindConstants.XML_UNBIND, BindConstants.NAMESPACE); + Element segElt = DomUtil.createElement(document, BindConstants.XML_SEGMENT, BindConstants.NAMESPACE, this.segment); + unbindElt.appendChild(segElt); + return unbindElt; + } +} Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/bind/UnbindInfo.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/bind/package-info.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/bind/package-info.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/bind/package-info.java (working copy) @@ -0,0 +1,18 @@ +/* + * 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. + */ +@org.osgi.annotation.versioning.Version("1.0.0") +package org.apache.jackrabbit.webdav.bind; Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/bind/package-info.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/BaseDavRequest.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/BaseDavRequest.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/BaseDavRequest.java (working copy) @@ -0,0 +1,219 @@ +/* + * 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.webdav.client.methods; + +import java.io.IOException; +import java.io.InputStream; +import java.net.URI; + +import javax.xml.parsers.ParserConfigurationException; + +import org.apache.http.HttpEntity; +import org.apache.http.HttpResponse; +import org.apache.http.StatusLine; +import org.apache.http.client.methods.HttpEntityEnclosingRequestBase; +import org.apache.jackrabbit.webdav.DavConstants; +import org.apache.jackrabbit.webdav.DavException; +import org.apache.jackrabbit.webdav.MultiStatus; +import org.apache.jackrabbit.webdav.lock.LockDiscovery; +import org.apache.jackrabbit.webdav.observation.EventDiscovery; +import org.apache.jackrabbit.webdav.observation.ObservationConstants; +import org.apache.jackrabbit.webdav.observation.Subscription; +import org.apache.jackrabbit.webdav.observation.SubscriptionDiscovery; +import org.apache.jackrabbit.webdav.xml.DomUtil; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.xml.sax.SAXException; + +/** + * Base class for HTTP request classes defined in this package. + */ +public abstract class BaseDavRequest extends HttpEntityEnclosingRequestBase { + + private static Logger log = LoggerFactory.getLogger(BaseDavRequest.class); + + public BaseDavRequest(URI uri) { + super(); + super.setURI(uri); + } + + /** + * Gets a {@link Document} representing the response body. + * @return document or {@code null} for null entity + * @throws IOException in case of I/O or XMP pasting problems + */ + public Document getResponseBodyAsDocument(HttpEntity entity) throws IOException { + + if (entity == null) { + return null; + } else { + // read response and try to build a xml document + InputStream in = entity.getContent(); + try { + return DomUtil.parseDocument(in); + } catch (ParserConfigurationException ex) { + throw new IOException("XML parser configuration error", ex); + } catch (SAXException ex) { + throw new IOException("XML parsing error", ex); + } finally { + in.close(); + } + } + } + + /** + * Return response body as {@link MultiStatus} object. + * @throws IllegalStateException when response does not represent a {@link MultiStatus} + * @throws DavException for failures in obtaining/parsing the response body + */ + public MultiStatus getResponseBodyAsMultiStatus(HttpResponse response) throws DavException { + try { + Document doc = getResponseBodyAsDocument(response.getEntity()); + if (doc == null) { + throw new DavException(response.getStatusLine().getStatusCode(), "no response body"); + } + return MultiStatus.createFromXml(doc.getDocumentElement()); + } catch (IOException ex) { + throw new DavException(response.getStatusLine().getStatusCode(), ex); + } + } + + /** + * Return response body as {@link LockDiscovery} object. + * @throws IllegalStateException when response does not represent a {@link LockDiscovery} + * @throws DavException for failures in obtaining/parsing the response body + */ + public LockDiscovery getResponseBodyAsLockDiscovery(HttpResponse response) throws DavException { + try { + Document doc = getResponseBodyAsDocument(response.getEntity()); + if (doc == null) { + throw new DavException(response.getStatusLine().getStatusCode(), "no response body"); + } + Element root = doc.getDocumentElement(); + + if (!DomUtil.matches(root, DavConstants.XML_PROP, DavConstants.NAMESPACE) + && DomUtil.hasChildElement(root, DavConstants.PROPERTY_LOCKDISCOVERY, DavConstants.NAMESPACE)) { + throw new DavException(response.getStatusLine().getStatusCode(), + "Missing DAV:prop response body in LOCK response."); + } + + Element lde = DomUtil.getChildElement(root, DavConstants.PROPERTY_LOCKDISCOVERY, DavConstants.NAMESPACE); + if (!DomUtil.hasChildElement(lde, DavConstants.XML_ACTIVELOCK, DavConstants.NAMESPACE)) { + throw new DavException(response.getStatusLine().getStatusCode(), + "The DAV:lockdiscovery must contain a least a single DAV:activelock in response to a successful LOCK request."); + } + + return LockDiscovery.createFromXml(lde); + } catch (IOException ex) { + throw new DavException(response.getStatusLine().getStatusCode(), ex); + } + } + + /** + * Return response body as {@link SubscriptionDiscovery} object. + * @throws IllegalStateException when response does not represent a {@link SubscriptionDiscovery} + * @throws DavException for failures in obtaining/parsing the response body + */ + public SubscriptionDiscovery getResponseBodyAsSubscriptionDiscovery(HttpResponse response) throws DavException { + try { + Document doc = getResponseBodyAsDocument(response.getEntity()); + if (doc == null) { + throw new DavException(response.getStatusLine().getStatusCode(), "no response body"); + } + Element root = doc.getDocumentElement(); + + if (!DomUtil.matches(root, DavConstants.XML_PROP, DavConstants.NAMESPACE) + && DomUtil.hasChildElement(root, ObservationConstants.SUBSCRIPTIONDISCOVERY.getName(), + ObservationConstants.SUBSCRIPTIONDISCOVERY.getNamespace())) { + throw new DavException(response.getStatusLine().getStatusCode(), + "Missing DAV:prop response body in SUBSCRIBE response."); + } + + Element sde = DomUtil.getChildElement(root, ObservationConstants.SUBSCRIPTIONDISCOVERY.getName(), + ObservationConstants.SUBSCRIPTIONDISCOVERY.getNamespace()); + SubscriptionDiscovery sd = SubscriptionDiscovery.createFromXml(sde); + if (((Subscription[]) sd.getValue()).length > 0) { + return sd; + } else { + throw new DavException(response.getStatusLine().getStatusCode(), + "Missing 'subscription' elements in SUBSCRIBE response body. At least a single subscription must be present if SUBSCRIBE was successful."); + } + } catch (IOException ex) { + throw new DavException(response.getStatusLine().getStatusCode(), ex); + } + } + + /** + * Return response body as {@link EventDiscovery} object. + * @throws IllegalStateException when response does not represent a {@link EventDiscovery} + * @throws DavException for failures in obtaining/parsing the response body + */ + public EventDiscovery getResponseBodyAsEventDiscovery(HttpResponse response) throws DavException { + try { + Document doc = getResponseBodyAsDocument(response.getEntity()); + if (doc == null) { + throw new DavException(response.getStatusLine().getStatusCode(), "no response body"); + } + return EventDiscovery.createFromXml(doc.getDocumentElement()); + } catch (IOException ex) { + throw new DavException(response.getStatusLine().getStatusCode(), ex); + } + } + + /** + * Check the response and throw when it is considered to represent a failure. + */ + public void checkSuccess(HttpResponse response) throws DavException { + if (!succeeded(response)) { + throw getResponseException(response); + } + } + + /** + * Obtain a {@link DavException} representing the response. + * @throws IllegalStateException when the response is considered to be successful + */ + public DavException getResponseException(HttpResponse response) { + if (succeeded(response)) { + String msg = "Cannot retrieve exception from successful response."; + log.warn(msg); + throw new IllegalStateException(msg); + } + + StatusLine st = response.getStatusLine(); + Element responseRoot = null; + try { + responseRoot = getResponseBodyAsDocument(response.getEntity()).getDocumentElement(); + } catch (IOException e) { + // non-parseable body -> use null element + } + + return new DavException(st.getStatusCode(), st.getReasonPhrase(), null, responseRoot); + } + + /** + * Check the provided {@link HttpResponse} for successful execution. The default implementation treats all + * 2xx status codes (RFC 7231, Section 6.3). + * Implementations can further restrict the accepted range of responses (or even check the response body). + */ + public boolean succeeded(HttpResponse response) { + int status = response.getStatusLine().getStatusCode(); + return status >= 200 && status <= 299; + } +} Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/BaseDavRequest.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpBind.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpBind.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpBind.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.webdav.client.methods; + +import java.io.IOException; +import java.net.URI; + +import org.apache.http.HttpResponse; +import org.apache.jackrabbit.webdav.DavMethods; +import org.apache.jackrabbit.webdav.DavServletResponse; +import org.apache.jackrabbit.webdav.bind.BindInfo; + +/** + * Represents an HTTP BIND request. + * + * @see RFC 5842, Section 4 + * @since 2.13.6 + */ +public class HttpBind extends BaseDavRequest { + + public HttpBind(URI uri, BindInfo info) throws IOException { + super(uri); + super.setEntity(XmlEntity.create(info)); + } + + public HttpBind(String uri, BindInfo info) throws IOException { + this(URI.create(uri), info); + } + + @Override + public String getMethod() { + return DavMethods.METHOD_BIND; + } + + @Override + public boolean succeeded(HttpResponse response) { + int statusCode = response.getStatusLine().getStatusCode(); + return statusCode == DavServletResponse.SC_OK || statusCode == DavServletResponse.SC_CREATED; + } +} \ No newline at end of file Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpBind.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpCheckin.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpCheckin.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpCheckin.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.webdav.client.methods; + +import java.net.URI; + +import org.apache.http.HttpResponse; +import org.apache.jackrabbit.webdav.DavMethods; +import org.apache.jackrabbit.webdav.DavServletResponse; + +/** + * Represents an HTTP CHECKIN request. + * + * @see RFC 3253, Section 4.4 + * @since 2.13.6 + */ +public class HttpCheckin extends BaseDavRequest { + + public HttpCheckin(URI uri) { + super(uri); + } + + public HttpCheckin(String uri) { + this(URI.create(uri)); + } + + @Override + public String getMethod() { + return DavMethods.METHOD_CHECKIN; + } + + @Override + public boolean succeeded(HttpResponse response) { + int statusCode = response.getStatusLine().getStatusCode(); + return statusCode == DavServletResponse.SC_CREATED; + } +} Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpCheckin.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpCheckout.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpCheckout.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpCheckout.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.webdav.client.methods; + +import java.net.URI; + +import org.apache.http.HttpResponse; +import org.apache.jackrabbit.webdav.DavMethods; +import org.apache.jackrabbit.webdav.DavServletResponse; + +/** + * Represents an HTTP CHECKOUT request. + * + * @see RFC 3253, Section 4.3 + * @since 2.13.6 + */ +public class HttpCheckout extends BaseDavRequest { + + public HttpCheckout(URI uri) { + super(uri); + } + + public HttpCheckout(String uri) { + this(URI.create(uri)); + } + + @Override + public String getMethod() { + return DavMethods.METHOD_CHECKOUT; + } + + @Override + public boolean succeeded(HttpResponse response) { + int statusCode = response.getStatusLine().getStatusCode(); + return statusCode == DavServletResponse.SC_OK; + } +} Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpCheckout.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpCopy.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpCopy.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpCopy.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.webdav.client.methods; + +import java.net.URI; + +import org.apache.http.HttpResponse; +import org.apache.jackrabbit.webdav.DavConstants; +import org.apache.jackrabbit.webdav.DavMethods; +import org.apache.jackrabbit.webdav.DavServletResponse; + +/** + * Represents an HTTP COPY request. + * + * @see RFC 4918, Section 9.8 + * @since 2.13.6 + */ +public class HttpCopy extends BaseDavRequest { + + public HttpCopy(URI uri, URI dest, boolean overwrite, boolean shallow) { + super(uri); + super.setHeader(DavConstants.HEADER_DESTINATION, dest.toASCIIString()); + if (!overwrite) { + super.setHeader(DavConstants.HEADER_OVERWRITE, "F"); + } + if (shallow) { + super.setHeader("Depth", "0"); + } + } + + public HttpCopy(String uri, String dest, boolean overwrite, boolean shallow) { + this(URI.create(uri), URI.create(dest), overwrite, shallow); + } + + @Override + public String getMethod() { + return DavMethods.METHOD_COPY; + } + + @Override + public boolean succeeded(HttpResponse response) { + int statusCode = response.getStatusLine().getStatusCode(); + return statusCode == DavServletResponse.SC_CREATED || statusCode == DavServletResponse.SC_NO_CONTENT; + } +} Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpCopy.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpDelete.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpDelete.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpDelete.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.webdav.client.methods; + +import java.net.URI; + +import org.apache.jackrabbit.webdav.DavMethods; + +/** + * Represents an HTTP DELETE request. + * + * @see RFC 7231, Section 4.3.5 + * @since 2.13.6 + */ +public class HttpDelete extends BaseDavRequest { + + public HttpDelete(URI uri){ + super(uri); + } + + public HttpDelete(String uri) { + this(URI.create(uri)); + } + + @Override + public String getMethod() { + return DavMethods.METHOD_DELETE; + } +} \ No newline at end of file Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpDelete.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpLabel.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpLabel.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpLabel.java (working copy) @@ -0,0 +1,57 @@ +/* + * 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.webdav.client.methods; + +import java.io.IOException; +import java.net.URI; + +import org.apache.http.HttpResponse; +import org.apache.jackrabbit.webdav.DavMethods; +import org.apache.jackrabbit.webdav.DavServletResponse; +import org.apache.jackrabbit.webdav.header.DepthHeader; +import org.apache.jackrabbit.webdav.version.LabelInfo; + +/** + * Represents an HTTP LABEL request. + * + * @see RFC 3253, Section 8.2 + * @since 2.13.6 + */ +public class HttpLabel extends BaseDavRequest { + + public HttpLabel(URI uri, LabelInfo labelInfo) throws IOException { + super(uri); + DepthHeader dh = new DepthHeader(labelInfo.getDepth()); + super.setHeader(dh.getHeaderName(), dh.getHeaderValue()); + super.setEntity(XmlEntity.create(labelInfo)); + } + + public HttpLabel(String uri, LabelInfo labelInfo) throws IOException { + this(URI.create(uri), labelInfo); + } + + @Override + public String getMethod() { + return DavMethods.METHOD_LABEL; + } + + @Override + public boolean succeeded(HttpResponse response) { + int statusCode = response.getStatusLine().getStatusCode(); + return statusCode == DavServletResponse.SC_OK; + } +} Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpLabel.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpLock.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpLock.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpLock.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.webdav.client.methods; + +import java.io.IOException; +import java.net.URI; +import java.util.Arrays; + +import org.apache.http.Header; +import org.apache.http.HttpResponse; +import org.apache.jackrabbit.webdav.DavConstants; +import org.apache.jackrabbit.webdav.DavMethods; +import org.apache.jackrabbit.webdav.DavServletResponse; +import org.apache.jackrabbit.webdav.header.DepthHeader; +import org.apache.jackrabbit.webdav.header.IfHeader; +import org.apache.jackrabbit.webdav.header.TimeoutHeader; +import org.apache.jackrabbit.webdav.lock.LockInfo; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Represents an HTTP LOCK request. + * + * @see RFC 4918, Section 9.10 + * @since 2.13.6 + */ +public class HttpLock extends BaseDavRequest { + + private static final Logger LOG = LoggerFactory.getLogger(HttpLock.class); + + private final boolean isRefresh; + + public HttpLock(URI uri, LockInfo lockInfo) throws IOException { + super(uri); + + TimeoutHeader th = new TimeoutHeader(lockInfo.getTimeout()); + super.setHeader(th.getHeaderName(), th.getHeaderValue()); + DepthHeader dh = new DepthHeader(lockInfo.isDeep()); + super.setHeader(dh.getHeaderName(), dh.getHeaderValue()); + + super.setEntity(XmlEntity.create(lockInfo)); + + isRefresh = false; + } + + public HttpLock(String uri, LockInfo lockInfo) throws IOException { + this(URI.create(uri), lockInfo); + } + + public HttpLock(URI uri, long timeout, String[] lockTokens) { + super(uri); + + TimeoutHeader th = new TimeoutHeader(timeout); + super.setHeader(th.getHeaderName(), th.getHeaderValue()); + IfHeader ifh = new IfHeader(lockTokens); + super.setHeader(ifh.getHeaderName(), ifh.getHeaderValue()); + isRefresh = true; + } + + public HttpLock(String uri, long timeout, String[] lockTokens) { + this(URI.create(uri), timeout, lockTokens); + } + + @Override + public String getMethod() { + return DavMethods.METHOD_LOCK; + } + + public String getLockToken(HttpResponse response) { + Header[] ltHeader = response.getHeaders(DavConstants.HEADER_LOCK_TOKEN); + if (ltHeader == null || ltHeader.length == 0) { + return null; + } else if (ltHeader.length != 1) { + LOG.debug("Multiple 'Lock-Token' header fields in response for " + getURI() + ": " + Arrays.asList(ltHeader)); + return null; + } else { + String v = ltHeader[0].getValue().trim(); + if (!v.startsWith("<") || !v.endsWith(">")) { + LOG.debug("Invalid 'Lock-Token' header field in response for " + getURI() + ": " + Arrays.asList(ltHeader)); + return null; + } else { + return v.substring(1, v.length() - 1); + } + } + } + + @Override + public boolean succeeded(HttpResponse response) { + int statusCode = response.getStatusLine().getStatusCode(); + boolean lockTokenHeaderOk = isRefresh || null != getLockToken(response); + return lockTokenHeaderOk && (statusCode == DavServletResponse.SC_OK || statusCode == DavServletResponse.SC_CREATED); + } +} \ No newline at end of file Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpLock.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpMerge.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpMerge.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpMerge.java (working copy) @@ -0,0 +1,55 @@ +/* + * 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.webdav.client.methods; + +import java.io.IOException; +import java.net.URI; + +import org.apache.http.HttpResponse; +import org.apache.jackrabbit.webdav.DavMethods; +import org.apache.jackrabbit.webdav.DavServletResponse; +import org.apache.jackrabbit.webdav.version.MergeInfo; + +/** + * Represents an HTTP MERGE request. + * + * @see RFC 3253, Section 11.2 + * @since 2.13.6 + */ +public class HttpMerge extends BaseDavRequest { + + public HttpMerge(URI uri, MergeInfo mergeInfo) throws IOException { + super(uri); + super.setEntity(XmlEntity.create(mergeInfo)); + } + + public HttpMerge(String uri, MergeInfo mergeInfo) throws IOException { + this(URI.create(uri), mergeInfo); + } + + @Override + public String getMethod() { + return DavMethods.METHOD_MERGE; + } + + @Override + public boolean succeeded(HttpResponse response) { + int statusCode = response.getStatusLine().getStatusCode(); + // TODO: is this correct? + return statusCode == DavServletResponse.SC_MULTI_STATUS; + } +} Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpMerge.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpMkcol.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpMkcol.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpMkcol.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.webdav.client.methods; + +import java.net.URI; + +import org.apache.http.HttpResponse; +import org.apache.jackrabbit.webdav.DavMethods; +import org.apache.jackrabbit.webdav.DavServletResponse; + +/** + * Represents an HTTP MKCOL request. + * + * @see RFC 4918, Section 9.3 + * @since 2.13.6 + */ +public class HttpMkcol extends BaseDavRequest { + + public HttpMkcol(URI uri) { + super(uri); + } + + public HttpMkcol(String uri) { + this(URI.create(uri)); + } + + @Override + public String getMethod() { + return DavMethods.METHOD_MKCOL; + } + + @Override + public boolean succeeded(HttpResponse response) { + int statusCode = response.getStatusLine().getStatusCode(); + return statusCode == DavServletResponse.SC_CREATED; + } +} Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpMkcol.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpMkworkspace.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpMkworkspace.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpMkworkspace.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.webdav.client.methods; + +import java.net.URI; + +import org.apache.http.HttpResponse; +import org.apache.jackrabbit.webdav.DavMethods; +import org.apache.jackrabbit.webdav.DavServletResponse; + +/** + * Represents an HTTP MKWORKSPACE request. + * + * @see RFC 3253, Section 6.3 + * @since 2.13.6 + */ +public class HttpMkworkspace extends BaseDavRequest { + + public HttpMkworkspace(URI uri) { + super(uri); + } + + public HttpMkworkspace(String uri) { + this(URI.create(uri)); + } + + @Override + public String getMethod() { + return DavMethods.METHOD_MKWORKSPACE; + } + + @Override + public boolean succeeded(HttpResponse response) { + int statusCode = response.getStatusLine().getStatusCode(); + return statusCode == DavServletResponse.SC_CREATED; + } +} Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpMkworkspace.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpMove.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpMove.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpMove.java (working copy) @@ -0,0 +1,56 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.jackrabbit.webdav.client.methods; + +import java.net.URI; + +import org.apache.http.HttpResponse; +import org.apache.jackrabbit.webdav.DavConstants; +import org.apache.jackrabbit.webdav.DavMethods; +import org.apache.jackrabbit.webdav.DavServletResponse; + +/** + * Represents an HTTP MOVE request. + * + * @see RFC 4918, Section 9.9 + * @since 2.13.6 + */ +public class HttpMove extends BaseDavRequest { + + public HttpMove(URI uri, URI dest, boolean overwrite) { + super(uri); + super.setHeader(DavConstants.HEADER_DESTINATION, dest.toASCIIString()); + if (!overwrite) { + super.setHeader(DavConstants.HEADER_OVERWRITE, "F"); + } + } + + public HttpMove(String uri, String dest, boolean overwrite) { + this(URI.create(uri), URI.create(dest), overwrite); + } + + @Override + public String getMethod() { + return DavMethods.METHOD_MOVE; + } + + @Override + public boolean succeeded(HttpResponse response) { + int statusCode = response.getStatusLine().getStatusCode(); + return statusCode == DavServletResponse.SC_CREATED || statusCode == DavServletResponse.SC_NO_CONTENT; + } +} Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpMove.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpOptions.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpOptions.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpOptions.java (working copy) @@ -0,0 +1,79 @@ +/* + * 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.webdav.client.methods; + +import java.net.URI; +import java.util.Collections; +import java.util.HashSet; +import java.util.Set; + +import org.apache.http.Header; +import org.apache.http.HttpResponse; +import org.apache.jackrabbit.webdav.DavConstants; +import org.apache.jackrabbit.webdav.header.FieldValueParser; +import org.apache.jackrabbit.webdav.search.SearchConstants; + +/** + * Represents an HTTP OPTIONS request. + * + * @see RFC 7231, Section 4.3.7 + * @since 2.13.6 + */ +public class HttpOptions extends org.apache.http.client.methods.HttpOptions { + + public HttpOptions(URI uri) { + super(uri); + } + + public HttpOptions(String uri) { + super(URI.create(uri)); + } + + /** + * Compute the set of compliance classes returned in the "dav" header field + */ + public Set getDavComplianceClasses(HttpResponse response) { + Header[] headers = response.getHeaders(DavConstants.HEADER_DAV); + return parseTokenOrCodedUrlheaderField(headers, false); + } + + /** + * Compute set of search grammars returned in the "dasl" header field + */ + public Set getSearchGrammars(HttpResponse response) { + Header[] headers = response.getHeaders(SearchConstants.HEADER_DASL); + return parseTokenOrCodedUrlheaderField(headers, true); + } + + private Set parseTokenOrCodedUrlheaderField(Header[] headers, boolean removeBrackets) { + if (headers == null) { + return Collections.emptySet(); + } + else { + Set result = new HashSet(); + for (Header h : headers) { + for (String s : FieldValueParser.tokenizeList(h.getValue())) { + if (removeBrackets && s.startsWith("<") && s.endsWith(">")) { + s = s.substring(1, s.length() - 1); + } + result.add(s.trim()); + } + } + return Collections.unmodifiableSet(result); + } + } +} Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpOptions.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpOrderpatch.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpOrderpatch.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpOrderpatch.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.webdav.client.methods; + +import java.io.IOException; +import java.net.URI; + +import org.apache.http.HttpResponse; +import org.apache.jackrabbit.webdav.DavMethods; +import org.apache.jackrabbit.webdav.DavServletResponse; +import org.apache.jackrabbit.webdav.ordering.OrderPatch; + +/** + * Represents an HTTP ORDERPATCH request. + * + * @see RFC 3648, Section 5 + * @since 2.13.6 + */ +public class HttpOrderpatch extends BaseDavRequest { + + public HttpOrderpatch(URI uri, OrderPatch info) throws IOException { + super(uri); + super.setEntity(XmlEntity.create(info)); + } + + public HttpOrderpatch(String uri, OrderPatch info) throws IOException { + this(URI.create(uri), info); + } + + @Override + public String getMethod() { + return DavMethods.METHOD_ORDERPATCH; + } + + @Override + public boolean succeeded(HttpResponse response) { + return response.getStatusLine().getStatusCode() == DavServletResponse.SC_OK; + } +} \ No newline at end of file Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpOrderpatch.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpPoll.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpPoll.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpPoll.java (working copy) @@ -0,0 +1,58 @@ +/* + * 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.webdav.client.methods; + +import java.net.URI; + +import org.apache.http.HttpResponse; +import org.apache.jackrabbit.webdav.DavMethods; +import org.apache.jackrabbit.webdav.DavServletResponse; +import org.apache.jackrabbit.webdav.header.PollTimeoutHeader; +import org.apache.jackrabbit.webdav.observation.ObservationConstants; + +/** + * Represents an HTTP POLL request. + *

+ * Note that "POLL" is a custom HTTP extension, not defined in a standards paper. + * @since 2.13.6 + */ +public class HttpPoll extends BaseDavRequest { + + public HttpPoll(URI uri, String subscriptionId, long timeout) { + super(uri); + super.setHeader(ObservationConstants.HEADER_SUBSCRIPTIONID, subscriptionId); + if (timeout > 0) { + PollTimeoutHeader th = new PollTimeoutHeader(timeout); + super.setHeader(th.getHeaderName(), th.getHeaderValue()); + } + } + + public HttpPoll(String uri, String subscriptionId, long timeout) { + this(URI.create(uri), subscriptionId, timeout); + } + + @Override + public String getMethod() { + return DavMethods.METHOD_POLL; + } + + @Override + public boolean succeeded(HttpResponse response) { + int statusCode = response.getStatusLine().getStatusCode(); + return statusCode == DavServletResponse.SC_OK; + } +} \ No newline at end of file Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpPoll.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpPropfind.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpPropfind.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpPropfind.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.webdav.client.methods; + +import java.io.IOException; +import java.net.URI; + +import org.apache.http.HttpResponse; +import org.apache.jackrabbit.webdav.DavConstants; +import org.apache.jackrabbit.webdav.DavMethods; +import org.apache.jackrabbit.webdav.DavServletResponse; +import org.apache.jackrabbit.webdav.header.DepthHeader; +import org.apache.jackrabbit.webdav.property.DavPropertyNameSet; +import org.apache.jackrabbit.webdav.property.PropfindInfo; + +/** + * Represents an HTTP PROPFIND request. + * + * @see RFC 4918, Section 9.1 + * @since 2.13.6 + */ +public class HttpPropfind extends BaseDavRequest { + + public HttpPropfind(URI uri, int propfindType, DavPropertyNameSet names, int depth) throws IOException { + super(uri); + + DepthHeader dh = new DepthHeader(depth); + super.setHeader(dh.getHeaderName(), dh.getHeaderValue()); + + PropfindInfo info = new PropfindInfo(propfindType, names); + super.setEntity(XmlEntity.create(info)); + } + + public HttpPropfind(URI uri, DavPropertyNameSet names, int depth) throws IOException { + this(uri, DavConstants.PROPFIND_BY_PROPERTY, names, depth); + } + + public HttpPropfind(URI uri, int propfindType, int depth) throws IOException { + this(uri, propfindType, new DavPropertyNameSet(), depth); + } + + public HttpPropfind(String uri, int propfindType, int depth) throws IOException { + this(URI.create(uri), propfindType, depth); + } + + public HttpPropfind(String uri, int propfindType, DavPropertyNameSet names, int depth) throws IOException { + this(URI.create(uri), propfindType, names, depth); + } + + public HttpPropfind(String uri, DavPropertyNameSet names, int depth) throws IOException { + this(URI.create(uri), names, depth); + } + + @Override + public String getMethod() { + return DavMethods.METHOD_PROPFIND; + } + + @Override + public boolean succeeded(HttpResponse response) { + return response.getStatusLine().getStatusCode() == DavServletResponse.SC_MULTI_STATUS; + } +} \ No newline at end of file Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpPropfind.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpProppatch.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpProppatch.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpProppatch.java (working copy) @@ -0,0 +1,104 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.jackrabbit.webdav.client.methods; + +import java.io.IOException; +import java.net.URI; +import java.util.List; + +import org.apache.http.HttpResponse; +import org.apache.jackrabbit.webdav.DavMethods; +import org.apache.jackrabbit.webdav.DavServletResponse; +import org.apache.jackrabbit.webdav.property.DavPropertyNameSet; +import org.apache.jackrabbit.webdav.property.DavPropertySet; +import org.apache.jackrabbit.webdav.property.PropEntry; +import org.apache.jackrabbit.webdav.property.ProppatchInfo; + +/** + * Represents an HTTP PROPPATCH request. + * + * @see RFC 4918, Section 9.2 + * @since 2.13.6 + */ +public class HttpProppatch extends BaseDavRequest { + + // private DavPropertyNameSet propertyNames; + + public HttpProppatch(URI uri, ProppatchInfo info) throws IOException { + super(uri); + super.setEntity(XmlEntity.create(info)); + // this.propertyNames = info.getAffectedProperties(); + } + + public HttpProppatch(URI uri, List changeList) throws IOException { + this(uri, new ProppatchInfo(changeList)); + } + + public HttpProppatch(URI uri, DavPropertySet setProperties, DavPropertyNameSet removeProperties) throws IOException { + this(uri, new ProppatchInfo(setProperties, removeProperties)); + } + + public HttpProppatch(String uri, List changeList) throws IOException { + this(URI.create(uri), new ProppatchInfo(changeList)); + } + + public HttpProppatch(String uri, DavPropertySet setProperties, DavPropertyNameSet removeProperties) throws IOException { + this(URI.create(uri), new ProppatchInfo(setProperties, removeProperties)); + } + + @Override + public String getMethod() { + return DavMethods.METHOD_PROPPATCH; + } + + @Override + public boolean succeeded(HttpResponse response) { + return response.getStatusLine().getStatusCode() == DavServletResponse.SC_MULTI_STATUS; + + // disabled code that fails for current PROPPATCH behavior of Jackrabbit +// MultiStatusResponse responses[] = super.getResponseBodyAsMultiStatus(response).getResponses(); +// if (responses.length != 1) { +// throw new DavException(DavServletResponse.SC_MULTI_STATUS, +// "PROPPATCH failed: Expected exactly one multistatus response element, but got " + responses.length); +// } +// DavPropertyNameSet okSet = responses[0].getPropertyNames(DavServletResponse.SC_OK); +// if (okSet.isEmpty()) { +// throw new DavException(DavServletResponse.SC_MULTI_STATUS, +// "PROPPATCH failed: No 'OK' response found for resource " + responses[0].getHref()); +// } else { +// DavPropertyNameIterator it = propertyNames.iterator(); +// while (it.hasNext()) { +// DavPropertyName pn = it.nextPropertyName(); +// boolean success = okSet.remove(pn); +// if (!success) { +// throw new DavException(DavServletResponse.SC_MULTI_STATUS, +// "PROPPATCH failed: Property name not present in multistatus response: " + pn); +// } +// } +// } +// if (!okSet.isEmpty()) { +// StringBuilder b = new StringBuilder(); +// DavPropertyNameIterator it = okSet.iterator(); +// while (it.hasNext()) { +// b.append(it.nextPropertyName().toString()).append("; "); +// } +// throw new DavException(DavServletResponse.SC_MULTI_STATUS, +// "PROPPATCH failed: The following properties outside of the original request where set or removed: " + b.toString()); +// } +// return true; + } +} \ No newline at end of file Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpProppatch.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpRebind.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpRebind.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpRebind.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.webdav.client.methods; + +import java.io.IOException; +import java.net.URI; + +import org.apache.http.HttpResponse; +import org.apache.jackrabbit.webdav.DavMethods; +import org.apache.jackrabbit.webdav.DavServletResponse; +import org.apache.jackrabbit.webdav.bind.RebindInfo; + +/** + * Represents an HTTP REBIND request. + * + * @see RFC 5842, Section 6 + * @since 2.13.6 + */ +public class HttpRebind extends BaseDavRequest { + + public HttpRebind(URI uri, RebindInfo info) throws IOException { + super(uri); + super.setEntity(XmlEntity.create(info)); + } + + public HttpRebind(String uri, RebindInfo info) throws IOException { + this(URI.create(uri), info); + } + + @Override + public String getMethod() { + return DavMethods.METHOD_REBIND; + } + + @Override + public boolean succeeded(HttpResponse response) { + int statusCode = response.getStatusLine().getStatusCode(); + return statusCode == DavServletResponse.SC_OK || statusCode == DavServletResponse.SC_CREATED; + } +} \ No newline at end of file Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpRebind.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpReport.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpReport.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpReport.java (working copy) @@ -0,0 +1,66 @@ +/* + * 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.webdav.client.methods; + +import java.io.IOException; +import java.net.URI; + +import org.apache.http.HttpResponse; +import org.apache.jackrabbit.webdav.DavConstants; +import org.apache.jackrabbit.webdav.DavMethods; +import org.apache.jackrabbit.webdav.DavServletResponse; +import org.apache.jackrabbit.webdav.header.DepthHeader; +import org.apache.jackrabbit.webdav.version.report.ReportInfo; + +/** + * Represents an HTTP REPORT request. + * + * @see RFC 3253, Section 3.6 + * @since 2.13.6 + */ +public class HttpReport extends BaseDavRequest { + + private final boolean isDeep; + + public HttpReport(URI uri, ReportInfo reportInfo) throws IOException { + super(uri); + DepthHeader dh = new DepthHeader(reportInfo.getDepth()); + isDeep = reportInfo.getDepth() > DavConstants.DEPTH_0; + super.setHeader(dh.getHeaderName(), dh.getHeaderValue()); + super.setEntity(XmlEntity.create(reportInfo)); + } + + public HttpReport(String uri, ReportInfo reportInfo) throws IOException { + this(URI.create(uri), reportInfo); + } + + @Override + public String getMethod() { + return DavMethods.METHOD_REPORT; + } + + @Override + public boolean succeeded(HttpResponse response) { + int statusCode = response.getStatusLine().getStatusCode(); + if (isDeep) { + return statusCode == DavServletResponse.SC_MULTI_STATUS; + } else { + return statusCode == DavServletResponse.SC_OK || statusCode == DavServletResponse.SC_MULTI_STATUS; + } + + } +} \ No newline at end of file Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpReport.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpSearch.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpSearch.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpSearch.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.webdav.client.methods; + +import java.io.IOException; +import java.net.URI; + +import org.apache.http.HttpResponse; +import org.apache.jackrabbit.webdav.DavMethods; +import org.apache.jackrabbit.webdav.DavServletResponse; +import org.apache.jackrabbit.webdav.search.SearchInfo; + +/** + * Represents an HTTP SEARCH request. + * + * @see RFC 5323, Section 2 + * @since 2.13.6 + */ +public class HttpSearch extends BaseDavRequest { + + public HttpSearch(URI uri, SearchInfo searchInfo) throws IOException { + super(uri); + super.setEntity(XmlEntity.create(searchInfo)); + } + + public HttpSearch(String uri, SearchInfo searchInfo) throws IOException { + this(URI.create(uri), searchInfo); + } + + @Override + public String getMethod() { + return DavMethods.METHOD_SEARCH; + } + + @Override + public boolean succeeded(HttpResponse response) { + int statusCode = response.getStatusLine().getStatusCode(); + return statusCode == DavServletResponse.SC_MULTI_STATUS; + } +} \ No newline at end of file Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpSearch.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpSubscribe.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpSubscribe.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpSubscribe.java (working copy) @@ -0,0 +1,88 @@ +/* + * 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.webdav.client.methods; + +import java.io.IOException; +import java.net.URI; + +import org.apache.http.HttpResponse; +import org.apache.jackrabbit.webdav.DavConstants; +import org.apache.jackrabbit.webdav.DavMethods; +import org.apache.jackrabbit.webdav.DavServletResponse; +import org.apache.jackrabbit.webdav.header.CodedUrlHeader; +import org.apache.jackrabbit.webdav.header.DepthHeader; +import org.apache.jackrabbit.webdav.header.TimeoutHeader; +import org.apache.jackrabbit.webdav.observation.ObservationConstants; +import org.apache.jackrabbit.webdav.observation.SubscriptionInfo; + +/** + * Represents an HTTP SUBSCRIBE request. + *

+ * Note that "SUBSCRIBE" is a custom HTTP extension, not defined in a standards paper. + * @since 2.13.6 + */ +public class HttpSubscribe extends BaseDavRequest { + + public HttpSubscribe(URI uri, SubscriptionInfo info, String subscriptionId) throws IOException { + super(uri); + if (info == null) { + throw new IllegalArgumentException("SubscriptionInfo must not be null."); + } + // optional subscriptionId (only required to modify an existing + // subscription) + if (subscriptionId != null) { + CodedUrlHeader h = new CodedUrlHeader(ObservationConstants.HEADER_SUBSCRIPTIONID, subscriptionId); + super.setHeader(h.getHeaderName(), h.getHeaderValue()); + } + // optional timeout header + long to = info.getTimeOut(); + if (to != DavConstants.UNDEFINED_TIMEOUT) { + TimeoutHeader h = new TimeoutHeader(info.getTimeOut()); + super.setHeader(h.getHeaderName(), h.getHeaderValue()); + } + // always set depth header since value is boolean flag + DepthHeader dh = new DepthHeader(info.isDeep()); + super.setHeader(dh.getHeaderName(), dh.getHeaderValue()); + super.setEntity(XmlEntity.create(info)); + } + + public HttpSubscribe(String uri, SubscriptionInfo info, String subscriptionId) throws IOException { + this(URI.create(uri), info, subscriptionId); + } + + public String getSubscriptionId(HttpResponse response) { + org.apache.http.Header sbHeader = response.getFirstHeader(ObservationConstants.HEADER_SUBSCRIPTIONID); + if (sbHeader != null) { + CodedUrlHeader cuh = new CodedUrlHeader(ObservationConstants.HEADER_SUBSCRIPTIONID, sbHeader.getValue()); + return cuh.getCodedUrl(); + } + else { + return null; + } + } + + @Override + public String getMethod() { + return DavMethods.METHOD_SUBSCRIBE; + } + + @Override + public boolean succeeded(HttpResponse response) { + int statusCode = response.getStatusLine().getStatusCode(); + return statusCode == DavServletResponse.SC_OK; + } +} \ No newline at end of file Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpSubscribe.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpUnbind.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpUnbind.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpUnbind.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.webdav.client.methods; + +import java.io.IOException; +import java.net.URI; + +import org.apache.http.HttpResponse; +import org.apache.jackrabbit.webdav.DavMethods; +import org.apache.jackrabbit.webdav.DavServletResponse; +import org.apache.jackrabbit.webdav.bind.UnbindInfo; + +/** + * Represents an HTTP UNBIND request. + * + * @see RFC 5842, Section 5 + * @since 2.13.6 + */ +public class HttpUnbind extends BaseDavRequest { + + public HttpUnbind(URI uri, UnbindInfo info) throws IOException { + super(uri); + super.setEntity(XmlEntity.create(info)); + } + + public HttpUnbind(String uri, UnbindInfo info) throws IOException { + this(URI.create(uri), info); + } + + @Override + public String getMethod() { + return DavMethods.METHOD_UNBIND; + } + + @Override + public boolean succeeded(HttpResponse response) { + int statusCode = response.getStatusLine().getStatusCode(); + return statusCode == DavServletResponse.SC_OK || statusCode == DavServletResponse.SC_NO_CONTENT; + } +} \ No newline at end of file Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpUnbind.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpUnlock.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpUnlock.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpUnlock.java (working copy) @@ -0,0 +1,55 @@ +/* + * 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.webdav.client.methods; + +import java.net.URI; + +import org.apache.http.HttpResponse; +import org.apache.jackrabbit.webdav.DavConstants; +import org.apache.jackrabbit.webdav.DavMethods; +import org.apache.jackrabbit.webdav.DavServletResponse; +import org.apache.jackrabbit.webdav.header.CodedUrlHeader; + +/** + * Represents an HTTP UNLOCK request. + * + * @see RFC 4918, Section 9.11 + * @since 2.13.6 + */ +public class HttpUnlock extends BaseDavRequest { + + public HttpUnlock(URI uri, String lockToken) { + super(uri); + CodedUrlHeader lth = new CodedUrlHeader(DavConstants.HEADER_LOCK_TOKEN, lockToken); + super.setHeader(lth.getHeaderName(), lth.getHeaderValue()); + } + + public HttpUnlock(String uri, String lockToken) { + this(URI.create(uri), lockToken); + } + + @Override + public String getMethod() { + return DavMethods.METHOD_UNLOCK; + } + + @Override + public boolean succeeded(HttpResponse response) { + int statusCode = response.getStatusLine().getStatusCode(); + return statusCode == DavServletResponse.SC_OK || statusCode == DavServletResponse.SC_NO_CONTENT; + } +} \ No newline at end of file Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpUnlock.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpUnsubscribe.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpUnsubscribe.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpUnsubscribe.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.webdav.client.methods; + +import java.net.URI; + +import org.apache.http.HttpResponse; +import org.apache.jackrabbit.webdav.DavMethods; +import org.apache.jackrabbit.webdav.DavServletResponse; +import org.apache.jackrabbit.webdav.observation.ObservationConstants; + +/** + * Represents an HTTP UNSUBSCRIBE request. + *

+ * Note that "UNSUBSCRIBE" is a custom HTTP extension, not defined in a standards paper. + * @since 2.13.6 + */ +public class HttpUnsubscribe extends BaseDavRequest { + + public HttpUnsubscribe(URI uri, String subscriptionId) { + super(uri); + super.setHeader(ObservationConstants.HEADER_SUBSCRIPTIONID, subscriptionId); + } + + public HttpUnsubscribe(String uri, String subscriptionId) { + this(URI.create(uri), subscriptionId); + } + + @Override + public String getMethod() { + return DavMethods.METHOD_UNSUBSCRIBE; + } + + @Override + public boolean succeeded(HttpResponse response) { + int statusCode = response.getStatusLine().getStatusCode(); + return statusCode == DavServletResponse.SC_NO_CONTENT; + } +} \ No newline at end of file Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpUnsubscribe.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpUpdate.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpUpdate.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpUpdate.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.webdav.client.methods; + +import java.io.IOException; +import java.net.URI; + +import org.apache.http.HttpResponse; +import org.apache.jackrabbit.webdav.DavMethods; +import org.apache.jackrabbit.webdav.DavServletResponse; +import org.apache.jackrabbit.webdav.version.UpdateInfo; + +/** + * Represents an HTTP UPDATE request. + * + * @see RFC 3253, Section 7.1 + * @since 2.13.6 + */ +public class HttpUpdate extends BaseDavRequest { + + public HttpUpdate(URI uri, UpdateInfo updateInfo) throws IOException { + super(uri); + super.setEntity(XmlEntity.create(updateInfo)); + } + + public HttpUpdate(String uri, UpdateInfo updateInfo) throws IOException { + this(URI.create(uri), updateInfo); + } + + @Override + public String getMethod() { + return DavMethods.METHOD_UPDATE; + } + + @Override + public boolean succeeded(HttpResponse response) { + int statusCode = response.getStatusLine().getStatusCode(); + return statusCode == DavServletResponse.SC_MULTI_STATUS; + } +} Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpUpdate.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpVersionControl.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpVersionControl.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpVersionControl.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.webdav.client.methods; + +import java.net.URI; + +import org.apache.http.HttpResponse; +import org.apache.jackrabbit.webdav.DavMethods; +import org.apache.jackrabbit.webdav.DavServletResponse; + +/** + * Represents an HTTP VERSION-CONTROL request. + * + * @see RFC 3253, Section 3.5 + * @since 2.13.6 + */ +public class HttpVersionControl extends BaseDavRequest { + + public HttpVersionControl(URI uri) { + super(uri); + } + + public HttpVersionControl(String uri) { + this(URI.create(uri)); + } + + @Override + public String getMethod() { + return DavMethods.METHOD_VERSION_CONTROL; + } + + @Override + public boolean succeeded(HttpResponse response) { + int statusCode = response.getStatusLine().getStatusCode(); + return statusCode == DavServletResponse.SC_OK; + } +} Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpVersionControl.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/XmlEntity.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/XmlEntity.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/XmlEntity.java (working copy) @@ -0,0 +1,68 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.jackrabbit.webdav.client.methods; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; + +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.transform.TransformerException; + +import org.apache.http.HttpEntity; +import org.apache.http.entity.ByteArrayEntity; +import org.apache.http.entity.ContentType; +import org.apache.jackrabbit.webdav.xml.DomUtil; +import org.apache.jackrabbit.webdav.xml.XmlSerializable; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.w3c.dom.Document; +import org.xml.sax.SAXException; + +/** + * Utility methods for creating request entities from {@link Document}s or {@link XmlSerializable}s. + */ +public class XmlEntity { + + private static Logger LOG = LoggerFactory.getLogger(XmlEntity.class); + + private static ContentType CT = ContentType.create("application/xml", "UTF-8"); + + public static HttpEntity create(Document doc) throws IOException { + try { + ByteArrayOutputStream xml = new ByteArrayOutputStream(); + DomUtil.transformDocument(doc, xml); + return new ByteArrayEntity(xml.toByteArray(), CT); + } catch (TransformerException ex) { + LOG.error(ex.getMessage()); + throw new IOException(ex); + } catch (SAXException ex) { + LOG.error(ex.getMessage()); + throw new IOException(ex); + } + } + + public static HttpEntity create(XmlSerializable payload) throws IOException { + try { + Document doc = DomUtil.createDocument(); + doc.appendChild(payload.toXml(doc)); + return create(doc); + } catch (ParserConfigurationException ex) { + LOG.error(ex.getMessage()); + throw new IOException(ex); + } + } +} Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/XmlEntity.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/package-info.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/package-info.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/package-info.java (working copy) @@ -0,0 +1,31 @@ +/* + * 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. + */ + +/** + * Provides classes for use with the Apache HttpClient, supporting WebDAV + * request methods. + *

+ * This version also contains classes for use with the obsolete "Commons + * HttpClient"; they have been marked "deprecated" and will be removed in the + * next major release. + * + * @see JCR-2406 + * @see https://hc.apache.org/httpcomponents-client-4.5.x/ + */ +@org.osgi.annotation.versioning.Version("2.0.0") +package org.apache.jackrabbit.webdav.client.methods; Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/package-info.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/header/CodedUrlHeader.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/header/CodedUrlHeader.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/header/CodedUrlHeader.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.webdav.header; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.servlet.http.HttpServletRequest; + +/** + * CodedUrlHeader... + */ +public class CodedUrlHeader implements Header { + + private static Logger log = LoggerFactory.getLogger(CodedUrlHeader.class); + + private final String headerName; + private final String headerValue; + + public CodedUrlHeader(String headerName, String headerValue) { + this.headerName = headerName; + if (headerValue != null && !(headerValue.startsWith("<") && headerValue.endsWith(">"))) { + headerValue = "<" + headerValue + ">"; + } + this.headerValue = headerValue; + } + + /** + * Return the name of the header + * + * @return header name + * @see Header#getHeaderName() + */ + public String getHeaderName() { + return headerName; + } + + /** + * Return the value of the header + * + * @return value + * @see Header#getHeaderValue() + */ + public String getHeaderValue() { + return headerValue; + } + + /** + * Returns the token present in the header value or null. + * If the header contained multiple tokens separated by ',' the first value + * is returned. + * + * @return token present in the CodedURL header or null if + * the header is not present. + * @see #getCodedUrls() + */ + public String getCodedUrl() { + String[] codedUrls = getCodedUrls(); + return (codedUrls != null) ? codedUrls[0] : null; + } + + /** + * Return an array of coded urls as present in the header value or null if + * no value is present. + * + * @return array of coded urls + */ + public String[] getCodedUrls() { + String[] codedUrls = null; + if (headerValue != null) { + String[] values = headerValue.split(","); + codedUrls = new String[values.length]; + for (int i = 0; i < values.length; i++) { + int p1 = values[i].indexOf('<'); + if (p1<0) { + throw new IllegalArgumentException("Invalid CodedURL header value:" + values[i]); + } + int p2 = values[i].indexOf('>', p1); + if (p2<0) { + throw new IllegalArgumentException("Invalid CodedURL header value:" + values[i]); + } + codedUrls[i] = values[i].substring(p1+1, p2); + } + } + return codedUrls; + } + + /** + * Retrieves the header with the given name and builds a new CodedUrlHeader. + * + * @param request + * @param headerName + * @return new CodedUrlHeader instance + */ + public static CodedUrlHeader parse(HttpServletRequest request, String headerName) { + String headerValue = request.getHeader(headerName); + return new CodedUrlHeader(headerName, headerValue); + } +} \ No newline at end of file Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/header/CodedUrlHeader.java ___________________________________________________________________ Added: svn Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/header/DepthHeader.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/header/DepthHeader.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/header/DepthHeader.java (working copy) @@ -0,0 +1,128 @@ +/* + * 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.webdav.header; + +import org.apache.jackrabbit.webdav.DavConstants; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.servlet.http.HttpServletRequest; + +/** + * DepthHeader... + */ +public class DepthHeader implements Header, DavConstants { + + private static Logger log = LoggerFactory.getLogger(DepthHeader.class); + + private final int depth; + + /** + * Create a new DepthHeader from the given integer. + * + * @param depth + */ + public DepthHeader(int depth) { + if (depth == DEPTH_0 || depth == DEPTH_1 || depth == DEPTH_INFINITY) { + this.depth = depth; + } else { + throw new IllegalArgumentException("Invalid depth: " + depth); + } + } + + /** + * Create a new DepthHeader with either value {@link #DEPTH_0 0} + * or {@link #DEPTH_INFINITY infinity}. + * + * @param isDeep + */ + public DepthHeader(boolean isDeep) { + this.depth = (isDeep) ? DEPTH_INFINITY : DEPTH_0; + } + + /** + * @return integer representation of the depth indicated by the given header. + */ + public int getDepth() { + return depth; + } + + /** + * Return {@link DavConstants#HEADER_DEPTH Depth} + * + * @return {@link DavConstants#HEADER_DEPTH Depth} + * @see DavConstants#HEADER_DEPTH + * @see Header#getHeaderName() + */ + public String getHeaderName() { + return DavConstants.HEADER_DEPTH; + } + + /** + * Returns the header value. + * + * @return header value + * @see Header#getHeaderValue() + */ + public String getHeaderValue() { + if (depth == DavConstants.DEPTH_0 || depth == DavConstants.DEPTH_1) { + return String.valueOf(depth); + } else { + return DavConstants.DEPTH_INFINITY_S; + } + } + + /** + * Retrieve the Depth header from the given request object and parse the + * value. If no header is present or the value is empty String, the + * defaultValue is used ot build a new DepthHeader instance. + * + * @param request + * @param defaultValue + * @return a new DepthHeader instance + */ + public static DepthHeader parse(HttpServletRequest request, int defaultValue) { + String headerValue = request.getHeader(HEADER_DEPTH); + if (headerValue == null || "".equals(headerValue)) { + return new DepthHeader(defaultValue); + } else { + return new DepthHeader(depthToInt(headerValue)); + } + } + + /** + * Convert the String depth value to an integer. + * + * @param depth + * @return integer representation of the given depth String + * @throws IllegalArgumentException if the String does not represent a valid + * depth. + */ + private static int depthToInt(String depth) { + int d; + if (depth.equalsIgnoreCase(DavConstants.DEPTH_INFINITY_S)) { + d = DavConstants.DEPTH_INFINITY; + } else if (depth.equals(DavConstants.DEPTH_0+"")) { + d = DavConstants.DEPTH_0; + } else if (depth.equals(DavConstants.DEPTH_1+"")) { + d = DavConstants.DEPTH_1; + } else { + throw new IllegalArgumentException("Invalid depth value: " + depth); + } + return d; + } +} \ No newline at end of file Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/header/DepthHeader.java ___________________________________________________________________ Added: svn Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/header/FieldValueParser.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/header/FieldValueParser.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/header/FieldValueParser.java (working copy) @@ -0,0 +1,55 @@ +/* + * 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.webdav.header; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +public class FieldValueParser { + + /** + * Tokenize lists of token and quoted-url + * @param list field value + */ + public static List tokenizeList(String list) { + + String[] split = list.split(","); + if (split.length == 1) { + return Collections.singletonList(split[0].trim()); + } else { + List result = new ArrayList(); + String inCodedUrl = null; + for (String t : split) { + String trimmed = t.trim(); + // handle quoted-url containing "," + if (trimmed.startsWith("<") && !trimmed.endsWith(">")) { + inCodedUrl = trimmed + ","; + } else if (inCodedUrl != null && trimmed.endsWith(">")) { + inCodedUrl += trimmed; + result.add(inCodedUrl); + inCodedUrl = null; + } else { + if (trimmed.length() != 0) { + result.add(trimmed); + } + } + } + return Collections.unmodifiableList(result); + } + } +} Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/header/FieldValueParser.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/header/Header.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/header/Header.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/header/Header.java (working copy) @@ -0,0 +1,27 @@ +/* + * 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.webdav.header; + +/** + * Header... + */ +public interface Header { + + public String getHeaderName(); + + public String getHeaderValue(); +} \ No newline at end of file Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/header/Header.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-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/header/IfHeader.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/header/IfHeader.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/header/IfHeader.java (working copy) @@ -0,0 +1,888 @@ +/* + * 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.webdav.header; + +import org.apache.jackrabbit.webdav.DavConstants; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.servlet.http.HttpServletRequest; +import java.io.IOException; +import java.io.Reader; +import java.io.StringReader; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; + +/** + * The IfHeader class represents the state lists defined + * through the HTTP If header, which is specified in RFC 2518 as + * follows : + *

+     If = "If" ":" ( 1*No-tag-list | 1*Tagged-list)
+     No-tag-list = List
+     Tagged-list = Resource 1*List
+     Resource = Coded-URL
+     List = "(" 1*(["Not"](State-etag | "[" entity-tag "]")) ")"
+     State-etag = Coded-URL
+     Coded-URL = "<" absoluteURI ">"
+ * 
+ *

+ * Reformulating this specification into proper EBNF as specified by N. Wirth + * we get the following productions, which map to the parse METHODS of this + * class. Any whitespace is ignored except for white space surrounding and + * within words which is considered significant. + *

+     If = "If:" ( Tagged | Untagged ).
+     Tagged = { "<" Word ">" Untagged } .
+     Untagged = { "(" IfList ")" } .
+     IfList = { [ "Not" ] ( ("<" Word ">" ) | ( "[" Word "]" ) ) } .
+     Word = characters .
+ * 
+ *

+ * An If header either contains untagged IfList entries or + * tagged IfList entries but not a mixture of both. An If + * header containing tagged entries is said to be of tagged type while + * an If header containing untagged entries is said to be of + * untagged type. + *

+ * An IfList is a list of tokens - words enclosed in < > + * - and etags - words enclosed in [ ]. An IfList matches a + * (token, etag) tuple if all entries in the list match. If an entry in the list + * is prefixed with the word Not (parsed case insensitively) the entry + * must not match the concrete token or etag. + *

+ * Example: The ifList (<token> [etag]) only matches + * if the concret token has the value token and the conrete etag + * has the value etag. On the other hand, the ifList + * (Not <notoken>) matches any token which is not + * notoken (in this case the concrete value of the etag is + * not taken into consideration). + * + * @author Felix Meschberger + */ +public class IfHeader implements Header { + + /** + * default logger + */ + private static final Logger log = LoggerFactory.getLogger(IfHeader.class); + + /** + * The string representation of the header value + */ + private final String headerValue; + + /** + * The list of untagged state entries + */ + private final IfHeaderInterface ifHeader; + + /** + * The list of all positive tokens present in the If header. + */ + private List allTokens = new ArrayList(); + /** + * The list of all NOT tokens present in the If header. + */ + private List allNotTokens = new ArrayList(); + + /** + * Create a Untagged IfHeader if the given lock tokens. + * + * @param tokens + */ + public IfHeader(String[] tokens) { + allTokens.addAll(Arrays.asList(tokens)); + StringBuffer b = new StringBuffer(); + for (String token : tokens) { + b.append("(").append("<"); + b.append(token); + b.append(">").append(")"); + } + headerValue = b.toString(); + ifHeader = parse(); + } + + /** + * Parses the If header and creates and internal representation + * which is easy to query. + * + * @param req The request object + */ + public IfHeader(HttpServletRequest req) { + headerValue = req.getHeader(DavConstants.HEADER_IF); + ifHeader = parse(); + } + + /** + * Return {@link DavConstants#HEADER_IF If} + * + * @return {@link DavConstants#HEADER_IF If} + * @see DavConstants#HEADER_IF + */ + public String getHeaderName() { + return DavConstants.HEADER_IF; + } + + /** + * Return the String representation of the If header present on + * the given request or null. + * + * @return If header value as String or null. + */ + public String getHeaderValue() { + return headerValue; + } + + /** + * Returns true if an If header was present in the given request. False otherwise. + * + * @return true if an If header was present. + */ + public boolean hasValue() { + return ifHeader != null; + } + + /** + * Tries to match the contents of the If header with the given + * token and etag values with the restriction to only check for the tag. + *

+ * If the If header is of untagged type, the untagged IfList + * is matched against the token and etag given: A match of the token and + * etag is found if at least one of the IfList entries match the + * token and etag tuple. + * + * @param tag The tag to identify the IfList to match the token + * and etag against. + * @param token The token to compare. + * @param etag The ETag value to compare. + * + * @return If the If header is of untagged type the result is + * true if any of the IfList entries matches + * the token and etag values. For tagged type If header the + * result is true if either no entry for the given tag + * exists in the If header or if the IfList for the + * given tag matches the token and etag given. + */ + public boolean matches(String tag, String token, String etag) { + if (ifHeader == null) { + log.debug("matches: No If header, assume match"); + return true; + } else { + return ifHeader.matches(tag, token, etag); + } + } + + /** + * @return an iterator over all tokens present in the if header, that were + * not denied by a leading NOT statement. + */ + public Iterator getAllTokens() { + return allTokens.iterator(); + } + + /** + * @return an iterator over all NOT tokens present in the if header, that + * were explicitly denied. + */ + public Iterator getAllNotTokens() { + return allNotTokens.iterator(); + } + + /** + * Parse the original header value and build the internal IfHeaderInterface + * object that is easy to query. + */ + private IfHeaderInterface parse() { + IfHeaderInterface ifHeader; + if (headerValue != null && headerValue.length() > 0) { + StringReader reader = null; + int firstChar = 0; + + try { + reader = new StringReader(headerValue); + // get the first character to decide - expect '(' or '<' + try { + reader.mark(1); + firstChar = readWhiteSpace(reader); + reader.reset(); + } catch (IOException ignore) { + // may be thrown according to API but is only thrown by the + // StringReader class if the reader is already closed. + } + + if (firstChar == '(') { + ifHeader = parseUntagged(reader); + } else if (firstChar == '<') { + ifHeader = parseTagged(reader); + } else { + logIllegalState("If", firstChar, "(<", null); + ifHeader = null; + } + + } finally { + if (reader != null) { + reader.close(); + } + } + + } else { + log.debug("IfHeader: No If header in request"); + ifHeader = null; + } + return ifHeader; + } + + //---------- internal IF header parser ------------------------------------- + /** + * Parses a tagged type If header. This method implements the + * Tagged production given in the class comment : + *

+         Tagged = { "<" Word ">" Untagged } .
+     * 
+ * + * @param reader + * @return + */ + private IfHeaderMap parseTagged(StringReader reader) { + IfHeaderMap map = new IfHeaderMap(); + try { + while (true) { + // read next non-white space + int c = readWhiteSpace(reader); + if (c < 0) { + // end of input, no more entries + break; + } else if (c == '<') { + // start a tag with an IfList + String resource = readWord(reader, '>'); + if (resource != null) { + // go to untagged after reading the resource + map.put(resource, parseUntagged(reader)); + } else { + break; + } + } else { + // unexpected character + // catchup to end of input or start of a tag + logIllegalState("Tagged", c, "<", reader); + } + } + } catch (IOException ioe) { + log.error("parseTagged: Problem parsing If header: "+ioe.toString()); + } + + return map; + } + + /** + * Parses an untagged type If header. This method implements the + * Untagged production given in the class comment : + *
+         Untagged = { "(" IfList ")" } .
+     * 
+ * + * @param reader The StringReader to read from for parsing + * + * @return An ArrayList of {@link IfList} entries. + */ + private IfHeaderList parseUntagged(StringReader reader) { + IfHeaderList list = new IfHeaderList(); + try { + while (true) { + // read next non white space + reader.mark(1); + int c = readWhiteSpace(reader); + if (c < 0) { + // end of input, no more IfLists + break; + + } else if (c == '(') { + // start of an IfList, parse + list.add(parseIfList(reader)); + + } else if (c == '<') { + // start of a tag, return current list + reader.reset(); + break; + + } else { + // unexpected character + // catchup to end of input or start of an IfList + logIllegalState("Untagged", c, "(", reader); + } + } + } catch (IOException ioe) { + log.error("parseUntagged: Problem parsing If header: "+ioe.toString()); + } + return list; + } + + /** + * Parses an IfList in the If header. This method + * implements the Tagged production given in the class comment : + *
+         IfList = { [ "Not" ] ( ("<" Word ">" ) | ( "[" Word "]" ) ) } .
+     * 
+ * + * @param reader The StringReader to read from for parsing + * + * @return The {@link IfList} for the input IfList. + * + * @throws IOException if a problem occurs during reading. + */ + private IfList parseIfList(StringReader reader) throws IOException { + IfList res = new IfList(); + boolean positive = true; + String word; + + ReadLoop: + while (true) { + int nextChar = readWhiteSpace(reader); + switch (nextChar) { + case 'N': + case 'n': + // read not + + // check whether o or O + int not = reader.read(); + if (not != 'o' && not != 'O') { + logIllegalState("IfList-Not", not, "o", null); + break; + } + + // check whether t or T + not = reader.read(); + if (not !='t' && not != 'T') { + logIllegalState("IfList-Not", not, "t", null); + break; + } + + // read Not ok + positive = false; + break; + + case '<': + // state token + word = readWord(reader, '>'); + if (word != null) { + res.add(new IfListEntryToken(word, positive)); + // also add the token to the list of all tokens + if (positive) { + allTokens.add(word); + } else { + allNotTokens.add(word); + } + positive = true; + } + break; + + case '[': + // etag + word = readWord(reader, ']'); + if (word != null) { + res.add(new IfListEntryEtag(word, positive)); + positive = true; + } + break; + + case ')': + // correct end of list, end the loop + log.debug("parseIfList: End of If list, terminating loop"); + break ReadLoop; + + default: + logIllegalState("IfList", nextChar, "nN<[)", reader); + + // abort loop if EOF + if (nextChar < 0) { + break ReadLoop; + } + + break; + } + } + + // return the current list anyway + return res; + } + + /** + * Returns the first non-whitespace character from the reader or -1 if + * the end of the reader is encountered. + * + * @param reader The Reader to read from + * + * @return The first non-whitespace character or -1 in case of EOF. + * + * @throws IOException if a problem occurs during reading. + */ + private int readWhiteSpace(Reader reader) throws IOException { + int c = reader.read(); + while (c >= 0 && Character.isWhitespace((char) c)) { + c = reader.read(); + } + return c; + } + + /** + * Reads from the input until the end character is encountered and returns + * the string up to but not including this end character. If the end of input + * is reached before reading the end character null is + * returned. + *

+ * Note that this method does not support any escaping. + * + * @param reader The Reader to read from + * @param end The ending character limiting the word. + * + * @return The string read up to but not including the ending character or + * null if the end of input is reached before the ending + * character has been read. + * + * @throws IOException if a problem occurs during reading. + */ + private String readWord(Reader reader, char end) throws IOException { + StringBuffer buf = new StringBuffer(); + + // read the word value + int c = reader.read(); + for (; c >= 0 && c != end; c=reader.read()) { + buf.append((char) c); + } + + // check whether we succeeded + if (c < 0) { + log.error("readWord: Unexpected end of input reading word"); + return null; + } + + // build the string and return it + return buf.toString(); + } + + /** + * Logs an unexpected character with the corresponding state and list of + * expected characters. If the reader parameter is not null, characters + * are read until either the end of the input is reached or any of the + * characters in the expChar string is read. + * + * @param state The name of the current parse state. This method logs this + * name in the message. The intended value would probably be the + * name of the EBNF production during which the error occurs. + * @param effChar The effective character read. + * @param expChar The list of characters acceptable in the current state. + * @param reader The reader to be caught up to any of the expected + * characters. If null the input is not caught up to + * any of the expected characters (of course ;-). + */ + private void logIllegalState(String state, int effChar, String expChar, + StringReader reader) { + + // format the effective character to be logged + String effString = (effChar < 0) ? "" : String.valueOf((char) effChar); + + // log the error + log.error("logIllegalState: Unexpected character '"+effString+"' in state "+state+", expected any of "+expChar); + + // catch up if a reader is given + if (reader != null && effChar >= 0) { + try { + log.debug("logIllegalState: Catch up to any of "+expChar); + do { + reader.mark(1); + effChar = reader.read(); + } while (effChar >= 0 && expChar.indexOf(effChar) < 0); + if (effChar >= 0) { + reader.reset(); + } + } catch (IOException ioe) { + log.error("logIllegalState: IO Problem catching up to any of "+expChar); + } + } + } + + //---------- internal If header structure ---------------------------------- + + /** + * The IfListEntry abstract class is the base class for + * entries in an IfList production. This abstract base class + * provides common functionality to both types of entries, namely tokens + * enclosed in angle brackets (< >) and etags enclosed + * in square brackets ([ ]). + */ + private static abstract class IfListEntry { + + /** + * The entry string value - the semantics of this value depends on the + * implementing class. + */ + protected final String value; + + /** Flag to indicate, whether this is a positive match or not */ + protected final boolean positive; + + /** The cached result of the {@link #toString} method. */ + protected String stringValue; + + /** + * Sets up the final fields of this abstract class. The meaning of + * value parameter depends solely on the implementing class. From the + * point of view of this abstract class, it is simply a string value. + * + * @param value The string value of this instance + * @param positive true if matches are positive + */ + protected IfListEntry(String value, boolean positive) { + this.value = value; + this.positive = positive; + } + + /** + * Matches the value from the parameter to the internal string value. + * If the parameter and the {@link #value} field match, the method + * returns true for positive matches and false + * for negative matches. + *

+ * This helper method can be called by implementations to evaluate the + * concrete match on the correct value parameter. See + * {@link #match(String, String)} for the external API method. + * + * @param value The string value to compare to the {@link #value} + * field. + * + * @return true if the value parameter and the + * {@link #value} field match and the {@link #positive} field is + * true or if the values do not match and the + * {@link #positive} field is false. + */ + protected boolean match(String value) { + return positive == this.value.equals(value); + } + + /** + * Matches the entry's value to the the token or etag. Depending on the + * concrete implementation, only one of the parameters may be evaluated + * while the other may be ignored. + *

+ * Implementing METHODS may call the helper method {@link #match(String)} + * for the actual matching. + * + * @param token The token value to compare + * @param etag The etag value to compare + * + * @return true if the token/etag matches the IfList + * entry. + */ + public abstract boolean match(String token, String etag); + + /** + * Returns a short type name for the implementation. This method is + * used by the {@link #toString} method to build the string representation + * if the instance. + * + * @return The type name of the implementation. + */ + protected abstract String getType(); + + /** + * Returns the value of this entry. + * + * @return the value + */ + protected String getValue() { + return value; + } + + /** + * Returns the String representation of this entry. This method uses the + * {@link #getType} to build the string representation. + * + * @return the String representation of this entry. + */ + @Override + public String toString() { + if (stringValue == null) { + stringValue = getType() + ": " + (positive?"":"!") + value; + } + return stringValue; + } + } + + /** + * The IfListEntryToken extends the {@link IfListEntry} + * abstract class to represent an entry for token matching. + */ + private static class IfListEntryToken extends IfListEntry { + + /** + * Creates a token matching entry. + * + * @param token The token value pertinent to this instance. + * @param positive true if this is a positive match entry. + */ + IfListEntryToken(String token, boolean positive) { + super(token, positive); + } + + /** + * Matches the token parameter to the stored token value and returns + * true if the values match and if the match is positive. + * true is also returned for negative matches if the values + * do not match. + * + * @param token The token value to compare + * @param etag The etag value to compare, which is ignored in this + * implementation. + * + * @return true if the token matches the IfList + * entry's token value. + */ + @Override + public boolean match(String token, String etag) { + return super.match(token); + } + + /** + * Returns the type name of this implementation, which is fixed to + * be Token. + * + * @return The fixed string Token as the type name. + */ + @Override + protected String getType() { + return "Token"; + } + } + + /** + * The IfListEntryToken extends the {@link IfListEntry} + * abstract class to represent an entry for etag matching. + */ + private static class IfListEntryEtag extends IfListEntry { + + /** + * Creates an etag matching entry. + * + * @param etag The etag value pertinent to this instance. + * @param positive true if this is a positive match entry. + */ + IfListEntryEtag(String etag, boolean positive) { + super(etag, positive); + } + + /** + * Matches the etag parameter to the stored etag value and returns + * true if the values match and if the match is positive. + * true is also returned for negative matches if the values + * do not match. + * + * @param token The token value to compare, which is ignored in this + * implementation. + * @param etag The etag value to compare + * + * @return true if the etag matches the IfList + * entry's etag value. + */ + @Override + public boolean match(String token, String etag) { + return super.match(etag); + } + + /** + * Returns the type name of this implementation, which is fixed to + * be ETag. + * + * @return The fixed string ETag as the type name. + */ + @Override + protected String getType() { + return "ETag"; + } + } + + /** + * The IfList class extends the ArrayList class + * with the limitation to only support adding {@link IfListEntry} objects + * and adding a {@link #match} method. + *

+ * This class is a container for data contained in the If + * production IfList + *

+         IfList = { [ "Not" ] ( ("<" Word ">" ) | ( "[" Word "]" ) ) } .
+     * 
+ *

+ */ + private static class IfList extends ArrayList { + + /** + * Adds the {@link IfListEntry} at the end of the list. + * + * @param entry The {@link IfListEntry} to add to the list + * + * @return true (as per the general contract of Collection.add). + */ + @Override + public boolean add(IfListEntry entry) { + return super.add(entry); + } + + /** + * Adds the {@link IfListEntry} at the indicated position of the list. + * + * @param index + * @param entry + * + * @throws IndexOutOfBoundsException if index is out of range + * (index < 0 || index > size()). + */ + @Override + public void add(int index, IfListEntry entry) { + super.add(index, entry); + } + + /** + * Returns true if all {@link IfListEntry} objects in the + * list match the given token and etag. If the list is entry, it is + * considered to match the token and etag. + * + * @param token The token to compare. + * @param etag The etag to compare. + * + * @return true if all entries in the list match the + * given tag and token. + */ + public boolean match(String token, String etag) { + log.debug("match: Trying to match token="+token+", etag="+etag); + for (int i=0; i < size(); i++) { + IfListEntry ile = get(i); + if (!ile.match(token, etag)) { + log.debug("match: Entry "+i+"-"+ile+" does not match"); + return false; + } + } + // invariant: all entries matched + + return true; + } + } + + /** + * The IfHeaderInterface interface abstracts away the difference of + * tagged and untagged If header lists. The single method provided + * by this interface is to check whether a request may be applied to a + * resource with given token and etag. + */ + private static interface IfHeaderInterface { + + /** + * Matches the resource, token, and etag against this + * IfHeaderInterface instance. + * + * @param resource The resource to match this instance against. This + * must be absolute URI of the resource as defined in Section 3 + * (URI Syntactic Components) of RFC 2396 Uniform Resource + * Identifiers (URI): Generic Syntax. + * @param token The resource's lock token to match + * @param etag The resource's etag to match + * + * @return true if the header matches the resource with + * token and etag, which means that the request is applicable + * to the resource according to the If header. + */ + public boolean matches(String resource, String token, String etag); + } + + /** + * The IfHeaderList class implements the {@link IfHeaderInterface} + * interface to support untagged lists of {@link IfList}s. This class + * implements the data container for the production : + *

+         Untagged = { "(" IfList ")" } .
+     * 
+ */ + private static class IfHeaderList extends ArrayList implements IfHeaderInterface { + + /** + * Matches a list of {@link IfList}s against the token and etag. If any of + * the {@link IfList}s matches, the method returns true. + * On the other hand false is only returned if non of the + * {@link IfList}s match. + * + * @param resource The resource to match, which is ignored by this + * implementation. A value of null is therefor + * acceptable. + * @param token The token to compare. + * @param etag The ETag value to compare. + * + * @return True if any of the {@link IfList}s matches the token + * and etag, else false is returned. + */ + public boolean matches(String resource, String token, String etag) { + log.debug("matches: Trying to match token="+token+", etag="+etag); + + for (IfList il : this) { + if (il.match(token, etag)) { + log.debug("matches: Found match with " + il); + return true; + } + } + // invariant: no match found + + return false; + } + } + + /** + * The IfHeaderMap class implements the {@link IfHeaderInterface} + * interface to support tagged lists of {@link IfList}s. This class + * implements the data container for the production : + *
+         Tagged = { "<" Word ">" "(" IfList ")" } .
+     * 
+ */ + private static class IfHeaderMap extends HashMap implements IfHeaderInterface { + + /** + * Matches the token and etag for the given resource. If the resource is + * not mentioned in the header, a match is assumed and true + * is returned in this case. + * + * @param resource The absolute URI of the resource for which to find + * a match. + * @param token The token to compare. + * @param etag The etag to compare. + * + * @return true if either no entry exists for the resource + * or if the entry for the resource matches the token and etag. + */ + public boolean matches(String resource, String token, String etag) { + log.debug("matches: Trying to match resource="+resource+", token="+token+","+etag); + + IfHeaderList list = get(resource); + if (list == null) { + log.debug("matches: No entry for tag "+resource+", assuming match"); + return true; + } else { + return list.matches(resource, token, etag); + } + } + } +} Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/header/IfHeader.java ___________________________________________________________________ Added: svn Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/header/LabelHeader.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/header/LabelHeader.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/header/LabelHeader.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.webdav.header; + +import org.apache.jackrabbit.webdav.WebdavRequest; +import org.apache.jackrabbit.webdav.util.EncodeUtil; +import org.apache.jackrabbit.webdav.version.DeltaVConstants; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * LabelHeader... + */ +public class LabelHeader implements Header { + + private static Logger log = LoggerFactory.getLogger(LabelHeader.class); + + private final String label; + + public LabelHeader(String label) { + if (label == null) { + throw new IllegalArgumentException("null is not a valid label."); + } + this.label = label; + } + + public String getLabel() { + return label; + } + + public String getHeaderName() { + return DeltaVConstants.HEADER_LABEL; + } + + public String getHeaderValue() { + return EncodeUtil.escape(label); + } + + public static LabelHeader parse(WebdavRequest request) { + String hv = request.getHeader(DeltaVConstants.HEADER_LABEL); + if (hv == null) { + return null; + } else { + return new LabelHeader(EncodeUtil.unescape(hv)); + } + } +} \ No newline at end of file Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/header/LabelHeader.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-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/header/OverwriteHeader.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/header/OverwriteHeader.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/header/OverwriteHeader.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.webdav.header; + +import org.apache.jackrabbit.webdav.DavConstants; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.servlet.http.HttpServletRequest; + +/** + * OverwriteHeader... + */ +public class OverwriteHeader implements Header { + + private static Logger log = LoggerFactory.getLogger(OverwriteHeader.class); + + public static final String OVERWRITE_TRUE = "T"; + public static final String OVERWRITE_FALSE = "F"; + + /** + * Set 'doOverwrite' to true by default. See RFC 2518: + * "If the overwrite header is not included in a COPY or MOVE request then + * the resource MUST treat the request as if it has an overwrite header of + * value {@link #OVERWRITE_TRUE}". + */ + private final boolean doOverwrite; + + public OverwriteHeader(boolean doOverwrite) { + this.doOverwrite = doOverwrite; + } + + /** + * Create a new OverwriteHeader for the given request object. + * If the latter does not contain an "Overwrite" header field, the default + * applies, which is {@link #OVERWRITE_TRUE} according to RFC 2518. + * + * @param request + */ + public OverwriteHeader(HttpServletRequest request) { + String overwriteHeader = request.getHeader(DavConstants.HEADER_OVERWRITE); + if (overwriteHeader != null) { + doOverwrite = overwriteHeader.equalsIgnoreCase(OVERWRITE_TRUE); + } else { + // no Overwrite header -> default is 'true' + doOverwrite = true; + } + } + + public String getHeaderName() { + return DavConstants.HEADER_OVERWRITE; + } + + public String getHeaderValue() { + return (doOverwrite) ? OVERWRITE_TRUE : OVERWRITE_FALSE; + } + + public boolean isOverwrite() { + return doOverwrite; + } +} \ No newline at end of file Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/header/OverwriteHeader.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-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/header/PollTimeoutHeader.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/header/PollTimeoutHeader.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/header/PollTimeoutHeader.java (working copy) @@ -0,0 +1,52 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.jackrabbit.webdav.header; + +import org.apache.jackrabbit.webdav.observation.ObservationConstants; + +import javax.servlet.http.HttpServletRequest; + +/** + * PollTimeoutHeader implements a timeout header for subscription + * polling. + */ +public class PollTimeoutHeader extends TimeoutHeader { + + public PollTimeoutHeader(long timeout) { + super(timeout); + } + + @Override + public String getHeaderName() { + return ObservationConstants.HEADER_POLL_TIMEOUT; + } + + /** + * Parses the request timeout header and converts it into a new + * PollTimeoutHeader object.
The default value is used as + * fallback if the String is not parseable. + * + * @param request + * @param defaultValue + * @return a new PollTimeoutHeader object. + */ + public static PollTimeoutHeader parseHeader(HttpServletRequest request, long defaultValue) { + String timeoutStr = request.getHeader(ObservationConstants.HEADER_POLL_TIMEOUT); + long timeout = parse(timeoutStr, defaultValue); + return new PollTimeoutHeader(timeout); + } +} Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/header/PollTimeoutHeader.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/header/TimeoutHeader.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/header/TimeoutHeader.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/header/TimeoutHeader.java (working copy) @@ -0,0 +1,104 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.jackrabbit.webdav.header; + +import org.apache.jackrabbit.webdav.DavConstants; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.servlet.http.HttpServletRequest; + +/** + * TimeoutHeader... + */ +public class TimeoutHeader implements Header, DavConstants { + + private static Logger log = LoggerFactory.getLogger(TimeoutHeader.class); + + private final long timeout; + + public TimeoutHeader(long timeout) { + this.timeout = timeout; + } + + public String getHeaderName() { + return DavConstants.HEADER_TIMEOUT; + } + + public String getHeaderValue() { + if (timeout == INFINITE_TIMEOUT) { + return TIMEOUT_INFINITE; + } else { + return "Second-" + (timeout / 1000); + } + } + + public long getTimeout() { + return timeout; + } + + /** + * Parses the request timeout header and converts it into a new + * TimeoutHeader object.
The default value is used as + * fallback if the String is not parseable. + * + * @param request + * @param defaultValue + * @return a new TimeoutHeader object. + */ + public static TimeoutHeader parse(HttpServletRequest request, long defaultValue) { + String timeoutStr = request.getHeader(HEADER_TIMEOUT); + long timeout = parse(timeoutStr, defaultValue); + return new TimeoutHeader(timeout); + } + + /** + * Parses the given timeout String and converts the timeout value + * into a long indicating the number of milliseconds until expiration time + * is reached.
+ * NOTE: If the timeout String equals to {@link #TIMEOUT_INFINITE 'infinite'} + * {@link Integer#MAX_VALUE} is returned. If the Sting is invalid or is in an + * invalid format that cannot be parsed, the default value is returned. + * + * @param timeoutStr + * @param defaultValue + * @return long representing the timeout present in the header or the default + * value if the header is missing or could not be parsed. + */ + public static long parse(String timeoutStr, long defaultValue) { + long timeout = defaultValue; + if (timeoutStr != null && timeoutStr.length() > 0) { + int secondsInd = timeoutStr.indexOf("Second-"); + if (secondsInd >= 0) { + secondsInd += 7; // read over "Second-" + int i = secondsInd; + while (i < timeoutStr.length() && Character.isDigit(timeoutStr.charAt(i))) { + i++; + } + try { + timeout = 1000L * Long.parseLong(timeoutStr.substring(secondsInd, i)); + } catch (NumberFormatException ignore) { + // ignore and return 'undefined' timeout + log.error("Invalid timeout format: " + timeoutStr); + } + } else if (timeoutStr.equalsIgnoreCase(TIMEOUT_INFINITE)) { + timeout = INFINITE_TIMEOUT; + } + } + return timeout; + } +} \ No newline at end of file Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/header/TimeoutHeader.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-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/header/package-info.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/header/package-info.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/header/package-info.java (working copy) @@ -0,0 +1,18 @@ +/* + * 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. + */ +@org.osgi.annotation.versioning.Version("1.1.0") +package org.apache.jackrabbit.webdav.header; Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/header/package-info.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/io/InputContext.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/io/InputContext.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/io/InputContext.java (working copy) @@ -0,0 +1,78 @@ +/* + * 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.webdav.io; + +import java.io.InputStream; + +/** + * InputContext... + */ +public interface InputContext { + + /** + * Return true, if there are any data to be imported (and not only properties) + * + * @return + */ + public boolean hasStream(); + + /** + * Returns the input stream of the resource to import. + * + * @return the input stream. + */ + 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 -1 if the contentlength could not be + * determined. + * + * @return the content length + */ + public long getContentLength(); + + /** + * Return the content type or null + * + * @return + */ + public String getContentType(); + + /** + * Returns the value of the given property or null if this property does + * not exist. + * + * @param propertyName + * @return String property value or null + */ + public String getProperty(String propertyName); +} Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/io/InputContext.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 \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/io/InputContextImpl.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/io/InputContextImpl.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/io/InputContextImpl.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.webdav.io; + +import org.apache.jackrabbit.webdav.DavConstants; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.servlet.http.HttpServletRequest; +import java.io.InputStream; +import java.util.Date; + +/** + * InputContextImpl class encapsulates the InputStream + * and some header values as present in the POST, PUT or MKCOL request. + */ +public class InputContextImpl implements InputContext { + + private static Logger log = LoggerFactory.getLogger(InputContextImpl.class); + + private final HttpServletRequest request; + private final InputStream in; + + public InputContextImpl(HttpServletRequest request, InputStream in) { + if (request == null) { + throw new IllegalArgumentException("DavResource and Request must not be null."); + } + + this.request = request; + this.in = in; + } + + public boolean hasStream() { + return in != null; + } + + /** + * Returns the input stream of the resource to import. + * + * @return the input stream. + */ + public InputStream getInputStream() { + return in; + } + + public long getModificationTime() { + return new Date().getTime(); + } + + /** + * Returns the content language or null. + * + * @return contentLanguage + */ + public String getContentLanguage() { + return request.getHeader(DavConstants.HEADER_CONTENT_LANGUAGE); + } + + /** + * @return content length or -1 when unknown + */ + public long getContentLength() { + String length = request.getHeader(DavConstants.HEADER_CONTENT_LENGTH); + if (length == null) { + // header not present + return -1; + } else { + try { + return Long.parseLong(length); + } catch (NumberFormatException ex) { + log.error("broken Content-Length header: " + length); + return -1; + } + } + } + + public String getContentType() { + return request.getHeader(DavConstants.HEADER_CONTENT_TYPE); + } + + public String getProperty(String propertyName) { + return request.getHeader(propertyName); + } +} Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/io/InputContextImpl.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-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/io/OutputContext.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/io/OutputContext.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/io/OutputContext.java (working copy) @@ -0,0 +1,82 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.jackrabbit.webdav.io; + +import java.io.OutputStream; + +/** + * OutputContext... + */ +public interface OutputContext { + + /** + * Return true if the given export context can provide an output stream + */ + public boolean hasStream(); + + /** + * Return the output stream to be used for the export or null + * + * @return + */ + public OutputStream getOutputStream(); + + /** + * Sets the content language. + * + * @param contentLanguage + */ + public void setContentLanguage(String contentLanguage); + + /** + * Sets the length of the data. + * + * @param contentLength the content length + */ + public void setContentLength(long contentLength); + + /** + * Set the content type for the resource content + * + * @param contentType + */ + public void setContentType(String contentType); + + /** + * 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); + + /** + * Allows to set additional properties that are not covered by an extra setter + * method. + * + * @param propertyName + * @param propertyValue + */ + public void setProperty(String propertyName, String propertyValue); +} Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/io/OutputContext.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-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/io/OutputContextImpl.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/io/OutputContextImpl.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/io/OutputContextImpl.java (working copy) @@ -0,0 +1,88 @@ +/* + * 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.webdav.io; + +import org.apache.jackrabbit.webdav.DavConstants; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.servlet.http.HttpServletResponse; +import java.io.OutputStream; + +/** + * OutputContextImpl... + */ +public class OutputContextImpl implements OutputContext { + + private static Logger log = LoggerFactory.getLogger(OutputContextImpl.class); + + private final HttpServletResponse response; + private final OutputStream out; + + public OutputContextImpl(HttpServletResponse response, OutputStream out) { + if (response == null) { + throw new IllegalArgumentException("Response must not be null."); + } + + this.response = response; + this.out = out; + } + + public boolean hasStream() { + return out != null; + } + + public OutputStream getOutputStream() { + return out; + } + + public void setContentLanguage(String contentLanguage) { + if (contentLanguage != null) { + response.setHeader(DavConstants.HEADER_CONTENT_LANGUAGE, contentLanguage); + } + } + + public void setContentLength(long contentLength) { + if (contentLength >= 0) { + response.setContentLengthLong(contentLength); + } // else: negative content length -> ignore. + } + + public void setContentType(String contentType) { + if (contentType != null) { + response.setContentType(contentType); + } + } + + public void setModificationTime(long modificationTime) { + if (modificationTime >= 0) { + response.addDateHeader(DavConstants.HEADER_LAST_MODIFIED, modificationTime); + } + } + + public void setETag(String etag) { + if (etag != null) { + response.setHeader(DavConstants.HEADER_ETAG, etag); + } + } + + public void setProperty(String propertyName, String propertyValue) { + if (propertyName != null && propertyValue != null) { + response.setHeader(propertyName, propertyValue); + } + } +} \ No newline at end of file Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/io/OutputContextImpl.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-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/io/package-info.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/io/package-info.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/io/package-info.java (working copy) @@ -0,0 +1,18 @@ +/* + * 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. + */ +@org.osgi.annotation.versioning.Version("1.0.1") +package org.apache.jackrabbit.webdav.io; Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/io/package-info.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/lock/AbstractActiveLock.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/lock/AbstractActiveLock.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/lock/AbstractActiveLock.java (working copy) @@ -0,0 +1,86 @@ +/* + * 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.webdav.lock; + +import org.apache.jackrabbit.webdav.DavConstants; +import org.apache.jackrabbit.webdav.xml.DomUtil; +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +/** + * AbstractActiveLock... + */ +public abstract class AbstractActiveLock implements ActiveLock, DavConstants { + + private String lockroot; + + /** + * @see ActiveLock#getLockroot() + */ + public String getLockroot() { + return lockroot; + } + + /** + * @see ActiveLock#setLockroot(String) + */ + public void setLockroot(String lockroot) { + this.lockroot = lockroot; + } + + /** + * Returns the default Xml representation of the 'activelock' element + * as defined by RFC 4918. + * + * @return Xml representation + * @param document + */ + public Element toXml(Document document) { + Element activeLock = DomUtil.createElement(document, XML_ACTIVELOCK, NAMESPACE); + + // lockscope property + activeLock.appendChild(getScope().toXml(document)); + // locktype property + activeLock.appendChild(getType().toXml(document)); + // depth + activeLock.appendChild(DomUtil.depthToXml(isDeep(), document)); + // timeout + long timeout = getTimeout(); + if (!isExpired() && timeout != UNDEFINED_TIMEOUT) { + activeLock.appendChild(DomUtil.timeoutToXml(timeout, document)); + } + + // owner + if (getOwner() != null) { + DomUtil.addChildElement(activeLock, XML_OWNER, NAMESPACE, getOwner()); + } + + // locktoken + if (getToken() != null) { + Element lToken = DomUtil.addChildElement(activeLock, XML_LOCKTOKEN, NAMESPACE); + lToken.appendChild(DomUtil.hrefToXml(getToken(), document)); + } + + // lock root + if (getLockroot() != null) { + Element lroot = DomUtil.addChildElement(activeLock, XML_LOCKROOT, NAMESPACE); + lroot.appendChild(DomUtil.hrefToXml(getLockroot(), document)); + } + return activeLock; + } + +} \ No newline at end of file Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/lock/AbstractActiveLock.java ___________________________________________________________________ Added: svn Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/lock/AbstractLockEntry.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/lock/AbstractLockEntry.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/lock/AbstractLockEntry.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.webdav.lock; + +import org.apache.jackrabbit.webdav.DavConstants; +import org.apache.jackrabbit.webdav.xml.DomUtil; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +/** + * AbstractLockEntry provides the generic {@link org.apache.jackrabbit.webdav.xml.XmlSerializable#toXml} method. + */ +public abstract class AbstractLockEntry implements LockEntry, DavConstants { + + private static Logger log = LoggerFactory.getLogger(AbstractLockEntry.class); + + /** + * Returns the Xml representation of this LockEntry. + * + * @return Xml representation + * @see org.apache.jackrabbit.webdav.xml.XmlSerializable#toXml(Document) + * @param document + */ + public Element toXml(Document document) { + Element entry = DomUtil.createElement(document, XML_LOCKENTRY, NAMESPACE); + entry.appendChild(getScope().toXml(document)); + entry.appendChild(getType().toXml(document)); + return entry; + } + +} \ No newline at end of file Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/lock/AbstractLockEntry.java ___________________________________________________________________ Added: svn Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/lock/ActiveLock.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/lock/ActiveLock.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/lock/ActiveLock.java (working copy) @@ -0,0 +1,124 @@ +/* + * 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.webdav.lock; + +import org.apache.jackrabbit.webdav.xml.XmlSerializable; + +/** + * ActiveLock encapsulates the lock information for a + * {@link org.apache.jackrabbit.webdav.DavResource}. + */ +public interface ActiveLock extends XmlSerializable { + + /** + * Return true, if the given token matches the lock token present in this + * lock thus indicating that any lock relevant operation should not fail + * due to a lock. + * + * @param lockToken to be checked + * @return true if the given lock token matches. + */ + public boolean isLockedByToken(String lockToken); + + /** + * Returns true, if this lock is already expired. + * + * @return true if the lock is expired + */ + public boolean isExpired(); + + /** + * Return the lock token. + * + * @return token string representing the lock token. + */ + public String getToken(); + + /** + * Return the name (or id) of the lock owner. + * + * @return name (or id) of the lock owner. + */ + public String getOwner(); + + /** + * Set the name (or id) of the lock owner + * + * @param owner + */ + public void setOwner(String owner); + + /** + * Return the number of milliseconds the lock will live until it is expired + * or -1 if the timeout is not available (or the client is not allowed + * to retrieve it). + * + * @return number of milliseconds. + */ + public long getTimeout(); + + /** + * Defines the number of milliseconds until the timeout is reached. + * + * @param timeout + */ + public void setTimeout(long timeout); + + /** + * Return true if the lock is deep. + * + * @return true if the lock is deep. + */ + public boolean isDeep(); + + /** + * Set the lock deepness. + * + * @param isDeep + */ + public void setIsDeep(boolean isDeep); + + /** + * Returns the lockroot. + * + * @return lockroot + * @see RFC 4918 + */ + public String getLockroot(); + + /** + * Set the lockroot. + * + * @param lockroot + * @see RFC 4918 + */ + public void setLockroot(String lockroot); + + /** + * Return the type of this lock. + * + * @return type + */ + public Type getType(); + + /** + * Return the scope of this lock. + * + * @return scope + */ + public Scope getScope(); +} Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/lock/ActiveLock.java ___________________________________________________________________ Added: svn Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/lock/DefaultActiveLock.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/lock/DefaultActiveLock.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/lock/DefaultActiveLock.java (working copy) @@ -0,0 +1,147 @@ +/* + * 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.webdav.lock; + +import java.util.UUID; + +import org.apache.jackrabbit.webdav.DavConstants; + +/** + * DefaultActiveLock implements the ActiveLock interface + * and represents an exclusive write lock with a random uuid lock token. + * Lock owner, timeout and depth is retrieved from the {@link LockInfo} object + * passed in the constructor. If the lockinfo is null, the following default + * values are set:
+ * - timeout is set to infinity.
+ * - isDeep is set to true.
+ * 
+ */ +public class DefaultActiveLock extends AbstractActiveLock { + + private final String token = DavConstants.OPAQUE_LOCK_TOKEN_PREFIX + UUID.randomUUID(); + private String owner; + private boolean isDeep = true; // deep by default + private long expirationTime = DavConstants.INFINITE_TIMEOUT; // never expires by default; + + /** + * Create a new DefaultActiveLock with default values. + */ + public DefaultActiveLock() { + } + + /** + * Create a new lock + * + * @param lockInfo + * @throws IllegalArgumentException if either scope or type is invalid. + */ + public DefaultActiveLock(LockInfo lockInfo) { + if (lockInfo != null) { + if (!(Type.WRITE.equals(lockInfo.getType()) && Scope.EXCLUSIVE.equals(lockInfo.getScope()))) { + throw new IllegalArgumentException("Only 'exclusive write' lock is allowed scope/type pair."); + } + owner = lockInfo.getOwner(); + isDeep = lockInfo.isDeep(); + setTimeout(lockInfo.getTimeout()); + } + } + + /** + * @see ActiveLock#isLockedByToken(String) + */ + public boolean isLockedByToken(String lockToken) { + return (token != null) && token.equals(lockToken); + } + + /** + * @see ActiveLock#isExpired() + */ + public boolean isExpired() { + return System.currentTimeMillis() > expirationTime; + } + + /** + * @see ActiveLock#getToken() + */ + public String getToken() { + return token; + } + + /** + * @see ActiveLock#getOwner() + */ + public String getOwner() { + return owner; + } + + /** + * @see ActiveLock#setOwner(String) + */ + public void setOwner(String owner) { + this.owner = owner; + } + + /** + * @see ActiveLock#getTimeout() + */ + public long getTimeout() { + return expirationTime - System.currentTimeMillis(); + } + + /** + * @see ActiveLock#setTimeout(long) + */ + public void setTimeout(long timeout) { + if (timeout > 0) { + expirationTime = System.currentTimeMillis() + timeout; + } + } + + /** + * @see ActiveLock#isDeep() + */ + public boolean isDeep() { + return isDeep; + } + + /** + * @see ActiveLock#setIsDeep(boolean) + */ + public void setIsDeep(boolean isDeep) { + this.isDeep = isDeep; + } + + /** + * This is always a write lock. + * + * @return the lock type + * @see Type#WRITE + */ + public Type getType() { + return Type.WRITE; + } + + /** + * This is always an exclusive lock. + * + * @return the lock scope. + * @see Scope#EXCLUSIVE + */ + public Scope getScope() { + return Scope.EXCLUSIVE; + } +} Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/lock/DefaultActiveLock.java ___________________________________________________________________ Added: svn Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/lock/LockDiscovery.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/lock/LockDiscovery.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/lock/LockDiscovery.java (working copy) @@ -0,0 +1,233 @@ +/* + * 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.webdav.lock; + +import org.apache.jackrabbit.webdav.property.AbstractDavProperty; +import org.apache.jackrabbit.webdav.property.DavPropertyName; +import org.apache.jackrabbit.webdav.xml.DomUtil; +import org.apache.jackrabbit.webdav.xml.ElementIterator; +import org.apache.jackrabbit.webdav.header.TimeoutHeader; +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +import java.util.ArrayList; +import java.util.List; + +/** + * The LockDiscovery class encapsulates the webdav lock discovery + * property that is sent in the request body (PROPFIND and LOCK) and received + * in a LOCK response body. + */ +public class LockDiscovery extends AbstractDavProperty> { + + /** + * Listing of existing locks applied to the resource this discovery was + * requested for. Each entry reveals, who has a lock, what type of lock he has, + * the timeout type and the time remaining on the timeout, and the lock-type. + * NOTE, that any of the information listed may be not available for the + * server is free to withhold any or all of this information. + */ + private List activeLocks = new ArrayList(); + + /** + * Creates a new empty LockDiscovery property + */ + public LockDiscovery() { + super(DavPropertyName.LOCKDISCOVERY, false); + } + + /** + * Create a new LockDiscovery property + * + * @param lock + */ + public LockDiscovery(ActiveLock lock) { + super(DavPropertyName.LOCKDISCOVERY, false); + addActiveLock(lock); + } + + /** + * Create a new LockDiscovery property + * + * @param locks + */ + public LockDiscovery(ActiveLock[] locks) { + super(DavPropertyName.LOCKDISCOVERY, false); + for (ActiveLock lock : locks) { + addActiveLock(lock); + } + } + + private void addActiveLock(ActiveLock lock) { + if (lock != null) { + activeLocks.add(lock); + } + } + + /** + * Returns the list of active locks. + * + * @return list of active locks + * @see org.apache.jackrabbit.webdav.property.DavProperty#getValue() + */ + public List getValue() { + return activeLocks; + } + + /** + * Creates a <lockdiscovery> element in response + * to a LOCK request or to the lockdiscovery property of a PROPFIND request.
+ * NOTE: if the {@link #activeLocks} list is empty an empty lockdiscovery + * property is created ( <lockdiscovery/>) + * @return A <lockdiscovery> element. + * @param document + */ + @Override + public Element toXml(Document document) { + Element lockdiscovery = getName().toXml(document); + for (ActiveLock lock : activeLocks) { + lockdiscovery.appendChild(lock.toXml(document)); + } + return lockdiscovery; + } + + //---------------------------------------------------< factory from xml >--- + /** + * Builds a new LockDiscovery object from the given xml element. + * + * @param lockDiscoveryElement + * @return + * @throws IllegalArgumentException if the given xml element is not a + * DAV:lockdiscovery element. + */ + public static LockDiscovery createFromXml(Element lockDiscoveryElement) { + if (!DomUtil.matches(lockDiscoveryElement, PROPERTY_LOCKDISCOVERY, NAMESPACE)) { + throw new IllegalArgumentException("DAV:lockdiscovery element expected."); + } + + List activeLocks = new ArrayList(); + ElementIterator it = DomUtil.getChildren(lockDiscoveryElement, XML_ACTIVELOCK, NAMESPACE); + while (it.hasNext()) { + Element al = it.nextElement(); + activeLocks.add(new ALockImpl(al)); + } + + return new LockDiscovery(activeLocks.toArray(new ActiveLock[activeLocks.size()])); + } + + //------< inner class >----------------------------------------------------- + /** + * Simple implementation of ActiveLock interface, that retrieves + * the values from the DAV:activelock XML element.
+ * Note, that all set-methods as well as {@link #isExpired()} are not + * implemented. + */ + private static class ALockImpl implements ActiveLock { + + private final Element alElement; + + private ALockImpl(Element alElement) { + if (!DomUtil.matches(alElement, XML_ACTIVELOCK, NAMESPACE)) { + throw new IllegalArgumentException("DAV:activelock element expected."); + } + this.alElement = alElement; + } + + public boolean isLockedByToken(String lockToken) { + String lt = getToken(); + if (lt == null) { + return false; + } else { + return lt.equals(lockToken); + } + } + + public boolean isExpired() { + throw new UnsupportedOperationException("Not implemented"); + } + + public String getToken() { + Element ltEl = DomUtil.getChildElement(alElement, XML_LOCKTOKEN, NAMESPACE); + if (ltEl != null) { + return DomUtil.getChildText(ltEl, XML_HREF, NAMESPACE); + } + return null; + } + + public String getOwner() { + String owner = null; + Element ow = DomUtil.getChildElement(alElement, XML_OWNER, NAMESPACE); + if (ow != null) { + if (DomUtil.hasChildElement(ow, XML_HREF, NAMESPACE)) { + owner = DomUtil.getChildTextTrim(ow, XML_HREF, NAMESPACE); + } else { + owner = DomUtil.getTextTrim(ow); + } + } + return owner; + } + + public void setOwner(String owner) { + throw new UnsupportedOperationException("Not implemented"); + } + + public long getTimeout() { + // get timeout string. if no DAV:timeout element is present, + // 't' will be 'null' and the undefined timeout will be returned. + String t = DomUtil.getChildTextTrim(alElement, XML_TIMEOUT, NAMESPACE); + return TimeoutHeader.parse(t, UNDEFINED_TIMEOUT); + } + + public void setTimeout(long timeout) { + throw new UnsupportedOperationException("Not implemented"); + } + + public boolean isDeep() { + String depth = DomUtil.getChildTextTrim(alElement, XML_DEPTH, NAMESPACE); + return DEPTH_INFINITY_S.equalsIgnoreCase(depth); + } + + public void setIsDeep(boolean isDeep) { + throw new UnsupportedOperationException("Not implemented"); + } + + public String getLockroot() { + Element root = DomUtil.getChildElement(alElement, XML_LOCKROOT, NAMESPACE); + if (root != null) { + return DomUtil.getChildTextTrim(root, XML_HREF, NAMESPACE); + } + // no lockroot element + return null; + } + + public void setLockroot(String lockroot) { + throw new UnsupportedOperationException("Not implemented"); + } + + public Type getType() { + return Type.createFromXml(DomUtil.getChildElement(alElement, XML_LOCKTYPE, NAMESPACE)); + } + + public Scope getScope() { + return Scope.createFromXml(DomUtil.getChildElement(alElement, XML_LOCKSCOPE, NAMESPACE)); + } + + public Element toXml(Document document) { + return (Element) document.importNode(alElement, true); + } + } +} Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/lock/LockDiscovery.java ___________________________________________________________________ Added: svn Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/lock/LockEntry.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/lock/LockEntry.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/lock/LockEntry.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.webdav.lock; + +import org.apache.jackrabbit.webdav.xml.XmlSerializable; + +/** + * LockEntry... + */ +public interface LockEntry extends XmlSerializable { + + /** + * Returns the type of this lock entry + * + * @return type of this lock entry. + */ + public Type getType(); + + /** + * Returns the scope of this lock entry. + * + * @return scope of this lock entry. + */ + public Scope getScope(); +} \ No newline at end of file Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/lock/LockEntry.java ___________________________________________________________________ Added: svn Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/lock/LockInfo.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/lock/LockInfo.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/lock/LockInfo.java (working copy) @@ -0,0 +1,237 @@ +/* + * 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.webdav.lock; + +import org.apache.jackrabbit.webdav.DavConstants; +import org.apache.jackrabbit.webdav.DavException; +import org.apache.jackrabbit.webdav.DavServletResponse; +import org.apache.jackrabbit.webdav.xml.DomUtil; +import org.apache.jackrabbit.webdav.xml.ElementIterator; +import org.apache.jackrabbit.webdav.xml.XmlSerializable; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +/** + * LockInfo is a simple utility class encapsulating the information + * passed with a LOCK request. It combines both the request body (which if present + * is required to by a 'lockinfo' Xml element) and the lock relevant request + * headers '{@link DavConstants#HEADER_TIMEOUT Timeout}' and + * '{@link DavConstants#HEADER_DEPTH Depth}'.
+ * Note that is class is not intended to perform any validation of the information + * given, since this left to those objects responsible for the lock creation + * on the requested resource. + */ +public class LockInfo implements DavConstants, XmlSerializable { + + private static Logger log = LoggerFactory.getLogger(LockInfo.class); + + private Type type; + private Scope scope; + private String owner; + private boolean isDeep; + private long timeout; + + private boolean isRefreshLock; + + /** + * Create a new LockInfo used for refreshing an existing lock. + * + * @param timeout + */ + public LockInfo(long timeout) { + this.timeout = (timeout > 0) ? timeout : INFINITE_TIMEOUT; + this.isRefreshLock = true; + } + + /** + * Create a new LockInfo + * + * @param scope + * @param type + * @param owner + * @param timeout + * @param isDeep + */ + public LockInfo(Scope scope, Type type, String owner, long timeout, boolean isDeep) { + this.timeout = (timeout > 0) ? timeout : INFINITE_TIMEOUT; + this.isDeep = isDeep; + + if (scope == null || type == null) { + this.isRefreshLock = true; + } else { + this.scope = scope; + this.type = type; + this.owner = owner; + } + } + + /** + * Create a new LockInfo object from the given information. If + * liElement is null this lockinfo is assumed to + * be issued from a 'Refresh Lock' request. + * + * @param liElement 'lockinfo' element present in the request body of a LOCK request + * or null if the request was intended to refresh an existing lock. + * @param timeout Requested timespan until the lock should expire. A LOCK + * request MUST contain a '{@link DavConstants#HEADER_TIMEOUT Timeout}' + * according to RFC 2518. + * @param isDeep boolean value indicating whether the lock should be applied + * with depth infinity or only to the requested resource. + * @throws DavException if the liElement is not + * null but does not start with an 'lockinfo' element. + */ + public LockInfo(Element liElement, long timeout, boolean isDeep) throws DavException { + this.timeout = (timeout > 0) ? timeout : INFINITE_TIMEOUT; + this.isDeep = isDeep; + + if (liElement != null) { + if (!DomUtil.matches(liElement, XML_LOCKINFO, NAMESPACE)) { + log.warn("'DAV:lockinfo' element expected."); + throw new DavException(DavServletResponse.SC_BAD_REQUEST); + } + + ElementIterator it = DomUtil.getChildren(liElement); + while (it.hasNext()) { + Element child = it.nextElement(); + String childName = child.getLocalName(); + if (XML_LOCKTYPE.equals(childName)) { + type = Type.createFromXml(child); + } else if (XML_LOCKSCOPE.equals(childName)) { + scope = Scope.createFromXml(child); + } else if (XML_OWNER.equals(childName)) { + // first try if 'owner' is inside a href element + owner = DomUtil.getChildTextTrim(child, XML_HREF, NAMESPACE); + if (owner==null) { + // otherwise: assume owner is a simple text element + owner = DomUtil.getTextTrim(child); + } + } + } + isRefreshLock = false; + } else { + isRefreshLock = true; + } + } + + /** + * Returns the lock type or null if no 'lockinfo' element was + * passed to the constructor or did not contain an 'type' element and the + * type has not been set otherwise. + * + * @return type or null + */ + public Type getType() { + return type; + } + + /** + * Set the lock type. + * + * @param type + */ + public void setType(Type type) { + this.type = type; + } + + /** + * Return the lock scope or null if no 'lockinfo' element was + * passed to the constructor or did not contain an 'scope' element and the + * scope has not been set otherwise. + * + * @return scope or null + */ + public Scope getScope() { + return scope; + } + + /** + * Set the lock scope. + * + * @param scope + */ + public void setScope(Scope scope) { + this.scope = scope; + } + + /** + * Return the owner indicated by the corresponding child element from the + * 'lockinfo' element or null if no 'lockinfo' element was + * passed to the constructor or did not contain an 'owner' element. + * + * @return owner or null + */ + public String getOwner() { + return owner; + } + + /** + * Returns true if the lock must be applied with depth infinity. + * + * @return true if a deep lock must be created. + */ + public boolean isDeep() { + return isDeep; + } + + /** + * Returns the time until the lock is requested to expire. + * + * @return time until the lock should expire. + */ + public long getTimeout() { + return timeout; + } + + /** + * Returns true if this LockInfo was created for a LOCK + * request intended to refresh an existing lock rather than creating a + * new one. + * + * @return true if the corresponding LOCK request was intended to refresh + * an existing lock. + */ + public boolean isRefreshLock() { + return isRefreshLock; + } + + /** + * Returns the xml representation of this lock info.
+ * NOTE however, that the depth and the timeout are not included + * in the xml. They will be passed to the server using the corresponding + * request headers. + * + * @param document + * @return xml representation of this lock info. + * @see org.apache.jackrabbit.webdav.xml.XmlSerializable#toXml(Document) + */ + public Element toXml(Document document) { + if (isRefreshLock) { + return null; + } else { + Element lockInfo = DomUtil.createElement(document, XML_LOCKINFO, NAMESPACE); + lockInfo.appendChild(scope.toXml(document)); + lockInfo.appendChild(type.toXml(document)); + if (owner != null) { + DomUtil.addChildElement(lockInfo, XML_OWNER, NAMESPACE, owner); + } + return lockInfo; + } + } + +} \ No newline at end of file Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/lock/LockInfo.java ___________________________________________________________________ Added: svn Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/lock/LockManager.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/lock/LockManager.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/lock/LockManager.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.webdav.lock; + +import org.apache.jackrabbit.webdav.DavException; +import org.apache.jackrabbit.webdav.DavResource; + +/** + * The LockManager interface. + */ +public interface LockManager { + + /** + * Create a new lock for the given {@link org.apache.jackrabbit.webdav.DavResource resource}. + * + * @param lockInfo + * @param resource + * @return + * @throws DavException + */ + public ActiveLock createLock(LockInfo lockInfo, DavResource resource) + throws DavException; + + /** + * Refresh the lock identified by the given lockToken and initially created + * on the specified resource. The update information can be retrieved from + * the lockInfo object passes. + * + * @param lockInfo + * @param lockToken + * @param resource + * @return + * @throws DavException + */ + public ActiveLock refreshLock(LockInfo lockInfo, String lockToken, DavResource resource) + throws DavException; + + /** + * Release the lock identified by the given lockToken and initially created + * on the specified resource. + * + * @param lockToken + * @param resource + * @throws DavException + */ + public void releaseLock(String lockToken, DavResource resource) + throws DavException; + + /** + * Retrieve the lock with the given type and scope that is applied to the + * given resource. The lock may be either initially created on this resource + * or might be inherited from an ancestor resource that hold a deep lock. + * If no such lock applies to the given resource null must be + * returned. + * + * @param type + * @param scope + * @param resource + * @return lock with the given type and scope applied to the resource or + * null if no lock applies. + */ + public ActiveLock getLock(Type type, Scope scope, DavResource resource); + + /** + * Returns true, if the the manager contains a lock for the given + * resource, that is hold by the specified token. + * + * @param lockToken + * @param resource + * @return true if the resource is locked by the specified token. + */ + public boolean hasLock(String lockToken, DavResource resource); +} \ No newline at end of file Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/lock/LockManager.java ___________________________________________________________________ Added: svn Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/lock/Scope.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/lock/Scope.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/lock/Scope.java (working copy) @@ -0,0 +1,122 @@ +/* + * 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.webdav.lock; + +import org.apache.jackrabbit.webdav.DavConstants; +import org.apache.jackrabbit.webdav.xml.DomUtil; +import org.apache.jackrabbit.webdav.xml.Namespace; +import org.apache.jackrabbit.webdav.xml.XmlSerializable; +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +import java.util.HashMap; +import java.util.Map; + +/** + * The Scope class abstracts the lock scope as defined by RFC 2518. + */ +public class Scope implements XmlSerializable { + + private static final Map scopes = new HashMap(); + + public static final Scope EXCLUSIVE = Scope.create(DavConstants.XML_EXCLUSIVE, DavConstants.NAMESPACE); + public static final Scope SHARED = Scope.create(DavConstants.XML_SHARED, DavConstants.NAMESPACE); + + private final String localName; + private final Namespace namespace; + + /** + * Private constructor + * + * @param localName + * @param namespace + */ + private Scope(String localName, Namespace namespace) { + this.localName = localName; + this.namespace = namespace; + } + + /** + * Return the Xml representation of the lock scope object as present in + * the LOCK request and response body and in the {@link LockDiscovery}. + * + * @return Xml representation + * @see org.apache.jackrabbit.webdav.xml.XmlSerializable#toXml(Document) + */ + public Element toXml(Document document) { + Element lockScope = DomUtil.createElement(document, DavConstants.XML_LOCKSCOPE, DavConstants.NAMESPACE); + DomUtil.addChildElement(lockScope, localName, namespace); + return lockScope; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + localName.hashCode(); + result = prime * result + namespace.hashCode(); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } else if (obj instanceof Scope) { + Scope other = (Scope) obj; + return localName.equals(other.localName) && namespace.equals(other.namespace); + } else { + return false; + } + } + + /** + * Create a Scope object from the given Xml element. + * + * @param lockScope + * @return Scope object. + */ + public static Scope createFromXml(Element lockScope) { + if (lockScope != null && DavConstants.XML_LOCKSCOPE.equals(lockScope.getLocalName())) { + // we have the parent element and must retrieve the scope first + lockScope = DomUtil.getFirstChildElement(lockScope); + } + if (lockScope == null) { + throw new IllegalArgumentException("'null' is not a valid lock scope entry."); + } + Namespace namespace = Namespace.getNamespace(lockScope.getPrefix(), lockScope.getNamespaceURI()); + return create(lockScope.getLocalName(), namespace); + } + + /** + * Create a Scope object from the given name and namespace. + * + * @param localName + * @param namespace + * @return Scope object. + */ + public static Scope create(String localName, Namespace namespace) { + String key = DomUtil.getExpandedName(localName, namespace); + if (scopes.containsKey(key)) { + return scopes.get(key); + } else { + Scope scope = new Scope(localName, namespace); + scopes.put(key, scope); + return scope; + } + } +} Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/lock/Scope.java ___________________________________________________________________ Added: svn Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/lock/SimpleLockManager.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/lock/SimpleLockManager.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/lock/SimpleLockManager.java (working copy) @@ -0,0 +1,233 @@ +/* + * 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.webdav.lock; + +import org.apache.jackrabbit.webdav.DavException; +import org.apache.jackrabbit.webdav.DavResource; +import org.apache.jackrabbit.webdav.DavResourceIterator; +import org.apache.jackrabbit.webdav.DavServletResponse; + +import java.util.HashMap; +import java.util.Map; + +/** + * Simple manager for webdav locks.
+ */ +public class SimpleLockManager implements LockManager { + + /** map of locks */ + private Map locks = new HashMap(); + + /** + * + * @param lockToken + * @param resource + * @return + * @see LockManager#hasLock(String, org.apache.jackrabbit.webdav.DavResource) + */ + public boolean hasLock(String lockToken, DavResource resource) { + ActiveLock lock = locks.get(resource.getResourcePath()); + if (lock != null && lock.getToken().equals(lockToken)) { + return true; + } + return false; + } + + /** + * Returns the lock applying to the given resource or null if + * no lock can be found. + * + * @param type + * @param scope + * @param resource + * @return lock that applies to the given resource or null. + */ + public synchronized ActiveLock getLock(Type type, Scope scope, DavResource resource) { + if (!(Type.WRITE.equals(type) && Scope.EXCLUSIVE.equals(scope))) { + return null; + } + return getLock(resource.getResourcePath()); + } + + /** + * Looks for a valid lock at the given path or a deep lock present with + * a parent path. + * + * @param path + * @return + */ + private ActiveLock getLock(String path) { + ActiveLock lock = locks.get(path); + if (lock != null) { + // check if not expired + if (lock.isExpired()) { + lock = null; + } + } + if (lock == null) { + // check, if child of deep locked parent + if (!path.equals("/")) { + ActiveLock parentLock = getLock(getParentPath(path)); + if (parentLock != null && parentLock.isDeep()) { + lock = parentLock; + } + } + } + return lock; + } + + /** + * Adds the lock for the given resource, replacing any existing lock. + * + * @param lockInfo + * @param resource being the lock holder + */ + public synchronized ActiveLock createLock(LockInfo lockInfo, + DavResource resource) + throws DavException { + if (lockInfo == null || resource == null) { + throw new IllegalArgumentException("Neither lockInfo nor resource must be null."); + } + + String resourcePath = resource.getResourcePath(); + // test if there is already a lock present on this resource + ActiveLock lock = locks.get(resourcePath); + if (lock != null && lock.isExpired()) { + locks.remove(resourcePath); + lock = null; + } + if (lock != null) { + throw new DavException(DavServletResponse.SC_LOCKED, "Resource '" + resource.getResourcePath() + "' already holds a lock."); + } + // test if the new lock would conflict with any lock inherited from the + // collection or with a lock present on any member resource. + for (String key : locks.keySet()) { + // TODO: is check for lock on internal-member correct? + if (isDescendant(key, resourcePath)) { + ActiveLock l = locks.get(key); + if (l.isDeep() || (key.equals(getParentPath(resourcePath)) && !resource.isCollection())) { + throw new DavException(DavServletResponse.SC_LOCKED, "Resource '" + resource.getResourcePath() + "' already inherits a lock by its collection."); + } + } else if (isDescendant(resourcePath, key)) { + if (lockInfo.isDeep() || isInternalMember(resource, key)) { + throw new DavException(DavServletResponse.SC_CONFLICT, "Resource '" + resource.getResourcePath() + "' cannot be locked due to a lock present on the member resource '" + key + "'."); + } + + } + } + lock = new DefaultActiveLock(lockInfo); + locks.put(resource.getResourcePath(), lock); + return lock; + } + + /** + * + * @param lockInfo + * @param lockToken + * @param resource + * @return + * @throws DavException + * @see DavResource#refreshLock(org.apache.jackrabbit.webdav.lock.LockInfo, String) + */ + public ActiveLock refreshLock(LockInfo lockInfo, String lockToken, DavResource resource) + throws DavException { + ActiveLock lock = getLock(lockInfo.getType(), lockInfo.getScope(), resource); + if (lock == null) { + throw new DavException(DavServletResponse.SC_PRECONDITION_FAILED); + } else if (!lock.getToken().equals(lockToken)) { + throw new DavException(DavServletResponse.SC_LOCKED); + } + lock.setTimeout(lockInfo.getTimeout()); + return lock; + } + + /** + * Remove the lock hold by the given resource. + * + * @param lockToken + * @param resource that is the lock holder + */ + public synchronized void releaseLock(String lockToken, DavResource resource) + throws DavException { + if (!locks.containsKey(resource.getResourcePath())) { + throw new DavException(DavServletResponse.SC_PRECONDITION_FAILED); + } + ActiveLock lock = locks.get(resource.getResourcePath()); + if (lock.getToken().equals(lockToken)) { + locks.remove(resource.getResourcePath()); + } else { + throw new DavException(DavServletResponse.SC_LOCKED); + } + } + + /** + * Return true, if the resource with the given memberPath is a internal + * non-collection member of the given resource, thus affected by a + * non-deep lock present on the resource. + * + * @param resource + * @param memberPath + * @return + */ + private static boolean isInternalMember(DavResource resource, String memberPath) { + if (resource.getResourcePath().equals(getParentPath(memberPath))) { + // find the member with the given path + DavResourceIterator it = resource.getMembers(); + while (it.hasNext()) { + DavResource member = it.nextResource(); + if (member.getResourcePath().equals(memberPath)) { + // return true if that member is not a collection + return !member.isCollection(); + } + } + } + return false; + } + + /** + * @param path Path to retrieve the parent path for. + * @return empty string if the specified path contains no '/', "/" if the + * last index of '/' is zero. Otherwise the last segment is cut off the + * specified path. + */ + private static String getParentPath(String path) { + int idx = path.lastIndexOf('/'); + switch (idx) { + case -1: + return ""; + case 0: + return "/"; + default: + return path.substring(0, idx); + } + } + + /** + * Determines if the descendant path is hierarchical a + * descendant of path. + * + * @param path the current path + * @param descendant the potential descendant + * @return true if the descendant is a descendant; + * false otherwise. + */ + private static boolean isDescendant(String path, String descendant) { + String pattern = path.endsWith("/") ? path : path + "/"; + return !pattern.equals(descendant) && descendant.startsWith(pattern); + } +} + Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/lock/SimpleLockManager.java ___________________________________________________________________ Added: svn Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/lock/SupportedLock.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/lock/SupportedLock.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/lock/SupportedLock.java (working copy) @@ -0,0 +1,166 @@ +/* + * 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.webdav.lock; + +import org.apache.jackrabbit.webdav.property.AbstractDavProperty; +import org.apache.jackrabbit.webdav.property.DavPropertyName; +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +/** + * The SupportedLock class encapsulates the lock capabilities + * of a resource. It is mainly responsible for generating the <supportedlock> + * property. + */ +public class SupportedLock extends AbstractDavProperty> { + + /** the list of lock entries */ + private final List entries = new ArrayList(); + + /** + * Creates a new empty SupportedLock property. + */ + public SupportedLock() { + super(DavPropertyName.SUPPORTEDLOCK, false); + } + + /** + * Adds a capability to this lock support. + * + * @param type Can currently only be 'write' + * @param scope Can currently only be 'exclusive' or 'shared' + * + * @throws IllegalArgumentException If an argument contains invalid string + */ + public void addEntry(Type type, Scope scope) { + entries.add(new WriteLockEntry(type, scope)); + } + + /** + * Adds a capability to this lock support. + * + * @param entry specifying the type of lock that is supported by this entry. + * @see LockEntry + */ + public void addEntry(LockEntry entry) { + if (entry == null) { + throw new IllegalArgumentException("The lock entry cannot be null."); + } + entries.add(entry); + } + + /** + * Returns true if this a lock with the given type and scope is supported. + * + * @param type + * @param scope + * @return true if applying a lock with the given type and scope is basically + * supported. + */ + public boolean isSupportedLock(Type type, Scope scope) { + for (LockEntry le : entries) { + if (le.getType().equals(type) && le.getScope().equals(scope)) { + return true; + } + } + return false; + } + + /** + * Returns an iterator over all supported locks. + * + * @return an iterator over all supported locks + */ + public Iterator getSupportedLocks() { + return entries.iterator(); + } + + /** + * Creates an XML element that represents the <supportedlock> tag. + * + * @return An XML element of this lock support. + * @param document + */ + @Override + public Element toXml(Document document) { + Element support = getName().toXml(document); + for (LockEntry le : entries) { + support.appendChild(le.toXml(document)); + } + return support; + } + + /** + * Returns the list of supported lock entries. + * + * @return list of supported lock. + * @see org.apache.jackrabbit.webdav.property.DavProperty#getValue() + */ + public List getValue() { + return entries; + } + + /** + * Class representing the default lock entries defined by + * RFC 2518. + */ + private final static class WriteLockEntry extends AbstractLockEntry { + + /** the lock scope */ + private final Scope scope; + + /** + * Creates a new WriteLockEntry + * + * @param type Can currently only be + * {@link Type#WRITE write} + * @param scope Can currently only be {@link Scope#EXCLUSIVE exclusive} + * or {@link Scope#SHARED shared}. + * + * @throws IllegalArgumentException If an argument contains invalid string + */ + WriteLockEntry(Type type, Scope scope) { + if (!Type.WRITE.equals(type)) { + throw new IllegalArgumentException("Invalid Type:" + type); + } + if (!Scope.EXCLUSIVE.equals(scope) && !Scope.SHARED.equals(scope)) { + throw new IllegalArgumentException("Invalid scope:" +scope); + } + this.scope = scope; + } + + /** + * @return always returns {@link Type#WRITE write}. + * @see LockEntry#getType() + */ + public Type getType() { + return Type.WRITE; + } + + /** + * @return returns {@link Scope#EXCLUSIVE} or {@link Scope#SHARED}. + * @see LockEntry#getScope() + */ + public Scope getScope() { + return scope; + } + } +} Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/lock/SupportedLock.java ___________________________________________________________________ Added: svn Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/lock/Type.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/lock/Type.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/lock/Type.java (working copy) @@ -0,0 +1,129 @@ +/* + * 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.webdav.lock; + +import org.apache.jackrabbit.webdav.DavConstants; +import org.apache.jackrabbit.webdav.xml.DomUtil; +import org.apache.jackrabbit.webdav.xml.Namespace; +import org.apache.jackrabbit.webdav.xml.XmlSerializable; +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +import java.util.HashMap; +import java.util.Map; + +/** + * The Type class encapsulates the lock type as defined by RFC 2518. + */ +public class Type implements XmlSerializable { + + private static Map types = new HashMap(); + + public static final Type WRITE = Type.create(DavConstants.XML_WRITE, DavConstants.NAMESPACE); + + private final String localName; + private final Namespace namespace; + + private int hashCode = -1; + + /** + * Private constructor. + * + * @param name + * @param namespace + */ + private Type(String name, Namespace namespace) { + this.localName = name; + this.namespace = namespace; + } + + /** + * Returns the Xml representation of this lock Type. + * + * @return Xml representation + * @see org.apache.jackrabbit.webdav.xml.XmlSerializable#toXml(Document) + */ + public Element toXml(Document document) { + Element lockType = DomUtil.createElement(document, DavConstants.XML_LOCKTYPE, DavConstants.NAMESPACE); + DomUtil.addChildElement(lockType, localName, namespace); + return lockType; + } + + @Override + public int hashCode() { + if (hashCode == -1) { + StringBuilder b = new StringBuilder(); + b.append("LockType : {").append(namespace).append("}").append(localName); + hashCode = b.toString().hashCode(); + } + return hashCode; + } + + /** + * Returns true if this Type is equal to the given one. + * + * @param obj + * @return + */ + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj instanceof Type) { + Type other = (Type) obj; + return localName.equals(other.localName) && namespace.equals(other.namespace); + } + return false; + } + + /** + * Create a Type object from the given Xml element. + * + * @param lockType + * @return Type object. + */ + public static Type createFromXml(Element lockType) { + if (lockType != null && DavConstants.XML_LOCKTYPE.equals(lockType.getLocalName())) { + // we have the parent element and must retrieve the type first + lockType = DomUtil.getFirstChildElement(lockType); + } + if (lockType == null) { + throw new IllegalArgumentException("'null' is not valid lock type entry."); + } + Namespace namespace = Namespace.getNamespace(lockType.getPrefix(), lockType.getNamespaceURI()); + return create(lockType.getLocalName(), namespace); + } + + /** + * Create a Type object from the given localName and namespace. + * + * @param localName + * @param namespace + * @return Type object. + */ + public static Type create(String localName, Namespace namespace) { + String key = DomUtil.getExpandedName(localName, namespace); + if (types.containsKey(key)) { + return types.get(key); + } else { + Type type = new Type(localName, namespace); + types.put(key, type); + return type; + } + } +} Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/lock/Type.java ___________________________________________________________________ Added: svn Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/lock/package-info.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/lock/package-info.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/lock/package-info.java (working copy) @@ -0,0 +1,18 @@ +/* + * 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. + */ +@org.osgi.annotation.versioning.Version("1.0.1") +package org.apache.jackrabbit.webdav.lock; Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/lock/package-info.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/observation/DefaultEventType.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/observation/DefaultEventType.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/observation/DefaultEventType.java (working copy) @@ -0,0 +1,148 @@ +/* + * 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.webdav.observation; + +import org.apache.jackrabbit.webdav.xml.Namespace; +import org.apache.jackrabbit.webdav.xml.DomUtil; +import org.apache.jackrabbit.webdav.xml.XmlSerializable; +import org.apache.jackrabbit.webdav.xml.ElementIterator; +import org.w3c.dom.Element; +import org.w3c.dom.Document; + +import java.util.Map; +import java.util.HashMap; +import java.util.List; +import java.util.ArrayList; + +/** + * DefaultEventType defines a simple EventType implementation that + * only consists of a qualified event name consisting of namespace plus local + * name. + */ +public class DefaultEventType implements EventType { + + private static final Map eventTypes = new HashMap(); + + private final String localName; + private final Namespace namespace; + + /** + * Avoid instantiation of DefaultEventType. Since the amount + * of available (and registered) events is considered to be limited, the + * static {@link #create(String, Namespace) method is defined. + * + * @param localName + * @param namespace + */ + private DefaultEventType(String localName, Namespace namespace) { + this.localName = localName; + this.namespace = namespace; + } + + /** + * Factory method to create a new EventType. + * + * @param localName + * @param namespace + * @return + */ + public static EventType create(String localName, Namespace namespace) { + if (localName == null || "".equals(localName)) { + throw new IllegalArgumentException("null and '' are not valid local names of an event type."); + } + String key = DomUtil.getExpandedName(localName, namespace); + if (eventTypes.containsKey(key)) { + return eventTypes.get(key); + } else { + EventType type = new DefaultEventType(localName, namespace); + eventTypes.put(key, type); + return type; + } + } + + /** + * Factory method to create an array of new EventType for the + * specified localNames and the specified namespace. + * + * @param localNames + * @param namespace + * @return An array of event types. + */ + public static EventType[] create(String[] localNames, Namespace namespace) { + EventType[] types = new EventType[localNames.length]; + for (int i = 0; i < localNames.length; i++) { + types[i] = create(localNames[i], namespace); + } + return types; + } + + /** + * Retrieves one or multiple EventTypes from the 'eventtype' + * Xml element. While a subscription may register multiple types (thus + * the 'eventtype' contains multiple child elements), a single event may only + * refer to one single type. + * + * @param eventType + * @return + */ + public static EventType[] createFromXml(Element eventType) { + if (!DomUtil.matches(eventType, ObservationConstants.XML_EVENTTYPE, ObservationConstants.NAMESPACE)) { + throw new IllegalArgumentException("'eventtype' element expected which contains a least a single child element."); + } + + List etypes = new ArrayList(); + ElementIterator it = DomUtil.getChildren(eventType); + while (it.hasNext()) { + Element el = it.nextElement(); + etypes.add(create(el.getLocalName(), DomUtil.getNamespace(el))); + } + return etypes.toArray(new EventType[etypes.size()]); + } + + //----------------------------------------------------------< EventType >--- + /** + * @see EventType#getName() + */ + public String getName() { + return localName; + } + + /** + * @see EventType#getNamespace() + */ + public Namespace getNamespace() { + return namespace; + } + + //----------------------------------------------------< XmlSerializable >--- + /** + * Returns a single empty Xml element where namespace and local name of this + * event type define the elements name. + *
+     * EventType.create("someevent", Namespace.getNamespace("F", "http://www.foo.bar/eventtypes"));
+     *
+     * returns the following element upon call of toXml:
+     *
+     * <F:someevent xmlns:F="http://www.foo.bar/eventtypes" />
+     * 
+ * + * @see XmlSerializable#toXml(Document) + */ + public Element toXml(Document document) { + return DomUtil.createElement(document, localName, namespace); + } +} Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/observation/DefaultEventType.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-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/observation/EventBundle.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/observation/EventBundle.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/observation/EventBundle.java (working copy) @@ -0,0 +1,29 @@ +/* + * 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.webdav.observation; + +import org.apache.jackrabbit.webdav.xml.XmlSerializable; + +/** + * EventBundle defines an empty interface used to represent a bundle + * of events. + * + * @see EventDiscovery#addEventBundle(EventBundle) + */ +public interface EventBundle extends XmlSerializable { + +} \ No newline at end of file Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/observation/EventBundle.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-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/observation/EventDiscovery.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/observation/EventDiscovery.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/observation/EventDiscovery.java (working copy) @@ -0,0 +1,121 @@ +/* + * 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.webdav.observation; + +import org.apache.jackrabbit.webdav.xml.DomUtil; +import org.apache.jackrabbit.webdav.xml.ElementIterator; +import org.apache.jackrabbit.webdav.xml.XmlSerializable; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +/** + * EventDiscovery represents the request body of a successful + * POLL request. It reveals all events that occurred since the last POLL. The + * definition what events that particular subscription is interested in was + * specified with the initial SUBSCRIPTION that started the event listening. + */ +public class EventDiscovery implements ObservationConstants, XmlSerializable { + + private static Logger log = LoggerFactory.getLogger(EventDiscovery.class); + + private final List bundles = new ArrayList(); + + /** + * Add the Xml representation of an single 'eventBundle' listing the + * events that resulted from a change in the server, filtered by the + * restrictions present in the corresponding subscription. + * + * @param eventBundle + * @see Subscription + */ + public void addEventBundle(EventBundle eventBundle) { + if (eventBundle != null) { + bundles.add(eventBundle); + } + } + + /** + * Returns an iterator over the {@link EventBundle event bundles} currently + * present on this discovery. + * + * @return iterator over event bundles present. + */ + public Iterator getEventBundles() { + return bundles.iterator(); + } + + /** + * Returns true, if this event discovery does not report any events (thus + * {@link #getEventBundles()} would return an empty iterator. + * + * @return true if {@link #getEventBundles()} would return an empty iterator, + * false otherwise. + */ + public boolean isEmpty() { + return bundles.isEmpty(); + } + + /** + * Returns the Xml representation of this EventDiscovery as + * being present in the POLL response body. + * + * @return Xml representation + * @see org.apache.jackrabbit.webdav.xml.XmlSerializable#toXml(Document) + * @param document + */ + public Element toXml(Document document) { + Element ed = DomUtil.createElement(document, XML_EVENTDISCOVERY, NAMESPACE); + for (EventBundle bundle : bundles) { + ed.appendChild(bundle.toXml(document)); + } + return ed; + } + + /** + * Build a EventDiscovery from the specified xml element. + * + * @param eventDiscoveryElement + * @return new EventDiscovery instance. + * @throws IllegalArgumentException if the given document is null + * or does not provide the required element. + */ + public static EventDiscovery createFromXml(Element eventDiscoveryElement) { + if (!DomUtil.matches(eventDiscoveryElement, XML_EVENTDISCOVERY, ObservationConstants.NAMESPACE)) { + throw new IllegalArgumentException( + "{" + ObservationConstants.NAMESPACE + "}" + XML_EVENTDISCOVERY + " element expected, but got: {" + + eventDiscoveryElement.getNamespaceURI() + "}" + eventDiscoveryElement.getLocalName()); + } + EventDiscovery eventDiscovery = new EventDiscovery(); + ElementIterator it = DomUtil.getChildren(eventDiscoveryElement, XML_EVENTBUNDLE, ObservationConstants.NAMESPACE); + while (it.hasNext()) { + final Element ebElement = it.nextElement(); + EventBundle eb = new EventBundle() { + public Element toXml(Document document) { + return (Element) document.importNode(ebElement, true); + } + }; + eventDiscovery.addEventBundle(eb); + } + return eventDiscovery; + } +} Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/observation/EventDiscovery.java ___________________________________________________________________ Added: svn Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/observation/EventType.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/observation/EventType.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/observation/EventType.java (working copy) @@ -0,0 +1,30 @@ +/* + * 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.webdav.observation; + +import org.apache.jackrabbit.webdav.xml.Namespace; +import org.apache.jackrabbit.webdav.xml.XmlSerializable; + +/** + * EventType... + */ +public interface EventType extends XmlSerializable { + + public String getName(); + + public Namespace getNamespace(); +} \ No newline at end of file Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/observation/EventType.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-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/observation/Filter.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/observation/Filter.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/observation/Filter.java (working copy) @@ -0,0 +1,74 @@ +/* + * 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.webdav.observation; + +import org.apache.jackrabbit.webdav.xml.DomUtil; +import org.apache.jackrabbit.webdav.xml.Namespace; +import org.apache.jackrabbit.webdav.xml.XmlSerializable; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +/** + * Filter... + */ +public class Filter implements XmlSerializable { + + private static Logger log = LoggerFactory.getLogger(Filter.class); + + private final String filterName; + private final Namespace filterNamespace; + private final String filterValue; + + public Filter(String filterName, Namespace filterNamespace, String filterValue) { + if (filterName == null) { + throw new IllegalArgumentException("filterName must not be null."); + } + this.filterName = filterName; + this.filterNamespace = filterNamespace; + this.filterValue = filterValue; + } + + public Filter(Element filterElem) { + filterName = filterElem.getLocalName(); + filterNamespace = DomUtil.getNamespace(filterElem); + filterValue = DomUtil.getTextTrim(filterElem); + } + + public String getName() { + return filterName; + } + + public Namespace getNamespace() { + return filterNamespace; + } + + public String getValue() { + return filterValue; + } + + public boolean isMatchingFilter(String localName, Namespace namespace) { + boolean matchingNsp = (filterNamespace == null) ? namespace == null : filterNamespace.equals(namespace); + return filterName.equals(localName) && matchingNsp; + } + + public Element toXml(Document document) { + return DomUtil.createElement(document, filterName, filterNamespace, filterValue); + } + +} \ No newline at end of file Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/observation/Filter.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-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/observation/ObservationConstants.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/observation/ObservationConstants.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/observation/ObservationConstants.java (working copy) @@ -0,0 +1,101 @@ +/* + * 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.webdav.observation; + +import javax.xml.namespace.QName; + +import org.apache.jackrabbit.webdav.property.DavPropertyName; +import org.apache.jackrabbit.webdav.xml.Namespace; + +/** + * ObservationConstants interface provide constants for request + * and response headers, Xml elements and property names used for handling + * observation over WebDAV. There exists no public standard for this + * functionality. + */ +public interface ObservationConstants { + + /** + * The namespace + */ + public static final Namespace NAMESPACE = Namespace.getNamespace("dcr", "http://www.day.com/jcr/webdav/1.0"); + + //---< Headers >------------------------------------------------------------ + /** + * The SubscriptionId request header
+ */ + public static final String HEADER_SUBSCRIPTIONID = "SubscriptionId"; + + /** + * The PollTimeout request header. + */ + public static final String HEADER_POLL_TIMEOUT = "PollTimeout"; + + //---< XML Element, Attribute Names >--------------------------------------- + /** + * subscription Xml element
+ * Mandatory element inside the {@link #SUBSCRIPTIONDISCOVERY subscriptiondiscovery} + * property indicating the event listeners present for this session.
+ * NOTE, that this will not reveal any subscription made by another session. + */ + public static final String XML_SUBSCRIPTION = "subscription"; + + /** + * Xml elements + */ + public static final String XML_SUBSCRIPTIONINFO = "subscriptioninfo"; + + public static final String XML_EVENTTYPE = "eventtype"; + public static final String XML_NOLOCAL = "nolocal"; + public static final String XML_FILTER = "filter"; + public static final String XML_SUBSCRIPTIONID = "subscriptionid"; + public static final String XML_EVENTSWITHTYPES = "eventswithnodetypes"; + public static final String XML_EVENTSWITHLOCALFLAG = "eventswithlocalflag"; + public static final String XML_UUID = "uuid"; + public static final String XML_NODETYPE_NAME = "nodetype-name"; + + public static final String XML_EVENTDISCOVERY = "eventdiscovery"; + public static final String XML_EVENTBUNDLE = "eventbundle"; + public static final String XML_EVENT_TRANSACTION_ID = "transactionid"; + public static final String XML_EVENT_LOCAL = "local"; + public static final String XML_EVENT = "event"; + public static final String XML_EVENTUSERID = "eventuserid"; + public static final String XML_EVENTUSERDATA = "eventuserdata"; + public static final String XML_EVENTDATE = "eventdate"; + public static final String XML_EVENTIDENTIFIER = "eventidentifier"; + public static final String XML_EVENTINFO = "eventinfo"; + public static final String XML_EVENTPRIMARNODETYPE = "eventprimarynodetype"; + public static final String XML_EVENTMIXINNODETYPE = "eventmixinnodetype"; + + public static final QName N_EVENT = new QName(NAMESPACE.getURI(), XML_EVENT); + public static final QName N_EVENTBUNDLE = new QName(NAMESPACE.getURI(), XML_EVENTBUNDLE); + public static final QName N_EVENTDATE = new QName(NAMESPACE.getURI(), XML_EVENTDATE); + public static final QName N_EVENTDISCOVERY = new QName(NAMESPACE.getURI(), XML_EVENTDISCOVERY); + public static final QName N_EVENTINFO = new QName(NAMESPACE.getURI(), XML_EVENTINFO); + public static final QName N_EVENTMIXINNODETYPE = new QName(NAMESPACE.getURI(), XML_EVENTMIXINNODETYPE); + public static final QName N_EVENTPRIMARYNODETYPE = new QName(NAMESPACE.getURI(), XML_EVENTPRIMARNODETYPE); + public static final QName N_EVENTTYPE = new QName(NAMESPACE.getURI(), XML_EVENTTYPE); + public static final QName N_EVENTUSERDATA = new QName(NAMESPACE.getURI(), XML_EVENTUSERDATA); + public static final QName N_EVENTUSERID = new QName(NAMESPACE.getURI(), XML_EVENTUSERID); + + //---< Property Names >----------------------------------------------------- + /** + * The protected subscription discovery property is used to find out about + * existing subscriptions present on the specified resource. + */ + public static final DavPropertyName SUBSCRIPTIONDISCOVERY = DavPropertyName.create("subscriptiondiscovery", NAMESPACE); +} Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/observation/ObservationConstants.java ___________________________________________________________________ Added: svn Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/observation/ObservationDavServletRequest.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/observation/ObservationDavServletRequest.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/observation/ObservationDavServletRequest.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.webdav.observation; + +import org.apache.jackrabbit.webdav.DavException; +import org.apache.jackrabbit.webdav.DavServletRequest; + +/** + * ObservationDavServletRequest provides extensions to the + * {@link DavServletRequest} interface used for dealing with observation. + */ +public interface ObservationDavServletRequest extends DavServletRequest { + + /** + * Return the {@link ObservationConstants#HEADER_SUBSCRIPTIONID SubscriptionId header} + * or null if no such header is present. + * + * @return the {@link ObservationConstants#HEADER_SUBSCRIPTIONID SubscriptionId header} + */ + public String getSubscriptionId(); + + /** + * Returns the {@link ObservationConstants#HEADER_POLL_TIMEOUT PollTimeout header} + * or 0 (zero) if no such header is present. + * + * @return milliseconds indicating length of the poll timeout. + */ + public long getPollTimeout(); + + /** + * Return a {@link SubscriptionInfo} object representing the subscription + * info present in the SUBSCRIBE request body or null if + * retrieving the subscription info fails. + * + * @return subscription info object encapsulating the SUBSCRIBE request body + * or null if the subscription info cannot be built. + * @throws DavException if an invalid request body was encountered. + */ + public SubscriptionInfo getSubscriptionInfo() throws DavException; +} \ No newline at end of file Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/observation/ObservationDavServletRequest.java ___________________________________________________________________ Added: svn Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/observation/ObservationDavServletResponse.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/observation/ObservationDavServletResponse.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/observation/ObservationDavServletResponse.java (working copy) @@ -0,0 +1,45 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.jackrabbit.webdav.observation; + +import org.apache.jackrabbit.webdav.DavServletResponse; + +import java.io.IOException; + +/** + * ObservationDavServletResponse provides extensions to the + * {@link DavServletResponse} interface used for dealing with observation. + */ +public interface ObservationDavServletResponse extends DavServletResponse { + + /** + * Send the response to a successful SUBSCRIBE request. + * + * @param subscription that needs to be represented in the response body. + * @throws IOException + */ + public void sendSubscriptionResponse(Subscription subscription) throws IOException; + + /** + * Send the response to a successful POLL request. + * + * @param eventDiscovery {@link EventDiscovery} object to be returned in + * the response body. + * @throws IOException + */ + public void sendPollResponse(EventDiscovery eventDiscovery) throws IOException; +} \ No newline at end of file Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/observation/ObservationDavServletResponse.java ___________________________________________________________________ Added: svn Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/observation/ObservationResource.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/observation/ObservationResource.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/observation/ObservationResource.java (working copy) @@ -0,0 +1,72 @@ +/* + * 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.webdav.observation; + +import org.apache.jackrabbit.webdav.DavException; +import org.apache.jackrabbit.webdav.DavResource; + +/** + * ObservationResource extends the {@link DavResource} interface by + * observation relevant METHODS. + */ +public interface ObservationResource extends DavResource { + + public String METHODS = "SUBSCRIBE, UNSUBSCRIBE, POLL"; + + /** + * Initializes this resource. + * + * @param subsMgr subscription manager object + */ + public void init(SubscriptionManager subsMgr); + + /** + * Subscribe this resource for event listening defined by the specified + * subscription info. A subscriptionId may be specified in case an existing + * subscription should be modified. + * + * @param info SubscriptionInfo object as defined by the + * request body and headers. + * @param subscriptionId or null if the + * {@link ObservationConstants#HEADER_SUBSCRIPTIONID SubscriptionId} header + * is missing. + * @return Subscription object in case the subscription was + * successful. + */ + public Subscription subscribe(SubscriptionInfo info, String subscriptionId) throws DavException; + + /** + * Unsubscribe the event listener with the given SubscriptionId. + * + * @param subscriptionId as present in the {@link ObservationConstants#HEADER_SUBSCRIPTIONID + * SubscriptionId} header. + */ + public void unsubscribe(String subscriptionId) throws DavException; + + /** + * Retrieve the list of events that where recorded for the event listener + * with the given SubscriptionId. + * + * @param subscriptionId as present in the + * {@link ObservationConstants#HEADER_SUBSCRIPTIONID SubscriptionId} header. + * @param timeout as present in the + * {@link ObservationConstants#HEADER_POLL_TIMEOUT} header or 0 (zero) if + * none is present. + * @return EventDiscovery object + */ + public EventDiscovery poll(String subscriptionId, long timeout) throws DavException; +} \ No newline at end of file Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/observation/ObservationResource.java ___________________________________________________________________ Added: svn Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/observation/Subscription.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/observation/Subscription.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/observation/Subscription.java (working copy) @@ -0,0 +1,49 @@ +/* + * 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.webdav.observation; + +import org.apache.jackrabbit.webdav.xml.XmlSerializable; + +/** + * Subscription represents public representation of the event + * listener created (or modified) by a successful SUBSCRIBE request.
+ * Please note that this interface extends the XmlSerializable + * interface. The Xml representation of a Subscription is + * returned in the response to a successful SUBSCRIBE request as well + * as in a PROPFIND request. In both cases the subscription is packed into + * a {@link SubscriptionDiscovery} property object. + */ +public interface Subscription extends XmlSerializable { + + /** + * Returns the id of this subscription, that must be used for un-subscribing + * as well as for event discovery later on. + * + * @return subscriptionId + */ + public String getSubscriptionId(); + + /** + * @return whether events will be returned with node type information + */ + public boolean eventsProvideNodeTypeInformation(); + + /** + * @return whether events will be returned with the "noLocal" flag + */ + public boolean eventsProvideNoLocalFlag(); +} \ No newline at end of file Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/observation/Subscription.java ___________________________________________________________________ Added: svn Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/observation/SubscriptionDiscovery.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/observation/SubscriptionDiscovery.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/observation/SubscriptionDiscovery.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.webdav.observation; + +import org.apache.jackrabbit.webdav.property.AbstractDavProperty; +import org.apache.jackrabbit.webdav.xml.DomUtil; +import org.apache.jackrabbit.webdav.xml.ElementIterator; +import org.apache.jackrabbit.webdav.xml.XmlSerializable; +import org.apache.jackrabbit.webdav.DavConstants; +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +import java.util.List; +import java.util.ArrayList; + +/** + * SubscriptionDiscovery encapsulates the 'subscriptiondiscovery' + * property of a webdav resource. + */ +public class SubscriptionDiscovery extends AbstractDavProperty { + + private final Subscription[] subscriptions; + + /** + * Create a new SubscriptionDiscovery that lists the given + * subscriptions. + * + * @param subscriptions + */ + public SubscriptionDiscovery(Subscription[] subscriptions) { + super(ObservationConstants.SUBSCRIPTIONDISCOVERY, true); + if (subscriptions != null) { + this.subscriptions = subscriptions; + } else { + this.subscriptions = new Subscription[0]; + } + } + + /** + * Create a new SubscriptionDiscovery that contains a single + * subscription entry. + * + * @param subscription + */ + public SubscriptionDiscovery(Subscription subscription) { + super(ObservationConstants.SUBSCRIPTIONDISCOVERY, true); + if (subscription != null) { + this.subscriptions = new Subscription[]{subscription}; + } else { + this.subscriptions = new Subscription[0]; + } + } + + /** + * Returns an array of {@link Subscription}s. + * + * @return an array of {@link Subscription}s + * @see org.apache.jackrabbit.webdav.property.DavProperty#getValue() + */ + public Subscription[] getValue() { + return subscriptions; + } + + /** + * Returns the Xml representation of the subscription discovery. + * + * @return Xml representation + * @see org.apache.jackrabbit.webdav.xml.XmlSerializable#toXml(Document) + * @param document + */ + @Override + public Element toXml(Document document) { + Element elem = getName().toXml(document); + for (Subscription subscription : subscriptions) { + elem.appendChild(subscription.toXml(document)); + } + return elem; + } + + //-----------------------------------------------------< static Factory >--- + public static SubscriptionDiscovery createFromXml(Element sDiscoveryElement) { + if (!DomUtil.matches(sDiscoveryElement, ObservationConstants.SUBSCRIPTIONDISCOVERY.getName(), ObservationConstants.SUBSCRIPTIONDISCOVERY.getNamespace())) { + throw new IllegalArgumentException("'subscriptiondiscovery' element expected."); + } + + List subscriptions = new ArrayList(); + ElementIterator it = DomUtil.getChildren(sDiscoveryElement, ObservationConstants.XML_SUBSCRIPTION, ObservationConstants.NAMESPACE); + while (it.hasNext()) { + final Element sb = it.nextElement(); + // anonymous inner class: Subscription interface + Subscription s = new Subscription() { + /** + * @see Subscription#getSubscriptionId() + */ + public String getSubscriptionId() { + Element ltEl = DomUtil.getChildElement(sb, ObservationConstants.XML_SUBSCRIPTIONID, ObservationConstants.NAMESPACE); + if (ltEl != null) { + return DomUtil.getChildText(sb, DavConstants.XML_HREF, DavConstants.NAMESPACE); + } + return null; + } + + public boolean eventsProvideNodeTypeInformation() { + String t = DomUtil.getChildText(sb, ObservationConstants.XML_EVENTSWITHTYPES, ObservationConstants.NAMESPACE); + return t == null ? false : Boolean.parseBoolean(t); + } + + public boolean eventsProvideNoLocalFlag() { + String t = DomUtil.getChildText(sb, ObservationConstants.XML_EVENTSWITHLOCALFLAG, ObservationConstants.NAMESPACE); + return t == null ? false : Boolean.parseBoolean(t); + } + + /** + * @see XmlSerializable#toXml(Document) + */ + public Element toXml(Document document) { + return (Element) document.importNode(sb, true); + } + }; + subscriptions.add(s); + } + + return new SubscriptionDiscovery(subscriptions.toArray(new Subscription[subscriptions.size()])); + } +} \ No newline at end of file Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/observation/SubscriptionDiscovery.java ___________________________________________________________________ Added: svn Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/observation/SubscriptionInfo.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/observation/SubscriptionInfo.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/observation/SubscriptionInfo.java (working copy) @@ -0,0 +1,242 @@ +/* + * 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.webdav.observation; + +import org.apache.jackrabbit.webdav.DavException; +import org.apache.jackrabbit.webdav.DavServletResponse; +import org.apache.jackrabbit.webdav.header.TimeoutHeader; +import org.apache.jackrabbit.webdav.header.DepthHeader; +import org.apache.jackrabbit.webdav.xml.DomUtil; +import org.apache.jackrabbit.webdav.xml.ElementIterator; +import org.apache.jackrabbit.webdav.xml.Namespace; +import org.apache.jackrabbit.webdav.xml.XmlSerializable; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +import java.util.ArrayList; +import java.util.List; + +/** + * SubscriptionInfo class encapsulates the subscription info + * that forms the request body of a SUBSCRIBE request.
+ * The following xml layout is defined for the subscription info: + *
+ * <!ELEMENT subscriptioninfo ( eventtype, nolocal?, filter? ) >
+ * <!ELEMENT eventtype ANY >
+ *
+ * ANY defines any sequence of elements where at least one defines a valid
+ * eventtype. Note that a single eventtype must not occur multiple times.
+
+ * <!ELEMENT nolocal EMPTY >
+ * <!ELEMENT filter ANY >
+ *
+ * ANY: any sequence of elements identifying a filter for event listening but
+ * at least a single element.
+ * 
+ * @see ObservationConstants#XML_SUBSCRIPTIONINFO + */ +public class SubscriptionInfo implements ObservationConstants, XmlSerializable { + + private static Logger log = LoggerFactory.getLogger(SubscriptionInfo.class); + + private final EventType[] eventTypes; + private final Filter[] filters; + private final boolean noLocal; + private final boolean isDeep; + private final long timeout; + + /** + * Create a new SubscriptionInfo + * + * @param eventTypes + * @param isDeep + * @param timeout + */ + public SubscriptionInfo(EventType[] eventTypes, boolean isDeep, long timeout) { + this(eventTypes, null, false, isDeep, timeout); + } + + /** + * Create a new SubscriptionInfo + * + * @param eventTypes + * @param filters + * @param noLocal + * @param isDeep + * @param timeout + */ + public SubscriptionInfo(EventType[] eventTypes, Filter[] filters, boolean noLocal, boolean isDeep, long timeout) { + if (eventTypes == null || eventTypes.length == 0) { + throw new IllegalArgumentException("'subscriptioninfo' must at least indicate a single event type."); + } + + this.eventTypes = eventTypes; + this.noLocal = noLocal; + + if (filters != null) { + this.filters = filters; + } else { + this.filters = new Filter[0]; + } + + this.isDeep = isDeep; + this.timeout = timeout; + } + + /** + * Create a new SubscriptionInfo from the given Xml element + * and from additional information that is transported within the request + * header: + *
    + *
  • {@link TimeoutHeader timeout},
  • + *
  • {@link DepthHeader isDeep}
  • + *
+ * @param reqInfo Xml element present in the request body. + * @param timeout as defined in the {@link org.apache.jackrabbit.webdav.DavConstants#HEADER_TIMEOUT timeout header}. + * @param isDeep as defined in the {@link org.apache.jackrabbit.webdav.DavConstants#HEADER_DEPTH depth header}. + * @throws IllegalArgumentException if the reqInfo element does not contain the mandatory elements. + */ + public SubscriptionInfo(Element reqInfo, long timeout, boolean isDeep) throws DavException { + if (!DomUtil.matches(reqInfo, XML_SUBSCRIPTIONINFO, NAMESPACE)) { + log.warn("Element with name 'subscriptioninfo' expected"); + throw new DavException(DavServletResponse.SC_BAD_REQUEST); + } + Element el = DomUtil.getChildElement(reqInfo, XML_EVENTTYPE, NAMESPACE); + if (el != null) { + eventTypes = DefaultEventType.createFromXml(el); + if (eventTypes.length == 0) { + log.warn("'subscriptioninfo' must at least indicate a single, valid event type."); + throw new DavException(DavServletResponse.SC_BAD_REQUEST); + } + } else { + log.warn("'subscriptioninfo' must contain an 'eventtype' child element."); + throw new DavException(DavServletResponse.SC_BAD_REQUEST); + } + + List filters = new ArrayList(); + el = DomUtil.getChildElement(reqInfo, XML_FILTER, NAMESPACE); + if (el != null) { + ElementIterator it = DomUtil.getChildren(el); + while (it.hasNext()) { + Filter f = new Filter(it.nextElement()); + filters.add(f); + } + } + this.filters = filters.toArray(new Filter[filters.size()]); + + this.noLocal = DomUtil.hasChildElement(reqInfo, XML_NOLOCAL, NAMESPACE); + this.isDeep = isDeep; + this.timeout = timeout; + } + + /** + * Return array of event type names present in the subscription info. + * + * @return array of String defining the names of the events this subscription + * should listen to. + * + */ + public EventType[] getEventTypes() { + return eventTypes; + } + + /** + * Return all filters defined for this SubscriptionInfo + * + * @return all filters or an empty Filter array. + */ + public Filter[] getFilters() { + return filters; + } + + /** + * Return array of filters with the specified name. + * + * @param localName the filter elements must provide. + * @param namespace + * @return array containing the text of the filter elements with the given + * name. + */ + public Filter[] getFilters(String localName, Namespace namespace) { + List l = new ArrayList(); + for (Filter filter : filters) { + if (filter.isMatchingFilter(localName, namespace)) { + l.add(filter); + } + } + return l.toArray(new Filter[l.size()]); + } + + /** + * Returns true if the {@link #XML_NOLOCAL} element is present in this + * subscription info. + * + * @return if {@link #XML_NOLOCAL} element is present. + */ + public boolean isNoLocal() { + return noLocal; + } + + /** + * Returns true if the {@link org.apache.jackrabbit.webdav.DavConstants#HEADER_DEPTH + * depths header} defined a depth other than '0'. + * + * @return true if this subscription info was created with isDeep + * true. + */ + public boolean isDeep() { + return isDeep; + } + + /** + * Return the timeout as retrieved from the request. + * + * @return timeout. + */ + public long getTimeOut() { + return timeout; + } + + /** + * Xml representation of this SubscriptionInfo. + * + * @return Xml representation + * @see org.apache.jackrabbit.webdav.xml.XmlSerializable#toXml(Document) + * @param document + */ + public Element toXml(Document document) { + Element subscrInfo = DomUtil.createElement(document, XML_SUBSCRIPTIONINFO, NAMESPACE); + Element eventType = DomUtil.addChildElement(subscrInfo, XML_EVENTTYPE, NAMESPACE); + for (EventType et : eventTypes) { + eventType.appendChild(et.toXml(document)); + } + + if (filters.length > 0) { + Element filter = DomUtil.addChildElement(subscrInfo, XML_FILTER, NAMESPACE); + for (Filter f : filters) { + filter.appendChild(f.toXml(document)); + } + } + + if (noLocal) { + DomUtil.addChildElement(subscrInfo, XML_NOLOCAL, NAMESPACE); + } + return subscrInfo; + } +} Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/observation/SubscriptionInfo.java ___________________________________________________________________ Added: svn Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/observation/SubscriptionManager.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/observation/SubscriptionManager.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/observation/SubscriptionManager.java (working copy) @@ -0,0 +1,69 @@ +/* + * 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.webdav.observation; + +import org.apache.jackrabbit.webdav.DavException; + +/** + * SubscriptionManager interface. + */ +public interface SubscriptionManager { + + /** + * Retrieve the {@link org.apache.jackrabbit.webdav.observation.SubscriptionDiscovery} object for the given + * resource. Note, that the discovery object will be empty if there are + * no subscriptions present. + * + * @param resource + */ + public SubscriptionDiscovery getSubscriptionDiscovery(ObservationResource resource); + + /** + * Create a new Subscription or update an existing Subscription.. + * + * @param info + * @param subscriptionId + * @param resource + * @return Subscription that has been created or updated + * @throws DavException if the subscription fails + */ + public Subscription subscribe(SubscriptionInfo info, String subscriptionId, + ObservationResource resource) + throws DavException; + + /** + * Unsubscribe the Subscription with the given id. + * + * @param subscriptionId + * @param resource + * @throws DavException + */ + public void unsubscribe(String subscriptionId, ObservationResource resource) + throws DavException; + + /** + * Retrieve the list of events that occurred since the last poll. + * + * @param subscriptionId identifier for the subscription + * @param timeout the time in milliseconds to wait at most for events + * if none is present currently. + * @param resource + * @return + */ + public EventDiscovery poll(String subscriptionId, long timeout, ObservationResource resource) + throws DavException; +} \ No newline at end of file Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/observation/SubscriptionManager.java ___________________________________________________________________ Added: svn Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/observation/package-info.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/observation/package-info.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/observation/package-info.java (working copy) @@ -0,0 +1,18 @@ +/* + * 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. + */ +@org.osgi.annotation.versioning.Version("1.1.0") +package org.apache.jackrabbit.webdav.observation; Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/observation/package-info.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/ordering/OrderPatch.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/ordering/OrderPatch.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/ordering/OrderPatch.java (working copy) @@ -0,0 +1,212 @@ +/* + * 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.webdav.ordering; + +import org.apache.jackrabbit.webdav.DavConstants; +import org.apache.jackrabbit.webdav.DavException; +import org.apache.jackrabbit.webdav.DavServletResponse; +import org.apache.jackrabbit.webdav.xml.DomUtil; +import org.apache.jackrabbit.webdav.xml.ElementIterator; +import org.apache.jackrabbit.webdav.xml.XmlSerializable; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +import java.util.ArrayList; +import java.util.List; + +/** + * OrderPatch represents the mandatory request body of an + * ORDERPATCH request. RFC 3648 defines the following structure for it:
+ *
+ * <!ELEMENT orderpatch (ordering-type?, order-member*) >
+ * <!ELEMENT order-member (segment, position) >
+ * <!ELEMENT position (first | last | before | after) >
+ * <!ELEMENT segment (#PCDATA) >
+ * <!ELEMENT first EMPTY >
+ * <!ELEMENT last EMPTY >
+ * <!ELEMENT before segment >
+ * <!ELEMENT after segment >
+ * 
+ */ +public class OrderPatch implements OrderingConstants, XmlSerializable { + + private static Logger log = LoggerFactory.getLogger(OrderPatch.class); + + private Member[] instructions; + private String orderingType; + + /** + * Create a new OrderPath object. + * + * @param orderingType + * @param instruction + */ + public OrderPatch(String orderingType, Member instruction) { + this(orderingType, new Member[] {instruction}); + } + + /** + * Create a new OrderPath object. + * + * @param orderingType + * @param instructions + */ + public OrderPatch(String orderingType, Member[] instructions) { + if (orderingType == null || instructions == null) { + throw new IllegalArgumentException("ordering type and instructions cannot be null."); + } + this.orderingType = orderingType; + this.instructions = instructions; + } + + /** + * Return the ordering type. + * + * @return ordering type + */ + public String getOrderingType() { + return orderingType; + } + + /** + * Return an array of {@link Member} objects defining the re-ordering + * instructions to be applied to the requested resource. + * + * @return ordering instructions. + */ + public Member[] getOrderInstructions() { + return instructions; + } + + //------------------------------------------< XmlSerializable interface >--- + /** + * + * @return + * @param document + */ + public Element toXml(Document document) { + Element orderPatch = DomUtil.createElement(document, XML_ORDERPATCH, NAMESPACE); + // add DAV:ordering-type below DAV:orderpatch + Element otype = DomUtil.addChildElement(orderPatch, XML_ORDERING_TYPE, NAMESPACE); + otype.appendChild(DomUtil.hrefToXml(orderingType, document)); + // add DAV:member elements below DAV:orderpatch + for (Member instruction : instructions) { + orderPatch.appendChild(instruction.toXml(document)); + } + return orderPatch; + } + + //------------------------------------------------------< static method >--- + /** + * Create a new OrderPath object. + * + * @param orderPatchElement + * @throws IllegalArgumentException if the specified Xml element was not valid. + */ + public static OrderPatch createFromXml(Element orderPatchElement) throws DavException { + if (!DomUtil.matches(orderPatchElement, XML_ORDERPATCH, NAMESPACE)) { + log.warn("ORDERPATH request body must start with an 'orderpatch' element."); + throw new DavException(DavServletResponse.SC_BAD_REQUEST); + } + + // retrieve the href of the orderingtype element + String orderingType; + Element otype = DomUtil.getChildElement(orderPatchElement, XML_ORDERING_TYPE, NAMESPACE); + if (otype != null) { + orderingType = DomUtil.getChildText(otype, DavConstants.XML_HREF, DavConstants.NAMESPACE); + } else { + log.warn("ORDERPATH request body must contain an 'ordering-type' child element."); + throw new DavException(DavServletResponse.SC_BAD_REQUEST); + } + + // set build the list of ordering instructions + List tmpList = new ArrayList(); + ElementIterator it = DomUtil.getChildren(orderPatchElement, XML_ORDER_MEMBER, NAMESPACE); + while (it.hasNext()) { + Element el = it.nextElement(); + try { + // retrieve text 'DAV:segment' child of this DAV:order-member element + String segment = DomUtil.getChildText(el, XML_SEGMENT, NAMESPACE); + // retrieve the 'DAV:position' child element + Position pos = Position.createFromXml(DomUtil.getChildElement(el, XML_POSITION, NAMESPACE)); + Member om = new Member(segment, pos); + tmpList.add(om); + } catch (IllegalArgumentException e) { + log.warn("Invalid element in 'orderpatch' request body: " + e.getMessage()); + throw new DavException(DavServletResponse.SC_BAD_REQUEST); + } + } + Member[] instructions = tmpList.toArray(new Member[tmpList.size()]); + return new OrderPatch(orderingType, instructions); + } + + //-------------------------------------------------------------------------- + /** + * Internal class Member represents the 'Order-Member' children + * elements of an 'OrderPatch' request body present in the ORDERPATCH request. + */ + public static class Member implements XmlSerializable { + + private String memberHandle; + private Position position; + + /** + * Create a new Member object. + * + * @param memberHandle + * @param position + */ + public Member(String memberHandle, Position position) { + this.memberHandle = memberHandle; + this.position = position; + } + + /** + * Return the handle of the internal member to be reordered. + * + * @return handle of the internal member. + */ + public String getMemberHandle() { + return memberHandle; + } + + /** + * Return the position where the internal member identified by the + * member handle should be placed. + * + * @return position for the member after the request. + * @see #getMemberHandle() + */ + public Position getPosition() { + return position; + } + + //--------------------------------------< XmlSerializable interface >--- + /** + * @see org.apache.jackrabbit.webdav.xml.XmlSerializable#toXml(Document) + */ + public Element toXml(Document document) { + Element memberElem = DomUtil.createElement(document, XML_ORDER_MEMBER, NAMESPACE); + DomUtil.addChildElement(memberElem, XML_SEGMENT, NAMESPACE, memberHandle); + memberElem.appendChild(position.toXml(document)); + return memberElem; + } + + } +} Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/ordering/OrderPatch.java ___________________________________________________________________ Added: svn Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/ordering/OrderingConstants.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/ordering/OrderingConstants.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/ordering/OrderingConstants.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.webdav.ordering; + +import org.apache.jackrabbit.webdav.DavConstants; +import org.apache.jackrabbit.webdav.property.DavPropertyName; +import org.apache.jackrabbit.webdav.xml.Namespace; + +/** + * OrderingConstants provide constants for request and response + * headers, Xml elements and property names defined by + * RFC 3648. + */ +public interface OrderingConstants { + + /** + * The namespace + */ + public static final Namespace NAMESPACE = DavConstants.NAMESPACE; + + /** + * Constant representing the DAV:custom ordering type URI, which indicates + * that the collection is not ordered. + */ + public static final String ORDERING_TYPE_CUSTOM = "DAV:custom"; + + /** + * Constant representing the DAV:unordered ordering type URI, which indicates + * that the collection is to be ordered, but the semantics of the ordering + * is not being advertised. + */ + public static final String ORDERING_TYPE_UNORDERED = "DAV:unordered"; + + //---< Headers >------------------------------------------------------------ + /** + * The "Ordering-Type" request header. + */ + public static final String HEADER_ORDERING_TYPE = "Ordering-Type"; + + /** + * When a new member is added to a collection with a client-maintained + * ordering (for example, with PUT, COPY, or MKCOL), its position in the + * ordering can be set with the new Position header.

+ * + * Position = "Position" ":" ("first" | "last" | (("before" | "after") segment)) + * + *

NOTE: segment is defined in section 3.3 of RFC2396. + */ + public static final String HEADER_POSITION = "Position"; + + //---< XML Element, Attribute Names >--------------------------------------- + /** + * Xml elements used for reordering internal members of a collection. + */ + public static final String XML_ORDERPATCH = "orderpatch"; + public static final String XML_ORDERING_TYPE = "ordering-type"; + public static final String XML_ORDER_MEMBER = "order-member"; + public static final String XML_POSITION = "position"; + public static final String XML_SEGMENT = "segment"; + + public static final String XML_FIRST = "first"; + public static final String XML_LAST = "last"; + public static final String XML_BEFORE = "before"; + public static final String XML_AFTER = "after"; + + //---< XML Element, Attribute Names >--------------------------------------- + /** + * The DAV:ordering-type property indicates whether the collection is + * ordered and, if so, uniquely identifies the semantics of the ordering. + * + * @see OrderingType + */ + public static final DavPropertyName ORDERING_TYPE = DavPropertyName.create("ordering-type", DavConstants.NAMESPACE); + + /** + * Required live property for resources that honor the 'ordered-collections' + * compliance class defined by RFC 3648.
+ * The supported-method-set property has been introduced with RFC 3253. + * + * @see org.apache.jackrabbit.webdav.version.DeltaVConstants#SUPPORTED_METHOD_SET + */ + public static final DavPropertyName SUPPORTED_METHOD_SET = DavPropertyName.create("supported-method-set", DavConstants.NAMESPACE); + + /** + * Required live property for resources that honor the 'ordered-collections' + * compliance class defined by RFC 3648.
+ * The supported-live-property-set property has been introduced with RFC 3253. + * + * @see org.apache.jackrabbit.webdav.version.DeltaVConstants#SUPPORTED_LIVE_PROPERTY_SET + */ + public static final DavPropertyName SUPPORTED_LIVE_PROPERTY_SET = DavPropertyName.create("supported-live-property-set", DavConstants.NAMESPACE); +} \ No newline at end of file Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/ordering/OrderingConstants.java ___________________________________________________________________ Added: svn Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/ordering/OrderingDavServletRequest.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/ordering/OrderingDavServletRequest.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/ordering/OrderingDavServletRequest.java (working copy) @@ -0,0 +1,55 @@ +/* + * 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.webdav.ordering; + +import org.apache.jackrabbit.webdav.DavException; +import org.apache.jackrabbit.webdav.DavServletRequest; + +/** + * OrderingDavServletRequest provides extensions to the + * {@link DavServletRequest} interface used for ordering members of orderable + * collections. + */ +public interface OrderingDavServletRequest extends DavServletRequest { + + /** + * Returns the {@link OrderingConstants#HEADER_ORDERING_TYPE Ordering-Type header}. + * + * @return the String value of the {@link OrderingConstants#HEADER_ORDERING_TYPE Ordering-Type header}. + */ + public String getOrderingType(); + + /** + * Return a Position object encapsulating the {@link OrderingConstants#HEADER_POSITION + * Position header} field or null if no Position header is present + * or does not contain a valid format. + * + * @return Position object encapsulating the {@link OrderingConstants#HEADER_POSITION + * Position header} + */ + public Position getPosition(); + + /** + * Return a OrderPatch object encapsulating the request body + * of an ORDERPATCH request or null if the request body was + * either missing or could not be parsed. + * + * @return OrderPatch object encapsulating the request body. + */ + public OrderPatch getOrderPatch() throws DavException; + +} \ No newline at end of file Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/ordering/OrderingDavServletRequest.java ___________________________________________________________________ Added: svn Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/ordering/OrderingResource.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/ordering/OrderingResource.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/ordering/OrderingResource.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.webdav.ordering; + +import org.apache.jackrabbit.webdav.DavException; +import org.apache.jackrabbit.webdav.DavResource; + +/** + * OrderingResource extends the {@link DavResource} interface by + * METHODS relating to ordering functionality defined by + * RFC 3648. + */ +public interface OrderingResource extends DavResource { + + public String METHODS = "ORDERPATCH"; + + /** + * Returns true if this resources allows ordering of its internal members. + * + * @return true if internal members are orderable. + */ + public boolean isOrderable(); + + /** + * Reorders the internal members of this resource according to the + * instructions present in the specified {@link OrderPatch} object. + * + * @param orderPatch as present in the ORDERPATCH request body. + * @throws DavException + */ + public void orderMembers(OrderPatch orderPatch) throws DavException; + +} \ No newline at end of file Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/ordering/OrderingResource.java ___________________________________________________________________ Added: svn Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/ordering/OrderingType.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/ordering/OrderingType.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/ordering/OrderingType.java (working copy) @@ -0,0 +1,52 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.jackrabbit.webdav.ordering; + +import org.apache.jackrabbit.webdav.property.HrefProperty; + +/** + * OrderingType represents the {@link #ORDERING_TYPE + * DAV:ordering-type} property as defined by + * RFC 3648. This property is + * protected cannot be set using PROPPATCH. Its value may only be set by + * including the Ordering-Type header with a MKCOL request or by submitting an + * ORDERPATCH request. + * + * @see org.apache.jackrabbit.webdav.property.DavProperty#isInvisibleInAllprop() + */ +public class OrderingType extends HrefProperty implements OrderingConstants { + + /** + * Creates a OrderingType with the default type (e.g. default + * value). The default value is specified to be {@link #ORDERING_TYPE_UNORDERED}. + */ + public OrderingType() { + this(null); + } + + /** + * Create an OrderingType with the given ordering.
+ * NOTE: the ordering-type property is defined to be protected. + * + * @param href + * @see org.apache.jackrabbit.webdav.property.DavProperty#isInvisibleInAllprop() + */ + public OrderingType(String href) { + // spec requires that the default value is 'DAV:unordered' + super(ORDERING_TYPE, (href != null) ? href : ORDERING_TYPE_UNORDERED, true); + } +} Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/ordering/OrderingType.java ___________________________________________________________________ Added: svn Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/ordering/Position.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/ordering/Position.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/ordering/Position.java (working copy) @@ -0,0 +1,164 @@ +/* + * 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.webdav.ordering; + +import org.apache.jackrabbit.webdav.xml.DomUtil; +import org.apache.jackrabbit.webdav.xml.ElementIterator; +import org.apache.jackrabbit.webdav.xml.XmlSerializable; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +import java.util.HashSet; +import java.util.Set; + +/** + * Position encapsulates the position in ordering information + * contained in a Webdav request. This includes both the + * {@link OrderingConstants#HEADER_POSITION Position header} and the position + * Xml element present in the request body of an ORDERPATCH request. + * + * @see OrderingConstants#HEADER_POSITION + * @see OrderingConstants#XML_POSITION + * @see OrderPatch + */ +public class Position implements OrderingConstants, XmlSerializable { + + private static Logger log = LoggerFactory.getLogger(Position.class); + + private static final Set VALID_TYPES = new HashSet(); + static { + VALID_TYPES.add(XML_FIRST); + VALID_TYPES.add(XML_LAST); + VALID_TYPES.add(XML_AFTER); + VALID_TYPES.add(XML_BEFORE); + } + + private final String type; + private final String segment; + + /** + * Create a new Position object with the specified type. + * Since any type except for {@link #XML_FIRST first} and {@link #XML_LAST last} + * must be combined with a segment, only the mentioned types are valid + * arguments. + * + * @param type {@link #XML_FIRST first} or {@link #XML_LAST last} + * @throws IllegalArgumentException if the given type is other than {@link #XML_FIRST} + * or {@link #XML_LAST}. + */ + public Position(String type) { + if (!VALID_TYPES.contains(type)) { + throw new IllegalArgumentException("Invalid type: " + type); + } + if (!(XML_FIRST.equals(type) || XML_LAST.equals(type))) { + throw new IllegalArgumentException("If type is other than 'first' or 'last' a segment must be specified"); + } + this.type = type; + this.segment = null; + } + + /** + * Create a new Position object with the specified type and + * segment. + * + * @param type + * @param segment + * @throws IllegalArgumentException if the specified type and segment do not + * form a valid pair. + */ + public Position(String type, String segment) { + if (!VALID_TYPES.contains(type)) { + throw new IllegalArgumentException("Invalid type: " + type); + } + if ((XML_AFTER.equals(type) || XML_BEFORE.equals(type)) && (segment == null || "".equals(segment))) { + throw new IllegalArgumentException("If type is other than 'first' or 'last' a segment must be specified"); + } + this.type = type; + this.segment = segment; + } + + /** + * Return the type of this Position object, which may be any + * of the following valid types: {@link #XML_FIRST first}, + * {@link #XML_LAST last}, {@link #XML_AFTER after}, {@link #XML_BEFORE before} + * + * @return type + */ + public String getType() { + return type; + } + + /** + * Returns the segment used to create this Position object or + * null if no segment is present with the type. + * + * @return segment or null + * @see #getType() + */ + public String getSegment() { + return segment; + } + + //------------------------------------------< XmlSerializable interface >--- + /** + * @see org.apache.jackrabbit.webdav.xml.XmlSerializable#toXml(Document) + * @param document + */ + public Element toXml(Document document) { + Element positionElement = DomUtil.createElement(document, XML_POSITION, NAMESPACE); + Element typeElement = DomUtil.addChildElement(positionElement, type, NAMESPACE); + if (segment != null) { + DomUtil.addChildElement(typeElement, XML_SEGMENT, NAMESPACE, segment); + } + return positionElement; + } + + //-----------------------------------------------------< static methods >--- + /** + * Create a new Position object from the specified position + * element. The element must fulfill the following structure:
+ *
+     * <!ELEMENT position (first | last | before | after) >
+     * <!ELEMENT segment (#PCDATA) >
+     * <!ELEMENT first EMPTY >
+     * <!ELEMENT last EMPTY >
+     * <!ELEMENT before segment >
+     * <!ELEMENT after segment >
+     * 
+ * + * @param positionElement Xml element defining the position. + * @throws IllegalArgumentException if the given Xml element is not valid. + */ + public static Position createFromXml(Element positionElement) { + if (!DomUtil.matches(positionElement, XML_POSITION, NAMESPACE)) { + throw new IllegalArgumentException("The 'DAV:position' element required."); + } + ElementIterator it = DomUtil.getChildren(positionElement); + if (it.hasNext()) { + Element el = it.nextElement(); + String type = el.getLocalName(); + // read the text of DAV:segment child element inside the type + String segmentText = DomUtil.getChildText(el, XML_SEGMENT, NAMESPACE); + // stop after the first iteration + return new Position(type, segmentText); + } else { + throw new IllegalArgumentException("The 'DAV:position' element required with exact one child indicating the type."); + } + } +} Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/ordering/Position.java ___________________________________________________________________ Added: svn Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/ordering/package-info.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/ordering/package-info.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/ordering/package-info.java (working copy) @@ -0,0 +1,18 @@ +/* + * 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. + */ +@org.osgi.annotation.versioning.Version("1.0.0") +package org.apache.jackrabbit.webdav.ordering; Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/ordering/package-info.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/package-info.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/package-info.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/package-info.java (working copy) @@ -0,0 +1,18 @@ +/* + * 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. + */ +@org.osgi.annotation.versioning.Version("1.4.0") +package org.apache.jackrabbit.webdav; Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/package-info.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/property/AbstractDavProperty.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/property/AbstractDavProperty.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/property/AbstractDavProperty.java (working copy) @@ -0,0 +1,163 @@ +/* + * 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.webdav.property; + +import org.apache.jackrabbit.webdav.DavConstants; +import org.apache.jackrabbit.webdav.xml.DomUtil; +import org.apache.jackrabbit.webdav.xml.XmlSerializable; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.Node; + +import java.util.Collection; + +/** + * AbstractDavProperty provides generic METHODS used by various + * implementations of the {@link DavProperty} interface. + */ +public abstract class AbstractDavProperty implements DavProperty { + + private static Logger log = LoggerFactory.getLogger(AbstractDavProperty.class); + + private final DavPropertyName name; + private final boolean isInvisibleInAllprop; + + /** + * Create a new AbstractDavProperty with the given {@link DavPropertyName} + * and a boolean flag indicating whether this property should be suppressed + * in PROPFIND/allprop responses. + */ + public AbstractDavProperty(DavPropertyName name, boolean isInvisibleInAllprop) { + this.name = name; + this.isInvisibleInAllprop = isInvisibleInAllprop; + } + + /** + * Computes the hash code using this property's name and value. + * + * @return the hash code + */ + @Override + public int hashCode() { + int hashCode = getName().hashCode(); + if (getValue() != null) { + hashCode += getValue().hashCode(); + } + return hashCode % Integer.MAX_VALUE; + } + + /** + * Checks if this property has the same {@link DavPropertyName name} + * and value as the given one. + * + * @param obj the object to compare to + * @return true if the 2 objects are equal; + * false otherwise + */ + @Override + public boolean equals(Object obj) { + if (obj instanceof DavProperty) { + DavProperty prop = (DavProperty) obj; + boolean equalName = getName().equals(prop.getName()); + boolean equalValue = (getValue() == null) ? prop.getValue() == null : getValue().equals(prop.getValue()); + return equalName && equalValue; + } + return false; + } + + + /** + * Return a XML element representation of this property. The value of the + * property will be added as text or as child element. + *
+     * new DavProperty("displayname", "WebDAV Directory").toXml
+     * gives a element like:
+     * <D:displayname>WebDAV Directory</D:displayname>
+     *
+     * new DavProperty("resourcetype", new Element("collection")).toXml
+     * gives a element like:
+     * <D:resourcetype><D:collection/></D:resourcetype>
+     *
+     * Element[] customVals = { new Element("bla", customNamespace), new Element("bli", customNamespace) };
+     * new DavProperty("custom-property", customVals, customNamespace).toXml
+     * gives an element like
+     * <Z:custom-property>
+     *    <Z:bla/>
+     *    <Z:bli/>
+     * </Z:custom-property>
+     * 
+ * + * @return a XML element of this property + * @see org.apache.jackrabbit.webdav.xml.XmlSerializable#toXml(Document) + * @param document + */ + public Element toXml(Document document) { + Element elem = getName().toXml(document); + T value = getValue(); + // todo: improve.... + if (value != null) { + if (value instanceof XmlSerializable) { + elem.appendChild(((XmlSerializable)value).toXml(document)); + } else if (value instanceof Node) { + Node n = document.importNode((Node)value, true); + elem.appendChild(n); + } else if (value instanceof Node[]) { + for (int i = 0; i < ((Node[])value).length; i++) { + Node n = document.importNode(((Node[])value)[i], true); + elem.appendChild(n); + } + } else if (value instanceof Collection) { + for (Object entry : ((Collection) value)) { + if (entry instanceof XmlSerializable) { + elem.appendChild(((XmlSerializable) entry).toXml(document)); + } else if (entry instanceof Node) { + Node n = document.importNode((Node) entry, true); + elem.appendChild(n); + } else { + DomUtil.setText(elem, entry.toString()); + } + } + } else { + DomUtil.setText(elem, value.toString()); + } + } + return elem; + } + + /** + * Returns the name of this property. + * + * @return name + * @see DavProperty#getName() + */ + public DavPropertyName getName() { + return name; + } + + /** + * Return true if this property should be suppressed + * in a PROPFIND/{@link DavConstants#PROPFIND_ALL_PROP DAV:allprop} + * response. See RFC 4918, Section 9.1. + * + * @see org.apache.jackrabbit.webdav.property.DavProperty#isInvisibleInAllprop() + */ + public boolean isInvisibleInAllprop() { + return isInvisibleInAllprop; + } +} Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/property/AbstractDavProperty.java ___________________________________________________________________ Added: svn Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/property/DavProperty.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/property/DavProperty.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/property/DavProperty.java (working copy) @@ -0,0 +1,71 @@ +/* + * 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.webdav.property; + +import org.apache.jackrabbit.webdav.DavConstants; +import org.apache.jackrabbit.webdav.xml.XmlSerializable; + +/** + * The Property class represents a Property of a WebDAV + * resource. The {@link Object#hashCode()} and {@link Object#equals(Object)} methods are + * overridden in a way, such that the name and value of the property are + * respected. This means, a property is equal to another if the names + * and values are equal.
+ * The XML representation of a DavProperty: + *
+ * new DavProperty("displayname", "WebDAV Directory").toXml
+ * gives a element like:
+ * <D:displayname>WebDAV Directory</D:displayname>
+ *
+ * new DavProperty("resourcetype", new Element("collection")).toXml
+ * gives a element like:
+ * <D:resourcetype><D:collection/></D:resourcetype>
+ *
+ * Element[] customVals = { new Element("bla", customNamespace), new Element("bli", customNamespace) };
+ * new DavProperty("custom-property", customVals, customNamespace).toXml
+ * gives an element like
+ * <Z:custom-property>
+ *    <Z:bla/>
+ *    <Z:bli/>
+ * </Z:custom-property>
+ * 
+ */ +public interface DavProperty extends XmlSerializable, DavConstants, PropEntry { + + /** + * Returns the name of this property + * + * @return the name of this property + */ + public DavPropertyName getName(); + + /** + * Returns the value of this property + * + * @return the value of this property + */ + public T getValue(); + + /** + * Return true if this property should be suppressed + * in a PROPFIND/{@link DavConstants#PROPFIND_ALL_PROP DAV:allprop} + * response. See RFC 4918, Section 9.1. + * + * @return true, if this property should be suppressed in a PROPFIND/allprop response + */ + public boolean isInvisibleInAllprop(); +} Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/property/DavProperty.java ___________________________________________________________________ Added: svn Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/property/DavPropertyIterator.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/property/DavPropertyIterator.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/property/DavPropertyIterator.java (working copy) @@ -0,0 +1,34 @@ +/* + * 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.webdav.property; + +import java.util.Iterator; +import java.util.NoSuchElementException; + +/** + * The DavPropertyIterator extends the Iterator by + * a property specific next() method. + */ +public interface DavPropertyIterator extends Iterator> { + /** + * Returns the next Property. + * + * @return the next Property in the iteration. + * @throws java.util.NoSuchElementException if iteration has no more elements. + */ + public DavProperty nextProperty() throws NoSuchElementException; +} Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/property/DavPropertyIterator.java ___________________________________________________________________ Added: svn Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/property/DavPropertyName.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/property/DavPropertyName.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/property/DavPropertyName.java (working copy) @@ -0,0 +1,206 @@ +/* + * 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.webdav.property; + +import org.apache.jackrabbit.webdav.DavConstants; +import org.apache.jackrabbit.webdav.xml.DomUtil; +import org.apache.jackrabbit.webdav.xml.Namespace; +import org.apache.jackrabbit.webdav.xml.XmlSerializable; +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +import java.util.HashMap; +import java.util.Map; + +/** + * The DavPropertyName class reflects a WebDAV property name. It + * holds together the local name of the property and its namespace. + */ +public class DavPropertyName implements DavConstants, XmlSerializable, PropEntry { + + /** internal 'cache' of created property names */ + private static final Map> cache = new HashMap>(); + + /* some standard webdav property (that have #PCDATA) */ + public static final DavPropertyName CREATIONDATE = DavPropertyName.create(PROPERTY_CREATIONDATE); + public static final DavPropertyName DISPLAYNAME = DavPropertyName.create(PROPERTY_DISPLAYNAME); + public static final DavPropertyName GETCONTENTLANGUAGE = DavPropertyName.create(PROPERTY_GETCONTENTLANGUAGE); + public static final DavPropertyName GETCONTENTLENGTH = DavPropertyName.create(PROPERTY_GETCONTENTLENGTH); + public static final DavPropertyName GETCONTENTTYPE = DavPropertyName.create(PROPERTY_GETCONTENTTYPE); + public static final DavPropertyName GETETAG = DavPropertyName.create(PROPERTY_GETETAG); + public static final DavPropertyName GETLASTMODIFIED = DavPropertyName.create(PROPERTY_GETLASTMODIFIED); + + /* some standard webdav property (that have other elements) */ + public static final DavPropertyName LOCKDISCOVERY = DavPropertyName.create(PROPERTY_LOCKDISCOVERY); + public static final DavPropertyName RESOURCETYPE = DavPropertyName.create(PROPERTY_RESOURCETYPE); + public static final DavPropertyName SOURCE = DavPropertyName.create(PROPERTY_SOURCE); + public static final DavPropertyName SUPPORTEDLOCK = DavPropertyName.create(PROPERTY_SUPPORTEDLOCK); + + /* property use by microsoft that are not specified in the RFC 2518 */ + public static final DavPropertyName ISCOLLECTION = DavPropertyName.create("iscollection"); + + /** the name of the property */ + private final String name; + + /** the namespace of the property */ + private final Namespace namespace; + + /** + * Creates a new DavPropertyName with the given name and + * Namespace. + * + * @param name The local name of the new property name + * @param namespace The namespace of the new property name + * + * @return The WebDAV property name + */ + public synchronized static DavPropertyName create(String name, Namespace namespace) { + + // get (or create) map for the given namespace + Map map = cache.get(namespace); + if (map == null) { + map = new HashMap(); + cache.put(namespace, map); + } + // get (or create) property name object + DavPropertyName ret = map.get(name); + if (ret == null) { + if (namespace.equals(NAMESPACE)) { + // ensure prefix for default 'DAV:' namespace + namespace = NAMESPACE; + } + ret = new DavPropertyName(name, namespace); + map.put(name, ret); + } + return ret; + } + + /** + * Creates a new DavPropertyName with the given local name + * and the default WebDAV {@link DavConstants#NAMESPACE namespace}. + * + * @param name The local name of the new property name + * + * @return The WebDAV property name + */ + public synchronized static DavPropertyName create(String name) { + return create(name, NAMESPACE); + } + + /** + * Create a new DavPropertyName with the name and namespace + * of the given Xml element. + * + * @param nameElement + * @return DavPropertyName instance + */ + public synchronized static DavPropertyName createFromXml(Element nameElement) { + if (nameElement == null) { + throw new IllegalArgumentException("Cannot build DavPropertyName from a 'null' element."); + } + String ns = nameElement.getNamespaceURI(); + if (ns == null) { + return create(nameElement.getLocalName(), Namespace.EMPTY_NAMESPACE); + } else { + return create(nameElement.getLocalName(), Namespace.getNamespace(nameElement.getPrefix(), ns)); + } + } + + /** + * Creates a new DavPropertyName with the given name and + * Namespace. + * + * @param name The local name of the new property name + * @param namespace The namespace of the new property name + */ + private DavPropertyName(String name, Namespace namespace) { + if (name == null || namespace == null) { + throw new IllegalArgumentException("Name and namespace must not be 'null' for a DavPropertyName."); + } + this.name = name; + this.namespace = namespace; + } + + /** + * Return the name of this DavPropertyName. + * + * @return name + */ + public String getName() { + return name; + } + + /** + * Return the namespace of this DavPropertyName. + * + * @return namespace + */ + public Namespace getNamespace() { + return namespace; + } + + /** + * Computes the hash code using this properties name and namespace. + * + * @return the hash code + */ + @Override + public int hashCode() { + return (name.hashCode() + namespace.hashCode()) % Integer.MAX_VALUE; + } + + /** + * Checks if this property has the same name and namespace as the + * given one. + * + * @param obj the object to compare to + * + * @return true if the 2 objects are equal; + * false otherwise + */ + @Override + public boolean equals(Object obj) { + if (obj instanceof DavPropertyName) { + DavPropertyName propName = (DavPropertyName) obj; + return name.equals(propName.name) && namespace.equals(propName.namespace); + } + return false; + } + + /** + * Returns a string representation of this property suitable for debugging + * + * @return a human readable string representation + */ + @Override + public String toString() { + return DomUtil.getExpandedName(name, namespace); + } + + /** + * Creates a element with the name and namespace of this + * DavPropertyName. + * + * @return A element with the name and namespace of this + * DavPropertyName. + * @param document + */ + public Element toXml(Document document) { + return DomUtil.createElement(document, name, namespace); + } +} + Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/property/DavPropertyName.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/property/DavPropertyNameIterator.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/property/DavPropertyNameIterator.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/property/DavPropertyNameIterator.java (working copy) @@ -0,0 +1,28 @@ +/* + * 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.webdav.property; + +import java.util.Iterator; + +/** + * DavPropertyNameIterator... + */ +public interface DavPropertyNameIterator extends Iterator { + + public DavPropertyName nextPropertyName(); + +} Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/property/DavPropertyNameIterator.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-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/property/DavPropertyNameSet.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/property/DavPropertyNameSet.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/property/DavPropertyNameSet.java (working copy) @@ -0,0 +1,203 @@ +/* + * 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.webdav.property; + +import org.apache.jackrabbit.webdav.xml.DomUtil; +import org.apache.jackrabbit.webdav.xml.ElementIterator; +import org.apache.jackrabbit.webdav.xml.Namespace; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.w3c.dom.Element; + +import java.util.Collection; +import java.util.HashSet; +import java.util.Iterator; +import java.util.Set; + +/** + * DavPropertyNameSet represents a Set of {@link DavPropertyName} + * objects. + */ +public class DavPropertyNameSet extends PropContainer + implements Iterable { + + private static Logger log = LoggerFactory.getLogger(DavPropertyNameSet.class); + private final Set set = new HashSet(); + + /** + * Create a new empty set. + */ + public DavPropertyNameSet() { + } + + /** + * Create a new DavPropertyNameSet with the given initial values. + * + * @param initialSet + */ + public DavPropertyNameSet(DavPropertyNameSet initialSet) { + addAll(initialSet); + } + + /** + * Create a new DavPropertyNameSet from the given DAV:prop + * element. + * + * @param propElement + * @throws IllegalArgumentException if the specified element is null + * or is not a DAV:prop element. + */ + public DavPropertyNameSet(Element propElement) { + if (!DomUtil.matches(propElement, XML_PROP, NAMESPACE)) { + throw new IllegalArgumentException("'DAV:prop' element expected."); + } + + // fill the set + ElementIterator it = DomUtil.getChildren(propElement); + while (it.hasNext()) { + add(DavPropertyName.createFromXml(it.nextElement())); + } + } + + /** + * Adds the specified {@link DavPropertyName} object to this + * set if it is not already present. + * + * @param propertyName element to be added to this set. + * @return {@code true} if the set did not already contain the specified + * element. + */ + public boolean add(DavPropertyName propertyName) { + return set.add(propertyName); + } + + /** + * Creates a DavPropertyName from the given parameters and add it to this set. + * + * @param localName + * @param namespace + * @return {@code true} if the set did not already contain the specified + * property name. + */ + public boolean add(String localName, Namespace namespace) { + return set.add(DavPropertyName.create(localName, namespace)); + } + + /** + * Add the property names contained in the specified set to this set. + * + * @param propertyNames + * @return true if the set has been modified by this call. + */ + public boolean addAll(DavPropertyNameSet propertyNames) { + return set.addAll(propertyNames.set); + } + + /** + * Removes the specified {@link DavPropertyName} object from this set. + * + * @param propertyName + * @return true if the given property name could be removed. + * @see HashSet#remove(Object) + */ + public boolean remove(DavPropertyName propertyName) { + return set.remove(propertyName); + } + + /** + * @return Iterator over all DavPropertyNames contained in this + * set. + */ + public DavPropertyNameIterator iterator() { + return new PropertyNameIterator(); + } + + //------------------------------------------------------< PropContainer >--- + /** + * @see PropContainer#contains(DavPropertyName) + */ + @Override + public boolean contains(DavPropertyName name) { + return set.contains(name); + } + + /** + * @param contentEntry NOTE that an instance of DavPropertyName + * in order to successfully add the given entry. + * @return true if contentEntry is an instance of DavPropertyName + * that could be added to this set. False otherwise. + * @see PropContainer#addContent(Object) + */ + @Override + public boolean addContent(PropEntry contentEntry) { + if (contentEntry instanceof DavPropertyName) { + return add((DavPropertyName) contentEntry); + } + log.debug("DavPropertyName object expected. Found: " + contentEntry.getClass().toString()); + return false; + } + + /** + * @see PropContainer#isEmpty() + */ + @Override + public boolean isEmpty() { + return set.isEmpty(); + } + + /** + * @see PropContainer#getContentSize() + */ + @Override + public int getContentSize() { + return set.size(); + } + + /** + * @see PropContainer#getContent() + */ + @Override + public Collection getContent() { + return set; + } + + //--------------------------------------------------------< inner class >--- + private class PropertyNameIterator implements DavPropertyNameIterator { + + private Iterator iter; + + private PropertyNameIterator() { + this.iter = set.iterator(); + } + + public DavPropertyName nextPropertyName() { + return iter.next(); + } + + public void remove() { + iter.remove(); + } + + public boolean hasNext() { + return iter.hasNext(); + } + + public DavPropertyName next() { + return iter.next(); + } + } +} Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/property/DavPropertyNameSet.java ___________________________________________________________________ Added: svn Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/property/DavPropertySet.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/property/DavPropertySet.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/property/DavPropertySet.java (working copy) @@ -0,0 +1,300 @@ +/* + * 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.webdav.property; + +import org.apache.jackrabbit.webdav.xml.Namespace; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.Collection; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; +import java.util.NoSuchElementException; + +/** + * The DavPropertySet class represents a set of WebDAV + * property. + */ +public class DavPropertySet extends PropContainer + implements Iterable> { + + private static Logger log = LoggerFactory.getLogger(DavPropertySet.class); + + /** + * the set of property + */ + private final Map> map = new HashMap>(); + + /** + * Adds a new property to this set. + * + * @param property The property to add + * + * @return The previously assigned property or null. + */ + public DavProperty add(DavProperty property) { + return map.put(property.getName(), property); + } + + /** + * + * @param pset Properties to add + */ + public void addAll(DavPropertySet pset) { + map.putAll(pset.map); + } + + /** + * Retrieves the property with the specified name and the + * default WebDAV {@link org.apache.jackrabbit.webdav.DavConstants#NAMESPACE namespace}. + * + * @param name The name of the property to retrieve + * + * @return The desired property or null + */ + public DavProperty get(String name) { + return get(DavPropertyName.create(name)); + } + + /** + * Retrieves the property with the specified name and + * namespace. + * + * @param name The name of the property to retrieve + * @param namespace The namespace of the property to retrieve + * + * @return The desired property or null + */ + public DavProperty get(String name, Namespace namespace) { + return get(DavPropertyName.create(name, namespace)); + } + + /** + * Retrieves the property with the specified name + * + * @param name The webdav property name of the property to retrieve + * + * @return The desired property or null + */ + public DavProperty get(DavPropertyName name) { + return map.get(name); + } + + + /** + * Removes the indicated property from this set. + * + * @param name The webdav property name to remove + * + * @return The removed property or null + */ + public DavProperty remove(DavPropertyName name) { + return map.remove(name); + } + + /** + * Removes the property with the specified name and the + * default WebDAV {@link org.apache.jackrabbit.webdav.DavConstants#NAMESPACE namespace}. + * + * @param name The name of the property to remove + * + * @return The removed property or null + */ + public DavProperty remove(String name) { + return remove(DavPropertyName.create(name)); + } + + /** + * Removes the property with the specified name and + * namespace from this set. + * + * @param name The name of the property to remove + * @param namespace The namespace of the property to remove + * + * @return The removed property or null + */ + public DavProperty remove(String name, Namespace namespace) { + return remove(DavPropertyName.create(name, namespace)); + } + + /** + * Returns an iterator over all property in this set. + * + * @return An iterator over {@link DavProperty}. + */ + public DavPropertyIterator iterator() { + return new PropIter(); + } + + /** + * Returns an iterator over all those property in this set, that have the + * indicated namespace. + * + * @param namespace The namespace of the property in the iteration. + * + * @return An iterator over {@link DavProperty}. + */ + public DavPropertyIterator iterator(Namespace namespace) { + return new PropIter(namespace); + } + + /** + * Return the names of all properties present in this set. + * + * @return array of {@link DavPropertyName property names} present in this set. + */ + public DavPropertyName[] getPropertyNames() { + return map.keySet().toArray(new DavPropertyName[map.keySet().size()]); + } + + //------------------------------------------------------< PropContainer >--- + /** + * Checks if this set contains the property with the specified name. + * + * @param name The name of the property + * @return true if this set contains the property; + * false otherwise. + * @see PropContainer#contains(DavPropertyName) + */ + @Override + public boolean contains(DavPropertyName name) { + return map.containsKey(name); + } + + /** + * @param contentEntry NOTE, that the given object must be an instance of + * DavProperty in order to be successfully added to this set. + * @return true if the specified object is an instance of DavProperty + * and false otherwise. + * @see PropContainer#addContent(PropEntry) + */ + @Override + public boolean addContent(PropEntry contentEntry) { + if (contentEntry instanceof DavProperty) { + add((DavProperty) contentEntry); + return true; + } + log.debug("DavProperty object expected. Found: " + contentEntry.getClass().toString()); + return false; + } + + /** + * @see PropContainer#isEmpty() + */ + @Override + public boolean isEmpty() { + return map.isEmpty(); + } + + /** + * @see PropContainer#getContentSize() + */ + @Override + public int getContentSize() { + return map.size(); + } + + /** + * @see PropContainer#getContent() + */ + @Override + public Collection getContent() { + return map.values(); + } + + //---------------------------------------------------------- Inner class --- + /** + * Implementation of a DavPropertyIterator that returns webdav property. + * Additionally, it can only return property with the given namespace. + */ + private class PropIter implements DavPropertyIterator { + + /** the namespace to match against */ + private final Namespace namespace; + + /** the internal iterator */ + private final Iterator> iterator; + + /** the next property to return */ + private DavProperty next; + + /** + * Creates a new property iterator. + */ + private PropIter() { + this(null); + } + + /** + * Creates a new iterator with the given namespace + * @param namespace The namespace to match against + */ + private PropIter(Namespace namespace) { + this.namespace = namespace; + iterator = map.values().iterator(); + seek(); + } + + /** + * @see DavPropertyIterator#nextProperty(); + */ + public DavProperty nextProperty() throws NoSuchElementException { + if (next==null) { + throw new NoSuchElementException(); + } + DavProperty ret = next; + seek(); + return ret; + } + + /** + * @see DavPropertyIterator#hasNext(); + */ + public boolean hasNext() { + return next!=null; + } + + /** + * @see DavPropertyIterator#next(); + */ + public DavProperty next() { + return nextProperty(); + } + + /** + * @see DavPropertyIterator#remove(); + */ + public void remove() { + throw new UnsupportedOperationException(); + } + + /** + * Seeks for the next valid property + */ + private void seek() { + while (iterator.hasNext()) { + next = iterator.next(); + if (namespace == null || namespace.equals(next.getName().getNamespace())) { + return; + } + } + next = null; + } + } +} + Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/property/DavPropertySet.java ___________________________________________________________________ Added: svn Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/property/DefaultDavProperty.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/property/DefaultDavProperty.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/property/DefaultDavProperty.java (working copy) @@ -0,0 +1,144 @@ +/* + * 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.webdav.property; + +import org.apache.jackrabbit.webdav.xml.DomUtil; +import org.apache.jackrabbit.webdav.xml.Namespace; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.w3c.dom.Element; +import org.w3c.dom.Node; + +import java.util.List; + +/** + * DefaultDavProperty... + */ +public class DefaultDavProperty extends AbstractDavProperty { + + private static Logger log = LoggerFactory.getLogger(DefaultDavProperty.class); + + /** + * the value of the property + */ + private final T value; + + /** + * Creates a new WebDAV property with the given namespace, name and value. + * If the property is intended to be protected the isProtected flag must + * be set to true. + * + * @param name the name of the property + * @param value the value of the property + * @param namespace the namespace of the property + * @param isInvisibleInAllprop A value of true, defines this property to be protected. + * It will not be returned in a {@link org.apache.jackrabbit.webdav.DavConstants#PROPFIND_ALL_PROP DAV:allprop} + * PROPFIND request and cannot be set/removed with a PROPPATCH request. + */ + public DefaultDavProperty(String name, T value, Namespace namespace, boolean isInvisibleInAllprop) { + super(DavPropertyName.create(name, namespace), isInvisibleInAllprop); + this.value = value; + } + + /** + * Creates a new non-protected WebDAV property with the given namespace, name + * and value. + * + * @param name the name of the property + * @param value the value of the property + * @param namespace the namespace of the property + */ + public DefaultDavProperty(String name, T value, Namespace namespace) { + this(name, value, namespace, false); + } + + /** + * Creates a new WebDAV property with the given DavPropertyName + * and value. If the property is meant to be protected the 'isProtected' + * flag must be set to true. + * + * @param name the name of the property + * @param value the value of the property + * @param isInvisibleInAllprop A value of true, defines this property to be protected. + * It will not be returned in a {@link org.apache.jackrabbit.webdav.DavConstants#PROPFIND_ALL_PROP DAV:allprop} + * PROPFIND request and cannot be set/removed with a PROPPATCH request. + */ + public DefaultDavProperty(DavPropertyName name, T value, boolean isInvisibleInAllprop) { + super(name, isInvisibleInAllprop); + this.value = value; + } + + /** + * Creates a new non- protected WebDAV property with the given + * DavPropertyName and value. + * + * @param name the name of the property + * @param value the value of the property + */ + public DefaultDavProperty(DavPropertyName name, T value) { + this(name, value, false); + } + + /** + * Returns the value of this property + * + * @return the value of this property + */ + public T getValue() { + return value; + } + + /** + * Create a new DefaultDavProperty instance from the given Xml + * element. Name and namespace of the element are building the {@link DavPropertyName}, + * while the element's content forms the property value. The following logic + * is applied: + *
+     * - empty Element           -> null value
+     * - single Text content     -> String value
+     * - single non-Text content -> Element.getContent(0) is used as value
+     * - other: List obtained from Element.getContent() is used as value
+     * 
+ * + * @param propertyElement + * @return + */ + public static DefaultDavProperty createFromXml(Element propertyElement) { + if (propertyElement == null) { + throw new IllegalArgumentException("Cannot create a new DavProperty from a 'null' element."); + } + DavPropertyName name = DavPropertyName.createFromXml(propertyElement); + DefaultDavProperty prop; + + if (!DomUtil.hasContent(propertyElement)) { + prop = new DefaultDavProperty(name, null, false); + } else { + List c = DomUtil.getContent(propertyElement); + if (c.size() == 1) { + Node n = c.get(0); + if (n instanceof Element) { + prop = new DefaultDavProperty(name, (Element) n, false); + } else { + prop = new DefaultDavProperty(name, n.getNodeValue(), false); + } + } else /* size > 1 */ { + prop = new DefaultDavProperty>(name, c, false); + } + } + return prop; + } +} \ No newline at end of file Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/property/DefaultDavProperty.java ___________________________________________________________________ Added: svn Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/property/HrefProperty.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/property/HrefProperty.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/property/HrefProperty.java (working copy) @@ -0,0 +1,159 @@ +/* + * 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.webdav.property; + +import org.apache.jackrabbit.webdav.xml.DomUtil; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +/** + * HrefProperty is an extension to the common {@link DavProperty}. + * The String representation of the property value is always displayed as text + * inside an extra 'href' element. If the value is a String array each array + * element is added as text to a separate 'href' element. + * + * @see org.apache.jackrabbit.webdav.DavConstants#XML_HREF + * @see org.apache.jackrabbit.webdav.property.DavProperty#getValue() + */ +public class HrefProperty extends AbstractDavProperty { + + private static Logger log = LoggerFactory.getLogger(HrefProperty.class); + + private final String[] value; + + /** + * Creates a new WebDAV property with the given DavPropertyName + * + * @param name the name of the property + * @param value the value of the property + * @param isInvisibleInAllprop A value of true, defines this property to be invisible in PROPFIND/allprop + * It will not be returned in a {@link org.apache.jackrabbit.webdav.DavConstants#PROPFIND_ALL_PROP DAV:allprop} + * PROPFIND request. + */ + public HrefProperty(DavPropertyName name, String value, boolean isInvisibleInAllprop) { + super(name, isInvisibleInAllprop); + this.value = new String[]{value}; + } + + /** + * Creates a new WebDAV property with the given DavPropertyName + * + * @param name the name of the property + * @param value the value of the property + * @param isInvisibleInAllprop A value of true, defines this property to be invisible in PROPFIND/allprop + * It will not be returned in a {@link org.apache.jackrabbit.webdav.DavConstants#PROPFIND_ALL_PROP DAV:allprop} + * PROPFIND request. + */ + public HrefProperty(DavPropertyName name, String[] value, boolean isInvisibleInAllprop) { + super(name, isInvisibleInAllprop); + this.value = value; + } + + /** + * Create a new HrefProperty from the specified property. + * Please note, that the property must have a List value + * object, consisting of {@link #XML_HREF href} Element entries. + * + * @param prop + */ + public HrefProperty(DavProperty prop) { + super(prop.getName(), prop.isInvisibleInAllprop()); + if (prop instanceof HrefProperty) { + // already an HrefProperty: no parsing required + this.value = ((HrefProperty)prop).value; + } else { + // assume property has be built from xml + ArrayList hrefList = new ArrayList(); + Object val = prop.getValue(); + if (val instanceof List) { + for (Object entry : ((List) val)) { + if (entry instanceof Element && XML_HREF.equals(((Element) entry).getLocalName())) { + String href = DomUtil.getText((Element) entry); + if (href != null) { + hrefList.add(href); + } else { + log.warn("Valid DAV:href element expected instead of " + entry.toString()); + } + } else { + log.warn("DAV: href element expected in the content of " + getName().toString()); + } + } + } else if (val instanceof Element && XML_HREF.equals(((Element)val).getLocalName())) { + String href = DomUtil.getTextTrim((Element)val); + if (href != null) { + hrefList.add(href); + } else { + log.warn("Valid DAV:href element expected instead of " + val.toString()); + } + } + value = hrefList.toArray(new String[hrefList.size()]); + } + } + + /** + * Returns an Xml element with the following form: + *
+     * <Z:name>
+     *    <DAV:href>value</DAV:href/>
+     * </Z:name>
+     * 
+ * where Z: represents the prefix of the namespace defined with the initial + * webdav property name. + * + * @return Xml representation + * @see org.apache.jackrabbit.webdav.xml.DomUtil#hrefToXml(String,org.w3c.dom.Document) + * @param document + */ + @Override + public Element toXml(Document document) { + Element elem = getName().toXml(document); + String[] value = getValue(); + if (value != null) { + for (String href : value) { + elem.appendChild(DomUtil.hrefToXml(href, document)); + } + } + return elem; + } + + /** + * Returns an array of String. + * + * @return an array of String. + * @see DavProperty#getValue() + */ + public String[] getValue() { + return value; + } + + /** + * Return an list of String containing the text of those DAV:href elements + * that would be returned as child elements of this property on + * {@link org.apache.jackrabbit.webdav.xml.XmlSerializable#toXml(Document)} + * + * @return list of href String + */ + public List getHrefs() { + return (value != null) ? Arrays.asList(value) : new ArrayList(); + } +} Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/property/HrefProperty.java ___________________________________________________________________ Added: svn Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/property/PropContainer.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/property/PropContainer.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/property/PropContainer.java (working copy) @@ -0,0 +1,119 @@ +/* + * 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.webdav.property; + +import org.apache.jackrabbit.webdav.DavConstants; +import org.apache.jackrabbit.webdav.xml.DomUtil; +import org.apache.jackrabbit.webdav.xml.XmlSerializable; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +import java.util.Collection; + +/** + * PropContainer... + */ +public abstract class PropContainer implements XmlSerializable, DavConstants { + + private static Logger log = LoggerFactory.getLogger(PropContainer.class); + + /** + * Tries to add the specified object to the PropContainer and + * returns a boolean indicating whether the content could be added to the + * internal set/map. + * + * @param contentEntry + * @return true if the object could be added; false otherwise + * @deprecated Use {@link #addContent(PropEntry)} instead. + */ + public boolean addContent(Object contentEntry) { + if (contentEntry instanceof PropEntry) { + return addContent((PropEntry) contentEntry); + } else { + return false; + } + } + + /** + * Tries to add the specified entry to the PropContainer and + * returns a boolean indicating whether the content could be added to the + * internal set/map. + * + * @param contentEntry + * @return true if the object could be added; false otherwise + */ + public abstract boolean addContent(PropEntry contentEntry); + + /** + * Returns true if the PropContainer does not yet contain any content elements. + * + * @return true if this container is empty. + */ + public abstract boolean isEmpty(); + + /** + * Returns the number of property related content elements that are present + * in this PropContainer. + * + * @return number of content elements + */ + public abstract int getContentSize(); + + /** + * Returns the collection that contains all the content elements of this + * PropContainer. + * + * @return collection representing the contents of this PropContainer. + */ + public abstract Collection getContent(); + + /** + * Returns true if this PropContainer contains a content element + * that matches the given DavPropertyName. + * + * @param name + * @return true if any of the content elements (be it a DavProperty or a + * DavPropertyName only) matches the given name. + */ + public abstract boolean contains(DavPropertyName name); + + /** + * Returns the xml representation of a property related set with the + * following format: + *
+     * <!ELEMENT prop (ANY) >
+     * where ANY consists of a list of elements each reflecting the xml
+     * representation of the entries returned by {@link #getContent()}.
+     * 
+ * + * @see XmlSerializable#toXml(Document) + */ + public Element toXml(Document document) { + Element prop = DomUtil.createElement(document, XML_PROP, NAMESPACE); + for (Object content : getContent()) { + if (content instanceof XmlSerializable) { + prop.appendChild(((XmlSerializable) content).toXml(document)); + } else { + log.debug("Unexpected content in PropContainer: should be XmlSerializable."); + } + } + return prop; + } + +} Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/property/PropContainer.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-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/property/PropEntry.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/property/PropEntry.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/property/PropEntry.java (working copy) @@ -0,0 +1,25 @@ +/* + * 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.webdav.property; + +/** + * Marker interface used to flag the different types of entries that form + * part of a PROPPATCH request and define the possible entries for a + * PropContainer. + */ +public interface PropEntry { +} Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/property/PropEntry.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-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/property/PropfindInfo.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/property/PropfindInfo.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/property/PropfindInfo.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.webdav.property; + +import org.apache.jackrabbit.webdav.DavConstants; +import org.apache.jackrabbit.webdav.xml.DomUtil; +import org.apache.jackrabbit.webdav.xml.XmlSerializable; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.Node; + +public class PropfindInfo implements XmlSerializable { + + private final int propfindType; + private final DavPropertyNameSet propNameSet; + + public PropfindInfo(int propfindType, DavPropertyNameSet propNameSet) { + this.propfindType = propfindType; + this.propNameSet = propNameSet; + } + + @Override + public Element toXml(Document document) { + Element propfind = DomUtil.createElement(document, DavConstants.XML_PROPFIND, DavConstants.NAMESPACE); + + // fill the propfind element + switch (propfindType) { + case DavConstants.PROPFIND_ALL_PROP: + propfind.appendChild(DomUtil.createElement(document, DavConstants.XML_ALLPROP, DavConstants.NAMESPACE)); + break; + + case DavConstants.PROPFIND_PROPERTY_NAMES: + propfind.appendChild(DomUtil.createElement(document, DavConstants.XML_PROPNAME, DavConstants.NAMESPACE)); + break; + + case DavConstants.PROPFIND_BY_PROPERTY: + if (propNameSet == null) { + // name set missing, ask for a property that is known to + // exist + Element prop = DomUtil.createElement(document, DavConstants.XML_PROP, DavConstants.NAMESPACE); + Element resourcetype = DomUtil.createElement(document, DavConstants.PROPERTY_RESOURCETYPE, + DavConstants.NAMESPACE); + prop.appendChild(resourcetype); + propfind.appendChild(prop); + } else { + propfind.appendChild(propNameSet.toXml(document)); + } + break; + + case DavConstants.PROPFIND_ALL_PROP_INCLUDE: + propfind.appendChild(DomUtil.createElement(document, DavConstants.XML_ALLPROP, DavConstants.NAMESPACE)); + if (propNameSet != null && !propNameSet.isEmpty()) { + Element include = DomUtil.createElement(document, DavConstants.XML_INCLUDE, DavConstants.NAMESPACE); + Element prop = propNameSet.toXml(document); + for (Node c = prop.getFirstChild(); c != null; c = c.getNextSibling()) { + // copy over the children of to + // element + include.appendChild(c.cloneNode(true)); + } + propfind.appendChild(include); + } + break; + + default: + throw new IllegalArgumentException("unknown propfind type"); + } + + return propfind; + } +} Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/property/PropfindInfo.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/property/ProppatchInfo.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/property/ProppatchInfo.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/property/ProppatchInfo.java (working copy) @@ -0,0 +1,128 @@ +/* + * 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.webdav.property; + +import java.util.List; + +import org.apache.jackrabbit.webdav.DavConstants; +import org.apache.jackrabbit.webdav.xml.DomUtil; +import org.apache.jackrabbit.webdav.xml.XmlSerializable; +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +public class ProppatchInfo implements XmlSerializable { + + private final List changeList; + private final DavPropertySet setProperties; + private final DavPropertyNameSet removeProperties; + + private final DavPropertyNameSet propertyNames = new DavPropertyNameSet(); + + public ProppatchInfo(List changeList) { + if (changeList == null || changeList.isEmpty()) { + throw new IllegalArgumentException("PROPPATCH cannot be executed without properties to be set or removed."); + } + this.changeList = changeList; + this.setProperties = null; + this.removeProperties = null; + for (PropEntry entry : changeList) { + if (entry instanceof DavPropertyName) { + // DAV:remove + this.propertyNames.add((DavPropertyName) entry); + } else if (entry instanceof DavProperty) { + // DAV:set + DavProperty setProperty = (DavProperty) entry; + this.propertyNames.add(setProperty.getName()); + } else { + throw new IllegalArgumentException("ChangeList may only contain DavPropertyName and DavProperty elements."); + } + } + } + + public ProppatchInfo(DavPropertySet setProperties, DavPropertyNameSet removeProperties) { + if (setProperties == null || removeProperties == null) { + throw new IllegalArgumentException("Neither setProperties nor removeProperties must be null."); + } + if (setProperties.isEmpty() && removeProperties.isEmpty()) { + throw new IllegalArgumentException("Either setProperties or removeProperties can be empty; not both of them."); + } + this.changeList = null; + this.setProperties = setProperties; + this.removeProperties = removeProperties; + this.propertyNames.addAll(removeProperties); + for (DavPropertyName setName : setProperties.getPropertyNames()) { + this.propertyNames.add(setName); + } + } + + public DavPropertyNameSet getAffectedProperties() { + if (this.propertyNames.isEmpty()) { + throw new IllegalStateException("must be called after toXml()"); + } + return this.propertyNames; + } + + @Override + public Element toXml(Document document) { + Element proppatch = DomUtil.createElement(document, DavConstants.XML_PROPERTYUPDATE, DavConstants.NAMESPACE); + + if (changeList != null) { + Element propElement = null; + boolean isSet = false; + for (Object entry : changeList) { + if (entry instanceof DavPropertyName) { + // DAV:remove + DavPropertyName removeName = (DavPropertyName) entry; + if (propElement == null || isSet) { + isSet = false; + propElement = getPropElement(proppatch, false); + } + propElement.appendChild(removeName.toXml(document)); + } else if (entry instanceof DavProperty) { + // DAV:set + DavProperty setProperty = (DavProperty) entry; + if (propElement == null || !isSet) { + isSet = true; + propElement = getPropElement(proppatch, true); + } + propElement.appendChild(setProperty.toXml(document)); + } else { + throw new IllegalArgumentException("ChangeList may only contain DavPropertyName and DavProperty elements."); + } + } + } else { + // DAV:set + if (!setProperties.isEmpty()) { + Element set = DomUtil.addChildElement(proppatch, DavConstants.XML_SET, DavConstants.NAMESPACE); + set.appendChild(setProperties.toXml(document)); + } + // DAV:remove + if (!removeProperties.isEmpty()) { + Element remove = DomUtil.addChildElement(proppatch, DavConstants.XML_REMOVE, DavConstants.NAMESPACE); + remove.appendChild(removeProperties.toXml(document)); + } + } + + return proppatch; + } + + private Element getPropElement(Element propUpdate, boolean isSet) { + Element updateEntry = DomUtil.addChildElement(propUpdate, isSet ? DavConstants.XML_SET : DavConstants.XML_REMOVE, + DavConstants.NAMESPACE); + return DomUtil.addChildElement(updateEntry, DavConstants.XML_PROP, DavConstants.NAMESPACE); + } +} Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/property/ProppatchInfo.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/property/ResourceType.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/property/ResourceType.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/property/ResourceType.java (working copy) @@ -0,0 +1,205 @@ +/* + * 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.webdav.property; + +import org.apache.jackrabbit.webdav.version.DeltaVConstants; +import org.apache.jackrabbit.webdav.xml.DomUtil; +import org.apache.jackrabbit.webdav.xml.Namespace; +import org.apache.jackrabbit.webdav.xml.XmlSerializable; +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +/** + * The ResourceType class represents the webdav resource + * type property. The property may contain multiple resource type + * values. Predefined resource types are those defined by RFC2518 and RFC3253: + *
    + *
  • {@link #DEFAULT_RESOURCE the empty default resource type},
  • + *
  • '{@link #COLLECTION DAV:collection}',
  • + *
  • '{@link #VERSION_HISTORY DAV:version-history}',
  • + *
  • '{@link #ACTIVITY DAV:activity}',
  • + *
  • '{@link #BASELINE DAV:baseline}',
  • + *
+ */ +public class ResourceType extends AbstractDavProperty> { + + /** + * The default resource type + */ + public static final int DEFAULT_RESOURCE = 0; + + /** + * The collection resource type + */ + public static final int COLLECTION = DEFAULT_RESOURCE + 1; + + /** + * The version-history resource type + */ + public static final int VERSION_HISTORY = COLLECTION + 1; + + /** + * The activity resource type + */ + public static final int ACTIVITY = VERSION_HISTORY + 1; + + /** + * The baseline resource type + */ + public static final int BASELINE = ACTIVITY + 1; + + /** + * Array containing all possible resourcetype elements + */ + private static final List NAMES = new ArrayList(); + static { + NAMES.add(null); + NAMES.add(new TypeName(XML_COLLECTION, NAMESPACE)); + NAMES.add(new TypeName(DeltaVConstants.XML_VERSION_HISTORY, DeltaVConstants.NAMESPACE)); + NAMES.add(new TypeName(DeltaVConstants.XML_ACTIVITY, DeltaVConstants.NAMESPACE)); + NAMES.add(new TypeName(DeltaVConstants.XML_BASELINE, DeltaVConstants.NAMESPACE)); + } + + private final int[] resourceTypes; + + /** + * Create a single-valued resource type property + */ + public ResourceType(int resourceType) { + this(new int[] { resourceType }); + } + + /** + * Create a multi-valued resource type property + */ + public ResourceType(int[] resourceTypes) { + super(DavPropertyName.RESOURCETYPE, false); + for (int resourceType : resourceTypes) { + if (!isValidResourceType(resourceType)) { + throw new IllegalArgumentException("Invalid resource type '" + resourceType + "'."); + } + } + this.resourceTypes = resourceTypes; + } + + /** + * Returns a Set of resource types each implementing the XmlSerializable + * interface. + * + * @return a Set of resource types representing this property. + * @see DavProperty#getValue() + */ + public Set getValue() { + Set rTypes = new HashSet(); + for (int resourceType : resourceTypes) { + TypeName n = NAMES.get(resourceType); + if (n != null) { + rTypes.add(n); + } + } + return rTypes; + } + + /** + * Returns the resource types specified with the constructor. + * + * @return resourceTypes + */ + public int[] getResourceTypes() { + return resourceTypes; + } + + /** + * Returns true if the given integer defines a valid resource type. + * + * @param resourceType to be validated. + * @return true if this is one of the predefined resource types + */ + private static boolean isValidResourceType(int resourceType) { + if (resourceType < DEFAULT_RESOURCE || resourceType > NAMES.size()-1) { + return false; + } + return true; + } + + /** + * Register an additional resource type + * + * @param name + * @param namespace + * @return int to be used for creation of a new ResourceType property + * that contains this type. + * @throws IllegalArgumentException if the given element is null or + * if the registration fails for another reason. + */ + public static int registerResourceType(String name, Namespace namespace) { + if (name == null || namespace == null) { + throw new IllegalArgumentException("Cannot register a resourcetype"); + } + TypeName tn = new TypeName(name, namespace); + // avoid duplicate registrations + if (NAMES.contains(tn)) { + return NAMES.indexOf(tn); + } + // register new type + if (NAMES.add(tn)) { + return NAMES.size() - 1; + } else { + throw new IllegalArgumentException("Could not register resourcetype " + namespace.getPrefix() + name); + } + } + + //--------------------------------------------------------< inner class >--- + /** + * Private inner class used to register predefined and user defined resource + * types. + */ + private static class TypeName implements XmlSerializable { + + private final String localName; + private final Namespace namespace; + private final int hashCode; + + private TypeName(String localName, Namespace namespace) { + this.localName = localName; + this.namespace = namespace; + hashCode = DomUtil.getExpandedName(localName, namespace).hashCode(); + } + + @Override + public int hashCode() { + return hashCode; + } + + @Override + public boolean equals(Object o) { + if (o instanceof TypeName) { + return hashCode == ((TypeName)o).hashCode; + } + return false; + } + + public Element toXml(Document document) { + return DomUtil.createElement(document, localName, namespace); + } + } +} Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/property/ResourceType.java ___________________________________________________________________ Added: svn Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/property/package-info.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/property/package-info.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/property/package-info.java (working copy) @@ -0,0 +1,18 @@ +/* + * 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. + */ +@org.osgi.annotation.versioning.Version("1.0.0") +package org.apache.jackrabbit.webdav.property; Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/property/package-info.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/search/QueryGrammerSet.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/search/QueryGrammerSet.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/search/QueryGrammerSet.java (working copy) @@ -0,0 +1,144 @@ +/* + * 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.webdav.search; + +import org.apache.jackrabbit.webdav.property.AbstractDavProperty; +import org.apache.jackrabbit.webdav.property.DavProperty; +import org.apache.jackrabbit.webdav.xml.DomUtil; +import org.apache.jackrabbit.webdav.xml.Namespace; +import org.apache.jackrabbit.webdav.xml.XmlSerializable; +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +import java.util.HashSet; +import java.util.Set; + +/** + * QueryGrammerSet is a {@link DavProperty} that + * encapsulates the 'supported-query-grammer-set' as defined by the + * Webdav SEARCH internet draft. + */ +public class QueryGrammerSet extends AbstractDavProperty> implements SearchConstants { + + private final Set queryGrammers = new HashSet(); + + /** + * Create a new empty QueryGrammerSet. Supported query grammers + * may be added by calling {@link #addQueryLanguage(String, Namespace)}. + */ + public QueryGrammerSet() { + super(QUERY_GRAMMER_SET, true); + } + + /** + * Add another query queryGrammer to this set. + * + * @param grammerName + * @param namespace + */ + public void addQueryLanguage(String grammerName, Namespace namespace) { + queryGrammers.add(new Grammer(grammerName, namespace)); + } + + /** + * Return a String array containing the URIs of the query + * languages supported. + * + * @return names of the supported query languages + */ + public String[] getQueryLanguages() { + int size = queryGrammers.size(); + if (size > 0) { + String[] qLangStr = new String[size]; + Grammer[] grammers = queryGrammers.toArray(new Grammer[size]); + for (int i = 0; i < grammers.length; i++) { + qLangStr[i] = grammers[i].namespace.getURI() + grammers[i].localName; + } + return qLangStr; + } else { + return new String[0]; + } + } + + /** + * Return the Xml representation of this property according to the definition + * of the 'supported-query-grammer-set'. + * + * @return Xml representation + * @see SearchConstants#QUERY_GRAMMER_SET + * @see org.apache.jackrabbit.webdav.xml.XmlSerializable#toXml(Document) + * @param document + */ + @Override + public Element toXml(Document document) { + Element elem = getName().toXml(document); + for (Grammer qGrammer : queryGrammers) { + elem.appendChild(qGrammer.toXml(document)); + } + return elem; + } + + /** + * Returns the set of supported query grammers. + * + * @return list of supported query languages. + * @see org.apache.jackrabbit.webdav.property.DavProperty#getValue() + */ + public Set getValue() { + return queryGrammers; + } + + + private class Grammer implements XmlSerializable { + + private final String localName; + private final Namespace namespace; + private final int hashCode; + + Grammer(String localName, Namespace namespace) { + this.localName = localName; + this.namespace = namespace; + hashCode = DomUtil.getExpandedName(localName, namespace).hashCode(); + } + + @Override + public int hashCode() { + return hashCode; + } + + @Override + public boolean equals(Object obj) { + if (obj == this) { + return true; + } + if (obj instanceof Grammer) { + return obj.hashCode() == hashCode(); + } + return false; + } + + /** + * @see XmlSerializable#toXml(org.w3c.dom.Document) + */ + public Element toXml(Document document) { + Element sqg = DomUtil.createElement(document, XML_QUERY_GRAMMAR, SearchConstants.NAMESPACE); + Element grammer = DomUtil.addChildElement(sqg, XML_GRAMMER, SearchConstants.NAMESPACE); + DomUtil.addChildElement(grammer, localName, namespace); + return sqg; + } + } +} \ No newline at end of file Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/search/QueryGrammerSet.java ___________________________________________________________________ Added: svn Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/search/SearchConstants.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/search/SearchConstants.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/search/SearchConstants.java (working copy) @@ -0,0 +1,91 @@ +/* + * 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.webdav.search; + +import org.apache.jackrabbit.webdav.DavConstants; +import org.apache.jackrabbit.webdav.property.DavPropertyName; +import org.apache.jackrabbit.webdav.xml.Namespace; + +/** + * SearchConstants interface provide constants for request + * and response headers, Xml elements and property names used for WebDAV + * search. + */ +public interface SearchConstants { + + /** + * Namespace definition.
+ * NOTE: For convenience reasons, the namespace is defined to be the default + * {@link DavConstants#NAMESPACE DAV:} namespace. This is not correct for the + * underlying specification is still in a draft state. See also the editorial + * note inside the + * Internet Draft WebDAV Search + * document. + */ + public static final Namespace NAMESPACE = DavConstants.NAMESPACE; + + /** + * Predefined basic query grammer. + */ + public static final String BASICSEARCH = NAMESPACE.getPrefix()+"basicsearch"; + + //---< Headers >------------------------------------------------------------ + /** + * The DASL response header specifying the query languages supported by + * the requested resource. + */ + public static final String HEADER_DASL = "DASL"; + + //---< XML Element, Attribute Names >--------------------------------------- + /** + * Xml element name for a single query grammar element inside + * the {@link #QUERY_GRAMMER_SET supported-query-grammer-set property}. + */ + public static final String XML_QUERY_GRAMMAR = "supported-query-grammar"; + + /** + * Name constant for the 'DAV:grammar' element, which is used inside the + * {@link #XML_QUERY_GRAMMAR} element. + */ + public static final String XML_GRAMMER = "grammar"; + + /** + * Xml element name for the required request body of a SEARCH request. + * + * @see SearchInfo + * @see SearchResource#search(SearchInfo) + */ + public static final String XML_SEARCHREQUEST = "searchrequest"; + + /** + * Optional Xml element name used in the SEARCH request body instead of {@link #XML_SEARCHREQUEST} + * in order to access a given query schema. + */ + public static final String XML_QUERY_SCHEMA_DISCOVERY = "query-schema-discovery"; + + //---< Property Names >----------------------------------------------------- + /** + * Property indicating the set of query languages the given resource is + * able deal with. The property has the following definition:
+ *
+     * <!ELEMENT supported-query-grammar-set (supported-query-grammar*)>
+     * <!ELEMENT supported-query-grammar grammar>
+     * <!ELEMENT grammar ANY>
+     * 
+ */ + public static final DavPropertyName QUERY_GRAMMER_SET = DavPropertyName.create("supported-query-grammar-set", NAMESPACE); +} \ No newline at end of file Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/search/SearchConstants.java ___________________________________________________________________ Added: svn Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/search/SearchInfo.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/search/SearchInfo.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/search/SearchInfo.java (working copy) @@ -0,0 +1,271 @@ +/* + * 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.webdav.search; + +import org.apache.jackrabbit.webdav.DavException; +import org.apache.jackrabbit.webdav.DavServletResponse; +import org.apache.jackrabbit.webdav.DavConstants; +import org.apache.jackrabbit.webdav.xml.DomUtil; +import org.apache.jackrabbit.webdav.xml.Namespace; +import org.apache.jackrabbit.webdav.xml.XmlSerializable; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.Attr; + +import java.util.Map; +import java.util.HashMap; +import java.util.Collections; +import java.util.Set; +import java.util.HashSet; + +/** + * SearchInfo parses the 'searchrequest' element of a SEARCH + * request body and performs basic validation. Both query language and the + * query itself can be access from the resulting object.
+ * NOTE: The query is expected to be represented by the text contained in the + * Xml element specifying the query language, thus the 'basicsearch' defined + * by the Webdav Search Internet Draft is not supported by this implementation. + *

+ * + * Example of a valid 'searchrequest' body + *

+ * <d:searchrequest xmlns:d="DAV:" dcr:="http://www.day.com/jcr/webdav/1.0" >
+ *    <dcr:xpath>//sv:node[@sv:name='myapp:paragraph'][1]</dcr:xpath>
+ * </d:searchrequest>
+ * 
+ * + * Would return the following values: + *
+ *    getLanguageName() -> xpath
+ *    getQuery()        -> //sv:node[@sv:name='myapp:paragraph'][1]
+ * 
+ * + */ +public class SearchInfo implements SearchConstants, XmlSerializable { + + private static Logger log = LoggerFactory.getLogger(SearchInfo.class); + + public static final long NRESULTS_UNDEFINED = -1; + public static final long OFFSET_UNDEFINED = -1; + + private static final String LIMIT = "limit"; + private static final String NRESULTS = "nresults"; + private static final String OFFSET = "offset"; + + /** + * Set of namespace uri String which are ignored in the search request. + */ + private static final Set IGNORED_NAMESPACES; + + static { + Set s = new HashSet(); + s.add(Namespace.XMLNS_NAMESPACE.getURI()); + s.add(Namespace.XML_NAMESPACE.getURI()); + s.add(DavConstants.NAMESPACE.getURI()); + IGNORED_NAMESPACES = Collections.unmodifiableSet(s); + } + + private final String language; + private final Namespace languageNamespace; + private final String query; + private final Map namespaces; + + private long nresults = NRESULTS_UNDEFINED; + private long offset = OFFSET_UNDEFINED; + + /** + * Create a new SearchInfo instance. + * + * @param language + * @param languageNamespace + * @param query + * @param namespaces the re-mapped namespaces. Key=prefix, value=uri. + */ + public SearchInfo(String language, Namespace languageNamespace, String query, + Map namespaces) { + this.language = language; + this.languageNamespace = languageNamespace; + this.query = query; + this.namespaces = Collections.unmodifiableMap(new HashMap(namespaces)); + } + + /** + * Create a new SearchInfo instance. + * + * @param language + * @param languageNamespace + * @param query + */ + public SearchInfo(String language, Namespace languageNamespace, String query) { + this(language, languageNamespace, query, Collections.emptyMap()); + } + + /** + * Returns the name of the query language to be used. + * + * @return name of the query language + */ + public String getLanguageName() { + return language; + } + + /** + * Returns the namespace of the language specified with the search request element. + * + * @return namespace of the requested language. + */ + public Namespace getLanguageNameSpace() { + return languageNamespace; + } + + /** + * Return the query string. + * + * @return query string + */ + public String getQuery() { + return query; + } + + /** + * Returns the namespaces that have been re-mapped by the user. + * + * @return map of namespace to prefix mappings. Key=prefix, value=uri. + */ + public Map getNamespaces() { + return namespaces; + } + + /** + * Returns the maximal number of search results that should be returned. + * + * @return the maximal number of search results that should be returned. + */ + public long getNumberResults() { + return nresults; + } + + /** + * Sets the maximal number of search results that should be returned. + * + * @param nresults The maximal number of search results + */ + public void setNumberResults(long nresults) { + this.nresults = nresults; + } + + /** + * Returns the desired offset in the total result set. + * + * @return the desired offset in the total result set. + */ + public long getOffset() { + return offset; + } + + /** + * Sets the desired offset in the total result set. + * + * @param offset The desired offset in the total result set. + */ + public void setOffset(long offset) { + this.offset = offset; + } + + /** + * Return the xml representation of this SearchInfo instance. + * + * @return xml representation + * @param document + */ + public Element toXml(Document document) { + Element sRequestElem = DomUtil.createElement(document, XML_SEARCHREQUEST, NAMESPACE); + for (String prefix : namespaces.keySet()) { + String uri = namespaces.get(prefix); + DomUtil.setNamespaceAttribute(sRequestElem, prefix, uri); + } + DomUtil.addChildElement(sRequestElem, language, languageNamespace, query); + if (nresults != NRESULTS_UNDEFINED|| offset != OFFSET_UNDEFINED) { + Element limitE = DomUtil.addChildElement(sRequestElem, LIMIT, NAMESPACE); + if (nresults != NRESULTS_UNDEFINED) { + DomUtil.addChildElement(limitE, NRESULTS, NAMESPACE, nresults + ""); + } + if (offset != OFFSET_UNDEFINED) { + // TODO define reasonable namespace... + DomUtil.addChildElement(limitE, OFFSET, Namespace.EMPTY_NAMESPACE, offset + ""); + } + } + return sRequestElem; + } + + /** + * Create a new SearchInfo from the specifying document + * retrieved from the request body. + * + * @param searchRequest + * @throws DavException if the root element's name is other than + * 'searchrequest' or if it does not contain a single child element specifying + * the query language to be used. + */ + public static SearchInfo createFromXml(Element searchRequest) throws DavException { + if (searchRequest == null || !XML_SEARCHREQUEST.equals(searchRequest.getLocalName())) { + log.warn("The root element must be 'searchrequest'."); + throw new DavException(DavServletResponse.SC_BAD_REQUEST); + } + Element first = DomUtil.getFirstChildElement(searchRequest); + Attr[] nsAttributes = DomUtil.getNamespaceAttributes(searchRequest); + Map namespaces = new HashMap(); + for (Attr nsAttribute : nsAttributes) { + // filter out xmlns namespace and DAV namespace + if (!IGNORED_NAMESPACES.contains(nsAttribute.getValue())) { + namespaces.put(nsAttribute.getLocalName(), nsAttribute.getValue()); + } + } + SearchInfo sInfo; + if (first != null) { + sInfo = new SearchInfo(first.getLocalName(), DomUtil.getNamespace(first), DomUtil.getText(first), namespaces); + } else { + log.warn("A single child element is expected with the 'DAV:searchrequest'."); + throw new DavException(DavServletResponse.SC_BAD_REQUEST); + } + + Element limit = DomUtil.getChildElement(searchRequest, LIMIT, NAMESPACE); + if (limit != null) { + // try to get the value DAV:nresults element + String nresults = DomUtil.getChildTextTrim(limit, NRESULTS, NAMESPACE); + if (nresults != null) { + try { + sInfo.setNumberResults(Long.valueOf(nresults)); + } catch (NumberFormatException e) { + log.error("DAV:nresults cannot be parsed into a long -> ignore."); + } + } + // try of an offset is defined within the DAV:limit element. + String offset = DomUtil.getChildTextTrim(limit, OFFSET, Namespace.EMPTY_NAMESPACE); + if (offset != null) { + try { + sInfo.setOffset(Long.valueOf(offset)); + } catch (NumberFormatException e) { + log.error("'offset' cannot be parsed into a long -> ignore."); + } + } + } + return sInfo; + } +} Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/search/SearchInfo.java ___________________________________________________________________ Added: svn Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/search/SearchResource.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/search/SearchResource.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/search/SearchResource.java (working copy) @@ -0,0 +1,55 @@ +/* + * 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.webdav.search; + +import org.apache.jackrabbit.webdav.DavException; +import org.apache.jackrabbit.webdav.MultiStatus; + +/** + * SearchResource defines METHODS required in order to handle + * a SEARCH request. + */ +public interface SearchResource { + + /** + * The 'SEARCH' method + */ + public String METHODS = "SEARCH"; + + + /** + * Returns the protected DAV:supported-method-set property which is defined + * mandatory by RTF 3253. This method call is a shortcut for + * DavResource.getProperty(SearchConstants.QUERY_GRAMMER_SET). + * + * @return the DAV:supported-query-grammer-set + * @see SearchConstants#QUERY_GRAMMER_SET + */ + public QueryGrammerSet getQueryGrammerSet(); + + /** + * Runs a search with the language and query defined in the {@link SearchInfo} + * object specified and returns a {@link MultiStatus} object listing the + * results. + * + * @param sInfo SearchInfo element encapsulating the SEARCH + * request body. + * @return MultiStatus object listing the results. + * @throws DavException + */ + public MultiStatus search(SearchInfo sInfo) throws DavException; +} \ No newline at end of file Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/search/SearchResource.java ___________________________________________________________________ Added: svn Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/search/package-info.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/search/package-info.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/search/package-info.java (working copy) @@ -0,0 +1,18 @@ +/* + * 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. + */ +@org.osgi.annotation.versioning.Version("1.0.0") +package org.apache.jackrabbit.webdav.search; Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/search/package-info.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/security/AclProperty.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/security/AclProperty.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/security/AclProperty.java (working copy) @@ -0,0 +1,262 @@ +/* + * 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.webdav.security; + +import org.apache.jackrabbit.webdav.DavConstants; +import org.apache.jackrabbit.webdav.DavException; +import org.apache.jackrabbit.webdav.DavServletResponse; +import org.apache.jackrabbit.webdav.property.AbstractDavProperty; +import org.apache.jackrabbit.webdav.property.DavProperty; +import org.apache.jackrabbit.webdav.xml.DomUtil; +import org.apache.jackrabbit.webdav.xml.ElementIterator; +import org.apache.jackrabbit.webdav.xml.XmlSerializable; +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +/** + * AclProperty defines a protected property that specifies the list + * of access control entries (ACEs). The set of ACEs define the privileges granted + * or denied to principals on the resource a given property instance belongs to. + *
+ * RFC 3744 defines the following format for this property: + *
+ * <!ELEMENT acl (ace*) >
+ * <!ELEMENT ace ((principal | invert), (grant|deny), protected?, inherited?)>
+ * <!ELEMENT principal (href | all | authenticated | unauthenticated | property | self)>
+ * <!ELEMENT invert (principal)>
+ * <!ELEMENT grant (privilege+)>
+ * <!ELEMENT deny (privilege+)>
+ * <!ELEMENT protected EMPTY>
+ * <!ELEMENT inherited (href)>
+ * 
+ * + * @see Principal for details regarding DAV:principal + * @see Privilege for details regarding DAV:privilege + */ +public class AclProperty extends AbstractDavProperty> { + + private final List aces; + + /** + * Create a new AclProperty from the given ACEs. + * + * @see AclProperty#createGrantAce(Principal, Privilege[], boolean, boolean, AclResource) for a factory method to create a grant ACE. + * @see AclProperty#createDenyAce(Principal, Privilege[], boolean, boolean, AclResource) for a factory method to create a deny ACE. + */ + public AclProperty(Ace[] accessControlElements) { + this((accessControlElements == null) ? new ArrayList() : Arrays.asList(accessControlElements)); + } + + private AclProperty(List aces) { + super(SecurityConstants.ACL, true); + this.aces = aces; + } + + /** + * @return a List of Ace object. If this property defines no ACEs + * an empty list is returned. + * @see DavProperty#getValue() + */ + public List getValue() { + return aces; + } + + /** + * Build a new AclProperty object from the request body of the + * ACL method call. + * + * @param aclElement + * @return new AclProperty + * @throws DavException + */ + public static AclProperty createFromXml(Element aclElement) throws DavException { + if (!DomUtil.matches(aclElement, SecurityConstants.ACL.getName(), SecurityConstants.ACL.getNamespace())) { + throw new DavException(DavServletResponse.SC_BAD_REQUEST, "ACL request requires a DAV:acl body."); + } + List aces = new ArrayList(); + ElementIterator it = DomUtil.getChildren(aclElement, Ace.XML_ACE, SecurityConstants.NAMESPACE); + while (it.hasNext()) { + Element aceElem = it.nextElement(); + aces.add(Ace.createFromXml(aceElem)); + } + return new AclProperty(aces); + } + + public static Ace createGrantAce(Principal principal, Privilege[] privileges, boolean invert, boolean isProtected, AclResource inheritedFrom) { + return new Ace(principal, invert, privileges, true, isProtected, inheritedFrom); + } + + public static Ace createDenyAce(Principal principal, Privilege[] privileges, boolean invert, boolean isProtected, AclResource inheritedFrom) { + return new Ace(principal, invert, privileges, false, isProtected, inheritedFrom); + } + + //--------------------------------------------------------< inner class >--- + /** + * Simple WebDAV ACE implementation + */ + public static class Ace implements XmlSerializable, SecurityConstants { + + private static final String XML_ACE = "ace"; + private static final String XML_INVERT = "invert"; + private static final String XML_GRANT = "grant"; + private static final String XML_DENY = "deny"; + private static final String XML_PROTECTED = "protected"; + private static final String XML_INHERITED = "inherited"; + + private final Principal principal; + private final boolean invert; + private final Privilege[] privileges; + private final boolean grant; + private final boolean isProtected; + private final String inheritedHref; + + /** + * Private constructor + * + * @param principal + * @param invert + * @param privileges + * @param grant + * @param isProtected + * @param inherited + */ + private Ace(Principal principal, boolean invert, Privilege[] privileges, + boolean grant, boolean isProtected, AclResource inherited) { + this(principal, invert, privileges, grant, isProtected, + ((inherited != null) ? inherited.getHref() : null)); + } + + /** + * Private constructor + * + * @param principal + * @param invert + * @param privileges + * @param grant + * @param isProtected + * @param inheritedHref + */ + private Ace(Principal principal, boolean invert, Privilege[] privileges, + boolean grant, boolean isProtected, String inheritedHref) { + if (principal == null) { + throw new IllegalArgumentException("Cannot create a new ACE with 'null' principal."); + } + if (privileges == null || privileges.length == 0) { + throw new IllegalArgumentException("Cannot create a new ACE: at least a single privilege must be specified."); + } + this.principal = principal; + this.invert = invert; + this.privileges = privileges; + this.grant = grant; + this.isProtected = isProtected; + this.inheritedHref = inheritedHref; + } + + public Principal getPrincipal() { + return principal; + } + + public boolean isInvert() { + return invert; + } + + public Privilege[] getPrivileges() { + return privileges; + } + + public boolean isGrant() { + return grant; + } + + public boolean isDeny() { + return !grant; + } + + public boolean isProtected() { + return isProtected; + } + + public String getInheritedHref() { + return inheritedHref; + } + + /** + * @see XmlSerializable#toXml(Document) + */ + public Element toXml(Document document) { + Element ace = DomUtil.createElement(document, XML_ACE, SecurityConstants.NAMESPACE); + if (invert) { + Element inv = DomUtil.addChildElement(ace, XML_INVERT, SecurityConstants.NAMESPACE); + inv.appendChild(principal.toXml(document)); + } else { + ace.appendChild(principal.toXml(document)); + } + Element gd = DomUtil.addChildElement(ace, ((grant) ? XML_GRANT : XML_DENY), SecurityConstants.NAMESPACE); + for (Privilege privilege : privileges) { + gd.appendChild(privilege.toXml(document)); + } + if (isProtected) { + DomUtil.addChildElement(ace, XML_PROTECTED, SecurityConstants.NAMESPACE); + } + if (inheritedHref != null) { + Element inh = DomUtil.addChildElement(ace, XML_INHERITED, SecurityConstants.NAMESPACE); + inh.appendChild(DomUtil.hrefToXml(inheritedHref, document)); + } + return ace; + } + + private static Ace createFromXml(Element aceElement) throws DavException { + boolean invert = DomUtil.hasChildElement(aceElement, XML_INVERT, NAMESPACE); + Element pe; + if (invert) { + Element invertE = DomUtil.getChildElement(aceElement, XML_INVERT, NAMESPACE); + pe = DomUtil.getChildElement(invertE, Principal.XML_PRINCIPAL, NAMESPACE); + } else { + pe = DomUtil.getChildElement(aceElement, Principal.XML_PRINCIPAL, SecurityConstants.NAMESPACE); + } + Principal principal = Principal.createFromXml(pe); + + boolean grant = DomUtil.hasChildElement(aceElement, Ace.XML_GRANT, SecurityConstants.NAMESPACE); + Element gdElem; + if (grant) { + gdElem = DomUtil.getChildElement(aceElement, XML_GRANT, NAMESPACE); + } else { + gdElem = DomUtil.getChildElement(aceElement, XML_DENY, NAMESPACE); + } + List privilegeList = new ArrayList(); + ElementIterator privIt = DomUtil.getChildren(gdElem, Privilege.XML_PRIVILEGE, NAMESPACE); + while (privIt.hasNext()) { + Privilege pv = Privilege.getPrivilege(privIt.nextElement()); + privilegeList.add(pv); + } + Privilege[] privileges = privilegeList.toArray(new Privilege[privilegeList.size()]); + + boolean isProtected = DomUtil.hasChildElement(aceElement, XML_PROTECTED, NAMESPACE); + String inheritedHref = null; + if (DomUtil.hasChildElement(aceElement, XML_INHERITED, NAMESPACE)) { + Element inhE = DomUtil.getChildElement(aceElement, XML_INHERITED, NAMESPACE); + inheritedHref = DomUtil.getChildText(inhE, DavConstants.XML_HREF, DavConstants.NAMESPACE); + } + + return new Ace(principal, invert, privileges, grant, isProtected, inheritedHref); + } + } +} Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/security/AclProperty.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-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/security/AclResource.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/security/AclResource.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/security/AclResource.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.webdav.security; + +import org.apache.jackrabbit.webdav.DavException; +import org.apache.jackrabbit.webdav.DavResource; +import org.apache.jackrabbit.webdav.DavServletResponse; +import org.apache.jackrabbit.webdav.version.DeltaVResource; +import org.apache.jackrabbit.webdav.version.report.Report; +import org.apache.jackrabbit.webdav.version.report.ReportInfo; + +/** + * AclResource... + */ +public interface AclResource extends DavResource { + + /** + * The AclResource must support the ACL method and the REPORT method in order + * to retrieve various security related reports. + * + * @see DeltaVResource#METHODS + * @see org.apache.jackrabbit.webdav.DavResource#METHODS + */ + public String METHODS = "ACL, REPORT"; + + /** + * Modify the DAV:acl property of this resource object.
+ * Note: RFC 3744 limits modification of access control elements (ACEs) to + * elements that are neither inherited nor protected. + * + * @param aclProperty DAV:acl property listing the set of ACEs to be modified + * by this call. This may be a subset of all access control elements + * present on this resource object only. + * @throws DavException If the request fails. RFC 3744 defines a set of + * preconditions which must be met for a successful ACL request. + * If these conditions are violated, this method must fail with + * {@link DavServletResponse#SC_FORBIDDEN 403 (Forbidden)} or + * {@link DavServletResponse#SC_CONFLICT 409 (Conflict)} and should provide + * a detailed error condition in the response body. See + * RFC 3744 Section 8.1.1 + * (ACL Preconditions) for further details. + */ + public void alterAcl(AclProperty aclProperty) throws DavException; + + /** + * Same as {@link DeltaVResource#getReport(ReportInfo)}. + * + * @param reportInfo specifying the report details retrieved from the REPORT + * request. + * @return the requested report. + * @throws DavException in case an error occurred or if the specified + * ReportInfo is either not valid or cannot be run by this + * resource. + */ + public Report getReport(ReportInfo reportInfo) throws DavException; +} Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/security/AclResource.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-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/security/AclRestrictionsProperty.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/security/AclRestrictionsProperty.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/security/AclRestrictionsProperty.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.webdav.security; + +import org.apache.jackrabbit.webdav.property.AbstractDavProperty; +import org.apache.jackrabbit.webdav.property.DavProperty; +import org.apache.jackrabbit.webdav.xml.DomUtil; +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +/** + * AclRestrictionsProperty as defined by RFC 3744 Section 5.6. + * DAV:acl-restrictions: + *
+ * <!ELEMENT acl-restrictions (grant-only?, no-invert?, deny-before-grant?, required-principal?)>
+ * <!ELEMENT grant-only EMPTY>
+ * <!ELEMENT no-invert EMPTY>
+ * <!ELEMENT deny-before-grant EMPTY>
+ * <!ELEMENT required-principal (all? | authenticated? | unauthenticated? | self? | href* | property*)>
+ * 
+ * + * @see Principal + * @see AclProperty + */ +public class AclRestrictionsProperty extends AbstractDavProperty { + + // TODO: RFC 3744 defines a distinct structure for required-principal + // than for principal. Current 'normal' principal is used instead. + + private static final String XML_GRANT_ONLY = "grant-only"; + private static final String XML_NO_INVERT = "no-invert"; + private static final String XML_DENY_BEFORE_GRANT = "deny-before-grant"; + + private final boolean grantOnly; + private final boolean noInvert; + private final boolean denyBeforeGrant; + private final Principal requiredPrincipal; + + public AclRestrictionsProperty(boolean grantOnly, boolean noInvert, boolean denyBeforeGrant, Principal requiredPrincipal) { + super(SecurityConstants.ACL_RESTRICTIONS, true); + this.grantOnly = grantOnly; + this.noInvert = noInvert; + this.denyBeforeGrant = denyBeforeGrant; + this.requiredPrincipal = requiredPrincipal; + } + + /** + * Not implemented. + * + * @throws UnsupportedOperationException + */ + public Object getValue() { + throw new UnsupportedOperationException("Not implemented. Use the property specific methods instead."); + } + + /** + * @see DavProperty#toXml(Document) + */ + @Override + public Element toXml(Document document) { + Element elem = getName().toXml(document); + if (grantOnly) { + DomUtil.addChildElement(elem, XML_GRANT_ONLY, SecurityConstants.NAMESPACE); + } + if (noInvert) { + DomUtil.addChildElement(elem, XML_NO_INVERT, SecurityConstants.NAMESPACE); + } + if (denyBeforeGrant) { + DomUtil.addChildElement(elem, XML_DENY_BEFORE_GRANT, SecurityConstants.NAMESPACE); + } + if (requiredPrincipal != null) { + elem.appendChild(requiredPrincipal.toXml(document)); + } + return elem; + } + + public boolean isGrantOnly() { + return grantOnly; + } + + public boolean isNoInvert() { + return noInvert; + } + + public boolean isDenyBeforeGrant() { + return denyBeforeGrant; + } + + public Principal getRequiredPrincipal() { + // TODO: check of should be replaced by specific required-principal... + return requiredPrincipal; + } +} Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/security/AclRestrictionsProperty.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-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/security/CurrentUserPrivilegeSetProperty.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/security/CurrentUserPrivilegeSetProperty.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/security/CurrentUserPrivilegeSetProperty.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.webdav.security; + +import org.apache.jackrabbit.webdav.DavException; +import org.apache.jackrabbit.webdav.DavServletResponse; +import org.apache.jackrabbit.webdav.property.AbstractDavProperty; +import org.apache.jackrabbit.webdav.property.DavProperty; +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +import java.util.Collection; +import java.util.HashSet; +import java.util.Set; + +/** + * CurrentUserPrivilegeSetProperty... + */ +public class CurrentUserPrivilegeSetProperty extends AbstractDavProperty> { + + private final Set privileges; + + /** + * Create a new instance of this property. + * + * @param privileges array privileges. + */ + public CurrentUserPrivilegeSetProperty(Privilege[] privileges) { + super(SecurityConstants.CURRENT_USER_PRIVILEGE_SET, true); + + this.privileges = new HashSet(); + for (Privilege privilege : privileges) { + if (privilege != null) { + this.privileges.add(privilege); + } + } + } + + /** + * Create a new CurrentUserPrivilegeSetProperty from a DavProperty + * as obtained from a MultiStatusResponse. + * + * @param xmlDavProperty + * @throws DavException + */ + public CurrentUserPrivilegeSetProperty(DavProperty xmlDavProperty) throws DavException { + super(xmlDavProperty.getName(), true); + if (!SecurityConstants.CURRENT_USER_PRIVILEGE_SET.equals(getName())) { + throw new DavException(DavServletResponse.SC_BAD_REQUEST, "DAV:current-user-privilege-set expected."); + } + privileges = new HashSet(); + + // parse property value + Object value = xmlDavProperty.getValue(); + if (value != null) { + if (value instanceof Element) { + privileges.add(Privilege.getPrivilege((Element)value)); + } else if (value instanceof Collection) { + for (Object entry : ((Collection) value)) { + if (entry instanceof Element) { + privileges.add(Privilege.getPrivilege((Element) entry)); + } + } + } + } + } + + /** + * @return a Collection of Privilege objects use for xml serialization. + * @see DavProperty#getValue() + * @see AbstractDavProperty#toXml(Document) + */ + public Collection getValue() { + return privileges; + } +} \ No newline at end of file Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/security/CurrentUserPrivilegeSetProperty.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-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/security/Principal.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/security/Principal.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/security/Principal.java (working copy) @@ -0,0 +1,189 @@ +/* + * 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.webdav.security; + +import org.apache.jackrabbit.webdav.DavConstants; +import org.apache.jackrabbit.webdav.DavException; +import org.apache.jackrabbit.webdav.DavServletResponse; +import org.apache.jackrabbit.webdav.property.DavPropertyName; +import org.apache.jackrabbit.webdav.xml.DomUtil; +import org.apache.jackrabbit.webdav.xml.XmlSerializable; +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +import java.util.HashMap; +import java.util.Map; + +/** + * Principal encapsulates the DAV:principal element which identifies + * the principal to which this ACE applies. + * RFC 3744 defines the following structure for this element: + *
+ * <!ELEMENT principal (href | all | authenticated | unauthenticated | property | self)>
+ * 
+ */ +public class Principal implements XmlSerializable, SecurityConstants { + + public static final String XML_PRINCIPAL = "principal"; + + private static final String XML_ALL = "all"; + private static final String XML_AUTHENTICATED = "authenticated"; + private static final String XML_UNAUTHENTICATED = "unauthenticated"; + private static final String XML_SELF = "self"; + private static final String XML_PROPERTY = "property"; + + private static final int TYPE_ALL = 0; + private static final int TYPE_AUTHENTICATED = 1; + private static final int TYPE_UNAUTHENTICATED = 2; + private static final int TYPE_SELF = 3; + private static final int TYPE_PROPERTY = 4; + private static final int TYPE_HREF = 5; + + private static final Principal ALL_PRINCIPAL = new Principal(TYPE_ALL); + private static final Principal AUTHENTICATED_PRINCIPAL = new Principal(TYPE_AUTHENTICATED); + private static final Principal UNAUTHENTICATED_PRINCIPAL = new Principal(TYPE_UNAUTHENTICATED); + private static final Principal SELF_PRINCIPAL = new Principal(TYPE_SELF); + + private static final Map PROP_PRINCIPALS = new HashMap(); + + private final int type; + private DavPropertyName propertyName; + private String href; + + private Principal(int type) { + this.type = type; + } + + private Principal(DavPropertyName propertyName) { + this.type = TYPE_PROPERTY; + this.propertyName = propertyName; + } + + private Principal(String href) { + this.type = TYPE_HREF; + this.href = href; + } + + /** + * @return href if this Principal is a href-typed principal, null + * otherwise. + */ + public String getHref() { + return href; + } + + /** + * @return propertyName if this Principal is a property-principal, + * null otherwise. + */ + public DavPropertyName getPropertyName() { + return propertyName; + } + + /** + * @see XmlSerializable#toXml(Document) + */ + public Element toXml(Document document) { + Element pEl = DomUtil.createElement(document, XML_PRINCIPAL, NAMESPACE); + switch (type) { + case TYPE_ALL: + DomUtil.addChildElement(pEl, XML_ALL, NAMESPACE); + break; + case TYPE_AUTHENTICATED: + DomUtil.addChildElement(pEl, XML_AUTHENTICATED, NAMESPACE); + break; + case TYPE_UNAUTHENTICATED: + DomUtil.addChildElement(pEl, XML_UNAUTHENTICATED, NAMESPACE); + break; + case TYPE_SELF: + DomUtil.addChildElement(pEl, XML_SELF, NAMESPACE); + break; + case TYPE_PROPERTY: + Element prop = DomUtil.addChildElement(pEl, XML_PROPERTY, NAMESPACE); + prop.appendChild(propertyName.toXml(document)); + break; + case TYPE_HREF: + Element hrefEl = DomUtil.hrefToXml(href, document); + pEl.appendChild(hrefEl); + break; + // no default + } + return pEl; + } + + public static Principal getAllPrincipal() { + return ALL_PRINCIPAL; + } + + public static Principal getAuthenticatedPrincipal() { + return AUTHENTICATED_PRINCIPAL; + } + + public static Principal getUnauthenticatedPrincipal() { + return UNAUTHENTICATED_PRINCIPAL; + } + + public static Principal getSelfPrincipal() { + return SELF_PRINCIPAL; + } + + public static Principal getPropertyPrincipal(DavPropertyName propertyName) { + if (propertyName == null) { + throw new IllegalArgumentException("Property-Principal must contain a valid property name."); + } + // there is a limited amount of properties, that can be used + // for a Property-Principal + if (PROP_PRINCIPALS.containsKey(propertyName)) { + return PROP_PRINCIPALS.get(propertyName); + } else { + Principal p = new Principal(propertyName); + PROP_PRINCIPALS.put(propertyName, p); + return p; + } + } + + public static Principal getHrefPrincipal(String href) { + if (href == null) { + throw new IllegalArgumentException("Href-Principal must contain a valid href."); + } + return new Principal(href); + } + + public static Principal createFromXml(Element principalElement) throws DavException { + if (!DomUtil.matches(principalElement, XML_PRINCIPAL, NAMESPACE)) { + throw new DavException(DavServletResponse.SC_BAD_REQUEST, "DAV:principal element expected."); + } + if (DomUtil.hasChildElement(principalElement, XML_ALL, NAMESPACE)) { + return ALL_PRINCIPAL; + } else if (DomUtil.hasChildElement(principalElement, XML_SELF, NAMESPACE)) { + return SELF_PRINCIPAL; + } else if (DomUtil.hasChildElement(principalElement, XML_AUTHENTICATED, NAMESPACE)) { + return AUTHENTICATED_PRINCIPAL; + } else if (DomUtil.hasChildElement(principalElement, XML_UNAUTHENTICATED, NAMESPACE)) { + return UNAUTHENTICATED_PRINCIPAL; + } else if (DomUtil.hasChildElement(principalElement, DavConstants.XML_HREF, DavConstants.NAMESPACE)) { + String href = DomUtil.getChildText(principalElement, DavConstants.XML_HREF, DavConstants.NAMESPACE); + return getHrefPrincipal(href); + } else if (DomUtil.hasChildElement(principalElement, XML_PROPERTY, NAMESPACE)) { + Element propEl = DomUtil.getChildElement(principalElement, XML_PROPERTY, NAMESPACE); + DavPropertyName pn = DavPropertyName.createFromXml(DomUtil.getFirstChildElement(propEl)); + return getPropertyPrincipal(pn); + } else { + throw new DavException(DavServletResponse.SC_BAD_REQUEST, "Invalid structure inside DAV:principal element."); + } + } +} Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/security/Principal.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-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/security/Privilege.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/security/Privilege.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/security/Privilege.java (working copy) @@ -0,0 +1,204 @@ +/* + * 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.webdav.security; + +import org.apache.jackrabbit.webdav.DavException; +import org.apache.jackrabbit.webdav.DavServletResponse; +import org.apache.jackrabbit.webdav.xml.DomUtil; +import org.apache.jackrabbit.webdav.xml.Namespace; +import org.apache.jackrabbit.webdav.xml.XmlSerializable; +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +import java.util.HashMap; +import java.util.Map; + +/** + * Privilege + */ +public class Privilege implements XmlSerializable { + + public static final String XML_PRIVILEGE = "privilege"; + + /** + * Map for registered privileges + */ + private static final Map REGISTERED_PRIVILEGES = new HashMap(); + + //-------------------------------------< Privileges defined by RFC 3744 >--- + /** + * The read privilege controls methods that return information about the + * state of the resource, including the resource's properties. Affected + * methods include GET and PROPFIND and OPTIONS. + * + * @see RFC 3744 Section 3.1. DAV:read Privilege + */ + public static final Privilege PRIVILEGE_READ = getPrivilege("read", SecurityConstants.NAMESPACE); + /** + * The write privilege controls methods that lock a resource or modify the + * content, dead properties, or (in the case of a collection) membership of + * the resource, such as PUT and PROPPATCH. + * + * @see RFC 3744 Section 3.2. DAV:write Privilege + */ + public static final Privilege PRIVILEGE_WRITE = getPrivilege("write", SecurityConstants.NAMESPACE); + /** + * The DAV:write-properties privilege controls methods that modify the dead + * properties of the resource, such as PROPPATCH. Whether this privilege may + * be used to control access to any live properties is determined by the + * implementation. + * + * @see RFC 3744 Section 3.3. DAV:write-properties Privilege + */ + public static final Privilege PRIVILEGE_WRITE_PROPERTIES = getPrivilege("write-properties", SecurityConstants.NAMESPACE); + /** + * The DAV:write-content privilege controls methods that modify the content + * of an existing resource, such as PUT. + * + * @see RFC 3744 Section 3.4. DAV:write-content Privilege + */ + public static final Privilege PRIVILEGE_WRITE_CONTENT = getPrivilege("write-content", SecurityConstants.NAMESPACE); + /** + * The DAV:unlock privilege controls the use of the UNLOCK method by a + * principal other than the lock owner (the principal that created a lock + * can always perform an UNLOCK). + * + * @see RFC 3744 Section 3.5. DAV:unlock Privilege + */ + public static final Privilege PRIVILEGE_UNLOCK = getPrivilege("unlock", SecurityConstants.NAMESPACE); + /** + * The DAV:read-acl privilege controls the use of PROPFIND to retrieve the + * DAV:acl property of the resource. + * + * @see RFC 3744 Section 3.6. DAV:read-acl Privilege + */ + public static final Privilege PRIVILEGE_READ_ACL = getPrivilege("read-acl", SecurityConstants.NAMESPACE); + /** + * The DAV:read-current-user-privilege-set privilege controls the use of + * PROPFIND to retrieve the DAV:current-user-privilege-set property of the + * resource. + * + * @see RFC 3744 Section 3.7. DAV:"read-current-user-privilege-set Privilege + */ + public static final Privilege PRIVILEGE_READ_CURRENT_USER_PRIVILEGE_SET = getPrivilege("read-current-user-privilege-set", SecurityConstants.NAMESPACE); + /** + * The DAV:write-acl privilege controls use of the ACL method to modify the + * DAV:acl property of the resource. + * + * @see RFC 3744 Section 3.8. DAV:write-acl Privilege + */ + public static final Privilege PRIVILEGE_WRITE_ACL = getPrivilege("write-acl", SecurityConstants.NAMESPACE); + /** + * The DAV:bind privilege allows a method to add a new member URL to the + * specified collection (for example via PUT or MKCOL). It is ignored for + * resources that are not collections. + * + * @see RFC 3744 Section 3.9. DAV:bind Privilege + */ + public static final Privilege PRIVILEGE_BIND = getPrivilege("bind", SecurityConstants.NAMESPACE); + /** + * The DAV:unbind privilege allows a method to remove a member URL from the + * specified collection (for example via DELETE or MOVE). It is ignored for + * resources that are not collections. + * + * @see RFC 3744 Section 3.10. DAV:unbind Privilege + */ + public static final Privilege PRIVILEGE_UNBIND = getPrivilege("unbind", SecurityConstants.NAMESPACE); + /** + * DAV:all is an aggregate privilege that contains the entire set of + * privileges that can be applied to the resource. + * + * @see RFC 3744 Section 3.11. DAV:all Privilege + */ + public static final Privilege PRIVILEGE_ALL = getPrivilege("all", SecurityConstants.NAMESPACE); + + private final String privilege; + private final Namespace namespace; + + /** + * Private constructor + * + * @param privilege + * @param namespace + */ + private Privilege(String privilege, Namespace namespace) { + this.privilege = privilege; + this.namespace = namespace; + } + + /** + * @return The local name of this Privilege. + */ + public String getName() { + return privilege; + } + + /** + * @return The namespace of this Privilege. + */ + public Namespace getNamespace() { + return namespace; + } + + /** + * @see XmlSerializable#toXml(Document) + */ + public Element toXml(Document document) { + Element privEl = DomUtil.createElement(document, XML_PRIVILEGE, SecurityConstants.NAMESPACE); + DomUtil.addChildElement(privEl, privilege, namespace); + return privEl; + } + + /** + * Factory method to create/retrieve a Privilege. + * + * @param privilege + * @param namespace + * @return + */ + public static Privilege getPrivilege(String privilege, Namespace namespace) { + if (privilege == null) { + throw new IllegalArgumentException("'null' is not a valid privilege."); + } + if (namespace == null) { + namespace = Namespace.EMPTY_NAMESPACE; + } + String key = "{" + namespace.getURI() + "}" + privilege; + if (REGISTERED_PRIVILEGES.containsKey(key)) { + return REGISTERED_PRIVILEGES.get(key); + } else { + Privilege p = new Privilege(privilege, namespace); + REGISTERED_PRIVILEGES.put(key, p); + return p; + } + } + + /** + * Factory method to create/retrieve a Privilege from the given + * DAV:privilege element. + * + * @param privilege + * @return + */ + public static Privilege getPrivilege(Element privilege) throws DavException { + if (!DomUtil.matches(privilege, XML_PRIVILEGE, SecurityConstants.NAMESPACE)) { + throw new DavException(DavServletResponse.SC_BAD_REQUEST, "DAV:privilege element expected."); + } + Element el = DomUtil.getFirstChildElement(privilege); + return getPrivilege(el.getLocalName(), DomUtil.getNamespace(el)); + } +} Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/security/Privilege.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-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/security/SecurityConstants.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/security/SecurityConstants.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/security/SecurityConstants.java (working copy) @@ -0,0 +1,110 @@ +/* + * 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.webdav.security; + +import org.apache.jackrabbit.webdav.DavConstants; +import org.apache.jackrabbit.webdav.DavMethods; +import org.apache.jackrabbit.webdav.property.DavPropertyName; +import org.apache.jackrabbit.webdav.property.HrefProperty; +import org.apache.jackrabbit.webdav.property.ResourceType; +import org.apache.jackrabbit.webdav.xml.Namespace; + +/** + * SecurityConstants interface lists constants defined by + * RFC 3744 (WebDAV Access + * Control Protocol). + */ +public interface SecurityConstants { + + /** + * Default Namespace constant + */ + public static final Namespace NAMESPACE = DavConstants.NAMESPACE; + + /** + * Principal resources must define DAV:principal XML element in the value + * of the DAV:resourcetype property. + */ + public static int PRINCIPAL_RESOURCETYPE = ResourceType.registerResourceType("principal", NAMESPACE); + + //---< Property Names for Principal Resource >------------------------------ + /** + * Protected href property DAV:principal-URL for principal resources. + * @see HrefProperty + */ + public static final DavPropertyName PRINCIPAL_URL = DavPropertyName.create("principal-URL", NAMESPACE); + /** + * Protected href property DAV:alternate-URI-set for principal resources. + * @see HrefProperty + */ + public static final DavPropertyName ALTERNATE_URI_SET = DavPropertyName.create("alternate-URI-set", NAMESPACE); + /** + * Protected href property DAV:group-member-set for principal resources. + * @see HrefProperty + */ + public static final DavPropertyName GROUP_MEMBER_SET = DavPropertyName.create("group-member-set", NAMESPACE); + /** + * Protected href property DAV:group-membership for principal resources. + * @see HrefProperty + */ + public static final DavPropertyName GROUP_MEMBERSHIP = DavPropertyName.create("group-membership", NAMESPACE); + + //---< Property Names for DavResource >------------------------------------- + /** + * Protected href property DAV:owner + * @see HrefProperty + */ + public static final DavPropertyName OWNER = DavPropertyName.create("owner", NAMESPACE); + /** + * Protected href property DAV:group + * @see HrefProperty + */ + public static final DavPropertyName GROUP = DavPropertyName.create("group", NAMESPACE); + /** + * Protected property DAV:supported-privilege-set + * @see CurrentUserPrivilegeSetProperty + */ + public static final DavPropertyName SUPPORTED_PRIVILEGE_SET = DavPropertyName.create("supported-privilege-set", NAMESPACE); + /** + * Protected property DAV:current-user-privilege-set + * @see CurrentUserPrivilegeSetProperty + */ + public static final DavPropertyName CURRENT_USER_PRIVILEGE_SET = DavPropertyName.create("current-user-privilege-set", NAMESPACE); + /** + * Protected property DAV:acl. Note, that DAV:acl property may be altered + * with a ACL request. + * + * @see AclProperty + * @see DavMethods#METHOD_ACL + */ + public static final DavPropertyName ACL = DavPropertyName.create("acl", NAMESPACE); + /** + * Protected property DAV:acl-restrictions + * @see AclRestrictionsProperty + */ + public static final DavPropertyName ACL_RESTRICTIONS = DavPropertyName.create("acl-restrictions", NAMESPACE); + /** + * Protected href property DAV:inherited-acl-set + * @see HrefProperty + */ + public static final DavPropertyName INHERITED_ACL_SET = DavPropertyName.create("inherited-acl-set", NAMESPACE); + /** + * Protected href property DAV:principal-collection-set + * @see HrefProperty + */ + public static final DavPropertyName PRINCIPAL_COLLECTION_SET = DavPropertyName.create("principal-collection-set", NAMESPACE); +} Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/security/SecurityConstants.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-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/security/SupportedPrivilege.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/security/SupportedPrivilege.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/security/SupportedPrivilege.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.webdav.security; + +import java.util.ArrayList; +import java.util.List; + +import org.apache.jackrabbit.webdav.DavException; +import org.apache.jackrabbit.webdav.DavServletResponse; +import org.apache.jackrabbit.webdav.xml.DomUtil; +import org.apache.jackrabbit.webdav.xml.ElementIterator; +import org.apache.jackrabbit.webdav.xml.Namespace; +import org.apache.jackrabbit.webdav.xml.XmlSerializable; +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +/** + * SupportedPrivilege... + */ +public class SupportedPrivilege implements XmlSerializable { + + private static final String XML_SUPPORTED_PRIVILEGE = "supported-privilege"; + private static final String XML_ABSTRACT = "abstract"; + private static final String XML_DESCRIPTION = "description"; + + private final Privilege privilege; + private final boolean isAbstract; + private final String description; + private final String descriptionLanguage; + private final SupportedPrivilege[] supportedPrivileges; + + /** + * + * @param privilege + * @param description + * @param descriptionLanguage + * @param isAbstract + * @param supportedPrivileges + */ + public SupportedPrivilege(Privilege privilege, String description, + String descriptionLanguage, boolean isAbstract, + SupportedPrivilege[] supportedPrivileges) { + if (privilege == null) { + throw new IllegalArgumentException("DAV:supported-privilege element must contain a single privilege."); + } + this.privilege = privilege; + this.description = description; + this.descriptionLanguage = descriptionLanguage; + this.isAbstract = isAbstract; + this.supportedPrivileges = supportedPrivileges; + } + + /** + * @see XmlSerializable#toXml(Document) + */ + public Element toXml(Document document) { + Element spElem = DomUtil.createElement(document, XML_SUPPORTED_PRIVILEGE, SecurityConstants.NAMESPACE); + spElem.appendChild(privilege.toXml(document)); + if (isAbstract) { + DomUtil.addChildElement(spElem, XML_ABSTRACT, SecurityConstants.NAMESPACE); + } + if (description != null) { + Element desc = DomUtil.addChildElement(spElem, XML_DESCRIPTION, SecurityConstants.NAMESPACE, description); + if (descriptionLanguage != null) { + DomUtil.setAttribute(desc, "lang", Namespace.XML_NAMESPACE, descriptionLanguage); + } + } + if (supportedPrivileges != null) { + for (SupportedPrivilege supportedPrivilege : supportedPrivileges) { + spElem.appendChild(supportedPrivilege.toXml(document)); + } + } + return spElem; + } + + public Privilege getPrivilege() { + return privilege; + } + + public boolean isAbstract() { + return isAbstract; + } + + public SupportedPrivilege[] getSupportedPrivileges() { + return supportedPrivileges; + } + + /** + * Factory method to create/retrieve a SupportedPrivilege from the given + * DAV:privilege element. + * + * @param privilege + * @return + */ + static SupportedPrivilege getSupportedPrivilege(Element supportedPrivilege) throws DavException { + if (!DomUtil.matches(supportedPrivilege, XML_SUPPORTED_PRIVILEGE, SecurityConstants.NAMESPACE)) { + throw new DavException(DavServletResponse.SC_BAD_REQUEST, "DAV:supported-privilege element expected."); + } + boolean isAbstract = false; + Privilege privilege = null; + String description = null; + String descriptionLanguage = null; + List sp = new ArrayList(); + + ElementIterator children = DomUtil.getChildren(supportedPrivilege); + while (children.hasNext()) { + Element child = children.next(); + if (child.getLocalName().equals(XML_ABSTRACT)) { + isAbstract = true; + } else if (child.getLocalName().equals(Privilege.XML_PRIVILEGE)) { + privilege = Privilege.getPrivilege(child); + } else if (child.getLocalName().equals(XML_DESCRIPTION)) { + description = child.getLocalName(); + if (child.hasAttribute(descriptionLanguage)) { + descriptionLanguage = child.getAttribute(descriptionLanguage); + } + } else if (child.getLocalName().equals(XML_SUPPORTED_PRIVILEGE)) { + sp.add(getSupportedPrivilege(child)); + } + } + return new SupportedPrivilege(privilege, description, + descriptionLanguage, isAbstract, + sp.toArray(new SupportedPrivilege[sp.size()])); + } +} Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/security/SupportedPrivilege.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-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/security/SupportedPrivilegeSetProperty.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/security/SupportedPrivilegeSetProperty.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/security/SupportedPrivilegeSetProperty.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.webdav.security; + +import org.apache.jackrabbit.webdav.DavException; +import org.apache.jackrabbit.webdav.DavServletResponse; +import org.apache.jackrabbit.webdav.property.AbstractDavProperty; +import org.apache.jackrabbit.webdav.property.DavProperty; +import org.w3c.dom.Element; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.List; +import java.util.Collections; + +/** + * SupportedPrivilegeSetProperty defines the + * {@link SecurityConstants#SUPPORTED_PRIVILEGE_SET} property, used to identify + * the privileges defined for the resource. RFC 3744 defines the the following + * structure for this property: + *
+ * <!ELEMENT supported-privilege-set (supported-privilege*)>
+ * <!ELEMENT supported-privilege (privilege, abstract?, description, supported-privilege*)>
+ * <!ELEMENT privilege ANY>
+ * <!ELEMENT abstract EMPTY>
+ * <!ELEMENT description #PCDATA>
+ * 
+ * + * @see SupportedPrivilege + * @see Privilege + */ +public class SupportedPrivilegeSetProperty extends AbstractDavProperty> { + + private final SupportedPrivilege[] supportedPrivileges; + + /** + * Create a new SupportedPrivilegeSetProperty. + * + * @param supportedPrivileges + */ + public SupportedPrivilegeSetProperty(SupportedPrivilege[] supportedPrivileges) { + super(SecurityConstants.SUPPORTED_PRIVILEGE_SET, true); + this.supportedPrivileges = supportedPrivileges; + } + + public SupportedPrivilegeSetProperty(DavProperty p) throws DavException { + super(SecurityConstants.SUPPORTED_PRIVILEGE_SET, true); + if (!SecurityConstants.SUPPORTED_PRIVILEGE_SET.equals(getName())) { + throw new DavException(DavServletResponse.SC_BAD_REQUEST, "DAV:supported-privilege-set expected."); + } + + List supportedPrivs = new ArrayList(); + + for (Object obj : Collections.singletonList(p.getValue())) { + if (obj instanceof Element) { + supportedPrivs.add(SupportedPrivilege.getSupportedPrivilege((Element) obj)); + } else if (obj instanceof Collection) { + for (Object entry : ((Collection) obj)) { + if (entry instanceof Element) { + supportedPrivs.add(SupportedPrivilege.getSupportedPrivilege((Element) entry)); + } + } + } + } + supportedPrivileges = supportedPrivs.toArray(new SupportedPrivilege[supportedPrivs.size()]); + } + + /** + * @return List of {@link SupportedPrivilege}s. + */ + public List getValue() { + List l; + if (supportedPrivileges == null) { + l = Collections.emptyList(); + } else { + l = Arrays.asList(supportedPrivileges); + } + return l; + } +} \ No newline at end of file Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/security/SupportedPrivilegeSetProperty.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-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/security/package-info.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/security/package-info.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/security/package-info.java (working copy) @@ -0,0 +1,18 @@ +/* + * 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. + */ +@org.osgi.annotation.versioning.Version("1.0.0") +package org.apache.jackrabbit.webdav.security; Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/security/package-info.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/security/report/AbstractSecurityReport.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/security/report/AbstractSecurityReport.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/security/report/AbstractSecurityReport.java (working copy) @@ -0,0 +1,82 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.jackrabbit.webdav.security.report; + +import org.apache.jackrabbit.webdav.DavConstants; +import org.apache.jackrabbit.webdav.DavException; +import org.apache.jackrabbit.webdav.DavResource; +import org.apache.jackrabbit.webdav.DavServletResponse; +import org.apache.jackrabbit.webdav.MultiStatus; +import org.apache.jackrabbit.webdav.MultiStatusResponse; +import org.apache.jackrabbit.webdav.version.report.AbstractReport; +import org.apache.jackrabbit.webdav.version.report.Report; +import org.apache.jackrabbit.webdav.version.report.ReportInfo; +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +/** + * AbstractSecurityReport covers basic validation and utilities + * common to the majority of the reports defined within RFC 3744. + */ +public abstract class AbstractSecurityReport extends AbstractReport { + + protected MultiStatusResponse[] responses; + + /** + * Always returns true. + * + * @return true + */ + public boolean isMultiStatusReport() { + return true; + } + + /** + * Checks if the given resource and report info are not null, + * that the requested report type matches this implementation and that no + * other Depth header than 0 is present. + * + * @param resource + * @param info + * @throws DavException + */ + public void init(DavResource resource, ReportInfo info) throws DavException { + if (resource == null || info == null) { + throw new DavException(DavServletResponse.SC_BAD_REQUEST, "Unable to run report: WebDAV Resource and ReportInfo must not be null."); + } + if (!getType().isRequestedReportType(info)) { + throw new DavException(DavServletResponse.SC_BAD_REQUEST, "Expected report type: '" + getType().getReportName() + "', found: '" + info.getReportName() + ";" + "'."); + } + if (info.getDepth() > DavConstants.DEPTH_0) { + throw new DavException(DavServletResponse.SC_BAD_REQUEST, "Invalid Depth header: " + info.getDepth()); + } + } + + /** + * @return DAV:multistatus element listing the matching resources. + * @see Report#toXml(Document) + */ + public Element toXml(Document document) { + MultiStatus ms = new MultiStatus(); + if (responses != null) { + for (MultiStatusResponse response : responses) { + ms.addResponse(response); + } + } + return ms.toXml(document); + } +} Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/security/report/AbstractSecurityReport.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-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/security/report/AclPrincipalReport.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/security/report/AclPrincipalReport.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/security/report/AclPrincipalReport.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.webdav.security.report; + +import org.apache.jackrabbit.webdav.DavException; +import org.apache.jackrabbit.webdav.DavResource; +import org.apache.jackrabbit.webdav.DavResourceLocator; +import org.apache.jackrabbit.webdav.DavServletResponse; +import org.apache.jackrabbit.webdav.MultiStatusResponse; +import org.apache.jackrabbit.webdav.property.DavProperty; +import org.apache.jackrabbit.webdav.security.AclProperty; +import org.apache.jackrabbit.webdav.security.SecurityConstants; +import org.apache.jackrabbit.webdav.version.report.Report; +import org.apache.jackrabbit.webdav.version.report.ReportInfo; +import org.apache.jackrabbit.webdav.version.report.ReportType; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * The AclPrincipalReport report returns the requested property set + * for all principals in the DAV:acl property, that are identified by http(s) + * URLs or by a DAV:property principal. + *

+ * The request body MUST be a DAV:acl-principal-prop-set XML element: + *

+ * <!ELEMENT acl-principal-prop-set ANY>
+ * ANY value: a sequence of one or more elements, with at most one
+ *            DAV:prop element.
+ * prop: see RFC 2518, Section 12.11
+ * 
+ * The response body MUST be a DAV:multistatus element containing a + * DAV:response element for each principal identified by a http(s) URL listed + * in a DAV:principal XML element of an ACE within the DAV:acl property of the + * resource this report is requested for. + */ +public class AclPrincipalReport extends AbstractSecurityReport { + + public static final String REPORT_NAME = "acl-principal-prop-set"; + + /** + * The report type + */ + public static final ReportType REPORT_TYPE = ReportType.register(REPORT_NAME, SecurityConstants.NAMESPACE, AclPrincipalReport.class); + + /** + * @see Report#getType() + */ + public ReportType getType() { + return REPORT_TYPE; + } + + /** + * @see Report#init(DavResource, ReportInfo) + */ + @Override + public void init(DavResource resource, ReportInfo info) throws DavException { + super.init(resource, info); + // build the DAV:responses objects. + DavProperty acl = resource.getProperty(SecurityConstants.ACL); + if (!(acl instanceof AclProperty)) { + throw new DavException(DavServletResponse.SC_INTERNAL_SERVER_ERROR, "DAV:acl property expected."); + } + + DavResourceLocator loc = resource.getLocator(); + Map respMap = new HashMap(); + List list = (List) ((AclProperty)acl).getValue(); + for (AclProperty.Ace ace : list) { + String href = normalizeResourceHref(ace.getPrincipal().getHref()); + if (href == null || respMap.containsKey(href)) { + // ignore non-href principals and principals that have been listed before + continue; + } + // href-principal that has not been found before + DavResourceLocator princLocator = loc.getFactory().createResourceLocator(loc.getPrefix(), href); + DavResource principalResource = resource.getFactory().createResource(princLocator, resource.getSession()); + respMap.put(href, new MultiStatusResponse(principalResource, info.getPropertyNameSet())); + } + this.responses = respMap.values().toArray(new MultiStatusResponse[respMap.size()]); + } +} Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/security/report/AclPrincipalReport.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-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/security/report/PrincipalMatchReport.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/security/report/PrincipalMatchReport.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/security/report/PrincipalMatchReport.java (working copy) @@ -0,0 +1,115 @@ +/* + * 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.webdav.security.report; + +import org.apache.jackrabbit.webdav.DavException; +import org.apache.jackrabbit.webdav.DavResource; +import org.apache.jackrabbit.webdav.DavServletResponse; +import org.apache.jackrabbit.webdav.MultiStatusResponse; +import org.apache.jackrabbit.webdav.property.DavPropertyName; +import org.apache.jackrabbit.webdav.security.SecurityConstants; +import org.apache.jackrabbit.webdav.version.report.Report; +import org.apache.jackrabbit.webdav.version.report.ReportInfo; +import org.apache.jackrabbit.webdav.version.report.ReportType; +import org.apache.jackrabbit.webdav.xml.DomUtil; +import org.w3c.dom.Element; + +/** + * PrincipalMatchReport can be request for any collection resources. + * The resulting report identifies member resources that either represent the + * requesting principal ("principal resources") or contain a specified property + * that matches the requesting principal in its value. For the first match + * the request body must contain a DAV:self element, for the latter a + * DAV:principal-property element which in turn specifies the property to + * be examined. + *

+ * The request body MUST be a DAV:principal-match XML element: + *

+ * <!ELEMENT principal-match ((principal-property | self), prop?)>
+ * <!ELEMENT principal-property ANY>
+ * ANY value: an element whose value identifies a property. The value of this
+ * property typically contains an href element referring to a principal.
+ * <!ELEMENT self EMPTY>
+ * prop: see RFC 2518, Section 12.11
+ * 
+ * The response body of a successful report must contain a DAV:multistatus + * element. Each matching member is present with a separate DAV:response element. + */ +public class PrincipalMatchReport extends AbstractSecurityReport { + + public static final String XML_PRINCIPAL_PROPERTY = "principal-property"; + public static final String XML_SELF = "self"; + + /** + * The report name + */ + public static final String REPORT_NAME = "principal-match"; + + /** + * The report type + */ + public static final ReportType REPORT_TYPE = ReportType.register(REPORT_NAME, SecurityConstants.NAMESPACE, PrincipalMatchReport.class); + + private DavPropertyName principalPropertyName; + + /** + * @see Report#getType() + */ + public ReportType getType() { + return REPORT_TYPE; + } + + /** + * @see Report#init(DavResource, ReportInfo) + */ + @Override + public void init(DavResource resource, ReportInfo info) throws DavException { + super.init(resource, info); + if (info.containsContentElement(XML_PRINCIPAL_PROPERTY, SecurityConstants.NAMESPACE)) { + Element pp = info.getContentElement(XML_PRINCIPAL_PROPERTY, SecurityConstants.NAMESPACE); + principalPropertyName = DavPropertyName.createFromXml(DomUtil.getFirstChildElement(pp)); + } else if (info.containsContentElement(XML_SELF, SecurityConstants.NAMESPACE)) { + principalPropertyName = SecurityConstants.PRINCIPAL_URL; + } else { + throw new DavException(DavServletResponse.SC_BAD_REQUEST, "DAV:self or DAV:principal-property element required within report info."); + } + } + + //------------------------------------< implementation specific methods >--- + /** + * Retrieve the property name that indicates which property must be search + * for matching principals.
+ * Note, that the search result must be converted to {@link MultiStatusResponse}s + * that must be returned back to this report. + * + * @return property name which should be check for match with the current + * user. + * @see #setResponses(MultiStatusResponse[]) + */ + public DavPropertyName getPrincipalPropertyName() { + return principalPropertyName; + } + + /** + * Write the result(s) of the match back to the report. + * + * @param responses + */ + public void setResponses(MultiStatusResponse[] responses) { + this.responses = responses; + } +} Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/security/report/PrincipalMatchReport.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-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/security/report/PrincipalSearchReport.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/security/report/PrincipalSearchReport.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/security/report/PrincipalSearchReport.java (working copy) @@ -0,0 +1,184 @@ +/* + * 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.webdav.security.report; + +import org.apache.jackrabbit.webdav.DavConstants; +import org.apache.jackrabbit.webdav.DavException; +import org.apache.jackrabbit.webdav.DavResource; +import org.apache.jackrabbit.webdav.DavServletResponse; +import org.apache.jackrabbit.webdav.MultiStatusResponse; +import org.apache.jackrabbit.webdav.property.DavPropertyNameSet; +import org.apache.jackrabbit.webdav.property.HrefProperty; +import org.apache.jackrabbit.webdav.security.SecurityConstants; +import org.apache.jackrabbit.webdav.version.report.Report; +import org.apache.jackrabbit.webdav.version.report.ReportInfo; +import org.apache.jackrabbit.webdav.version.report.ReportType; +import org.apache.jackrabbit.webdav.xml.DomUtil; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.w3c.dom.Element; + +import java.util.List; + +/** + * The PrincipalSearchReport performs a search for all principals + * that match the search criteria specified in the request. + *

+ * The following XML structure is required in the request body: + *

+ * <!ELEMENT principal-property-search ((property-search+), prop?, apply-to-principal-collection-set?) >
+ * <!ELEMENT property-search (prop, match) >
+ *  prop: see RFC 2518, Section 12.11
+ * <!ELEMENT match #PCDATA >
+ * <!ELEMENT apply-to-principal-collection-set #EMPTY >
+ * 
+ * DAV:property-search contains lists the properties to be + * searched inside the DAV:prop element and the query string inside the DAV:match + * element. Multiple DAV:property-search elements or multiple elements within the + * DAV:prop element will be interpreted with a logical AND. + *

+ * DAV:prop lists the property names to be reported in the + * response for each of the principle resources found. + *

+ * DAV:apply-to-principal-collection-set: Optional empty element. + * If present in the request body the search will be executed over all members + * of the collections that are listed as values in the DAV:principal-collection-set + * property present on the resource the report has been requested for. + * Otherwise the search is limited to all members (at any depth) of that resource + * itself. + *

+ * The response body must contain a single DAV:multistatus XML element. + */ +public class PrincipalSearchReport extends AbstractSecurityReport { + + private static Logger log = LoggerFactory.getLogger(PrincipalSearchReport.class); + + public static final String XML_APPLY_TO_PRINCIPAL_COLLECTION_SET = "apply-to-principal-collection-set"; + public static final String XML_PROPERTY_SEARCH = "property-search"; + public static final String XML_MATCH = "match"; + + /** + * The report name + */ + public static final String REPORT_NAME = "principal-property-search"; + + /** + * The report type + */ + public static final ReportType REPORT_TYPE = ReportType.register(REPORT_NAME, SecurityConstants.NAMESPACE, PrincipalSearchReport.class); + + private String[] searchRoots; + private SearchArgument[] searchArguments; + + /** + * @see Report#getType() + */ + public ReportType getType() { + return REPORT_TYPE; + } + + /** + * @see Report#init(DavResource, ReportInfo) + */ + @Override + public void init(DavResource resource, ReportInfo info) throws DavException { + super.init(resource, info); + // make sure the request body contains all mandatory elements + if (!info.containsContentElement(XML_PROPERTY_SEARCH, SecurityConstants.NAMESPACE)) { + throw new DavException(DavServletResponse.SC_BAD_REQUEST, "Request body must contain at least a single DAV:property-search element."); + } + List psElements = info.getContentElements(XML_PROPERTY_SEARCH, SecurityConstants.NAMESPACE); + searchArguments = new SearchArgument[psElements.size()]; + int i = 0; + for (Element psElement : psElements) { + searchArguments[i++] = new SearchArgument(psElement); + } + + if (info.containsContentElement(XML_APPLY_TO_PRINCIPAL_COLLECTION_SET, SecurityConstants.NAMESPACE)) { + HrefProperty p = new HrefProperty(resource.getProperty(SecurityConstants.PRINCIPAL_COLLECTION_SET)); + searchRoots = p.getHrefs().toArray(new String[0]); + } else { + searchRoots = new String[] {resource.getHref()}; + } + } + + //------------------------------------< implementation specific methods >--- + /** + * Retrieve the the locations where the search should be performed.
+ * Note, that the search result must be converted to {@link MultiStatusResponse}s + * that must be returned back to this report. + * + * @return href of collections that act as start for the search. + * @see #setResponses(MultiStatusResponse[]) + */ + public String[] getSearchRoots() { + return searchRoots; + } + + /** + * Retrieve the search arguments used to run the search for principals.
+ * Note, that the search result must be converted to {@link MultiStatusResponse}s + * that must be returned back to this report. + * + * @return array of SearchArgument used to run the principal + * search. + * @see #setResponses(MultiStatusResponse[]) + */ + public SearchArgument[] getSearchArguments() { + return searchArguments; + } + + /** + * Write the search result back to the report. + * + * @param responses + */ + public void setResponses(MultiStatusResponse[] responses) { + this.responses = responses; + } + + //--------------------------------< implementation specific inner class >--- + /** + * Inner utility class preparing the query arguments present in the + * DAV:property-search element(s). + */ + protected class SearchArgument { + + private final DavPropertyNameSet searchProps; + private final String searchString; + + private SearchArgument(Element propSearch) { + searchProps = new DavPropertyNameSet(DomUtil.getChildElement(propSearch, DavConstants.XML_PROP, DavConstants.NAMESPACE)); + searchString = DomUtil.getChildText(propSearch, XML_MATCH, SecurityConstants.NAMESPACE); + } + + /** + * @return property name set used to restrict the search to a limited + * amount of properties. + */ + protected DavPropertyNameSet getSearchProperties() { + return searchProps; + } + + /** + * @return query string as present in the DAV:match element. + */ + protected String getSearchString() { + return searchString; + } + } +} Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/security/report/PrincipalSearchReport.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-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/security/report/SearchablePropertyReport.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/security/report/SearchablePropertyReport.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/security/report/SearchablePropertyReport.java (working copy) @@ -0,0 +1,204 @@ +/* + * 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.webdav.security.report; + +import java.util.HashSet; +import java.util.Set; + +import org.apache.jackrabbit.webdav.DavConstants; +import org.apache.jackrabbit.webdav.DavException; +import org.apache.jackrabbit.webdav.DavResource; +import org.apache.jackrabbit.webdav.DavServletResponse; +import org.apache.jackrabbit.webdav.property.DavPropertyName; +import org.apache.jackrabbit.webdav.property.DavPropertyNameSet; +import org.apache.jackrabbit.webdav.security.SecurityConstants; +import org.apache.jackrabbit.webdav.version.report.AbstractReport; +import org.apache.jackrabbit.webdav.version.report.Report; +import org.apache.jackrabbit.webdav.version.report.ReportInfo; +import org.apache.jackrabbit.webdav.version.report.ReportType; +import org.apache.jackrabbit.webdav.xml.DomUtil; +import org.apache.jackrabbit.webdav.xml.Namespace; +import org.apache.jackrabbit.webdav.xml.XmlSerializable; +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +/** + * SearchablePropertyReport identifies those properties that may be + * searched using the {@link PrincipalSearchReport DAV:principal-property-search REPORT}. + * This report must be supported on all collections identified in the value of + * a DAV:principal-collection-set property. + *

+ * The request body MUST be an empty DAV:principal-search-property-set element. + *

+ * The response body MUST be a DAV:principal-search-property-set XML element + * with the following structure: + *

+ *  <!ELEMENT principal-search-property-set (principal-search-property*) >
+ *  <!ELEMENT principal-search-property (prop, description) >
+ *  prop: see RFC 2518, Section 12.11
+ *  <!ELEMENT description #PCDATA >
+ *  Human readable description. Note, that the language of the description must
+ *  be indicated by the xml:lang attribute.
+ * 
+ * + * Note that a DAV:principal-search-property XML element is required for each + * property that may be searched with the DAV:principal-property-search REPORT. + */ +public class SearchablePropertyReport extends AbstractReport { + + /** + * The report name + */ + public static final String REPORT_NAME = "principal-search-property-set"; + + /** + * The report type + */ + public static final ReportType REPORT_TYPE = ReportType.register(REPORT_NAME, SecurityConstants.NAMESPACE, SearchablePropertyReport.class); + + /** + * Constant used for the DAV:principal-search-property-set response element. + */ + public static final String XML_PRINCIPAL_SEARCH_PROPERTY_SET = "principal-search-property-set"; + + /** + * Set collecting the DAV:principal-search-property entries. + */ + private final Set searchPropertySet = new HashSet(); + + /** + * @see Report#getType() + */ + public ReportType getType() { + return REPORT_TYPE; + } + + /** + * @return false Status code of after a successful completion must be + * {@link DavServletResponse#SC_OK 200 (ok)}. + * @see Report#isMultiStatusReport() + */ + public boolean isMultiStatusReport() { + return false; + } + + /** + * @see Report#init(DavResource, ReportInfo) + */ + public void init(DavResource resource, ReportInfo info) throws DavException { + if (resource == null || info == null) { + throw new DavException(DavServletResponse.SC_BAD_REQUEST, "Unable to run report: WebDAV Resource and ReportInfo must not be null."); + } + if (!getType().isRequestedReportType(info)) { + throw new DavException(DavServletResponse.SC_BAD_REQUEST, "Expected report type: '" + getType().getReportName() + "', found: '" + info.getReportName() + ";" + "'."); + } + if (info.getDepth() > DavConstants.DEPTH_0) { + throw new DavException(DavServletResponse.SC_BAD_REQUEST, "Invalid Depth header: " + info.getDepth()); + } + } + + /** + * @see Report#toXml(Document) + */ + public Element toXml(Document document) { + Element rootElem = DomUtil.createElement(document, XML_PRINCIPAL_SEARCH_PROPERTY_SET, SecurityConstants.NAMESPACE); + for (PrincipalSearchProperty psp : searchPropertySet) { + rootElem.appendChild(psp.toXml(document)); + } + return rootElem; + } + + //-----------------------------------------------------< implementation >--- + /** + * Add a property name that should be listed in the DAV:principal-search-property-set. + * + * @param propName a property name that may be searched in the {@link PrincipalSearchReport}. + * @param description Human readable description of the searchable property. + * @param language defines in which language the description is written. + * @throws IllegalArgumentException if propName is null. + */ + public void addPrincipalSearchProperty(DavPropertyName propName, + String description, String language) { + searchPropertySet.add(new PrincipalSearchProperty(propName, description, language)); + } + + //--------------------------------------------------------< inner class >--- + /** + * Inner class encapsulating the DAV:principal-search-property + */ + private class PrincipalSearchProperty implements XmlSerializable { + + private static final String XML_PRINCIPAL_SEARCH_PROPERTY = "principal-search-property"; + private static final String XML_DESCRIPTION = "description"; + private static final String ATTR_LANG = "lang"; + + private final DavPropertyName propName; + private final String description; + private final String language; + private final int hashCode; + + private PrincipalSearchProperty(DavPropertyName propName, + String description, + String language) { + if (propName == null) { + throw new IllegalArgumentException("null is not a valid DavPropertyName for the DAV:principal-search-property."); + } + this.propName = propName; + this.description = description; + this.language = language; + hashCode = propName.hashCode(); + } + + /** + * @see XmlSerializable#toXml(Document) + */ + public Element toXml(Document document) { + Element psElem = DomUtil.createElement(document, XML_PRINCIPAL_SEARCH_PROPERTY, SecurityConstants.NAMESPACE); + // create property set from the single property name + DavPropertyNameSet pnSet = new DavPropertyNameSet(); + pnSet.add(propName); + psElem.appendChild(pnSet.toXml(document)); + // append description if present + if (description != null) { + Element desc = DomUtil.addChildElement(psElem, XML_DESCRIPTION, SecurityConstants.NAMESPACE, description); + if (language != null) { + DomUtil.setAttribute(desc, ATTR_LANG, Namespace.XML_NAMESPACE, language); + } + } + return psElem; + } + + //---------------------------------------------------------< Object >--- + @Override + public boolean equals(Object obj) { + if (obj == this) { + return true; + } + if (obj instanceof PrincipalSearchProperty) { + PrincipalSearchProperty other = (PrincipalSearchProperty)obj; + // ignore the optional description/language + return hashCode == other.hashCode; + } + return false; + } + + @Override + public int hashCode() { + return hashCode; + } + } +} Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/security/report/SearchablePropertyReport.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-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/security/report/package-info.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/security/report/package-info.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/security/report/package-info.java (working copy) @@ -0,0 +1,18 @@ +/* + * 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. + */ +@org.osgi.annotation.versioning.Version("1.1.0") +package org.apache.jackrabbit.webdav.security.report; Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/security/report/package-info.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/server/AbstractWebdavServlet.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/server/AbstractWebdavServlet.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/server/AbstractWebdavServlet.java (working copy) @@ -0,0 +1,1557 @@ +/* + * 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.webdav.server; + +import org.apache.jackrabbit.webdav.ContentCodingAwareRequest; +import org.apache.jackrabbit.webdav.DavCompliance; +import org.apache.jackrabbit.webdav.DavConstants; +import org.apache.jackrabbit.webdav.DavException; +import org.apache.jackrabbit.webdav.DavLocatorFactory; +import org.apache.jackrabbit.webdav.DavMethods; +import org.apache.jackrabbit.webdav.DavResource; +import org.apache.jackrabbit.webdav.DavResourceFactory; +import org.apache.jackrabbit.webdav.DavServletRequest; +import org.apache.jackrabbit.webdav.DavServletResponse; +import org.apache.jackrabbit.webdav.DavSessionProvider; +import org.apache.jackrabbit.webdav.MultiStatus; +import org.apache.jackrabbit.webdav.MultiStatusResponse; +import org.apache.jackrabbit.webdav.WebdavRequest; +import org.apache.jackrabbit.webdav.WebdavRequestImpl; +import org.apache.jackrabbit.webdav.WebdavResponse; +import org.apache.jackrabbit.webdav.WebdavResponseImpl; +import org.apache.jackrabbit.webdav.bind.RebindInfo; +import org.apache.jackrabbit.webdav.bind.UnbindInfo; +import org.apache.jackrabbit.webdav.bind.BindableResource; +import org.apache.jackrabbit.webdav.bind.BindInfo; +import org.apache.jackrabbit.webdav.header.CodedUrlHeader; +import org.apache.jackrabbit.webdav.io.InputContext; +import org.apache.jackrabbit.webdav.io.InputContextImpl; +import org.apache.jackrabbit.webdav.io.OutputContext; +import org.apache.jackrabbit.webdav.io.OutputContextImpl; +import org.apache.jackrabbit.webdav.lock.ActiveLock; +import org.apache.jackrabbit.webdav.lock.LockDiscovery; +import org.apache.jackrabbit.webdav.lock.LockInfo; +import org.apache.jackrabbit.webdav.observation.EventDiscovery; +import org.apache.jackrabbit.webdav.observation.ObservationResource; +import org.apache.jackrabbit.webdav.observation.Subscription; +import org.apache.jackrabbit.webdav.observation.SubscriptionInfo; +import org.apache.jackrabbit.webdav.ordering.OrderPatch; +import org.apache.jackrabbit.webdav.ordering.OrderingResource; +import org.apache.jackrabbit.webdav.property.DavProperty; +import org.apache.jackrabbit.webdav.property.DavPropertyName; +import org.apache.jackrabbit.webdav.property.DavPropertyNameSet; +import org.apache.jackrabbit.webdav.property.DavPropertySet; +import org.apache.jackrabbit.webdav.property.PropEntry; +import org.apache.jackrabbit.webdav.search.SearchConstants; +import org.apache.jackrabbit.webdav.search.SearchInfo; +import org.apache.jackrabbit.webdav.search.SearchResource; +import org.apache.jackrabbit.webdav.security.AclProperty; +import org.apache.jackrabbit.webdav.security.AclResource; +import org.apache.jackrabbit.webdav.transaction.TransactionInfo; +import org.apache.jackrabbit.webdav.transaction.TransactionResource; +import org.apache.jackrabbit.webdav.util.CSRFUtil; +import org.apache.jackrabbit.webdav.util.HttpDateTimeFormatter; +import org.apache.jackrabbit.webdav.version.ActivityResource; +import org.apache.jackrabbit.webdav.version.DeltaVConstants; +import org.apache.jackrabbit.webdav.version.DeltaVResource; +import org.apache.jackrabbit.webdav.version.LabelInfo; +import org.apache.jackrabbit.webdav.version.MergeInfo; +import org.apache.jackrabbit.webdav.version.OptionsInfo; +import org.apache.jackrabbit.webdav.version.OptionsResponse; +import org.apache.jackrabbit.webdav.version.UpdateInfo; +import org.apache.jackrabbit.webdav.version.VersionControlledResource; +import org.apache.jackrabbit.webdav.version.VersionResource; +import org.apache.jackrabbit.webdav.version.VersionableResource; +import org.apache.jackrabbit.webdav.version.report.Report; +import org.apache.jackrabbit.webdav.version.report.ReportInfo; +import org.apache.jackrabbit.webdav.xml.DomUtil; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.time.format.DateTimeParseException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Enumeration; +import java.util.List; +import java.util.Locale; + +/** + * AbstractWebdavServlet + *

+ */ +abstract public class AbstractWebdavServlet extends HttpServlet implements DavConstants { + + // todo respect Position header + /** + * default logger + */ + private static Logger log = LoggerFactory.getLogger(AbstractWebdavServlet.class); + + /** the 'missing-auth-mapping' init parameter */ + public final static String INIT_PARAM_MISSING_AUTH_MAPPING = "missing-auth-mapping"; + + /** + * Name of the optional init parameter that defines the value of the + * 'WWW-Authenticate' header. + *

+ * If the parameter is omitted the default value + * {@link #DEFAULT_AUTHENTICATE_HEADER "Basic Realm=Jackrabbit Webdav Server"} + * is used. + * + * @see #getAuthenticateHeaderValue() + */ + public static final String INIT_PARAM_AUTHENTICATE_HEADER = "authenticate-header"; + + /** + * Default value for the 'WWW-Authenticate' header, that is set, if request + * results in a {@link DavServletResponse#SC_UNAUTHORIZED 401 (Unauthorized)} + * error. + * + * @see #getAuthenticateHeaderValue() + */ + public static final String DEFAULT_AUTHENTICATE_HEADER = "Basic realm=\"Jackrabbit Webdav Server\""; + + /** + * Name of the parameter that specifies the configuration of the CSRF protection. + * May contain a comma-separated list of allowed referrer hosts. + * If the parameter is omitted or left empty the behaviour is to only allow requests which have an empty referrer + * or a referrer host equal to the server host. + * If the parameter is set to 'disabled' no referrer checks will be performed at all. + */ + public static final String INIT_PARAM_CSRF_PROTECTION = "csrf-protection"; + + /** + * Name of the 'createAbsoluteURI' init parameter that defines whether hrefs + * should be created with a absolute URI or as absolute Path (ContextPath). + * The value should be 'true' or 'false'. The default value if not set is true. + */ + public final static String INIT_PARAM_CREATE_ABSOLUTE_URI = "createAbsoluteURI"; + + + /** + * Header value as specified in the {@link #INIT_PARAM_AUTHENTICATE_HEADER} parameter. + */ + private String authenticate_header; + + /** + * CSRF protection utility + */ + private CSRFUtil csrfUtil; + + /** + * Create per default absolute URI hrefs + */ + private boolean createAbsoluteURI = true; + + @Override + public void init() throws ServletException { + super.init(); + + // authenticate header + authenticate_header = getInitParameter(INIT_PARAM_AUTHENTICATE_HEADER); + if (authenticate_header == null) { + authenticate_header = DEFAULT_AUTHENTICATE_HEADER; + } + log.info(INIT_PARAM_AUTHENTICATE_HEADER + " = " + authenticate_header); + + // read csrf protection params + String csrfParam = getInitParameter(INIT_PARAM_CSRF_PROTECTION); + csrfUtil = new CSRFUtil(csrfParam); + log.info(INIT_PARAM_CSRF_PROTECTION + " = " + csrfParam); + + //create absolute URI hrefs.. + String param = getInitParameter(INIT_PARAM_CREATE_ABSOLUTE_URI); + if (param != null) { + createAbsoluteURI = Boolean.parseBoolean(param); + } + log.info(INIT_PARAM_CREATE_ABSOLUTE_URI + " = " + createAbsoluteURI); + } + + /** + * Checks if the precondition for this request and resource is valid. + * + * @param request + * @param resource + * @return + */ + abstract protected boolean isPreconditionValid(WebdavRequest request, DavResource resource); + + /** + * Returns the DavSessionProvider. + * + * @return the session provider + */ + abstract public DavSessionProvider getDavSessionProvider(); + + /** + * Returns the DavSessionProvider. + * + * @param davSessionProvider + */ + abstract public void setDavSessionProvider(DavSessionProvider davSessionProvider); + + /** + * Returns the DavLocatorFactory. + * + * @return the locator factory + */ + abstract public DavLocatorFactory getLocatorFactory(); + + /** + * Sets the DavLocatorFactory. + * + * @param locatorFactory + */ + abstract public void setLocatorFactory(DavLocatorFactory locatorFactory); + + /** + * Returns the DavResourceFactory. + * + * @return the resource factory + */ + abstract public DavResourceFactory getResourceFactory(); + + /** + * Sets the DavResourceFactory. + * + * @param resourceFactory + */ + abstract public void setResourceFactory(DavResourceFactory resourceFactory); + + /** + * Returns the value of the 'WWW-Authenticate' header, that is returned in + * case of 401 error: the value is retrireved from the corresponding init + * param or defaults to {@link #DEFAULT_AUTHENTICATE_HEADER}. + * + * @return corresponding init parameter or {@link #DEFAULT_AUTHENTICATE_HEADER}. + * @see #INIT_PARAM_AUTHENTICATE_HEADER + */ + public String getAuthenticateHeaderValue() { + return authenticate_header; + } + + /** + * Returns if a absolute URI should be created for hrefs. + * + * @return absolute URI hrefs + */ + protected boolean isCreateAbsoluteURI() { + return createAbsoluteURI; + } + + /** + * Service the given request. + * + * @param request + * @param response + * @throws ServletException + * @throws IOException + */ + @Override + protected void service(HttpServletRequest request, HttpServletResponse response) + throws ServletException, IOException { + + WebdavRequest webdavRequest = new WebdavRequestImpl(request, getLocatorFactory(), isCreateAbsoluteURI()); + // DeltaV requires 'Cache-Control' header for all methods except 'VERSION-CONTROL' and 'REPORT'. + int methodCode = DavMethods.getMethodCode(request.getMethod()); + boolean noCache = DavMethods.isDeltaVMethod(webdavRequest) && !(DavMethods.DAV_VERSION_CONTROL == methodCode || DavMethods.DAV_REPORT == methodCode); + WebdavResponse webdavResponse = new WebdavResponseImpl(response, noCache); + + try { + WebdavRequestContextHolder.setContext(new WebdavRequestContextImpl(webdavRequest)); + + // make sure there is a authenticated user + if (!getDavSessionProvider().attachSession(webdavRequest)) { + return; + } + + // perform referrer host checks if CSRF protection is enabled + if (!csrfUtil.isValidRequest(webdavRequest)) { + webdavResponse.sendError(HttpServletResponse.SC_FORBIDDEN); + return; + } + + // JCR-4165: reject any content-coding in request until we can + // support it (see JCR-4166) + if (!(webdavRequest instanceof ContentCodingAwareRequest)) { + List ces = getContentCodings(request); + if (!ces.isEmpty()) { + webdavResponse.setStatus(HttpServletResponse.SC_UNSUPPORTED_MEDIA_TYPE); + webdavResponse.setHeader("Accept-Encoding", "identity"); + webdavResponse.setContentType("text/plain; charset=UTF-8"); + webdavResponse.getWriter().println("Content-Encodings not supported, but received: " + ces); + webdavResponse.getWriter().flush(); + } + } + + // check matching if=header for lock-token relevant operations + DavResource resource = getResourceFactory().createResource(webdavRequest.getRequestLocator(), webdavRequest, webdavResponse); + if (!isPreconditionValid(webdavRequest, resource)) { + webdavResponse.sendError(HttpServletResponse.SC_PRECONDITION_FAILED); + return; + } + if (!execute(webdavRequest, webdavResponse, methodCode, resource)) { + super.service(request, response); + } + } catch (DavException e) { + handleDavException(webdavRequest, webdavResponse, e); + } catch (IOException ex) { + Throwable cause = ex.getCause(); + if (cause instanceof DavException) { + handleDavException(webdavRequest, webdavResponse, (DavException) cause); + } else { + throw ex; + } + } finally { + WebdavRequestContextHolder.clearContext(); + getDavSessionProvider().releaseSession(webdavRequest); + } + } + + private void handleDavException(WebdavRequest webdavRequest, WebdavResponse webdavResponse, DavException ex) + throws IOException { + if (ex.getErrorCode() == HttpServletResponse.SC_UNAUTHORIZED) { + sendUnauthorized(webdavRequest, webdavResponse, ex); + } else { + Element condition = ex.getErrorCondition(); + if (DomUtil.matches(condition, ContentCodingAwareRequest.PRECONDITION_SUPPORTED)) { + if (webdavRequest instanceof ContentCodingAwareRequest) { + webdavResponse.setHeader("Accept-Encoding", ((ContentCodingAwareRequest) webdavRequest).getAcceptableCodings()); + } + } + webdavResponse.sendError(ex); + } + } + + /** + * If request payload was uncompressed, hint about acceptable content codings (RFC 7694) + */ + private void addHintAboutPotentialRequestEncodings(WebdavRequest webdavRequest, WebdavResponse webdavResponse) { + if (webdavRequest instanceof ContentCodingAwareRequest) { + ContentCodingAwareRequest ccr = (ContentCodingAwareRequest)webdavRequest; + List ces = ccr.getRequestContentCodings(); + if (ces.isEmpty()) { + webdavResponse.setHeader("Accept-Encoding", ccr.getAcceptableCodings()); + } + } + } + + /** + * Sets the "WWW-Authenticate" header and writes the appropriate error + * to the given webdav response. + * + * @param request The webdav request. + * @param response The webdav response. + * @param error The DavException that leads to the unauthorized response. + * @throws IOException + */ + protected void sendUnauthorized(WebdavRequest request, + WebdavResponse response, DavException error) throws IOException { + response.setHeader("WWW-Authenticate", getAuthenticateHeaderValue()); + if (error == null || error.getErrorCode() != HttpServletResponse.SC_UNAUTHORIZED) { + response.sendError(HttpServletResponse.SC_UNAUTHORIZED); + } else { + response.sendError(error.getErrorCode(), error.getStatusPhrase()); + } + } + + /** + * Executes the respective method in the given webdav context + * + * @param request + * @param response + * @param method + * @param resource + * @throws ServletException + * @throws IOException + * @throws DavException + */ + protected boolean execute(WebdavRequest request, WebdavResponse response, + int method, DavResource resource) + throws ServletException, IOException, DavException { + + switch (method) { + case DavMethods.DAV_GET: + doGet(request, response, resource); + break; + case DavMethods.DAV_HEAD: + doHead(request, response, resource); + break; + case DavMethods.DAV_PROPFIND: + doPropFind(request, response, resource); + break; + case DavMethods.DAV_PROPPATCH: + doPropPatch(request, response, resource); + break; + case DavMethods.DAV_POST: + doPost(request, response, resource); + break; + case DavMethods.DAV_PUT: + doPut(request, response, resource); + break; + case DavMethods.DAV_DELETE: + doDelete(request, response, resource); + break; + case DavMethods.DAV_COPY: + doCopy(request, response, resource); + break; + case DavMethods.DAV_MOVE: + doMove(request, response, resource); + break; + case DavMethods.DAV_MKCOL: + doMkCol(request, response, resource); + break; + case DavMethods.DAV_OPTIONS: + doOptions(request, response, resource); + break; + case DavMethods.DAV_LOCK: + doLock(request, response, resource); + break; + case DavMethods.DAV_UNLOCK: + doUnlock(request, response, resource); + break; + case DavMethods.DAV_ORDERPATCH: + doOrderPatch(request, response, resource); + break; + case DavMethods.DAV_SUBSCRIBE: + doSubscribe(request, response, resource); + break; + case DavMethods.DAV_UNSUBSCRIBE: + doUnsubscribe(request, response, resource); + break; + case DavMethods.DAV_POLL: + doPoll(request, response, resource); + break; + case DavMethods.DAV_SEARCH: + doSearch(request, response, resource); + break; + case DavMethods.DAV_VERSION_CONTROL: + doVersionControl(request, response, resource); + break; + case DavMethods.DAV_LABEL: + doLabel(request, response, resource); + break; + case DavMethods.DAV_REPORT: + doReport(request, response, resource); + break; + case DavMethods.DAV_CHECKIN: + doCheckin(request, response, resource); + break; + case DavMethods.DAV_CHECKOUT: + doCheckout(request, response, resource); + break; + case DavMethods.DAV_UNCHECKOUT: + doUncheckout(request, response, resource); + break; + case DavMethods.DAV_MERGE: + doMerge(request, response, resource); + break; + case DavMethods.DAV_UPDATE: + doUpdate(request, response, resource); + break; + case DavMethods.DAV_MKWORKSPACE: + doMkWorkspace(request, response, resource); + break; + case DavMethods.DAV_MKACTIVITY: + doMkActivity(request, response, resource); + break; + case DavMethods.DAV_BASELINE_CONTROL: + doBaselineControl(request, response, resource); + break; + case DavMethods.DAV_ACL: + doAcl(request, response, resource); + break; + case DavMethods.DAV_REBIND: + doRebind(request, response, resource); + break; + case DavMethods.DAV_UNBIND: + doUnbind(request, response, resource); + break; + case DavMethods.DAV_BIND: + doBind(request, response, resource); + break; + default: + // any other method + return false; + } + return true; + } + + /** + * The OPTION method + * + * @param request + * @param response + * @param resource + */ + protected void doOptions(WebdavRequest request, WebdavResponse response, + DavResource resource) throws IOException, DavException { + response.addHeader(DavConstants.HEADER_DAV, resource.getComplianceClass()); + response.addHeader("Allow", resource.getSupportedMethods()); + response.addHeader("MS-Author-Via", DavConstants.HEADER_DAV); + if (resource instanceof SearchResource) { + String[] langs = ((SearchResource) resource).getQueryGrammerSet().getQueryLanguages(); + for (String lang : langs) { + response.addHeader(SearchConstants.HEADER_DASL, "<" + lang + ">"); + } + } + // with DeltaV the OPTIONS request may contain a Xml body. + OptionsResponse oR = null; + OptionsInfo oInfo = request.getOptionsInfo(); + if (oInfo != null && resource instanceof DeltaVResource) { + oR = ((DeltaVResource) resource).getOptionResponse(oInfo); + } + if (oR == null) { + response.setStatus(DavServletResponse.SC_OK); + } else { + response.sendXmlResponse(oR, DavServletResponse.SC_OK); + } + } + + /** + * The HEAD method + * + * @param request + * @param response + * @param resource + * @throws IOException + */ + protected void doHead(WebdavRequest request, WebdavResponse response, + DavResource resource) throws IOException { + spoolResource(request, response, resource, false); + } + + /** + * The GET method + * + * @param request + * @param response + * @param resource + * @throws IOException + */ + protected void doGet(WebdavRequest request, WebdavResponse response, + DavResource resource) throws IOException, DavException { + spoolResource(request, response, resource, true); + } + + /** + * @param request + * @param response + * @param resource + * @param sendContent + * @throws IOException + */ + private void spoolResource(WebdavRequest request, WebdavResponse response, + DavResource resource, boolean sendContent) + throws IOException { + + if (!resource.exists()) { + response.sendError(HttpServletResponse.SC_NOT_FOUND); + return; + } + + long modSince = UNDEFINED_TIME; + try { + // will throw if multiple field lines present + String value = getSingletonField(request, "If-Modified-Since"); + if (value != null) { + modSince = HttpDateTimeFormatter.parse(value); + } + } catch (IllegalArgumentException | DateTimeParseException ex) { + log.debug("illegal value for if-modified-since ignored: " + ex.getMessage()); + } + + if (modSince > UNDEFINED_TIME) { + long modTime = resource.getModificationTime(); + // test if resource has been modified. note that formatted modification + // time lost the milli-second precision + if (modTime != UNDEFINED_TIME && (modTime / 1000 * 1000) <= modSince) { + // resource has not been modified since the time indicated in the + // 'If-Modified-Since' header. + + DavProperty etagProp = resource.getProperty(DavPropertyName.GETETAG); + if (etagProp != null) { + // 304 response MUST contain Etag when available + response.setHeader("etag", etagProp.getValue().toString()); + } + response.setStatus(HttpServletResponse.SC_NOT_MODIFIED); + return; + } + } + + // spool resource properties and eventually resource content. + OutputStream out = (sendContent) ? response.getOutputStream() : null; + resource.spool(getOutputContext(response, out)); + response.flushBuffer(); + } + + /** + * The PROPFIND method + * + * @param request + * @param response + * @param resource + * @throws IOException + */ + protected void doPropFind(WebdavRequest request, WebdavResponse response, + DavResource resource) throws IOException, DavException { + + if (!resource.exists()) { + response.sendError(DavServletResponse.SC_NOT_FOUND); + return; + } + + int depth = request.getDepth(DEPTH_INFINITY); + DavPropertyNameSet requestProperties = request.getPropFindProperties(); + int propfindType = request.getPropFindType(); + + MultiStatus mstatus = new MultiStatus(); + mstatus.addResourceProperties(resource, requestProperties, propfindType, depth); + + addHintAboutPotentialRequestEncodings(request, response); + + response.sendMultiStatus(mstatus, + acceptsGzipEncoding(request) ? Collections.singletonList("gzip") : Collections.emptyList()); + } + + /** + * The PROPPATCH method + * + * @param request + * @param response + * @param resource + * @throws IOException + */ + protected void doPropPatch(WebdavRequest request, WebdavResponse response, + DavResource resource) + throws IOException, DavException { + + List changeList = request.getPropPatchChangeList(); + if (changeList.isEmpty()) { + response.sendError(DavServletResponse.SC_BAD_REQUEST); + return; + } + + MultiStatus ms = new MultiStatus(); + MultiStatusResponse msr = resource.alterProperties(changeList); + ms.addResponse(msr); + + addHintAboutPotentialRequestEncodings(request, response); + + response.sendMultiStatus(ms); + } + + /** + * The POST method. Delegate to PUT + * + * @param request + * @param response + * @param resource + * @throws IOException + * @throws DavException + */ + protected void doPost(WebdavRequest request, WebdavResponse response, + DavResource resource) throws IOException, DavException { + response.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED); + } + + /** + * The PUT method + * + * @param request + * @param response + * @param resource + * @throws IOException + * @throws DavException + */ + protected void doPut(WebdavRequest request, WebdavResponse response, + DavResource resource) throws IOException, DavException { + + if (request.getHeader("Content-Range") != null) { + response.sendError(DavServletResponse.SC_BAD_REQUEST, "Content-Range in PUT request not supported"); + return; + } + + DavResource parentResource = resource.getCollection(); + if (parentResource == null || !parentResource.exists()) { + // parent does not exist + response.sendError(DavServletResponse.SC_CONFLICT); + return; + } + + int status; + // test if resource already exists + if (resource.exists()) { + status = DavServletResponse.SC_NO_CONTENT; + } else { + status = DavServletResponse.SC_CREATED; + } + + parentResource.addMember(resource, getInputContext(request, request.getInputStream())); + response.setStatus(status); + } + + /** + * The MKCOL method + * + * @param request + * @param response + * @param resource + * @throws IOException + * @throws DavException + */ + protected void doMkCol(WebdavRequest request, WebdavResponse response, + DavResource resource) throws IOException, DavException { + + DavResource parentResource = resource.getCollection(); + if (parentResource == null || !parentResource.exists() || !parentResource.isCollection()) { + // parent does not exist or is not a collection + response.sendError(DavServletResponse.SC_CONFLICT); + return; + } + // shortcut: mkcol is only allowed on deleted/non-existing resources + if (resource.exists()) { + response.sendError(DavServletResponse.SC_METHOD_NOT_ALLOWED); + return; + } + + if (request.getContentLength() > 0 || request.getHeader("Transfer-Encoding") != null) { + parentResource.addMember(resource, getInputContext(request, request.getInputStream())); + } else { + parentResource.addMember(resource, getInputContext(request, null)); + } + response.setStatus(DavServletResponse.SC_CREATED); + } + + /** + * The DELETE method + * + * @param request + * @param response + * @param resource + * @throws IOException + * @throws DavException + */ + protected void doDelete(WebdavRequest request, WebdavResponse response, + DavResource resource) throws IOException, DavException { + DavResource parent = resource.getCollection(); + if (parent != null) { + parent.removeMember(resource); + response.setStatus(DavServletResponse.SC_NO_CONTENT); + } else { + response.sendError(DavServletResponse.SC_FORBIDDEN, "Cannot remove the root resource."); + } + } + + /** + * The COPY method + * + * @param request + * @param response + * @param resource + * @throws IOException + * @throws DavException + */ + protected void doCopy(WebdavRequest request, WebdavResponse response, + DavResource resource) throws IOException, DavException { + + // only depth 0 and infinity is allowed + int depth = request.getDepth(DEPTH_INFINITY); + if (!(depth == DEPTH_0 || depth == DEPTH_INFINITY)) { + response.sendError(DavServletResponse.SC_BAD_REQUEST); + return; + } + + DavResource destResource = getResourceFactory().createResource(request.getDestinationLocator(), request, response); + int status = validateDestination(destResource, request, true); + if (status > DavServletResponse.SC_NO_CONTENT) { + response.sendError(status); + return; + } + + resource.copy(destResource, depth == DEPTH_0); + response.setStatus(status); + } + + /** + * The MOVE method + * + * @param request + * @param response + * @param resource + * @throws IOException + * @throws DavException + */ + protected void doMove(WebdavRequest request, WebdavResponse response, + DavResource resource) throws IOException, DavException { + + DavResource destResource = getResourceFactory().createResource(request.getDestinationLocator(), request, response); + int status = validateDestination(destResource, request, true); + if (status > DavServletResponse.SC_NO_CONTENT) { + response.sendError(status); + return; + } + + resource.move(destResource); + response.setStatus(status); + } + + /** + * The BIND method + * + * @param request + * @param response + * @param resource the collection resource to which a new member will be added + * @throws IOException + * @throws DavException + */ + protected void doBind(WebdavRequest request, WebdavResponse response, + DavResource resource) throws IOException, DavException { + + if (!resource.exists()) { + response.sendError(DavServletResponse.SC_NOT_FOUND); + } + BindInfo bindInfo = request.getBindInfo(); + DavResource oldBinding = getResourceFactory().createResource(request.getHrefLocator(bindInfo.getHref()), request, response); + if (!(oldBinding instanceof BindableResource)) { + response.sendError(DavServletResponse.SC_METHOD_NOT_ALLOWED); + return; + } + DavResource newBinding = getResourceFactory().createResource(request.getMemberLocator(bindInfo.getSegment()), request, response); + int status = validateDestination(newBinding, request, false); + if (status > DavServletResponse.SC_NO_CONTENT) { + response.sendError(status); + return; + } + ((BindableResource) oldBinding).bind(resource, newBinding); + response.setStatus(status); + } + + /** + * The REBIND method + * + * @param request + * @param response + * @param resource the collection resource to which a new member will be added + * @throws IOException + * @throws DavException + */ + protected void doRebind(WebdavRequest request, WebdavResponse response, + DavResource resource) throws IOException, DavException { + + if (!resource.exists()) { + response.sendError(DavServletResponse.SC_NOT_FOUND); + } + RebindInfo rebindInfo = request.getRebindInfo(); + DavResource oldBinding = getResourceFactory().createResource(request.getHrefLocator(rebindInfo.getHref()), request, response); + if (!(oldBinding instanceof BindableResource)) { + response.sendError(DavServletResponse.SC_METHOD_NOT_ALLOWED); + return; + } + DavResource newBinding = getResourceFactory().createResource(request.getMemberLocator(rebindInfo.getSegment()), request, response); + int status = validateDestination(newBinding, request, false); + if (status > DavServletResponse.SC_NO_CONTENT) { + response.sendError(status); + return; + } + ((BindableResource) oldBinding).rebind(resource, newBinding); + response.setStatus(status); + } + + /** + * The UNBIND method + * + * @param request + * @param response + * @param resource the collection resource from which a member will be removed + * @throws IOException + * @throws DavException + */ + protected void doUnbind(WebdavRequest request, WebdavResponse response, + DavResource resource) throws IOException, DavException { + + UnbindInfo unbindInfo = request.getUnbindInfo(); + DavResource srcResource = getResourceFactory().createResource(request.getMemberLocator(unbindInfo.getSegment()), request, response); + resource.removeMember(srcResource); + } + + /** + * Validate the given destination resource and return the proper status + * code: Any return value greater/equal than {@link DavServletResponse#SC_NO_CONTENT} + * indicates an error. + * + * @param destResource destination resource to be validated. + * @param request + * @param checkHeader flag indicating if the destination header must be present. + * @return status code indicating whether the destination is valid. + */ + protected int validateDestination(DavResource destResource, WebdavRequest request, boolean checkHeader) + throws DavException { + + if (checkHeader) { + String destHeader = request.getHeader(HEADER_DESTINATION); + if (destHeader == null || "".equals(destHeader)) { + return DavServletResponse.SC_BAD_REQUEST; + } + } + if (destResource.getLocator().equals(request.getRequestLocator())) { + return DavServletResponse.SC_FORBIDDEN; + } + + int status; + if (destResource.exists()) { + if (request.isOverwrite()) { + // matching if-header required for existing resources + if (!request.matchesIfHeader(destResource)) { + return DavServletResponse.SC_PRECONDITION_FAILED; + } else { + // overwrite existing resource + DavResource col; + try { + col = destResource.getCollection(); + } + catch (IllegalArgumentException ex) { + return DavServletResponse.SC_BAD_GATEWAY; + } + col.removeMember(destResource); + status = DavServletResponse.SC_NO_CONTENT; + } + } else { + // cannot copy/move to an existing item, if overwrite is not forced + return DavServletResponse.SC_PRECONDITION_FAILED; + } + } else { + // destination does not exist >> copy/move can be performed + status = DavServletResponse.SC_CREATED; + } + return status; + } + + /** + * The LOCK method + * + * @param request + * @param response + * @param resource + * @throws IOException + * @throws DavException + */ + protected void doLock(WebdavRequest request, WebdavResponse response, + DavResource resource) throws IOException, DavException { + + LockInfo lockInfo = request.getLockInfo(); + if (lockInfo.isRefreshLock()) { + // refresh any matching existing locks + ActiveLock[] activeLocks = resource.getLocks(); + List lList = new ArrayList(); + for (ActiveLock activeLock : activeLocks) { + // adjust lockinfo with type/scope retrieved from the lock. + lockInfo.setType(activeLock.getType()); + lockInfo.setScope(activeLock.getScope()); + + DavProperty etagProp = resource.getProperty(DavPropertyName.GETETAG); + String etag = etagProp != null ? String.valueOf(etagProp.getValue()) : ""; + if (request.matchesIfHeader(resource.getHref(), activeLock.getToken(), etag)) { + lList.add(resource.refreshLock(lockInfo, activeLock.getToken())); + } + } + if (lList.isEmpty()) { + throw new DavException(DavServletResponse.SC_PRECONDITION_FAILED); + } + ActiveLock[] refreshedLocks = lList.toArray(new ActiveLock[lList.size()]); + response.sendRefreshLockResponse(refreshedLocks); + } else { + int status = HttpServletResponse.SC_OK; + if (!resource.exists()) { + // lock-empty requires status code 201 (Created) + status = HttpServletResponse.SC_CREATED; + } + + // create a new lock + ActiveLock lock = resource.lock(lockInfo); + + CodedUrlHeader header = new CodedUrlHeader( + DavConstants.HEADER_LOCK_TOKEN, lock.getToken()); + response.setHeader(header.getHeaderName(), header.getHeaderValue()); + + DavPropertySet propSet = new DavPropertySet(); + propSet.add(new LockDiscovery(lock)); + response.sendXmlResponse(propSet, status); + } + } + + /** + * The UNLOCK method + * + * @param request + * @param response + * @param resource + * @throws DavException + */ + protected void doUnlock(WebdavRequest request, WebdavResponse response, + DavResource resource) throws DavException { + // get lock token from header + String lockToken = request.getLockToken(); + TransactionInfo tInfo = request.getTransactionInfo(); + if (tInfo != null) { + ((TransactionResource) resource).unlock(lockToken, tInfo); + } else { + resource.unlock(lockToken); + } + response.setStatus(DavServletResponse.SC_NO_CONTENT); + } + + /** + * The ORDERPATCH method + * + * @param request + * @param response + * @param resource + * @throws IOException + * @throws DavException + */ + protected void doOrderPatch(WebdavRequest request, + WebdavResponse response, + DavResource resource) + throws IOException, DavException { + + if (!(resource instanceof OrderingResource)) { + response.sendError(DavServletResponse.SC_METHOD_NOT_ALLOWED); + return; + } + + OrderPatch op = request.getOrderPatch(); + if (op == null) { + response.sendError(DavServletResponse.SC_BAD_REQUEST); + return; + } + // perform reordering of internal members + ((OrderingResource) resource).orderMembers(op); + response.setStatus(DavServletResponse.SC_OK); + } + + /** + * The SUBSCRIBE method + * + * @param request + * @param response + * @param resource + * @throws IOException + * @throws DavException + */ + protected void doSubscribe(WebdavRequest request, + WebdavResponse response, + DavResource resource) + throws IOException, DavException { + + if (!(resource instanceof ObservationResource)) { + response.sendError(DavServletResponse.SC_METHOD_NOT_ALLOWED); + return; + } + + SubscriptionInfo info = request.getSubscriptionInfo(); + if (info == null) { + response.sendError(DavServletResponse.SC_UNSUPPORTED_MEDIA_TYPE); + return; + } + Subscription subs = ((ObservationResource) resource).subscribe(info, request.getSubscriptionId()); + response.sendSubscriptionResponse(subs); + } + + /** + * The UNSUBSCRIBE method + * + * @param request + * @param response + * @param resource + * @throws IOException + * @throws DavException + */ + protected void doUnsubscribe(WebdavRequest request, + WebdavResponse response, + DavResource resource) + throws IOException, DavException { + + if (!(resource instanceof ObservationResource)) { + response.sendError(DavServletResponse.SC_METHOD_NOT_ALLOWED); + return; + } + ((ObservationResource) resource).unsubscribe(request.getSubscriptionId()); + response.setStatus(DavServletResponse.SC_NO_CONTENT); + } + + /** + * The POLL method + * + * @param request + * @param response + * @param resource + * @throws IOException + * @throws DavException + */ + protected void doPoll(WebdavRequest request, + WebdavResponse response, + DavResource resource) + throws IOException, DavException { + + if (!(resource instanceof ObservationResource)) { + response.sendError(DavServletResponse.SC_METHOD_NOT_ALLOWED); + return; + } + EventDiscovery ed = ((ObservationResource) resource).poll( + request.getSubscriptionId(), request.getPollTimeout()); + response.sendPollResponse(ed); + } + + /** + * The VERSION-CONTROL method + * + * @param request + * @param response + * @param resource + * @throws DavException + * @throws IOException + */ + protected void doVersionControl(WebdavRequest request, WebdavResponse response, + DavResource resource) + throws DavException, IOException { + if (!(resource instanceof VersionableResource)) { + response.sendError(DavServletResponse.SC_METHOD_NOT_ALLOWED); + return; + } + ((VersionableResource) resource).addVersionControl(); + } + + /** + * The LABEL method + * + * @param request + * @param response + * @param resource + * @throws DavException + * @throws IOException + */ + protected void doLabel(WebdavRequest request, WebdavResponse response, + DavResource resource) + throws DavException, IOException { + + LabelInfo labelInfo = request.getLabelInfo(); + if (resource instanceof VersionResource) { + ((VersionResource) resource).label(labelInfo); + } else if (resource instanceof VersionControlledResource) { + ((VersionControlledResource) resource).label(labelInfo); + } else { + // any other resource type that does not support a LABEL request + response.sendError(DavServletResponse.SC_METHOD_NOT_ALLOWED); + } + } + + /** + * The REPORT method + * + * @param request + * @param response + * @param resource + * @throws DavException + * @throws IOException + */ + protected void doReport(WebdavRequest request, WebdavResponse response, + DavResource resource) + throws DavException, IOException { + ReportInfo info = request.getReportInfo(); + Report report; + if (resource instanceof DeltaVResource) { + report = ((DeltaVResource) resource).getReport(info); + } else if (resource instanceof AclResource) { + report = ((AclResource) resource).getReport(info); + } else { + response.sendError(DavServletResponse.SC_METHOD_NOT_ALLOWED); + return; + } + + int statusCode = (report.isMultiStatusReport()) ? DavServletResponse.SC_MULTI_STATUS : DavServletResponse.SC_OK; + addHintAboutPotentialRequestEncodings(request, response); + response.sendXmlResponse(report, statusCode, acceptsGzipEncoding(request) ? Collections.singletonList("gzip") : Collections.emptyList()); + } + + /** + * The CHECKIN method + * + * @param request + * @param response + * @param resource + * @throws DavException + * @throws IOException + */ + protected void doCheckin(WebdavRequest request, WebdavResponse response, + DavResource resource) + throws DavException, IOException { + + if (!(resource instanceof VersionControlledResource)) { + response.sendError(DavServletResponse.SC_METHOD_NOT_ALLOWED); + return; + } + String versionHref = ((VersionControlledResource) resource).checkin(); + response.setHeader(DeltaVConstants.HEADER_LOCATION, versionHref); + response.setStatus(DavServletResponse.SC_CREATED); + } + + /** + * The CHECKOUT method + * + * @param request + * @param response + * @param resource + * @throws DavException + * @throws IOException + */ + protected void doCheckout(WebdavRequest request, WebdavResponse response, + DavResource resource) + throws DavException, IOException { + if (!(resource instanceof VersionControlledResource)) { + response.sendError(DavServletResponse.SC_METHOD_NOT_ALLOWED); + return; + } + ((VersionControlledResource) resource).checkout(); + } + + /** + * The UNCHECKOUT method + * + * @param request + * @param response + * @param resource + * @throws DavException + * @throws IOException + */ + protected void doUncheckout(WebdavRequest request, WebdavResponse response, + DavResource resource) + throws DavException, IOException { + if (!(resource instanceof VersionControlledResource)) { + response.sendError(DavServletResponse.SC_METHOD_NOT_ALLOWED); + return; + } + ((VersionControlledResource) resource).uncheckout(); + } + + /** + * The MERGE method + * + * @param request + * @param response + * @param resource + * @throws DavException + * @throws IOException + */ + protected void doMerge(WebdavRequest request, WebdavResponse response, + DavResource resource) throws DavException, IOException { + + if (!(resource instanceof VersionControlledResource)) { + response.sendError(DavServletResponse.SC_METHOD_NOT_ALLOWED); + return; + } + MergeInfo info = request.getMergeInfo(); + MultiStatus ms = ((VersionControlledResource) resource).merge(info); + response.sendMultiStatus(ms); + } + + /** + * The UPDATE method + * + * @param request + * @param response + * @param resource + * @throws DavException + * @throws IOException + */ + protected void doUpdate(WebdavRequest request, WebdavResponse response, + DavResource resource) throws DavException, IOException { + + if (!(resource instanceof VersionControlledResource)) { + response.sendError(DavServletResponse.SC_METHOD_NOT_ALLOWED); + return; + } + UpdateInfo info = request.getUpdateInfo(); + MultiStatus ms = ((VersionControlledResource) resource).update(info); + response.sendMultiStatus(ms); + } + + /** + * The MKWORKSPACE method + * + * @param request + * @param response + * @param resource + * @throws DavException + * @throws IOException + */ + protected void doMkWorkspace(WebdavRequest request, WebdavResponse response, + DavResource resource) throws DavException, IOException { + if (resource.exists()) { + AbstractWebdavServlet.log.warn("Cannot create a new workspace. Resource already exists."); + response.sendError(DavServletResponse.SC_FORBIDDEN); + return; + } + + DavResource parentResource = resource.getCollection(); + if (parentResource == null || !parentResource.exists() || !parentResource.isCollection()) { + // parent does not exist or is not a collection + response.sendError(DavServletResponse.SC_CONFLICT); + return; + } + if (!(parentResource instanceof DeltaVResource)) { + response.sendError(DavServletResponse.SC_METHOD_NOT_ALLOWED); + return; + } + ((DeltaVResource) parentResource).addWorkspace(resource); + response.setStatus(DavServletResponse.SC_CREATED); + } + + /** + * The MKACTIVITY method + * + * @param request + * @param response + * @param resource + * @throws DavException + * @throws IOException + */ + protected void doMkActivity(WebdavRequest request, WebdavResponse response, + DavResource resource) throws DavException, IOException { + if (resource.exists()) { + AbstractWebdavServlet.log.warn("Unable to create activity: A resource already exists at the request-URL " + request.getRequestURL()); + response.sendError(DavServletResponse.SC_FORBIDDEN); + return; + } + + DavResource parentResource = resource.getCollection(); + if (parentResource == null || !parentResource.exists() || !parentResource.isCollection()) { + // parent does not exist or is not a collection + response.sendError(DavServletResponse.SC_CONFLICT); + return; + } + // TODO: improve. see http://issues.apache.org/jira/browse/JCR-394 + if (!parentResource.getComplianceClass().contains(DavCompliance.ACTIVITY)) { + response.sendError(DavServletResponse.SC_METHOD_NOT_ALLOWED); + return; + } + + if (!(resource instanceof ActivityResource)) { + AbstractWebdavServlet.log.error("Unable to create activity: ActivityResource expected"); + response.sendError(DavServletResponse.SC_INTERNAL_SERVER_ERROR); + return; + } + + // try to add the new activity resource + parentResource.addMember(resource, getInputContext(request, request.getInputStream())); + + // Note: mandatory cache control header has already been set upon response creation. + response.setStatus(DavServletResponse.SC_CREATED); + } + + /** + * The BASELINECONTROL method + * + * @param request + * @param response + * @param resource + * @throws DavException + * @throws IOException + */ + protected void doBaselineControl(WebdavRequest request, WebdavResponse response, + DavResource resource) + throws DavException, IOException { + + if (!resource.exists()) { + AbstractWebdavServlet.log.warn("Unable to add baseline control. Resource does not exist " + resource.getHref()); + response.sendError(DavServletResponse.SC_NOT_FOUND); + return; + } + // TODO: improve. see http://issues.apache.org/jira/browse/JCR-394 + if (!(resource instanceof VersionControlledResource) || !resource.isCollection()) { + AbstractWebdavServlet.log.warn("BaselineControl is not supported by resource " + resource.getHref()); + response.sendError(DavServletResponse.SC_METHOD_NOT_ALLOWED); + return; + } + + // TODO : missing method on VersionControlledResource + throw new DavException(DavServletResponse.SC_NOT_IMPLEMENTED); + /* + ((VersionControlledResource) resource).addBaselineControl(request.getRequestDocument()); + // Note: mandatory cache control header has already been set upon response creation. + response.setStatus(DavServletResponse.SC_OK); + */ + } + + /** + * The SEARCH method + * + * @param request + * @param response + * @param resource + * @throws DavException + * @throws IOException + */ + protected void doSearch(WebdavRequest request, WebdavResponse response, + DavResource resource) throws DavException, IOException { + + if (!(resource instanceof SearchResource)) { + response.sendError(DavServletResponse.SC_METHOD_NOT_ALLOWED); + return; + } + Document doc = request.getRequestDocument(); + if (doc != null) { + SearchInfo sR = SearchInfo.createFromXml(doc.getDocumentElement()); + response.sendMultiStatus(((SearchResource) resource).search(sR)); + } else { + // request without request body is valid if requested resource + // is a 'query' resource. + response.sendMultiStatus(((SearchResource) resource).search(null)); + } + } + + /** + * The ACL method + * + * @param request + * @param response + * @param resource + * @throws DavException + * @throws IOException + */ + protected void doAcl(WebdavRequest request, WebdavResponse response, + DavResource resource) throws DavException, IOException { + if (!(resource instanceof AclResource)) { + response.sendError(DavServletResponse.SC_METHOD_NOT_ALLOWED); + return; + } + Document doc = request.getRequestDocument(); + if (doc == null) { + throw new DavException(DavServletResponse.SC_BAD_REQUEST, "ACL request requires a DAV:acl body."); + } + AclProperty acl = AclProperty.createFromXml(doc.getDocumentElement()); + ((AclResource)resource).alterAcl(acl); + } + + /** + * Return a new InputContext used for adding resource members + * + * @param request + * @param in + * @return + * @see #spoolResource(WebdavRequest, WebdavResponse, DavResource, boolean) + */ + protected InputContext getInputContext(DavServletRequest request, InputStream in) { + return new InputContextImpl(request, in); + } + + /** + * Return a new OutputContext used for spooling resource properties and + * the resource content + * + * @param response + * @param out + * @return + * @see #doPut(WebdavRequest, WebdavResponse, DavResource) + * @see #doMkCol(WebdavRequest, WebdavResponse, DavResource) + */ + protected OutputContext getOutputContext(DavServletResponse response, OutputStream out) { + return new OutputContextImpl(response, out); + } + + /** + * Obtain the (ordered!) list of content codings that have been used in the + * request + */ + public static List getContentCodings(HttpServletRequest request) { + return getListElementsFromHeaderField(request, "Content-Encoding"); + } + + /** + * Check whether recipient accepts GZIP content coding + */ + private static boolean acceptsGzipEncoding(HttpServletRequest request) { + List result = getListElementsFromHeaderField(request, "Accept-Encoding"); + for (String s : result) { + s = s.replace(" ", ""); + int semi = s.indexOf(';'); + if ("gzip".equals(s)) { + return true; + } else if (semi > 0) { + String enc = s.substring(0, semi); + String parm = s.substring(semi + 1); + if ("gzip".equals(enc) && parm.startsWith("q=")) { + float q = Float.valueOf(parm.substring(2)); + return q > 0; + } + } + } + return false; + } + + private static List getListElementsFromHeaderField(HttpServletRequest request, String fieldName) { + List result = Collections.emptyList(); + for (Enumeration ceh = request.getHeaders(fieldName); ceh.hasMoreElements();) { + for (String h : ceh.nextElement().split(",")) { + if (!h.trim().isEmpty()) { + if (result.isEmpty()) { + result = new ArrayList(); + } + result.add(h.trim().toLowerCase(Locale.ENGLISH)); + } + } + } + + return result; + } + + /** + * Get field value of a singleton field + * @param request HTTP request + * @param fieldName field name + * @return the field value (when there is indeed a single field line) or {@code null} when field not present + * @throws IllegalArgumentException when multiple field lines present + */ + protected static String getSingletonField(HttpServletRequest request, String fieldName) { + Enumeration lines = request.getHeaders(fieldName); + if (!lines.hasMoreElements()) { + return null; + } else { + String value = lines.nextElement(); + if (!lines.hasMoreElements()) { + return value; + } else { + List v = new ArrayList<>(); + v.add(value); + while (lines.hasMoreElements()) { + v.add(lines.nextElement()); + } + throw new IllegalArgumentException("Multiple field lines for '" + fieldName + "' header field: " + v); + } + } + } +} + Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/server/AbstractWebdavServlet.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-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/server/WebdavRequestContextHolder.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/server/WebdavRequestContextHolder.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/server/WebdavRequestContextHolder.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.webdav.server; + +import org.apache.jackrabbit.webdav.WebdavRequestContext; + +/** + * Associates a {@link WebdavRequestContext} with the current execution thread. + */ +public final class WebdavRequestContextHolder { + + private static ThreadLocal tlWebdavRequestContext = new ThreadLocal<>(); + + private WebdavRequestContextHolder() { + } + + /** + * Return the {@link WebdavRequestContext} with the current execution thread. + * @return the {@link WebdavRequestContext} with the current execution thread + */ + public static WebdavRequestContext getContext() { + return tlWebdavRequestContext.get(); + } + + static void setContext(WebdavRequestContext context) { + tlWebdavRequestContext.set(context); + } + + static void clearContext() { + tlWebdavRequestContext.remove(); + } +} Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/server/WebdavRequestContextHolder.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/server/WebdavRequestContextImpl.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/server/WebdavRequestContextImpl.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/server/WebdavRequestContextImpl.java (working copy) @@ -0,0 +1,35 @@ +/* + * 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.webdav.server; + +import org.apache.jackrabbit.webdav.WebdavRequest; +import org.apache.jackrabbit.webdav.WebdavRequestContext; + +class WebdavRequestContextImpl implements WebdavRequestContext { + + private final WebdavRequest request; + + WebdavRequestContextImpl(final WebdavRequest request) { + this.request = request; + } + + @Override + public WebdavRequest getRequest() { + return request; + } + +} Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/server/WebdavRequestContextImpl.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/server/package-info.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/server/package-info.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/server/package-info.java (working copy) @@ -0,0 +1,18 @@ +/* + * 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. + */ +@org.osgi.annotation.versioning.Version("1.2.0") +package org.apache.jackrabbit.webdav.server; Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/server/package-info.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/transaction/TransactionConstants.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/transaction/TransactionConstants.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/transaction/TransactionConstants.java (working copy) @@ -0,0 +1,125 @@ +/* + * 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.webdav.transaction; + +import org.apache.jackrabbit.webdav.DavConstants; +import org.apache.jackrabbit.webdav.lock.Scope; +import org.apache.jackrabbit.webdav.lock.Type; +import org.apache.jackrabbit.webdav.xml.Namespace; + +/** + * TransactionConstants interface provide constants for request + * and response headers, Xml elements and property names used for handling + * transactions over WebDAV. There exists no public standard for this functionality. + * + * todo: 'local' and 'global' are not accurate terms in the given context > replace + */ +public interface TransactionConstants { + + /** + * Namespace for transaction related xml elements + */ + public static final Namespace NAMESPACE = Namespace.getNamespace("dcr", "http://www.day.com/jcr/webdav/1.0"); + + //---< Headers >------------------------------------------------------------ + /** + * TransactionId Header + */ + public static final String HEADER_TRANSACTIONID = "TransactionId"; + + //---< XML Element, Attribute Names >--------------------------------------- + /** + * transaction XML element
+ * Used as element inside the {@link DavConstants#XML_LOCKTYPE locktype} + * element. + * @see DavConstants#XML_LOCKTYPE + */ + public static final String XML_TRANSACTION = "transaction"; + + /** + * global XML element
+ * Used as element inside of the {@link DavConstants#XML_LOCKSCOPE lockscope} element. + * + * @see DavConstants#XML_LOCKSCOPE + */ + public static final String XML_GLOBAL = "global"; + + /** + * local XML element
+ * Used as element inside of the {@link DavConstants#XML_LOCKSCOPE lockscope} element. + * It indicates the transaction to be local (e.g. transient changes to + * a repository). + * + * @see DavConstants#XML_LOCKSCOPE + */ + public static final String XML_LOCAL = "local"; + + /** + * transactioninfo XML element
+ * Mandatory element of the UNLOCK request body, if the unlock request + * is intended to complete a transaction. + */ + public static final String XML_TRANSACTIONINFO = "transactioninfo"; + + /** + * transactionstatus XML element
+ * Mandatory element inside the {@link #XML_TRANSACTIONINFO transactioninfo} + * element indicating how the transaction should be completed. + * @see #XML_TRANSACTIONINFO + */ + public static final String XML_TRANSACTIONSTATUS = "transactionstatus"; + + /** + * commit XML element
+ * Used as element inside of the {@link #XML_TRANSACTIONSTATUS transactionstatus} + * element. It indicates a completion by committing the transaction. + * @see #XML_TRANSACTIONSTATUS + */ + public static final String XML_COMMIT = "commit"; + + /** + * rollback XML element
+ * Used as element inside of the {@link #XML_TRANSACTIONSTATUS transactionstatus} + * element. It indicates a completion by roll backing the transaction. + * @see #XML_TRANSACTIONSTATUS + */ + public static final String XML_ROLLBACK = "rollback"; + + //---< Lock Type, Lock Scope >---------------------------------------------- + /** + * "transaction" lock type constant. + * @see #XML_TRANSACTION + * @see Type#create(String, Namespace) + */ + public static final Type TRANSACTION = Type.create(XML_TRANSACTION, TransactionConstants.NAMESPACE); + + /** + * "local" lock scope constant. + * + * @see #XML_LOCAL + * @see Scope#create(String, Namespace) + */ + public static final Scope LOCAL = Scope.create(XML_LOCAL, TransactionConstants.NAMESPACE); + + /** + * "global" lock scope constant. + * + * @see #XML_GLOBAL + * @see Scope#create(String, Namespace) + */ + public static final Scope GLOBAL = Scope.create(XML_GLOBAL, TransactionConstants.NAMESPACE); +} \ No newline at end of file Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/transaction/TransactionConstants.java ___________________________________________________________________ Added: svn Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/transaction/TransactionDavServletRequest.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/transaction/TransactionDavServletRequest.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/transaction/TransactionDavServletRequest.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.webdav.transaction; + +import org.apache.jackrabbit.webdav.DavException; +import org.apache.jackrabbit.webdav.DavServletRequest; + +/** + * TransactionDavServletRequest provides extensions to the + * {@link DavServletRequest} interface used for dealing with transaction lock + * requests. + */ +public interface TransactionDavServletRequest extends DavServletRequest { + + /** + * Retrieve the 'transactioninfo' request body that must be included with + * the UNLOCK request of a transaction lock. If the request body is does not + * provide the information required (either because it is missing or the + * Xml is not valid) null is returned. + * + * @return TransactionInfo object encapsulating the 'transactioninfo' + * Xml element present in the request body or null if no + * body is present or if it could not be parsed. + * @throws DavException if an invalid request body is present. + */ + public TransactionInfo getTransactionInfo() throws DavException; + + + /** + * Retrieve the transaction id from the + * {@link TransactionConstants#HEADER_TRANSACTIONID TransactionId header}. + * + * @return transaction id as present in the {@link TransactionConstants#HEADER_TRANSACTIONID TransactionId header} + * or null. + */ + public String getTransactionId(); +} \ No newline at end of file Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/transaction/TransactionDavServletRequest.java ___________________________________________________________________ Added: svn Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/transaction/TransactionInfo.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/transaction/TransactionInfo.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/transaction/TransactionInfo.java (working copy) @@ -0,0 +1,105 @@ +/* + * 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.webdav.transaction; + +import org.apache.jackrabbit.webdav.DavException; +import org.apache.jackrabbit.webdav.DavServletResponse; +import org.apache.jackrabbit.webdav.xml.DomUtil; +import org.apache.jackrabbit.webdav.xml.XmlSerializable; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +/** + * TransactionInfo class encapsulates the information present + * in the {@link #XML_TRANSACTIONINFO} element that forms the request body of + * the UNLOCk request for a transaction lock. + * + * @see TransactionConstants#XML_TRANSACTIONINFO + * @see TransactionConstants#XML_TRANSACTION + */ +public class TransactionInfo implements TransactionConstants, XmlSerializable { + + private static Logger log = LoggerFactory.getLogger(TransactionInfo.class); + + private final boolean isCommit; + + /** + * Creates a TransactionInfo object + * + * @param isCommit + */ + public TransactionInfo(boolean isCommit) { + this.isCommit = isCommit; + } + + /** + * Creates a TransactionInfo object from the given 'transactionInfo' + * element. The 'transactionInfo' must have the following form: + *

+     *
+     *  <!ELEMENT transactioninfo (transactionstatus) >
+     *  <!ELEMENT transactionstatus ( commit | rollback ) >
+     *  <!ELEMENT commit EMPTY >
+     *  <!ELEMENT rollback EMPTY >
+     * 
+ * @param transactionInfo as present in the UNLOCK request body. + * @throws IllegalArgumentException if the given transactionInfo element + * is not valid. + */ + public TransactionInfo(Element transactionInfo) throws DavException { + if (transactionInfo == null || !XML_TRANSACTIONINFO.equals(transactionInfo.getLocalName())) { + log.warn("'transactionInfo' element expected."); + throw new DavException(DavServletResponse.SC_BAD_REQUEST); + } + Element txStatus = DomUtil.getChildElement(transactionInfo, XML_TRANSACTIONSTATUS, NAMESPACE); + if (txStatus != null) { + // retrieve status: commit or rollback + isCommit = DomUtil.hasChildElement(txStatus, XML_COMMIT, NAMESPACE); + } else { + log.warn("transactionInfo must contain a single 'transactionstatus' element."); + throw new DavException(DavServletResponse.SC_BAD_REQUEST); + } + } + + /** + * Returns true, if this info requires a 'commit' action, false otherwise + * (i.e. 'rollback' is requested). + * + * @return true if a 'commit' element was present. false otherwise. + * @see #XML_COMMIT + * @see #XML_ROLLBACK + */ + public boolean isCommit() { + return isCommit; + } + + //------------------------------------------< XmlSerializable interface >--- + /** + * @see org.apache.jackrabbit.webdav.xml.XmlSerializable#toXml(Document) + * @param document + */ + public Element toXml(Document document) { + Element elem = DomUtil.createElement(document, XML_TRANSACTIONINFO, NAMESPACE); + Element st = DomUtil.addChildElement(elem, XML_TRANSACTIONSTATUS, NAMESPACE); + String lName = (isCommit) ? XML_COMMIT : XML_ROLLBACK; + DomUtil.addChildElement(st, lName, NAMESPACE); + return elem; + } + +} \ No newline at end of file Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/transaction/TransactionInfo.java ___________________________________________________________________ Added: svn Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/transaction/TransactionResource.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/transaction/TransactionResource.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/transaction/TransactionResource.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.webdav.transaction; + +import org.apache.jackrabbit.webdav.DavException; +import org.apache.jackrabbit.webdav.DavResource; + +/** + * TransactionResource extends the {@link DavResource} interface by + * transaction relevant METHODS. + */ +public interface TransactionResource extends DavResource { + + public static final String METHODS = ""; + + /** + * Initializes the TransactionResource. + * + * @param txMgr + * @param transactionId + */ + public void init(TxLockManager txMgr, String transactionId); + + /** + * The TransactionId or null according to the value of the + * corresponding request {@link TransactionConstants#HEADER_TRANSACTIONID header} + * field. + * + * @return TransactionId header or null + */ + public String getTransactionId(); + + /** + * Overloads the {@link DavResource#unlock unlock} method of the DavResource + * interface. + * + * @param lockToken lock token as present in the request header. + * @param info transaction info object as present in the UNLOCK request body. + * @throws DavException if an error occurs + * @see DavResource#unlock(String) + * @see TransactionDavServletRequest#getTransactionId() + * @see org.apache.jackrabbit.webdav.DavServletRequest#getLockToken() + */ + public void unlock(String lockToken, TransactionInfo info) throws DavException; +} \ No newline at end of file Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/transaction/TransactionResource.java ___________________________________________________________________ Added: svn Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/transaction/TxActiveLock.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/transaction/TxActiveLock.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/transaction/TxActiveLock.java (working copy) @@ -0,0 +1,93 @@ +/* + * 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.webdav.transaction; + +import org.apache.jackrabbit.webdav.lock.DefaultActiveLock; +import org.apache.jackrabbit.webdav.lock.LockInfo; +import org.apache.jackrabbit.webdav.lock.Scope; +import org.apache.jackrabbit.webdav.lock.Type; + +/** + * TxActiveLock represents the transaction lock present on a + * {@link TransactionResource}. + */ +public class TxActiveLock extends DefaultActiveLock implements TransactionConstants { + + public static final long DEFAULT_TIMEOUT = 300000; // 5 minutes + + private final Scope scope; + + /** + * Create a new transaction lock.
+ * If the lockInfo element is null the timeout defaults to + * half and hour. The default scope is 'local'. + * + * @param lockInfo + * @throws IllegalArgumentException if either scope or type is invalid or if + * a depth other than infinity is requested. + */ + public TxActiveLock(LockInfo lockInfo) { + if (lockInfo != null) { + if (!TRANSACTION.equals(lockInfo.getType())) { + throw new IllegalArgumentException("Only 'transaction' type is allowed for a transaction-activelock object."); + } + if (!(LOCAL.equals(lockInfo.getScope()) || GLOBAL.equals(lockInfo.getScope()))) { + throw new IllegalArgumentException("Only 'global' or 'local' are valid scopes within a transaction-activelock element."); + } + if (!lockInfo.isDeep()) { + throw new IllegalArgumentException("Only transaction locks can only be deep."); + } + setOwner(lockInfo.getOwner()); + setTimeout(lockInfo.getTimeout()); + scope = lockInfo.getScope(); + } else { + setTimeout(DEFAULT_TIMEOUT); + // local scope by default + scope = LOCAL; + } + } + + /** + * Always returns true. + * + * @return true + */ + @Override + public boolean isDeep() { + return true; + } + + /** + * Always returns the {@link #TRANSACTION} type. + * + * @return {@link #TRANSACTION} + */ + @Override + public Type getType() { + return TRANSACTION; + } + + /** + * Returns the scope of this lock which is either {@link #LOCAL} or {@link #GLOBAL}. + * + * @return {@link #LOCAL} or {@link #GLOBAL} + */ + @Override + public Scope getScope() { + return scope; + } +} Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/transaction/TxActiveLock.java ___________________________________________________________________ Added: svn Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/transaction/TxLockEntry.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/transaction/TxLockEntry.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/transaction/TxLockEntry.java (working copy) @@ -0,0 +1,72 @@ +/* + * 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.webdav.transaction; + +import org.apache.jackrabbit.webdav.lock.AbstractLockEntry; +import org.apache.jackrabbit.webdav.lock.Scope; +import org.apache.jackrabbit.webdav.lock.Type; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * TxLockEntry represents the lock entry objects allowed for + * a transaction lock. + */ +public final class TxLockEntry extends AbstractLockEntry implements TransactionConstants { + + private static Logger log = LoggerFactory.getLogger(TxLockEntry.class); + + private final Scope scope; + + /** + * Create a lock entry that identifies transaction lock. + * + * @param isLocal boolean value indicating whether this is a local or a global + * lock entry. + */ + public TxLockEntry(boolean isLocal) { + if (isLocal) { + scope = LOCAL; + } else { + scope = GLOBAL; + } + } + + /** + * Returns the {@link #TRANSACTION 'transaction'} lock type. + * + * @return always returns the 'transaction' type. + * @see org.apache.jackrabbit.webdav.lock.LockEntry#getType() + * @see #TRANSACTION + */ + public Type getType() { + return TRANSACTION; + } + + /** + * Returns either {@link #LOCAL local} or {@link #GLOBAL global} scope + * depending on the initial constructor value. + * + * @return returns 'global' or 'local' scope. + * @see org.apache.jackrabbit.webdav.lock.LockEntry#getScope() + * @see #GLOBAL + * @see #LOCAL + */ + public Scope getScope() { + return scope; + } +} \ No newline at end of file Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/transaction/TxLockEntry.java ___________________________________________________________________ Added: svn Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/transaction/TxLockManager.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/transaction/TxLockManager.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/transaction/TxLockManager.java (working copy) @@ -0,0 +1,65 @@ +/* + * 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.webdav.transaction; + +import org.apache.jackrabbit.webdav.DavException; +import org.apache.jackrabbit.webdav.lock.ActiveLock; +import org.apache.jackrabbit.webdav.lock.LockManager; +import org.apache.jackrabbit.webdav.lock.Scope; +import org.apache.jackrabbit.webdav.lock.Type; + +/** + * TxLockManager manages locks with locktype + * '{@link TransactionConstants#TRANSACTION dcr:transaction}'. + * + * todo: removing all expired locks + * todo: 'local' and 'global' are not accurate terms in the given context > replace + * todo: the usage of the 'global' transaction is not according to the JTA specification, + * which explicitly requires any transaction present on a servlet to be completed before + * the service method returns. Starting/completing transactions on the session object, + * which is possible with the jackrabbit implementation is a hack. + * todo: review of this transaction part is therefore required. Is there a use-case + * for those 'global' transactions at all... + */ +public interface TxLockManager extends LockManager { + + + /** + * Release the lock identified by the given lock token. + * + * @param lockInfo + * @param lockToken + * @param resource + * @throws org.apache.jackrabbit.webdav.DavException + */ + public void releaseLock(TransactionInfo lockInfo, String lockToken, + TransactionResource resource) throws DavException; + + + /** + * Return the lock applied to the given resource or null + * + * @param type + * @param scope + * @param resource + * @return lock applied to the given resource or null + * @see org.apache.jackrabbit.webdav.lock.LockManager#getLock(org.apache.jackrabbit.webdav.lock.Type, org.apache.jackrabbit.webdav.lock.Scope, org.apache.jackrabbit.webdav.DavResource) + */ + public ActiveLock getLock(Type type, Scope scope, TransactionResource resource); + + +} Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/transaction/TxLockManager.java ___________________________________________________________________ Added: svn Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/transaction/package-info.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/transaction/package-info.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/transaction/package-info.java (working copy) @@ -0,0 +1,18 @@ +/* + * 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. + */ +@org.osgi.annotation.versioning.Version("1.0.0") +package org.apache.jackrabbit.webdav.transaction; Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/transaction/package-info.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/util/CSRFUtil.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/util/CSRFUtil.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/util/CSRFUtil.java (working copy) @@ -0,0 +1,168 @@ +/* + * 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.webdav.util; + +import java.net.URI; +import java.net.URISyntaxException; +import java.util.Arrays; +import java.util.Collections; +import java.util.Enumeration; +import java.util.HashSet; +import java.util.Locale; +import java.util.Set; + +import javax.servlet.http.HttpServletRequest; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * CSRFUtil... + */ +public class CSRFUtil { + + /** + * Constant used to + */ + public static final String DISABLED = "disabled"; + + /** + * Request content types for CSRF checking, see JCR-3909, JCR-4002, and JCR-4009 + */ + public static final Set CONTENT_TYPES = Collections.unmodifiableSet(new HashSet( + Arrays.asList( + new String[] { + "application/x-www-form-urlencoded", + "multipart/form-data", + "text/plain" + } + ) + )); + + /** + * logger instance + */ + private static final Logger log = LoggerFactory.getLogger(CSRFUtil.class); + + /** + * Disable referrer based CSRF protection + */ + private final boolean disabled; + + /** + * Additional allowed referrer hosts for CSRF protection + */ + private final Set allowedReferrerHosts; + + /** + * Creates a new instance from the specified configuration, which defines + * the behaviour of the referrer based CSRF protection as follows: + *
    + *
  1. If config is null or empty string the default + * behaviour is to allow only requests with an empty referrer header or a + * referrer host equal to the server host
  2. + *
  3. A comma separated list of additional allowed referrer hosts which are + * valid in addition to default behaviour (see above).
  4. + *
  5. The value {@link #DISABLED} may be used to disable the referrer checking altogether
  6. + *
+ * + * @param config The configuration value which may be any of the following: + *
    + *
  • null or empty string for the default behaviour, which + * only allows requests with an empty referrer header or a + * referrer host equal to the server host
  • + *
  • A comma separated list of additional allowed referrer hosts which are + * valid in addition to default behaviour (see above).
  • + *
  • {@link #DISABLED} in order to disable the referrer checking altogether
  • + *
+ */ + public CSRFUtil(String config) { + if (config == null || config.length() == 0) { + disabled = false; + allowedReferrerHosts = Collections.emptySet(); + log.debug("CSRF protection disabled"); + } else { + if (DISABLED.equalsIgnoreCase(config.trim())) { + disabled = true; + allowedReferrerHosts = Collections.emptySet(); + } else { + disabled = false; + String[] allowed = config.split(","); + allowedReferrerHosts = new HashSet(allowed.length); + for (String entry : allowed) { + allowedReferrerHosts.add(entry.trim()); + } + } + log.debug("CSRF protection enabled, allowed referrers: " + allowedReferrerHosts); + } + } + + public boolean isValidRequest(HttpServletRequest request) { + + if (disabled) { + return true; + } else if (!"POST".equals(request.getMethod())) { + // protection only needed for POST + return true; + } else { + Enumeration cts = (Enumeration) request.getHeaders("Content-Type"); + String ct = null; + if (cts != null && cts.hasMoreElements()) { + String t = cts.nextElement(); + // prune parameters + int semicolon = t.indexOf(';'); + if (semicolon >= 0) { + t = t.substring(0, semicolon); + } + ct = t.trim().toLowerCase(Locale.ENGLISH); + } + if (cts != null && cts.hasMoreElements()) { + // reject if there are more header field instances + log.debug("request blocked because there were multiple content-type header fields"); + return false; + } + if (ct != null && !CONTENT_TYPES.contains(ct)) { + // type present and not in blacklist + return true; + } + + String refHeader = request.getHeader("Referer"); + // empty referrer headers are not allowed for POST + relevant + // content types (see JCR-3909) + if (refHeader == null) { + log.debug("POST with content type " + ct + " blocked due to missing referer header field"); + return false; + } + + try { + String host = new URI(refHeader).getHost(); + // test referrer-host equals server or + // if it is contained in the set of explicitly allowed host + // names + boolean ok = host == null || host.equals(request.getServerName()) || allowedReferrerHosts.contains(host); + if (!ok) { + log.debug("POST with content type " + ct + " blocked due to referer header field being: " + refHeader); + } + return ok; + } catch (URISyntaxException ex) { + // referrer malformed -> block access + log.debug("POST with content type " + ct + " blocked due to malformed referer header field: " + refHeader); + return false; + } + } + } +} \ No newline at end of file Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/util/CSRFUtil.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-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/util/EncodeUtil.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/util/EncodeUtil.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/util/EncodeUtil.java (working copy) @@ -0,0 +1,220 @@ +/* + * 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.webdav.util; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.ByteArrayOutputStream; +import java.io.UnsupportedEncodingException; +import java.nio.charset.StandardCharsets; +import java.util.BitSet; + +/** + * EncodeUtil provides helper methods for URL encoding and decoding + * (copied from jcr-commons jackrabbit.util.Text). + * + * @see JCR-2897. + */ +public final class EncodeUtil { + + /** + * logger instance + */ + private static final Logger log = LoggerFactory.getLogger(EncodeUtil.class); + + /** + * hextable used for {@link #escape(String, char, boolean)} + */ + public static final char[] hexTable = "0123456789abcdef".toCharArray(); + + /** + * The list of characters that are not encoded by the escape() + * and unescape() METHODS. They contains the characters as + * defined 'unreserved' in section 2.3 of the RFC 2396 'URI generic syntax': + *

+ *

+     * unreserved  = alphanum | mark
+     * mark        = "-" | "_" | "." | "!" | "~" | "*" | "'" | "(" | ")"
+     * 
+ */ + private static BitSet URISave; + + /** + * Same as {@link #URISave} but also contains the '/' + */ + private static BitSet URISaveEx; + + static { + URISave = new BitSet(256); + int i; + for (i = 'a'; i <= 'z'; i++) { + URISave.set(i); + } + for (i = 'A'; i <= 'Z'; i++) { + URISave.set(i); + } + for (i = '0'; i <= '9'; i++) { + URISave.set(i); + } + URISave.set('-'); + URISave.set('_'); + URISave.set('.'); + URISave.set('!'); + URISave.set('~'); + URISave.set('*'); + URISave.set('\''); + URISave.set('('); + URISave.set(')'); + + URISaveEx = (BitSet) URISave.clone(); + URISaveEx.set('/'); + } + + /** + * Does a URL encoding of the string. The characters that + * don't need encoding are those defined 'unreserved' in section 2.3 of + * the 'URI generic syntax' RFC 2396. + * + * @param string the string to encode + * @return the escaped string + * @throws NullPointerException if string is null. + */ + public static String escape(String string) { + return escape(string, '%', false); + } + + /** + * Does a URL encoding of the path. The characters that + * don't need encoding are those defined 'unreserved' in section 2.3 of + * the 'URI generic syntax' RFC 2396. In contrast to the + * {@link #escape(String)} method, not the entire path string is escaped, + * but every individual part (i.e. the slashes are not escaped). + * + * @param path the path to encode + * @return the escaped path + * @throws NullPointerException if path is null. + */ + public static String escapePath(String path) { + return escape(path, '%', true); + } + + /** + * Does an URL encoding of the string using the + * escape character. The characters that don't need encoding + * are those defined 'unreserved' in section 2.3 of the 'URI generic syntax' + * RFC 2396, but without the escape character. If isPath is + * true, additionally the slash '/' is ignored, too. + * + * @param string the string to encode. + * @param escape the escape character. + * @param isPath if true, the string is treated as path + * @return the escaped string + * @throws NullPointerException if string is null. + */ + private static String escape(String string, char escape, boolean isPath) { + BitSet validChars = isPath ? URISaveEx : URISave; + byte[] bytes = string.getBytes(StandardCharsets.UTF_8); + StringBuffer out = new StringBuffer(bytes.length); + for (byte aByte : bytes) { + int c = aByte & 0xff; + if (validChars.get(c) && c != escape) { + out.append((char) c); + } else { + out.append(escape); + out.append(hexTable[(c >> 4) & 0x0f]); + out.append(hexTable[(c) & 0x0f]); + } + } + return out.toString(); + } + + /** + * Does a URL decoding of the string. Please note that in + * opposite to the {@link java.net.URLDecoder} it does not transform the + + * into spaces. + * + * @param string the string to decode + * @return the decoded string + * @throws NullPointerException if string is null. + * @throws ArrayIndexOutOfBoundsException if not enough character follow an + * escape character + * @throws IllegalArgumentException if the 2 characters following the escape + * character do not represent a hex-number. + */ + public static String unescape(String string) { + return unescape(string, '%'); + } + + /** + * Does a URL decoding of the string using the + * escape character. Please note that in opposite to the + * {@link java.net.URLDecoder} it does not transform the + into spaces. + * + * @param string the string to decode + * @param escape the escape character + * @return the decoded string + * @throws NullPointerException if string is null. + * @throws IllegalArgumentException if the 2 characters following the escape + * character do not represent a hex-number + * or if not enough characters follow an + * escape character + */ + private static String unescape(String string, char escape) { + byte[] utf8 = string.getBytes(StandardCharsets.UTF_8); + + // Check whether escape occurs at invalid position + if ((utf8.length >= 1 && utf8[utf8.length - 1] == escape) || + (utf8.length >= 2 && utf8[utf8.length - 2] == escape)) { + throw new IllegalArgumentException("Premature end of escape sequence at end of input"); + } + + ByteArrayOutputStream out = new ByteArrayOutputStream(utf8.length); + for (int k = 0; k < utf8.length; k++) { + byte b = utf8[k]; + if (b == escape) { + out.write((decodeDigit(utf8[++k]) << 4) + decodeDigit(utf8[++k])); + } + else { + out.write(b); + } + } + + return new String(out.toByteArray(), StandardCharsets.UTF_8); + } + + private static byte decodeDigit(byte b) { + if (b >= 0x30 && b <= 0x39) { + return (byte) (b - 0x30); + } + else if (b >= 0x41 && b <= 0x46) { + return (byte) (b - 0x37); + } + else if (b >= 0x61 && b <= 0x66) { + return (byte) (b - 0x57); + } + else { + throw new IllegalArgumentException("Escape sequence is not hexadecimal: " + (char)b); + } + } + + /** + * Private constructor: avoid instantiation. + */ + private EncodeUtil() { + } +} \ No newline at end of file Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/util/EncodeUtil.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-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/util/HttpDateFormat.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/util/HttpDateFormat.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/util/HttpDateFormat.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.webdav.util; + +import java.text.SimpleDateFormat; +import java.util.Locale; +import java.util.TimeZone; + +/** + * HttpDateFormat... + */ +public class HttpDateFormat extends SimpleDateFormat { + + private static final TimeZone GMT_TIMEZONE = TimeZone.getTimeZone("GMT"); + + /** + * Pattern for the modification date as defined by RFC 1123 + */ + public static final String MODIFICATION_DATE_PATTERN = "EEE, dd MMM yyyy HH:mm:ss z"; + + /** + * Simple date format pattern for the creation date ISO representation (partial). + */ + public static final String CREATION_DATE_PATTERN = "yyyy-MM-dd'T'HH:mm:ss'Z'"; + + public HttpDateFormat(String pattern) { + super(pattern, Locale.ENGLISH); + super.setTimeZone(GMT_TIMEZONE); + } + + /** + * Creates a new HttpDateFormat using the + * {@link #MODIFICATION_DATE_PATTERN modifcation date pattern}. + * + * @return a new HttpDateFormat. + */ + public static HttpDateFormat modificationDateFormat() { + return new HttpDateFormat(MODIFICATION_DATE_PATTERN); + } + + /** + * Creates a new HttpDateFormat using the + * {@link #CREATION_DATE_PATTERN creation date pattern}. + * + * @return a new HttpDateFormat. + */ + public static HttpDateFormat creationDateFormat() { + return new HttpDateFormat(CREATION_DATE_PATTERN); + } +} \ No newline at end of file Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/util/HttpDateFormat.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-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/util/HttpDateTimeFormatter.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/util/HttpDateTimeFormatter.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/util/HttpDateTimeFormatter.java (working copy) @@ -0,0 +1,152 @@ +/* + * 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.webdav.util; + +import java.time.Instant; +import java.time.LocalDate; +import java.time.ZoneOffset; +import java.time.ZonedDateTime; +import java.time.format.DateTimeFormatter; +import java.time.format.DateTimeFormatterBuilder; +import java.time.format.DateTimeParseException; +import java.time.temporal.ChronoField; +import java.util.Locale; + +/** + * Parsers and Serializers for HTTP dates (RFC 7231, Section 7.1.1.1), using + * {@link DateTimeFormatter} (from Java 8). + */ +public class HttpDateTimeFormatter { + + private static DateTimeFormatter IMFFIXDATE = DateTimeFormatter.ofPattern("EEE, dd MMM yyyy HH:mm:ss 'GMT'", Locale.ENGLISH) + .withZone(ZoneOffset.UTC); + + // see + // https://greenbytes.de/tech/webdav/rfc7231.html#rfc.section.7.1.1.1.p.6 + private static DateTimeFormatter RFC850DATE = new DateTimeFormatterBuilder().appendPattern("EEEE, dd-MMM-") + .appendValueReduced(ChronoField.YEAR_OF_ERA, 2, 2, LocalDate.now().minusYears(50)).appendPattern(" HH:mm:ss 'GMT'") + .toFormatter().withLocale(Locale.ENGLISH).withZone(ZoneOffset.UTC); + + private static DateTimeFormatter ASCTIMEDATE = new DateTimeFormatterBuilder().appendPattern("EEE MMM ").padNext(2, ' ') + .appendValue(ChronoField.DAY_OF_MONTH).appendPattern(" HH:mm:ss yyyy").toFormatter().withLocale(Locale.ENGLISH) + .withZone(ZoneOffset.UTC); + + /** + * Parse HTTP "IMF-fixdate" format (see RFC 7231, Section 7.1.1.1) + * + * @param fieldValue + * string value + * @return ms since epoch throws DateTimeParseException on invalid input + */ + public static long parseImfFixedDate(String fieldValue) { + ZonedDateTime d = ZonedDateTime.parse(fieldValue, IMFFIXDATE); + return d.toInstant().toEpochMilli(); + } + + /** + * Parse HTTP "rfc850-date" format (see RFC 7231, Section 7.1.1.1) + * + * @param fieldValue + * string value + * @return ms since epoch throws DateTimeParseException on invalid input + */ + public static long parseRfc850Date(String fieldValue) { + ZonedDateTime d = ZonedDateTime.parse(fieldValue, RFC850DATE); + return d.toInstant().toEpochMilli(); + } + + /** + * Parse HTTP "asctime-date" format (see RFC 7231, Section 7.1.1.1) + * + * @param fieldValue + * string value + * @return ms since epoch throws DateTimeParseException on invalid input + */ + public static long parseAscTimeDate(String fieldValue) { + ZonedDateTime d = ZonedDateTime.parse(fieldValue, ASCTIMEDATE); + return d.toInstant().toEpochMilli(); + } + + /** + * Parse HTTP format, trying the three allowable formats defined in RFC + * 7231, Section 7.1.1.1 + * + * @param fieldValue + * string value + * @return ms since epoch throws DateTimeParseException on invalid input + */ + public static long parse(String fieldValue) { + try { + return parseImfFixedDate(fieldValue); + } catch (DateTimeParseException ex) { + try { + return parseRfc850Date(fieldValue); + } catch (DateTimeParseException ex2) { + try { + return parseAscTimeDate(fieldValue); + } catch (DateTimeParseException ex3) { + // if we get here, throw original exception for IMFFIXDATE + throw ex; + } + } + } + } + + /** + * Format as HTTP default date (IMF-fixdate) (see RFC 7231, Section 7.1.1.1) + * + * @param millisSinceEpoch + * ms since epoch + * @return string representation + */ + public static String format(long millisSinceEpoch) { + return IMFFIXDATE.format(Instant.ofEpochMilli(millisSinceEpoch)); + } + + /** + * Format as HTTP "IMF-fixdate" (see RFC 7231, Section 7.1.1.1) + * + * @param millisSinceEpoch + * ms since epoch + * @return string representation + */ + public static String formatImfFixed(long millisSinceEpoch) { + return IMFFIXDATE.format(Instant.ofEpochMilli(millisSinceEpoch)); + } + + /** + * Format as HTTP "rfc850-date" (see RFC 7231, Section 7.1.1.1) + * + * @param millisSinceEpoch + * ms since epoch + * @return string representation + */ + public static String formatRfc850(long millisSinceEpoch) { + return RFC850DATE.format(Instant.ofEpochMilli(millisSinceEpoch)); + } + + /** + * Format as HTTP "asctime-date" (see RFC 7231, Section 7.1.1.1) + * + * @param millisSinceEpoch + * ms since epoch + * @return string representation + */ + public static String formatAscTime(long millisSinceEpoch) { + return ASCTIMEDATE.format(Instant.ofEpochMilli(millisSinceEpoch)); + } +} Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/util/HttpDateTimeFormatter.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/util/LinkHeaderFieldParser.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/util/LinkHeaderFieldParser.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/util/LinkHeaderFieldParser.java (working copy) @@ -0,0 +1,197 @@ +/* + * 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.webdav.util; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.Enumeration; +import java.util.HashMap; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.apache.http.NameValuePair; +import org.apache.http.message.BasicHeaderValueParser; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Simple parser for HTTP Link header fields, as defined in RFC 5988. + */ +public class LinkHeaderFieldParser { + + /** + * the default logger + */ + private static Logger log = LoggerFactory.getLogger(LinkHeaderFieldParser.class); + + private final List relations; + + public LinkHeaderFieldParser(List fieldValues) { + List tmp = new ArrayList(); + if (fieldValues != null) { + for (String value : fieldValues) { + addFields(tmp, value); + } + } + relations = Collections.unmodifiableList(tmp); + } + + public LinkHeaderFieldParser(Enumeration en) { + if (en != null && en.hasMoreElements()) { + List tmp = new ArrayList(); + + while (en.hasMoreElements()) { + addFields(tmp, en.nextElement().toString()); + } + relations = Collections.unmodifiableList(tmp); + } else { + // optimize case of no Link headers + relations = Collections.emptyList(); + } + } + + public String getFirstTargetForRelation(String relationType) { + + for (LinkRelation lr : relations) { + + String relationNames = lr.getParameters().get("rel"); + if (relationNames != null) { + + // split rel value on whitespace + for (String rn : relationNames.toLowerCase(Locale.ENGLISH) + .split("\\s")) { + if (relationType.equals(rn)) { + return lr.getTarget(); + } + } + } + } + + return null; + } + + // A single header field instance can contain multiple, comma-separated + // fields. + private void addFields(List l, String fieldValue) { + + boolean insideAngleBrackets = false; + boolean insideDoubleQuotes = false; + + for (int i = 0; i < fieldValue.length(); i++) { + + char c = fieldValue.charAt(i); + + if (insideAngleBrackets) { + insideAngleBrackets = c != '>'; + } else if (insideDoubleQuotes) { + insideDoubleQuotes = c != '"'; + if (c == '\\' && i < fieldValue.length() - 1) { + // skip over next character + c = fieldValue.charAt(++i); + } + } else { + insideAngleBrackets = c == '<'; + insideDoubleQuotes = c == '"'; + + if (c == ',') { + String v = fieldValue.substring(0, i); + if (v.length() > 0) { + try { + l.add(new LinkRelation(v)); + } catch (Exception ex) { + log.warn("parse error in Link Header field value", + ex); + } + } + addFields(l, fieldValue.substring(i + 1)); + return; + } + } + } + + if (fieldValue.length() > 0) { + try { + l.add(new LinkRelation(fieldValue)); + } catch (Exception ex) { + log.warn("parse error in Link Header field value", ex); + } + } + } + + private static class LinkRelation { + + private static Pattern P = Pattern.compile("\\s*<(.*)>\\s*(.*)"); + + private String target; + private Map parameters; + + /** + * Parses a single link relation, consisting of and optional + * parameters. + * + * @param field + * field value + * @throws Exception + */ + public LinkRelation(String field) throws Exception { + + // find the link target using a regexp + Matcher m = P.matcher(field); + if (!m.matches()) { + throw new Exception("illegal Link header field value:" + field); + } + + target = m.group(1); + + // pass the remainder to the generic parameter parser + NameValuePair[] params = BasicHeaderValueParser.parseParameters(m.group(2), null); + + if (params.length == 0) { + parameters = Collections.emptyMap(); + } else if (params.length == 1) { + NameValuePair nvp = params[0]; + parameters = Collections.singletonMap(nvp.getName() + .toLowerCase(Locale.ENGLISH), nvp.getValue()); + } else { + parameters = new HashMap(); + for (NameValuePair p : params) { + if (null != parameters.put( + p.getName().toLowerCase(Locale.ENGLISH), + p.getValue())) { + throw new Exception("duplicate parameter + " + + p.getName() + " field ignored"); + } + } + } + } + + public String getTarget() { + return target; + } + + public Map getParameters() { + return parameters; + } + + public String toString() { + return target + " " + parameters; + } + } +} Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/util/LinkHeaderFieldParser.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/util/package-info.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/util/package-info.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/util/package-info.java (working copy) @@ -0,0 +1,18 @@ +/* + * 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. + */ +@org.osgi.annotation.versioning.Version("1.1.0") +package org.apache.jackrabbit.webdav.util; Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/util/package-info.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/ActivityResource.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/ActivityResource.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/ActivityResource.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.webdav.version; + +import org.apache.jackrabbit.webdav.property.DavPropertyName; + +/** + * An activity is a resource that selects a set of versions that are on a single + * "line of descent", where a line of descent is a sequence of versions connected + * by successor relationships. If an activity selects versions from multiple + * version histories, the versions selected in each version history must be on a + * single line of descent. + *

+ * RFC 3253 defines the following required live properties for an Activity + * resource. + *

    + *
  • {@link #ACTIVITY_VERSION_SET DAV:activity-version-set}
  • + *
  • {@link #ACTIVITY_CHECKOUT_SET DAV:activity-checkout-set}
  • + *
  • {@link #SUBACTIVITY_SET DAV:subactivity-set}
  • + *
  • {@link #CURRENT_WORKSPACE_SET DAV:current-workspace-set}
  • + *
  • all DeltaV-compliant resource properties}.
  • + *
  • Note, that the {@link org.apache.jackrabbit.webdav.DavConstants#PROPERTY_RESOURCETYPE DAV:resourcetype} + * property returned by an Activity resource must be + * {@link org.apache.jackrabbit.webdav.property.ResourceType#ACTIVITY DAV:activity}
  • + *
+ *

+ * The Activity resource must support all methods defined for a + * {@link DeltaVResource DeltaV-compliant resource}. Since no additional methods + * are required for an activity this interface mainly acts as marker. + *

+ * Please refer to RFC 3253 + * Section 13 for a complete description of this resource type. + */ +public interface ActivityResource extends DeltaVResource { + + /** + * The computed DAV:activity-version-set property identifies each version + * whose DAV:activity-set property identifies this activity. Multiple + * versions of a single version history can be selected by an activity's + * DAV:activity-version-set property, but all DAV:activity-version-set + * versions from a given version history must be on a single line of descent + * from the root version of that version history. + *

+ * Note that the DAV:activity-version-set represents a + * {@link org.apache.jackrabbit.webdav.property.HrefProperty HrefProperty} + */ + public static final DavPropertyName ACTIVITY_VERSION_SET = DavPropertyName.create("activity-version-set", DeltaVConstants.NAMESPACE); + + /** + * The computed DAV:activity-checkout-set property identifies each + * checked-out resource whose DAV:activity-set identifies this activity. + *

+ * Note that the DAV:activity-checkout-set represents a + * {@link org.apache.jackrabbit.webdav.property.HrefProperty HrefProperty} + */ + public static final DavPropertyName ACTIVITY_CHECKOUT_SET = DavPropertyName.create("activity-checkout-set", DeltaVConstants.NAMESPACE); + + /** + * The DAV:subactivity-set property identifies each activity that forms a + * part of the logical change being captured by this activity. An activity + * behaves as if its DAV:activity-version-set is extended by the + * DAV:activity-version-set of each activity identified in the + * DAV:subactivity-set. In particular, the versions in this extended set + * MUST be on a single line of descent, and when an activity selects a version + * for merging, the latest version in this extended set is the one that will + * be merged. + *

+ * A server MAY reject attempts to modify the DAV:subactivity-set of an activity. + * + * Note that the DAV:subactivity-set represents a + * {@link org.apache.jackrabbit.webdav.property.HrefProperty HrefProperty} + */ + public static final DavPropertyName SUBACTIVITY_SET = DavPropertyName.create("subactivity-set", DeltaVConstants.NAMESPACE); + + /** + * The computed DAV:current-workspace-set property identifies identifies + * each workspace whose DAV:current-activity-set identifies this activity. + *

+ * Note that the DAV:current-workspace-set represents a + * {@link org.apache.jackrabbit.webdav.property.HrefProperty HrefProperty} + */ + public static final DavPropertyName CURRENT_WORKSPACE_SET = DavPropertyName.create("current-workspace-set", DeltaVConstants.NAMESPACE); + +} \ No newline at end of file Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/ActivityResource.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-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/BaselineResource.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/BaselineResource.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/BaselineResource.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.webdav.version; + +import org.apache.jackrabbit.webdav.property.DavPropertyName; +import org.apache.jackrabbit.webdav.DavResource; +import org.apache.jackrabbit.webdav.DavException; + +/** + * BaselineResource represents the 'version' of a configuration + * which is represented by a 'version-controlled-configuration' (VCC) resource. + * Such as new versions are created by CHECKIN of a version-controlled + * resource, a new baseline is created, whenever the VCC resource, that + * represents a set of resources rather than a single resource, is checked-in. + *

+ * Since the baseline behaves like a VersionResource and only is + * defined to provide additional protected properties, this interface only adds + * a convenience method that allows to retrieve the baseline collection. + *

+ * Supported live properties: + *

+ * DAV:baseline-collection
+ * DAV:subbaseline-set
+ * all version properties.
+ * 
+ * + * Supported methods: + *
+ * all version methods.
+ * 
+ */ +public interface BaselineResource extends VersionResource { + + /** + * The protected DAV:baseline-collection property identifies a distinct + * collection that lists as members all version-controlled resources of + * the configuration this baseline belongs to (the baseline being one + * version of the corresponding vc-configuration-resource). In other words: + * each member in the list must correspond to a member of the baseline-controlled + * collection at the time this baseline (version) was created. + *

+ * + * Note that the DAV:baseline-collection represents a + * {@link org.apache.jackrabbit.webdav.property.HrefProperty HrefProperty} + */ + public static final DavPropertyName BASELINE_COLLECTION = DavPropertyName.create("baseline-collection", DeltaVConstants.NAMESPACE); + + /** + * The protected DAV:subbaseline-set property identifies a set of baseline + * resources. Note however, that the subbaselines of this resource are + * not only formed from the baseline resources listed in this property + * but also includes all subbaseline resources of the latter. + * + * Note that the DAV:subbaseline-set represents a + * {@link org.apache.jackrabbit.webdav.property.HrefProperty HrefProperty} + */ + public static final DavPropertyName SUBBASELINE_SET = DavPropertyName.create("subbaseline-set", DeltaVConstants.NAMESPACE); + + /** + * Return the resource that represents the baseline-collection of this + * baseline, which is identified the href present in the {@link #BASELINE_COLLECTION} + * property. + * + * @return baseline collection + */ + public DavResource getBaselineCollection() throws DavException; +} \ No newline at end of file Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/BaselineResource.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-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/DeltaVConstants.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/DeltaVConstants.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/DeltaVConstants.java (working copy) @@ -0,0 +1,374 @@ +/* + * 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.webdav.version; + +import org.apache.jackrabbit.webdav.DavConstants; +import org.apache.jackrabbit.webdav.property.DavPropertyName; +import org.apache.jackrabbit.webdav.xml.Namespace; + +/** + * DeltaVConstants defines the following headers and properties + * required for any resource that is compliant to + * RFC 3253:

+ * + * Headers: + *

+ * Label
+ * 
+ * + * Properties: + *
+ * DAV:comment
+ * DAV:creator-displayname
+ * DAV:supported-method-set
+ * DAV:supported-live-property-set
+ * DAV:supported-report-set
+ * 
+ * + * Some additional resource properties are defined by the various advanced + * version features: + *
+ * DAV:workspace (workspace feature)
+ * DAV:version-controlled-configuration (baseline)
+ * 
+ */ +public interface DeltaVConstants { + + /** + * The DAV: namespace. + */ + public static final Namespace NAMESPACE = DavConstants.NAMESPACE; + + //---< Headers >------------------------------------------------------------ + /** + * For certain METHODS, if the request-URL identifies a version-controlled + * resource, a label can be specified in a LabelInfo request header to cause the + * method to be applied to the version selected by that label.
+ * LabelInfo header MUST have no effect on a request whose request-URL does not + * identify a version-controlled resource. In particular, it MUST have no + * effect on a request whose request-URL identifies a version or a version + * history. + */ + public static final String HEADER_LABEL = "Label"; + + /** + * Location header as defined by + * RFC 2616. In the versioning + * context it is used to indicate the location of the new version created by a + * successful checkin in the response.

+ * From RFC 2616:
+ * The Location response-header field is used to redirect the recipient to a + * location other than the Request-URI for completion of the request or + * identification of a new resource.
+ * For 201 (Created) responses, the Location is that of the new resource + * which was created by the request. + */ + public static final String HEADER_LOCATION = "Location"; + + //---< Property Names >----------------------------------------------------- + /** + * The "DAV:comment" property is used to track a brief comment about a resource that is + * suitable for presentation to a user. The DAV:comment of a version can be + * used to indicate why that version was created. + */ + public static final DavPropertyName COMMENT = DavPropertyName.create("comment", NAMESPACE); + + /** + * The "DAV:creator-displayname" property contains a description of the creator of + * the resource that is suitable for presentation to a user. The + * DAV:creator-displayname of a version can be used to indicate who created + * that version. + */ + public static final DavPropertyName CREATOR_DISPLAYNAME = DavPropertyName.create("creator-displayname", NAMESPACE); + + /** + * Required protected live property for any resources being compliant with + * RFC 3253. Clients should classify a resource by examine the values of the + * DAV:supported-method-set and DAV:supported-live-property-set + * properties of that resource.
+ * Property structure: + *
+     * <!ELEMENT supported-method-set (supported-method*)>
+     * <!ELEMENT supported-method ANY>
+     * <!ATTLIST supported-method name NMTOKEN #REQUIRED>
+     * name value: a method name
+     * 
+ * + * @see #SUPPORTED_LIVE_PROPERTY_SET + */ + public static final DavPropertyName SUPPORTED_METHOD_SET = DavPropertyName.create("supported-method-set", NAMESPACE); + + /** + * Required protected live property for any resources being compliant with + * RFC 3253. Clients should classify a resource by examine the values of the + * DAV:supported-method-set and DAV:supported-live-property-set + * properties of that resource.
+ * Property structure: + *
+     * <!ELEMENT supported-live-property-set (supported-live-property*)>
+     * <!ELEMENT supported-live-property name>
+     * <!ELEMENT prop ANY>
+     * ANY value: a property element type
+     * 
+ * + * @see #SUPPORTED_METHOD_SET + */ + public static final DavPropertyName SUPPORTED_LIVE_PROPERTY_SET = DavPropertyName.create("supported-live-property-set", NAMESPACE); + + /** + * Protected "supported-report-set" property identifies the reports that are + * supported by the resource. + * + * @see #SUPPORTED_REPORT_SET + */ + public static final DavPropertyName SUPPORTED_REPORT_SET = DavPropertyName.create("supported-report-set", NAMESPACE); + + /** + * Protected "workspace" property indicating the workspace of a resource. + * This property is required for all resources if (but only if) the workspace + * feature is supported. + *

+ * Note that the DAV:activity-version-set represents a + * {@link org.apache.jackrabbit.webdav.property.HrefProperty HrefProperty}. + * It is defined to have the following format: + *

+     * <!ELEMENT workspace (href)>
+     * 
+ * + * @see WorkspaceResource + */ + public static final DavPropertyName WORKSPACE = DavPropertyName.create("workspace", NAMESPACE); + + /** + * The Baseline feature introduces the computed DAV:version-controlled-configuration + * property for all resources that are member of a version-controlled + * configuration. This may be the case if the resource is a collection under + * baseline control or is a member of a collection under baseline control. + *

+ * Note that the DAV:activity-version-set represents a + * {@link org.apache.jackrabbit.webdav.property.HrefProperty HrefProperty}. + * It is defined to have the following format: + *

+     * <!ELEMENT version-controlled-configuration (href)>
+     * 
+ */ + public static final DavPropertyName VERSION_CONTROLLED_CONFIGURATION = DavPropertyName.create("version-controlled-configuration", NAMESPACE); + + + //---< XML Element, Attribute Names >--------------------------------------- + /** + * Xml elements + */ + public static final String XML_ACTIVITY = "activity"; + public static final String XML_BASELINE = "baseline"; + + public static final String XML_SUPPORTED_METHOD = "supported-method"; + public static final String XML_VERSION_HISTORY = "version-history"; + public static final String XML_VERSION = "version"; + public static final String XML_WORKSPACE = "workspace"; + + // options + /** + * If the OPTIONS request contains a body, i must start with an DAV:options + * element. + * + * @see OptionsInfo + * @see #XML_VH_COLLECTION_SET + * @see #XML_WSP_COLLECTION_SET + * @see #XML_ACTIVITY_COLLECTION_SET + */ + public static final String XML_OPTIONS = "options"; + + /** + * If an XML response body for a successful request is included, it must be + * a DAV:options-response XML element. + * + * @see OptionsResponse + */ + public static final String XML_OPTIONS_RESPONSE = "options-response"; + + /** + * A DAV:version-history-collection-set element may be included in the OPTIONS + * request body to identify collections that may contain version history + * resources.
+ * The response body for a successful request must in consequence contain a + * DAV:version-history-collection-set element identifying collections that + * may contain version histories. An identified collection may be the root + * collection of a tree of collections, all of which may contain version + * histories. + * + *
+     * <!ELEMENT version-history-collection-set (href*)>
+     * 
+ */ + public static final String XML_VH_COLLECTION_SET = "version-history-collection-set"; + + /** + * A DAV:workspace-collection-set element may be included in the OPTIONS request + * body to identify collections that may contain workspace resources.
+ * The response body for a successful request must contain a + * DAV:workspace-collection-set element identifying collections that may + * contain workspaces. An identified collection may be the root collection + * of a tree of collections, all of which may contain workspaces. + * + *
+     * <!ELEMENT workspace-collection-set (href*)>
+     * 
+ */ + public static final String XML_WSP_COLLECTION_SET = "workspace-collection-set"; + + /** + * A DAV:workspace-collection-set element may be included in the OPTIONS request + * body to identify collections that may contain activity resources.
+ * The response body for a successful request must contain a + * DAV:workspace-collection-set element identifying collections that may + * contain activity resources. An identified collection may be the root collection + * of a tree of collections, all of which may contain activity resources. + * + *
+     * <!ELEMENT activity-collection-set (href*)>
+     * 
+ */ + public static final String XML_ACTIVITY_COLLECTION_SET = "activity-collection-set"; + + /** + * Name of Xml element contained in the {@link #SUPPORTED_REPORT_SET} property. + * + * @see #SUPPORTED_REPORT_SET + * @see org.apache.jackrabbit.webdav.version.report.SupportedReportSetProperty + */ + public static final String XML_SUPPORTED_REPORT = "supported-report"; + + /** + * Name of Xml child elements of {@link #XML_SUPPORTED_REPORT}. + * + * @see org.apache.jackrabbit.webdav.version.report.SupportedReportSetProperty + */ + public static final String XML_REPORT = "report"; + + /** + * Top element for the 'DAV:version-tree' report + */ + public static final String XML_VERSION_TREE = "version-tree"; + + /** + * Top element for the 'DAV:expand-property' report + */ + public static final String XML_EXPAND_PROPERTY = "expand-property"; + + /** + * 'DAV:property' element to be used inside the 'DAV:expand-property' element. + * + * @see #XML_EXPAND_PROPERTY + */ + public static final String XML_PROPERTY = "property"; + + /** + * 'DAV:name' attribute for the property element + * + * @see #XML_PROPERTY + */ + public static final String ATTR_NAME = "name"; + + /** + * 'DAV:namespace' attribute for the property element + * + * @see #XML_PROPERTY + */ + public static final String ATTR_NAMESPACE = "namespace"; + + /** + * Top element for the 'DAV:locate-by-history' report + */ + public static final String XML_LOCATE_BY_HISTORY = "locate-by-history"; + + /** + * 'DAV:version-history-set' to be used inside the 'DAV:locate-by-history' + * element + * + * @see #XML_LOCATE_BY_HISTORY + */ + public static final String XML_VERSION_HISTORY_SET = "version-history-set"; + + + /** + * Xml element representing the mandatory root element of a LABEL request + * body. + * + * @see #XML_LABEL_NAME + * @see #XML_LABEL_ADD + * @see #XML_LABEL_REMOVE + * @see #XML_LABEL_SET + * @see LabelInfo + */ + public static final String XML_LABEL = "label"; + public static final String XML_LABEL_NAME = "label-name"; + public static final String XML_LABEL_ADD = "add"; + public static final String XML_LABEL_REMOVE = "remove"; + public static final String XML_LABEL_SET = "set"; + + /** + * Xml element defining the top element in the UPDATE request body. RFC 3253 + * defines the following structure for the 'update' element. + *
+     * <!ELEMENT update ANY>
+     * ANY value: A sequence of elements with at most one DAV:version element
+     * and at most one DAV:prop element.
+     * <!ELEMENT version (href)>
+     * prop: see RFC 2518, Section 12.11
+     * 
+ */ + public static final String XML_UPDATE = "update"; + + // auto-version + /** + * Value for the DAV:auto-version property indicating that any modification + * (such as PUT/PROPPATCH) applied to a checked-in version-controlled + * resource will automatically be preceded by a checkout and followed by a + * checkin operation.
+ * See also RFC 3253 DAV:auto-version + */ + public static final String XML_CHECKOUT_CHECKIN = "checkout-checkin"; + /** + * Value for the DAV:auto-version property indicating that any modification + * (such as PUT/PROPPATCH) applied to a checked-in version-controlled + * resource will automatically be preceded by a checkout operation. + * If the resource is not write-locked, the request is automatically + * followed by a checkin operation.
+ * See also RFC 3253 DAV:auto-version + */ + public static final String XML_CHECKOUT_UNLOCK_CHECKIN = "checkout-unlocked-checkin"; + /** + * Value for the DAV:auto-version property indicating that any modification + * (such as PUT/PROPPATCH) applied to a checked-in version-controlled + * resource will automatically be preceded by a checkout operation.
+ * See also RFC 3253 DAV:auto-version + */ + public static final String XML_CHECKOUT = "checkout"; + /** + * Value for the DAV:auto-version property indicating that any modification + * (such as PUT/PROPPATCH) applied to a write-locked checked-in version-controlled + * resource will automatically be preceded by a checkout operation.
+ * See also RFC 3253 DAV:auto-version + */ + public static final String XML_LOCKED_CHECKIN = "locked-checkout"; + + // merge + public static final String XML_MERGE = "merge"; + public static final String XML_N0_AUTO_MERGE = "no-auto-merge"; + public static final String XML_N0_CHECKOUT = "no-checkout"; +} \ No newline at end of file Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/DeltaVConstants.java ___________________________________________________________________ Added: svn Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/DeltaVResource.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/DeltaVResource.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/DeltaVResource.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.webdav.version; + +import org.apache.jackrabbit.webdav.DavException; +import org.apache.jackrabbit.webdav.DavResource; +import org.apache.jackrabbit.webdav.property.DavPropertyName; +import org.apache.jackrabbit.webdav.version.report.Report; +import org.apache.jackrabbit.webdav.version.report.ReportInfo; + +/** + * The DeltaVResource encapsulates the functionality common to all + * DeltaV compliant resources. + *

+ * RFC 3253 defines the following required properties: + *

    + *
  • {@link DeltaVConstants#COMMENT DAV:comment}
  • + *
  • {@link DeltaVConstants#CREATOR_DISPLAYNAME DAV:creator-displayname}
  • + *
  • {@link DeltaVConstants#SUPPORTED_METHOD_SET DAV:supported-method-set}
  • + *
  • {@link DeltaVConstants#SUPPORTED_LIVE_PROPERTY_SET DAV:supported-live-property-set}
  • + *
  • {@link DeltaVConstants#SUPPORTED_REPORT_SET DAV:supported-report-set}
  • + *
  • all properties defined in WebDAV [RFC2518].
  • + *
+ *

+ * In addition a DeltaV compliant resource must support the following METHODS: + *

    + *
  • REPORT
  • + *
  • all METHODS defined in WebDAV [RFC2518]
  • + *
  • all METHODS defined in HTTP/1.1 [RFC2616].
  • + *
+ * + * @see DavResource + */ +public interface DeltaVResource extends DavResource { + + /** + * The generic deltaV compliant resource defines one additional method REPORT. + * + * @see org.apache.jackrabbit.webdav.DavResource#METHODS + */ + public String METHODS = "REPORT"; + + /** + * If the server support the Workspace featured defined by RFC 3253 certain + * DeltaVResources may also support the MKWORKSPACE method. + * + * @see #addWorkspace(DavResource) + */ + public String METHODS_INCL_MKWORKSPACE = "REPORT, MKWORKSPACE"; + + /** + * Retrieves the information requested in the OPTIONS request body and + * returns the corresponding values. + * + * @param optionsInfo + * @return object to be included to the OPTIONS response body or null + * if the specified optionsInfo was null or empty. + */ + public OptionsResponse getOptionResponse(OptionsInfo optionsInfo); + + /** + * Runs the report specified by the given ReportInfo. + * + * @param reportInfo + * @return the requested report. + * @throws DavException in case an error occurred or if the specified ReportInfo + * is either not valid or cannot be run by the given resource. + */ + public Report getReport(ReportInfo reportInfo) throws DavException; + + /** + * Add a new member to this resource, that represents a workspace.
+ * Please note that no resource must exist at the location of the new workspace. + * + * @param workspace resource representing the new workspace to be created as + * member of this resource. + * @throws DavException if creating the new workspace fails. + */ + // TODO: MKWORKSPACE may include an xml request body... + public void addWorkspace(DavResource workspace) throws DavException; + + /** + * Returns an array of DavResource objects that are referenced + * by the {@link org.apache.jackrabbit.webdav.property.HrefProperty} with + * the specified {@link DavPropertyName name}. + * + * @param hrefPropertyName + * @return An array of DavResources + * @throws DavException if the given hrefPropertyName does point to an + * unknown property or does not represent the name of a + * {@link org.apache.jackrabbit.webdav.property.HrefProperty href property}. + * Finally the exception may be caused if the property contains the href + * of a non-existing resource, which cannot be resolved. + * @see org.apache.jackrabbit.webdav.property.HrefProperty + */ + public DavResource[] getReferenceResources(DavPropertyName hrefPropertyName) throws DavException; +} \ No newline at end of file Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/DeltaVResource.java ___________________________________________________________________ Added: svn Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/DeltaVServletRequest.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/DeltaVServletRequest.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/DeltaVServletRequest.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.webdav.version; + +import org.apache.jackrabbit.webdav.DavException; +import org.apache.jackrabbit.webdav.DavServletRequest; +import org.apache.jackrabbit.webdav.version.report.ReportInfo; + +/** + * DeltaVServletRequest provides extension useful for functionality + * related to RFC 3253. + */ +public interface DeltaVServletRequest extends DavServletRequest { + + /** + * Returns the Label header or null + * + * @return label header or null + * @see DeltaVConstants#HEADER_LABEL + */ + public String getLabel(); + + /** + * Return the request body as LabelInfo object or null + * if parsing the request body or the creation of the label info failed. + * + * @return LabelInfo object or null + * @throws DavException in case of an invalid request body + */ + public LabelInfo getLabelInfo() throws DavException; + + /** + * Return the request body as MergeInfo object or null + * if the creation failed due to invalid format. + * + * @return MergeInfo object or null + * @throws DavException in case of an invalid request body + */ + public MergeInfo getMergeInfo() throws DavException; + + /** + * Parses the UPDATE request body a build the corresponding UpdateInfo + * object. If the request body is missing or does not of the required format + * null is returned. + * + * @return the parsed update request body or null + * @throws DavException in case of an invalid request body + */ + public UpdateInfo getUpdateInfo() throws DavException; + + /** + * Returns the request body and the Depth header as ReportInfo + * object. The default depth, if no {@link org.apache.jackrabbit.webdav.DavConstants#HEADER_DEPTH + * Depth header}, is {@link org.apache.jackrabbit.webdav.DavConstants#DEPTH_0}. + * If the request body could not be parsed into an {@link org.w3c.dom.Element} + * null is returned. + * + * @return ReportInfo or null + * @throws DavException in case of an invalid request body + */ + public ReportInfo getReportInfo() throws DavException; + + /** + * Returns the {@link OptionsInfo} present with the request or null. + * + * @return {@link OptionsInfo} or null + * @throws DavException in case of an invalid request body + */ + public OptionsInfo getOptionsInfo() throws DavException; +} \ No newline at end of file Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/DeltaVServletRequest.java ___________________________________________________________________ Added: svn Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/LabelInfo.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/LabelInfo.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/LabelInfo.java (working copy) @@ -0,0 +1,188 @@ +/* + * 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.webdav.version; + +import org.apache.jackrabbit.webdav.DavConstants; +import org.apache.jackrabbit.webdav.DavException; +import org.apache.jackrabbit.webdav.DavServletResponse; +import org.apache.jackrabbit.webdav.xml.DomUtil; +import org.apache.jackrabbit.webdav.xml.XmlSerializable; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +/** + * LabelInfo encapsulates the request body of a LABEL request + * used to add, set or remove a label from the requested version resource or + * from that version specified with the Label header in case the requested resource + * is a version-controlled resource.

+ * The request body (thus the 'labelElement' passed to the constructor must be + * a DAV:label element: + *
+ * <!ELEMENT label ANY>
+ * ANY value: A sequence of elements with at most one DAV:add,
+ * DAV:set, or DAV:remove element.
+ * <!ELEMENT add (label-name)>
+ * <!ELEMENT set (label-name)>
+ * <!ELEMENT remove (label-name)>
+ * <!ELEMENT label-name (#PCDATA)>
+ * PCDATA value: string
+ * 
+ * Please note, that the given implementation only recognizes the predefined elements 'add', + * 'set' and 'remove'. + */ +public class LabelInfo implements DeltaVConstants, XmlSerializable { + + private static Logger log = LoggerFactory.getLogger(LabelInfo.class); + + public static final int TYPE_SET = 0; + public static final int TYPE_REMOVE = 1; + public static final int TYPE_ADD = 2; + + public static String[] typeNames = new String[] { XML_LABEL_SET , XML_LABEL_REMOVE, XML_LABEL_ADD}; + + private final int depth; + private final int type; + private final String labelName; + + public LabelInfo(String labelName, String type) { + if (labelName == null) { + throw new IllegalArgumentException("Label name must not be null."); + } + boolean validType = false; + int i = 0; + while (i < typeNames.length) { + if (typeNames[i].equals(type)) { + validType = true; + break; + } + i++; + } + if (!validType) { + throw new IllegalArgumentException("Invalid type: " + type); + } + this.type = i; + this.labelName = labelName; + this.depth = DavConstants.DEPTH_0; + } + + public LabelInfo(String labelName, int type) { + this(labelName, type, DavConstants.DEPTH_0); + } + + public LabelInfo(String labelName, int type, int depth) { + if (labelName == null) { + throw new IllegalArgumentException("Label name must not be null."); + } + if (type < TYPE_SET || type > TYPE_ADD) { + throw new IllegalArgumentException("Invalid type: " + type); + } + this.labelName = labelName; + this.type = type; + this.depth = depth; + } + + /** + * Create a new LabelInfo from the given element and depth + * integer. If the specified Xml element does have a {@link DeltaVConstants#XML_LABEL} + * root element or no label name is specified with the action to perform + * the creation will fail. + * + * @param labelElement + * @param depth + * @throws DavException if the specified element does not + * start with a {@link DeltaVConstants#XML_LABEL} element or if the DAV:label + * element contains illegal instructions e.g. contains multiple DAV:add, DAV:set + * or DAV:remove elements. + */ + public LabelInfo(Element labelElement, int depth) throws DavException { + if (!DomUtil.matches(labelElement, DeltaVConstants.XML_LABEL, DeltaVConstants.NAMESPACE)) { + log.warn("DAV:label element expected"); + throw new DavException(DavServletResponse.SC_BAD_REQUEST); + } + + String label = null; + int type = -1; + for (int i = 0; i < typeNames.length && type == -1; i++) { + if (DomUtil.hasChildElement(labelElement, typeNames[i], NAMESPACE)) { + type = i; + Element el = DomUtil.getChildElement(labelElement, typeNames[i], NAMESPACE); + label = DomUtil.getChildText(el, XML_LABEL_NAME, NAMESPACE); + } + } + if (label == null) { + log.warn("DAV:label element must contain at least one set, add or remove element defining a label-name."); + throw new DavException(DavServletResponse.SC_BAD_REQUEST); + } + this.labelName = label; + this.type = type; + this.depth = depth; + } + + /** + * Create a new LabelInfo from the given element. As depth + * the default value 0 is assumed. + * + * @param labelElement + * @throws DavException + * @see #LabelInfo(org.w3c.dom.Element, int) + */ + public LabelInfo(Element labelElement) throws DavException { + this(labelElement, 0); + } + + /** + * Return the text present inside the 'DAV:label-name' element or null + * + * @return 'label-name' or null + */ + public String getLabelName() { + return labelName; + } + + /** + * Return the type of the LABEL request. This might either be {@link #TYPE_SET}, + * {@link #TYPE_ADD} or {@link #TYPE_REMOVE}. + * + * @return type + */ + public int getType() { + return type; + } + + /** + * Return the depth + * + * @return depth + */ + public int getDepth() { + return depth; + } + + /** + * @see org.apache.jackrabbit.webdav.xml.XmlSerializable#toXml(Document) + * @param document + */ + public Element toXml(Document document) { + Element label = DomUtil.createElement(document, XML_LABEL, NAMESPACE); + Element typeElem = DomUtil.addChildElement(label, typeNames[type], NAMESPACE); + DomUtil.addChildElement(typeElem, XML_LABEL_NAME, NAMESPACE, labelName); + return label; + } + +} \ No newline at end of file Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/LabelInfo.java ___________________________________________________________________ Added: svn Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/LabelSetProperty.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/LabelSetProperty.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/LabelSetProperty.java (working copy) @@ -0,0 +1,63 @@ +/* + * 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.webdav.version; + +import org.apache.jackrabbit.webdav.property.AbstractDavProperty; +import org.apache.jackrabbit.webdav.xml.DomUtil; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +/** + * LabelSetProperty... + */ +public class LabelSetProperty extends AbstractDavProperty { + + private static Logger log = LoggerFactory.getLogger(LabelSetProperty.class); + + private final String[] value; + + /** + * Create a new LabelSetProperty. + * + * @param labels + */ + public LabelSetProperty(String[] labels) { + super(VersionResource.LABEL_NAME_SET, true); + this.value = labels; + } + + + public String[] getValue() { + return value; + } + + /** + * @see org.apache.jackrabbit.webdav.xml.XmlSerializable#toXml(Document) + * @param document + */ + @Override + public Element toXml(Document document) { + Element elem = getName().toXml(document); + for (String str : value) { + DomUtil.addChildElement(elem, DeltaVConstants.XML_LABEL_NAME, DeltaVConstants.NAMESPACE, str); + } + return elem; + } + +} Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/LabelSetProperty.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-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/MergeInfo.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/MergeInfo.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/MergeInfo.java (working copy) @@ -0,0 +1,182 @@ +/* + * 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.webdav.version; + +import org.apache.jackrabbit.webdav.DavConstants; +import org.apache.jackrabbit.webdav.DavException; +import org.apache.jackrabbit.webdav.DavServletResponse; +import org.apache.jackrabbit.webdav.property.DavPropertyNameSet; +import org.apache.jackrabbit.webdav.xml.DomUtil; +import org.apache.jackrabbit.webdav.xml.ElementIterator; +import org.apache.jackrabbit.webdav.xml.XmlSerializable; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +import java.util.ArrayList; +import java.util.List; + +/** + * MergeInfo encapsulates the information present in the DAV:merge + * element, that forms the mandatory request body of a MERGE request.
+ * The DAV:merge element is specified to have the following form. + *
+ * <!ELEMENT merge ANY>
+ * ANY value: A sequence of elements with one DAV:source element, at most one
+ * DAV:no-auto-merge element, at most one DAV:no-checkout element, at most one
+ * DAV:prop element, and any legal set of elements that can occur in a DAV:checkout
+ * element.
+ * <!ELEMENT source (href+)>
+ * <!ELEMENT no-auto-merge EMPTY>
+ * <!ELEMENT no-checkout EMPTY>
+ * prop: see RFC 2518, Section 12.11
+ * 
+ */ +public class MergeInfo implements DeltaVConstants, XmlSerializable { + + private static Logger log = LoggerFactory.getLogger(MergeInfo.class); + + private final Element mergeElement; + private final DavPropertyNameSet propertyNameSet; + + /** + * Create a new MergeInfo + * + * @param mergeElement + * @throws DavException if the mergeElement is null + * or not a DAV:merge element. + */ + public MergeInfo(Element mergeElement) throws DavException { + if (!DomUtil.matches(mergeElement, XML_MERGE, NAMESPACE)) { + log.warn("'DAV:merge' element expected"); + throw new DavException(DavServletResponse.SC_BAD_REQUEST); + } + + // if property name set if present + Element propElem = DomUtil.getChildElement(mergeElement, DavConstants.XML_PROP, DavConstants.NAMESPACE); + if (propElem != null) { + propertyNameSet = new DavPropertyNameSet(propElem); + mergeElement.removeChild(propElem); + } else { + propertyNameSet = new DavPropertyNameSet(); + } + this.mergeElement = mergeElement; + } + + /** + * Returns the URL specified with the DAV:source element or null + * if no such child element is present in the DAV:merge element. + * + * @return href present in the DAV:source child element or null. + */ + public String[] getSourceHrefs() { + List sourceHrefs = new ArrayList(); + Element srcElem = DomUtil.getChildElement(mergeElement, DavConstants.XML_SOURCE, DavConstants.NAMESPACE); + if (srcElem != null) { + ElementIterator it = DomUtil.getChildren(srcElem, DavConstants.XML_HREF, DavConstants.NAMESPACE); + while (it.hasNext()) { + String href = DomUtil.getTextTrim(it.nextElement()); + if (href != null) { + sourceHrefs.add(href); + } + } + } + return sourceHrefs.toArray(new String[sourceHrefs.size()]); + } + + /** + * Returns true if the DAV:merge element contains a DAV:no-auto-merge child element. + * + * @return true if the DAV:merge element contains a DAV:no-auto-merge child. + */ + public boolean isNoAutoMerge() { + return DomUtil.hasChildElement(mergeElement, XML_N0_AUTO_MERGE, NAMESPACE); + } + + /** + * Returns true if the DAV:merge element contains a DAV:no-checkout child element. + * + * @return true if the DAV:merge element contains a DAV:no-checkout child + */ + public boolean isNoCheckout() { + return DomUtil.hasChildElement(mergeElement, XML_N0_CHECKOUT, NAMESPACE); + } + + /** + * Returns a {@link DavPropertyNameSet}. If the DAV:merge element contains + * a DAV:prop child element the properties specified therein are included + * in the set. Otherwise an empty set is returned.
+ * + * WARNING: modifying the DavPropertyNameSet returned by this method does + * not modify this UpdateInfo. + * + * @return set listing the properties specified in the DAV:prop element indicating + * those properties that must be reported in the response body. + */ + public DavPropertyNameSet getPropertyNameSet() { + return propertyNameSet; + } + + /** + * Returns the DAV:merge element used to create this MergeInfo + * object. + * + * @return DAV:merge element + */ + public Element getMergeElement() { + return mergeElement; + } + + /** + * @see org.apache.jackrabbit.webdav.xml.XmlSerializable#toXml(Document) + * @param document + */ + public Element toXml(Document document) { + Element elem = (Element)document.importNode(mergeElement, true); + if (!propertyNameSet.isEmpty()) { + elem.appendChild(propertyNameSet.toXml(document)); + } + return elem; + } + + + /** + * Factory method to create a minimal DAV:merge element to create a new + * MergeInfo object. + * + * @param mergeSource + * @param isNoAutoMerge + * @param isNoCheckout + * @param factory + * @return + */ + public static Element createMergeElement(String[] mergeSource, boolean isNoAutoMerge, boolean isNoCheckout, Document factory) { + Element mergeElem = DomUtil.createElement(factory, XML_MERGE, NAMESPACE); + Element source = DomUtil.addChildElement(mergeElem, DavConstants.XML_SOURCE, DavConstants.NAMESPACE); + for (String ms : mergeSource) { + source.appendChild(DomUtil.hrefToXml(ms, factory)); + } + if (isNoAutoMerge) { + DomUtil.addChildElement(mergeElem, XML_N0_AUTO_MERGE, NAMESPACE); + } + if (isNoCheckout) { + DomUtil.addChildElement(mergeElem, XML_N0_CHECKOUT, NAMESPACE); + } + return mergeElem; + } +} Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/MergeInfo.java ___________________________________________________________________ Added: svn Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/OptionsInfo.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/OptionsInfo.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/OptionsInfo.java (working copy) @@ -0,0 +1,126 @@ +/* + * 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.webdav.version; + +import org.apache.jackrabbit.webdav.DavException; +import org.apache.jackrabbit.webdav.DavServletResponse; +import org.apache.jackrabbit.webdav.xml.DomUtil; +import org.apache.jackrabbit.webdav.xml.ElementIterator; +import org.apache.jackrabbit.webdav.xml.Namespace; +import org.apache.jackrabbit.webdav.xml.XmlSerializable; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +import java.util.HashSet; +import java.util.Set; +import java.util.Arrays; + +/** + * OptionsInfo represents the Xml request body, that may be present + * with a OPTIONS request. + *
+ * The DAV:options element is specified to have the following form. + * + *
+ * <!ELEMENT options ANY>
+ * ANY value: A sequence of elements each at most once.
+ * 
+ * + * Note, that this is a simplified implementation of the very generic + * definition: We assume that the DAV:options element only contains empty child + * elements, such as e.g. {@link DeltaVConstants#XML_VH_COLLECTION_SET DAV:version-history-collection-set} + * or {@link DeltaVConstants#XML_WSP_COLLECTION_SET DAV:workspace-collection-set}. + * + * @see DeltaVConstants#XML_VH_COLLECTION_SET + * @see DeltaVConstants#XML_WSP_COLLECTION_SET + * @see DeltaVConstants#XML_ACTIVITY_COLLECTION_SET + */ +public class OptionsInfo implements XmlSerializable { + + private static Logger log = LoggerFactory.getLogger(OptionsInfo.class); + + private final Set entriesLocalNames = new HashSet(); + + /** + * Create a new OptionsInfo with the specified entries. Each entry will + * be converted to an empty Xml element when calling toXml. + * As namespace {@link DeltaVConstants#NAMESPACE} is used. + * + * @param entriesLocalNames + */ + public OptionsInfo(String[] entriesLocalNames) { + if (entriesLocalNames != null) { + this.entriesLocalNames.addAll(Arrays.asList(entriesLocalNames)); + } + } + + /** + * Private constructor used to create an OptionsInfo from Xml. + */ + private OptionsInfo() {} + + /** + * Returns true if a child element with the given name and namespace is present. + * + * @param localName + * @param namespace + * @return true if such a child element exists in the options element. + */ + public boolean containsElement(String localName, Namespace namespace) { + if (DeltaVConstants.NAMESPACE.equals(namespace)) { + return entriesLocalNames.contains(localName); + } + return false; + } + + /** + * @see org.apache.jackrabbit.webdav.xml.XmlSerializable#toXml(Document) + * @param document + */ + public Element toXml(Document document) { + Element optionsElem = DomUtil.createElement(document, DeltaVConstants.XML_OPTIONS, DeltaVConstants.NAMESPACE); + for (String localName : entriesLocalNames) { + DomUtil.addChildElement(optionsElem, localName, DeltaVConstants.NAMESPACE); + } + return optionsElem; + } + + /** + * Build an OptionsInfo object from the root element present + * in the request body. + * + * @param optionsElement + * @return + * @throws DavException if the optionsElement is null + * or not a DAV:options element. + */ + public static OptionsInfo createFromXml(Element optionsElement) throws DavException { + if (!DomUtil.matches(optionsElement, DeltaVConstants.XML_OPTIONS, DeltaVConstants.NAMESPACE)) { + log.warn("DAV:options element expected"); + throw new DavException(DavServletResponse.SC_BAD_REQUEST); + } + OptionsInfo oInfo = new OptionsInfo(); + ElementIterator it = DomUtil.getChildren(optionsElement); + while (it.hasNext()) { + // todo: not correct since assuming its the deltaV-namespace + oInfo.entriesLocalNames.add(it.nextElement().getLocalName()); + } + return oInfo; + } +} Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/OptionsInfo.java ___________________________________________________________________ Added: svn Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/OptionsResponse.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/OptionsResponse.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/OptionsResponse.java (working copy) @@ -0,0 +1,144 @@ +/* + * 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.webdav.version; + +import org.apache.jackrabbit.webdav.DavConstants; +import org.apache.jackrabbit.webdav.xml.DomUtil; +import org.apache.jackrabbit.webdav.xml.ElementIterator; +import org.apache.jackrabbit.webdav.xml.Namespace; +import org.apache.jackrabbit.webdav.xml.XmlSerializable; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * OptionsResponse encapsulates the DAV:options-response element + * present in the response body of a successful OPTIONS request (with body). + *
+ * The DAV:options-response element is defined to have the following format. + * + *
+ * <!ELEMENT options-response ANY>
+ * ANY value: A sequence of elements
+ * 
+ * + * Please note, that OptionsResponse represents a simplified implementation + * of the given structure. We assume, that there may only entries that consist + * of a qualified name and a set of href child elements. + * + * @see DeltaVConstants#XML_ACTIVITY_COLLECTION_SET + * @see DeltaVConstants#XML_VH_COLLECTION_SET + * @see DeltaVConstants#XML_WSP_COLLECTION_SET + */ +public class OptionsResponse implements DeltaVConstants, XmlSerializable { + + private static Logger log = LoggerFactory.getLogger(OptionsResponse.class); + + private final Map entries = new HashMap(); + + /** + * Add a new entry to this OptionsResponse and make each + * href present in the String array being a separate {@link org.apache.jackrabbit.webdav.DavConstants#XML_HREF DAV:href} + * element within the entry. + * + * @param localName + * @param namespace + * @param hrefs + */ + public void addEntry(String localName, Namespace namespace, String[] hrefs) { + Entry entry = new Entry(localName, namespace, hrefs); + entries.put(DomUtil.getExpandedName(localName, namespace), entry); + } + + /** + * + * @param localName + * @param namespace + * @return + */ + public String[] getHrefs(String localName, Namespace namespace) { + String key = DomUtil.getExpandedName(localName, namespace); + if (entries.containsKey(key)) { + return entries.get(key).hrefs; + } else { + return new String[0]; + } + } + + /** + * Return the Xml representation. + * + * @return Xml representation. + * @see org.apache.jackrabbit.webdav.xml.XmlSerializable#toXml(Document) + * @param document + */ + public Element toXml(Document document) { + Element optionsResponse = DomUtil.createElement(document, XML_OPTIONS_RESPONSE, NAMESPACE); + for (Entry entry : entries.values()) { + Element elem = DomUtil.addChildElement(optionsResponse, entry.localName, entry.namespace); + for (String href : entry.hrefs) { + elem.appendChild(DomUtil.hrefToXml(href, document)); + } + } + return optionsResponse; + } + + /** + * Build a new OptionsResponse object from the given xml element. + * + * @param orElem + * @return a new OptionsResponse object + * @throws IllegalArgumentException if the specified element is null + * or if its name is other than 'DAV:options-response'. + */ + public static OptionsResponse createFromXml(Element orElem) { + if (!DomUtil.matches(orElem, XML_OPTIONS_RESPONSE, NAMESPACE)) { + throw new IllegalArgumentException("DAV:options-response element expected"); + } + OptionsResponse oResponse = new OptionsResponse(); + ElementIterator it = DomUtil.getChildren(orElem); + while (it.hasNext()) { + Element el = it.nextElement(); + List hrefs = new ArrayList(); + ElementIterator hrefIt = DomUtil.getChildren(el, DavConstants.XML_HREF, DavConstants.NAMESPACE); + while (hrefIt.hasNext()) { + hrefs.add(DomUtil.getTextTrim(hrefIt.nextElement())); + } + oResponse.addEntry(el.getLocalName(), DomUtil.getNamespace(el), hrefs.toArray(new String[hrefs.size()])); + } + return oResponse; + } + + private static class Entry { + + private final String localName; + private final Namespace namespace; + private final String[] hrefs; + + private Entry(String localName, Namespace namespace, String[] hrefs) { + this.localName = localName; + this.namespace = namespace; + this.hrefs = hrefs; + } + } +} Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/OptionsResponse.java ___________________________________________________________________ Added: svn Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/SupportedMethodSetProperty.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/SupportedMethodSetProperty.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/SupportedMethodSetProperty.java (working copy) @@ -0,0 +1,63 @@ +/* + * 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.webdav.version; + +import org.apache.jackrabbit.webdav.property.AbstractDavProperty; +import org.apache.jackrabbit.webdav.xml.DomUtil; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +/** + * The SupportedMethodSetProperty + */ +public class SupportedMethodSetProperty extends AbstractDavProperty implements DeltaVConstants { + + private static Logger log = LoggerFactory.getLogger(SupportedMethodSetProperty.class); + + private final String[] methods; + + /** + * Create a new SupportedMethodSetProperty property. + * + * @param methods that are supported by the resource having this property. + */ + public SupportedMethodSetProperty(String[] methods) { + super(DeltaVConstants.SUPPORTED_METHOD_SET, true); + this.methods = methods; + } + + public String[] getValue() { + return methods; + } + + /** + * @see org.apache.jackrabbit.webdav.xml.XmlSerializable#toXml(Document) + * @param document + */ + @Override + public Element toXml(Document document) { + Element elem = getName().toXml(document); + for (String method : methods) { + Element methodElem = DomUtil.addChildElement(elem, XML_SUPPORTED_METHOD, DeltaVConstants.NAMESPACE); + DomUtil.setAttribute(methodElem, "name", DeltaVConstants.NAMESPACE, method); + } + return elem; + } + +} Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/SupportedMethodSetProperty.java ___________________________________________________________________ Added: svn Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/UpdateInfo.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/UpdateInfo.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/UpdateInfo.java (working copy) @@ -0,0 +1,243 @@ +/* + * 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.webdav.version; + +import org.apache.jackrabbit.webdav.DavConstants; +import org.apache.jackrabbit.webdav.DavException; +import org.apache.jackrabbit.webdav.DavServletResponse; +import org.apache.jackrabbit.webdav.property.DavPropertyNameSet; +import org.apache.jackrabbit.webdav.xml.DomUtil; +import org.apache.jackrabbit.webdav.xml.ElementIterator; +import org.apache.jackrabbit.webdav.xml.XmlSerializable; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +import java.util.ArrayList; +import java.util.List; + +/** + * UpdateInfo encapsulates the request body of an UPDATE request. + * RFC 3253 defines the request body as follows: + *
+ * <!ELEMENT update ANY>
+ * ANY value: A sequence of elements with at most one DAV:label-name or
+ * DAV:version element (but not both).
+ * In addition at one DAV:prop element can be present.
+ *
+ * <!ELEMENT version (href)>
+ * <!ELEMENT label-name (#PCDATA)> PCDATA value: string
+ * prop: see RFC 2518, Section 12.11
+ * 
+ * + * In order to reflect the complete range of version restoring and updating + * of nodes defined by JSR170 the definition has been extended: + *
+ * <!ELEMENT update ( (version | label-name | workspace ) , (prop)?, (removeExisting)? ) >
+ * <!ELEMENT version (href+) >
+ * <!ELEMENT label-name (#PCDATA) >
+ * <!ELEMENT workspace (href) >
+ * <!ELEMENT prop ANY >
+ * <!ELEMENT removeExisting EMPTY >
+ * 
+ */ +public class UpdateInfo implements DeltaVConstants, XmlSerializable { + + private static Logger log = LoggerFactory.getLogger(UpdateInfo.class); + + public static final int UPDATE_BY_VERSION = 0; + public static final int UPDATE_BY_LABEL = 1; + public static final int UPDATE_BY_WORKSPACE = 2; + + private Element updateElement; + + private DavPropertyNameSet propertyNameSet = new DavPropertyNameSet(); + private String[] source; + private int type; + + public UpdateInfo(String[] updateSource, int updateType, DavPropertyNameSet propertyNameSet) { + if (updateSource == null || updateSource.length == 0) { + throw new IllegalArgumentException("Version href array must not be null and have a minimal length of 1."); + } + if (updateType < UPDATE_BY_VERSION || updateType > UPDATE_BY_WORKSPACE) { + throw new IllegalArgumentException("Illegal type of UpdateInfo."); + } + this.type = updateType; + this.source = (updateType == UPDATE_BY_VERSION) ? updateSource : new String[] {updateSource[0]}; + if (propertyNameSet != null) { + this.propertyNameSet = propertyNameSet; + } + } + + /** + * Create a new UpdateInfo object. + * + * @param updateElement + * @throws DavException if the updateElement is null + * or not a DAV:update element or if the element does not match the required + * structure. + */ + public UpdateInfo(Element updateElement) throws DavException { + if (!DomUtil.matches(updateElement, XML_UPDATE, NAMESPACE)) { + log.warn("DAV:update element expected"); + throw new DavException(DavServletResponse.SC_BAD_REQUEST); + } + + boolean done = false; + if (DomUtil.hasChildElement(updateElement, XML_VERSION, NAMESPACE)) { + Element vEl = DomUtil.getChildElement(updateElement, XML_VERSION, NAMESPACE); + ElementIterator hrefs = DomUtil.getChildren(vEl, DavConstants.XML_HREF, DavConstants.NAMESPACE); + List hrefList = new ArrayList(); + while (hrefs.hasNext()) { + hrefList.add(DomUtil.getText(hrefs.nextElement())); + } + source = hrefList.toArray(new String[hrefList.size()]); + type = UPDATE_BY_VERSION; + done = true; + } + + // alternatively 'DAV:label-name' elements may be present. + if (!done && DomUtil.hasChildElement(updateElement, XML_LABEL_NAME, NAMESPACE)) { + source = new String[] {DomUtil.getChildText(updateElement, XML_LABEL_NAME, NAMESPACE)}; + type = UPDATE_BY_LABEL; + done = true; + } + + // last possibility: a DAV:workspace element + if (!done) { + Element wspElem = DomUtil.getChildElement(updateElement, XML_WORKSPACE, NAMESPACE); + if (wspElem != null) { + source = new String[] {DomUtil.getChildTextTrim(wspElem, DavConstants.XML_HREF, DavConstants.NAMESPACE)}; + type = UPDATE_BY_WORKSPACE; + } else { + log.warn("DAV:update element must contain either DAV:version, DAV:label-name or DAV:workspace child element."); + throw new DavException(DavServletResponse.SC_BAD_REQUEST); + } + } + + // if property name set if present + if (DomUtil.hasChildElement(updateElement, DavConstants.XML_PROP, DavConstants.NAMESPACE)) { + Element propEl = DomUtil.getChildElement(updateElement, DavConstants.XML_PROP, DavConstants.NAMESPACE); + propertyNameSet = new DavPropertyNameSet(propEl); + updateElement.removeChild(propEl); + } else { + propertyNameSet = new DavPropertyNameSet(); + } + this.updateElement = updateElement; + } + + /** + * + * @return + */ + public String[] getVersionHref() { + return (type == UPDATE_BY_VERSION) ? source : null; + } + + /** + * + * @return + */ + public String[] getLabelName() { + return (type == UPDATE_BY_LABEL) ? source : null; + } + + /** + * + * @return + */ + public String getWorkspaceHref() { + return (type == UPDATE_BY_WORKSPACE) ? source[0] : null; + } + + /** + * Returns a {@link DavPropertyNameSet}. If the DAV:update element contains + * a DAV:prop child element the properties specified therein are included + * in the set. Otherwise an empty set is returned. + *

+ * WARNING: modifying the DavPropertyNameSet returned by this method does + * not modify this UpdateInfo. + * + * @return set listing the properties specified in the DAV:prop element indicating + * those properties that must be reported in the response body. + */ + public DavPropertyNameSet getPropertyNameSet() { + return propertyNameSet; + } + + /** + * + * @return + */ + public Element getUpdateElement() { + return updateElement; + } + + /** + * @see org.apache.jackrabbit.webdav.xml.XmlSerializable#toXml(Document) + * @param document + */ + public Element toXml(Document document) { + Element elem; + if (updateElement != null) { + elem = (Element)document.importNode(updateElement, true); + } else { + elem = createUpdateElement(source, type, document); + } + if (!propertyNameSet.isEmpty()) { + elem.appendChild(propertyNameSet.toXml(document)); + } + return elem; + } + + /** + * Factory method to create the basic structure of an UpdateInfo + * object. + * + * @param updateSource + * @param updateType + * @param factory + * @return + */ + public static Element createUpdateElement(String[] updateSource, int updateType, Document factory) { + if (updateSource == null || updateSource.length == 0) { + throw new IllegalArgumentException("Update source must specific at least a single resource used to run the update."); + } + + Element elem = DomUtil.createElement(factory, XML_UPDATE, NAMESPACE); + switch (updateType) { + case UPDATE_BY_VERSION: + Element vE = DomUtil.addChildElement(elem, XML_VERSION, NAMESPACE); + for (String source : updateSource) { + vE.appendChild(DomUtil.hrefToXml(source, factory)); + } + break; + case UPDATE_BY_LABEL: + DomUtil.addChildElement(elem, XML_LABEL_NAME, NAMESPACE, updateSource[0]); + break; + case UPDATE_BY_WORKSPACE: + Element wspEl = DomUtil.addChildElement(elem, XML_WORKSPACE, NAMESPACE, updateSource[0]); + wspEl.appendChild(DomUtil.hrefToXml(updateSource[0], factory)); + break; + // no default. + default: + throw new IllegalArgumentException("Invalid update type: " + updateType); + } + return elem; + } +} Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/UpdateInfo.java ___________________________________________________________________ Added: svn Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/VersionControlledResource.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/VersionControlledResource.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/VersionControlledResource.java (working copy) @@ -0,0 +1,363 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.jackrabbit.webdav.version; + +import org.apache.jackrabbit.webdav.DavException; +import org.apache.jackrabbit.webdav.MultiStatus; +import org.apache.jackrabbit.webdav.property.DavPropertyName; + +/** + * The VersionControlledResource represents in contrast to the + * VersionableResource a resource, that has already been put + * under version-control. This resource can be checked-in, checked-out and + * has its own {@link VersionHistoryResource version history}. + *

+ * RFC 3253 defines the following required properties for a + * version-controlled resource (vc-resource): + *

    + *
  • DAV:auto-version
  • + *
  • DAV:version-history (version-history)
  • + *
  • DAV:workspace (workspace)
  • + *
  • DAV:version-controlled-configuration (baseline)
  • + *
  • all DeltaV-compliant resource properties.
  • + *
+ * + * checked-in vc-resource: + *
    + *
  • DAV:checked-in
  • + *
+ * + * checked-out vc-resource: + *
    + *
  • DAV:checked-out
  • + *
  • DAV:predecessor-set
  • + *
  • DAV:checkout-fork (in-place-checkout or working resource)
  • + *
  • DAV:checkin-fork (in-place-checkout or working resource)
  • + *
  • DAV:merge-set (merge)
  • + *
  • DAV:auto-merge-set (merge)
  • + *
  • DAV:unreserved (activity)
  • + *
  • DAV:activity-set (activity)
  • + *
+ * + * If the Version-Controlled-Collection feature is supported (see section 14 + * of RFC 3253) the following computed property is required: + *
    + *
  • DAV:eclipsed-set
  • + *
+ * + * If the Baseline feature is supported (see section 12 of RFC 3253), a version- + * controlled resource may represent a 'configuration' rather than a single + * resource. In this case the RFC defines the following required properties: + *
    + *
  • DAV:baseline-controlled-collection
  • + *
  • DAV:subbaseline-set (if the configuration resource is checked-out)
  • + *
+ * + *

+ * In addition a version-controlled resource must support the following METHODS: + *

    + *
  • VERSION-CONTROL
  • + *
  • MERGE (merge)
  • + *
  • all DeltaV-compliant resource METHODS.
  • + *
+ * + * checked-in vc-resource: + *
    + *
  • CHECKOUT (checkout-in-place)
  • + *
  • UPDATE (update)
  • + *
  • all version-controlled resource METHODS.
  • + *
+ * + * checked-out vc-resource: + *
    + *
  • CHECKIN (checkout-in-place or working-resource)
  • + *
  • UNCHECKOUT (checkout-in-place)
  • + *
  • all DeltaV-compliant resource METHODS.
  • + *
+ * + * @see DeltaVResource + * @see VersionableResource + */ +public interface VersionControlledResource extends VersionableResource { + + /** + * Methods defined for a checked-in version-controlled resource: CHECKOUT, UPDATE, MERGE, LABEL + */ + public String methods_checkedIn = "CHECKOUT, UPDATE, MERGE, LABEL"; + /** + * Methods defined for a checked-out version-controlled resource: CHECKIN, MERGE + */ + public String methods_checkedOut = "CHECKIN, MERGE"; + + /** + * The DAV:auto-version property determines how it responds to a method that + * attempts to modify its content or dead properties. Possible responses + * include various combinations of automated checkout, write lock and checkin + * as well as failure until the resource is explicitly checked-out.
+ * See RFC 3253 for a detailed + * description. + */ + public static final DavPropertyName AUTO_VERSION = DavPropertyName.create("auto-version", DeltaVConstants.NAMESPACE); + + /** + * The computed property DAV:version-history identifies the version history + * resource for the DAV:checked-in or DAV:checked-out version of this + * version-controlled resource.
+ * The property is defined to have the following format: + *
+     * <!ELEMENT version-history (href)>
+     * 
+ */ + public static final DavPropertyName VERSION_HISTORY = DavPropertyName.create("version-history", DeltaVConstants.NAMESPACE); + + /** + * The DAV:checked-in property appears on a checked-in version-controlled + * resource, and identifies the base version of this version-controlled + * resource. This property is removed when the resource is checked out, and + * then added back (identifying a new version) when the resource is checked + * back in.
+ * This property is defined to have the following format: + *
+     * <!ELEMENT checked-in (href)>
+     * 
+ */ + public static final DavPropertyName CHECKED_IN = DavPropertyName.create("checked-in", DeltaVConstants.NAMESPACE); + + /** + * The DAV:checked-out property identifies the base version of this resource. + * It is the same that was identified by the DAV:checked-in property at the + * time the resource was checked out. This property is removed when the + * resource is checked in.
+ * This property is defined to have the following format: + *
+     * <!ELEMENT checked-out (href)>
+     * 
+ * + * @see #CHECKED_IN + */ + public static final DavPropertyName CHECKED_OUT = DavPropertyName.create("checked-out", DeltaVConstants.NAMESPACE); + + /** + * The DAV:predecessor-set property of a version-controlled resource points + * to those version resources, that are scheduled to become the predecessors + * of this resource when it is back checked-in. This property is not + * protected, however a server may reject attempts to modify the + * DAV:predecessor-set of a version-controlled resource.
+ * This property is defined to have the following format: + *
+     * <!ELEMENT predecessor-set (href+)>
+     * 
+ * + * @see #checkin() + * @see VersionResource#PREDECESSOR_SET + */ + public static final DavPropertyName PREDECESSOR_SET = DavPropertyName.create("predecessor-set", DeltaVConstants.NAMESPACE); + + /** + * This property determines the DAV:checkin-fork property of the version + * that results from checking in this resource. + */ + public static final DavPropertyName CHECKIN_FORK = DavPropertyName.create("checkin-fork", DeltaVConstants.NAMESPACE); + + /** + * This property determines the DAV:checkout-fork property of the version + * that results from checking in this resource. + */ + public static final DavPropertyName CHECKOUT_FORK = DavPropertyName.create("checkout-fork", DeltaVConstants.NAMESPACE); + + /** + * This property identifies each version that is to be merged into this + * checked-out resource. This property is set, whenever a MERGE request + * with the DAV:no-auto-merge flag succeeded. The client then must confirm + * each single merge by removing the version from the DAV:merge-set or + * moving it the the versions DAV:predecessor-set.
+ * This property is defined to have the following format: + *
+     * <!ELEMENT merge-set (href*)>
+     * 
+ * + * @see #merge(MergeInfo) + */ + public static final DavPropertyName MERGE_SET = DavPropertyName.create("merge-set", DeltaVConstants.NAMESPACE); + + /** + * The DAV:auto-merge-set property identifies each version that the server + * has merged into this checked-out resource. The client should confirm that + * the merge has been performed correctly before moving a URL from the + * DAV:auto-merge-set to the DAV:predecessor-set of a checked-out resource.
+ * This property is defined to have the following format: + *
+     * <!ELEMENT auto-merge-set (href*)>
+     * 
+ * + * @see #merge(MergeInfo) + */ + public static final DavPropertyName AUTO_MERGE_SET = DavPropertyName.create("auto-merge-set", DeltaVConstants.NAMESPACE); + + /** + * DAV:unreserved is a property for a checked-out resource, if the server + * supports the activity feature.
+ * It indicates whether the DAV:activity-set of another checked-out resource + * associated with the version history of this version-controlled resource + * can have an activity that is in the DAV:activity-set property of this + * checked-out resource. + *
+ * A result of the requirement that an activity must form a single line of + * descent through a given version history is that if multiple checked-out + * resources for a given version history are checked out unreserved into a + * single activity, only the first CHECKIN will succeed. Before another of + * these checked-out resources can be checked in, the user will first have + * to merge into that checked-out resource the latest version selected by + * that activity from that version history, and then modify the + * DAV:predecessor-set of that checked-out resource to identify that version. + *

+ * This property is defined to have the following format: + *

+     * <!ELEMENT unreserved (#PCDATA)>
+     * PCDATA value: boolean
+     * 
+ * @see VersionResource#ACTIVITY_SET + */ + public static final DavPropertyName UNRESERVED = DavPropertyName.create("activity-set", DeltaVConstants.NAMESPACE); + + /** + * DAV:activity-set is a property for a checked-out resource, if the + * server supports the activity feature.
+ * This property determines the DAV:activity-set property of the version that + * results from checking in this resource. + * + * @see VersionResource#ACTIVITY_SET + */ + public static final DavPropertyName ACTIVITY_SET = DavPropertyName.create("activity-set", DeltaVConstants.NAMESPACE); + + /** + * If the 'Version-Controlled-Collection Feature' is supported the + * DAV:eclipsed-set property present on a collection identifies all + * internal members that are not version-controlled and hide a vc internal + * member with the same name. + *

+ * This property is defined to have the following format: + *

+     * <!ELEMENT eclipsed-set (binding-name*)>
+     * <!ELEMENT binding-name (#PCDATA)>
+     * PCDATA value: URL segment
+     * 
+ * + * @see VersionResource#VERSION_CONTROLLED_BINDING_SET + */ + public static final DavPropertyName ECLIPSED_SET = DavPropertyName.create("eclipsed-set", DeltaVConstants.NAMESPACE); + + /** + * If the 'Baseline' feature is supported, DAV:baseline-controlled-collection + * is a required property of any version-controlled resource, that represents + * a 'configuration'. It identifies the collection that contains the + * version-controlled resources whose versions are tracked by this + * configuration. + *

+ * This property is defined to have the following format: + *

+     * <!ELEMENT baseline-controlled-collection (href)>
+     * 
+ * Note that the DAV:baseline-controlled-collection represents a + * {@link org.apache.jackrabbit.webdav.property.HrefProperty HrefProperty} + * + * @see DeltaVConstants#VERSION_CONTROLLED_CONFIGURATION for the corresponding + * property, that is required for all resources that are contained in this + * version-controlled-configuration. + */ + public static final DavPropertyName BASELINE_CONTROLLED_COLLECTION = DavPropertyName.create("baseline-controlled-collection", DeltaVConstants.NAMESPACE); + + /** + * This property is mandatory for all checked-out version-controlled-configuration + * resources. It determines the DAV:subbaseline-set property of the baseline + * that results from checking in this resource. + *

+ * This property is defined to have the following format: + *

+     * <!ELEMENT subbaseline-set (href*)>
+     * 
+ * Note that the DAV:baseline-controlled-collection represents a + * {@link org.apache.jackrabbit.webdav.property.HrefProperty HrefProperty} + * @see BaselineResource#SUBBASELINE_SET + */ + public static final DavPropertyName SUBBASELINE_SET = DavPropertyName.create("subbaseline-set", DeltaVConstants.NAMESPACE); + + /** + * Perform a checkin on the version controlled resource. + * + * @return String representing the location of the version created by the + * checkin. + * @throws DavException if an error occurs. + */ + public String checkin() throws DavException; + + /** + * Perform a checkout on the version controlled resource. + * + * @throws DavException + */ + public void checkout() throws DavException; + + /** + * Perform an uncheckout on the version controlled resource. + * + * @throws DavException + */ + public void uncheckout() throws DavException; + + /** + * Perform an update on this resource using the specified {@link UpdateInfo}. + * + * @param updateInfo + * @return MultiStatus containing the list of resources that + * have been modified by this update call. + * @throws DavException + */ + public MultiStatus update(UpdateInfo updateInfo) throws DavException; + + /** + * Perform a merge on this resource using the specified {@link MergeInfo}. + * + * @param mergeInfo + * @return MultiStatus containing the list of resources that + * have been modified. + * @throws DavException + */ + public MultiStatus merge(MergeInfo mergeInfo) throws DavException; + + /** + * Modify the labels of the version referenced by the DAV:checked-in property + * of this checked-in version-controlled resource. If the resource is not + * checked-in the request must fail. + * + * @param labelInfo + * @throws org.apache.jackrabbit.webdav.DavException + * @see LabelInfo + * @see VersionResource#label(LabelInfo) for the pre- and postcondition of + * a successful LABEL request. + */ + public void label(LabelInfo labelInfo) throws DavException; + + /** + * Returns the VersionHistoryResource, that is referenced in the + * '{@link #VERSION_HISTORY version-history}' property. + * + * @return + * @throws DavException + */ + public VersionHistoryResource getVersionHistory() throws DavException; +} \ No newline at end of file Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/VersionControlledResource.java ___________________________________________________________________ Added: svn Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/VersionHistoryResource.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/VersionHistoryResource.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/VersionHistoryResource.java (working copy) @@ -0,0 +1,73 @@ +/* + * 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.webdav.version; + +import org.apache.jackrabbit.webdav.DavException; +import org.apache.jackrabbit.webdav.property.DavPropertyName; +import org.apache.jackrabbit.webdav.property.ResourceType; + +/** + * VersionHistoryResource represents a collection that has + * all versions of a given version-controlled resource as members. + *

+ * RFC 3253 defines the following required properties for a version history: + *

    + *
  • DAV:version-set
  • + *
  • DAV:root-version
  • + *
  • all DeltaV-compliant resource properties.
  • + *
+ *

+ * In addition a version history resource must support the following METHODS: + *

    + *
  • all DeltaV-compliant resource METHODS.
  • + *
+ * + * NOTE: the {@link org.apache.jackrabbit.webdav.DavConstants#PROPERTY_RESOURCETYPE DAV:resourcetype} + * property must indicate 'DAV:version-history'. + * + * @see DeltaVResource + * @see ResourceType#VERSION_HISTORY + */ +public interface VersionHistoryResource extends DeltaVResource { + + // supported METHODS: same as DeltaVResource > set to empty string + public static final String METHODS = ""; + + /** + * Computed (protected) property identifying the root version of this version + * history. + */ + public static final DavPropertyName ROOT_VERSION = DavPropertyName.create("root-version", DeltaVConstants.NAMESPACE); + + /** + * The protected property DAV:version-set identifies each version of this + * version history. + * + * @see #getVersions() + */ + public static final DavPropertyName VERSION_SET = DavPropertyName.create("version-set", DeltaVConstants.NAMESPACE); + + /** + * Returns an array of VersionResources containing all versions + * that are a member of this resource. + * + * @return all VersionResources that belong to this version history. + * @throws org.apache.jackrabbit.webdav.DavException + * @see #VERSION_SET + */ + public VersionResource[] getVersions() throws DavException; +} \ No newline at end of file Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/VersionHistoryResource.java ___________________________________________________________________ Added: svn Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/VersionResource.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/VersionResource.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/VersionResource.java (working copy) @@ -0,0 +1,213 @@ +/* + * 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.webdav.version; + +import org.apache.jackrabbit.webdav.DavException; +import org.apache.jackrabbit.webdav.property.DavPropertyName; + +/** + * VersionResource is a resource that contains a copy of a particular + * state of a version-controlled resource. A new version resource is created whenever + * a checked-out version-controlled resource is checked-in. The server allocates + * a distinct new URL for each new version, and this URL will never be used to + * identify any resource other than that version. The content and dead properties + * of a version never change. + *

+ * RFC 3253 defines the following required properties for a version resource: + *

    + *
  • DAV:predecessor-set (protected)
  • + *
  • DAV:successor-set (computed)
  • + *
  • DAV:checkout-set
  • + *
  • DAV:version-name
  • + *
  • DAV:checkout-fork (in-place-checkout or working resource)
  • + *
  • DAV:checkin-fork (in-place-checkout or working resource)
  • + *
  • DAV:version-history (version-history)
  • + *
  • DAV:label-name-set (label)
  • + *
  • DAV:activity-set (activity)
  • + *
  • all DeltaV-compliant resource properties.
  • + *
+ * + * If the 'Version-Controlled-Collection Feature' is supported (see section 14 + * of RFC 3253) the following protected property is defined for a version + * resource associated with a version-controlled collection. + *
    + *
  • DAV:version-controlled-binding-set
  • + *
+ * + *

+ * In addition a version resource must support the following METHODS: + *

    + *
  • LABEL (label)
  • + *
  • CHECKOUT (working-resource)
  • + *
  • all DeltaV-compliant resource METHODS.
  • + *
+ * + * @see DeltaVResource + */ +public interface VersionResource extends DeltaVResource { + + /** + * The version resource defines one additional method LABEL. + * + * @see DeltaVResource#METHODS + * @see org.apache.jackrabbit.webdav.DavResource#METHODS + */ + public String METHODS = "LABEL"; + + /** + * Required protected property 'DAV:label-name-set' for a version of a webdav + * resource introduced with the 'LabelInfo' feature. + * This property contains the labels that currently select this version.
+ * Property structure is defined as follows:
+ *
+     * <!ELEMENT label-name-set (label-name*)>
+     * <!ELEMENT label-name (#PCDATA)>
+     * PCDATA value: string
+     * 
+ */ + public static final DavPropertyName LABEL_NAME_SET = DavPropertyName.create("label-name-set", DeltaVConstants.NAMESPACE); + + /** + * The protected DAV:predecessor property identifies each predecessor of + * this version. Except for the root version, which has no predecessors, + * each version has at least one predecessor.
+ * The property is defined to have the following format: + *
+     * <!ELEMENT predecessor-set (href*)>
+     * 
+ */ + public static final DavPropertyName PREDECESSOR_SET = DavPropertyName.create("predecessor-set", DeltaVConstants.NAMESPACE); + + /** + * The computed property DAV:successor-set identifies each version whose + * DAV:predecessor-set identifies this version.
+ * The property is defined to have the following format: + *
+     * <!ELEMENT successor-set (href*)>
+     * 
+ * + */ + public static final DavPropertyName SUCCESSOR_SET = DavPropertyName.create("successor-set", DeltaVConstants.NAMESPACE); + + /** + * The computed property DAV:checkout-set identifies each checked-out + * resource whose DAV:checked-out property identifies this version.
+ * The property is defined to have the following format: + *
+     * <!ELEMENT checkout-set (href*)>
+     * 
+ * + * @see VersionControlledResource#CHECKED_OUT + */ + public static final DavPropertyName CHECKOUT_SET = DavPropertyName.create("checkout-set", DeltaVConstants.NAMESPACE); + + /** + * The protected property DAV:version-name defines a human readable id for + * this version. The id defined to be unique within the version-history this + * version belongs to.
+ * The property is defined to have the following format: + *
+     * <!ELEMENT version-name (#PCDATA)>
+     * PCDATA value: string
+     * 
+ */ + public static final DavPropertyName VERSION_NAME = DavPropertyName.create("version-name", DeltaVConstants.NAMESPACE); + + /** + * The computed property DAV:version-history identifies the version history + * that contains this version.
+ * The property is defined to have the following format: + *
+     * <!ELEMENT version-history (href)>
+     * 
+ */ + public static final DavPropertyName VERSION_HISTORY = DavPropertyName.create("version-history", DeltaVConstants.NAMESPACE); + + /** + * This property controls the behavior of CHECKOUT when a version already + * is checked out or has a successor. + */ + public static final DavPropertyName CHECKOUT_FORK = DavPropertyName.create("checkout-fork", DeltaVConstants.NAMESPACE); + + /** + * This property controls the behavior of CHECKIN when a version already + * has a successor. + */ + public static final DavPropertyName CHECKIN_FORK = DavPropertyName.create("checkin-fork", DeltaVConstants.NAMESPACE); + + /** + * DAV:activity-set is a required property for a version resource, if the + * server supports the activity feature.
+ * It identifies the activities that determine to which logical changes this + * version contributes, and on which lines of descent this version appears. + * A server MAY restrict the DAV:activity-set to identify a single activity. + * A server MAY refuse to allow the value of the DAV:activity-set property + * of a version to be modified. + *

+ * The property is defined to have the following format: + *

+     * <!ELEMENT activity-set (href*)>
+     * 
+ * Note that the DAV:activity-set represents a + * {@link org.apache.jackrabbit.webdav.property.HrefProperty HrefProperty} + */ + public static final DavPropertyName ACTIVITY_SET = DavPropertyName.create("activity-set", DeltaVConstants.NAMESPACE); + + /** + * If the 'Version-Controlled-Collection Feature' is supported the + * DAV:version-controlled-binding-set property identifies the name and the + * version history of all version-controlled internal members of the + * collection this version resource belongs to. + *

+ * This property is defined to have the following format: + *

+     * <!ELEMENT version-controlled-binding-set (version-controlled-binding*)>
+     * <!ELEMENT version-controlled-binding (binding-name, version-history)>
+     * <!ELEMENT binding-name (#PCDATA)>
+     * PCDATA value: URL segment
+     * <!ELEMENT version-history (href)>
+     * 
+ * + * @see VersionControlledResource#ECLIPSED_SET + */ + public static final DavPropertyName VERSION_CONTROLLED_BINDING_SET = DavPropertyName.create("version-controlled-binding-set", DeltaVConstants.NAMESPACE); + + /** + * Modify the labels of this version resource. The modifications (SET, ADD or + * REMOVE) are listed in the specified LabelInfo object.
+ * The case of a label name must be preserved when it is stored and retrieved. + *
If the type of modification is ADD, then the label must not yet occur on + * any other version within the same version history. In contrast a SET + * modification will move the indicated label to this version, if it existed + * with another version before. After a successful LABEL request the label + * must not appear with any other version in the same version history. + * + * @param labelInfo + * @throws org.apache.jackrabbit.webdav.DavException + * @see LabelInfo + */ + public void label(LabelInfo labelInfo) throws DavException; + + /** + * Returns the VersionHistoryResource, that is referenced in the + * {@link #VERSION_HISTORY DAV:version-history} property. + * + * @return + * @throws DavException + */ + public VersionHistoryResource getVersionHistory() throws DavException; +} \ No newline at end of file Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/VersionResource.java ___________________________________________________________________ Added: svn Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/VersionableResource.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/VersionableResource.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/VersionableResource.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.webdav.version; + +import org.apache.jackrabbit.webdav.DavException; + +/** + * VersionableResource represents an extension to the basic + * {@link DeltaVResource}, that allows to adding version-control support. By + * calling {@link #addVersionControl()} resource is put under version control, + * thus the versionable resource turns into a version controlled resource. + *

+ * RFC 3253 defines the following required properties for a versionable resource: + *

    + *
  • {@link DeltaVConstants#WORKSPACE DAV:workspace} (workspace feature)
  • + *
  • DAV:version-controlled-configuration (baseline feature)
  • + *
  • all DeltaV-compliant resource properties
  • + *
+ *

+ * In addition a versionable resource must support the following METHODS: + *

    + *
  • VERSION-CONTROL
  • + *
  • all DeltaV-compliant resource METHODS.
  • + *
+ * + * @see DeltaVResource + */ +public interface VersionableResource extends DeltaVResource { + + /** + * The versionable resource defines one additional method VERSION-CONTROL. + * + * @see DeltaVResource#METHODS + * @see org.apache.jackrabbit.webdav.DavResource#METHODS + */ + public String METHODS = "VERSION-CONTROL"; + + /** + * Converts this versionable resource into a version-controlled resource. If + * this resource is already version-controlled this resource is not affected. + * If however, this resource is not versionable an DavException + * (error code: {@link org.apache.jackrabbit.webdav.DavServletResponse#SC_METHOD_NOT_ALLOWED} + * is thrown. The same applies, if this resource is versionable but its + * current state does not allow to made it a version-controlled one or + * if any other error occurs. + * + * @throws org.apache.jackrabbit.webdav.DavException + */ + public void addVersionControl() throws DavException; +} \ No newline at end of file Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/VersionableResource.java ___________________________________________________________________ Added: svn Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/WorkspaceResource.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/WorkspaceResource.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/WorkspaceResource.java (working copy) @@ -0,0 +1,94 @@ +/* + * 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.webdav.version; + +import org.apache.jackrabbit.webdav.property.DavPropertyName; + +/** + * A workspace resource is a collection whose members are related + * version-controlled and non-version-controlled resources. + * + *

+ * RFC 3253 defines the following required live properties for an Workspace + * resource. + *

    + *
  • all DeltaV-compliant resource properties
  • + *
  • {@link #WORKSPACE_CHECKOUT_SET DAV:workspace-checkout-set}
  • + *
  • {@link #BASELINE_CONTROLLED_COLLECTION_SET DAV:baseline-controlled-collection-set} (baseline)
  • + *
  • {@link #CURRENT_ACTIVITY_SET DAV:current-activity-set} (activity)
  • + *
+ * Note, that RFC 3253 doesn't define a separate resource type for a workspace. + *

+ * The workspace resource must support all methods defined for a DeltaV-compliant + * collection. Since no additional methods are required for a workspace this + * interface mainly acts as marker. + *

+ * Please refer to RFC 3253 + * Section 6 for a complete description of this resource type. + */ +public interface WorkspaceResource extends DeltaVResource { + + /** + * The DAV:workspace-checkout-set property is the only required property + * which is additionally added to a workspace resource.
+ * This computed property identifies each checked-out resource whose + * DAV:workspace property identifies this workspace. + *

+ * Note that the DAV:workspace-checkout-set represents a + * {@link org.apache.jackrabbit.webdav.property.HrefProperty HrefProperty}. + */ + public static final DavPropertyName WORKSPACE_CHECKOUT_SET = DavPropertyName.create("workspace-checkout-set", DeltaVConstants.NAMESPACE); + + /** + * @deprecated Use {@link #CURRENT_ACTIVITY_SET} instead. + */ + public static final DavPropertyName CUURENT_ACTIVITY_SET = DavPropertyName.create("current-activity-set", DeltaVConstants.NAMESPACE); + + /** + * DAV:current-activity-set is a required property for a workspace resource, + * if the server supports the activity feature.
+ * It identifies the activities that currently are being performed in this + * workspace. When a member of this workspace is checked out, if no activity + * is specified in the checkout request, the DAV:current-activity-set will + * be used. This allows an activity-unaware client to update a workspace in + * which activity tracking is required. The DAV:current-activity-set MAY be + * restricted to identify at most one activity. + *

+ * The property is defined to have the following format: + *

+     * <!ELEMENT current-activity-set (href*)>
+     * 
+ * Note that the DAV:current-activity-set represents a + * {@link org.apache.jackrabbit.webdav.property.HrefProperty HrefProperty} + */ + public static final DavPropertyName CURRENT_ACTIVITY_SET = DavPropertyName.create("current-activity-set", DeltaVConstants.NAMESPACE); + + /** + * The Baseline feature (section 12) defines the following computed property + * for a workspace resource: DAV:baseline-controlled-collection-set lists + * all collections of this workspace, that are under baseline control. This + * list may include the workspace itself. + *

+ * The property is defined to have the following format: + *

+     * <!ELEMENT baseline-controlled-collection-set (href*)>
+     * 
+ * Note that the DAV:baseline-controlled-collection-set represents a + * {@link org.apache.jackrabbit.webdav.property.HrefProperty HrefProperty} + */ + public static final DavPropertyName BASELINE_CONTROLLED_COLLECTION_SET = DavPropertyName.create("baseline-controlled-collection-set", DeltaVConstants.NAMESPACE); +} \ No newline at end of file Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/WorkspaceResource.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-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/package-info.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/package-info.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/package-info.java (working copy) @@ -0,0 +1,18 @@ +/* + * 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. + */ +@org.osgi.annotation.versioning.Version("1.0.0") +package org.apache.jackrabbit.webdav.version; Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/package-info.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/report/AbstractReport.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/report/AbstractReport.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/report/AbstractReport.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.webdav.version.report; + +import org.apache.jackrabbit.webdav.WebdavRequest; +import org.apache.jackrabbit.webdav.WebdavRequestContext; +import org.apache.jackrabbit.webdav.server.WebdavRequestContextHolder; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Abstract Report. + */ +public abstract class AbstractReport implements Report { + + private static Logger log = LoggerFactory.getLogger(AbstractReport.class); + + /** + * Normalize the resource {@code href}. For example, remove contextPath prefix if found. + * @param href resource href + * @return normalized resource {@code href} + */ + protected String normalizeResourceHref(final String href) { + if (href == null) { + return href; + } + + final WebdavRequestContext requestContext = WebdavRequestContextHolder.getContext(); + final WebdavRequest request = (requestContext != null) ? requestContext.getRequest() : null; + + if (request == null) { + log.error("WebdavRequest is unavailable in the current execution context."); + return href; + } + + final String contextPath = request.getContextPath(); + + if (!contextPath.isEmpty() && href.startsWith(contextPath)) { + return href.substring(contextPath.length()); + } + + return href; + } + +} \ No newline at end of file Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/report/AbstractReport.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/report/CompareBaselineReport.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/report/CompareBaselineReport.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/report/CompareBaselineReport.java (working copy) @@ -0,0 +1,188 @@ +/* + * 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.webdav.version.report; + +import java.util.ArrayList; +import java.util.List; + +import org.apache.jackrabbit.webdav.DavConstants; +import org.apache.jackrabbit.webdav.DavException; +import org.apache.jackrabbit.webdav.DavResource; +import org.apache.jackrabbit.webdav.DavResourceIterator; +import org.apache.jackrabbit.webdav.DavResourceLocator; +import org.apache.jackrabbit.webdav.DavServletResponse; +import org.apache.jackrabbit.webdav.property.HrefProperty; +import org.apache.jackrabbit.webdav.version.BaselineResource; +import org.apache.jackrabbit.webdav.version.DeltaVConstants; +import org.apache.jackrabbit.webdav.version.VersionControlledResource; +import org.apache.jackrabbit.webdav.version.VersionResource; +import org.apache.jackrabbit.webdav.xml.DomUtil; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +/** + * CompareBaselineReport... + */ +public class CompareBaselineReport extends AbstractReport { + + private static Logger log = LoggerFactory.getLogger(CompareBaselineReport.class); + + private static final String XML_COMPARE_BASELINE = "compare-baseline"; + private static final String XML_COMPARE_BASELINE_REPORT = "compare-baseline-report"; + private static final String XML_ADDED_VERSION = "added-version"; + private static final String XML_DELETED_VERSION = "deleted-version"; + private static final String XML_CHANGED_VERSION = "changed-version"; + + public static final ReportType COMPARE_BASELINE = ReportType.register(XML_COMPARE_BASELINE, DeltaVConstants.NAMESPACE, CompareBaselineReport.class); + + private BaselineResource requestBaseline; + private BaselineResource compareBaseline; + + /** + * Returns {@link #COMPARE_BASELINE}. + * + * @see Report#getType() + */ + public ReportType getType() { + return COMPARE_BASELINE; + } + + /** + * Always returns false. + * + * @return false + * @see Report#isMultiStatusReport() + */ + public boolean isMultiStatusReport() { + return false; + } + + /** + * + * @param resource + * @param info + * @throws DavException + * @see Report#init(DavResource, ReportInfo) + */ + public void init(DavResource resource, ReportInfo info) throws DavException { + // validate info + if (!getType().isRequestedReportType(info)) { + throw new DavException(DavServletResponse.SC_BAD_REQUEST, "DAV:compare-baseline element expected."); + } + + // make sure the report is applied to a version history resource + if (resource != null && (resource instanceof BaselineResource)) { + this.requestBaseline = (BaselineResource) resource; + } else { + throw new DavException(DavServletResponse.SC_BAD_REQUEST, "DAV:compare-baseline report can only be created for a baseline resource."); + } + + // make sure the DAV:href element inside the request body points to + // an baseline resource (precondition for this report). + String compareHref = normalizeResourceHref(DomUtil.getText(info.getContentElement(DavConstants.XML_HREF, DavConstants.NAMESPACE))); + DavResourceLocator locator = resource.getLocator(); + DavResourceLocator compareLocator = locator.getFactory().createResourceLocator(locator.getPrefix(), compareHref); + + DavResource compRes = resource.getFactory().createResource(compareLocator, resource.getSession()); + if (compRes instanceof BaselineResource) { + compareBaseline = (BaselineResource) compRes; + } else { + throw new DavException(DavServletResponse.SC_BAD_REQUEST, "DAV:latest-activity-version report: The DAV:href in the request body MUST identify an activity."); + } + + // TODO: eventually add check for 'same-baseline-history' (RFC: "A server MAY require that the baselines being compared be from the same baseline history.") + } + + /** + * @see org.apache.jackrabbit.webdav.xml.XmlSerializable#toXml(Document) + */ + public Element toXml(Document document) { + Element el = DomUtil.createElement(document, XML_COMPARE_BASELINE_REPORT, DeltaVConstants.NAMESPACE); + try { + // TODO: check if correct + List requestVs = new ArrayList(); + getVersions(requestBaseline.getBaselineCollection(), requestVs); + + List compareVs = new ArrayList(); + getVersions(compareBaseline.getBaselineCollection(), compareVs); + + for (VersionResource requestV : requestVs) { + if (!compareVs.remove(requestV)) { + // check if another version of the same vh is present (change) + VersionResource changedV = findChangedVersion(requestV, compareVs); + if (changedV != null) { + // found a 'changed-version' entry + Element cv = DomUtil.addChildElement(el, XML_CHANGED_VERSION, DeltaVConstants.NAMESPACE); + cv.appendChild(DomUtil.hrefToXml(requestV.getHref(), document)); + cv.appendChild(DomUtil.hrefToXml(changedV.getHref(), document)); + } else { + // no corresponding version => 'deleted-version' + Element cv = DomUtil.addChildElement(el, XML_DELETED_VERSION, DeltaVConstants.NAMESPACE); + cv.appendChild(DomUtil.hrefToXml(requestV.getHref(), document)); + } + + } // else: both baseline contain a vc-resource with the same checked-in version + } + + // all remaining versions from the 'compare-baseline' can be considered + // to be added-versions. + for (VersionResource addedV : compareVs) { + Element cv = DomUtil.addChildElement(el, XML_ADDED_VERSION, DeltaVConstants.NAMESPACE); + cv.appendChild(DomUtil.hrefToXml(addedV.getHref(), document)); + } + } catch (DavException e) { + log.error("Internal error while building report", e); + } + return el; + } + + private void getVersions(DavResource collection, List vList) throws DavException { + DavResourceIterator it = collection.getMembers(); + while (it.hasNext()) { + DavResource member = it.nextResource(); + if (member instanceof VersionControlledResource) { + String href = new HrefProperty(member.getProperty(VersionControlledResource.CHECKED_IN)).getHrefs().get(0); + DavResourceLocator locator = member.getLocator(); + DavResourceLocator vLocator = locator.getFactory().createResourceLocator(locator.getPrefix(), href); + + DavResource v = member.getFactory().createResource(vLocator, member.getSession()); + if (v instanceof VersionResource) { + vList.add((VersionResource) v); + } else { + log.error("Internal error: DAV:checked-in property must point to a VersionResource."); + } + } + if (member.isCollection()) { + getVersions(member, vList); + } + } + } + + private VersionResource findChangedVersion(VersionResource requestV, List compareVs) throws DavException { + VersionResource[] vs = requestV.getVersionHistory().getVersions(); + for (VersionResource v : vs) { + if (compareVs.remove(v)) { + // another version of the same versionhistory is present among + // the compare-baseline versions. + return v; + } + } + return null; + } +} Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/report/CompareBaselineReport.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-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/report/ExpandPropertyReport.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/report/ExpandPropertyReport.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/report/ExpandPropertyReport.java (working copy) @@ -0,0 +1,266 @@ +/* + * 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.webdav.version.report; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import org.apache.jackrabbit.webdav.DavException; +import org.apache.jackrabbit.webdav.DavResource; +import org.apache.jackrabbit.webdav.DavResourceIterator; +import org.apache.jackrabbit.webdav.DavServletResponse; +import org.apache.jackrabbit.webdav.MultiStatus; +import org.apache.jackrabbit.webdav.MultiStatusResponse; +import org.apache.jackrabbit.webdav.property.AbstractDavProperty; +import org.apache.jackrabbit.webdav.property.DavProperty; +import org.apache.jackrabbit.webdav.property.DavPropertyName; +import org.apache.jackrabbit.webdav.property.HrefProperty; +import org.apache.jackrabbit.webdav.version.DeltaVConstants; +import org.apache.jackrabbit.webdav.version.DeltaVResource; +import org.apache.jackrabbit.webdav.xml.DomUtil; +import org.apache.jackrabbit.webdav.xml.ElementIterator; +import org.apache.jackrabbit.webdav.xml.Namespace; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +/** + * ExpandPropertyReport encapsulates the DAV:expand-property report, + * that provides a mechanism for retrieving in one request the properties from + * the resources identified by those DAV:href elements. It should be supported by + * all resources that support the REPORT method. + *

+ * RFC 3253 specifies the following required format for the request body: + *

+ * <!ELEMENT expand-property (property*)>
+ * <!ELEMENT property (property*)>
+ * <!ATTLIST property name NMTOKEN #REQUIRED>
+ * name value: a property element type
+ * <!ATTLIST property namespace NMTOKEN "DAV:">
+ * namespace value: an XML namespace
+ * 
+ * NOTE: any DAV:property elements defined in the request body, that does not + * represent {@link HrefProperty} is treated as in a common PROPFIND request. + * + * @see DeltaVConstants#XML_EXPAND_PROPERTY + * @see DeltaVConstants#XML_PROPERTY + */ +public class ExpandPropertyReport extends AbstractReport implements DeltaVConstants { + + private static Logger log = LoggerFactory.getLogger(ExpandPropertyReport.class); + + private DavResource resource; + private ReportInfo info; + private Iterator propertyElements; + + /** + * Returns {@link ReportType#EXPAND_PROPERTY}. + * + * @return + * @see Report#getType() + */ + public ReportType getType() { + return ReportType.EXPAND_PROPERTY; + } + + /** + * Always returns true. + * + * @return true + * @see org.apache.jackrabbit.webdav.version.report.Report#isMultiStatusReport() + */ + public boolean isMultiStatusReport() { + return true; + } + + /** + * @see Report#init(DavResource, ReportInfo) + */ + public void init(DavResource resource, ReportInfo info) throws DavException { + setResource(resource); + setInfo(info); + } + + /** + * Set the target resource. + * + * @param resource + * @throws DavException if the specified resource is null + */ + private void setResource(DavResource resource) throws DavException { + if (resource == null) { + throw new DavException(DavServletResponse.SC_BAD_REQUEST, "The resource specified must not be null."); + } + this.resource = resource; + } + + /** + * Set the ReportInfo. + * + * @param info + * @throws DavException if the given ReportInfo + * does not contain a DAV:expand-property element. + */ + private void setInfo(ReportInfo info) throws DavException { + if (info == null) { + throw new DavException(DavServletResponse.SC_BAD_REQUEST, "The report info specified must not be null."); + } + if (!getType().isRequestedReportType(info)) { + throw new DavException(DavServletResponse.SC_BAD_REQUEST, "DAV:expand-property element expected."); + } + this.info = info; + propertyElements = info.getContentElements(XML_PROPERTY, NAMESPACE).iterator(); + } + + /** + * Run the report + * + * @return Xml Document as defined by + * RFC 2518 + * @see org.apache.jackrabbit.webdav.xml.XmlSerializable#toXml(Document) + * @param document + */ + public Element toXml(Document document) { + return getMultiStatus().toXml(document); + } + + /** + * Retrieve the multistatus object that is returned in response to the + * expand-property report request. + * + * @return + * @throws NullPointerException if info and resource have not been set. + */ + private MultiStatus getMultiStatus() { + MultiStatus ms = new MultiStatus(); + addResponses(resource, info.getDepth(), ms); + return ms; + } + + /** + * Fills the specified MultiStatus object by generating a + * MultiStatusResponse for the given resource (and + * its member according to the depth value). + * + * @param res + * @param depth + * @param ms + * @see #getResponse(DavResource, Iterator) + */ + private void addResponses(DavResource res, int depth, MultiStatus ms) { + MultiStatusResponse response = getResponse(res, propertyElements); + ms.addResponse(response); + if (depth > 0 && res.isCollection()) { + DavResourceIterator it = res.getMembers(); + while (it.hasNext()) { + addResponses(it.nextResource(), depth-1, ms); + } + } + } + + /** + * Builds a MultiStatusResponse for the given resource respecting + * the properties specified. Any property that represents a {@link HrefProperty} + * is expanded: It's name equals the name of a valid {@link HrefProperty}. + * However the value of that given property (consisting of one or multiple DAV:href elements) + * is replaced by the Xml representation of a separate + * {@link MultiStatusResponse multistatus responses} for the + * resource referenced by the given DAV:href elements. The responses may + * themselves have properties, which are defined by the separate list. + * + * @param res + * @param propertyElements + * @return MultiStatusResponse for the given resource. + * @see ExpandProperty + */ + private MultiStatusResponse getResponse(DavResource res, Iterator propertyElements) { + MultiStatusResponse resp = new MultiStatusResponse(res.getHref(), null); + while (propertyElements.hasNext()) { + Element propertyElem = propertyElements.next(); + // retrieve the localName present in the "name" attribute + String nameAttr = propertyElem.getAttribute(ATTR_NAME); + if (nameAttr == null || "".equals(nameAttr)) { + // NOTE: this is not valid according to the DTD + continue; + } + // retrieve the namespace present in the "namespace" attribute + // NOTE: if this attribute is missing the DAV: namespace represents the default. + String namespaceAttr = propertyElem.getAttribute(ATTR_NAMESPACE); + Namespace namespace = (namespaceAttr != null) ? Namespace.getNamespace(namespaceAttr) : NAMESPACE; + + DavPropertyName propName = DavPropertyName.create(nameAttr, namespace); + DavProperty p = res.getProperty(propName); + if (p != null) { + if (p instanceof HrefProperty && res instanceof DeltaVResource) { + ElementIterator it = DomUtil.getChildren(propertyElem, XML_PROPERTY, NAMESPACE); + resp.add(new ExpandProperty((DeltaVResource)res, (HrefProperty)p, it)); + } else { + resp.add(p); + } + } else { + resp.add(propName, DavServletResponse.SC_NOT_FOUND); + } + } + return resp; + } + + //--------------------------------------------------------< inner class >--- + /** + * ExpandProperty extends DavProperty. It's name + * equals the name of a valid {@link HrefProperty}. However the value of + * that given property (consisting of one or multiple DAV:href elements) + * is replaced by the Xml representation of a separate + * {@link MultiStatusResponse multistatus responses} for the + * resource referenced to by the given DAV:href elements. The responses may + * themselves have properties, which are defined by the separate list. + */ + private class ExpandProperty extends AbstractDavProperty> { + + private List valueList = new ArrayList(); + + /** + * Create a new ExpandProperty. + * + * @param hrefProperty + * @param elementIter + */ + private ExpandProperty(DeltaVResource deltaVResource, HrefProperty hrefProperty, ElementIterator elementIter) { + super(hrefProperty.getName(), hrefProperty.isInvisibleInAllprop()); + try { + DavResource[] refResource = deltaVResource.getReferenceResources(hrefProperty.getName()); + for (DavResource res : refResource) { + MultiStatusResponse resp = getResponse(res, elementIter); + valueList.add(resp); + } + } catch (DavException e) { + // invalid references or unknown property + log.error(e.getMessage()); + } + } + + /** + * Returns a List of {@link MultiStatusResponse} objects. + * + * @return + */ + public List getValue() { + return valueList; + } + } +} Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/report/ExpandPropertyReport.java ___________________________________________________________________ Added: svn Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/report/LatestActivityVersionReport.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/report/LatestActivityVersionReport.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/report/LatestActivityVersionReport.java (working copy) @@ -0,0 +1,151 @@ +/* + * 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.webdav.version.report; + +import java.util.List; + +import org.apache.jackrabbit.webdav.DavConstants; +import org.apache.jackrabbit.webdav.DavException; +import org.apache.jackrabbit.webdav.DavResource; +import org.apache.jackrabbit.webdav.DavResourceLocator; +import org.apache.jackrabbit.webdav.DavServletResponse; +import org.apache.jackrabbit.webdav.property.HrefProperty; +import org.apache.jackrabbit.webdav.version.ActivityResource; +import org.apache.jackrabbit.webdav.version.DeltaVConstants; +import org.apache.jackrabbit.webdav.version.VersionHistoryResource; +import org.apache.jackrabbit.webdav.version.VersionResource; +import org.apache.jackrabbit.webdav.xml.DomUtil; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +/** + * LatestActivityVersionReport is applied to a version history to + * identify the latest version that is selected from that version history by a + * given activity. + */ +public class LatestActivityVersionReport extends AbstractReport { + + private static Logger log = LoggerFactory.getLogger(LatestActivityVersionReport.class); + + private static final String XML_LATEST_ACTIVITY_VERSION = "latest-activity-version"; + private static final String XML_LATEST_ACTIVITY_VERSION_REPORT = "latest-activity-version-report"; + + public static final ReportType LATEST_ACTIVITY_VERSION = ReportType.register(XML_LATEST_ACTIVITY_VERSION, DeltaVConstants.NAMESPACE, LatestActivityVersionReport.class); + + private VersionHistoryResource vhResource; + private DavResource activity; + + /** + * Returns {@link #LATEST_ACTIVITY_VERSION}. + * + * @see Report#getType() + */ + public ReportType getType() { + return LATEST_ACTIVITY_VERSION; + } + + /** + * Always returns false. + * + * @return false + * @see Report#isMultiStatusReport() + */ + public boolean isMultiStatusReport() { + return false; + } + + /** + * Check all the preconditions for this report. + * + * @throws DavException if a precondition is not met. + * @see Report#init(DavResource, ReportInfo) + */ + public void init(DavResource resource, ReportInfo info) throws DavException { + // validate info + if (!getType().isRequestedReportType(info)) { + throw new DavException(DavServletResponse.SC_BAD_REQUEST, "DAV:latest-activity-version element expected."); + } + + // make sure the report is applied to a vh-resource + if (resource != null && (resource instanceof VersionHistoryResource)) { + vhResource = (VersionHistoryResource) resource; + } else { + throw new DavException(DavServletResponse.SC_BAD_REQUEST, "DAV:latest-activity-version report can only be created for a version history resource."); + } + + // make sure the DAV:href element inside the request body points to + // an activity resource (precondition for this report). + String activityHref = normalizeResourceHref(DomUtil.getText(info.getContentElement(DavConstants.XML_HREF, DavConstants.NAMESPACE))); + DavResourceLocator vhLocator = resource.getLocator(); + DavResourceLocator activityLocator = vhLocator.getFactory().createResourceLocator(vhLocator.getPrefix(), activityHref); + + activity = resource.getFactory().createResource(activityLocator, resource.getSession()); + if (!(activity instanceof ActivityResource)) { + throw new DavException(DavServletResponse.SC_BAD_REQUEST, "DAV:latest-activity-version report: The DAV:href in the request body MUST identify an activity."); + } + } + + /** + * + * @see org.apache.jackrabbit.webdav.xml.XmlSerializable#toXml(Document) + */ + public Element toXml(Document document) { + String latestVersionHref = getLatestVersionHref(); + + Element el = DomUtil.createElement(document, XML_LATEST_ACTIVITY_VERSION_REPORT, DeltaVConstants.NAMESPACE); + el.appendChild(DomUtil.hrefToXml(latestVersionHref, document)); + return el; + } + + /** + * The latest-version-href MUST identify the version of the given + * version history that is a member of the DAV:activity-version-set of the + * given activity and has no descendant that is a member of the + * DAV:activity-version-set of that activity. + * + * @return href of the latest version or "" + */ + private String getLatestVersionHref() { + String latestVersionHref = ""; // not found (TODO: check if this valid according to the RFC) + try { + List versionHrefs = new HrefProperty(activity.getProperty(ActivityResource.ACTIVITY_VERSION_SET)).getHrefs(); + + for (VersionResource vr : vhResource.getVersions()) { + String href = vr.getHref(); + if (versionHrefs.contains(href)) { + if ("".equals(latestVersionHref)) { + // shortcut + latestVersionHref = href; + } else { + // if this vr is a descendant of the one already found, set latestVersion again + List predecessors = new HrefProperty(vr.getProperty(VersionResource.PREDECESSOR_SET)).getHrefs(); + if (predecessors.contains(latestVersionHref)) { + // version is a descendant of the vr identified by latestVersionHref + latestVersionHref = href; + } // else: version is predecessor -> nothing to do. + } + } + } + + } catch (DavException e) { + log.error("Unexpected error while retrieving href of latest version.", e); + } + return latestVersionHref; + } +} Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/report/LatestActivityVersionReport.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-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/report/LocateByHistoryReport.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/report/LocateByHistoryReport.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/report/LocateByHistoryReport.java (working copy) @@ -0,0 +1,175 @@ +/* + * 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.webdav.version.report; + +import java.util.HashSet; +import java.util.Set; + +import org.apache.jackrabbit.webdav.DavConstants; +import org.apache.jackrabbit.webdav.DavException; +import org.apache.jackrabbit.webdav.DavResource; +import org.apache.jackrabbit.webdav.DavResourceIterator; +import org.apache.jackrabbit.webdav.DavServletResponse; +import org.apache.jackrabbit.webdav.MultiStatus; +import org.apache.jackrabbit.webdav.property.DavPropertyNameSet; +import org.apache.jackrabbit.webdav.version.DeltaVConstants; +import org.apache.jackrabbit.webdav.version.VersionControlledResource; +import org.apache.jackrabbit.webdav.version.VersionHistoryResource; +import org.apache.jackrabbit.webdav.xml.DomUtil; +import org.apache.jackrabbit.webdav.xml.ElementIterator; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +/** + * LocateByHistoryReport encapsulates the DAV:locate-by-hisotry + * report, that may be used to locate a version-controlled resource for that + * version history. The DAV:locate-by-history report can be applied to a collection + * to locate the collection member that is a version-controlled resource for a + * specified version history resource. + * + *
+ * <!ELEMENT locate-by-history (version-history-set, prop)>
+ * <!ELEMENT version-history-set (href+)>
+ * 
+ */ +public class LocateByHistoryReport extends AbstractReport implements DeltaVConstants { + + private static Logger log = LoggerFactory.getLogger(LocateByHistoryReport.class); + + private ReportInfo info; + private Set vhHrefSet = new HashSet(); + private DavResource resource; + + /** + * Returns {@link ReportType#LOCATE_BY_HISTORY}. + * + * @see Report#getType() + */ + public ReportType getType() { + return ReportType.LOCATE_BY_HISTORY; + } + + /** + * @see Report#init(DavResource, ReportInfo) + */ + public void init(DavResource resource, ReportInfo info) throws DavException { + if (resource == null || !(resource instanceof VersionControlledResource)) { + throw new DavException(DavServletResponse.SC_BAD_REQUEST, "DAV:version-tree report can only be created for version-controlled resources and version resources."); + } + this.resource = resource; + setInfo(info); + } + + /** + * Set the ReportInfo + * + * @param info + * @throws DavException if the given ReportInfo + * does not contain a DAV:version-tree element. + */ + private void setInfo(ReportInfo info) throws DavException { + if (info == null || !getType().isRequestedReportType(info)) { + throw new DavException(DavServletResponse.SC_BAD_REQUEST, "DAV:locate-by-history element expected."); + } + Element versionHistorySet = info.getContentElement(XML_VERSION_HISTORY_SET, NAMESPACE); + if (versionHistorySet == null) { + throw new DavException(DavServletResponse.SC_BAD_REQUEST, "The DAV:locate-by-history element must contain a DAV:version-history-set child."); + } + ElementIterator it = DomUtil.getChildren(versionHistorySet, DavConstants.XML_HREF, DavConstants.NAMESPACE); + while (it.hasNext()) { + String href = DomUtil.getText(it.nextElement()); + if (href != null) { + vhHrefSet.add(href); + } + } + this.info = info; + } + + /** + * Always returns true. + * + * @return true + * @see org.apache.jackrabbit.webdav.version.report.Report#isMultiStatusReport() + */ + public boolean isMultiStatusReport() { + return true; + } + + /** + * Run the report. + * + * @return Xml Document representing the report in the required + * format. + * @see org.apache.jackrabbit.webdav.xml.XmlSerializable#toXml(Document) + * @param document + */ + public Element toXml(Document document) { + return getMultiStatus().toXml(document); + } + + /** + * Retrieve the MultiStatus that is returned in response to a locate-by-history + * report request. + * + * @return + * @throws NullPointerException if info or resource is null. + */ + private MultiStatus getMultiStatus() { + MultiStatus ms = new MultiStatus(); + buildResponse(resource, info.getPropertyNameSet(), info.getDepth(), ms); + return ms; + } + + /** + * Fill the MultiStatus with the MultiStatusResponses + * generated for the specified resource and its members according to the + * depth value. + * + * @param res + * @param propNameSet + * @param depth + * @param ms + */ + private void buildResponse(DavResource res, DavPropertyNameSet propNameSet, + int depth, MultiStatus ms) { + // loop over members first, since this report only list members + DavResourceIterator it = res.getMembers(); + while (!vhHrefSet.isEmpty() && it.hasNext()) { + DavResource childRes = it.nextResource(); + if (childRes instanceof VersionControlledResource) { + try { + VersionHistoryResource vhr = ((VersionControlledResource)childRes).getVersionHistory(); + if (vhHrefSet.remove(vhr.getHref())) { + if (propNameSet.isEmpty()) { + ms.addResourceStatus(childRes, DavServletResponse.SC_OK, 0); + } else { + ms.addResourceProperties(childRes, propNameSet, 0); + } + } + } catch (DavException e) { + log.info(e.getMessage()); + } + } + // traverse subtree + if (depth > 0) { + buildResponse(it.nextResource(), propNameSet, depth-1, ms); + } + } + } +} Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/report/LocateByHistoryReport.java ___________________________________________________________________ Added: svn Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/report/Report.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/report/Report.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/report/Report.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.webdav.version.report; + +import org.apache.jackrabbit.webdav.DavException; +import org.apache.jackrabbit.webdav.DavResource; +import org.apache.jackrabbit.webdav.version.DeltaVResource; +import org.apache.jackrabbit.webdav.xml.XmlSerializable; + +/** + * The Report interface defines METHODS needed in order to respond + * to a REPORT request. The REPORT method is a required feature to all + * DeltaV resources. + * + * @see DeltaVResource#getReport(ReportInfo) + */ +public interface Report extends XmlSerializable { + + /** + * Returns the registered type of this report. + * + * @return the type of this report. + */ + public ReportType getType(); + + /** + * Returns true if this Report will send a MultiStatus + * response.
+ * Please note that RFC 3253 that the the response must be a 207 Multi-Status, + * if a Depth request header is present. + * + * @return + */ + public boolean isMultiStatusReport(); + + /** + * Set the DeltaVResource for which this report was requested + * and the ReportInfo as specified by the REPORT request body, + * that defines the details for this report.
+ * Please note that this methods should perform basic validation checks + * in order to prevent exceptional situations during the xml serialization. + * + * @param resource + * @param info + * @throws DavException + */ + public void init(DavResource resource, ReportInfo info) throws DavException; +} \ No newline at end of file Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/report/Report.java ___________________________________________________________________ Added: svn Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/report/ReportInfo.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/report/ReportInfo.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/report/ReportInfo.java (working copy) @@ -0,0 +1,263 @@ +/* + * 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.webdav.version.report; + +import org.apache.jackrabbit.webdav.DavConstants; +import org.apache.jackrabbit.webdav.DavException; +import org.apache.jackrabbit.webdav.DavServletResponse; +import org.apache.jackrabbit.webdav.property.DavPropertyNameSet; +import org.apache.jackrabbit.webdav.xml.DomUtil; +import org.apache.jackrabbit.webdav.xml.ElementIterator; +import org.apache.jackrabbit.webdav.xml.Namespace; +import org.apache.jackrabbit.webdav.xml.XmlSerializable; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.Node; + +import java.util.ArrayList; +import java.util.List; + +/** + * The ReportInfo class encapsulates the body of a REPORT request. + * RFC 3253 the top Xml element + * being the name of the requested report. In addition a Depth header may + * be present (default value: {@link DavConstants#DEPTH_0}). + */ +public class ReportInfo implements XmlSerializable { + + private static Logger log = LoggerFactory.getLogger(ReportInfo.class); + + private final String typeLocalName; + private final Namespace typeNamespace; + private final int depth; + private final DavPropertyNameSet propertyNames; + private final List content = new ArrayList(); + + /** + * Create a new ReportInfo + * + * @param type + */ + public ReportInfo(ReportType type) { + this(type, DavConstants.DEPTH_0, null); + } + + /** + * Create a new ReportInfo + * + * @param type + * @param depth + */ + public ReportInfo(ReportType type, int depth) { + this(type, depth, null); + } + + /** + * Create a new ReportInfo + * + * @param type + * @param depth + * @param propertyNames + */ + public ReportInfo(ReportType type, int depth, DavPropertyNameSet propertyNames) { + this(type.getLocalName(), type.getNamespace(), depth, propertyNames); + } + + /** + * Create a new ReportInfo + * + * @param typeLocalName + * @param typeNamespace + */ + public ReportInfo(String typeLocalName, Namespace typeNamespace) { + this(typeLocalName, typeNamespace, DavConstants.DEPTH_0, null); + } + + /** + * Create a new ReportInfo + * + * @param typelocalName + * @param typeNamespace + * @param depth + * @param propertyNames + */ + public ReportInfo(String typelocalName, Namespace typeNamespace, int depth, DavPropertyNameSet propertyNames) { + this.typeLocalName = typelocalName; + this.typeNamespace = typeNamespace; + this.depth = depth; + if (propertyNames != null) { + this.propertyNames = new DavPropertyNameSet(propertyNames); + } else { + this.propertyNames = new DavPropertyNameSet(); + } + } + + /** + * Create a new ReportInfo object from the given Xml element. + * + * @param reportElement + * @param depth Depth value as retrieved from the {@link DavConstants#HEADER_DEPTH}. + * @throws DavException if the report element is null. + */ + public ReportInfo(Element reportElement, int depth) throws DavException { + if (reportElement == null) { + log.warn("Report request body must not be null."); + throw new DavException(DavServletResponse.SC_BAD_REQUEST); + } + + this.typeLocalName = reportElement.getLocalName(); + this.typeNamespace = DomUtil.getNamespace(reportElement); + this.depth = depth; + Element propElement = DomUtil.getChildElement(reportElement, DavConstants.XML_PROP, DavConstants.NAMESPACE); + if (propElement != null) { + propertyNames = new DavPropertyNameSet(propElement); + reportElement.removeChild(propElement); + } else { + propertyNames = new DavPropertyNameSet(); + } + + ElementIterator it = DomUtil.getChildren(reportElement); + while (it.hasNext()) { + Element el = it.nextElement(); + if (!DavConstants.XML_PROP.equals(el.getLocalName())) { + content.add(el); + } + } + } + + /** + * Returns the depth field. The request must be applied separately to the + * collection itself and to all members of the collection that satisfy the + * depth value. + * + * @return depth + */ + public int getDepth() { + return depth; + } + + /** + * Name of the report type that will be / has been requested. + * + * @return Name of the report type + */ + public String getReportName() { + return DomUtil.getExpandedName(typeLocalName, typeNamespace); + } + + /** + * Indicates whether this info contains an element with the given name/namespace. + * + * @param localName + * @param namespace + * @return true if an element with the given name/namespace is present in the + * body of the request info. + */ + public boolean containsContentElement(String localName, Namespace namespace) { + if (content.isEmpty()) { + return false; + } + for (Element elem : content) { + boolean sameNamespace = (namespace == null) ? elem.getNamespaceURI() == null : namespace.isSame(elem.getNamespaceURI()); + if (sameNamespace && elem.getLocalName().equals(localName)) { + return true; + } + } + return false; + } + + /** + * Retrieves the Xml element with the given name/namespace that is a child + * of this info. If no such child exists null is returned. If + * multiple elements with the same name exist, the first one is returned. + * + * @param localName + * @param namespace + * @return Xml element with the given name/namespace or null + */ + public Element getContentElement(String localName, Namespace namespace) { + List values = getContentElements(localName, namespace); + if (values.isEmpty()) { + return null; + } else { + return values.get(0); + } + } + + /** + * Returns a list containing all child Xml elements of this info that have + * the specified name/namespace. If this info contains no such element, + * an empty list is returned. + * + * @param localName + * @param namespace + * @return List contain all child elements with the given name/namespace + * or an empty list. + */ + public List getContentElements(String localName, Namespace namespace) { + List l = new ArrayList(); + for (Element elem : content) { + if (DomUtil.matches(elem, localName, namespace)) { + l.add(elem); + } + } + return l; + } + + /** + * Add the specified Xml element as child of this info. + * + * @param contentElement + */ + public void setContentElement(Element contentElement) { + content.add(contentElement); + } + + /** + * Returns a DavPropertyNameSet providing the property names present + * in an eventual {@link DavConstants#XML_PROP} child element. If no such + * child element is present an empty set is returned. + * + * @return {@link DavPropertyNameSet} providing the property names present + * in an eventual {@link DavConstants#XML_PROP DAV:prop} child element or an empty set. + */ + public DavPropertyNameSet getPropertyNameSet() { + return propertyNames; + } + + + /** + * @see org.apache.jackrabbit.webdav.xml.XmlSerializable#toXml(Document) + * @param document + */ + public Element toXml(Document document) { + Element reportElement = DomUtil.createElement(document, typeLocalName, typeNamespace); + if (!content.isEmpty()) { + for (Element contentEntry : content) { + Node n = document.importNode(contentEntry, true); + reportElement.appendChild(n); + } + } + if (!propertyNames.isEmpty()) { + reportElement.appendChild(propertyNames.toXml(document)); + } + return reportElement; + } + +} Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/report/ReportInfo.java ___________________________________________________________________ Added: svn Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/report/ReportType.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/report/ReportType.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/report/ReportType.java (working copy) @@ -0,0 +1,190 @@ +/* + * 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.webdav.version.report; + +import org.apache.jackrabbit.webdav.DavException; +import org.apache.jackrabbit.webdav.DavServletResponse; +import org.apache.jackrabbit.webdav.version.DeltaVConstants; +import org.apache.jackrabbit.webdav.version.DeltaVResource; +import org.apache.jackrabbit.webdav.xml.DomUtil; +import org.apache.jackrabbit.webdav.xml.Namespace; +import org.apache.jackrabbit.webdav.xml.XmlSerializable; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +import java.util.HashMap; + +/** + * ReportType... + */ +public class ReportType implements DeltaVConstants, XmlSerializable { + + private static Logger log = LoggerFactory.getLogger(ReportType.class); + + private static final HashMap types = new HashMap(); + + public static final ReportType VERSION_TREE = register(XML_VERSION_TREE, NAMESPACE, VersionTreeReport.class); + public static final ReportType EXPAND_PROPERTY = register(XML_EXPAND_PROPERTY, NAMESPACE, ExpandPropertyReport.class); + public static final ReportType LOCATE_BY_HISTORY = register(XML_LOCATE_BY_HISTORY, NAMESPACE, LocateByHistoryReport.class); + + private final String key; + private final String localName; + private final Namespace namespace; + private final Class reportClass; + + /** + * Private constructor + * + * @see ReportType#register(String, org.apache.jackrabbit.webdav.xml.Namespace, Class) + */ + private ReportType(String localName, Namespace namespace, String key, Class reportClass) { + this.localName = localName; + this.namespace = namespace; + this.key = key; + this.reportClass = reportClass; + } + + /** + * Creates a new {@link Report} with this type. + * + * @return + * @throws DavException + */ + public Report createReport(DeltaVResource resource, ReportInfo info) throws DavException { + try { + Report report = reportClass.newInstance(); + report.init(resource, info); + return report; + } catch (IllegalAccessException e) { + // should never occur + throw new DavException(DavServletResponse.SC_INTERNAL_SERVER_ERROR, "Failed to create new report (" + reportClass.getName() + ") from class: " + e.getMessage()); + } catch (InstantiationException e) { + // should never occur + throw new DavException(DavServletResponse.SC_INTERNAL_SERVER_ERROR, "Failed to create new report (" + reportClass.getName() + ") from class: " + e.getMessage()); + } + } + + /** + * Returns an Xml element representing this report type. It may be used to + * build the body for a REPORT request. + * + * @param document + * @return Xml representation + * @see XmlSerializable#toXml(org.w3c.dom.Document) + */ + public Element toXml(Document document) { + return DomUtil.createElement(document, localName, namespace); + } + + /** + * Returns true if this ReportType is requested by the given + * ReportInfo + * + * @param reqInfo + * @return + */ + public boolean isRequestedReportType(ReportInfo reqInfo) { + if (reqInfo != null) { + return getReportName().equals(reqInfo.getReportName()); + } + return false; + } + + /** + * Return the qualified name of this ReportType. + * + * @return qualified name + */ + public String getReportName() { + return key; + } + + /** + * + * @return + */ + public String getLocalName() { + return localName; + } + + /** + * + * @return + */ + public Namespace getNamespace() { + return namespace; + } + + /** + * Register the report type with the given name, namespace and class, that can + * run that report. + * + * @param localName + * @param namespace + * @param reportClass + * @return + * @throws IllegalArgumentException if either parameter is null or + * if the given class does not implement the {@link Report} interface or if + * it does not provide an empty constructor. + */ + public static ReportType register(String localName, Namespace namespace, Class reportClass) { + if (localName == null || namespace == null || reportClass == null) { + throw new IllegalArgumentException("A ReportType cannot be registered with a null name, namespace or report class"); + } + String key = DomUtil.getExpandedName(localName, namespace); + if (types.containsKey(key)) { + return types.get(key); + } else { + try { + Object report = reportClass.newInstance(); + if (!(report instanceof Report)) { + throw new IllegalArgumentException("Unable to register Report class: " + reportClass + " does not implement the Report interface."); + } + } catch (IllegalAccessException e) { + throw new IllegalArgumentException("Error while validating Report class: " + e.getMessage()); + } catch (InstantiationException e) { + throw new IllegalArgumentException("Error while validating Report class.: " + e.getMessage()); + } + + ReportType type = new ReportType(localName, namespace, key, reportClass); + types.put(key, type); + return type; + } + } + + /** + * Return the ReportType requested by the given report info object. + * + * @param reportInfo + * @return the requested ReportType + * @throws IllegalArgumentException if the reportInfo is null or + * if the requested report type has not been registered yet. + */ + public static ReportType getType(ReportInfo reportInfo) { + if (reportInfo == null) { + throw new IllegalArgumentException("ReportInfo must not be null."); + } + String key = reportInfo.getReportName(); + if (types.containsKey(key)) { + return types.get(key); + } else { + throw new IllegalArgumentException("The request report '"+key+"' has not been registered yet."); + } + } +} Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/report/ReportType.java ___________________________________________________________________ Added: svn Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/report/SupportedReportSetProperty.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/report/SupportedReportSetProperty.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/report/SupportedReportSetProperty.java (working copy) @@ -0,0 +1,119 @@ +/* + * 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.webdav.version.report; + +import org.apache.jackrabbit.webdav.property.AbstractDavProperty; +import org.apache.jackrabbit.webdav.version.DeltaVConstants; +import org.apache.jackrabbit.webdav.xml.DomUtil; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +import java.util.HashSet; +import java.util.Set; + +/** + * SupportedReportSetProperty represents the DAV:supported-report-set + * property defined by RFC 3253. It identifies the reports that are supported by + * the given resource. + *
+ * <!ELEMENT supported-report-set (supported-report*)>
+ * <!ELEMENT supported-report report>
+ * <!ELEMENT report ANY>
+ * ANY value: a report element type
+ * 
+ */ +public class SupportedReportSetProperty extends AbstractDavProperty> { + + private static Logger log = LoggerFactory.getLogger(SupportedReportSetProperty.class); + + private final Set reportTypes = new HashSet(); + + /** + * Create a new empty SupportedReportSetProperty. + */ + public SupportedReportSetProperty() { + super(DeltaVConstants.SUPPORTED_REPORT_SET, true); + } + + /** + * Create a new SupportedReportSetProperty property. + * + * @param reportTypes that are supported by the resource having this property. + */ + public SupportedReportSetProperty(ReportType[] reportTypes) { + super(DeltaVConstants.SUPPORTED_REPORT_SET, true); + for (ReportType reportType : reportTypes) { + addReportType(reportType); + } + } + + /** + * Add an additional report type to this property's value. + * + * @param reportType + */ + public void addReportType(ReportType reportType) { + reportTypes.add(reportType); + } + + /** + * Returns true if the report type indicated in the specified RequestInfo + * object is included in the supported reports. + * + * @param reqInfo + * @return true if the requested report is supported. + */ + public boolean isSupportedReport(ReportInfo reqInfo) { + for (ReportType reportType : reportTypes) { + if (reportType.isRequestedReportType(reqInfo)) { + return true; + } + } + return false; + } + + /** + * Returns a set of report types. + * + * @return set of {@link ReportType}. + * @see org.apache.jackrabbit.webdav.property.DavProperty#getValue() + */ + public Set getValue() { + return reportTypes; + } + + /** + * Returns the Xml representation of this property. + * + * @return Xml representation listing all supported reports + * @see org.apache.jackrabbit.webdav.xml.XmlSerializable#toXml(Document) + * @param document + */ + @Override + public Element toXml(Document document) { + Element elem = getName().toXml(document); + for (ReportType rt : reportTypes) { + Element sr = DomUtil.addChildElement(elem, DeltaVConstants.XML_SUPPORTED_REPORT, DeltaVConstants.NAMESPACE); + Element r = DomUtil.addChildElement(sr, DeltaVConstants.XML_REPORT, DeltaVConstants.NAMESPACE); + r.appendChild(rt.toXml(document)); + } + return elem; + } + +} Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/report/SupportedReportSetProperty.java ___________________________________________________________________ Added: svn Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/report/VersionTreeReport.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/report/VersionTreeReport.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/report/VersionTreeReport.java (working copy) @@ -0,0 +1,187 @@ +/* + * 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.webdav.version.report; + +import org.apache.jackrabbit.webdav.DavException; +import org.apache.jackrabbit.webdav.DavResource; +import org.apache.jackrabbit.webdav.DavResourceIterator; +import org.apache.jackrabbit.webdav.DavServletResponse; +import org.apache.jackrabbit.webdav.MultiStatus; +import org.apache.jackrabbit.webdav.property.DavPropertyNameSet; +import org.apache.jackrabbit.webdav.version.DeltaVConstants; +import org.apache.jackrabbit.webdav.version.VersionControlledResource; +import org.apache.jackrabbit.webdav.version.VersionResource; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +/** + * VersionTreeReport encapsulates the DAV:version-tree report. + * It describes the requested properties of all the versions in the version + * history of a version. The DAV:version-tree report must be supported by all + * version resources and all version-controlled resources. + */ +public class VersionTreeReport extends AbstractReport implements DeltaVConstants { + + private static Logger log = LoggerFactory.getLogger(VersionTreeReport.class); + + private ReportInfo info; + private DavResource resource; + + /** + * Returns {@link ReportType#VERSION_TREE} + * + * @return {@link ReportType#VERSION_TREE} + * @see Report#getType() + */ + public ReportType getType() { + return ReportType.VERSION_TREE; + } + + /** + * Always returns true. + * + * @return true + * @see org.apache.jackrabbit.webdav.version.report.Report#isMultiStatusReport() + */ + public boolean isMultiStatusReport() { + return true; + } + + /** + * Validates the specified resource and info objects. + * + * @param resource + * @param info + * @throws org.apache.jackrabbit.webdav.DavException + * @see Report#init(DavResource, ReportInfo) + */ + public void init(DavResource resource, ReportInfo info) throws DavException { + setResource(resource); + setInfo(info); + } + + /** + * Set the DeltaVResource used to register this report. + * + * @param resource + * @throws DavException if the given resource is neither + * {@link VersionControlledResource} nor {@link VersionResource}. + */ + private void setResource(DavResource resource) throws DavException { + if (resource != null && (resource instanceof VersionControlledResource || resource instanceof VersionResource)) { + this.resource = resource; + } else { + throw new DavException(DavServletResponse.SC_BAD_REQUEST, "DAV:version-tree report can only be created for version-controlled resources and version resources."); + } + } + + /** + * Set the ReportInfo as specified by the REPORT request body, + * that defines the details for this report. + * + * @param info + * @throws DavException if the given ReportInfo + * does not contain a DAV:version-tree element. + */ + private void setInfo(ReportInfo info) throws DavException { + if (!getType().isRequestedReportType(info)) { + throw new DavException(DavServletResponse.SC_BAD_REQUEST, "DAV:version-tree element expected."); + } + this.info = info; + } + + /** + * Runs the DAV:version-tree report. + * + * @return Xml Document representing the report in the required + * format. + * @see org.apache.jackrabbit.webdav.xml.XmlSerializable#toXml(Document) + * @param document + */ + public Element toXml(Document document) { + return getMultiStatus().toXml(document); + } + + /** + * Retrieve the MultiStatus that is returned in response to a locate-by-history + * report request. + * + * @return + * @throws NullPointerException if info or resource is null. + */ + private MultiStatus getMultiStatus() { + if (info == null || resource == null) { + throw new NullPointerException("Error while running DAV:version-tree report"); + } + + MultiStatus ms = new MultiStatus(); + buildResponse(resource, info.getPropertyNameSet(), info.getDepth(), ms); + return ms; + } + + /** + * + * @param res + * @param propNameSet + * @param depth + * @param ms + */ + private void buildResponse(DavResource res, DavPropertyNameSet propNameSet, + int depth, MultiStatus ms) { + try { + for (VersionResource version : getVersions(res)) { + if (propNameSet.isEmpty()) { + ms.addResourceStatus(version, DavServletResponse.SC_OK, 0); + } else { + ms.addResourceProperties(version, propNameSet, 0); + } + } + } catch (DavException e) { + log.error(e.toString()); + } + if (depth > 0 && res.isCollection()) { + DavResourceIterator it = res.getMembers(); + while (it.hasNext()) { + buildResponse(it.nextResource(), propNameSet, depth-1, ms); + } + } + } + + /** + * Retrieve all versions from the version history associated with the given + * resource. If the versions cannot be retrieved from the given resource + * an exception is thrown. + * + * @param res + * @return array of {@link VersionResource}s or an empty array if the versions + * could not be retrieved. + * @throws DavException if the version history could not be retrieved from + * the given resource or if an error occurs while accessing the versions + * from the version history resource. + */ + private static VersionResource[] getVersions(DavResource res) throws DavException { + VersionResource[] versions = new VersionResource[0]; + if (res instanceof VersionControlledResource) { + versions = ((VersionControlledResource)res).getVersionHistory().getVersions(); + } else if (res instanceof VersionResource) { + versions = ((VersionResource)res).getVersionHistory().getVersions(); + } + return versions; + } +} Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/report/VersionTreeReport.java ___________________________________________________________________ Added: svn Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/report/package-info.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/report/package-info.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/report/package-info.java (working copy) @@ -0,0 +1,18 @@ +/* + * 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. + */ +@org.osgi.annotation.versioning.Version("1.1.0") +package org.apache.jackrabbit.webdav.version.report; Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/report/package-info.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/xml/DavDocumentBuilderFactory.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/xml/DavDocumentBuilderFactory.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/xml/DavDocumentBuilderFactory.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.webdav.xml; + +import java.io.IOException; + +import javax.xml.XMLConstants; +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.xml.sax.EntityResolver; +import org.xml.sax.InputSource; +import org.xml.sax.helpers.DefaultHandler; + +/** + * Custom {@link DocumentBuilderFactory} extended for use in WebDAV. + */ +public class DavDocumentBuilderFactory { + + private static final Logger LOG = LoggerFactory.getLogger(DavDocumentBuilderFactory.class); + + private final DocumentBuilderFactory DEFAULT_FACTORY = createFactory(); + + private DocumentBuilderFactory BUILDER_FACTORY = DEFAULT_FACTORY; + + private DocumentBuilderFactory createFactory() { + DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); + factory.setNamespaceAware(true); + factory.setIgnoringComments(true); + factory.setIgnoringElementContentWhitespace(true); + factory.setCoalescing(true); + try { + factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true); + } catch (ParserConfigurationException e) { + LOG.warn("Secure XML processing is not supported", e); + } catch (AbstractMethodError e) { + LOG.warn("Secure XML processing is not supported", e); + } + return factory; + } + + public void setFactory(DocumentBuilderFactory documentBuilderFactory) { + LOG.debug("DocumentBuilderFactory changed to: " + documentBuilderFactory); + BUILDER_FACTORY = documentBuilderFactory != null ? documentBuilderFactory : DEFAULT_FACTORY; + } + + /** + * An entity resolver that does not allow external entity resolution. See + * RFC 4918, Section 20.6 + */ + private static final EntityResolver DEFAULT_ENTITY_RESOLVER = new EntityResolver() { + @Override + public InputSource resolveEntity(String publicId, String systemId) throws IOException { + LOG.debug("Resolution of external entities in XML payload not supported - publicId: " + publicId + ", systemId: " + + systemId); + throw new IOException("This parser does not support resolution of external entities (publicId: " + publicId + + ", systemId: " + systemId + ")"); + } + }; + + public DocumentBuilder newDocumentBuilder() throws ParserConfigurationException { + DocumentBuilder db = BUILDER_FACTORY.newDocumentBuilder(); + if (BUILDER_FACTORY == DEFAULT_FACTORY) { + // if this is the default factory: set the default entity resolver as well + db.setEntityResolver(DEFAULT_ENTITY_RESOLVER); + } + db.setErrorHandler(new DefaultHandler()); + return db; + } +} Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/xml/DavDocumentBuilderFactory.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/xml/DomUtil.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/xml/DomUtil.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/xml/DomUtil.java (working copy) @@ -0,0 +1,839 @@ +/* + * 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.webdav.xml; + +import org.apache.jackrabbit.webdav.DavConstants; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.w3c.dom.Attr; +import org.w3c.dom.CharacterData; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; +import org.w3c.dom.Text; +import org.w3c.dom.NamedNodeMap; +import org.xml.sax.SAXException; + +import javax.xml.namespace.QName; +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.transform.Transformer; +import javax.xml.transform.TransformerException; +import javax.xml.transform.TransformerFactory; +import javax.xml.transform.dom.DOMSource; +import javax.xml.transform.stream.StreamResult; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.Writer; +import java.util.ArrayList; +import java.util.List; + +/** + * DomUtil provides some common utility methods related to w3c-DOM. + */ +public class DomUtil { + + private static Logger log = LoggerFactory.getLogger(DomUtil.class); + + /** + * Constant for DavDocumentBuilderFactory which is used + * to create and parse DOM documents. + */ + private static final DavDocumentBuilderFactory BUILDER_FACTORY = new DavDocumentBuilderFactory(); + + /** + * Support the replacement of {@link #BUILDER_FACTORY}. This is useful + * for injecting a customized BuilderFactory, for example with one that + * uses a local catalog resolver. This is one technique for addressing + * this issue: + * http://www.w3.org/blog/systeam/2008/02/08/w3c_s_excessive_dtd_traffic + * + * @param documentBuilderFactory + */ + public static void setBuilderFactory( + DocumentBuilderFactory documentBuilderFactory) { + BUILDER_FACTORY.setFactory(documentBuilderFactory); + } + + /** + * Transformer factory + */ + private static TransformerFactory TRANSFORMER_FACTORY = TransformerFactory.newInstance(); + + /** + * Creates and returns a new empty DOM document. + * + * @return new DOM document + * @throws ParserConfigurationException if the document can not be created + */ + public static Document createDocument() + throws ParserConfigurationException { + return BUILDER_FACTORY.newDocumentBuilder().newDocument(); + } + + /** + * Parses the given input stream and returns the resulting DOM document. + * + * @param stream XML input stream + * @return parsed DOM document + * @throws ParserConfigurationException if the document can not be created + * @throws SAXException if the document can not be parsed + * @throws IOException if the input stream can not be read + */ + public static Document parseDocument(InputStream stream) + throws ParserConfigurationException, SAXException, IOException { + DocumentBuilder docBuilder = BUILDER_FACTORY.newDocumentBuilder(); + return docBuilder.parse(stream); + } + + /** + * Returns the value of the named attribute of the current element. + * + * @param parent + * @param localName attribute local name or 'nodeName' if no namespace is + * specified. + * @param namespace or null + * @return attribute value, or null if not found + */ + public static String getAttribute(Element parent, String localName, Namespace namespace) { + if (parent == null) { + return null; + } + Attr attribute; + if (namespace == null) { + attribute = parent.getAttributeNode(localName); + } else { + attribute = parent.getAttributeNodeNS(namespace.getURI(), localName); + } + if (attribute != null) { + return attribute.getValue(); + } else { + return null; + } + } + + /** + * Returns the namespace attributes of the given element. + * + * @param element + * @return the namespace attributes. + */ + public static Attr[] getNamespaceAttributes(Element element) { + NamedNodeMap attributes = element.getAttributes(); + List nsAttr = new ArrayList(); + for (int i = 0; i < attributes.getLength(); i++) { + Attr attr = (Attr) attributes.item(i); + if (Namespace.XMLNS_NAMESPACE.getURI().equals(attr.getNamespaceURI())) { + nsAttr.add(attr); + } + } + return nsAttr.toArray(new Attr[nsAttr.size()]); + } + + /** + * Concatenates the values of all child nodes of type 'Text' or 'CDATA'/ + * + * @param element + * @return String representing the value of all Text and CDATA child nodes or + * null if the length of the resulting String is 0. + * @see #isText(Node) + */ + public static String getText(Element element) { + StringBuffer content = new StringBuffer(); + if (element != null) { + NodeList nodes = element.getChildNodes(); + for (int i = 0; i < nodes.getLength(); i++) { + Node child = nodes.item(i); + if (isText(child)) { + // cast to super class that contains Text and CData + content.append(((CharacterData) child).getData()); + } + } + } + return (content.length()==0) ? null : content.toString(); + } + + /** + * Same as {@link #getText(Element)} except that 'defaultValue' is returned + * instead of null, if the element does not contain any text. + * + * @param element + * @param defaultValue + * @return the text contained in the specified element or + * defaultValue if the element does not contain any text. + */ + public static String getText(Element element, String defaultValue) { + String txt = getText(element); + return (txt == null) ? defaultValue : txt; + } + + /** + * Removes leading and trailing whitespace after calling {@link #getText(Element)}. + * + * @param element + * @return Trimmed text or null + */ + public static String getTextTrim(Element element) { + String txt = getText(element); + return (txt == null) ? txt : txt.trim(); + } + + /** + * Calls {@link #getText(Element)} on the first child element that matches + * the given local name and namespace. + * + * @param parent + * @param childLocalName + * @param childNamespace + * @return text contained in the first child that matches the given local name + * and namespace or null. + * @see #getText(Element) + */ + public static String getChildText(Element parent, String childLocalName, Namespace childNamespace) { + Element child = getChildElement(parent, childLocalName, childNamespace); + return (child == null) ? null : getText(child); + } + + /** + * Calls {@link #getTextTrim(Element)} on the first child element that matches + * the given local name and namespace. + * + * @param parent + * @param childLocalName + * @param childNamespace + * @return text contained in the first child that matches the given local name + * and namespace or null. Note, that leading and trailing whitespace + * is removed from the text. + * @see #getTextTrim(Element) + */ + public static String getChildTextTrim(Element parent, String childLocalName, Namespace childNamespace) { + Element child = getChildElement(parent, childLocalName, childNamespace); + return (child == null) ? null : getTextTrim(child); + } + + /** + * Calls {@link #getTextTrim(Element)} on the first child element that matches + * the given name. + * + * @param parent + * @param childName + * @return text contained in the first child that matches the given name + * or null. Note, that leading and trailing whitespace + * is removed from the text. + * @see #getTextTrim(Element) + */ + public static String getChildTextTrim(Element parent, QName childName) { + Element child = getChildElement(parent, childName); + return (child == null) ? null : getTextTrim(child); + } + + /** + * Returns true if the given parent node has a child element that matches + * the specified local name and namespace. + * + * @param parent + * @param childLocalName + * @param childNamespace + * @return returns true if a child element exists that matches the specified + * local name and namespace. + */ + public static boolean hasChildElement(Node parent, String childLocalName, Namespace childNamespace) { + return getChildElement(parent, childLocalName, childNamespace) != null; + } + + /** + * Returns the first child element that matches the given local name and + * namespace. If no child element is present or no child element matches, + * null is returned. + * + * @param parent + * @param childLocalName + * @param childNamespace + * @return first child element matching the specified names or null. + */ + public static Element getChildElement(Node parent, String childLocalName, Namespace childNamespace) { + if (parent != null) { + NodeList children = parent.getChildNodes(); + for (int i = 0; i < children.getLength(); i++) { + Node child = children.item(i); + if (isElement(child) && matches(child, childLocalName, childNamespace)) { + return (Element)child; + } + } + } + return null; + } + + /** + * Returns the first child element that matches the given {@link QName}. + * If no child element is present or no child element matches, + * null is returned. + * + * @param parent + * @param childName + * @return first child element matching the specified name or null. + */ + public static Element getChildElement(Node parent, QName childName) { + if (parent != null) { + NodeList children = parent.getChildNodes(); + for (int i = 0; i < children.getLength(); i++) { + Node child = children.item(i); + if (isElement(child) && matches(child, childName)) { + return (Element)child; + } + } + } + return null; + } + + /** + * Returns a ElementIterator containing all child elements of + * the given parent node that match the given local name and namespace. + * If the namespace is null only the localName is compared. + * + * @param parent the node the children elements should be retrieved from + * @param childLocalName + * @param childNamespace + * @return an ElementIterator giving access to all child elements + * that match the specified localName and namespace. + */ + public static ElementIterator getChildren(Element parent, String childLocalName, Namespace childNamespace) { + return new ElementIterator(parent, childLocalName, childNamespace); + } + + /** + * Returns a ElementIterator containing all child elements of + * the given parent node that match the given {@link QName}. + * + * @param parent + * the node the children elements should be retrieved from + * @param childName + * @return an ElementIterator giving access to all child + * elements that match the specified name. + */ + public static ElementIterator getChildren(Element parent, QName childName) { + return new ElementIterator(parent, childName); + } + + /** + * Return an ElementIterator over all child elements. + * + * @param parent + * @return + * @see #getChildren(Element, String, Namespace) for a method that only + * retrieves child elements that match a specific local name and namespace. + */ + public static ElementIterator getChildren(Element parent) { + return new ElementIterator(parent); + } + + /** + * Return the first child element + * + * @return the first child element or null if the given node has no + * child elements. + */ + public static Element getFirstChildElement(Node parent) { + if (parent != null) { + NodeList children = parent.getChildNodes(); + for (int i = 0; i < children.getLength(); i++) { + Node child = children.item(i); + if (isElement(child)) { + return (Element)child; + } + } + } + return null; + } + + /** + * Return true if the given parent contains any child that is + * either an Element, Text or CDATA. + * + * @param parent + * @return true if the given parent contains any child that is + * either an Element, Text or CDATA. + */ + public static boolean hasContent(Node parent) { + if (parent != null) { + NodeList children = parent.getChildNodes(); + for (int i = 0; i < children.getLength(); i++) { + Node child = children.item(i); + if (isAcceptedNode(child)) { + return true; + } + } + } + return false; + } + + /** + * Return a list of all child nodes that are either Element, Text or CDATA. + * + * @param parent + * @return a list of all child nodes that are either Element, Text or CDATA. + */ + public static List getContent(Node parent) { + List content = new ArrayList(); + if (parent != null) { + NodeList children = parent.getChildNodes(); + for (int i = 0; i < children.getLength(); i++) { + Node child = children.item(i); + if (isAcceptedNode(child)) { + content.add(child); + } + } + } + return content; + } + + /** + * Build a Namespace from the prefix and uri retrieved from the given element. + * + * @return the Namespace of the given element. + */ + public static Namespace getNamespace(Element element) { + String uri = element.getNamespaceURI(); + String prefix = element.getPrefix(); + if (uri == null) { + return Namespace.EMPTY_NAMESPACE; + } else { + return Namespace.getNamespace(prefix, uri); + } + } + + /** + * Returns true if the specified node matches the required names. Note, that + * that tests return true if the required name is null. + * + * @param node + * @param requiredLocalName + * @param requiredNamespace + * @return true if local name and namespace match the corresponding properties + * of the given DOM node. + */ + public static boolean matches(Node node, String requiredLocalName, Namespace requiredNamespace) { + if (node == null) { + return false; + } + boolean matchingNamespace = matchingNamespace(node, requiredNamespace); + return matchingNamespace && matchingLocalName(node, requiredLocalName); + } + + /** + * Returns true if the specified node matches the required {@link QName}. + * + * @param node + * @param requiredName + * @return true if local name and namespace match the corresponding properties + * of the given DOM node. + */ + public static boolean matches(Node node, QName requiredName) { + if (node == null) { + return false; + } else { + String nodens = node.getNamespaceURI() != null ? node.getNamespaceURI() : ""; + return nodens.equals(requiredName.getNamespaceURI()) + && node.getLocalName().equals(requiredName.getLocalPart()); + } + } + + /** + * @param node + * @param requiredNamespace + * @return true if the required namespace is null or matches + * the namespace of the specified node. + */ + private static boolean matchingNamespace(Node node, Namespace requiredNamespace) { + if (requiredNamespace == null) { + return true; + } else { + return requiredNamespace.isSame(node.getNamespaceURI()); + } + } + + /** + * @param node + * @param requiredLocalName + * @return true if the required local name is null or if the + * nodes local name matches. + */ + private static boolean matchingLocalName(Node node, String requiredLocalName) { + if (requiredLocalName == null) { + return true; + } else { + String localName = node.getLocalName(); + return requiredLocalName.equals(localName); + } + } + + /** + * @param node + * @return true if the specified node is either an element or Text or CDATA + */ + private static boolean isAcceptedNode(Node node) { + return isElement(node) || isText(node); + } + + /** + * @param node + * @return true if the given node is of type element. + */ + static boolean isElement(Node node) { + return node.getNodeType() == Node.ELEMENT_NODE; + } + + /** + * @param node + * @return true if the given node is of type text or CDATA. + */ + static boolean isText(Node node) { + int ntype = node.getNodeType(); + return ntype == Node.TEXT_NODE || ntype == Node.CDATA_SECTION_NODE; + } + + //----------------------------------------------------< factory methods >--- + /** + * Create a new DOM element with the specified local name and namespace. + * + * @param factory + * @param localName + * @param namespace + * @return a new DOM element + * @see Document#createElement(String) + * @see Document#createElementNS(String, String) + */ + public static Element createElement(Document factory, String localName, Namespace namespace) { + if (namespace != null) { + return factory.createElementNS(namespace.getURI(), getPrefixedName(localName, namespace)); + } else { + return factory.createElement(localName); + } + } + + /** + * Create a new DOM element with the specified local name and namespace. + * + * @param factory + * @param elementName + * @return a new DOM element + * @see Document#createElement(String) + * @see Document#createElementNS(String, String) + */ + public static Element createElement(Document factory, QName elementName) { + return factory.createElementNS(elementName.getNamespaceURI(), getPrefixedName(elementName)); + } + + /** + * Create a new DOM element with the specified local name and namespace and + * add the specified text as Text node to it. + * + * @param factory + * @param localName + * @param namespace + * @param text + * @return a new DOM element + * @see Document#createElement(String) + * @see Document#createElementNS(String, String) + * @see Document#createTextNode(String) + * @see Node#appendChild(org.w3c.dom.Node) + */ + public static Element createElement(Document factory, String localName, Namespace namespace, String text) { + Element elem = createElement(factory, localName, namespace); + setText(elem, text); + return elem; + } + + /** + * Add a new child element with the given local name and namespace to the + * specified parent. + * + * @param parent + * @param localName + * @param namespace + * @return the new element that was attached to the given parent. + */ + public static Element addChildElement(Element parent, String localName, Namespace namespace) { + Element elem = createElement(parent.getOwnerDocument(), localName, namespace); + parent.appendChild(elem); + return elem; + } + + /** + * Add a new child element with the given local name and namespace to the + * specified parent. + * + * @param parent + * @param localName + * @param namespace + * @return the new element that was attached to the given parent. + */ + public static Element addChildElement(Node parent, String localName, Namespace namespace) { + Document doc = parent.getOwnerDocument(); + if (parent instanceof Document) { + doc = (Document) parent; + } + Element elem = createElement(doc, localName, namespace); + parent.appendChild(elem); + return elem; + } + + /** + * Add a new child element with the given local name and namespace to the + * specified parent. The specified text is added as Text node to the created + * child element. + * + * @param parent + * @param localName + * @param namespace + * @param text + * @return child element that was added to the specified parent + * @see Document#createElement(String) + * @see Document#createElementNS(String, String) + * @see Document#createTextNode(String) + * @see Node#appendChild(org.w3c.dom.Node) + */ + public static Element addChildElement(Element parent, String localName, Namespace namespace, String text) { + Element elem = createElement(parent.getOwnerDocument(), localName, namespace, text); + parent.appendChild(elem); + return elem; + } + + /** + * Create a new text node and add it as child to the given element. + * + * @param element + * @param text + */ + public static void setText(Element element, String text) { + if (text == null || "".equals(text)) { + // ignore null/empty string text + return; + } + Text txt = element.getOwnerDocument().createTextNode(text); + element.appendChild(txt); + } + + /** + * Add an attribute node to the given element. + * + * @param element + * @param attrLocalName + * @param attrNamespace + * @param attrValue + */ + public static void setAttribute(Element element, String attrLocalName, Namespace attrNamespace, String attrValue) { + if (attrNamespace == null) { + Attr attr = element.getOwnerDocument().createAttribute(attrLocalName); + attr.setValue(attrValue); + element.setAttributeNode(attr); + } else { + Attr attr = element.getOwnerDocument().createAttributeNS(attrNamespace.getURI(), getPrefixedName(attrLocalName, attrNamespace)); + attr.setValue(attrValue); + element.setAttributeNodeNS(attr); + } + } + + /** + * Adds a namespace attribute on the given element. + * + * @param element + * @param prefix + * @param uri + */ + public static void setNamespaceAttribute(Element element, String prefix, String uri) { + if (Namespace.EMPTY_NAMESPACE.equals(Namespace.getNamespace(prefix, uri))) { + /** + * don't try to set the empty namespace which will fail + * see {@link org.w3c.dom.DOMException#NAMESPACE_ERR} + * TODO: correct? + */ + log.debug("Empty namespace -> omit attribute setting."); + return; + } + setAttribute(element, prefix, Namespace.XMLNS_NAMESPACE, uri); + } + + /** + * Converts the given timeout (long value defining the number of milli- + * second until timeout is reached) to its Xml representation as defined + * by RFC 4918.
+ * + * @param timeout number of milli-seconds until timeout is reached. + * @return 'timeout' Xml element + */ + public static Element timeoutToXml(long timeout, Document factory) { + boolean infinite = timeout / 1000 > Integer.MAX_VALUE || timeout == DavConstants.INFINITE_TIMEOUT; + String expString = infinite ? DavConstants.TIMEOUT_INFINITE : "Second-" + timeout / 1000; + return createElement(factory, DavConstants.XML_TIMEOUT, DavConstants.NAMESPACE, expString); + } + + /** + * Returns the Xml representation of a boolean isDeep, where false + * presents a depth value of '0', true a depth value of 'infinity'. + * + * @param isDeep + * @return Xml representation + */ + public static Element depthToXml(boolean isDeep, Document factory) { + return depthToXml(isDeep? "infinity" : "0", factory); + } + + /** + * Returns the Xml representation of a depth String. Webdav defines the + * following valid values for depths: 0, 1, infinity + * + * @param depth + * @return 'deep' XML element + */ + public static Element depthToXml(String depth, Document factory) { + return createElement(factory, DavConstants.XML_DEPTH, DavConstants.NAMESPACE, depth); + } + + /** + * Builds a 'DAV:href' Xml element from the given href. + *

+ * Note that the path present needs to be a valid URI or URI reference. + * + * @param href String representing the text of the 'href' Xml element + * @param factory the Document used as factory + * @return Xml representation of a 'href' according to RFC 2518. + */ + public static Element hrefToXml(String href, Document factory) { + return createElement(factory, DavConstants.XML_HREF, DavConstants.NAMESPACE, href); + } + + /** + * Same as {@link #getExpandedName(String, Namespace)}. + * + * @param localName + * @param namespace + * @return the expanded name of a DOM node consisting of "{" + namespace uri + "}" + * + localName. If the specified namespace is null or represents + * the empty namespace, the local name is returned. + * @deprecated As of 2.0. Please use {@link #getExpandedName(String, Namespace)} + * instead. This method was named according to usage of 'qualified name' in + * JSR 170 that conflicts with the terminology used in XMLNS. As of JCR 2.0 + * the String consisting of "{" + namespace uri + "}" + localName + * is called Expanded Name. + * + */ + public static String getQualifiedName(String localName, Namespace namespace) { + return getExpandedName(localName, namespace); + } + + /** + * Returns a string representation of the name of a DOM node consisting + * of "{" + namespace uri + "}" + localName. If the specified namespace is + * null or represents the empty namespace, the local name is + * returned. + * + * @param localName + * @param namespace + * @return String representation of the name of a DOM node consisting of "{" + namespace uri + "}" + * + localName. If the specified namespace is null or represents + * the empty namespace, the local name is returned. + * @since 2.0 Replaces the deprecated method {@link #getQualifiedName(String, Namespace)}. + */ + public static String getExpandedName(String localName, Namespace namespace) { + if (namespace == null || namespace.equals(Namespace.EMPTY_NAMESPACE)) { + return localName; + } + StringBuffer b = new StringBuffer("{"); + b.append(namespace.getURI()).append("}"); + b.append(localName); + return b.toString(); + } + + /** + * Return the qualified name of a DOM node consisting of + * namespace prefix + ":" + local name. If the specified namespace is null + * or contains an empty prefix, the local name is returned.
+ * NOTE, that this is the value to be used for the 'qualified Name' parameter + * expected with the namespace sensitive factory methods. + * + * @param localName + * @param namespace + * @return qualified name consisting of prefix, ':' and local name. + * @see Document#createAttributeNS(String, String) + * @see Document#createElementNS(String, String) + */ + public static String getPrefixedName(String localName, Namespace namespace) { + return getPrefixName(namespace.getURI(), namespace.getPrefix(), localName); + } + + /** + * Return the qualified name of a DOM node consisting of + * namespace prefix + ":" + local name. If the specified namespace is null + * or contains an empty prefix, the local name is returned.
+ * NOTE, that this is the value to be used for the 'qualified Name' parameter + * expected with the namespace sensitive factory methods. + * + * @param name + * @return qualified name consisting of prefix, ':' and local name. + * @see Document#createAttributeNS(String, String) + * @see Document#createElementNS(String, String) + */ + public static String getPrefixedName(QName name) { + return getPrefixName(name.getNamespaceURI(), name.getPrefix(), name.getLocalPart()); + } + + private static String getPrefixName(String namespaceURI, String prefix, String localName) { + if (namespaceURI == null || prefix == null || "".equals(namespaceURI) || "".equals(prefix)) { + return localName; + } else { + StringBuffer buf = new StringBuffer(prefix); + buf.append(":"); + buf.append(localName); + return buf.toString(); + } + } + + /** + * Uses a new Transformer instance to transform the specified xml document + * to the specified writer output target. + * + * @param xmlDoc XML document to create the transformation + * Source for. + * @param writer The writer used to create a new transformation + * Result for. + * @throws TransformerException + */ + public static void transformDocument(Document xmlDoc, Writer writer) throws TransformerException, SAXException { + Transformer transformer = TRANSFORMER_FACTORY.newTransformer(); + transformer.transform(new DOMSource(xmlDoc), ResultHelper.getResult(new StreamResult(writer))); + } + + /** + * Uses a new Transformer instance to transform the specified xml document + * to the specified writer output target. + * + * @param xmlDoc XML document to create the transformation + * Source for. + * @param out The stream used to create a new transformation + * Result for. + * @throws TransformerException + */ + public static void transformDocument(Document xmlDoc, OutputStream out) throws TransformerException, SAXException { + Transformer transformer = TRANSFORMER_FACTORY.newTransformer(); + transformer.transform(new DOMSource(xmlDoc), ResultHelper.getResult(new StreamResult(out))); + } +} Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/xml/DomUtil.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-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/xml/ElementIterator.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/xml/ElementIterator.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/xml/ElementIterator.java (working copy) @@ -0,0 +1,170 @@ +/* + * 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.webdav.xml; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.w3c.dom.Element; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; + +import java.util.Iterator; +import java.util.NoSuchElementException; + +import javax.xml.namespace.QName; + +/** + * ElementIterator... + */ +public class ElementIterator implements Iterator { + + private static Logger log = LoggerFactory.getLogger(ElementIterator.class); + + private final Namespace namespace; + private final String localName; + private final QName qName; + + private Element next; + + /** + * Create a new instance of ElementIterator with the given + * parent element. Only child elements that match the given local name + * and namespace will be respected by {@link #hasNext()} and {@link #nextElement()}. + * + * @param parent + * @param localName local name the child elements must match + * @param namespace namespace the child elements must match + */ + public ElementIterator(Element parent, String localName, Namespace namespace) { + this.localName = localName; + this.namespace = namespace; + this.qName = null; + seek(parent); + } + + /** + * Create a new instance of ElementIterator with the given + * parent element. Only child elements that match the given {@link QName} + * will be respected by {@link #hasNext()} and {@link #nextElement()}. + * + * @param parent + * @param qname name to match (exactly) + */ + public ElementIterator(Element parent, QName qname) { + this.localName = null; + this.namespace = null; + this.qName = qname; + seek(parent); + } + + /** + * Create a new instance of ElementIterator with the given + * parent element. No filtering is applied to child elements that are + * iterated. + * + * @param parent + */ + public ElementIterator(Element parent) { + this(parent, null, null); + } + + /** + * Not implemented + * + * @throws UnsupportedOperationException + */ + public void remove() { + throw new UnsupportedOperationException("Remove not implemented."); + } + + /** + * Returns true if there is a next Element + * + * @return true if a next Element is available. + */ + public boolean hasNext() { + return next != null; + } + + /** + * @see java.util.Iterator#next() + * @see #nextElement() + */ + public Element next() { + return nextElement(); + } + + /** + * Returns the next Element in the iterator. + * + * @return the next element + * @throws NoSuchElementException if there is no next element. + */ + public Element nextElement() { + if (next==null) { + throw new NoSuchElementException(); + } + Element ret = next; + seek(); + return ret; + } + + /** + * Seeks for the first matching child element + */ + private void seek(Element parent) { + NodeList nodeList = parent.getChildNodes(); + for (int i = 0; i < nodeList.getLength(); i++) { + Node n = nodeList.item(i); + if (matchesName(n)) { + next = (Element)n; + return; + } + } + } + + /** + * Seeks for the next valid element (i.e. the next valid sibling) + */ + private void seek() { + Node n = next.getNextSibling(); + while (n != null) { + if (matchesName(n)) { + next = (Element)n; + return; + } else { + n = n.getNextSibling(); + } + } + // no next element found -> set to null in order to leave the loop. + next = null; + } + + /** + * Matches the node name according to either {@link #qName} or the pair + * of {@link #localName) and {@link #namespace}. + */ + private boolean matchesName(Node n) { + if (!DomUtil.isElement(n)) { + return false; + } else if (qName != null) { + return DomUtil.matches(n, qName); + } else { + return DomUtil.matches(n, localName, namespace); + } + } +} Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/xml/ElementIterator.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-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/xml/Namespace.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/xml/Namespace.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/xml/Namespace.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.webdav.xml; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Namespace + */ +public class Namespace { + + private static Logger log = LoggerFactory.getLogger(Namespace.class); + + public static final Namespace EMPTY_NAMESPACE = new Namespace("",""); + public static final Namespace XML_NAMESPACE = new Namespace("xml", "http://www.w3.org/XML/1998/namespace"); + public static final Namespace XMLNS_NAMESPACE = new Namespace("xmlns", "http://www.w3.org/2000/xmlns/"); + + private final String prefix; + private final String uri; + + private Namespace(String prefix, String uri) { + this.prefix = prefix; + this.uri = uri; + } + + //-----------------------------------------------------------< creation >--- + + public static Namespace getNamespace(String prefix, String uri) { + if (prefix == null) { + prefix = EMPTY_NAMESPACE.getPrefix(); + } + if (uri == null) { + uri = EMPTY_NAMESPACE.getURI(); + } + return new Namespace(prefix, uri); + } + + public static Namespace getNamespace(String uri) { + return getNamespace("", uri); + } + + //-------------------------------------------------------------------------- + + public String getPrefix() { + return prefix; + } + + public String getURI() { + return uri; + } + + /** + * Returns true if the a Namespace built from the + * specified namespaceURI is equal to this namespace object. + * + * @param namespaceURI A namespace URI to be compared to this namespace instance. + * @return true if the a Namespace built from the + * specified namespaceURI is equal to this namespace object; + * false otherwise. + */ + public boolean isSame(String namespaceURI) { + Namespace other = getNamespace(namespaceURI); + return this.equals(other); + } + + //-------------------------------------------------------------< Object >--- + @Override + public int hashCode() { + return uri.hashCode(); + } + + @Override + public boolean equals(Object obj) { + if (obj == this) { + return true; + } + if (obj instanceof Namespace) { + return uri.equals(((Namespace)obj).uri); + } + return false; + } +} \ No newline at end of file Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/xml/Namespace.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-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/xml/ResultHelper.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/xml/ResultHelper.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/xml/ResultHelper.java (working copy) @@ -0,0 +1,458 @@ +/* + * 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.webdav.xml; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.xml.sax.Attributes; +import org.xml.sax.ContentHandler; +import org.xml.sax.Locator; +import org.xml.sax.SAXException; +import org.xml.sax.helpers.AttributesImpl; +import org.xml.sax.helpers.DefaultHandler; + +import javax.xml.transform.OutputKeys; +import javax.xml.transform.Result; +import javax.xml.transform.Transformer; +import javax.xml.transform.TransformerConfigurationException; +import javax.xml.transform.TransformerFactory; +import javax.xml.transform.sax.SAXResult; +import javax.xml.transform.sax.SAXTransformerFactory; +import javax.xml.transform.sax.TransformerHandler; +import javax.xml.transform.stream.StreamResult; +import java.io.StringWriter; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +/** + * ResultHelper is a utility to assert proper namespace handling + * due to misbehavior of certain implementations with respect to xmlns attributes. + * The code is copied and slightly modified from jcr-commons + * SerializingContentHandler + * + * @see JCR-2897. + */ +public final class ResultHelper { + + /** + * logger instance + */ + private static final Logger log = LoggerFactory.getLogger(ResultHelper.class); + + /** The URI for xml namespaces */ + private static final String XML = "http://www.w3.org/XML/1998/namespace"; + + /** + * The factory used to create serializing SAX transformers. + */ + private static final SAXTransformerFactory FACTORY = + // Note that the cast from below is strictly speaking only valid when + // the factory instance supports the SAXTransformerFactory.FEATURE + // feature. But since this class would be useless without this feature, + // it's no problem to fail with a ClassCastException here and prevent + // this class from even being loaded. AFAIK all common JAXP + // implementations do support this feature. + (SAXTransformerFactory) TransformerFactory.newInstance(); + + /** + * Flag that indicates whether we need to work around the issue of + * the serializer not automatically generating the required xmlns + * attributes for the namespaces used in the document. + */ + private static final boolean NEEDS_XMLNS_ATTRIBUTES = + needsXmlnsAttributes(); + + /** + * Probes the available XML serializer for xmlns support. Used to set + * the value of the {@link #NEEDS_XMLNS_ATTRIBUTES} flag. + * + * @return whether the XML serializer needs explicit xmlns attributes + */ + private static boolean needsXmlnsAttributes() { + try { + StringWriter writer = new StringWriter(); + TransformerHandler probe = FACTORY.newTransformerHandler(); + probe.setResult(new StreamResult(writer)); + probe.startDocument(); + probe.startPrefixMapping("p", "uri"); + probe.startElement("uri", "e", "p:e", new AttributesImpl()); + probe.endElement("uri", "e", "p:e"); + probe.endPrefixMapping("p"); + probe.endDocument(); + return writer.toString().indexOf("xmlns") == -1; + } catch (Exception e) { + throw new UnsupportedOperationException("XML serialization fails"); + } + } + + /** + * In case the underlying XML library doesn't properly handle xmlns attributes + * this method creates new content handler dealing with the misbehavior and + * returns an new instance of SAXResult. Otherwise the passed result + * is returned back. + * + * @param result + * @return A instance of Result that properly handles xmlns attributes. + * @throws SAXException + */ + public static Result getResult(Result result) throws SAXException { + try { + TransformerHandler handler = FACTORY.newTransformerHandler(); + handler.setResult(result); + + // Specify the output properties to avoid surprises especially in + // character encoding or the output method (might be html for some + // documents!) + Transformer transformer = handler.getTransformer(); + transformer.setOutputProperty(OutputKeys.METHOD, "xml"); + transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8"); + transformer.setOutputProperty(OutputKeys.INDENT, "no"); + + if (NEEDS_XMLNS_ATTRIBUTES) { + // The serializer does not output xmlns declarations, + // so we need to do it explicitly with this wrapper + return new SAXResult(new SerializingContentHandler(handler)); + } else { + return result; + } + } catch (TransformerConfigurationException e) { + throw new SAXException("Failed to initialize XML serializer", e); + } + } + + /** + * private constructor to avoid instantiation + */ + private ResultHelper() { + } + + /** + * Special content handler fixing issues with xmlns attraibutes handling. + */ + private static final class SerializingContentHandler extends DefaultHandler { + /** + * The prefixes of startPrefixMapping() declarations for the coming element. + */ + private List prefixList = new ArrayList(); + + /** + * The URIs of startPrefixMapping() declarations for the coming element. + */ + private List uriList = new ArrayList(); + + /** + * Maps of URI<->prefix mappings. Used to work around a bug in the Xalan + * serializer. + */ + private Map uriToPrefixMap = new HashMap(); + private Map prefixToUriMap = new HashMap(); + + /** + * True if there has been some startPrefixMapping() for the coming element. + */ + private boolean hasMappings = false; + + /** + * Stack of the prefixes of explicitly generated prefix mapping calls + * per each element level. An entry is appended at the beginning of each + * {@link #startElement(String, String, String, org.xml.sax.Attributes)} call and + * removed at the end of each {@link #endElement(String, String, String)} + * call. By default the entry for each element is null to + * avoid losing performance, but whenever the code detects a new prefix + * mapping that needs to be registered, the null entry is + * replaced with a list of explicitly registered prefixes for that node. + * When that element is closed, the listed prefixes get unmapped. + * + * @see #checkPrefixMapping(String, String) + * @see JCR-1767 + */ + private final List addedPrefixMappings = new ArrayList(); + + /** + * The adapted content handler instance. + */ + private final ContentHandler handler; + + private SerializingContentHandler(ContentHandler handler) { + this.handler = handler; + } + + @Override + public void characters(char[] ch, int start, int length) throws SAXException { + handler.characters(ch, start, length); + } + + @Override + public void startDocument() throws SAXException { + // Cleanup + this.uriToPrefixMap.clear(); + this.prefixToUriMap.clear(); + clearMappings(); + + handler.startDocument(); + } + + /** + * Track mappings to be able to add xmlns: attributes + * in startElement(). + */ + @Override + public void startPrefixMapping(String prefix, String uri) throws SAXException { + // Store the mappings to reconstitute xmlns:attributes + // except prefixes starting with "xml": these are reserved + // VG: (uri != null) fixes NPE in startElement + if (uri != null && !prefix.startsWith("xml")) { + this.hasMappings = true; + this.prefixList.add(prefix); + this.uriList.add(uri); + + // append the prefix colon now, in order to save concatenations later, but + // only for non-empty prefixes. + if (prefix.length() > 0) { + this.uriToPrefixMap.put(uri, prefix + ":"); + } else { + this.uriToPrefixMap.put(uri, prefix); + } + + this.prefixToUriMap.put(prefix, uri); + } + + handler.startPrefixMapping(prefix, uri); + } + + /** + * Checks whether a prefix mapping already exists for the given namespace + * and generates the required {@link #startPrefixMapping(String, String)} + * call if the mapping is not found. By default the registered prefix + * is taken from the given qualified name, but a different prefix is + * automatically selected if that prefix is already used. + * + * @see JCR-1767 + * @param uri namespace URI + * @param qname element name with the prefix, or null + * @throws SAXException if the prefix mapping can not be added + */ + private void checkPrefixMapping(String uri, String qname) + throws SAXException { + // Only add the prefix mapping if the URI is not already known + if (uri != null && uri.length() > 0 && !uri.startsWith("xml") + && !uriToPrefixMap.containsKey(uri)) { + // Get the prefix + String prefix = "ns"; + if (qname != null && qname.length() > 0) { + int colon = qname.indexOf(':'); + if (colon != -1) { + prefix = qname.substring(0, colon); + } + } + + // Make sure that the prefix is unique + String base = prefix; + for (int i = 2; prefixToUriMap.containsKey(prefix); i++) { + prefix = base + i; + } + + int last = addedPrefixMappings.size() - 1; + List prefixes = (List) addedPrefixMappings.get(last); + if (prefixes == null) { + prefixes = new ArrayList(); + addedPrefixMappings.set(last, prefixes); + } + prefixes.add(prefix); + + startPrefixMapping(prefix, uri); + } + } + + /** + * Ensure all namespace declarations are present as xmlns: attributes + * and add those needed before delegating the startElement method on the + * specified handler. This is a workaround for a Xalan bug + * (at least in version 2.0.1) : org.apache.xalan.serialize.SerializerToXML + * ignores start/endPrefixMapping(). + */ + @Override + public void startElement( + String eltUri, String eltLocalName, String eltQName, Attributes attrs) + throws SAXException { + // JCR-1767: Generate extra prefix mapping calls where needed + addedPrefixMappings.add(null); + checkPrefixMapping(eltUri, eltQName); + for (int i = 0; i < attrs.getLength(); i++) { + checkPrefixMapping(attrs.getURI(i), attrs.getQName(i)); + } + + // try to restore the qName. The map already contains the colon + if (null != eltUri && eltUri.length() != 0 && this.uriToPrefixMap.containsKey(eltUri)) { + eltQName = this.uriToPrefixMap.get(eltUri) + eltLocalName; + } + if (this.hasMappings) { + // Add xmlns* attributes where needed + + // New Attributes if we have to add some. + AttributesImpl newAttrs = null; + + int mappingCount = this.prefixList.size(); + int attrCount = attrs.getLength(); + + for (int mapping = 0; mapping < mappingCount; mapping++) { + + // Build infos for this namespace + String uri = (String) this.uriList.get(mapping); + String prefix = (String) this.prefixList.get(mapping); + String qName = prefix.equals("") ? "xmlns" : ("xmlns:" + prefix); + + // Search for the corresponding xmlns* attribute + boolean found = false; + for (int attr = 0; attr < attrCount; attr++) { + if (qName.equals(attrs.getQName(attr))) { + // Check if mapping and attribute URI match + if (!uri.equals(attrs.getValue(attr))) { + throw new SAXException("URI in prefix mapping and attribute do not match"); + } + found = true; + break; + } + } + + if (!found) { + // Need to add this namespace + if (newAttrs == null) { + // Need to test if attrs is empty or we go into an infinite loop... + // Well know SAX bug which I spent 3 hours to remind of :-( + if (attrCount == 0) { + newAttrs = new AttributesImpl(); + } else { + newAttrs = new AttributesImpl(attrs); + } + } + + if (prefix.equals("")) { + newAttrs.addAttribute(XML, qName, qName, "CDATA", uri); + } else { + newAttrs.addAttribute(XML, prefix, qName, "CDATA", uri); + } + } + } // end for mapping + + // Cleanup for the next element + clearMappings(); + + // Start element with new attributes, if any + handler.startElement(eltUri, eltLocalName, eltQName, newAttrs == null ? attrs : newAttrs); + } else { + // Normal job + handler.startElement(eltUri, eltLocalName, eltQName, attrs); + } + } + + + /** + * Receive notification of the end of an element. + * Try to restore the element qName. + */ + @Override + public void endElement(String eltUri, String eltLocalName, String eltQName) throws SAXException { + // try to restore the qName. The map already contains the colon + if (null != eltUri && eltUri.length() != 0 && this.uriToPrefixMap.containsKey(eltUri)) { + eltQName = this.uriToPrefixMap.get(eltUri) + eltLocalName; + } + + handler.endElement(eltUri, eltLocalName, eltQName); + + // JCR-1767: Generate extra prefix un-mapping calls where needed + int last = addedPrefixMappings.size() - 1; + List prefixes = (List) addedPrefixMappings.remove(last); + if (prefixes != null) { + Iterator iterator = prefixes.iterator(); + while (iterator.hasNext()) { + endPrefixMapping((String) iterator.next()); + } + } + } + + /** + * End the scope of a prefix-URI mapping: + * remove entry from mapping tables. + */ + @Override + public void endPrefixMapping(String prefix) throws SAXException { + // remove mappings for xalan-bug-workaround. + // Unfortunately, we're not passed the uri, but the prefix here, + // so we need to maintain maps in both directions. + if (this.prefixToUriMap.containsKey(prefix)) { + this.uriToPrefixMap.remove(this.prefixToUriMap.get(prefix)); + this.prefixToUriMap.remove(prefix); + } + + if (hasMappings) { + // most of the time, start/endPrefixMapping calls have an element event between them, + // which will clear the hasMapping flag and so this code will only be executed in the + // rather rare occasion when there are start/endPrefixMapping calls with no element + // event in between. If we wouldn't remove the items from the prefixList and uriList here, + // the namespace would be incorrectly declared on the next element following the + // endPrefixMapping call. + int pos = prefixList.lastIndexOf(prefix); + if (pos != -1) { + prefixList.remove(pos); + uriList.remove(pos); + } + } + + handler.endPrefixMapping(prefix); + } + + @Override + public void ignorableWhitespace(char[] ch, int start, int length) throws SAXException { + handler.ignorableWhitespace(ch, start, length); + } + + @Override + public void processingInstruction(String target, String data) throws SAXException { + handler.processingInstruction(target, data); + } + + @Override + public void setDocumentLocator(Locator locator) { + handler.setDocumentLocator(locator); + } + + @Override + public void skippedEntity(String name) throws SAXException { + handler.skippedEntity(name); + } + + @Override + public void endDocument() throws SAXException { + // Cleanup + this.uriToPrefixMap.clear(); + this.prefixToUriMap.clear(); + clearMappings(); + + handler.endDocument(); + } + + private void clearMappings() { + this.hasMappings = false; + this.prefixList.clear(); + this.uriList.clear(); + } + } +} \ No newline at end of file Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/xml/ResultHelper.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-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/xml/XmlSerializable.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/xml/XmlSerializable.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/xml/XmlSerializable.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.webdav.xml; + +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +/** + * XmlSerializable... + */ +public interface XmlSerializable { + + /** + * Returns the xml representation of the implementing object as + * {@link org.w3c.dom.Element}. The given Document is used + * as factory and represents the {@link org.w3c.dom.Element#getOwnerDocument() + * owner document} of the returned DOM element. + * + * @return a w3c element representing this object + * @param document to be used as factory. + */ + public Element toXml(Document document); + +} \ No newline at end of file Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/xml/XmlSerializable.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-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/xml/package-info.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/xml/package-info.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/xml/package-info.java (working copy) @@ -0,0 +1,18 @@ +/* + * 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. + */ +@org.osgi.annotation.versioning.Version("1.2.0") +package org.apache.jackrabbit.webdav.xml; Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/xml/package-info.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/javadoc/org/apache/jackrabbit/webdav/client/methods/package.html =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/javadoc/org/apache/jackrabbit/webdav/client/methods/package.html (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/javadoc/org/apache/jackrabbit/webdav/client/methods/package.html (working copy) @@ -0,0 +1,93 @@ + + +

+This package contains classes and utilities used to build a WebDAV client +implementation.
+Currently it consists of DAV-specific extensions to the +Jakarta Commons HttpClient, +namely a set of methods. +

+ +

+

How to use Jakarta Commons HttpClient

+Please refer to the + tutorial + present with Jakarta Commons HttpClient for detailed +instructions. +

+ +

+

Simple Example

+The following simple example illustrates the additional functionality exposed + by the DavMethod which serves as basic interface for all + WebDAV specific extensions:

+ +First you need to create the HostConfiguration which at least + must define the uri pointing to your WebDAV enabled server +
+    String uri = "http://your-webdav-server";
+    HostConfiguration hostConfig = new HostConfiguration();
+    hostConfig.setHost(uri);
+
+ +Define a HttpConnectionManager, which also is responsible + for eventual multithreading support: +
+    HttpConnectionManager connectionManager = new MultiThreadedHttpConnectionManager();
+    HttpConnectionManagerParams params = new HttpConnectionManagerParams();
+    int maxHostConnections = 20;
+    params.setMaxConnectionsPerHost(hostConfig, maxHostConnections);
+    connectionManager.setParams(params);
+
+ +Create the HttpClient object and eventually pass the Credentials: +
+    HttpClient client = new HttpClient(connectionManager);
+    client.setHostConfiguration(hostConfig);
+    Credentials creds = new UsernamePasswordCredentials("userId", "pw");
+    client.getState().setCredentials(AuthScope.ANY, creds);
+
+ +In order to execute a WebDAV request, choose the appropriate DavMethod. + For example, a PROPFIND request could look as follows: +
+    String propfindUri = "http://your-webdav-server/anyresource";
+    DavMethod method = new PropFindMethod(propfindUri, DavConstants.PROPFIND_ALL_PROP, DavConstants.DEPTH_1);
+    client.executeMethod(method);
+
+ +The DavMethod interface defines two methods that allows you to determine if the + request was successfully executed without need to evaluate the status line and + knowing about the required status codes: +
    +
  • DavMethod.checkSuccess()
  • +
  • DavMethod.succeeded()
  • +
+ +
+    method.checkSuccess();
+
+ +In case of success you can retrieve the response body in an appropriate formate + and process it according to you needs,
+ For a PROPFIND request use e.g. DavMethod.getResponseBodyAsMultiStatus(): +
+    MultiStatus multiStatus = method.getResponseBodyAsMultiStatus();
+
+

+ \ No newline at end of file Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/javadoc/org/apache/jackrabbit/webdav/client/methods/package.html ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/javadoc/org/apache/jackrabbit/webdav/lock/package.html =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/javadoc/org/apache/jackrabbit/webdav/lock/package.html (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/javadoc/org/apache/jackrabbit/webdav/lock/package.html (working copy) @@ -0,0 +1,19 @@ + + +Provides interfaces and classes for locking related issues. + Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/javadoc/org/apache/jackrabbit/webdav/lock/package.html ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/javadoc/org/apache/jackrabbit/webdav/observation/package.html =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/javadoc/org/apache/jackrabbit/webdav/observation/package.html (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/javadoc/org/apache/jackrabbit/webdav/observation/package.html (working copy) @@ -0,0 +1,20 @@ + + +Contains interfaces and classes related to observation, which is not covered +by the WebDAV protocol. + Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/javadoc/org/apache/jackrabbit/webdav/observation/package.html ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/javadoc/org/apache/jackrabbit/webdav/ordering/package.html =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/javadoc/org/apache/jackrabbit/webdav/ordering/package.html (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/javadoc/org/apache/jackrabbit/webdav/ordering/package.html (working copy) @@ -0,0 +1,21 @@ + + +Contains interfaces and classes used to cover the functionality defined by the +RFC 3648: Web Distributed Authoring +and Versioning (WebDAV) Ordered Collections Protocol . + Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/javadoc/org/apache/jackrabbit/webdav/ordering/package.html ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/javadoc/org/apache/jackrabbit/webdav/property/package.html =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/javadoc/org/apache/jackrabbit/webdav/property/package.html (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/javadoc/org/apache/jackrabbit/webdav/property/package.html (working copy) @@ -0,0 +1,19 @@ + + +Interfaces and classes related to WebDAV properties. + Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/javadoc/org/apache/jackrabbit/webdav/property/package.html ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/javadoc/org/apache/jackrabbit/webdav/search/package.html =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/javadoc/org/apache/jackrabbit/webdav/search/package.html (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/javadoc/org/apache/jackrabbit/webdav/search/package.html (working copy) @@ -0,0 +1,21 @@ + + +Contains interfaces and classes used to cover the functionality defined by the +Internet +Draft WebDAV Search. + Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/javadoc/org/apache/jackrabbit/webdav/search/package.html ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/javadoc/org/apache/jackrabbit/webdav/transaction/package.html =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/javadoc/org/apache/jackrabbit/webdav/transaction/package.html (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/javadoc/org/apache/jackrabbit/webdav/transaction/package.html (working copy) @@ -0,0 +1,19 @@ + + +Contains interfaces and classes related to transaction locks. + Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/javadoc/org/apache/jackrabbit/webdav/transaction/package.html ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/javadoc/org/apache/jackrabbit/webdav/util/package.html =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/javadoc/org/apache/jackrabbit/webdav/util/package.html (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/javadoc/org/apache/jackrabbit/webdav/util/package.html (working copy) @@ -0,0 +1,19 @@ + + +Common utility classes. + Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/javadoc/org/apache/jackrabbit/webdav/util/package.html ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/javadoc/org/apache/jackrabbit/webdav/version/package.html =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/javadoc/org/apache/jackrabbit/webdav/version/package.html (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/javadoc/org/apache/jackrabbit/webdav/version/package.html (working copy) @@ -0,0 +1,20 @@ + + +Interfaces and classes used to cover functionality defined by +RFC 3253: Versioning Extensions to WebDAV. + Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/javadoc/org/apache/jackrabbit/webdav/version/package.html ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/javadoc/org/apache/jackrabbit/webdav/version/report/package.html =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/javadoc/org/apache/jackrabbit/webdav/version/report/package.html (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/javadoc/org/apache/jackrabbit/webdav/version/report/package.html (working copy) @@ -0,0 +1,19 @@ + + +Report interface and inplementation for default reports defined by RFC 3253. + Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/javadoc/org/apache/jackrabbit/webdav/version/report/package.html ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/javadoc/org/apache/jackrabbit/webdav/xml/package.html =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/javadoc/org/apache/jackrabbit/webdav/xml/package.html (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/javadoc/org/apache/jackrabbit/webdav/xml/package.html (working copy) @@ -0,0 +1,19 @@ + + +Xml utility classes. + Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/javadoc/org/apache/jackrabbit/webdav/xml/package.html ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/resources/org/apache/jackrabbit/webdav/statuscode.properties =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/resources/org/apache/jackrabbit/webdav/statuscode.properties (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/resources/org/apache/jackrabbit/webdav/statuscode.properties (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. + +100=Continue +101=Switching Protocols +102=Processing +200=OK +201=Created +202=Accepted +203=Non-Authoritative Information +204=No Content +205=Reset Content +206=Partial Content +207=Multi-Status +300=Multiple Choices +301=Moved Permanently +302=Found +303=See Other +304=Not Modified +305=Use Proxy +307=Temporary Redirect +400=Bad Request +401=Unauthorized +402=Payment Required +403=Forbidden +404=Not Found +405=Method Not Allowed +406=Not Acceptable +407=Proxy Authentication Required +408=Request Time-out +409=Conflict +410=Gone +411=Length Required +412=Precondition Failed +413=Request Entity Too Large +414=Request-URI Too Large +415=Unsupported Media Type +416=Requested range not satisfiable +417=Expectation Failed +420=Method Failure +422=Unprocessable Entity +423=Locked +424=Failed Dependency +500=Internal Server Error +501=Not Implemented +502=Bad Gateway +503=Service Unavailable +504=Gateway Time-out +505=HTTP Version not supported +507=Insufficient Storage Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/resources/org/apache/jackrabbit/webdav/statuscode.properties ___________________________________________________________________ Added: svn Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/test/java/org/apache/jackrabbit/webdav/header/FieldValueParserTest.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/test/java/org/apache/jackrabbit/webdav/header/FieldValueParserTest.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/test/java/org/apache/jackrabbit/webdav/header/FieldValueParserTest.java (working copy) @@ -0,0 +1,42 @@ +/* + * 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.webdav.header; + +import java.util.List; + +import org.junit.Test; +import static org.junit.Assert.assertArrayEquals; + +import junit.framework.TestCase; + +public class FieldValueParserTest extends TestCase { + + @Test + public void testDavComplianceHeader() { + + List l; + + l = FieldValueParser.tokenizeList("1"); + assertArrayEquals(new String[]{"1"}, l.toArray()); + + l = FieldValueParser.tokenizeList("1,2,,,,,3,,bind,"); + assertArrayEquals(new String[]{"1","2","3","bind"}, l.toArray()); + + l = FieldValueParser.tokenizeList("1,2,"); + assertArrayEquals(new String[]{"1","2",""}, l.toArray()); + } +} Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/test/java/org/apache/jackrabbit/webdav/header/FieldValueParserTest.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/test/java/org/apache/jackrabbit/webdav/header/TestAll.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/test/java/org/apache/jackrabbit/webdav/header/TestAll.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/test/java/org/apache/jackrabbit/webdav/header/TestAll.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.webdav.header; + +import junit.framework.Test; +import junit.framework.TestCase; +import junit.framework.TestSuite; + +public class TestAll extends TestCase { + + public static Test suite() { + TestSuite suite = new TestSuite("WebDAV header tests"); + + suite.addTestSuite(FieldValueParserTest.class); + + return suite; + } +} \ No newline at end of file Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/test/java/org/apache/jackrabbit/webdav/header/TestAll.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/test/java/org/apache/jackrabbit/webdav/io/OutputContextImplTest.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/test/java/org/apache/jackrabbit/webdav/io/OutputContextImplTest.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/test/java/org/apache/jackrabbit/webdav/io/OutputContextImplTest.java (working copy) @@ -0,0 +1,186 @@ +/* + * 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.webdav.io; + +import junit.framework.TestCase; + +import javax.servlet.http.HttpServletResponse; +import javax.servlet.http.Cookie; +import javax.servlet.ServletOutputStream; +import java.io.IOException; +import java.io.PrintWriter; +import java.util.Collection; +import java.util.Locale; + +/** + * OutputContextImplTest... + */ +public class OutputContextImplTest extends TestCase { + + public void testSetContentLength() { + HttpServletResponse response = new DummyResponse() { + @Override + public void setContentLength(int len) { + assertTrue(len >= 0); + } + @Override + public void setHeader(String name, String value) { + assertTrue(Long.parseLong(value) > Integer.MAX_VALUE); + } + @Override + public String getContentType() { + return null; + } + @Override + public void setCharacterEncoding(String charset) { + } + @Override + public int getStatus() { + return 0; + } + @Override + public String getHeader(String name) { + return null; + } + @Override + public Collection getHeaders(String name) { + return null; + } + @Override + public Collection getHeaderNames() { + return null; + } + @Override + public void setContentLengthLong(long len) { + } + }; + + OutputContext ctx = new OutputContextImpl(response, null); + + ctx.setContentLength(Long.MAX_VALUE); + ctx.setContentLength(Long.MIN_VALUE); + ctx.setContentLength(Integer.MAX_VALUE); + ctx.setContentLength((long) Integer.MAX_VALUE + 1); + ctx.setContentLength(0); + ctx.setContentLength(-1); + ctx.setContentLength(12345); + } + + private abstract class DummyResponse implements HttpServletResponse { + + public void addCookie(Cookie cookie) { + } + + public boolean containsHeader(String name) { + return false; + } + + public String encodeURL(String url) { + return null; + } + + public String encodeRedirectURL(String url) { + return null; + } + + public String encodeUrl(String url) { + return null; + } + + public String encodeRedirectUrl(String url) { + return null; + } + + public void sendError(int sc, String msg) throws IOException { + } + + public void sendError(int sc) throws IOException { + } + + public void sendRedirect(String location) throws IOException { + } + + public void setDateHeader(String name, long date) { + } + + public void addDateHeader(String name, long date) { + } + + public void setHeader(String name, String value) { + } + + public void addHeader(String name, String value) { + } + + public void setIntHeader(String name, int value) { + } + + public void addIntHeader(String name, int value) { + } + + public void setStatus(int sc) { + } + + public void setStatus(int sc, String sm) { + } + + public String getCharacterEncoding() { + return null; + } + + public ServletOutputStream getOutputStream() throws IOException { + return null; + } + + public PrintWriter getWriter() throws IOException { + return null; + } + + public void setContentLength(int len) { + } + + public void setContentType(String type) { + } + + public void setBufferSize(int size) { + } + + public int getBufferSize() { + return 0; + } + + public void flushBuffer() throws IOException { + } + + public void resetBuffer() { + } + + public boolean isCommitted() { + return false; + } + + public void reset() { + } + + public void setLocale(Locale loc) { + } + + public Locale getLocale() { + return null; + } + } +} Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/test/java/org/apache/jackrabbit/webdav/io/OutputContextImplTest.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-webdav-project/jackrabbit-webdav/src/test/java/org/apache/jackrabbit/webdav/io/TestAll.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/test/java/org/apache/jackrabbit/webdav/io/TestAll.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/test/java/org/apache/jackrabbit/webdav/io/TestAll.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.webdav.io; + +import junit.framework.Test; +import junit.framework.TestCase; +import junit.framework.TestSuite; + +public class TestAll extends TestCase { + + public static Test suite() { + TestSuite suite = new TestSuite("WebDAV IO tests"); + + suite.addTestSuite(OutputContextImplTest.class); + + return suite; + } +} \ No newline at end of file Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/test/java/org/apache/jackrabbit/webdav/io/TestAll.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-webdav-project/jackrabbit-webdav/src/test/java/org/apache/jackrabbit/webdav/lock/ActiveLockTest.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/test/java/org/apache/jackrabbit/webdav/lock/ActiveLockTest.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/test/java/org/apache/jackrabbit/webdav/lock/ActiveLockTest.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.webdav.lock; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.w3c.dom.Document; +import org.apache.jackrabbit.webdav.xml.DomUtil; +import junit.framework.TestCase; + +import javax.xml.parsers.ParserConfigurationException; +import java.util.List; + +/** + * ActiveLockTest... + */ +public class ActiveLockTest extends TestCase { + + /** + * logger instance + */ + private static final Logger log = LoggerFactory.getLogger(ActiveLockTest.class); + + public void testGetLockRoot() { + ActiveLock lock = new DefaultActiveLock(); + lock.setLockroot("lockroot"); + + assertEquals("lockroot", lock.getLockroot()); + } + + public void testParsing() throws ParserConfigurationException { + Document doc = DomUtil.createDocument(); + + ActiveLock lock = new DefaultActiveLock(); + lock.setLockroot("lockroot"); + lock.setOwner("owner"); + lock.setIsDeep(true); + + LockDiscovery disc = LockDiscovery.createFromXml(new LockDiscovery(lock).toXml(doc)); + List l = disc.getValue(); + + assertFalse(l.isEmpty()); + assertEquals(1, l.size()); + ActiveLock al = l.get(0); + + assertEquals("lockroot", al.getLockroot()); + assertEquals("owner", al.getOwner()); + assertTrue(al.isDeep()); + } +} Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/test/java/org/apache/jackrabbit/webdav/lock/ActiveLockTest.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-webdav-project/jackrabbit-webdav/src/test/java/org/apache/jackrabbit/webdav/lock/TestAll.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/test/java/org/apache/jackrabbit/webdav/lock/TestAll.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/test/java/org/apache/jackrabbit/webdav/lock/TestAll.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.webdav.lock; + +import junit.framework.Test; +import junit.framework.TestCase; +import junit.framework.TestSuite; + +public class TestAll extends TestCase { + + public static Test suite() { + TestSuite suite = new TestSuite("WebDAV lock tests"); + + suite.addTestSuite(ActiveLockTest.class); + + return suite; + } +} \ No newline at end of file Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/test/java/org/apache/jackrabbit/webdav/lock/TestAll.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-webdav-project/jackrabbit-webdav/src/test/java/org/apache/jackrabbit/webdav/util/CSRFUtilTest.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/test/java/org/apache/jackrabbit/webdav/util/CSRFUtilTest.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/test/java/org/apache/jackrabbit/webdav/util/CSRFUtilTest.java (working copy) @@ -0,0 +1,412 @@ +/* + * 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.webdav.util; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.UnsupportedEncodingException; +import java.security.Principal; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Enumeration; +import java.util.HashSet; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.Set; +import java.util.Vector; + +import javax.servlet.AsyncContext; +import javax.servlet.DispatcherType; +import javax.servlet.RequestDispatcher; +import javax.servlet.ServletContext; +import javax.servlet.ServletException; +import javax.servlet.ServletInputStream; +import javax.servlet.ServletRequest; +import javax.servlet.ServletResponse; +import javax.servlet.http.Cookie; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.servlet.http.HttpSession; +import javax.servlet.http.HttpUpgradeHandler; +import javax.servlet.http.Part; + +import junit.framework.TestCase; + +/** + * CSRFUtilTest... + */ +public class CSRFUtilTest extends TestCase { + + private static final String SERVER_NAME = "localhost"; + + private static final String GET = "GET"; + private static final String POST = "POST"; + + private static final List validURLs = new ArrayList(); + private static final List invalidURLs = new ArrayList(); + + static { + validURLs.add("http://localhost:4503/jackrabbit/server"); + validURLs.add("https://localhost:4503/jackrabbit/server"); + validURLs.add("https://localhost/jackrabbit/server"); + validURLs.add("//localhost/jackrabbit/server"); + validURLs.add("/jackrabbit/server"); + + invalidURLs.add("http://invalidHost/test"); + invalidURLs.add("http://host1:8080/test"); + invalidURLs.add("http://user:pw@host2/test"); + } + + static String[] noContentType = new String[0]; + + private static void testValid(CSRFUtil util, Collection validURLs, String method, Set contentTypes) { + if (null == contentTypes) { + for (String url : validURLs) { + assertTrue(url, util.isValidRequest(createRequest(url, method, noContentType))); + } + } else { + for (String contentType : contentTypes) { + for (String url : validURLs) { + assertTrue(url, util.isValidRequest(createRequest(url, method, contentType))); + } + } + } + } + + private static void testInvalid(CSRFUtil util, Collection invalidURLs, String method, Set contentTypes) { + if (null == contentTypes) { + for (String url : validURLs) { + assertFalse(url, util.isValidRequest(createRequest(url, method, noContentType))); + } + } else { + for (String contentType : contentTypes) { + for (String url : invalidURLs) { + assertFalse(url, util.isValidRequest(createRequest(url, method, contentType))); + } + } + } + } + + private static HttpServletRequest createRequest(String url, String method, String[] contentTypes) { + return new DummyRequest(url, SERVER_NAME, method, contentTypes); + } + + private static HttpServletRequest createRequest(String url, String method, String contentType) { + return new DummyRequest(url, SERVER_NAME, method, new String[] { contentType }); + } + + public void testNullConfig() throws Exception { + CSRFUtil util = new CSRFUtil(null); + testValid(util, validURLs, POST, CSRFUtil.CONTENT_TYPES); + testInvalid(util, invalidURLs, POST, CSRFUtil.CONTENT_TYPES); + } + + public void testEmptyConfig() throws Exception { + CSRFUtil util = new CSRFUtil(""); + testValid(util, validURLs, POST, CSRFUtil.CONTENT_TYPES); + testInvalid(util, invalidURLs, POST, CSRFUtil.CONTENT_TYPES); + } + + public void testNoReferrer() throws Exception { + CSRFUtil util = new CSRFUtil(""); + testValid(util, validURLs, POST, CSRFUtil.CONTENT_TYPES); + assertFalse("no referrer", util.isValidRequest(createRequest(null, POST, "text/plain"))); + assertFalse("no referrer", util.isValidRequest(createRequest(null, POST, noContentType))); + assertFalse("no referrer", util.isValidRequest(createRequest(null, POST, "TEXT/PLAIN; foo=bar"))); + assertTrue("no referrer", util.isValidRequest(createRequest(null, POST, "application/json"))); + assertFalse("no referrer", util.isValidRequest(createRequest(null, POST, new String[] { "application/json", "foo/bar" }))); + } + + public void testDisabledConfig() throws Exception { + CSRFUtil util = new CSRFUtil(CSRFUtil.DISABLED); + testValid(util, validURLs, POST, CSRFUtil.CONTENT_TYPES); + // since test is disabled any other referer host must be allowed + testValid(util, invalidURLs, POST, CSRFUtil.CONTENT_TYPES); + } + + public void testConfig() throws Exception { + List configs = new ArrayList(); + configs.add("host1,host2"); + configs.add(" host1 , host2 "); + configs.add("\rhost1,\rhost2\r"); + + // hosts listed in the config must be valid + List otherHosts = new ArrayList(); + otherHosts.add("http://host1:80/test"); + otherHosts.add("http://host1/test"); + otherHosts.add("https://user:pw@host2/test"); + + List invalidURLs = new ArrayList(); + invalidURLs.add("http://invalidHost/test"); + invalidURLs.add("http://host3:8080/test"); + invalidURLs.add("https://user:pw@host4/test"); + + for (String config : configs) { + CSRFUtil util = new CSRFUtil(config); + testValid(util, validURLs, POST, CSRFUtil.CONTENT_TYPES); + testValid(util, otherHosts, POST, CSRFUtil.CONTENT_TYPES); + testInvalid(util, invalidURLs, POST, CSRFUtil.CONTENT_TYPES); + } + } + + public void testMethodsAndMediaType() throws Exception { + CSRFUtil util = new CSRFUtil(""); + testValid(util, invalidURLs, GET, CSRFUtil.CONTENT_TYPES); + testValid(util, invalidURLs, POST, new HashSet(Arrays.asList(new String[] {"application/json"}))); + testInvalid(util, invalidURLs, POST, CSRFUtil.CONTENT_TYPES); + } + + private static final class DummyRequest implements HttpServletRequest { + + private final String referer; + private final String serverName; + private final String method; + private final String[] contentTypes; + + private DummyRequest(String referer, String serverName, String method, String[] contentTypes) { + this.referer = referer; + this.serverName = serverName; + this.method = method; + this.contentTypes = contentTypes; + } + + //---------------------------------------------< HttpServletRequest >--- + + public String getHeader(String name) { + if ("Referer".equalsIgnoreCase(name)) { + return referer; + } else { + return null; + } + } + + public String getServerName() { + return serverName; + } + + public String getContentType() { + return contentTypes.length == 0 ? null : contentTypes[0]; + } + + @SuppressWarnings({ "rawtypes", "unchecked" }) + public Enumeration getHeaders(String name) { + if (name != null && contentTypes.length > 0 && name.toLowerCase(Locale.ENGLISH).equals("content-type")) { + return new Vector(Arrays.asList(contentTypes)).elements(); + } else { + return null; + } + } + + //---------------------------------------------------------< unused >--- + public String getAuthType() { + return null; + } + public Cookie[] getCookies() { + return new Cookie[0]; + } + public long getDateHeader(String name) { + return 0; + } + public Enumeration getHeaderNames() { + return null; + } + public int getIntHeader(String name) { + return 0; + } + public String getMethod() { + return method; + } + public String getPathInfo() { + return null; + } + public String getPathTranslated() { + return null; + } + public String getContextPath() { + return null; + } + public String getQueryString() { + return null; + } + public String getRemoteUser() { + return null; + } + public boolean isUserInRole(String role) { + return false; + } + public Principal getUserPrincipal() { + return null; + } + public String getRequestedSessionId() { + return null; + } + public String getRequestURI() { + return null; + } + public StringBuffer getRequestURL() { + return null; + } + public String getServletPath() { + return null; + } + public HttpSession getSession(boolean create) { + return null; + } + public HttpSession getSession() { + return null; + } + public boolean isRequestedSessionIdValid() { + return false; + } + public boolean isRequestedSessionIdFromCookie() { + return false; + } + public boolean isRequestedSessionIdFromURL() { + return false; + } + public boolean isRequestedSessionIdFromUrl() { + return false; + } + public Object getAttribute(String name) { + return null; + } + public Enumeration getAttributeNames() { + return null; + } + public String getCharacterEncoding() { + return null; + } + public void setCharacterEncoding(String s) throws UnsupportedEncodingException { + + } + public int getContentLength() { + return 0; + } + public ServletInputStream getInputStream() throws IOException { + return null; + } + public String getParameter(String name) { + return null; + } + public Enumeration getParameterNames() { + return null; + } + public String[] getParameterValues(String name) { + return new String[0]; + } + public Map getParameterMap() { + return null; + } + public String getProtocol() { + return null; + } + public String getScheme() { + return null; + } + public int getServerPort() { + return 0; + } + public BufferedReader getReader() throws IOException { + return null; + } + public String getRemoteAddr() { + return null; + } + public String getRemoteHost() { + return null; + } + public void setAttribute(String name, Object o) { + + } + public void removeAttribute(String name) { + + } + public Locale getLocale() { + return null; + } + public Enumeration getLocales() { + return null; + } + public boolean isSecure() { + return false; + } + public RequestDispatcher getRequestDispatcher(String path) { + return null; + } + public String getRealPath(String path) { + return null; + } + public int getRemotePort() { + return 0; + } + public String getLocalName() { + return null; + } + public String getLocalAddr() { + return null; + } + public int getLocalPort() { + return 0; + } + public long getContentLengthLong() { + return 0; + } + public ServletContext getServletContext() { + return null; + } + public AsyncContext startAsync() throws IllegalStateException { + return null; + } + public AsyncContext startAsync(ServletRequest servletRequest, ServletResponse servletResponse) + throws IllegalStateException { + return null; + } + public boolean isAsyncStarted() { + return false; + } + public boolean isAsyncSupported() { + return false; + } + public AsyncContext getAsyncContext() { + return null; + } + public DispatcherType getDispatcherType() { + return null; + } + public String changeSessionId() { + return null; + } + public boolean authenticate(HttpServletResponse response) throws IOException, ServletException { + return false; + } + public void login(String username, String password) throws ServletException { + } + public void logout() throws ServletException { + } + public Collection getParts() throws IOException, ServletException { + return null; + } + public Part getPart(String name) throws IOException, ServletException { + return null; + } + public T upgrade(Class handlerClass) throws IOException, ServletException { + return null; + } + } +} \ No newline at end of file Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/test/java/org/apache/jackrabbit/webdav/util/CSRFUtilTest.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-webdav-project/jackrabbit-webdav/src/test/java/org/apache/jackrabbit/webdav/util/HttpDateTimeFormatterTest.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/test/java/org/apache/jackrabbit/webdav/util/HttpDateTimeFormatterTest.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/test/java/org/apache/jackrabbit/webdav/util/HttpDateTimeFormatterTest.java (working copy) @@ -0,0 +1,65 @@ +/* + * 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.webdav.util; + +import java.time.format.DateTimeParseException; + +import junit.framework.TestCase; + +public class HttpDateTimeFormatterTest extends TestCase { + + public void testImfDate() { + long t = HttpDateTimeFormatter.parseImfFixedDate("Sun, 06 Nov 1994 08:49:37 GMT"); + assertEquals(784111777000l, t); + assertEquals("Sun, 06 Nov 1994 08:49:37 GMT", HttpDateTimeFormatter.formatImfFixed(t)); + } + + public void testImfDateWrongTZ() { + try { + HttpDateTimeFormatter.parseImfFixedDate("Sun, 06 Nov 1994 08:49:37 CET"); + fail("should fail for incorrec tz"); + } catch (DateTimeParseException expected) { + } + } + + public void testImfDateWrongWeekday() { + try { + HttpDateTimeFormatter.parseImfFixedDate("Mon, 06 Nov 1994 08:49:37 GMT"); + fail("should fail for incorrec tz"); + } catch (DateTimeParseException expected) { + } + } + + // will fail after 2044 + public void testRFC850Date() { + long t = HttpDateTimeFormatter.parseRfc850Date("Sunday, 06-Nov-94 08:49:37 GMT"); + assertEquals(784111777000l, t); + assertEquals("Sunday, 06-Nov-94 08:49:37 GMT", HttpDateTimeFormatter.formatRfc850(t)); + } + + public void testAscTimeDate() { + long t = HttpDateTimeFormatter.parseAscTimeDate("Sun Nov 6 08:49:37 1994"); + assertEquals(784111777000l, t); + assertEquals("Sun Nov 6 08:49:37 1994", HttpDateTimeFormatter.formatAscTime(t)); + } + + public void testAscTimeDateZeroPad() { + long t = HttpDateTimeFormatter.parseAscTimeDate("Sun Nov 06 08:49:37 1994"); + assertEquals(784111777000l, t); + assertEquals("Sun Nov 6 08:49:37 1994", HttpDateTimeFormatter.formatAscTime(t)); + } +} Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/test/java/org/apache/jackrabbit/webdav/util/HttpDateTimeFormatterTest.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/test/java/org/apache/jackrabbit/webdav/util/LinkHeaderFieldParserTest.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/test/java/org/apache/jackrabbit/webdav/util/LinkHeaderFieldParserTest.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/test/java/org/apache/jackrabbit/webdav/util/LinkHeaderFieldParserTest.java (working copy) @@ -0,0 +1,65 @@ +/* + * 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.webdav.util; + +import java.util.Collections; + +import junit.framework.TestCase; + +/** + * LinkHeaderFieldParserTest... + */ +public class LinkHeaderFieldParserTest extends TestCase { + + public void testSimple() { + LinkHeaderFieldParser lhfp = new LinkHeaderFieldParser( + Collections.singletonList("; rel=foo")); + assertEquals("a", lhfp.getFirstTargetForRelation("foo")); + } + + public void testMulti() { + LinkHeaderFieldParser lhfp = new LinkHeaderFieldParser( + Collections.singletonList("; rel=foo, ; rel=bar")); + assertEquals("b", lhfp.getFirstTargetForRelation("bar")); + } + + public void testMultiQs() { + LinkHeaderFieldParser lhfp = new LinkHeaderFieldParser( + Collections + .singletonList("; rel=\"fo\\\"o,\", ; rel=bar")); + assertEquals("b,", lhfp.getFirstTargetForRelation("bar")); + } + + // broken by change to httpclient 4 +// public void testTruncated() { +// LinkHeaderFieldParser lhfp = new LinkHeaderFieldParser( +// Collections.singletonList("; rel=\"x\\\"")); +// assertEquals("a,", lhfp.getFirstTargetForRelation("x\\")); +// } + + public void testCommas() { + LinkHeaderFieldParser lhfp = new LinkHeaderFieldParser( + Collections.singletonList(",; rel=\"xy,z\",")); + assertEquals("a", lhfp.getFirstTargetForRelation("xy,z")); + } + + public void testMultiRel() { + LinkHeaderFieldParser lhfp = new LinkHeaderFieldParser( + Collections.singletonList(",; rel=\"a b\"")); + assertEquals("a", lhfp.getFirstTargetForRelation("a")); + } +} Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/test/java/org/apache/jackrabbit/webdav/util/LinkHeaderFieldParserTest.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/test/java/org/apache/jackrabbit/webdav/util/TestAll.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/test/java/org/apache/jackrabbit/webdav/util/TestAll.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/test/java/org/apache/jackrabbit/webdav/util/TestAll.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.webdav.util; + +import junit.framework.Test; +import junit.framework.TestCase; +import junit.framework.TestSuite; + +/** + * Test suite that includes all testcases for package org.apache.jackrabbit.webdav.util. + */ +public class TestAll extends TestCase { + + /** + * Returns a Test suite that executes all tests inside this + * package. + */ + public static Test suite() { + TestSuite suite = new TestSuite("org.apache.jackrabbit.webdav.util tests"); + + suite.addTestSuite(CSRFUtilTest.class); + suite.addTestSuite(LinkHeaderFieldParserTest.class); + + return suite; + } +} Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/test/java/org/apache/jackrabbit/webdav/util/TestAll.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-webdav-project/jackrabbit-webdav/src/test/java/org/apache/jackrabbit/webdav/xml/NamespaceTest.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/test/java/org/apache/jackrabbit/webdav/xml/NamespaceTest.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/test/java/org/apache/jackrabbit/webdav/xml/NamespaceTest.java (working copy) @@ -0,0 +1,94 @@ +/* + * 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.webdav.xml; + +import junit.framework.TestCase; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.HashMap; +import java.util.Map; + +/** + * NamespaceTest... + */ +public class NamespaceTest extends TestCase { + + /** + * logger instance + */ + private static final Logger log = LoggerFactory.getLogger(NamespaceTest.class); + + public void testGetNamespace() { + assertEquals(Namespace.EMPTY_NAMESPACE, Namespace.getNamespace("", "")); + assertEquals(Namespace.EMPTY_NAMESPACE, Namespace.getNamespace(null, null)); + assertEquals(Namespace.XML_NAMESPACE, Namespace.getNamespace(Namespace.XML_NAMESPACE.getPrefix(), Namespace.XML_NAMESPACE.getURI())); + assertEquals(Namespace.XMLNS_NAMESPACE, Namespace.getNamespace(Namespace.XMLNS_NAMESPACE.getPrefix(), Namespace.XMLNS_NAMESPACE.getURI())); + + Map m = new HashMap(); + m.put("foo", "http://foo.org/ns/foo"); + m.put("", "http://foo.org/ns/foo"); + m.put("off", "http://foo.org/ns/foo"); + m.put("off", ""); + + for (String prefix: m.keySet()) { + String uri = m.get(prefix); + Namespace ns = Namespace.getNamespace(prefix, uri); + assertEquals(prefix, ns.getPrefix()); + assertEquals(uri, ns.getURI()); + assertEquals(ns, Namespace.getNamespace(prefix, uri)); + } + } + + public void testIsSame() { + Map same = new HashMap(); + same.put("http://foo.org/ns/foo", Namespace.getNamespace("foo", "http://foo.org/ns/foo")); + same.put("http://foo.org/ns/foo", Namespace.getNamespace("abc", "http://foo.org/ns/foo")); + same.put("http://foo.org/ns/foo", Namespace.getNamespace("", "http://foo.org/ns/foo")); + same.put("http://foo.org/ns/foo", Namespace.getNamespace(null, "http://foo.org/ns/foo")); + same.put("", Namespace.EMPTY_NAMESPACE); + same.put(null, Namespace.EMPTY_NAMESPACE); + same.put(Namespace.XML_NAMESPACE.getURI(), Namespace.XML_NAMESPACE); + same.put(Namespace.XMLNS_NAMESPACE.getURI(), Namespace.XMLNS_NAMESPACE); + + for (String nsURI : same.keySet()) { + assertTrue(nsURI, same.get(nsURI).isSame(nsURI)); + } + + Map notSame = new HashMap(); + notSame.put("http://foo.org/ns/abc", Namespace.getNamespace("foo", "http://foo.org/ns/foo")); + notSame.put("", Namespace.getNamespace("abc", "http://foo.org/ns/foo")); + notSame.put(null, Namespace.getNamespace("", "http://foo.org/ns/foo")); + notSame.put("http://foo.org/ns/abc", Namespace.EMPTY_NAMESPACE); + notSame.put(Namespace.XML_NAMESPACE.getURI(), Namespace.EMPTY_NAMESPACE); + notSame.put(Namespace.EMPTY_NAMESPACE.getURI(), Namespace.XML_NAMESPACE); + notSame.put(Namespace.XMLNS_NAMESPACE.getURI(), Namespace.XML_NAMESPACE); + notSame.put(Namespace.XML_NAMESPACE.getURI(), Namespace.XMLNS_NAMESPACE); + + for (String nsURI : notSame.keySet()) { + assertFalse(notSame.get(nsURI).isSame(nsURI)); + } + } + + public void testEquals() { + assertEquals(Namespace.EMPTY_NAMESPACE, Namespace.getNamespace("prefix", "")); + assertEquals(Namespace.EMPTY_NAMESPACE, Namespace.getNamespace("prefix", null)); + + assertFalse(Namespace.EMPTY_NAMESPACE.equals(Namespace.getNamespace("", "something"))); + assertFalse(Namespace.EMPTY_NAMESPACE.equals(Namespace.getNamespace(null, "something"))); + } +} \ No newline at end of file Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/test/java/org/apache/jackrabbit/webdav/xml/NamespaceTest.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-webdav-project/jackrabbit-webdav/src/test/java/org/apache/jackrabbit/webdav/xml/ParserTest.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/test/java/org/apache/jackrabbit/webdav/xml/ParserTest.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/test/java/org/apache/jackrabbit/webdav/xml/ParserTest.java (working copy) @@ -0,0 +1,143 @@ +/* + * 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.webdav.xml; + +import java.io.ByteArrayInputStream; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.UnsupportedEncodingException; + +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; + +import junit.framework.TestCase; + +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.xml.sax.EntityResolver; +import org.xml.sax.InputSource; +import org.xml.sax.SAXException; + +public class ParserTest extends TestCase { + + // see + public void testBillionLaughs() throws UnsupportedEncodingException { + + String testBody = "" + "" + " " + + " " + + " " + + " " + + " " + + " " + + " " + + " " + + " " + + " " + "]>" + "&lol9;"; + InputStream is = new ByteArrayInputStream(testBody.getBytes("UTF-8")); + + try { + DomUtil.parseDocument(is); + fail("parsing this document should cause an exception"); + } catch (Exception expected) { + } + } + + public void testExternalEntities() throws IOException { + + String dname = "target"; + String fname = "test.xml"; + + File f = new File(dname, fname); + OutputStream os = new FileOutputStream(f); + os.write("testdata".getBytes()); + os.close(); + + String testBody = "\n" + + "]>\n&test;"; + InputStream is = new ByteArrayInputStream(testBody.getBytes("UTF-8")); + + try { + Document d = DomUtil.parseDocument(is); + Element root = d.getDocumentElement(); + String text = DomUtil.getText(root); + fail("parsing this document should cause an exception, but the following external content was included: " + text); + } catch (Exception expected) { + } + } + + public void testCustomEntityResolver() throws ParserConfigurationException, SAXException, IOException { + + try { + DocumentBuilderFactory dbf = new DocumentBuilderFactory() { + + DocumentBuilderFactory def = DocumentBuilderFactory.newInstance(); + + @Override + public void setFeature(String name, boolean value) throws ParserConfigurationException { + def.setFeature(name, value); + } + + @Override + public void setAttribute(String name, Object value) throws IllegalArgumentException { + def.setAttribute(name, value); + } + + @Override + public DocumentBuilder newDocumentBuilder() throws ParserConfigurationException { + DocumentBuilder db = def.newDocumentBuilder(); + db.setEntityResolver(new EntityResolver() { + @Override + public InputSource resolveEntity(String publicId, String systemId) throws SAXException, IOException { + if ("foo:test".equals(systemId)) { + return new InputSource(new ByteArrayInputStream("foo&bar".getBytes("UTF-8"))); + } else { + return null; + } + } + }); + return db; + } + + @Override + public boolean getFeature(String name) throws ParserConfigurationException { + return def.getFeature(name); + } + + @Override + public Object getAttribute(String name) throws IllegalArgumentException { + return def.getAttribute(name); + } + }; + + DomUtil.setBuilderFactory(dbf); + String testBody = "\n" + + "]>\n&test;"; + InputStream is = new ByteArrayInputStream(testBody.getBytes("UTF-8")); + + Document d = DomUtil.parseDocument(is); + Element root = d.getDocumentElement(); + String text = DomUtil.getText(root); + assertEquals("custom entity resolver apparently not called", "foo&bar", text); + } finally { + DomUtil.setBuilderFactory(null); + } + } +} \ No newline at end of file Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/test/java/org/apache/jackrabbit/webdav/xml/ParserTest.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/test/java/org/apache/jackrabbit/webdav/xml/TestAll.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/test/java/org/apache/jackrabbit/webdav/xml/TestAll.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/test/java/org/apache/jackrabbit/webdav/xml/TestAll.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.webdav.xml; + +import junit.framework.Test; +import junit.framework.TestCase; +import junit.framework.TestSuite; + +/** + * Test suite that includes all testcases for package org.apache.jackrabbit.webdav.xml. + */ +public class TestAll extends TestCase { + + /** + * Returns a Test suite that executes all tests inside this + * package. + */ + public static Test suite() { + TestSuite suite = new TestSuite("org.apache.jackrabbit.webdav.xml tests"); + + suite.addTestSuite(NamespaceTest.class); + suite.addTestSuite(ParserTest.class); + + return suite; + } +} Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/test/java/org/apache/jackrabbit/webdav/xml/TestAll.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-webdav-project/jackrabbit-webdav/src/test/resources/logback-test.xml =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/test/resources/logback-test.xml (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/test/resources/logback-test.xml (working copy) @@ -0,0 +1,31 @@ + + + + + + target/jcr.log + + %date{HH:mm:ss.SSS} %-5level %-40([%thread] %F:%L) %msg%n + + + + + + + + Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/test/resources/logback-test.xml ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav (working copy) Property changes on: jackrabbit-webdav-project/jackrabbit-webdav ___________________________________________________________________ Added: svn:ignore ## -0,0 +1,5 ## +target +.* +*.iws +*.ipr +*.iml Index: jackrabbit-webdav-project/pom.xml =================================================================== --- jackrabbit-webdav-project/pom.xml (nonexistent) +++ jackrabbit-webdav-project/pom.xml (working copy) @@ -0,0 +1,56 @@ + + 4.0.0 + + org.apache.jackrabbit + jackrabbit-parent + 2.21.16-SNAPSHOT + ../jackrabbit-parent/pom.xml + + jackrabbit-webdav-project + pom + Jackrabbit JCR Servlet Project + + jackrabbit-webdav + jackrabbit-webdav-jakarta + + + + org.osgi + org.osgi.annotation + provided + + + org.slf4j + slf4j-api + + + javax.servlet + javax.servlet-api + provided + + + org.apache.httpcomponents + httpcore + 4.4.16 + + + org.apache.httpcomponents + httpclient + 4.5.14 + + + org.slf4j + jcl-over-slf4j + + + junit + junit + test + + + ch.qos.logback + logback-classic + test + + + \ No newline at end of file Index: jackrabbit-webapp-project/jackrabbit-webapp/README.txt =================================================================== --- jackrabbit-webapp-project/jackrabbit-webapp/README.txt (nonexistent) +++ jackrabbit-webapp-project/jackrabbit-webapp/README.txt (working copy) @@ -0,0 +1,22 @@ +===================================== +Welcome to Jackrabbit Web Application +===================================== + +This is the Web Application component of the Apache Jackrabbit project. +This component provides servlets used to access a Jackrabbit repository: + + * RepositoryAccessServlet.java + * LoggingServlet.java + * RepositoryStartupServlet.java + +In addition, the project contains 2 different WebDAV servlets: + + * SimpleWebdavServlet.java + Adds WebDAV support (DAV 1,2) to your jackrabbit repository. + + * JCRWebdavServerServlet.java + A servlet used to remote JSR170 calls via WebDAV. + IMPORTANT: Please note, that this servlet is not intended to provide + common WebDAV support to the repository. Instead the primary goal is to + remote JSR170 calls. + For the corresponding client see -> jackrabbit-jcr2dav (work in progress). Property changes on: jackrabbit-webapp-project/jackrabbit-webapp/README.txt ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +author date id revision \ No newline at end of property Index: jackrabbit-webapp-project/jackrabbit-webapp/pom.xml =================================================================== --- jackrabbit-webapp-project/jackrabbit-webapp/pom.xml (nonexistent) +++ jackrabbit-webapp-project/jackrabbit-webapp/pom.xml (working copy) @@ -0,0 +1,117 @@ + + + + + + 4.0.0 + + + + + + org.apache.jackrabbit + jackrabbit-webapp-project + 2.21.16-SNAPSHOT + + jackrabbit-webapp + war + Jackrabbit Web Application + Web application that hosts and serves a Jackrabbit content repository + + + + org.apache.jackrabbit + jackrabbit-jcr-server + ${project.version} + + + org.apache.jackrabbit + jackrabbit-jcr-servlet + ${project.version} + + + + + + + + maven-antrun-plugin + + + package + + + + + + + run + + + + + + + org.codehaus.mojo + build-helper-maven-plugin + + + attach-artifacts + package + + attach-artifact + + + + + ${project.build.directory}/jackrabbit-webapp-${project.version}.jar + jar + + + + + + + + org.apache.rat + apache-rat-plugin + + + src/main/webapp/WEB-INF/log4j.dtd + + + + + + + + maven-failsafe-plugin + + + + derby.stream.error.file + target/derby.log + + + + + + + + + Property changes on: jackrabbit-webapp-project/jackrabbit-webapp/pom.xml ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webapp-project/jackrabbit-webapp/src/main/java/org/apache/jackrabbit/j2ee/AbstractConfig.java =================================================================== --- jackrabbit-webapp-project/jackrabbit-webapp/src/main/java/org/apache/jackrabbit/j2ee/AbstractConfig.java (nonexistent) +++ jackrabbit-webapp-project/jackrabbit-webapp/src/main/java/org/apache/jackrabbit/j2ee/AbstractConfig.java (working copy) @@ -0,0 +1,110 @@ +/* + * 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.j2ee; + +import org.apache.commons.beanutils.BeanMap; +import org.apache.jackrabbit.util.Text; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.Enumeration; +import java.util.Iterator; +import java.util.Properties; + +import javax.servlet.ServletConfig; +import javax.servlet.ServletException; + +/** + * Abstract configuration class that is based on a bean map. + */ +public abstract class AbstractConfig { + + /** + * default logger + */ + private static final Logger log = LoggerFactory.getLogger(AbstractConfig.class); + + protected boolean valid; + + private BeanMap map = new BeanMap(this); + + /** + * Initializes the configuration with values from the given properties + * @param props the configuration properties + */ + public void init(Properties props) throws ServletException { + Iterator iter = props.keySet().iterator(); + while (iter.hasNext()) { + String name = (String) iter.next(); + String mapName = toMapName(name, '.'); + try { + if (map.containsKey(mapName)) { + map.put(mapName, props.getProperty(name)); + } + } catch (Exception e) { + throw new ServletExceptionWithCause( + "Invalid configuration property: " + name, e); + } + } + } + + public void init(ServletConfig ctx) throws ServletException { + Enumeration names = ctx.getInitParameterNames(); + while (names.hasMoreElements()) { + String name = (String) names.nextElement(); + String mapName = toMapName(name, '-'); + try { + if (map.containsKey(mapName)) { + map.put(mapName, ctx.getInitParameter(name)); + } + } catch (Exception e) { + throw new ServletExceptionWithCause( + "Invalid servlet configuration option: " + name, e); + } + } + } + + public String toMapName(String name, char delim) { + StringBuffer ret = new StringBuffer(); + String[] elems = Text.explode(name, delim); + ret.append(elems[0]); + for (int i=1; i + * +-------------------+-------------------+ + * | Property Name | Init-Param Name | + * +-------------------+-------------------+ + * | repository.home | repository-home | + * | repository.config | repository-config | + * | repository.name | repository-name | + * +-------------------+-------------------+ + * + */ +public class BootstrapConfig extends AbstractConfig { + + private String repositoryHome; + + private String repositoryConfig; + + private String repositoryName; + + private JNDIConfig jndiConfig = new JNDIConfig(this); + + private RMIConfig rmiConfig = new RMIConfig(this); + + public void init(Properties props) throws ServletException { + super.init(props); + jndiConfig.init(props); + rmiConfig.init(props); + } + + public void init(ServletConfig ctx) throws ServletException { + super.init(ctx); + jndiConfig.init(ctx); + rmiConfig.init(ctx); + } + + public String getRepositoryHome() { + return repositoryHome; + } + + public void setRepositoryHome(String repositoryHome) { + this.repositoryHome = repositoryHome; + } + + public String getRepositoryConfig() { + return repositoryConfig; + } + + public void setRepositoryConfig(String repositoryConfig) { + this.repositoryConfig = repositoryConfig; + } + + public String getRepositoryName() { + return repositoryName; + } + + public void setRepositoryName(String repositoryName) { + this.repositoryName = repositoryName; + } + + public JNDIConfig getJndiConfig() { + return jndiConfig; + } + + public RMIConfig getRmiConfig() { + return rmiConfig; + } + + public void validate() { + valid = repositoryName != null; + jndiConfig.validate(); + rmiConfig.validate(); + } + + + public void logInfos() { + super.logInfos(); + if (jndiConfig.isValid()) { + jndiConfig.logInfos(); + } + if (rmiConfig.isValid()) { + rmiConfig.logInfos(); + } + } +} \ No newline at end of file Property changes on: jackrabbit-webapp-project/jackrabbit-webapp/src/main/java/org/apache/jackrabbit/j2ee/BootstrapConfig.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webapp-project/jackrabbit-webapp/src/main/java/org/apache/jackrabbit/j2ee/DerbyShutdown.java =================================================================== --- jackrabbit-webapp-project/jackrabbit-webapp/src/main/java/org/apache/jackrabbit/j2ee/DerbyShutdown.java (nonexistent) +++ jackrabbit-webapp-project/jackrabbit-webapp/src/main/java/org/apache/jackrabbit/j2ee/DerbyShutdown.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.j2ee; + +import java.lang.reflect.Method; +import java.sql.Driver; +import java.sql.DriverManager; +import java.sql.SQLException; +import java.util.Enumeration; + +import javax.servlet.ServletContextEvent; +import javax.servlet.ServletContextListener; + +/** + * Servlet context listener that releases all remaining Derby resources + * when the web application is undeployed. The resources are released only + * if the Derby classes were loaded from within this webapp. + * + * @see JCR-1301 + */ +public class DerbyShutdown implements ServletContextListener { + + public void contextInitialized(ServletContextEvent event) { + } + + public void contextDestroyed(ServletContextEvent event) { + ClassLoader loader = DerbyShutdown.class.getClassLoader(); + + // Deregister all JDBC drivers loaded from this webapp + Enumeration drivers = DriverManager.getDrivers(); + while (drivers.hasMoreElements()) { + Driver driver = drivers.nextElement(); + // Check if this driver comes from this webapp + if (driver.getClass().getClassLoader() == loader) { + try { + DriverManager.deregisterDriver(driver); + } catch (SQLException ignore) { + } + } + } + + // Explicitly tell Derby to release all remaining resources. + // Use reflection to avoid problems when the Derby is not used. + try { + Class monitorClass = + loader.loadClass("org.apache.derby.iapi.services.monitor.Monitor"); + if (monitorClass.getClassLoader() == loader) { + Method getMonitorMethod = + monitorClass.getMethod("getMonitor", new Class[0]); + Object monitor = + getMonitorMethod.invoke(null, new Object[0]); + if (monitor != null) { + Method shutdownMethod = + monitor.getClass().getMethod("shutdown", new Class[0]); + shutdownMethod.invoke(monitor, new Object[0]); + } + } + } catch (Exception ignore) { + } + } + +} \ No newline at end of file Property changes on: jackrabbit-webapp-project/jackrabbit-webapp/src/main/java/org/apache/jackrabbit/j2ee/DerbyShutdown.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webapp-project/jackrabbit-webapp/src/main/java/org/apache/jackrabbit/j2ee/Installer.java =================================================================== --- jackrabbit-webapp-project/jackrabbit-webapp/src/main/java/org/apache/jackrabbit/j2ee/Installer.java (nonexistent) +++ jackrabbit-webapp-project/jackrabbit-webapp/src/main/java/org/apache/jackrabbit/j2ee/Installer.java (working copy) @@ -0,0 +1,234 @@ +/* + * 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.j2ee; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.util.Properties; + +import javax.servlet.ServletContext; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; + +/** + * Provides very basic installation capabilities. + */ +public class Installer { + + /** + * the default logger + */ + private static final Logger log = LoggerFactory.getLogger(Installer.class); + + /** + * Return code for installation succeeded + */ + public static final int C_INSTALL_OK = 0; + + /** + * Return code for invalid input parameter + */ + public static final int C_INVALID_INPUT = 1; + + /** + * Return code for repository home already exists + */ + public static final int C_HOME_EXISTS = 2; + + /** + * Return code for repository home is missing + */ + public static final int C_HOME_MISSING = 3; + + /** + * Return code for repository config already exists + */ + public static final int C_CONFIG_EXISTS = 4; + + /** + * Return code for repository config is missing + */ + public static final int C_CONFIG_MISSING = 5; + + /** + * Return code for bootstrap config already exists + */ + public static final int C_BOOTSTRAP_EXISTS = 6; + + /** + * Return code for a general install error + */ + public static final int C_INSTALL_ERROR = 7; + + /** + * place to store the config file + */ + private final File bootstrapConfigFile; + + /** + * the servlet context + */ + private final ServletContext context; + + /** + * the place for the repository config template + * todo: to be configured + */ + private final String configTemplate = + "/org/apache/jackrabbit/core/repository.xml"; + + /** + * the place for the bootstrap properties template + * todo: to be configured + */ + private final String bootstrapTemplate = "/WEB-INF/templates/bootstrap.properties"; + + /** + * Creates a new installer + * @param bootstrapConfigFile the location for the config file + * @param context the servlet context for accessing resources + */ + public Installer(File bootstrapConfigFile, ServletContext context) { + this.bootstrapConfigFile = bootstrapConfigFile; + this.context = context; + } + + /** + * Handles the installation. + * + * @param req the servlet request with the input parameters + * @return the installation return code + * + * @throws ServletException if a servlet error occurs. + * @throws IOException if an I/O error occurs. + */ + public int installRepository(HttpServletRequest req) + throws ServletException, IOException { + String repHome = req.getParameter("repository_home"); + String repXml = req.getParameter("repository_xml"); + String mode = req.getParameter("mode"); + + if (repHome == null || mode == null) { + return C_INVALID_INPUT; + } + File home = new File(repHome); + + File config; + if (repXml == null || repXml.length() == 0) { + config = new File(home, "repository.xml"); + repXml = config.getPath(); + } else { + config = new File(repXml); + } + + if ("new".equals(mode)) { + // Test internal folder repository existence and not home because home is already created + // by org.apache.jackrabbit.server.remoting.davex.JcrRemotingServlet + if (new File(home, "repository").exists()) { + log.error("Trying to install new repository home '{}' but it already contain a repository", repHome); + return C_HOME_EXISTS; + } + if (config != null && config.exists()) { + log.error("Trying to install new repository config '{}' but already exists", repXml); + return C_CONFIG_EXISTS; + } + log.info("Creating new repository home '{}'", repHome); + home.mkdirs(); + + if (config != null) { + // install repository xml for Jackrabbit Classic + try { + installRepositoryConfig(config); + } catch (IOException e) { + log.error("Error while installing new repository config '{}': {}", repXml, e.toString()); + return C_BOOTSTRAP_EXISTS; + } + } + } else { + if (!home.exists()) { + log.error("Trying to use existing repository home '{}' but does not exists", repHome); + return C_HOME_MISSING; + } + if (config != null && !config.exists()) { + log.error("Trying to use existing repository config '{}' but does not exists", repXml); + return C_CONFIG_MISSING; + } + } + // install bootstrap.properties + try { + installBootstrap(bootstrapConfigFile, repHome, repXml); + } catch (IOException e) { + log.error("Error while installing '{}': {}", bootstrapConfigFile.getPath(), e.toString()); + return C_INSTALL_ERROR; + } + return C_INSTALL_OK; + } + + /** + * Installs the repository config file from the template + * @param dest the destination location + * @throws IOException if an I/O error occurs. + */ + private void installRepositoryConfig(File dest) throws IOException { + log.info("Creating new repository config: {}", dest.getPath()); + InputStream in = context.getResourceAsStream(configTemplate); + if (in == null) { + in = getClass().getResourceAsStream(configTemplate); + } + OutputStream out = new FileOutputStream(dest); + byte[] buffer = new byte[8192]; + int read; + while ((read = in.read(buffer)) >= 0) { + out.write(buffer, 0, read); + } + in.close(); + out.close(); + } + + /** + * Installs the bootstrap config file from the template + * @param dest the destination location + * @param repHome the repository home location + * @param repXml the repository xml location + * @throws IOException if an I/O error occurs + */ + private void installBootstrap(File dest, String repHome, String repXml) + throws IOException { + log.info("Creating new bootstrap properties: {}", dest.getPath()); + InputStream in = context.getResourceAsStream(bootstrapTemplate); + Properties props = new Properties(); + props.load(in); + props.setProperty("repository.home", repHome); + if (repXml != null) { + props.setProperty("repository.config", repXml); + } + in.close(); + if (!dest.getParentFile().exists()) { + dest.getParentFile().mkdirs(); + } + OutputStream out = new FileOutputStream(dest); + props.store(out, "bootstrap properties for the repository startup servlet."); + out.close(); + } + +} Property changes on: jackrabbit-webapp-project/jackrabbit-webapp/src/main/java/org/apache/jackrabbit/j2ee/Installer.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 rev \ No newline at end of property Index: jackrabbit-webapp-project/jackrabbit-webapp/src/main/java/org/apache/jackrabbit/j2ee/JCRWebdavServerServlet.java =================================================================== --- jackrabbit-webapp-project/jackrabbit-webapp/src/main/java/org/apache/jackrabbit/j2ee/JCRWebdavServerServlet.java (nonexistent) +++ jackrabbit-webapp-project/jackrabbit-webapp/src/main/java/org/apache/jackrabbit/j2ee/JCRWebdavServerServlet.java (working copy) @@ -0,0 +1,36 @@ +/* + * 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.j2ee; + +import javax.jcr.Repository; + +/** + * JCRWebdavServerServlet provides request/response handling for the + * JCRWebdavServer. + */ +public class JCRWebdavServerServlet extends + org.apache.jackrabbit.webdav.jcr.JCRWebdavServerServlet { + + /** + * Returns the repository available from the servlet context of this + * servlet. + */ + protected Repository getRepository() { + return RepositoryAccessServlet.getRepository(getServletContext()); + } + +} Property changes on: jackrabbit-webapp-project/jackrabbit-webapp/src/main/java/org/apache/jackrabbit/j2ee/JCRWebdavServerServlet.java ___________________________________________________________________ Added: svn Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webapp-project/jackrabbit-webapp/src/main/java/org/apache/jackrabbit/j2ee/JNDIConfig.java =================================================================== --- jackrabbit-webapp-project/jackrabbit-webapp/src/main/java/org/apache/jackrabbit/j2ee/JNDIConfig.java (nonexistent) +++ jackrabbit-webapp-project/jackrabbit-webapp/src/main/java/org/apache/jackrabbit/j2ee/JNDIConfig.java (working copy) @@ -0,0 +1,112 @@ +/* + * 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.j2ee; + +import java.util.Enumeration; +import java.util.Iterator; +import java.util.Properties; + +import javax.servlet.ServletConfig; +import javax.servlet.ServletException; + +/** + * The JNDI config hold information about JNDI connection details. + * + * It supports the following properties and init parameters: + *
+ * +-------------------+--------------------+
+ * | Property Name     | Init-Param Name    |
+ * +-------------------+--------------------+
+ * | jndi.enable       | {provider spec.}   |
+ * | java.naming.*     | java.naming.*      |
+ * +-------------------+--------------------+
+ * 
+ */ +public class JNDIConfig extends AbstractConfig { + + private boolean jndiEnabled; + + private String jndiName; + + private final BootstrapConfig parentConfig; + + private Properties jndiEnv = new Properties(); + + + public JNDIConfig(BootstrapConfig parentConfig) { + this.parentConfig = parentConfig; + } + + + public String getJndiName() { + return jndiName; + } + + public void setJndiName(String jndiName) { + this.jndiName = jndiName; + } + + public boolean enabled() { + return jndiEnabled; + } + + public String getJndiEnabled() { + return String.valueOf(jndiEnabled); + } + + public void setJndiEnabled(String jndiEnabled) { + this.jndiEnabled = Boolean.valueOf(jndiEnabled).booleanValue(); + } + + public Properties getJndiEnv() { + return jndiEnv; + } + + public void init(Properties props) throws ServletException { + super.init(props); + // add all props whose name starts with 'java.namming.' to the env + Iterator iter = props.keySet().iterator(); + while (iter.hasNext()) { + String name = (String) iter.next(); + if (name.startsWith("java.naming.")) { + jndiEnv.put(name, props.getProperty(name)); + } + } + } + + public void init(ServletConfig ctx) throws ServletException { + super.init(ctx); + // add all params whose name starts with 'java.namming.' to the env + Enumeration names = ctx.getInitParameterNames(); + while (names.hasMoreElements()) { + String name = (String) names.nextElement(); + if (name.startsWith("java.naming.")) { + jndiEnv.put(name, ctx.getInitParameter(name)); + } + } + // enable jndi if url is specified + jndiEnabled = jndiEnv.containsKey("java.naming.provider.url"); + } + + + public void validate() { + if (jndiName == null) { + jndiName = parentConfig.getRepositoryName(); + } + valid = true; + } +} \ No newline at end of file Property changes on: jackrabbit-webapp-project/jackrabbit-webapp/src/main/java/org/apache/jackrabbit/j2ee/JNDIConfig.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 rev \ No newline at end of property Index: jackrabbit-webapp-project/jackrabbit-webapp/src/main/java/org/apache/jackrabbit/j2ee/JcrApiNotFoundException.java =================================================================== --- jackrabbit-webapp-project/jackrabbit-webapp/src/main/java/org/apache/jackrabbit/j2ee/JcrApiNotFoundException.java (nonexistent) +++ jackrabbit-webapp-project/jackrabbit-webapp/src/main/java/org/apache/jackrabbit/j2ee/JcrApiNotFoundException.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.j2ee; + +/** + * Exception for signaling that the JCR API is not available. + */ +public class JcrApiNotFoundException extends ServletExceptionWithCause { + + /** + * Serial version UID + */ + private static final long serialVersionUID = -6439777923943394980L; + + /** + * Creates an exception to signal that the JCR API is not available. + * + * @param e the specific exception that indicates the lack of the JCR API + */ + public JcrApiNotFoundException(ClassNotFoundException e) { + super("JCR API (jcr-1.0.jar) not available in the classpath", e); + } + +} Property changes on: jackrabbit-webapp-project/jackrabbit-webapp/src/main/java/org/apache/jackrabbit/j2ee/JcrApiNotFoundException.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webapp-project/jackrabbit-webapp/src/main/java/org/apache/jackrabbit/j2ee/JcrRemotingServlet.java =================================================================== --- jackrabbit-webapp-project/jackrabbit-webapp/src/main/java/org/apache/jackrabbit/j2ee/JcrRemotingServlet.java (nonexistent) +++ jackrabbit-webapp-project/jackrabbit-webapp/src/main/java/org/apache/jackrabbit/j2ee/JcrRemotingServlet.java (working copy) @@ -0,0 +1,33 @@ +/* + * 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.j2ee; + +import javax.jcr.Repository; + +/** + * JcrRemotingServlet... + */ +public class JcrRemotingServlet extends org.apache.jackrabbit.server.remoting.davex.JcrRemotingServlet { + + /** + * Returns the repository available from the servlet context of this + * servlet. + */ + protected Repository getRepository() { + return RepositoryAccessServlet.getRepository(getServletContext()); + } +} \ No newline at end of file Property changes on: jackrabbit-webapp-project/jackrabbit-webapp/src/main/java/org/apache/jackrabbit/j2ee/JcrRemotingServlet.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-webapp-project/jackrabbit-webapp/src/main/java/org/apache/jackrabbit/j2ee/RMIConfig.java =================================================================== --- jackrabbit-webapp-project/jackrabbit-webapp/src/main/java/org/apache/jackrabbit/j2ee/RMIConfig.java (nonexistent) +++ jackrabbit-webapp-project/jackrabbit-webapp/src/main/java/org/apache/jackrabbit/j2ee/RMIConfig.java (working copy) @@ -0,0 +1,175 @@ +/* + * 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.j2ee; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.net.URI; +import java.net.URISyntaxException; +import java.rmi.registry.Registry; + +import javax.servlet.ServletConfig; +import javax.servlet.ServletException; + +/** + * The RMI config hold information about RMI connection details. + * + * It supports the following properties and init parameters: + *
+ * +-------------------+--------------------+
+ * | Property Name     | Init-Param Name    |
+ * +-------------------+--------------------+
+ * | rmi.enable        | {rmi-port sepc.}   |
+ * | rmi.host          | rmi-host           |
+ * | rmi.port          | rmi-port           |
+ * | rmi.name          | {repository name}  |
+ * | rmi.url           | rmi-url            |
+ * +-------------------+--------------------+
+ * 
+ */ +public class RMIConfig extends AbstractConfig { + + /** + * default logger + */ + private static final Logger log = LoggerFactory.getLogger(RMIConfig.class); + + private boolean rmiEnabled; + + private int rmiPort = -1; + + private String rmiHost; + + private String rmiName; + + private String rmiUri; + + private final BootstrapConfig parentConfig; + + + public RMIConfig(BootstrapConfig parentConfig) { + this.parentConfig = parentConfig; + } + + public void init(ServletConfig ctx) throws ServletException { + super.init(ctx); + // enable RMI if either port or url was defined + rmiEnabled = rmiPort >=0 || rmiUri != null; + } + + public String getRmiName() { + return rmiName; + } + + public void setRmiName(String rmiName) { + this.rmiName = rmiName; + } + + public boolean enabled() { + return rmiEnabled; + } + + public String getRmiEnabled() { + return String.valueOf(rmiEnabled); + } + + public void setRmiEnabled(String rmiEnabled) { + this.rmiEnabled = Boolean.valueOf(rmiEnabled).booleanValue(); + } + + public int rmiPort() { + return rmiPort; + } + + public String getRmiPort() { + return String.valueOf(rmiPort); + } + + public void setRmiPort(String rmiPort) { + this.rmiPort = Integer.decode(rmiPort).intValue(); + } + + public String getRmiHost() { + return rmiHost; + } + + public void setRmiHost(String rmiHost) { + this.rmiHost = rmiHost; + } + + public String getRmiUri() { + return rmiUri; + } + + public void setRmiUri(String rmiUri) { + this.rmiUri = rmiUri; + } + + public void validate() { + if (!rmiEnabled) { + return; + } + + if (rmiUri != null && rmiUri.length() > 0) { + // URI takes precedences, so check whether the configuration has to + // be set from the URI + try { + URI uri = new URI(rmiUri); + + // extract values from the URI, check later + rmiHost = uri.getHost(); + rmiPort = uri.getPort(); + rmiName = uri.getPath(); + + } catch (URISyntaxException e) { + log.warn("Cannot parse RMI URI '" + rmiUri + "'.", e); + rmiUri = null; // clear RMI URI use another one + rmiHost = null; // use default host, ignore rmi-host param + } + + // cut of leading slash from name if defined at all + if (rmiName != null && rmiName.startsWith("/")) { + rmiName = rmiName.substring(1); + } + } + + // check RMI port + if (rmiPort == -1 || rmiPort == 0) { + // accept -1 or 0 as a hint to use the default + rmiPort = Registry.REGISTRY_PORT; + } else if (rmiPort < -1 || rmiPort > 0xFFFF) { + // emit a warning if out of range, use defualt in this case + log.warn("Invalid port in rmi-port param " + rmiPort + ". using default port."); + rmiPort = Registry.REGISTRY_PORT; + } + + // check host - use an empty name if null (i.e. not configured) + if (rmiHost == null) { + rmiHost = ""; + } + + // check name - use repositoryName if empty or null + if (rmiName == null || rmiName.length() ==0) { + rmiName = parentConfig.getRepositoryName(); + } + + // reconstruct the rmiURI now because values might have been changed + rmiUri = "//" + rmiHost + ":" + rmiPort + "/" + rmiName; + valid = true; + } +} \ No newline at end of file Property changes on: jackrabbit-webapp-project/jackrabbit-webapp/src/main/java/org/apache/jackrabbit/j2ee/RMIConfig.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 rev \ No newline at end of property Index: jackrabbit-webapp-project/jackrabbit-webapp/src/main/java/org/apache/jackrabbit/j2ee/RepositoryAccessServlet.java =================================================================== --- jackrabbit-webapp-project/jackrabbit-webapp/src/main/java/org/apache/jackrabbit/j2ee/RepositoryAccessServlet.java (nonexistent) +++ jackrabbit-webapp-project/jackrabbit-webapp/src/main/java/org/apache/jackrabbit/j2ee/RepositoryAccessServlet.java (working copy) @@ -0,0 +1,363 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.jackrabbit.j2ee; + +import org.apache.jackrabbit.rmi.client.ClientRepositoryFactory; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; +import java.net.MalformedURLException; +import java.rmi.NotBoundException; +import java.rmi.RemoteException; +import java.util.Properties; + +import javax.jcr.Repository; +import javax.naming.InitialContext; +import javax.naming.NamingException; +import javax.servlet.ServletContext; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServlet; + +/** + * This Class implements a servlet that is used as unified mechanism to retrieve + * a jcr repository either through JNDI or RMI. + */ +public class RepositoryAccessServlet extends HttpServlet { + + /** + * default logger + */ + private static final Logger log = LoggerFactory.getLogger(RepositoryAccessServlet.class); + + /** + * initial param name for the bootstrap config location + */ + public final static String INIT_PARAM_BOOTSTRAP_CONFIG = "bootstrap-config"; + + /** + * Context parameter name for 'this' instance. + */ + private final static String CTX_PARAM_THIS = "repository.access.servlet"; + + /** + * Ugly hack to override the bootstrap file location in the test cases + */ + static String bootstrapOverride = null; + + /** + * the bootstrap config + */ + private BootstrapConfig config; + + /** + * the initialized initial context + */ + private InitialContext jndiContext; + + /** + * if this is set we try to get a Repository from the ServletContext + */ + private String repositoryContextAttributeName; + + /** + * the repository + */ + private Repository repository; + + /** + * Initializes the servlet.
+ * Please note that only one repository startup servlet may exist per + * webapp. it registers itself as context attribute and acts as singleton. + * + * @throws ServletException if a same servlet is already registered or of + * another initialization error occurs. + */ + public void init() throws ServletException { + // check if servlet is defined twice + if (getServletContext().getAttribute(CTX_PARAM_THIS) != null) { + throw new ServletException("Only one repository access servlet allowed per web-app."); + } + getServletContext().setAttribute(CTX_PARAM_THIS, this); + + repositoryContextAttributeName = getServletConfig().getInitParameter("repository.context.attribute.name"); + + log.info("RepositoryAccessServlet initialized."); + } + + /** + * Returns the instance of this servlet + * @param ctx the servlet context + * @return this servlet + */ + public static RepositoryAccessServlet getInstance(ServletContext ctx) { + final RepositoryAccessServlet instance = (RepositoryAccessServlet) ctx.getAttribute(CTX_PARAM_THIS); + if(instance==null) { + throw new IllegalStateException( + "No RepositoryAccessServlet instance in ServletContext, RepositoryAccessServlet servlet not initialized?" + ); + } + return instance; + } + + /** + * Returns the bootstrap config + * @return the bootstrap config + * @throws ServletException if the config is not valid + */ + private BootstrapConfig getConfig() throws ServletException { + if (config == null) { + // check if there is a loadable bootstrap config + Properties bootstrapProps = new Properties(); + String bstrp = bootstrapOverride; + if (bstrp == null) { + bstrp = getServletConfig().getInitParameter(INIT_PARAM_BOOTSTRAP_CONFIG); + } + if (bstrp != null) { + // check if it's a web-resource + InputStream in = getServletContext().getResourceAsStream(bstrp); + if (in == null) { + // check if it's a file + File file = new File(bstrp); + if (file.canRead()) { + try { + in = new FileInputStream(file); + } catch (FileNotFoundException e) { + throw new ServletExceptionWithCause( + "Bootstrap configuration not found: " + bstrp, e); + } + } + } + if (in != null) { + try { + bootstrapProps.load(in); + } catch (IOException e) { + throw new ServletExceptionWithCause( + "Bootstrap configuration failure: " + bstrp, e); + } finally { + try { + in.close(); + } catch (IOException e) { + // ignore + } + } + } + } + + // read bootstrap config + BootstrapConfig tmpConfig = new BootstrapConfig(); + tmpConfig.init(getServletConfig()); + tmpConfig.init(bootstrapProps); + tmpConfig.validate(); + if (!tmpConfig.isValid()) { + throw new ServletException( + "Repository access configuration is not valid."); + } + tmpConfig.logInfos(); + config = tmpConfig; + } + return config; + } + + /** + * Returns the initial jndi context or null if the jndi access + * is not configured or erroous. + * @return the initial context or null + */ + private InitialContext getInitialContext() { + if (jndiContext == null && config.getJndiConfig().enabled()) { + // retrieve JNDI Context environment + try { + jndiContext = new InitialContext(config.getJndiConfig().getJndiEnv()); + } catch (NamingException e) { + log.error("Create initial context: " + e.toString()); + } + } + return jndiContext; + } + + /** + * Checks if the repository is available via JNDI and returns it. + * @return the repository or null + * @throws ServletException if this servlet is not properly configured. + */ + private Repository getRepositoryByJNDI() throws ServletException { + BootstrapConfig config = getConfig(); + if (!config.getJndiConfig().isValid() || !config.getJndiConfig().enabled()) { + return null; + } + // acquire via JNDI + String repositoryName = config.getRepositoryName(); + InitialContext ctx = getInitialContext(); + if (ctx == null) { + return null; + } + try { + Repository r = (Repository) ctx.lookup(repositoryName); + log.info("Acquired repository via JNDI."); + return r; + } catch (NamingException e) { + log.error("Error while retrieving repository using JNDI (name={})", repositoryName, e); + return null; + } + } + + /** + * Checks if the repository is available via RMI and returns it. + * @return the repository or null + * @throws ServletException if this servlet is not properly configured. + */ + private Repository getRepositoryByRMI() throws ServletException { + BootstrapConfig config = getConfig(); + if (!config.getRmiConfig().isValid() || !config.getRmiConfig().enabled()) { + return null; + } + + // acquire via RMI + String rmiURI = config.getRmiConfig().getRmiUri(); + if (rmiURI == null) { + return null; + } + log.info(" trying to retrieve repository using rmi. uri={}", rmiURI); + ClientFactoryDelegater cfd; + try { + Class clazz = Class.forName(getServerFactoryDelegaterClass()); + cfd = (ClientFactoryDelegater) clazz.newInstance(); + } catch (Throwable e) { + log.error("Unable to locate RMI ClientRepositoryFactory. Is jcr-rmi.jar missing?", e); + return null; + } + + try { + Repository r = cfd.getRepository(rmiURI); + log.info("Acquired repository via RMI."); + return r; + } catch (Exception e) { + log.error("Error while retrieving repository using RMI: {}", rmiURI, e); + return null; + } + } + + /** + * If our config said so, try to retrieve a Repository from the ServletContext + */ + protected Repository getRepositoryByContextAttribute() { + Repository result = null; + if(repositoryContextAttributeName!=null) { + result = (Repository)getServletContext().getAttribute(repositoryContextAttributeName); + + if(log.isDebugEnabled()) { + if(result!=null) { + log.debug("Got Repository from ServletContext attribute '{}'", repositoryContextAttributeName); + } else { + log.debug("ServletContext attribute '{}' does not provide a Repository", repositoryContextAttributeName); + } + } + } + return result; + } + + /** + * Return the fully qualified name of the class providing the client + * repository. The class whose name is returned must implement the + * {@link ClientFactoryDelegater} interface. + * + * @return the qfn of the factory class. + */ + protected String getServerFactoryDelegaterClass() { + return getClass().getName() + "$RMIClientFactoryDelegater"; + } + + /** + * Returns the JCR repository + * + * @return a JCR repository + * @throws IllegalStateException if the repository is not available in the context. + */ + public Repository getRepository() { + try { + if (repository == null) { + // try to get via context attribute + repository = getRepositoryByContextAttribute(); + } + if (repository == null) { + // try to retrieve via jndi + repository = getRepositoryByJNDI(); + } + if (repository == null) { + // try to get via rmi + repository = getRepositoryByRMI(); + } + if (repository == null) { + throw new ServletException("N/A"); + } + return repository; + } catch (ServletException e) { + throw new IllegalStateException( + "The repository is not available. Please check" + + " RepositoryAccessServlet configuration in web.xml.", e); + } + } + + /** + * Returns the JCR repository + * + * @param ctx the servlet context + * @return a JCR repository + * @throws IllegalStateException if the repository is not available in the context. + */ + public static Repository getRepository(ServletContext ctx) { + return getInstance(ctx).getRepository(); + } + + /** + * Returns the config that was used to bootstrap this servlet. + * @return the bootstrap config or null. + */ + public BootstrapConfig getBootstrapConfig() { + return config; + } + + /** + * optional class for RMI, will only be used, if RMI client is present + */ + protected static abstract class ClientFactoryDelegater { + + public abstract Repository getRepository(String uri) + throws RemoteException, MalformedURLException, NotBoundException; + } + + /** + * optional class for RMI, will only be used, if RMI server is present + */ + protected static class RMIClientFactoryDelegater extends ClientFactoryDelegater { + + // only used to enforce linking upon Class.forName() + static String FactoryClassName = ClientRepositoryFactory.class.getName(); + + public Repository getRepository(String uri) + throws MalformedURLException, NotBoundException, RemoteException { + System.setProperty("java.rmi.server.useCodebaseOnly", "true"); + return new ClientRepositoryFactory().getRepository(uri); + } + } +} + Property changes on: jackrabbit-webapp-project/jackrabbit-webapp/src/main/java/org/apache/jackrabbit/j2ee/RepositoryAccessServlet.java ___________________________________________________________________ Added: svn Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webapp-project/jackrabbit-webapp/src/main/java/org/apache/jackrabbit/j2ee/RepositoryStartupServlet.java =================================================================== --- jackrabbit-webapp-project/jackrabbit-webapp/src/main/java/org/apache/jackrabbit/j2ee/RepositoryStartupServlet.java (nonexistent) +++ jackrabbit-webapp-project/jackrabbit-webapp/src/main/java/org/apache/jackrabbit/j2ee/RepositoryStartupServlet.java (working copy) @@ -0,0 +1,767 @@ +/* + * 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.j2ee; + +import org.apache.jackrabbit.api.JackrabbitRepository; +import org.apache.jackrabbit.commons.repository.RepositoryFactory; +import org.apache.jackrabbit.core.RepositoryImpl; +import org.apache.jackrabbit.core.config.RepositoryConfig; +import org.apache.jackrabbit.rmi.server.RemoteAdapterFactory; +import org.apache.jackrabbit.rmi.server.ServerAdapterFactory; +import org.apache.jackrabbit.servlet.AbstractRepositoryServlet; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.xml.sax.InputSource; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; +import java.net.InetAddress; +import java.net.ServerSocket; +import java.net.UnknownHostException; +import java.rmi.AlreadyBoundException; +import java.rmi.Naming; +import java.rmi.NoSuchObjectException; +import java.rmi.Remote; +import java.rmi.RemoteException; +import java.rmi.registry.LocateRegistry; +import java.rmi.registry.Registry; +import java.rmi.server.RMIServerSocketFactory; +import java.rmi.server.UnicastRemoteObject; +import java.util.Properties; + +import javax.jcr.Repository; +import javax.jcr.RepositoryException; +import javax.naming.InitialContext; +import javax.naming.NamingException; +import javax.servlet.ServletContext; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +/** + * The RepositoryStartupServlet starts a jackrabbit repository and registers it + * to the JNDI environment and optional to the RMI registry. + *

+ * Registration with RMI + *

+ * Upon successfull creation of the repository in the {@link #init()} method, + * the repository is registered with an RMI registry if the web application is + * so configured. To register with RMI, the following web application + * init-params are considered: rmi-port designating + * the port on which the RMI registry is listening, rmi-host + * designating the interface on the local host on which the RMI registry is + * active, repository-name designating the name to which the + * repository is to be bound in the registry, and rmi-uri + * designating an RMI URI complete with host, optional port and name to which + * the object is bound. + *

+ * If the rmi-uri parameter is configured with a non-empty value, + * the rmi-port and rmi-host parameters are ignored. + * The repository-name parameter is only considered if a non-empty + * rmi-uri parameter is configured if the latter does not contain + * a name to which to bind the repository. + *

+ * This is the algorithm used to find out the host, port and name for RMI + * registration: + *

    + *
  1. If neither a rmi-uri nor a rmi-host nor a + * rmi-port parameter is configured, the repository is not + * registered with any RMI registry. + *
  2. If a non-empty rmi-uri parameter is configured extract the + * host name (or IP address), port number and name to bind to from the + * URI. If the URI is not valid, host defaults to 0.0.0.0 + * meaning all interfaces on the local host, port defaults to the RMI + * default port (1099) and the name defaults to the value + * of the repository-name parameter. + *
  3. If a non-empty rmi-uri is not configured, the host is taken + * from the rmi-host parameter, the port from the + * rmi-port parameter and the name to bind the repository to + * from the repository-name parameter. If the + * rmi-host parameter is empty or not configured, the host + * defaults to 0.0.0.0 meaning all interfaces on the local + * host. If the rmi-port parameter is empty, not configured, + * zero or a negative value, the default port for the RMI registry + * (1099) is used. + *
+ *

+ * After finding the host and port of the registry, the RMI registry itself + * is acquired. It is assumed, that host and port primarily designate an RMI + * registry, which should be active on the local host but has not been started + * yet. In this case, the LocateRegistry.createRegistry method is + * called to create a registry on the local host listening on the host and port + * configured. If creation fails, the LocateRegistry.getRegistry + * method is called to get a remote instance of the registry. Note, that + * getRegistry does not create an actual registry on the given + * host/port nor does it check, whether an RMI registry is active. + *

+ * When the registry has been retrieved, either by creation or by just creating + * a remote instance, the repository is bound to the configured name in the + * registry. + *

+ * Possible causes for registration failures include: + *

    + *
  • The web application is not configured to register with an RMI registry at + * all. + *
  • The registry is expected to be running on a remote host but does not. + *
  • The registry is expected to be running on the local host but cannot be + * accessed. Reasons include another application which does not act as an + * RMI registry is running on the configured port and thus blocks creation + * of a new RMI registry. + *
  • An object may already be bound to the same name as is configured to be + * used for the repository. + *
+ *

+ * Note: if a bootstrap-config init parameter is specified the + * servlet tries to read the respective resource, either as context resource or + * as file. The properties specified in this file override the init params + * specified in the web.xml. + *

+ *

+ * Setup Wizard Functionality
+ * When using the first time, the configuration can miss the relevant + * repository parameters in the web.xml. if so, it must contain a + * bootstrap-config parameter that refers to a property file. + * This file must exist for proper working. If not, the repository is not + * started.
+ * If the servlet is not configured correctly and accessed via http, it will + * provide a simple wizard for the first time configuration. It prompts for + * a new (or existing) repository home and will copy the templates of the + * repository.xml and bootstrap.properties to the respective location. + */ +public class RepositoryStartupServlet extends AbstractRepositoryServlet { + + /** + * the default logger + */ + private static final Logger log = LoggerFactory.getLogger(RepositoryStartupServlet.class); + + /** + * the context attribute name foe 'this' instance. + */ + private final static String CTX_PARAM_THIS = "repository.startup.servet"; + + /** + * initial param name for the bootstrap config location + */ + public final static String INIT_PARAM_BOOTSTRAP_CONFIG = "bootstrap-config"; + + /** + * Ugly hack to override the bootstrap file location in the test cases + */ + static String bootstrapOverride = null; + + /** + * the registered repository + */ + private Repository repository; + + /** + * the jndi context; created based on configuration + */ + private InitialContext jndiContext; + + private Registry rmiRegistry = null; + + /** + * Keeps a strong reference to the server side RMI repository instance to + * prevent the RMI distributed Garbage Collector from collecting the + * instance making the repository unaccessible though it should still be. + * This field is only set to a non-null value, if registration + * of the repository to an RMI registry succeeded in the + * {@link #registerRMI()} method. + * + * @see #registerRMI() + * @see #unregisterRMI() + */ + private Remote rmiRepository; + + /** + * the file to the bootstrap config + */ + private File bootstrapConfigFile; + + /** + * The bootstrap configuration + */ + private BootstrapConfig config; + + /** + * Initializes the servlet.
+ * Please note that only one repository startup servlet may exist per + * webapp. it registers itself as context attribute and acts as singleton. + * + * @throws ServletException if a same servlet is already registered or of + * another initialization error occurs. + */ + public void init() throws ServletException { + super.init(); + // check if servlet is defined twice + if (getServletContext().getAttribute(CTX_PARAM_THIS) != null) { + throw new ServletException("Only one repository startup servlet allowed per web-app."); + } + getServletContext().setAttribute(CTX_PARAM_THIS, this); + startup(); + } + + /** + * Returns an instance of this servlet. Please note, that only 1 + * repository startup servlet can exist per webapp. + * + * @param context the servlet context + * @return this servlet + */ + public static RepositoryStartupServlet getInstance(ServletContext context) { + return (RepositoryStartupServlet) context.getAttribute(CTX_PARAM_THIS); + } + + /** + * Configures and starts the repository. It registers it then to the + * RMI registry and bind is to the JNDI context if so configured. + * @throws ServletException if an error occurs. + */ + public void startup() throws ServletException { + if (repository != null) { + log.error("Startup: Repository already running."); + throw new ServletException("Repository already running."); + } + log.info("RepositoryStartupServlet initializing..."); + try { + if (configure()) { + initRepository(); + registerRMI(); + registerJNDI(); + } + log.info("RepositoryStartupServlet initialized."); + } catch (ServletException e) { + // shutdown repository + shutdownRepository(); + log.error("RepositoryStartupServlet initializing failed: " + e, e); + } + } + + /** + * Does a shutdown of the repository and deregisters it from the RMI + * registry and unbinds if from the JNDI context if so configured. + */ + public void shutdown() { + if (repository == null) { + log.info("Shutdown: Repository already stopped."); + } else { + log.info("RepositoryStartupServlet shutting down..."); + shutdownRepository(); + unregisterRMI(); + unregisterJNDI(); + log.info("RepositoryStartupServlet shut down."); + } + } + + /** + * Restarts the repository. + * @throws ServletException if an error occurs. + * @see #shutdown() + * @see #startup() + */ + public void restart() throws ServletException { + if (repository != null) { + shutdown(); + } + startup(); + } + + /** + * destroy the servlet + */ + public void destroy() { + super.destroy(); + shutdown(); + } + + /** + * Returns the started repository or null if not started + * yet. + * @return the JCR repository + */ + public Repository getRepository() { + return repository; + } + + /** + * Returns a repository factory that returns the repository if available + * or throws an exception if not. + * + * @return repository factory + */ + public RepositoryFactory getRepositoryFactory() { + return new RepositoryFactory() { + public Repository getRepository() throws RepositoryException { + Repository r = repository; + if (r != null) { + return repository; + } else { + throw new RepositoryException("Repository not available"); + } + } + }; + } + + /** + * Reads the configuration and initializes the {@link #config} field if + * successful. + * @throws ServletException if an error occurs. + */ + private boolean configure() throws ServletException { + // check if there is a loadable bootstrap config + Properties bootstrapProps = new Properties(); + String bstrp = bootstrapOverride; + if (bstrp == null) { + bstrp = getServletConfig().getInitParameter(INIT_PARAM_BOOTSTRAP_CONFIG); + } + if (bstrp != null) { + // check if it's a web-resource + InputStream in = getServletContext().getResourceAsStream(bstrp); + if (in == null) { + // check if it's a file + bootstrapConfigFile = new File(bstrp); + if (bootstrapConfigFile.canRead()) { + try { + in = new FileInputStream(bootstrapConfigFile); + } catch (FileNotFoundException e) { + throw new ServletExceptionWithCause( + "Bootstrap configuration not found: " + bstrp, e); + } + } + } + if (in != null) { + try { + bootstrapProps.load(in); + } catch (IOException e) { + throw new ServletException( + "Bootstrap configuration failure: " + bstrp, e); + } finally { + try { + in.close(); + } catch (IOException e) { + // ignore + } + } + } + } + + // read bootstrap config + config = new BootstrapConfig(); + config.init(getServletConfig()); + config.init(bootstrapProps); + config.validate(); + if (!config.isValid() + || config.getRepositoryHome() == null) { + if (bstrp == null) { + log.error("Repository startup configuration is not valid."); + } else { + log.error("Repository startup configuration is not valid but a bootstrap config is specified."); + log.error("Either create the {} file or", bstrp); + log.error("use the '/config/index.jsp' for easy configuration."); + } + return false; + } else { + config.logInfos(); + return true; + } + } + + /** + * Creates a new Repository based on the configuration and initializes the + * {@link #repository} field if successful. + * + * @throws ServletException if an error occurs + */ + private void initRepository() throws ServletException { + // get repository config + File repHome; + try { + repHome = new File(config.getRepositoryHome()).getCanonicalFile(); + } catch (IOException e) { + throw new ServletExceptionWithCause( + "Repository configuration failure: " + config.getRepositoryHome(), e); + } + String repConfig = config.getRepositoryConfig(); + if (repConfig != null) { + InputStream in = getServletContext().getResourceAsStream(repConfig); + if (in == null) { + try { + in = new FileInputStream(new File(repConfig)); + } catch (FileNotFoundException e) { + // fallback to old config + try { + in = new FileInputStream(new File(repHome, repConfig)); + } catch (FileNotFoundException e1) { + throw new ServletExceptionWithCause( + "Repository configuration not found: " + repConfig, e); + } + } + } + + try { + repository = createRepository(new InputSource(in), repHome); + } catch (RepositoryException e) { + throw new ServletExceptionWithCause("Error while creating repository", e); + } + } else { + throw new ServletException("Missing configuration"); + } + } + + /** + * Shuts down the repository. If the repository is an instanceof + * {@link JackrabbitRepository} it's {@link JackrabbitRepository#shutdown()} + * method is called. in any case, the {@link #repository} field is + * nulled. + */ + private void shutdownRepository() { + if (repository instanceof JackrabbitRepository) { + ((JackrabbitRepository) repository).shutdown(); + } + repository = null; + } + + /** + * Creates the repository instance for the given config and homedir. + * Subclasses may override this method of providing own implementations of + * a {@link Repository}. + * + * @param is input source of the repository config + * @param homedir the repository home directory + * @return a new jcr repository. + * @throws RepositoryException if an error during creation occurs. + */ + protected Repository createRepository(InputSource is, File homedir) + throws RepositoryException { + RepositoryConfig config = RepositoryConfig.create(is, homedir.getAbsolutePath()); + return RepositoryImpl.create(config); + } + + /** + * Binds the repository to the JNDI context + * @throws ServletException if an error occurs. + */ + private void registerJNDI() throws ServletException { + JNDIConfig jc = config.getJndiConfig(); + if (jc.isValid() && jc.enabled()) { + try { + jndiContext = new InitialContext(jc.getJndiEnv()); + jndiContext.bind(jc.getJndiName(), repository); + log.info("Repository bound to JNDI with name: " + jc.getJndiName()); + } catch (NamingException e) { + throw new ServletExceptionWithCause( + "Unable to bind repository using JNDI: " + jc.getJndiName(), e); + } + } + } + + /** + * Unbinds the repository from the JNDI context. + */ + private void unregisterJNDI() { + if (jndiContext != null) { + try { + jndiContext.unbind(config.getJndiConfig().getJndiName()); + } catch (NamingException e) { + log("Error while unbinding repository from JNDI: " + e); + } + } + } + + /** + * Registers the repository to an RMI registry configured in the web + * application. See Registration with RMI in the + * class documentation for a description of the algorithms used to register + * the repository with an RMI registry. + * @throws ServletException if an error occurs. + */ + private void registerRMI() { + RMIConfig rc = config.getRmiConfig(); + if (!rc.isValid() || !rc.enabled()) { + return; + } + + // try to create remote repository + Remote remote; + try { + Class clazz = Class.forName(getRemoteFactoryDelegaterClass()); + RemoteFactoryDelegater rmf = (RemoteFactoryDelegater) clazz.newInstance(); + remote = rmf.createRemoteRepository(repository); + } catch (RemoteException e) { + log.warn("Unable to create RMI repository.", e); + return; + } catch (Throwable t) { + log.warn("Unable to create RMI repository." + + " The jcr-rmi jar might be missing.", t); + return; + } + + try { + System.setProperty("java.rmi.server.useCodebaseOnly", "true"); + Registry reg = null; + + // first try to create the registry, which will fail if another + // application is already running on the configured host/port + // or if the rmiHost is not local + try { + // find the server socket factory: use the default if the + // rmiHost is not configured + RMIServerSocketFactory sf; + if (rc.getRmiHost().length() > 0) { + log.debug("Creating RMIServerSocketFactory for host " + rc.getRmiHost()); + InetAddress hostAddress = InetAddress.getByName(rc.getRmiHost()); + sf = getRMIServerSocketFactory(hostAddress); + } else { + // have the RMI implementation decide which factory is the + // default actually + log.debug("Using default RMIServerSocketFactory"); + sf = null; + } + + // create a registry using the default client socket factory + // and the server socket factory retrieved above. This also + // binds to the server socket to the rmiHost:rmiPort. + reg = LocateRegistry.createRegistry(rc.rmiPort(), null, sf); + rmiRegistry = reg; + } catch (UnknownHostException uhe) { + // thrown if the rmiHost cannot be resolved into an IP-Address + // by getRMIServerSocketFactory + log.info("Cannot create Registry", uhe); + } catch (RemoteException e) { + // thrown by createRegistry if binding to the rmiHost:rmiPort + // fails, for example due to rmiHost being remote or another + // application already being bound to the port + log.info("Cannot create Registry", e); + } + + // if creation of the registry failed, we try to access an + // potentially active registry. We do not check yet, whether the + // registry is actually accessible. + if (reg == null) { + log.debug("Trying to access existing registry at " + rc.getRmiHost() + + ":" + rc.getRmiPort()); + try { + reg = LocateRegistry.getRegistry(rc.getRmiHost(), rc.rmiPort()); + } catch (RemoteException re) { + log.warn("Cannot create the reference to the registry at " + + rc.getRmiHost() + ":" + rc.getRmiPort(), re); + } + } + + // if we finally have a registry, register the repository with the + // rmiName + if (reg != null) { + log.debug("Registering repository as " + rc.getRmiName() + + " to registry " + reg); + reg.bind(rc.getRmiName(), remote); + + // when successfull, keep references + this.rmiRepository = remote; + log.info("Repository bound via RMI with name: " + rc.getRmiUri()); + } else { + log.info("RMI registry missing, cannot bind repository via RMI"); + } + } catch (RemoteException e) { + log.warn("Unable to bind repository via RMI: " + rc.getRmiUri(), e); + } catch (AlreadyBoundException e) { + log.warn("Unable to bind repository via RMI: " + rc.getRmiUri(), e); + } + } + + /** + * Unregisters the repository from the RMI registry, if it has previously + * been registered. + */ + private void unregisterRMI() { + if (rmiRepository != null) { + // Forcibly unexport the repository; + try { + UnicastRemoteObject.unexportObject(rmiRepository, true); + } catch (NoSuchObjectException e) { + log.warn("Odd, the RMI repository was not exported", e); + } + // drop strong reference to remote repository + rmiRepository = null; + + // unregister repository + try { + Naming.unbind(config.getRmiConfig().getRmiUri()); + } catch (Exception e) { + log("Error while unbinding repository from JNDI: " + e); + } + } + + if (rmiRegistry != null) { + try { + UnicastRemoteObject.unexportObject(rmiRegistry, true); + } catch (NoSuchObjectException e) { + log.warn("Odd, the RMI registry was not exported", e); + } + rmiRegistry = null; + } + } + + /** + * Returns the config that was used to bootstrap this servlet. + * @return the bootstrap config or null. + */ + public BootstrapConfig getBootstrapConfig() { + return config; + } + + /** + * Return the fully qualified name of the class providing the remote + * repository. The class whose name is returned must implement the + * {@link RemoteFactoryDelegater} interface. + *

+ * Subclasses may override this method for providing a name of a own + * implementation. + * + * @return getClass().getName() + "$RMIRemoteFactoryDelegater" + */ + protected String getRemoteFactoryDelegaterClass() { + return getClass().getName() + "$RMIRemoteFactoryDelegater"; + } + + /** + * Returns an RMIServerSocketFactory used to create the server + * socket for a locally created RMI registry. + *

+ * This implementation returns a new instance of a simple + * RMIServerSocketFactory which just creates instances of + * the java.net.ServerSocket class bound to the given + * hostAddress. Implementations may overwrite this method to + * provide factory instances, which provide more elaborate server socket + * creation, such as SSL server sockets. + * + * @param hostAddress The InetAddress instance representing the + * the interface on the local host to which the server sockets are + * bound. + * @return A new instance of a simple RMIServerSocketFactory + * creating java.net.ServerSocket instances bound to + * the rmiHost. + */ + protected RMIServerSocketFactory getRMIServerSocketFactory( + final InetAddress hostAddress) { + return new RMIServerSocketFactory() { + public ServerSocket createServerSocket(int port) throws IOException { + return new ServerSocket(port, -1, hostAddress); + } + }; + } + + /** + * optional class for RMI, will only be used, if RMI server is present + */ + protected static abstract class RemoteFactoryDelegater { + + public abstract Remote createRemoteRepository(Repository repository) + throws RemoteException; + } + + /** + * optional class for RMI, will only be used, if RMI server is present + */ + protected static class RMIRemoteFactoryDelegater extends RemoteFactoryDelegater { + + private static final RemoteAdapterFactory FACTORY = + new ServerAdapterFactory(); + + public Remote createRemoteRepository(Repository repository) + throws RemoteException { + return FACTORY.getRemoteRepository(repository); + } + + } + + //-------------------------------------------------< Installer Routines >--- + + /** + * {@inheritDoc} + */ + protected void doGet(HttpServletRequest req, HttpServletResponse resp) + throws ServletException, IOException { + if (repository == null) { + redirect(req, resp, "/bootstrap/missing.jsp"); + } else { + redirect(req, resp, "/bootstrap/running.jsp"); + } + } + + /** + * {@inheritDoc} + */ + protected void doPost(HttpServletRequest req, HttpServletResponse resp) + throws ServletException, IOException { + if (repository != null) { + redirect(req, resp, "/bootstrap/reconfigure.jsp"); + } else { + int rc = new Installer(bootstrapConfigFile, + getServletContext()).installRepository(req); + switch (rc) { + case Installer.C_INSTALL_OK: + // restart rep + restart(); + if (repository == null) { + redirect(req, resp, "/bootstrap/error.jsp"); + } else { + redirect(req, resp, "/bootstrap/success.jsp"); + } + break; + case Installer.C_INVALID_INPUT: + redirect(req, resp, "/bootstrap/missing.jsp"); + break; + case Installer.C_CONFIG_EXISTS: + case Installer.C_BOOTSTRAP_EXISTS: + case Installer.C_HOME_EXISTS: + redirect(req, resp, "/bootstrap/exists.jsp"); + break; + case Installer. C_HOME_MISSING: + case Installer.C_CONFIG_MISSING: + redirect(req, resp, "/bootstrap/notexists.jsp"); + break; + case Installer.C_INSTALL_ERROR: + redirect(req, resp, "/bootstrap/error.jsp"); + break; + } + } + } + + /** + * Helper function to send a redirect response respecting the context path. + * + * @param req the request + * @param resp the response + * @param loc the location for the redirect + * @throws IOException if an I/O error occurs. + */ + private void redirect(HttpServletRequest req, + HttpServletResponse resp, String loc) + throws IOException { + String cp = req.getContextPath(); + if (cp == null || cp.equals("/")) { + cp = ""; + } + resp.sendRedirect(cp + loc); + } +} + Property changes on: jackrabbit-webapp-project/jackrabbit-webapp/src/main/java/org/apache/jackrabbit/j2ee/RepositoryStartupServlet.java ___________________________________________________________________ Added: svn Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webapp-project/jackrabbit-webapp/src/main/java/org/apache/jackrabbit/j2ee/ServletExceptionWithCause.java =================================================================== --- jackrabbit-webapp-project/jackrabbit-webapp/src/main/java/org/apache/jackrabbit/j2ee/ServletExceptionWithCause.java (nonexistent) +++ jackrabbit-webapp-project/jackrabbit-webapp/src/main/java/org/apache/jackrabbit/j2ee/ServletExceptionWithCause.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.j2ee; + +import javax.servlet.ServletException; + +/** + * Utility class that links {@link ServletException} with support for + * the exception chaining mechanism in {@link Throwable}. + * + * @see JCR-1598 + */ +public class ServletExceptionWithCause extends ServletException { + + /** + * Serial version UID + */ + private static final long serialVersionUID = -7201954529718775444L; + + /** + * Creates a servlet exception with the given message and cause. + * + * @param message exception message + * @param cause cause of the exception + */ + public ServletExceptionWithCause(String message, Throwable cause) { + super(message, cause); + if (getCause() == null) { + initCause(cause); + } + } + +} Property changes on: jackrabbit-webapp-project/jackrabbit-webapp/src/main/java/org/apache/jackrabbit/j2ee/ServletExceptionWithCause.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webapp-project/jackrabbit-webapp/src/main/java/org/apache/jackrabbit/j2ee/SimpleWebdavServlet.java =================================================================== --- jackrabbit-webapp-project/jackrabbit-webapp/src/main/java/org/apache/jackrabbit/j2ee/SimpleWebdavServlet.java (nonexistent) +++ jackrabbit-webapp-project/jackrabbit-webapp/src/main/java/org/apache/jackrabbit/j2ee/SimpleWebdavServlet.java (working copy) @@ -0,0 +1,55 @@ +/* + * 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.j2ee; + +import javax.jcr.Repository; + +/** + * WebdavServlet provides webdav support (level 1 and 2 complient) for repository + * resources. + */ +public class SimpleWebdavServlet extends org.apache.jackrabbit.webdav.simple.SimpleWebdavServlet { + + /** + * the jcr repository + */ + private Repository repository; + + /** + * Returns the Repository. If no repository has been set or + * created the repository initialized by RepositoryAccessServlet + * is returned. + * + * @return repository + * @see RepositoryAccessServlet#getRepository(ServletContext) + */ + public Repository getRepository() { + if (repository == null) { + repository = RepositoryAccessServlet.getRepository(getServletContext()); + } + return repository; + } + + /** + * Sets the Repository. + * + * @param repository + */ + public void setRepository(Repository repository) { + this.repository = repository; + } +} Property changes on: jackrabbit-webapp-project/jackrabbit-webapp/src/main/java/org/apache/jackrabbit/j2ee/SimpleWebdavServlet.java ___________________________________________________________________ Added: svn Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webapp-project/jackrabbit-webapp/src/main/resources/logback.xml =================================================================== --- jackrabbit-webapp-project/jackrabbit-webapp/src/main/resources/logback.xml (nonexistent) +++ jackrabbit-webapp-project/jackrabbit-webapp/src/main/resources/logback.xml (working copy) @@ -0,0 +1,30 @@ + + + + + + + %d{yyyy-MM-dd HH:mm:ss.SSS} %-5level %-40([%thread] %F:%L) %msg%n + + + + + + + + Property changes on: jackrabbit-webapp-project/jackrabbit-webapp/src/main/resources/logback.xml ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/META-INF/LICENSE =================================================================== --- jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/META-INF/LICENSE (nonexistent) +++ jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/META-INF/LICENSE (working copy) @@ -0,0 +1,1625 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed 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. + + +APACHE JACKRABBIT SUBCOMPONENTS + +Apache Jackrabbit includes parts with separate copyright notices and license +terms. Your use of these subcomponents is subject to the terms and conditions +of the following licenses: + +XPath parser (jackrabbit-spi-commons) + + XPath 2.0/XQuery 1.0 Parser: + http://www.w3.org/2002/11/xquery-xpath-applets/xgrammar.zip + + Copyright (C) 2002 World Wide Web Consortium, (Massachusetts Institute of + Technology, European Research Consortium for Informatics and Mathematics, + Keio University). All Rights Reserved. + + This work is distributed under the W3C(R) Software License in the hope + that it will be useful, but WITHOUT ANY WARRANTY; without even the + implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + W3C(R) SOFTWARE NOTICE AND LICENSE + http://www.w3.org/Consortium/Legal/2002/copyright-software-20021231 + + This work (and included software, documentation such as READMEs, or + other related items) is being provided by the copyright holders under + the following license. By obtaining, using and/or copying this work, + you (the licensee) agree that you have read, understood, and will comply + with the following terms and conditions. + + Permission to copy, modify, and distribute this software and its + documentation, with or without modification, for any purpose and + without fee or royalty is hereby granted, provided that you include + the following on ALL copies of the software and documentation or + portions thereof, including modifications: + + 1. The full text of this NOTICE in a location viewable to users + of the redistributed or derivative work. + + 2. Any pre-existing intellectual property disclaimers, notices, + or terms and conditions. If none exist, the W3C Software Short + Notice should be included (hypertext is preferred, text is + permitted) within the body of any redistributed or derivative code. + + 3. Notice of any changes or modifications to the files, including + the date changes were made. (We recommend you provide URIs to the + location from which the code is derived.) + + THIS SOFTWARE AND DOCUMENTATION IS PROVIDED "AS IS," AND COPYRIGHT + HOLDERS MAKE NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, + INCLUDING BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS + FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF THE SOFTWARE OR + DOCUMENTATION WILL NOT INFRINGE ANY THIRD PARTY PATENTS, COPYRIGHTS, + TRADEMARKS OR OTHER RIGHTS. + + COPYRIGHT HOLDERS WILL NOT BE LIABLE FOR ANY DIRECT, INDIRECT, SPECIAL + OR CONSEQUENTIAL DAMAGES ARISING OUT OF ANY USE OF THE SOFTWARE OR + DOCUMENTATION. + + The name and trademarks of copyright holders may NOT be used in + advertising or publicity pertaining to the software without specific, + written prior permission. Title to copyright in this software and + any associated documentation will at all times remain with + copyright holders. + +PDFBox libraries (pdfbox, jempbox, fontbox) + + Copyright (c) 2002-2007, www.pdfbox.org + Copyright (c) 2006-2007, www.jempbox.org + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 3. Neither the name of pdfbox; nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. + +Adobe Font Metrics (AFM) for PDF Core 14 Fonts + + This file and the 14 PostScript(R) AFM files it accompanies may be used, + copied, and distributed for any purpose and without charge, with or without + modification, provided that all copyright notices are retained; that the + AFM files are not distributed without this file; that all modifications + to this file or any of the AFM files are prominently noted in the modified + file(s); and that this paragraph is not modified. Adobe Systems has no + responsibility or obligation to support the use of the AFM files. + +CMaps for PDF Fonts (http://www.adobe.com/devnet/font/#pcfi and +ftp://ftp.oreilly.com/pub/examples/nutshell/cjkv/adobe/) + + Copyright 1990-2001 Adobe Systems Incorporated. + All Rights Reserved. + + Patents Pending + + NOTICE: All information contained herein is the property + of Adobe Systems Incorporated. + + Permission is granted for redistribution of this file + provided this copyright notice is maintained intact and + that the contents of this file are not altered in any + way from its original form. + + PostScript and Display PostScript are trademarks of + Adobe Systems Incorporated which may be registered in + certain jurisdictions. + +Glyphlist (http://www.adobe.com/devnet/opentype/archives/glyph.html) + + Copyright (c) 1997,1998,2002,2007 Adobe Systems Incorporated + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this documentation file to use, copy, publish, distribute, + sublicense, and/or sell copies of the documentation, and to permit + others to do the same, provided that: + - No modification, editing or other alteration of this document is + allowed; and + - The above copyright notice and this permission notice shall be + included in all copies of the documentation. + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this documentation file, to create their own derivative works + from the content of this document to use, copy, publish, distribute, + sublicense, and/or sell the derivative works, and to permit others to do + the same, provided that the derived work is not represented as being a + copy or version of this document. + + Adobe shall not be liable to any party for any loss of revenue or profit + or for indirect, incidental, special, consequential, or other similar + damages, whether based on tort (including without limitation negligence + or strict liability), contract or other legal or equitable grounds even + if Adobe has been advised or had reason to know of the possibility of + such damages. The Adobe materials are provided on an "AS IS" basis. + Adobe specifically disclaims all express, statutory, or implied + warranties relating to the Adobe materials, including but not limited to + those concerning merchantability or fitness for a particular purpose or + non-infringement of any third party rights regarding the Adobe + materials. + +The International Components for Unicode (http://site.icu-project.org/) + + Copyright (c) 1995-2009 International Business Machines Corporation + and others + + All rights reserved. + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, and/or sell copies of the Software, and to permit persons + to whom the Software is furnished to do so, provided that the above + copyright notice(s) and this permission notice appear in all copies + of the Software and that both the above copyright notice(s) and this + permission notice appear in supporting documentation. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. + IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN THIS NOTICE + BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, + OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, + WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, + ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + SOFTWARE. + + Except as contained in this notice, the name of a copyright holder shall + not be used in advertising or otherwise to promote the sale, use or other + dealings in this Software without prior written authorization of the + copyright holder. + +MIME type information from file-4.26.tar.gz (http://www.darwinsys.com/file/) + + Copyright (c) Ian F. Darwin 1986, 1987, 1989, 1990, 1991, 1992, 1994, 1995. + Software written by Ian F. Darwin and others; + maintained 1994- Christos Zoulas. + + This software is not subject to any export provision of the United States + Department of Commerce, and may be exported to any country or planet. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice immediately at the beginning of the file, without modification, + this list of conditions, and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR + ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. + +Metadata extractor library (metadata-extractor) + + This is public domain software - that is, you can do whatever you want + with it, and include it software that is licensed under the GNU or the + BSD license, or whatever other licence you choose, including proprietary + closed source licenses. I do ask that you leave this header in tact. + + If you make modifications to this code that you think would benefit the + wider community, please send me a copy and I'll post it on my site. + + If you make use of this code, I'd appreciate hearing about it. + metadata_extractor [at] drewnoakes [dot] com + Latest version of this software kept at + http://drewnoakes.com/ + +ASM bytecode manipulation library (asm) + + Copyright (c) 2000-2005 INRIA, France Telecom + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 3. Neither the name of the copyright holders nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + THE POSSIBILITY OF SUCH DAMAGE. + +SLF4J libraries (slf4j-api, log4j-over-slf4j, jcl-over-slf4j) + + Copyright (c) 2004-2008 QOS.ch + All rights reserved. + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Logback library (logback-core, logback-classic) + + Logback: the reliable, generic, fast and flexible logging framework. + Copyright (C) 1999-2009, QOS.ch. All rights reserved. + + This program and the accompanying materials are dual-licensed under + either the terms of the Eclipse Public License v1.0 as published by + the Eclipse Foundation + + or (per the licensee's choosing) + + under the terms of the GNU Lesser General Public License version 2.1 + as published by the Free Software Foundation. + +XML API library, org.w3c classes (xml-apis) + + DOM Java Language Binding: + http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113/java-binding.html + + W3C IPR SOFTWARE NOTICE + Copyright (C) 2000 World Wide Web Consortium, (Massachusetts Institute of + Technology, Institut National de Recherche en Informatique et en + Automatique, Keio University). All Rights Reserved. + + The DOM bindings are published under the W3C Software Copyright Notice + and License. The software license requires "Notice of any changes or + modifications to the W3C files, including the date changes were made." + Consequently, modified versions of the DOM bindings must document that + they do not conform to the W3C standard; in the case of the IDL binding, + the pragma prefix can no longer be 'w3c.org'; in the case of the Java + binding, the package names can no longer be in the 'org.w3c' package. + + Note: The original version of the W3C Software Copyright Notice and + License could be found at + http://www.w3.org/Consortium/Legal/copyright-software-19980720 + + Copyright (C) 1994-2000 World Wide Web Consortium, (Massachusetts + Institute of Technology, Institut National de Recherche en Informatique + et en Automatique, Keio University). All Rights Reserved. + http://www.w3.org/Consortium/Legal/ + + This W3C work (including software, documents, or other related items) is + being provided by the copyright holders under the following license. By + obtaining, using and/or copying this work, you (the licensee) agree that + you have read, understood, and will comply with the following terms and + conditions: + + Permission to use, copy, and modify this software and its documentation, + with or without modification, for any purpose and without fee or royalty + is hereby granted, provided that you include the following on ALL copies + of the software and documentation or portions thereof, including + modifications, that you make: + + 1. The full text of this NOTICE in a location viewable to users of the + redistributed or derivative work. + + 2. Any pre-existing intellectual property disclaimers, notices, or + terms and conditions. If none exist, a short notice of the following + form (hypertext is preferred, text is permitted) should be used + within the body of any redistributed or derivative code: + "Copyright (C) [$date-of-software] World Wide Web Consortium, + (Massachusetts Institute of Technology, Institut National de + Recherche en Informatique et en Automatique, Keio University). + All Rights Reserved. http://www.w3.org/Consortium/Legal/" + + 3. Notice of any changes or modifications to the W3C files, including + the date changes were made. (We recommend you provide URIs to the + location from which the code is derived.) + + THIS SOFTWARE AND DOCUMENTATION IS PROVIDED "AS IS," AND COPYRIGHT HOLDERS + MAKE NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT + NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR + PURPOSE OR THAT THE USE OF THE SOFTWARE OR DOCUMENTATION WILL NOT INFRINGE + ANY THIRD PARTY PATENTS, COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS. + + COPYRIGHT HOLDERS WILL NOT BE LIABLE FOR ANY DIRECT, INDIRECT, SPECIAL + OR CONSEQUENTIAL DAMAGES ARISING OUT OF ANY USE OF THE SOFTWARE OR + DOCUMENTATION. + + The name and trademarks of copyright holders may NOT be used in + advertising or publicity pertaining to the software without specific, + written prior permission. Title to copyright in this software and any + associated documentation will at all times remain with copyright holders. + +XML API library, org.xml.sax classes (xml-apis) + + SAX2 is Free! + + I hereby abandon any property rights to SAX 2.0 (the Simple API for + XML), and release all of the SAX 2.0 source code, compiled code, and + documentation contained in this distribution into the Public Domain. + SAX comes with NO WARRANTY or guarantee of fitness for any purpose. + + David Megginson, david@megginson.com + 2000-05-05 + +Concurrent library (concurrent-1.3.4.jar) + + http://g.oswego.edu/dl/classes/EDU/oswego/cs/dl/util/concurrent/intro.html + + All classes are released to the public domain and may be used for any + purpose whatsoever without permission or acknowledgment. Portions of + the CopyOnWriteArrayList and ConcurrentReaderHashMap classes are adapted + from Sun JDK source code. These are copyright of Sun Microsystems, Inc, + and are used with their kind permission, as described in this license: + + TECHNOLOGY LICENSE FROM SUN MICROSYSTEMS, INC. TO DOUG LEA + + Whereas Doug Lea desires to utlized certain Java Software technologies + in the util.concurrent technology; and Whereas Sun Microsystems, Inc. + ("Sun") desires that Doug Lea utilize certain Java Software technologies + in the util.concurrent technology; + + Therefore the parties agree as follows, effective May 31, 2002: + + "Java Software technologies" means + + classes/java/util/ArrayList.java, and + classes/java/util/HashMap.java. + + The Java Software technologies are Copyright (c) 1994-2000 Sun + Microsystems, Inc. All rights reserved. + + Sun hereby grants Doug Lea a non-exclusive, worldwide, non-transferrable + license to use, reproduce, create derivate works of, and distribute the + Java Software and derivative works thereof in source and binary forms + as part of a larger work, and to sublicense the right to use, reproduce + and distribute the Java Software and Doug Lea's derivative works as the + part of larger works through multiple tiers of sublicensees provided that + the following conditions are met: + + -Neither the name of or trademarks of Sun may be used to endorse or + promote products including or derived from the Java Software technology + without specific prior written permission; and + -Redistributions of source or binary code must contain the above + copyright notice, this notice and and the following disclaimers: + + This software is provided "AS IS," without a warranty of any kind. + ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + MICROSYSTEMS, INC. AND ITS LICENSORS SHALL NOT BE LIABLE FOR ANY DAMAGES + SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING + THE SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN MICROSYSTEMS, INC. + OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, + HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF + THE USE OF OR INABILITY TO USE SOFTWARE, EVEN IF SUN MICROSYSTEMS, INC. + HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + + You acknowledge that Software is not designed,licensed or intended for + use in the design, construction, operation or maintenance of any nuclear + facility. + +Office Open XML schemas (ooxml-schemas-1.0.jar) + + The Office Open XML schema definitions used by Apache POI are + a part of the Office Open XML ECMA Specification (ECMA-376, [1]). + As defined in section 9.4 of the ECMA bylaws [2], this specification + is available to all interested parties without restriction: + + 9.4 All documents when approved shall be made available to + all interested parties without restriction. + + Furthermore, both Microsoft and Adobe have granted patent licenses + to this work [3,4,5]. + + [1] http://www.ecma-international.org/publications/standards/Ecma-376.htm + [2] http://www.ecma-international.org/memento/Ecmabylaws.htm + [3] http://www.microsoft.com/interop/osp/ + [4] http://www.ecma-international.org/publications/files/ECMA-ST/Ecma%20PATENT/ECMA-376%20Edition%201%20Microsoft%20Patent%20Declaration.pdf + [5] http://www.ecma-international.org/publications/files/ECMA-ST/Ecma%20PATENT/ga-2006-191.pdf + +DOM4J library (dom4j-1.6.1.jar) + + Copyright 2001-2005 (C) MetaStuff, Ltd. All Rights Reserved. + + Redistribution and use of this software and associated documentation + ("Software"), with or without modification, are permitted provided + that the following conditions are met: + + 1. Redistributions of source code must retain copyright + statements and notices. Redistributions must also contain a + copy of this document. + + 2. Redistributions in binary form must reproduce the + above copyright notice, this list of conditions and the + following disclaimer in the documentation and/or other + materials provided with the distribution. + + 3. The name "DOM4J" must not be used to endorse or promote + products derived from this Software without prior written + permission of MetaStuff, Ltd. For written permission, + please contact dom4j-info@metastuff.com. + + 4. Products derived from this Software may not be called "DOM4J" + nor may "DOM4J" appear in their names without prior written + permission of MetaStuff, Ltd. DOM4J is a registered + trademark of MetaStuff, Ltd. + + 5. Due credit should be given to the DOM4J Project - + http://www.dom4j.org + + THIS SOFTWARE IS PROVIDED BY METASTUFF, LTD. AND CONTRIBUTORS + ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT + NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + METASTUFF, LTD. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + OF THE POSSIBILITY OF SUCH DAMAGE. + +Unicode conversion code in Lucene Java (lucene-core) + + Copyright 2001-2004 Unicode, Inc. + + Disclaimer + + This source code is provided as is by Unicode, Inc. No claims are + made as to fitness for any particular purpose. No warranties of any + kind are expressed or implied. The recipient agrees to determine + applicability of information provided. If this file has been + purchased on magnetic or optical media from Unicode, Inc., the + sole remedy for any claim will be exchange of defective media + within 90 days of receipt. + + Limitations on Rights to Redistribute This Code + + Unicode, Inc. hereby grants the right to freely use the information + supplied in this file in the creation of products supporting the + Unicode Standard, and to make copies of this file in any form + for internal or external distribution as long as this notice + remains attached. + +Array utility code in Lucene Java (lucene-core) + + PSF LICENSE AGREEMENT FOR PYTHON 2.4 + ------------------------------------ + + 1. This LICENSE AGREEMENT is between the Python Software Foundation + ("PSF"), and the Individual or Organization ("Licensee") accessing and + otherwise using Python 2.4 software in source or binary form and its + associated documentation. + + 2. Subject to the terms and conditions of this License Agreement, PSF + hereby grants Licensee a nonexclusive, royalty-free, world-wide + license to reproduce, analyze, test, perform and/or display publicly, + prepare derivative works, distribute, and otherwise use Python 2.4 + alone or in any derivative version, provided, however, that PSF's + License Agreement and PSF's notice of copyright, i.e., "Copyright (c) + 2001, 2002, 2003, 2004 Python Software Foundation; All Rights Reserved" + are retained in Python 2.4 alone or in any derivative version prepared + by Licensee. + + 3. In the event Licensee prepares a derivative work that is based on + or incorporates Python 2.4 or any part thereof, and wants to make + the derivative work available to others as provided herein, then + Licensee hereby agrees to include in any such work a brief summary of + the changes made to Python 2.4. + + 4. PSF is making Python 2.4 available to Licensee on an "AS IS" + basis. PSF MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR + IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, PSF MAKES NO AND + DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS + FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF PYTHON 2.4 WILL NOT + INFRINGE ANY THIRD PARTY RIGHTS. + + 5. PSF SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF PYTHON + 2.4 FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS + A RESULT OF MODIFYING, DISTRIBUTING, OR OTHERWISE USING PYTHON 2.4, + OR ANY DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF. + + 6. This License Agreement will automatically terminate upon a material + breach of its terms and conditions. + + 7. Nothing in this License Agreement shall be deemed to create any + relationship of agency, partnership, or joint venture between PSF and + Licensee. This License Agreement does not grant permission to use PSF + trademarks or trade name in a trademark sense to endorse or promote + products or services of Licensee, or any third party. + + 8. By copying, installing or otherwise using Python 2.4, Licensee + agrees to be bound by the terms and conditions of this License + Agreement. + + BEOPEN.COM LICENSE AGREEMENT FOR PYTHON 2.0 + ------------------------------------------- + + BEOPEN PYTHON OPEN SOURCE LICENSE AGREEMENT VERSION 1 + + 1. This LICENSE AGREEMENT is between BeOpen.com ("BeOpen"), having an + office at 160 Saratoga Avenue, Santa Clara, CA 95051, and the + Individual or Organization ("Licensee") accessing and otherwise using + this software in source or binary form and its associated + documentation ("the Software"). + + 2. Subject to the terms and conditions of this BeOpen Python License + Agreement, BeOpen hereby grants Licensee a non-exclusive, + royalty-free, world-wide license to reproduce, analyze, test, perform + and/or display publicly, prepare derivative works, distribute, and + otherwise use the Software alone or in any derivative version, + provided, however, that the BeOpen Python License is retained in the + Software, alone or in any derivative version prepared by Licensee. + + 3. BeOpen is making the Software available to Licensee on an "AS IS" + basis. BEOPEN MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR + IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, BEOPEN MAKES NO AND + DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS + FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF THE SOFTWARE WILL NOT + INFRINGE ANY THIRD PARTY RIGHTS. + + 4. BEOPEN SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF THE + SOFTWARE FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS + AS A RESULT OF USING, MODIFYING OR DISTRIBUTING THE SOFTWARE, OR ANY + DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF. + + 5. This License Agreement will automatically terminate upon a material + breach of its terms and conditions. + + 6. This License Agreement shall be governed by and interpreted in all + respects by the law of the State of California, excluding conflict of + law provisions. Nothing in this License Agreement shall be deemed to + create any relationship of agency, partnership, or joint venture + between BeOpen and Licensee. This License Agreement does not grant + permission to use BeOpen trademarks or trade names in a trademark + sense to endorse or promote products or services of Licensee, or any + third party. As an exception, the "BeOpen Python" logos available at + http://www.pythonlabs.com/logos.html may be used according to the + permissions granted on that web page. + + 7. By copying, installing or otherwise using the software, Licensee + agrees to be bound by the terms and conditions of this License + Agreement. + + CNRI LICENSE AGREEMENT FOR PYTHON 1.6.1 + --------------------------------------- + + 1. This LICENSE AGREEMENT is between the Corporation for National + Research Initiatives, having an office at 1895 Preston White Drive, + Reston, VA 20191 ("CNRI"), and the Individual or Organization + ("Licensee") accessing and otherwise using Python 1.6.1 software in + source or binary form and its associated documentation. + + 2. Subject to the terms and conditions of this License Agreement, CNRI + hereby grants Licensee a nonexclusive, royalty-free, world-wide + license to reproduce, analyze, test, perform and/or display publicly, + prepare derivative works, distribute, and otherwise use Python 1.6.1 + alone or in any derivative version, provided, however, that CNRI's + License Agreement and CNRI's notice of copyright, i.e., "Copyright (c) + 1995-2001 Corporation for National Research Initiatives; All Rights + Reserved" are retained in Python 1.6.1 alone or in any derivative + version prepared by Licensee. Alternately, in lieu of CNRI's License + Agreement, Licensee may substitute the following text (omitting the + quotes): "Python 1.6.1 is made available subject to the terms and + conditions in CNRI's License Agreement. This Agreement together with + Python 1.6.1 may be located on the Internet using the following + unique, persistent identifier (known as a handle): 1895.22/1013. This + Agreement may also be obtained from a proxy server on the Internet + using the following URL: http://hdl.handle.net/1895.22/1013". + + 3. In the event Licensee prepares a derivative work that is based on + or incorporates Python 1.6.1 or any part thereof, and wants to make + the derivative work available to others as provided herein, then + Licensee hereby agrees to include in any such work a brief summary of + the changes made to Python 1.6.1. + + 4. CNRI is making Python 1.6.1 available to Licensee on an "AS IS" + basis. CNRI MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR + IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, CNRI MAKES NO AND + DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS + FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF PYTHON 1.6.1 WILL NOT + INFRINGE ANY THIRD PARTY RIGHTS. + + 5. CNRI SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF PYTHON + 1.6.1 FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS + A RESULT OF MODIFYING, DISTRIBUTING, OR OTHERWISE USING PYTHON 1.6.1, + OR ANY DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF. + + 6. This License Agreement will automatically terminate upon a material + breach of its terms and conditions. + + 7. This License Agreement shall be governed by the federal + intellectual property law of the United States, including without + limitation the federal copyright law, and, to the extent such + U.S. federal law does not apply, by the law of the Commonwealth of + Virginia, excluding Virginia's conflict of law provisions. + Notwithstanding the foregoing, with regard to derivative works based + on Python 1.6.1 that incorporate non-separable material that was + previously distributed under the GNU General Public License (GPL), the + law of the Commonwealth of Virginia shall govern this License + Agreement only as to issues arising under or with respect to + Paragraphs 4, 5, and 7 of this License Agreement. Nothing in this + License Agreement shall be deemed to create any relationship of + agency, partnership, or joint venture between CNRI and Licensee. This + License Agreement does not grant permission to use CNRI trademarks or + trade name in a trademark sense to endorse or promote products or + services of Licensee, or any third party. + + 8. By clicking on the "ACCEPT" button where indicated, or by copying, + installing or otherwise using Python 1.6.1, Licensee agrees to be + bound by the terms and conditions of this License Agreement. + + ACCEPT + + + CWI LICENSE AGREEMENT FOR PYTHON 0.9.0 THROUGH 1.2 + -------------------------------------------------- + + Copyright (c) 1991 - 1995, Stichting Mathematisch Centrum Amsterdam, + The Netherlands. All rights reserved. + + Permission to use, copy, modify, and distribute this software and its + documentation for any purpose and without fee is hereby granted, + provided that the above copyright notice appear in all copies and that + both that copyright notice and this permission notice appear in + supporting documentation, and that the name of Stichting Mathematisch + Centrum or CWI not be used in advertising or publicity pertaining to + distribution of the software without specific, written prior + permission. + + STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO + THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND + FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE + FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT + OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +AspectJ runtime library (aspectjrt) + + Eclipse Public License - v 1.0 + + THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS ECLIPSE + PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF + THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT. + + 1. DEFINITIONS + + "Contribution" means: + + a) in the case of the initial Contributor, the initial code and + documentation distributed under this Agreement, and + + b) in the case of each subsequent Contributor: + + i) changes to the Program, and + + ii) additions to the Program; + + where such changes and/or additions to the Program originate from and + are distributed by that particular Contributor. A Contribution + 'originates' from a Contributor if it was added to the Program by + such Contributor itself or anyone acting on such Contributor's behalf. + Contributions do not include additions to the Program which: (i) are + separate modules of software distributed in conjunction with the + Program under their own license agreement, and (ii) are not derivative + works of the Program. + + "Contributor" means any person or entity that distributes the Program. + + "Licensed Patents " mean patent claims licensable by a Contributor which + are necessarily infringed by the use or sale of its Contribution alone or + when combined with the Program. + + "Program" means the Contributions distributed in accordance with this + Agreement. + + "Recipient" means anyone who receives the Program under this Agreement, + including all Contributors. + + 2. GRANT OF RIGHTS + + a) Subject to the terms of this Agreement, each Contributor hereby grants + Recipient a non-exclusive, worldwide, royalty-free copyright license to + reproduce, prepare derivative works of, publicly display, publicly + perform, distribute and sublicense the Contribution of such + Contributor, if any, and such derivative works, in source code and + object code form. + + b) Subject to the terms of this Agreement, each Contributor hereby grants + Recipient a non-exclusive, worldwide, royalty-free patent license under + Licensed Patents to make, use, sell, offer to sell, import and + otherwise transfer the Contribution of such Contributor, if any, in + source code and object code form. This patent license shall apply to + the combination of the Contribution and the Program if, at the time + the Contribution is added by the Contributor, such addition of the + Contribution causes such combination to be covered by the Licensed + Patents. The patent license shall not apply to any other combinations + which include the Contribution. No hardware per se is licensed hereunder. + + c) Recipient understands that although each Contributor grants the + licenses to its Contributions set forth herein, no assurances are + provided by any Contributor that the Program does not infringe the + patent or other intellectual property rights of any other entity. Each + Contributor disclaims any liability to Recipient for claims brought by + any other entity based on infringement of intellectual property rights + or otherwise. As a condition to exercising the rights and licenses + granted hereunder, each Recipient hereby assumes sole responsibility + to secure any other intellectual property rights needed, if any. For + example, if a third party patent license is required to allow Recipient + to distribute the Program, it is Recipient's responsibility to acquire + that license before distributing the Program. + + d) Each Contributor represents that to its knowledge it has sufficient + copyright rights in its Contribution, if any, to grant the copyright + license set forth in this Agreement. + + 3. REQUIREMENTS + + A Contributor may choose to distribute the Program in object code form + under its own license agreement, provided that: + + a) it complies with the terms and conditions of this Agreement; and + + b) its license agreement: + + i) effectively disclaims on behalf of all Contributors all warranties + and conditions, express and implied, including warranties or + conditions of title and non-infringement, and implied warranties + or conditions of merchantability and fitness for a particular + purpose; + + ii) effectively excludes on behalf of all Contributors all liability + for damages, including direct, indirect, special, incidental and + consequential damages, such as lost profits; + + iii) states that any provisions which differ from this Agreement are + offered by that Contributor alone and not by any other party; and + + iv) states that source code for the Program is available from such + Contributor, and informs licensees how to obtain it in a + reasonable manner on or through a medium customarily used for + software exchange. + + When the Program is made available in source code form: + + a) it must be made available under this Agreement; and + + b) a copy of this Agreement must be included with each copy of the + Program. + + Contributors may not remove or alter any copyright notices contained + within the Program. + + Each Contributor must identify itself as the originator of its + Contribution, if any, in a manner that reasonably allows subsequent + Recipients to identify the originator of the Contribution. + + 4. COMMERCIAL DISTRIBUTION + + Commercial distributors of software may accept certain responsibilities + with respect to end users, business partners and the like. While this + license is intended to facilitate the commercial use of the Program, + the Contributor who includes the Program in a commercial product offering + should do so in a manner which does not create potential liability for + other Contributors. Therefore, if a Contributor includes the Program in + a commercial product offering, such Contributor ("Commercial Contributor") + hereby agrees to defend and indemnify every other Contributor + ("Indemnified Contributor") against any losses, damages and costs + (collectively "Losses") arising from claims, lawsuits and other legal + actions brought by a third party against the Indemnified Contributor to + the extent caused by the acts or omissions of such Commercial Contributor + in connection with its distribution of the Program in a commercial + product offering. The obligations in this section do not apply to any + claims or Losses relating to any actual or alleged intellectual property + infringement. In order to qualify, an Indemnified Contributor must: + a) promptly notify the Commercial Contributor in writing of such claim, + and b) allow the Commercial Contributor to control, and cooperate with + the Commercial Contributor in, the defense and any related settlement + negotiations. The Indemnified Contributor may participate in any such + claim at its own expense. + + For example, a Contributor might include the Program in a commercial + product offering, Product X. That Contributor is then a Commercial + Contributor. If that Commercial Contributor then makes performance claims, + or offers warranties related to Product X, those performance claims and + warranties are such Commercial Contributor's responsibility alone. Under + this section, the Commercial Contributor would have to defend claims + against the other Contributors related to those performance claims and + warranties, and if a court requires any other Contributor to pay any + damages as a result, the Commercial Contributor must pay those damages. + + 5. NO WARRANTY + + EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS PROVIDED + ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER + EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR + CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A + PARTICULAR PURPOSE. Each Recipient is solely responsible for determining + the appropriateness of using and distributing the Program and assumes all + risks associated with its exercise of rights under this Agreement , + including but not limited to the risks and costs of program errors, + compliance with applicable laws, damage to or loss of data, programs or + equipment, and unavailability or interruption of operations. + + 6. DISCLAIMER OF LIABILITY + + EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR + ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING + WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OR + DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED + HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + + 7. GENERAL + + If any provision of this Agreement is invalid or unenforceable under + applicable law, it shall not affect the validity or enforceability of + the remainder of the terms of this Agreement, and without further action + by the parties hereto, such provision shall be reformed to the minimum + extent necessary to make such provision valid and enforceable. + + If Recipient institutes patent litigation against any entity (including + a cross-claim or counterclaim in a lawsuit) alleging that the Program + itself (excluding combinations of the Program with other software or + hardware) infringes such Recipient's patent(s), then such Recipient's + rights granted under Section 2(b) shall terminate as of the date such + litigation is filed. + + All Recipient's rights under this Agreement shall terminate if it fails + to comply with any of the material terms or conditions of this Agreement + and does not cure such failure in a reasonable period of time after + becoming aware of such noncompliance. If all Recipient's rights under + this Agreement terminate, Recipient agrees to cease use and distribution + of the Program as soon as reasonably practicable. However, Recipient's + obligations under this Agreement and any licenses granted by Recipient + relating to the Program shall continue and survive. + + Everyone is permitted to copy and distribute copies of this Agreement, + but in order to avoid inconsistency the Agreement is copyrighted and may + only be modified in the following manner. The Agreement Steward reserves + the right to publish new versions (including revisions) of this Agreement + from time to time. No one other than the Agreement Steward has the right + to modify this Agreement. The Eclipse Foundation is the initial Agreement + Steward. The Eclipse Foundation may assign the responsibility to serve as + the Agreement Steward to a suitable separate entity. Each new version of + the Agreement will be given a distinguishing version number. The Program + (including Contributions) may always be distributed subject to the version + of the Agreement under which it was received. In addition, after a new + version of the Agreement is published, Contributor may elect to distribute + the Program (including its Contributions) under the new version. Except as + expressly stated in Sections 2(a) and 2(b) above, Recipient receives no + rights or licenses to the intellectual property of any Contributor under + this Agreement, whether expressly, by implication, estoppel or otherwise. + All rights in the Program not expressly granted under this Agreement + are reserved. + + This Agreement is governed by the laws of the State of New York and the + intellectual property laws of the United States of America. No party to + this Agreement will bring a legal action under this Agreement more than + one year after the cause of action arose. Each party waives its rights to + a jury trial in any resulting litigation. + +juniversalchardet library (juniversalchardet) + + MOZILLA PUBLIC LICENSE + Version 1.1 + + --------------- + + 1. Definitions. + + 1.0.1. "Commercial Use" means distribution or otherwise making the + Covered Code available to a third party. + + 1.1. "Contributor" means each entity that creates or contributes to + the creation of Modifications. + + 1.2. "Contributor Version" means the combination of the Original + Code, prior Modifications used by a Contributor, and the Modifications + made by that particular Contributor. + + 1.3. "Covered Code" means the Original Code or Modifications or the + combination of the Original Code and Modifications, in each case + including portions thereof. + + 1.4. "Electronic Distribution Mechanism" means a mechanism generally + accepted in the software development community for the electronic + transfer of data. + + 1.5. "Executable" means Covered Code in any form other than Source + Code. + + 1.6. "Initial Developer" means the individual or entity identified + as the Initial Developer in the Source Code notice required by Exhibit + A. + + 1.7. "Larger Work" means a work which combines Covered Code or + portions thereof with code not governed by the terms of this License. + + 1.8. "License" means this document. + + 1.8.1. "Licensable" means having the right to grant, to the maximum + extent possible, whether at the time of the initial grant or + subsequently acquired, any and all of the rights conveyed herein. + + 1.9. "Modifications" means any addition to or deletion from the + substance or structure of either the Original Code or any previous + Modifications. When Covered Code is released as a series of files, a + Modification is: + A. Any addition to or deletion from the contents of a file + containing Original Code or previous Modifications. + + B. Any new file that contains any part of the Original Code or + previous Modifications. + + 1.10. "Original Code" means Source Code of computer software code + which is described in the Source Code notice required by Exhibit A as + Original Code, and which, at the time of its release under this + License is not already Covered Code governed by this License. + + 1.10.1. "Patent Claims" means any patent claim(s), now owned or + hereafter acquired, including without limitation, method, process, + and apparatus claims, in any patent Licensable by grantor. + + 1.11. "Source Code" means the preferred form of the Covered Code for + making modifications to it, including all modules it contains, plus + any associated interface definition files, scripts used to control + compilation and installation of an Executable, or source code + differential comparisons against either the Original Code or another + well known, available Covered Code of the Contributor's choice. The + Source Code can be in a compressed or archival form, provided the + appropriate decompression or de-archiving software is widely available + for no charge. + + 1.12. "You" (or "Your") means an individual or a legal entity + exercising rights under, and complying with all of the terms of, this + License or a future version of this License issued under Section 6.1. + For legal entities, "You" includes any entity which controls, is + controlled by, or is under common control with You. For purposes of + this definition, "control" means (a) the power, direct or indirect, + to cause the direction or management of such entity, whether by + contract or otherwise, or (b) ownership of more than fifty percent + (50%) of the outstanding shares or beneficial ownership of such + entity. + + 2. Source Code License. + + 2.1. The Initial Developer Grant. + The Initial Developer hereby grants You a world-wide, royalty-free, + non-exclusive license, subject to third party intellectual property + claims: + (a) under intellectual property rights (other than patent or + trademark) Licensable by Initial Developer to use, reproduce, + modify, display, perform, sublicense and distribute the Original + Code (or portions thereof) with or without Modifications, and/or + as part of a Larger Work; and + + (b) under Patents Claims infringed by the making, using or + selling of Original Code, to make, have made, use, practice, + sell, and offer for sale, and/or otherwise dispose of the + Original Code (or portions thereof). + + (c) the licenses granted in this Section 2.1(a) and (b) are + effective on the date Initial Developer first distributes + Original Code under the terms of this License. + + (d) Notwithstanding Section 2.1(b) above, no patent license is + granted: 1) for code that You delete from the Original Code; 2) + separate from the Original Code; or 3) for infringements caused + by: i) the modification of the Original Code or ii) the + combination of the Original Code with other software or devices. + + 2.2. Contributor Grant. + Subject to third party intellectual property claims, each Contributor + hereby grants You a world-wide, royalty-free, non-exclusive license + + (a) under intellectual property rights (other than patent or + trademark) Licensable by Contributor, to use, reproduce, modify, + display, perform, sublicense and distribute the Modifications + created by such Contributor (or portions thereof) either on an + unmodified basis, with other Modifications, as Covered Code + and/or as part of a Larger Work; and + + (b) under Patent Claims infringed by the making, using, or + selling of Modifications made by that Contributor either alone + and/or in combination with its Contributor Version (or portions + of such combination), to make, use, sell, offer for sale, have + made, and/or otherwise dispose of: 1) Modifications made by that + Contributor (or portions thereof); and 2) the combination of + Modifications made by that Contributor with its Contributor + Version (or portions of such combination). + + (c) the licenses granted in Sections 2.2(a) and 2.2(b) are + effective on the date Contributor first makes Commercial Use of + the Covered Code. + + (d) Notwithstanding Section 2.2(b) above, no patent license is + granted: 1) for any code that Contributor has deleted from the + Contributor Version; 2) separate from the Contributor Version; + 3) for infringements caused by: i) third party modifications of + Contributor Version or ii) the combination of Modifications made + by that Contributor with other software (except as part of the + Contributor Version) or other devices; or 4) under Patent Claims + infringed by Covered Code in the absence of Modifications made by + that Contributor. + + 3. Distribution Obligations. + + 3.1. Application of License. + The Modifications which You create or to which You contribute are + governed by the terms of this License, including without limitation + Section 2.2. The Source Code version of Covered Code may be + distributed only under the terms of this License or a future version + of this License released under Section 6.1, and You must include a + copy of this License with every copy of the Source Code You + distribute. You may not offer or impose any terms on any Source Code + version that alters or restricts the applicable version of this + License or the recipients' rights hereunder. However, You may include + an additional document offering the additional rights described in + Section 3.5. + + 3.2. Availability of Source Code. + Any Modification which You create or to which You contribute must be + made available in Source Code form under the terms of this License + either on the same media as an Executable version or via an accepted + Electronic Distribution Mechanism to anyone to whom you made an + Executable version available; and if made available via Electronic + Distribution Mechanism, must remain available for at least twelve (12) + months after the date it initially became available, or at least six + (6) months after a subsequent version of that particular Modification + has been made available to such recipients. You are responsible for + ensuring that the Source Code version remains available even if the + Electronic Distribution Mechanism is maintained by a third party. + + 3.3. Description of Modifications. + You must cause all Covered Code to which You contribute to contain a + file documenting the changes You made to create that Covered Code and + the date of any change. You must include a prominent statement that + the Modification is derived, directly or indirectly, from Original + Code provided by the Initial Developer and including the name of the + Initial Developer in (a) the Source Code, and (b) in any notice in an + Executable version or related documentation in which You describe the + origin or ownership of the Covered Code. + + 3.4. Intellectual Property Matters + (a) Third Party Claims. + If Contributor has knowledge that a license under a third party's + intellectual property rights is required to exercise the rights + granted by such Contributor under Sections 2.1 or 2.2, + Contributor must include a text file with the Source Code + distribution titled "LEGAL" which describes the claim and the + party making the claim in sufficient detail that a recipient will + know whom to contact. If Contributor obtains such knowledge after + the Modification is made available as described in Section 3.2, + Contributor shall promptly modify the LEGAL file in all copies + Contributor makes available thereafter and shall take other steps + (such as notifying appropriate mailing lists or newsgroups) + reasonably calculated to inform those who received the Covered + Code that new knowledge has been obtained. + + (b) Contributor APIs. + If Contributor's Modifications include an application programming + interface and Contributor has knowledge of patent licenses which + are reasonably necessary to implement that API, Contributor must + also include this information in the LEGAL file. + + (c) Representations. + Contributor represents that, except as disclosed pursuant to + Section 3.4(a) above, Contributor believes that Contributor's + Modifications are Contributor's original creation(s) and/or + Contributor has sufficient rights to grant the rights conveyed by + this License. + + 3.5. Required Notices. + You must duplicate the notice in Exhibit A in each file of the Source + Code. If it is not possible to put such notice in a particular Source + Code file due to its structure, then You must include such notice in a + location (such as a relevant directory) where a user would be likely + to look for such a notice. If You created one or more Modification(s) + You may add your name as a Contributor to the notice described in + Exhibit A. You must also duplicate this License in any documentation + for the Source Code where You describe recipients' rights or ownership + rights relating to Covered Code. You may choose to offer, and to + charge a fee for, warranty, support, indemnity or liability + obligations to one or more recipients of Covered Code. However, You + may do so only on Your own behalf, and not on behalf of the Initial + Developer or any Contributor. You must make it absolutely clear than + any such warranty, support, indemnity or liability obligation is + offered by You alone, and You hereby agree to indemnify the Initial + Developer and every Contributor for any liability incurred by the + Initial Developer or such Contributor as a result of warranty, + support, indemnity or liability terms You offer. + + 3.6. Distribution of Executable Versions. + You may distribute Covered Code in Executable form only if the + requirements of Section 3.1-3.5 have been met for that Covered Code, + and if You include a notice stating that the Source Code version of + the Covered Code is available under the terms of this License, + including a description of how and where You have fulfilled the + obligations of Section 3.2. The notice must be conspicuously included + in any notice in an Executable version, related documentation or + collateral in which You describe recipients' rights relating to the + Covered Code. You may distribute the Executable version of Covered + Code or ownership rights under a license of Your choice, which may + contain terms different from this License, provided that You are in + compliance with the terms of this License and that the license for the + Executable version does not attempt to limit or alter the recipient's + rights in the Source Code version from the rights set forth in this + License. If You distribute the Executable version under a different + license You must make it absolutely clear that any terms which differ + from this License are offered by You alone, not by the Initial + Developer or any Contributor. You hereby agree to indemnify the + Initial Developer and every Contributor for any liability incurred by + the Initial Developer or such Contributor as a result of any such + terms You offer. + + 3.7. Larger Works. + You may create a Larger Work by combining Covered Code with other code + not governed by the terms of this License and distribute the Larger + Work as a single product. In such a case, You must make sure the + requirements of this License are fulfilled for the Covered Code. + + 4. Inability to Comply Due to Statute or Regulation. + + If it is impossible for You to comply with any of the terms of this + License with respect to some or all of the Covered Code due to + statute, judicial order, or regulation then You must: (a) comply with + the terms of this License to the maximum extent possible; and (b) + describe the limitations and the code they affect. Such description + must be included in the LEGAL file described in Section 3.4 and must + be included with all distributions of the Source Code. Except to the + extent prohibited by statute or regulation, such description must be + sufficiently detailed for a recipient of ordinary skill to be able to + understand it. + + 5. Application of this License. + + This License applies to code to which the Initial Developer has + attached the notice in Exhibit A and to related Covered Code. + + 6. Versions of the License. + + 6.1. New Versions. + Netscape Communications Corporation ("Netscape") may publish revised + and/or new versions of the License from time to time. Each version + will be given a distinguishing version number. + + 6.2. Effect of New Versions. + Once Covered Code has been published under a particular version of the + License, You may always continue to use it under the terms of that + version. You may also choose to use such Covered Code under the terms + of any subsequent version of the License published by Netscape. No one + other than Netscape has the right to modify the terms applicable to + Covered Code created under this License. + + 6.3. Derivative Works. + If You create or use a modified version of this License (which you may + only do in order to apply it to code which is not already Covered Code + governed by this License), You must (a) rename Your license so that + the phrases "Mozilla", "MOZILLAPL", "MOZPL", "Netscape", + "MPL", "NPL" or any confusingly similar phrase do not appear in your + license (except to note that your license differs from this License) + and (b) otherwise make it clear that Your version of the license + contains terms which differ from the Mozilla Public License and + Netscape Public License. (Filling in the name of the Initial + Developer, Original Code or Contributor in the notice described in + Exhibit A shall not of themselves be deemed to be modifications of + this License.) + + 7. DISCLAIMER OF WARRANTY. + + COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, + WITHOUT LIMITATION, WARRANTIES THAT THE COVERED CODE IS FREE OF + DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE OR NON-INFRINGING. + THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED CODE + IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, + YOU (NOT THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE + COST OF ANY NECESSARY SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER + OF WARRANTY CONSTITUTES AN ESSENTIAL PART OF THIS LICENSE. NO USE OF + ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER THIS DISCLAIMER. + + 8. TERMINATION. + + 8.1. This License and the rights granted hereunder will terminate + automatically if You fail to comply with terms herein and fail to cure + such breach within 30 days of becoming aware of the breach. All + sublicenses to the Covered Code which are properly granted shall + survive any termination of this License. Provisions which, by their + nature, must remain in effect beyond the termination of this License + shall survive. + + 8.2. If You initiate litigation by asserting a patent infringement + claim (excluding declatory judgment actions) against Initial Developer + or a Contributor (the Initial Developer or Contributor against whom + You file such action is referred to as "Participant") alleging that: + + (a) such Participant's Contributor Version directly or indirectly + infringes any patent, then any and all rights granted by such + Participant to You under Sections 2.1 and/or 2.2 of this License + shall, upon 60 days notice from Participant terminate prospectively, + unless if within 60 days after receipt of notice You either: (i) + agree in writing to pay Participant a mutually agreeable reasonable + royalty for Your past and future use of Modifications made by such + Participant, or (ii) withdraw Your litigation claim with respect to + the Contributor Version against such Participant. If within 60 days + of notice, a reasonable royalty and payment arrangement are not + mutually agreed upon in writing by the parties or the litigation claim + is not withdrawn, the rights granted by Participant to You under + Sections 2.1 and/or 2.2 automatically terminate at the expiration of + the 60 day notice period specified above. + + (b) any software, hardware, or device, other than such Participant's + Contributor Version, directly or indirectly infringes any patent, then + any rights granted to You by such Participant under Sections 2.1(b) + and 2.2(b) are revoked effective as of the date You first made, used, + sold, distributed, or had made, Modifications made by that + Participant. + + 8.3. If You assert a patent infringement claim against Participant + alleging that such Participant's Contributor Version directly or + indirectly infringes any patent where such claim is resolved (such as + by license or settlement) prior to the initiation of patent + infringement litigation, then the reasonable value of the licenses + granted by such Participant under Sections 2.1 or 2.2 shall be taken + into account in determining the amount or value of any payment or + license. + + 8.4. In the event of termination under Sections 8.1 or 8.2 above, + all end user license agreements (excluding distributors and resellers) + which have been validly granted by You or any distributor hereunder + prior to termination shall survive termination. + + 9. LIMITATION OF LIABILITY. + + UNDER NO CIRCUMSTANCES AND UNDER NO LEGAL THEORY, WHETHER TORT + (INCLUDING NEGLIGENCE), CONTRACT, OR OTHERWISE, SHALL YOU, THE INITIAL + DEVELOPER, ANY OTHER CONTRIBUTOR, OR ANY DISTRIBUTOR OF COVERED CODE, + OR ANY SUPPLIER OF ANY OF SUCH PARTIES, BE LIABLE TO ANY PERSON FOR + ANY INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES OF ANY + CHARACTER INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF GOODWILL, + WORK STOPPAGE, COMPUTER FAILURE OR MALFUNCTION, OR ANY AND ALL OTHER + COMMERCIAL DAMAGES OR LOSSES, EVEN IF SUCH PARTY SHALL HAVE BEEN + INFORMED OF THE POSSIBILITY OF SUCH DAMAGES. THIS LIMITATION OF + LIABILITY SHALL NOT APPLY TO LIABILITY FOR DEATH OR PERSONAL INJURY + RESULTING FROM SUCH PARTY'S NEGLIGENCE TO THE EXTENT APPLICABLE LAW + PROHIBITS SUCH LIMITATION. SOME JURISDICTIONS DO NOT ALLOW THE + EXCLUSION OR LIMITATION OF INCIDENTAL OR CONSEQUENTIAL DAMAGES, SO + THIS EXCLUSION AND LIMITATION MAY NOT APPLY TO YOU. + + 10. U.S. GOVERNMENT END USERS. + + The Covered Code is a "commercial item," as that term is defined in + 48 C.F.R. 2.101 (Oct. 1995), consisting of "commercial computer + software" and "commercial computer software documentation," as such + terms are used in 48 C.F.R. 12.212 (Sept. 1995). Consistent with 48 + C.F.R. 12.212 and 48 C.F.R. 227.7202-1 through 227.7202-4 (June 1995), + all U.S. Government End Users acquire Covered Code with only those + rights set forth herein. + + 11. MISCELLANEOUS. + + This License represents the complete agreement concerning subject + matter hereof. If any provision of this License is held to be + unenforceable, such provision shall be reformed only to the extent + necessary to make it enforceable. This License shall be governed by + California law provisions (except to the extent applicable law, if + any, provides otherwise), excluding its conflict-of-law provisions. + With respect to disputes in which at least one party is a citizen of, + or an entity chartered or registered to do business in the United + States of America, any litigation relating to this License shall be + subject to the jurisdiction of the Federal Courts of the Northern + District of California, with venue lying in Santa Clara County, + California, with the losing party responsible for costs, including + without limitation, court costs and reasonable attorneys' fees and + expenses. The application of the United Nations Convention on + Contracts for the International Sale of Goods is expressly excluded. + Any law or regulation which provides that the language of a contract + shall be construed against the drafter shall not apply to this + License. + + 12. RESPONSIBILITY FOR CLAIMS. + + As between Initial Developer and the Contributors, each party is + responsible for claims and damages arising, directly or indirectly, + out of its utilization of rights under this License and You agree to + work with Initial Developer and Contributors to distribute such + responsibility on an equitable basis. Nothing herein is intended or + shall be deemed to constitute any admission of liability. + + 13. MULTIPLE-LICENSED CODE. + + Initial Developer may designate portions of the Covered Code as + "Multiple-Licensed". "Multiple-Licensed" means that the Initial + Developer permits you to utilize portions of the Covered Code under + Your choice of the NPL or the alternative licenses, if any, specified + by the Initial Developer in the file described in Exhibit A. + + EXHIBIT A -Mozilla Public License. + + ``The contents of this file are subject to the Mozilla Public License + Version 1.1 (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.mozilla.org/MPL/ + + Software distributed under the License is distributed on an "AS IS" + basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the + License for the specific language governing rights and limitations + under the License. + + The Original Code is ______________________________________. + + The Initial Developer of the Original Code is ________________________. + Portions created by ______________________ are Copyright (C) ______ + _______________________. All Rights Reserved. + + Contributor(s): ______________________________________. + + Alternatively, the contents of this file may be used under the terms + of the _____ license (the "[___] License"), in which case the + provisions of [______] License are applicable instead of those + above. If you wish to allow use of your version of this file only + under the terms of the [____] License and not to allow others to use + your version of this file under the MPL, indicate your decision by + deleting the provisions above and replace them with the notice and + other provisions required by the [___] License. If you do not delete + the provisions above, a recipient may use your version of this file + under either the MPL or the [___] License." + + [NOTE: The text of this Exhibit A may differ slightly from the text of + the notices in the Source Code files of the Original Code. You should + use the text of this Exhibit A rather than the text found in the + Original Code Source Code for Your Modifications.] Property changes on: jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/META-INF/LICENSE ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +author date id revision \ No newline at end of property Index: jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/META-INF/NOTICE =================================================================== --- jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/META-INF/NOTICE (nonexistent) +++ jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/META-INF/NOTICE (working copy) @@ -0,0 +1,41 @@ +Apache Jackrabbit +Copyright 2010 The Apache Software Foundation + +This product includes software developed at +The Apache Software Foundation (http://www.apache.org/). + +Based on source code originally developed by +Day Software (http://www.day.com/). + +This product includes software from the following contributions: + +Original BZip2 classes contributed by Keiron Liddle +, Aftex Software to the Apache Ant project + +Original Tar classes from contributors of the Apache Ant project + +Original Zip classes from contributors of the Apache Ant project + +Original CPIO classes contributed by Markus Kuss and the jRPM project +(jrpm.sourceforge.net) + +Portions of Derby were originally developed by International Business +Machines Corporation and are licensed to the Apache Software Foundation +under the "Software Grant and Corporate Contribution License Agreement", +informally known as the "Derby CLA". The following copyright notice(s) +were affixed to portions of the code with which this file is now or was +at one time distributed and are placed here unaltered. + + (C) Copyright 1997,2004 International Business Machines Corporation. + All rights reserved. + + (C) Copyright IBM Corp. 2003. + +The JDBC apis for small devices and JDBC3 (under java/stubs/jsr169 and +java/stubs/jdbc3) were produced by trimming sources supplied by the +Apache Harmony project. The following notice covers the Harmony sources: + + Portions of Harmony were originally developed by + Intel Corporation and are licensed to the Apache Software + Foundation under the "Software Grant and Corporate Contribution + License Agreement", informally known as the "Intel Harmony CLA". Property changes on: jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/META-INF/NOTICE ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +author date id revision \ No newline at end of property Index: jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/WEB-INF/batchread.properties =================================================================== --- jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/WEB-INF/batchread.properties (nonexistent) +++ jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/WEB-INF/batchread.properties (working copy) @@ -0,0 +1,27 @@ +# 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. + +# This file contains an example batch read configuration used by +# JcrRemotingServlet according to the 'batchread-config' init-param. +# +# key = node type name +# value = desired depth for any node having the node type as primary type. +# +# - Use 'default' to set the default depth +# - Depth may be any int >= -1. +# - Depth -1 indicates infinite depth. + +default=5 +nt\:file=-1 \ No newline at end of file Property changes on: jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/WEB-INF/batchread.properties ___________________________________________________________________ Added: svn Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/WEB-INF/config.xml =================================================================== --- jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/WEB-INF/config.xml (nonexistent) +++ jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/WEB-INF/config.xml (working copy) @@ -0,0 +1,184 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + nt:file + nt:resource + + + + + + + + + + + + + rep + jcr + + + + + + Property changes on: jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/WEB-INF/config.xml ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/WEB-INF/protectedHandlers.properties =================================================================== --- jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/WEB-INF/protectedHandlers.properties (nonexistent) +++ jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/WEB-INF/protectedHandlers.properties (working copy) @@ -0,0 +1,17 @@ +# 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. + +# ProtectedItemRemoveHandler implementation class +javax.jcr.tck.access.control.list.handler=org.apache.jackrabbit.server.remoting.davex.AclRemoveHandler Index: jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/WEB-INF/templates/bootstrap.properties =================================================================== --- jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/WEB-INF/templates/bootstrap.properties (nonexistent) +++ jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/WEB-INF/templates/bootstrap.properties (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. + +# This is the template file for the 'bootstrap.properties' that will +# be placed in the repository home directory (or whatever is specified +# in the "bootstrap-config" init parameter. + +# Repository configuration settings (will be adjusted by installer) +repository.config=jackrabbit/repository/repository.xml +repository.home=jackrabbit/repository +repository.name=jackrabbit.repository + +# RMI Settings +rmi.enabled=true +rmi.port=0 +rmi.host=localhost +# If the URI is not specified, it's composed as follows: +#rmi.uri=//${rmi.host}:${rmi.port}/${repository.name} + +# JNDI Settings +# all properties starting with 'java.naming.' will go into the +# environment of the initial context +jndi.enabled=true +# if the name is not specified, it's initialized with the repository.name +#jndi.name=${repository.name} +java.naming.provider.url=http://www.apache.org/jackrabbit +java.naming.factory.initial=org.apache.jackrabbit.core.jndi.provider.DummyInitialContextFactory Property changes on: jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/WEB-INF/templates/bootstrap.properties ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/WEB-INF/web.xml =================================================================== --- jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/WEB-INF/web.xml (nonexistent) +++ jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/WEB-INF/web.xml (working copy) @@ -0,0 +1,407 @@ + + + + + + Jackrabbit JCR Server + + + + + + org.apache.jackrabbit.j2ee.DerbyShutdown + + + + + + + + RepositoryStartup + + Repository servlet that starts the repository and registers it to JNDI ans RMI. + If you already have the repository registered in this appservers JNDI context, + or if its accessible via RMI, you do not need to use this servlet. + + org.apache.jackrabbit.j2ee.RepositoryStartupServlet + + + bootstrap-config + jackrabbit/bootstrap.properties + + Property file that hold the same initialization properties than + the init-params below. If a parameter is specified in both + places the one in the bootstrap-config wins. + + + + + + + + + + 2 + + + + + + + + Repository + + This servlet provides other servlets and jsps a common way to access + the repository. The repository can be accessed via JNDI, RMI or Webdav. + + org.apache.jackrabbit.j2ee.RepositoryAccessServlet + + + bootstrap-config + jackrabbit/bootstrap.properties + + Property file that hold the same initialization properties than + the init-params below. If a parameter is specified in both + places the one in the bootstrap-config wins. + + + + + + + + + + 3 + + + + + + + Webdav + + The webdav servlet that connects HTTP request to the repository. + + org.apache.jackrabbit.j2ee.SimpleWebdavServlet + + + resource-path-prefix + /repository + + defines the prefix for spooling resources out of the repository. + + + + + + + + resource-config + /WEB-INF/config.xml + + Defines various dav-resource configuration parameters. + + + + + 4 + + + + + + + JCRWebdavServer + + The servlet used to remote JCR calls over HTTP. + + org.apache.jackrabbit.j2ee.JcrRemotingServlet + + missing-auth-mapping + + + Defines how a missing authorization header should be handled. + 1) If this init-param is missing, a 401 response is generated. + This is suitable for clients (eg. webdav clients) for which + sending a proper authorization header is not possible if the + server never sent a 401. + 2) If this init-param is present with an empty value, + null-credentials are returned, thus forcing an null login + on the repository. + 3) If this init-param is present with the value 'guestcredentials' + java.jcr.GuestCredentials are used to login to the repository. + 4) If this init-param has a 'user:password' value, the respective + simple credentials are generated. + + + + + + resource-path-prefix + /server + + defines the prefix for spooling resources out of the repository. + + + + + + batchread-config + /WEB-INF/batchread.properties + JcrRemotingServlet: Optional mapping from node type names to default depth. + + + protectedhandlers-config + /WEB-INF/protectedHandlersConfig.xml + JcrRemotingServlet: Handlers for removing protected items. + + + + 5 + + + + + + + RMI + org.apache.jackrabbit.servlet.remote.RemoteBindingServlet + + + + + + + RepositoryStartup + /admin/* + + + Webdav + /repository/* + + + JCRWebdavServer + /server/* + + + RMI + /rmi + + + + + + + index.jsp + + + + org.apache.jackrabbit.j2ee.JcrApiNotFoundException + /error/classpath.jsp + + + javax.jcr.RepositoryException + /error/repository.jsp + + + Property changes on: jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/WEB-INF/web.xml ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/about.jsp =================================================================== --- jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/about.jsp (nonexistent) +++ jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/about.jsp (working copy) @@ -0,0 +1,73 @@ +<%-- + 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. +--%><%@page import="java.io.InputStream, + java.io.InputStreamReader, + java.io.Reader"%><%! + + /** + * Escapes and outputs the contents of a given (UTF-8) text resource. + * TODO: There should be an easier way to do this! + * + * @param path path of the resource to output + * @param out the JSP output writer + * @throws Exception if something goes wrong + */ + private void output(String path, JspWriter out) throws Exception { + InputStream input = getServletContext().getResourceAsStream(path); + try { + Reader reader = new InputStreamReader(input, "UTF-8"); + for (int ch = reader.read(); ch != -1; ch = reader.read()) { + if (ch == '<') { + out.write("<"); + } else if (ch == '>') { + out.write(">"); + } else if (ch == '&') { + out.write("&"); + } else { + out.write((char) ch); + } + } + } finally { + input.close(); + } + } + +%><% request.setAttribute("title", "About Apache Jackrabbit"); +%> +

+ Apache Jackrabbit is a fully + conforming implementation of the Content Repository for Java Technology API + (JCR). A content repository is a hierarchical content store with support for + structured and unstructured content, full text search, versioning, + transactions, observation, and more. Typical applications that use content + repositories include content management, document management, and records + management systems. +

+

+ Version 1.0 of the JCR API was specified by the + Java Specification Request 170 + (JSR 170) and version 2.0 by the + Java Specification Request 283. +

+

+ Apache Jackrabbit is a project of the + Apache Software Foundation. +

+

Copyright Notice

+
<% output("/META-INF/NOTICE", out); %>
+

License Information

+
<% output("/META-INF/LICENSE", out); %>
+ Property changes on: jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/about.jsp ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/bootstrap/error.jsp =================================================================== --- jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/bootstrap/error.jsp (nonexistent) +++ jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/bootstrap/error.jsp (working copy) @@ -0,0 +1,23 @@ +<%-- + 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. +--%><%@page import="org.apache.jackrabbit.util.Text"%><% +request.setAttribute("title", "Content Repository Error"); +%> +

+ Some error occurred during setup. See the log files for details. +

+

back

+ Property changes on: jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/bootstrap/error.jsp ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/bootstrap/exists.jsp =================================================================== --- jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/bootstrap/exists.jsp (nonexistent) +++ jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/bootstrap/exists.jsp (working copy) @@ -0,0 +1,28 @@ +<%-- + 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. +--%><%@page import="org.apache.jackrabbit.util.Text"%><% +request.setAttribute("title", "Content Repository Exists"); +%> +

The repository home directory or configuration already exists.

+

+You have chosen to create a new repository but the specified home +directory or the configuration file already exist. +

+

+Please specify a correct location or choose to reuse an existing repository. +

+

back

+ Property changes on: jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/bootstrap/exists.jsp ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/bootstrap/missing.jsp =================================================================== --- jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/bootstrap/missing.jsp (nonexistent) +++ jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/bootstrap/missing.jsp (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. +--%><%@page import="org.apache.jackrabbit.util.Text"%><% +request.setAttribute("title", "Content Repository Setup"); +%> +

+ Your content repository is not properly configured yet. Please use + the forms below to setup the content repository. +

+

+ Alternatively, you can directly modify the settings in the + WEB-INF/web.xml deployment descriptor and redeploy this + web application. +

+ +

Create a new content repository

+
+ +

+ Use this form to create a new content repository in the given directory. + The directory is created by this web application and should not already + exist. The repository is created using a default configuration file. +

+

+ +

+

+
+ +

Use an existing content repository

+
+ +

+ Use this form to access an existing content repository in the given + directory. The repository configuration file should be available as + repository.xml within the given directory. +

+

+ Note that the repository can not be concurrently accessed by multiple + applications. You must use WebDAV or RMI through this web application + if you want to access the repository remotely. Other web applications + running in the same servlet container can access the repository locally + using JNDI. +

+

+ +

+

+
+ + Property changes on: jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/bootstrap/missing.jsp ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/bootstrap/notexists.jsp =================================================================== --- jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/bootstrap/notexists.jsp (nonexistent) +++ jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/bootstrap/notexists.jsp (working copy) @@ -0,0 +1,28 @@ +<%-- + 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. +--%><%@page import="org.apache.jackrabbit.util.Text"%><% +request.setAttribute("title", "Content Repository Not Found"); +%> +

The repository home directory or configuration do not exists.

+

+You have chosen to reuse an existing repository but the specified home +directory or the configuration file do not exist. +

+

+Please specify a correct location or choose to create a new repository. +

+

back

+ Property changes on: jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/bootstrap/notexists.jsp ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/bootstrap/reconfigure.jsp =================================================================== --- jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/bootstrap/reconfigure.jsp (nonexistent) +++ jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/bootstrap/reconfigure.jsp (working copy) @@ -0,0 +1,25 @@ +<%-- + 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. +--%><%@page import="org.apache.jackrabbit.util.Text"%><% +request.setAttribute("title", "Content Repository Already Running"); +%> +

Your repository is already properly configured an running.

+

+Your changes were discarded. To reconfigure or reinstall the repository modify +the respective configuration files or remove them. +

+

home

+ Property changes on: jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/bootstrap/reconfigure.jsp ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/bootstrap/running.jsp =================================================================== --- jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/bootstrap/running.jsp (nonexistent) +++ jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/bootstrap/running.jsp (working copy) @@ -0,0 +1,25 @@ +<%-- + 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. +--%><%@page import="org.apache.jackrabbit.util.Text"%><% +request.setAttribute("title", "Content Repository Ready"); +%> +

Your repository is properly configured an running.

+

+To reconfigure or reinstall the repository modify the respective configuration +files or remove them. +

+

home

+ Property changes on: jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/bootstrap/running.jsp ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/bootstrap/success.jsp =================================================================== --- jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/bootstrap/success.jsp (nonexistent) +++ jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/bootstrap/success.jsp (working copy) @@ -0,0 +1,25 @@ +<%-- + 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. +--%><%@page import="org.apache.jackrabbit.util.Text"%><% +request.setAttribute("title", "Content Repository Ready"); +%> +

Your repository is now properly configured an running.

+

+To reconfigure or reinstall the repository modify the respective configuration +files or remove them. +

+

home

+ Property changes on: jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/bootstrap/success.jsp ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/css/default.css =================================================================== --- jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/css/default.css (nonexistent) +++ jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/css/default.css (working copy) @@ -0,0 +1,91 @@ +/* + * 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. + */ + +body { font-family: Verdana, Helvetica, Arial, sans-serif; + font-size: small; color: #000000; + background-color: #e0e0e0; + margin: 1em 100px 1em 100px; + padding: 0; } + +#page { background-color: white; } + +a:link { color: #667C00; } +a:visited { color: #7C7C7C; } + +img { border: 0; } + +/* BANNER */ + +#banner { padding: 0 0 113px 0; + border-top: 6px solid black; + border-bottom: 2px solid black; } +#banner p { margin: 0; } +#jcr { float: left; } +#asf { float: right; } +#banner img { margin: 0; + padding: 10px 0 0 0; } +#banner a { text-decoration: none; } + +/* NAVIGATION */ + +#navigation { padding: 18px 0; + width: 180px; + float: left; + font-size: x-small; } + +#navigation ul + { margin: 0; + padding: 1ex 0 1ex 1em; + list-style: none; + font-weight: bold; } + +#navigation ul ul + { font-weight: normal; } + +#navigation a + { text-decoration: none; } + +a.external { font-style: italic; } + +/* CONTENT */ + +#content { margin: 1em 1em 1em 180px; } + +#content p { line-height: 1.3em; } + +h1, h2, h3 { color: #869900; } + +pre { background: #E0E0E0; + padding: 1em; + border: 1px dotted black; + overflow: auto; } + +td { font-size: small; } + +pre.code { font-family: monospace; font-size: small; + padding: 25px; } + +/* FOOTER */ + +#footer { clear: both; + border-top: 1px solid #999; + font-size: x-small; } + +#footer p { margin: 0; + text-align: center; } + +#footer a { text-decoration: none; } Property changes on: jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/css/default.css ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +author date id revision \ No newline at end of property Index: jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/error/classpath.jsp =================================================================== --- jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/error/classpath.jsp (nonexistent) +++ jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/error/classpath.jsp (working copy) @@ -0,0 +1,29 @@ +<%-- + 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. +--%><% +request.setAttribute("title", "JCR API Not Found"); +%> +

+The javax.jcr.Repository interface from the JCR API could not +be loaded. +

+

+To resolve this issue, you need to make the jcr-2.0.jar file +available in the shared classpath of the servlet container. The file is +available for download from the +JSR 283 web page. +

+ Property changes on: jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/error/classpath.jsp ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/error/repository.jsp =================================================================== --- jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/error/repository.jsp (nonexistent) +++ jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/error/repository.jsp (working copy) @@ -0,0 +1,42 @@ +<%-- + 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. +--%><%@ page isErrorPage="true" + import="org.apache.jackrabbit.util.Text, + java.io.StringWriter, + java.io.PrintWriter"%><% +request.setAttribute("title", "Repository Error"); +%> +

+ The content repository operation failed with the following + <%= exception.getClass().getSimpleName() %> error: +

+
<%= Text.encodeIllegalXMLCharacters(exception.getMessage()) %>
+

+ See the + troubleshooting page + for ideas on how to resolve this issue. +

+ +

Exception stack trace

+

+ Below is the full exception stack trace associated with this error: +

+<% +StringWriter buffer = new StringWriter(); +exception.printStackTrace(new PrintWriter(buffer)); +%> +
<%= Text.encodeIllegalXMLCharacters(buffer.toString()) %>
+ Property changes on: jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/error/repository.jsp ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/footer.jsp =================================================================== --- jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/footer.jsp (nonexistent) +++ jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/footer.jsp (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. +--%> + + + + + Property changes on: jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/footer.jsp ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/header.jsp =================================================================== --- jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/header.jsp (nonexistent) +++ jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/header.jsp (working copy) @@ -0,0 +1,88 @@ +<%-- + 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. +--%> +<%@page import="org.apache.jackrabbit.util.Text"%> +<% +String title = + Text.encodeIllegalXMLCharacters(request.getAttribute("title").toString()); +String context = + Text.encodeIllegalXMLCharacters(request.getContextPath()); +%> + + + + <%= title %> + + + + +
+ + +
+

<%= title %>

Property changes on: jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/header.jsp ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/images/0.gif =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Property changes on: jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/images/0.gif ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/images/asf-logo.gif =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Property changes on: jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/images/asf-logo.gif ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/images/asf-logo.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = image/png Property changes on: jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/images/asf-logo.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +image/png \ No newline at end of property Index: jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/images/favicon.ico =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Property changes on: jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/images/favicon.ico ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/images/jackrabbit.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = image/png Property changes on: jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/images/jackrabbit.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +image/png \ No newline at end of property Index: jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/images/jackrabbitlogo.gif =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Property changes on: jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/images/jackrabbitlogo.gif ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/images/jlogo.gif =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Property changes on: jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/images/jlogo.gif ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/index.jsp =================================================================== --- jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/index.jsp (nonexistent) +++ jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/index.jsp (working copy) @@ -0,0 +1,22 @@ +<%-- + 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. +--%><% +try { + Class.forName("javax.jcr.Repository"); +} catch (ClassNotFoundException e) { + throw new org.apache.jackrabbit.j2ee.JcrApiNotFoundException(e); +} +%> \ No newline at end of file Property changes on: jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/index.jsp ___________________________________________________________________ Added: svn Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/local.jsp =================================================================== --- jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/local.jsp (nonexistent) +++ jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/local.jsp (working copy) @@ -0,0 +1,103 @@ +<%-- + 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. +--%><%@page import="org.apache.jackrabbit.util.Text"%><% +request.setAttribute("title", "Local Repository Access"); +%> +

+ The content repository within this web application can be accessed + locally by other web applications within the same servlet container. + Local access is much faster than remote access. +

+

+ The content repository is made available both through JNDI and the + web application context. +

+ +

Accessing the repository through JNDI

+

+ By default the repository is only made available in a dummy JNDI directory + local to this web application. However, you can make the repository globally + available if your servlet container allows a web application to modify the + global JNDI directory or you are using some other JNDI directory that can + manage unserializable Java objects. +

+

+ To bind the the repository to such a JNDI directory, you need to modify + the java.naming parameters in either the /WEB-INF/web.xml + deployment descriptor or the jackrabbit/bootstrap.properties file. You need + to redeploy this web application to activate the changes. +

+

+ Use the following code to access a repository bound in a JNDI directory: +

+
+import javax.jcr.Repository;
+import javax.naming.Context;
+import javax.naming.InitialContext;
+
+Context context = new InitialContext(...);
+Repository repository = (Repository) context.lookup(...);
+
+ +

Accessing the repository through servlet context

+

+ This web application makes the repository available as the + javax.jcr.Repository attribute in the application context. + If your servlet container supports cross-context access, you can + access the repository directly using that attribute. +

+

+ For example in Apache Tomcat + you can enable cross-context access by setting the crossContext + attribute to true in the <Context/> configuration. +

+

+ Use the following code to access a repository through the servlet context: +

+
+import javax.jcr.Repository;
+import javax.servlet.ServletContext;
+
+ServletContext context = ...; // context of your servlet
+ServletContext jackrabbit =
+    context.getContext("<%= Text.encodeIllegalXMLCharacters(request.getContextPath()) %>");
+Repository repository = (Repository)
+    context.getAttribute(Repository.class.getName()).
+
+ +

Using the jackrabbit-jcr-servlet component

+

+ The jackrabbit-jcr-servlet component contains utility classes + for use within JCR web applications. With that component you can hide + both the above and the remote access options + from your code, and use just the following to access a repository: +

+
+import javax.jcr.Repository;
+import org.apache.jackrabbit.servlet.ServletRepository;
+
+public class MyServlet extends HttpServlet {
+
+    private final Repository repository = new ServletRepository(this);
+
+    // ...
+
+}
+
+

+ See the jackrabbit-jcr-servlet documentation for more details. +

+ Property changes on: jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/local.jsp ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/remote.jsp =================================================================== --- jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/remote.jsp (nonexistent) +++ jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/remote.jsp (working copy) @@ -0,0 +1,106 @@ +<%@ page import="java.net.URI"%><%-- + 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. +--%><%@page import="org.apache.jackrabbit.util.Text"%><% +request.setAttribute("title", "Remote Repository Access"); + +URI uri = new URI(request.getRequestURL().toString()); +String base = + uri.getScheme() + "://" + uri.getHost() + ":" + uri.getPort() + + request.getContextPath(); +base = Text.encodeIllegalXMLCharacters(base); +%> +

+ The content repository within this web application is made available + to remote clients through + RMI + and the jackrabbit-jcr-rmi component. +

+

+ The remote repository stub is available both in the RMI registry + (one is started automatically by this web application if not already running) + and as a direct HTTP download. The default URLs for accessing the remote + repository are: +

+
    +
  • RMI registry: //localhost/jackrabbit.repository
  • +
  • HTTP download: <%= base %>/rmi
  • +
+

+ Note that the above URLs are the defaults. You can disable or change them + by modifying the /WEB-INF/web.xml deployment descriptor. +

+ +

Accessing the remote repository

+

+ To access the remote content repository you need to use the + jackrabbit-jcr-rmi component in your application. If you use + Maven 2, you can declare the JCR and jackrabbit-jcr-rmi dependencies + like this: +

+
<dependency>
+  <groupId>javax.jcr</groupId>
+  <artifactId>jcr</artifactId>
+  <version>1.0</version>
+</dependency>
+<dependency>
+  <groupId>org.apache.jackrabbit</groupId>
+  <artifactId>jackrabbit-jcr-rmi</artifactId>
+  <version>1.4</version>
+</dependency>
+
+

+ With that dependency in place, you can use either the RMI registry or + the direct HTTP download to access the repository. +

+

+ The required code for accessing the repository using the RMI registry is: +

+
+import javax.jcr.Repository;
+import org.apache.jackrabbit.rmi.repository.RMIRemoteRepository;
+
+Repository repository =
+    new RMIRemoteRepository("//localhost/jackrabbit.repository");
+
+

+ The required code for accessing the repository using the RMI registry is: +

+
+import javax.jcr.Repository;
+import org.apache.jackrabbit.rmi.repository.URLRemoteRepository;
+
+Repository repository =
+    new URLRemoteRepository("<%= base %>/rmi");
+
+

+ See the JCR specification + and the + Repository + javadoc for details on what to do with the acquired Repository instance. +

+ +

Remote access performance

+

+ Note that the design goal of the current jackrabbit-jcr-rmi component + is correct and complete functionality instead of performance, so you should + not rely on remote access for performance-critical applications. +

+

+ You may want to look at the Jackrabbit clustering feature for best + performance for concurrently accessing the repository on multiple separate + servers. +

+ Property changes on: jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/remote.jsp ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/remoting/footer.jsp =================================================================== --- jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/remoting/footer.jsp (nonexistent) +++ jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/remoting/footer.jsp (working copy) @@ -0,0 +1,25 @@ +<%-- + 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. +--%> + +
+ + Property changes on: jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/remoting/footer.jsp ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +author date id revision \ No newline at end of property Index: jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/remoting/header.jsp =================================================================== --- jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/remoting/header.jsp (nonexistent) +++ jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/remoting/header.jsp (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. +--%> +<%@page import="org.apache.jackrabbit.util.Text"%> +<% +String context = Text.encodeIllegalXMLCharacters(request.getContextPath()); +%> + + + + JCR Remoting Server + + + + +
+ + Property changes on: jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/remoting/header.jsp ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +author date id revision \ No newline at end of property Index: jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/remoting/index.jsp =================================================================== --- jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/remoting/index.jsp (nonexistent) +++ jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/remoting/index.jsp (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. +--%><% +%> +
+

JCR Remoting Server - Introduction

+

Ths section shortly overviews the batch read/write extensions + added to the JCR remoting feature. +

+

+

Some principals are demonstrated in the corresponding example section.

+
+ \ No newline at end of file Property changes on: jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/remoting/index.jsp ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +author date id revision \ No newline at end of property Index: jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/remoting/json.js =================================================================== --- jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/remoting/json.js (nonexistent) +++ jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/remoting/json.js (working copy) @@ -0,0 +1,222 @@ +/* + 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. +*/ + +function getXMLHttpRequest(url, method, headers, params) { + var xmlhttp = null; + if (window.XMLHttpRequest) { + // code for all new browsers + xmlhttp = new XMLHttpRequest(); + } else if (window.ActiveXObject) { + // code for IE + try { + xmlhttp = new ActiveXObject("Msxml2.XMLHTTP"); + } catch (e) { + xmlhttp = new ActiveXObject("Microsoft.XMLHTTP"); + } + } + if (xmlhttp) { + if (!method) { + method = "GET"; + } + xmlhttp.open(method, url, false); + if (headers) { + for (var hdr in headers) { + xmlhttp.setRequestHeader(hdr, headers[hdr]); + } + } + xmlhttp.send(params); + return xmlhttp; + } else { + alert("Your browser does not support XMLHTTP."); + return null; + } +} + +var JsonFormatter = null; +(function() { + + JsonFormatter = new Object(); + JsonFormatter.clear = false; + + JsonFormatter.tree = function(jsonObj, baseHref) { + if (!jsonObj) { + return ""; + } + var indentionLevel = 0; + return JsonFormatter.objectTree("", jsonObj, indentionLevel, baseHref); + } + + JsonFormatter.format = function(jsonObj, clearSpecial) { + if (!jsonObj) { + return ""; + } + var indentionLevel = 0; + clear = clearSpecial; + return JsonFormatter.object(jsonObj, indentionLevel); + } + + JsonFormatter.addLineBreak = function(str) { + return str += "
"; + } + + JsonFormatter.addIndention = function(str, indention, indStr) { + for (var i = 0; i < indention; i++) { + str += indStr; + } + return str; + } + + JsonFormatter.object = function(value, indentionLevel) { + if (value instanceof Array) { + return JsonFormatter.array(value, indentionLevel); + } + + var str = "{"; + str = JsonFormatter.addLineBreak(str); + indentionLevel++; + var delim = false; + + for (var i in value) { + var v = value[i]; + if (clear && i.charAt(0) == ':') { + // skip special prop. + // TODO: evaluate and add to display info. + } else { + var fnctn = JsonFormatter[typeof v]; + if (fnctn) { + v = fnctn(v, indentionLevel); + if (typeof v == 'string') { + if (delim) { + str += ","; + str = JsonFormatter.addLineBreak(str); + } + str = JsonFormatter.addIndention(str, indentionLevel, "\t"); + str += JsonFormatter.string(i) + ' : ' + v; + delim = true; + } + } + } + } + indentionLevel--; + str = JsonFormatter.addLineBreak(str); + str = JsonFormatter.addIndention(str, indentionLevel, "\t"); + str += "}"; + return str; + } + + JsonFormatter.array = function(value, indentionLevel) { + var str = "["; + var delim = false; + for (var i in value) { + var arrVal = value[i]; + var fnctn = JsonFormatter[typeof arrVal]; + if (fnctn) { + arrVal = fnctn(arrVal); + if (delim) { + str += ", "; + } + str += arrVal; + delim = true; + } + } + str += "]"; + return str; + } + + JsonFormatter.boolean = function(value, indentionLevel) { + return String(value); + } + + JsonFormatter.string = function(value, indentionLevel) { + return '"' + value + '"'; + + } + + JsonFormatter.number = function(value, indentionLevel) { + return String(value); + } + + JsonFormatter.extractPropertyType = function(key, value) { + if (key == "::NodeIteratorSize") { + return null; + } else if (key.charAt(0) == ':' && typeof value == 'string') { + return value; + } else { + return null; + } + } + + JsonFormatter.buildKey = function(key, propType, href) { + var keyStr = key; + if (propType) { + var href = "javascript:alert('PropertyType = " + propType + "');"; + keyStr = "" + key + ""; + } else if (key.charAt(0) == ':') { + // binary + var propname = key.substring(1, key.length); + var binHref = href + "/" + propname; + keyStr = "" + propname + ""; + } + return keyStr; + } + + JsonFormatter.objectTree = function(key, value, indentionLevel, href) { + var str = "+ " + key; // + node-name + if (href && href.charAt(href.length - 1) == '/') { + href += key; + } else { + href += "/" + key; + } + + indentionLevel++; + var propType; + var childSize; + var delim = false; + + for (var i in value) { + var v = value[i]; + var pt = JsonFormatter.extractPropertyType(i, v); + if (pt) { + propType = pt; + continue; + } else if (i == "::NodeIteratorSize") { + continue; + } + str = JsonFormatter.addLineBreak(str); + str = JsonFormatter.addIndention(str, indentionLevel, "  "); + if (v instanceof Array) { + // value array - propname + var key = JsonFormatter.buildKey(i, propType, href); + propType = null; + str += "- " + key + ' = ' + JsonFormatter.array(v, indentionLevel); + } else if (v instanceof Object) { + str += JsonFormatter.objectTree(i, v, indentionLevel, href); + } else { + // simple value - propname + var fnctn = JsonFormatter[typeof v]; + if (fnctn) { + v = fnctn(v, indentionLevel); + var key = JsonFormatter.buildKey(i, propType, href); + propType = null; + str += "- " + key + ' = ' + v; + } + } + } + indentionLevel--; + return str; + } +})(); Property changes on: jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/remoting/json.js ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/remoting/read.jsp =================================================================== --- jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/remoting/read.jsp (nonexistent) +++ jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/remoting/read.jsp (working copy) @@ -0,0 +1,65 @@ +<%@ page import="java.net.URI" %> +<%@ page import="org.apache.jackrabbit.j2ee.JcrRemotingServlet" %> +<%@ page import="org.apache.jackrabbit.util.Text" %> +<%-- + 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. +--%><% + +URI uri = new URI(request.getRequestURL().toString()); +String href = + uri.getScheme() + "://" + uri.getHost() + ":" + uri.getPort() + + request.getContextPath() + + JcrRemotingServlet.getPathPrefix(pageContext.getServletContext()); +href = Text.encodeIllegalXMLCharacters(href); +href += "/default/jcr:root"; + +%> +
+

Read

+

Default Reading

+

Reading remotely from the repository generally follows the rules described in + JCR_Webdav_Protocol.zip. +

+

Batch Read

+

Batch read is triggered by adding a '.json' extension to the resource + href. Optionally the client may explicitely specify the desired batch + read depth by appending '.depth.json' extension. If no json extension + is present the GET request is processed by applied the default + remoting rules. +

+

The response to a batch read request contains a plain text representing + a JSON object. Its member either represent nodes or properties. +

    +
  • The name element of the Item path is added as key
  • +
  • The value of a Node entry is a JSON object.
  • +
  • The value of a Property entry is either a JSON array or a simple JSON value.
  • +
+

+

In order to cope with property types that cannot be expressed with JSON + a couple of special rules are defined: +

    +
  • Binary properties: The key gets a leading ":", the value represents the + length of the property. In order to retrieve the binary value, the + client must follow the default rules (see above).
  • +
  • Date, Name, Path and Reference properties: The type information is passed with a separate JSON pair.
  • +
  • The value of a Property entry is either a JSON array or a simple JSON value.
  • +
+

+ See Example: Batch Write for a demostration of + the batch read functionality. +

+
+ \ No newline at end of file Property changes on: jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/remoting/read.jsp ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +author date id revision \ No newline at end of property Index: jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/remoting/read_batch.jsp =================================================================== --- jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/remoting/read_batch.jsp (nonexistent) +++ jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/remoting/read_batch.jsp (working copy) @@ -0,0 +1,104 @@ +<%@ page import="java.net.URI" %> +<%@ page import="org.apache.jackrabbit.j2ee.JcrRemotingServlet" %> +<%@ page import="org.apache.jackrabbit.util.Text" %> +<%-- + 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. +--%><% + +URI uri = new URI(request.getRequestURL().toString()); +String href = + uri.getScheme() + "://" + uri.getHost() + ":" + uri.getPort() + + request.getContextPath() + + JcrRemotingServlet.getPathPrefix(pageContext.getServletContext()); +href = Text.encodeIllegalXMLCharacters(href); +href += "/default/jcr:root"; + +%> + + +
+

Examples: Batch Read

+

+ Enter the path of an existing node and the desired depth. +

+ + + + + + + + + + + + + + +
Node Path
Depth
Result type
+

+


+
+ \ No newline at end of file Property changes on: jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/remoting/read_batch.jsp ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +author date id revision \ No newline at end of property Index: jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/remoting/write.jsp =================================================================== --- jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/remoting/write.jsp (nonexistent) +++ jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/remoting/write.jsp (working copy) @@ -0,0 +1,161 @@ +<%@ page import="java.net.URI" %> +<%@ page import="org.apache.jackrabbit.j2ee.JcrRemotingServlet" %> +<%@ page import="org.apache.jackrabbit.util.Text" %> +<%-- + 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. +--%><% + +URI uri = new URI(request.getRequestURL().toString()); +String href = + uri.getScheme() + "://" + uri.getHost() + ":" + uri.getPort() + + request.getContextPath() + + JcrRemotingServlet.getPathPrefix(pageContext.getServletContext()); +href = Text.encodeIllegalXMLCharacters(href); +href += "/default/jcr:root"; + +%> +
+

Write

+

Default Writing

+

Writing remotely to the repository generally follows the rules described in + JCR_Webdav_Protocol.zip. +

+

Batch Write

+

A set of transient modifications can in addition be sent by using the + extended batch write: A single POST request that contains a custom + :diff parameter describing the changes to be applied. + The expected format is described in the + JavaDoc. +

+ Some cases however can be easily demonstrated. The following examples can + be tested with the form provided at + Example: Batch Write. +

+

Examples

+

The following examples illustrate the basics of the diff format. It does + not cover the special treatment of properties with type Date, + Name, Path, Reference and Binary (see below).

+

Set properties

+
+^prop1  : "stringvalue"
+^prop1  : "changedvalue"
+^prop2  : true
+^prop3  : 100.010
+^prop4  : 1234567890
+^prop5  : ["multi","valued","string prop"]
+^.      : "change existing property at path."
+^/abs/path/to/the/new/prop : "some value."
+

Add new nodes (optionally including child items)

+
++node   : {"title" : "title property of the new node"}
++node2  : {"childN" : {}, "childN2" : {}}
++/abs/path/to/the/new/node : {"text" : "some text"}
+

Move or rename nodes

+
+>node   : rename
+>rename : /moved/to/another/destination
+

Reorder nodes

+
+>childN : childN2#after
+>childN : #first
+>childN : #last
+>childN : childN2#before
+

Remove items

+
+-prop4  :
+-node2  :
+-/moved/to/another/destination :
+

Dealing with Special Property Types

+

Property types that can not be covered unambigously, need some special + handling (see JavaDoc). This affects JCR properties being of type +

    +
  • Date,
  • +
  • Name,
  • +
  • Path,
  • +
  • Reference,
  • +
  • Binary.
  • +
+ In order to set properties of any of the types listed, the value part in the + :diff param must be left empty and a separate request parameter must be + included. Its name equals the corresponding key in the :diff, its value represents + the property value. In addition the desired property type must be specified + using the conversion defined with + JcrValueType#contentTypeFromType(int). +

+

Set a Date property

+
+POST /jackrabbit/server/default/jcr%3aroot/testNode HTTP/1.1
+Content-Type: multipart/form-data; boundary=kTmAb2lkjCtxbMVFzHEplAJjHCUo5aQndaUu
+
+--kTmAb2lkjCtxbMVFzHEplAJjHCUo5aQndaUu
+Content-Disposition: form-data; name="dateProp"
+Content-Type: jcr-value/date
+
+2009-02-12T10:19:40.778+01:00         
+--kTmAb2lkjCtxbMVFzHEplAJjHCUo5aQndaUu
+Content-Disposition: form-data; name=":diff"
+Content-Type: text/plain
+
+^dateProp :  
+--kTmAb2lkjCtxbMVFzHEplAJjHCUo5aQndaUu--
+    
+

Setting Binary, Name, Path or Reference + properties works accordingly. +

+ +

Direct Content Editing

+

The functionality present with batch reading also enables very simplified + content editing using common HTML forms.

+

The :diff parameter is omitted altogether and each request parameter is + treated as property +

    +
  • param name : property name
  • +
  • param value : property value
  • +
+ whereas the form action indicates the path of the parent node. +

+

If no node exists at the specified path an attempt is made to create the + missing intermediate nodes. The primary node type of the new node is + either retrieved from the corresponding jcr:primaryType param or + automatically determined by the implementation.

+

Setting a property can be tested at + Example: Simplified Writing +

+

Examples

+

The following examples illustrate the simplified writing.

+

Set string property +

    +
  • Existing or non-existing node at /testnode
  • +
  • Set property 'propName' with value "any string value"
  • +
+

+
+<form method="POST" action="<%= href %>/testnode">
+    <input type="text" name="propName" value="any string value"/>
+</form>
+

Add node with a defined node type and set a property

+
    +
  • Non-existing node at /testnode/nonexisting
  • +
  • Define its primary type to be "nt:unstructured"
  • +
  • Set property 'propName' with value "any string value"
  • +
+
+<form method="POST" action="<%= href %>/nonexisting">
+    <input type="text" name="jcr:primaryType" value="nt:unstructured"/>
+    <input type="text" name="propName" value="any string value"/>
+</form>
+
+ \ No newline at end of file Property changes on: jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/remoting/write.jsp ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +author date id revision \ No newline at end of property Index: jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/remoting/write_batch.jsp =================================================================== --- jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/remoting/write_batch.jsp (nonexistent) +++ jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/remoting/write_batch.jsp (working copy) @@ -0,0 +1,84 @@ +<%@ page import="java.net.URI" %> +<%@ page import="org.apache.jackrabbit.j2ee.JcrRemotingServlet" %> +<%@ page import="org.apache.jackrabbit.util.Text" %> +<%-- + 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. +--%><% + +URI uri = new URI(request.getRequestURL().toString()); +String href = + uri.getScheme() + "://" + uri.getHost() + ":" + uri.getPort() + + request.getContextPath() + + JcrRemotingServlet.getPathPrefix(pageContext.getServletContext()); +href = Text.encodeIllegalXMLCharacters(href); +href += "/default/jcr:root"; + +%> + + +
+

Examples: Batch Write

+

+ Enter the path of an existing node or property (depending on the desired + actions) and enter the :diff value. +

+

See the introduction to batched writing + for examples. +

+ + + + + + + + + + +
Item Path
Diff
+

+


+
+ \ No newline at end of file Property changes on: jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/remoting/write_batch.jsp ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +author date id revision \ No newline at end of property Index: jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/remoting/write_simple.jsp =================================================================== --- jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/remoting/write_simple.jsp (nonexistent) +++ jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/remoting/write_simple.jsp (working copy) @@ -0,0 +1,101 @@ +<%@ page import="java.net.URI" %> +<%@ page import="org.apache.jackrabbit.j2ee.JcrRemotingServlet" %> +<%@ page import="org.apache.jackrabbit.util.Text" %> +<%-- + 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. +--%><% + +URI uri = new URI(request.getRequestURL().toString()); +String href = + uri.getScheme() + "://" + uri.getHost() + ":" + uri.getPort() + + request.getContextPath() + + JcrRemotingServlet.getPathPrefix(pageContext.getServletContext()); +href = Text.encodeIllegalXMLCharacters(href); +href += "/default/jcr:root"; + +%> + + +
+

Examples: Simplified Writing

+

If the JCR node at the specified absolute path allows to set a properties + with name title or text, submitting the form below will + will set those properties to the given values.

+

If no JCR node exists at the specified absolute path, the missing + intermediate nodes will be created if an applicable node type for the + specified node name(s) can be determined.

+ + + + + + + + + + + + + + +
Node Path
Title
Text
+

+


+
+ \ No newline at end of file Property changes on: jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/remoting/write_simple.jsp ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +author date id revision \ No newline at end of property Index: jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/search.jsp =================================================================== --- jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/search.jsp (nonexistent) +++ jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/search.jsp (working copy) @@ -0,0 +1,254 @@ +<%-- + 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. +--%><%@ page import="javax.jcr.Repository, + org.apache.jackrabbit.j2ee.RepositoryAccessServlet, + org.apache.jackrabbit.util.Text, + javax.jcr.Session, + javax.jcr.SimpleCredentials, + javax.jcr.query.Query, + javax.jcr.query.RowIterator, + java.text.NumberFormat, + javax.jcr.query.Row, + javax.jcr.Node, + java.net.URLEncoder, + java.text.SimpleDateFormat, + java.text.DateFormat, + java.util.List, + java.util.ArrayList, + java.util.Iterator, + javax.jcr.Value, + javax.jcr.RepositoryException"%> +<%@ page contentType="text/html;charset=UTF-8" %><% + Repository rep; + Session jcrSession; + try { + rep = RepositoryAccessServlet.getRepository(pageContext.getServletContext()); + jcrSession = rep.login(new SimpleCredentials("anonymous", "".toCharArray())); + } catch (Throwable e) { + %>Error while accessing the repository: <%= Text.encodeIllegalXMLCharacters(e.getMessage()) %>
<% + %>Check the configuration or use the easy setup wizard.<% + return; + } + try { + String wspName = jcrSession.getWorkspace().getName(); + String q = request.getParameter("q"); + if (q == null) { + q = ""; + } else { + q = new String(q.getBytes("ISO-8859-1"), "UTF-8"); + } + if (request.getParameter("as_q") != null) { + q += " " + new String(request.getParameter("as_q").getBytes("ISO-8859-1"), "UTF-8"); + } + String executedIn = ""; + String queryTerms = ""; + String totalResults = ""; + long from = 0; + long to = 10; + long total = 0; + long maxPage = 0; + long minPage = 0; + long currentPageIndex = 0; + List indexes = new ArrayList(); + RowIterator rows = null; + String suggestedQuery = null; + if (q != null && q.length() > 0) { + String stmt; + if (q.startsWith("related:")) { + String path = q.substring("related:".length()); + path = path.replaceAll("'", "''"); + stmt = "//element(*, nt:file)[rep:similar(jcr:content, '" + path + "/jcr:content')]/rep:excerpt(.) order by @jcr:score descending"; + queryTerms = "similar to " + Text.encodeIllegalXMLCharacters(path) + ""; + } else { + queryTerms = "for " + Text.encodeIllegalXMLCharacters(q) + ""; + q = q.replaceAll("'", "''"); + stmt = "//element(*, nt:file)[jcr:contains(jcr:content, '" + q + "')]/rep:excerpt(.) order by @jcr:score descending"; + } + Query query = jcrSession.getWorkspace().getQueryManager().createQuery(stmt, Query.XPATH); + long time = System.currentTimeMillis(); + rows = query.execute().getRows(); + time = System.currentTimeMillis() - time; + NumberFormat nf = NumberFormat.getNumberInstance(); + nf.setMaximumFractionDigits(2); + nf.setMinimumFractionDigits(2); + executedIn = nf.format(((double) time) / 1000d); + nf.setMaximumFractionDigits(0); + totalResults = nf.format(rows.getSize()); + if (request.getParameter("start") != null) { + from = Long.parseLong(request.getParameter("start")); + try { + rows.skip(from); + } catch (Exception e) { + // make sure rows are consumed + while (rows.hasNext()) { + rows.nextRow(); + } + } + } + to = Math.min(from + 10, rows.getSize()); + + total = rows.getSize(); + maxPage = total / 10L; + if (total % 10L > 0) { + maxPage++; + } + currentPageIndex = from / 10L; + maxPage = Math.min(maxPage, currentPageIndex + 10); + minPage = Math.max(0, currentPageIndex - 10); + for (long i = minPage; i < maxPage; i++) { + indexes.add(new Long(i)); + } + + if (total < 10 && !q.startsWith("related:")) { + try { + Value v = jcrSession.getWorkspace().getQueryManager().createQuery( + "/jcr:root[rep:spellcheck('" + q + "')]/(rep:spellcheck())", + Query.XPATH).execute().getRows().nextRow().getValue("rep:spellcheck()"); + if (v != null) { + suggestedQuery = v.getString(); + } + } catch (RepositoryException e) { + // ignore + } + } + } +request.setAttribute("title", "Search workspace " + wspName); +%> + +
+

+ +

+

+
+<% if (rows != null && rows.getSize() == 0) { %> +<% if (suggestedQuery != null) { %> +

Did you mean: + + <%= Text.encodeIllegalXMLCharacters(suggestedQuery) %> +
+

+<% } %> +

Your search - <%= Text.encodeIllegalXMLCharacters(q) %> - did not match any documents. +

Suggestions: +

    +
  • Make sure all words are spelled correctly.
  • +
  • Try different keywords.
  • +
  • Try more general keywords.
  • +
  • Try fewer keywords.
  • +
+ <% + } else if (rows != null) { + %> + + + +
Results <%= from + 1 %> - <%= to %> of about <%= totalResults %> <%= queryTerms %>. (<%= executedIn %> seconds) 
+<% if (suggestedQuery != null) { %> +

+ Did you mean: + + <%= Text.encodeIllegalXMLCharacters(suggestedQuery) %> +
+

+<% } %> +
+ <% + while (rows.hasNext() && rows.getPosition() < to) { + Row r = rows.nextRow(); + Node file = (Node) jcrSession.getItem(r.getValue("jcr:path").getString()); + Node resource = file.getNode("jcr:content"); + String size = ""; + if (resource.hasProperty("jcr:data")) { + double length = resource.getProperty("jcr:data").getLength(); + size = String.valueOf(Math.round(Math.ceil(length / 1000d))) + "k"; + } + DateFormat df = SimpleDateFormat.getDateInstance(SimpleDateFormat.LONG); + String lastModified = df.format(resource.getProperty("jcr:lastModified").getDate().getTime()); + %> +
" class=l><%= Text.encodeIllegalXMLCharacters(file.getName()) %>
+ + + +
<%= r.getValue("rep:excerpt(jcr:content)").getString() %> + <%= Text.encodeIllegalXMLCharacters(file.getPath()) %> - <%= size %> - <%= lastModified %> - ">Similar pages
+ <% + } // while + %> +
+ +
+ <% + if (indexes.size() > 1) { + %> +
+ + +
Result Page:  + <% + if (currentPageIndex != ((Long) indexes.get(0)).longValue()) { + %>&start=<%= (currentPageIndex - 1) * 10 %>>Previous<% + } else { + %><% + } + for (Iterator it = indexes.iterator(); it.hasNext(); ) { + long pageIdx = ((Long) it.next()).longValue(); + if (pageIdx == currentPageIndex) { + %><%= pageIdx + 1 %><% + } else { + %>&start=<%= pageIdx * 10 %>><%= pageIdx + 1 %><% + } + } + if (currentPageIndex < (maxPage - 1)) { + %>&start=<%= (currentPageIndex + 1) * 10 %>>Next<% + } else { + %><% + } + %> +
+
+ <% + } + %> + + +

+ + +

/search.jsp> + +
+
+ Search within results | Dissatisfied? Help us improve
+
+
+ + <% + } // if (rows != null) + + String tableClass = ""; + if (rows != null && rows.getSize() == 0) { + tableClass = " class=\"t n bt\""; + } + %> + +<% + } finally { + if (jcrSession != null) { + jcrSession.logout(); + } + } +%> \ No newline at end of file Property changes on: jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/search.jsp ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/swr.jsp =================================================================== --- jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/swr.jsp (nonexistent) +++ jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/swr.jsp (working copy) @@ -0,0 +1,69 @@ +<%-- + 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. +--%><%@ page import="javax.jcr.Repository, + javax.jcr.Session, + org.apache.jackrabbit.j2ee.RepositoryAccessServlet, + org.apache.jackrabbit.util.Text, + javax.jcr.SimpleCredentials, + java.text.NumberFormat" +%><%@ page contentType="text/html;charset=UTF-8" %><% + Repository rep; + Session jcrSession; + try { + rep = RepositoryAccessServlet.getRepository(pageContext.getServletContext()); + jcrSession = rep.login(new SimpleCredentials("anonymous", "".toCharArray())); + } catch (Throwable e) { + %>Error while accessing the repository: <%= Text.encodeIllegalXMLCharacters(e.getMessage()) %>
<% + %>Check the configuration or use the easy setup wizard.<% + return; + } + try { + String q = new String(request.getParameter("q").getBytes("ISO-8859-1"), "UTF-8"); + String swrnum = request.getParameter("swrnum"); + String numResults = null; + try { + numResults = NumberFormat.getNumberInstance().format(Long.parseLong(swrnum)); + } catch (NumberFormatException e) { + // ignore + } + if (q == null || numResults == null) { + return; + } + + request.setAttribute("title", "Search within results"); + %> +
+ + + +

There were about <%= numResults %> results for <%= Text.encodeIllegalXMLCharacters(q) %>.
+ Use the search box below to search within these results.

+
+
+ + + +
+
+
+ +<% + } finally { + if (jcrSession != null) { + jcrSession.logout(); + } + } +%> \ No newline at end of file Property changes on: jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/swr.jsp ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/troubleshooting.jsp =================================================================== --- jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/troubleshooting.jsp (nonexistent) +++ jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/troubleshooting.jsp (working copy) @@ -0,0 +1,105 @@ +<%-- + 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. +--%><%@page import="org.apache.jackrabbit.util.Text, + java.io.StringWriter, + java.io.PrintWriter"%><% +request.setAttribute("title", "Troubleshooting"); +%> +

+ If you experience problems with the Jackrabbit JCR server, please + check the following: +

+
    +
  1. + Did you encounter an exception? Copy the exception stack trace somewhere + so you don't loose it. The stack trace contains valuable information + for the Jackrabbit developers if you need to file a bug report for the + problem you encountered. +
  2. +
  3. + Is the repository up and running? Try browsing the + default workspace + to check if you can still see any content in the repository. You will + see an error message if the repository is not available. +
  4. +
  5. + What were you trying to do? Try to verify that your client code or + other manner of repository use is correct. Did it work before or are + you trying to do something new? +
  6. +
  7. + Are there any notable log entries? Check the log files for any related + warnings or errors. By default the Jackrabbit JCR Server writes log + entries to the standard output of the servlet container. You can customize + logging by editing the /WEB-INF/log4j.xml file and + redeploying this web application. +
  8. +
+

+ If none of the above steps help you identify or resolve the problem, + you can contact the Jackrabbit users mailing list or report the problem + in the Jackrabbit issue tracker to get support from the Jackrabbit community. + When contacting the community, please include any relevant details related + to the above questions and the environment information shown at the end + of this page. +

+ +

Jackrabbit mailing list

+

+ The Jackrabbit user mailing list, users@jackrabbit.apache.org, is the + place to discuss any problems or other issues regarding the use of + Apache Jackrabbit (or JCR content repositories in general). +

+

+ Feel free to subscribe the mailing list or browse the archives listed as + described in the + Jackrabbit mailing lists + page. +

+ +

Jackrabbit issue tracker

+

+ If you think you've identified a defect in Jackrabbit, you're welcome + to file a bug report in the + Jackrabbit issue tracker. + You can also use the issue tracker to request new features and other + improvements. +

+

+ You need an account in the issue tracker to report new issues or to comment + on existing. Use the + registration form + if you don't already have an account. No account is needed browsing + and searching existing issues. +

+ +

Environment information

+

+ This instance of the Jackrabbit JCR Server is running in + a <%= Text.encodeIllegalXMLCharacters(application.getServerInfo()) %> servlet container + that supports the Java Servlet API version + <%= application.getMajorVersion() %>.<%= application.getMinorVersion() %>. +

+

+ Details of the Java and operating system environment are included in + the system properties shown below: +

+<% +StringWriter buffer = new StringWriter(); +System.getProperties().list(new PrintWriter(buffer)); +%> +
<%= Text.encodeIllegalXMLCharacters(buffer.toString()) %>
+ Property changes on: jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/troubleshooting.jsp ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/webdav-jcr.jsp =================================================================== --- jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/webdav-jcr.jsp (nonexistent) +++ jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/webdav-jcr.jsp (working copy) @@ -0,0 +1,88 @@ +<%@ page import="org.apache.jackrabbit.j2ee.JCRWebdavServerServlet, + java.net.URI" +%><%-- + 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. +--%><%@page import="org.apache.jackrabbit.util.Text"%><% +request.setAttribute("title", "JCR Remoting Server"); + +URI uri = new URI(request.getRequestURL().toString()); +int port = uri.getPort(); +String href = + uri.getScheme() + "://" + uri.getHost() + (port == -1 ? "" : (":" + port)) + + request.getContextPath() + + JCRWebdavServerServlet.getPathPrefix(pageContext.getServletContext()); +href = Text.encodeIllegalXMLCharacters(href); +String shref = href + "/default/jcr:root"; +%> +

+ The JCR Remoting Server provides an item-based WebDAV view to the + JCR repository, mapping the functionality provided by JSR 170 to the + WebDAV protocol in order to allow remote content repository access + via WebDAV. +

+

+ See the draft document + JCR_Webdav_Protocol.zip + for more details regarding this remoting protocol. +

+

+ Batch read and write as well as the missing functionality (cross workspace + copy and clone) has been addressed with a extension + to the remoting server. +

+ +

Access the content repository

+

+ Use the following URLs to access the content repository in your remoting client: +

+
+
<%= href %>
+
to access all workspaces of your JCR repository
+
<%= shref %>
+
to access a single workspace (example with workspace named 'default')
+
+ +

Supported WebDAV functionality

+

+ This implementation focuses on replicating all JCR features for remote + access instead of providing standard WebDAV functionality or compatibility + with existing WebDAV clients. +

+

+ The following RFCs are used to implement the remoting functionality: +

+ + +

JCR Remoting Client

+

+ For the client counterpart of this WebDAV servlet please take a look at the + Jackrabbit SPI2DAV + module. +

+ +

Configuration

+
    +
  • Context Path: <%= Text.encodeIllegalXMLCharacters(request.getContextPath()) %>
  • +
  • Resource Path Prefix: <%= Text.encodeIllegalXMLCharacters(JCRWebdavServerServlet.getPathPrefix(pageContext.getServletContext())) %>
  • +
  • Workspace Name: optional (available workspaces are mapped as resources)
  • +
  • Additional servlet configuration: see /WEB-INF/web.xml
  • +
+ Property changes on: jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/webdav-jcr.jsp ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/webdav-remoting.jsp =================================================================== --- jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/webdav-remoting.jsp (nonexistent) +++ jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/webdav-remoting.jsp (working copy) @@ -0,0 +1,92 @@ +<%@ page import="org.apache.jackrabbit.j2ee.JCRWebdavServerServlet, + java.net.URI" +%><%-- + 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. +--%><%@page import="org.apache.jackrabbit.util.Text"%> +<%@ page import="org.apache.jackrabbit.j2ee.JcrRemotingServlet" %> +<% +request.setAttribute("title", "JCR Remoting Server with Batch Read/Write"); + +URI uri = new URI(request.getRequestURL().toString()); +int port = uri.getPort(); +String href = + uri.getScheme() + "://" + uri.getHost() + (port == -1 ? "" : (":" + port)) + + request.getContextPath() + + JCRWebdavServerServlet.getPathPrefix(pageContext.getServletContext()); +href = Text.encodeIllegalXMLCharacters(href); +String shref = href + "/default/jcr:root"; +%> +

+ The JCR Remoting Server provides an item-based WebDAV view to the + JCR repository, mapping the functionality provided by JSR 170 to the + WebDAV protocol in order to allow remote content repository access + via WebDAV. +

+

+ This implementation variant adds batch read and write functionality to the initial + JCR Remoting Server. In addition it supports + copy across workspaces and clone. +

+ +

Access the content repository

+

+ Use the following URLs to access the content repository in the remoting client: +

+
+
<%= href %>
+
to access all workspaces of your JCR repository
+
<%= shref %>
+
to access a single workspace (example with workspace named 'default')
+
+ +

Supported WebDAV functionality

+

+ See JCR Remoting Server. +

+ +

Batch Read

+

+Composes a JSON object for a node (and its child items) up to a explicitely +specified or configuration determined depth. +
+See JavaDoc for details +or try the Examples. +

+ +

Batch Write

+

+In contrast to the default JCR remoting this extended version allows to send +a block of modifications (SPI Batch) within a single POST request containing a +custom ":diff" parameter. +
+See the JavaDoc for details +or try the Examples. +

+ +

JCR Remoting Client

+

+ For the client counterpart of this WebDAV servlet please take a look at the extended SPI2DAV + project. +

+ +

Configuration

+
    +
  • Context Path: <%= Text.encodeIllegalXMLCharacters(request.getContextPath()) %>
  • +
  • Resource Path Prefix: <%= Text.encodeIllegalXMLCharacters(JcrRemotingServlet.getPathPrefix(pageContext.getServletContext())) %>
  • +
  • Workspace Name: optional (available workspaces are mapped as resources)
  • +
  • Additional servlet configuration: see /WEB-INF/web.xml
  • +
+ Property changes on: jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/webdav-remoting.jsp ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/webdav-simple.jsp =================================================================== --- jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/webdav-simple.jsp (nonexistent) +++ jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/webdav-simple.jsp (working copy) @@ -0,0 +1,84 @@ +<%@ page import="org.apache.jackrabbit.j2ee.SimpleWebdavServlet, + java.net.URI" +%><%-- + 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. +--%><%@page import="org.apache.jackrabbit.util.Text"%><% +request.setAttribute("title", "Standard WebDAV Server"); + +URI uri = new URI(request.getRequestURL().toString()); +int port = uri.getPort(); +String href = + uri.getScheme() + "://" + uri.getHost() + (port == -1 ? "" : (":" + port)) + + request.getContextPath() + + SimpleWebdavServlet.getPathPrefix(pageContext.getServletContext()) + + "/default/"; +href = Text.encodeIllegalXMLCharacters(href); +%> + +

+ The default WebDAV server (aka: Simple Server) is a + DAV 1,2 and + DeltaV + compliant WebDAV server implementation. It offers a file-based view to + the JCR repository, suitable for everybody looking for standard WebDAV + functionality. Essentially, the contents of the underlying content + repository are exposed as a hierarchical collection of files and folders. +

+ +

Access the content repository

+

+ Use the following URL to access the content repository in your WebDAV client: +

+ +

+ The server asks for authentication and will accept credentials for the default + admin user: admin/admin. You can modify this security policy in + the repository configuration file. +

+

+ To access other workspace than the default one, replace the last part of + the URL (/default/) with the name of another workspace. +

+

+ You can also search the default workspace. +

+ +

File system access

+

+ Many operating systems, including Windows and Mac OS X, allow you to + "mount" a WebDAV server as a shared network disk. You can use the above + URL to make the default workspace available as such a network disk, after + which you can use normal file system tools to copy files and folders to + and from the content repository. +

+ +

Supported WebDAV functionality

+ + +

Configuration

+
    +
  • Context path: <%= Text.encodeIllegalXMLCharacters(request.getContextPath()) %>
  • +
  • Resource path prefix: <%= Text.encodeIllegalXMLCharacters(SimpleWebdavServlet.getPathPrefix(pageContext.getServletContext())) %>
  • +
  • Servlet configuration: see /WEB-INF/web.xml
  • +
  • WebDAV specific resource configuration: see /WEB-INF/config.xml
  • +
+ Property changes on: jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/webdav-simple.jsp ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/welcome.jsp =================================================================== --- jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/welcome.jsp (nonexistent) +++ jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/welcome.jsp (working copy) @@ -0,0 +1,60 @@ +<%@ page import="org.apache.jackrabbit.j2ee.RepositoryAccessServlet, + javax.jcr.Repository" +%><%-- + 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. +--%><% + +Repository rep; +try { + rep = RepositoryAccessServlet.getRepository(pageContext.getServletContext()); +} catch (Throwable e) { + %><% +} + +request.setAttribute("title", "Apache Jackrabbit JCR Server"); +%> +

+ Welcome to the Apache Jackrabbit JCR Server. This web application + contains a JCR content repository and makes it available to clients + through WebDAV and other means. +

+

+ The following WebDAV view is provided for accessing the + content in the JCR content repository. +

+ +

+ In addition the JCR Server project provides means for JCR remoting over HTTP: +

+ +

+ Clients can also access the repository using the JCR API. Both local + and remote access is supported. +

+ +

+ For more information, including copyright and licensing details, visit the + About Apache Jackrabbit page. +

+ Property changes on: jackrabbit-webapp-project/jackrabbit-webapp/src/main/webapp/welcome.jsp ___________________________________________________________________ Added: svn Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webapp-project/jackrabbit-webapp/src/test/java/org/apache/jackrabbit/j2ee/TomcatIT.java =================================================================== --- jackrabbit-webapp-project/jackrabbit-webapp/src/test/java/org/apache/jackrabbit/j2ee/TomcatIT.java (nonexistent) +++ jackrabbit-webapp-project/jackrabbit-webapp/src/test/java/org/apache/jackrabbit/j2ee/TomcatIT.java (working copy) @@ -0,0 +1,137 @@ +/* + * 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.j2ee; + +import java.io.BufferedWriter; +import java.io.File; +import java.io.IOException; +import java.net.URL; +import java.nio.charset.StandardCharsets; +import java.util.List; + +import junit.framework.TestCase; + +import org.apache.catalina.startup.Tomcat; +import org.apache.commons.io.FileUtils; +import org.slf4j.bridge.SLF4JBridgeHandler; + +import com.gargoylesoftware.htmlunit.WebClient; +import com.gargoylesoftware.htmlunit.html.HtmlElement; +import com.gargoylesoftware.htmlunit.html.HtmlForm; +import com.gargoylesoftware.htmlunit.html.HtmlInput; +import com.gargoylesoftware.htmlunit.html.HtmlPage; +import com.google.common.io.Files; + +public class TomcatIT extends TestCase { + + static { + SLF4JBridgeHandler.install(); + } + + private URL url; + + private Tomcat tomcat; + + private WebClient client; + + protected void setUp() throws Exception { + File war = null; + for (File f : new File("target").listFiles()) { + if (f.isDirectory() && new File(f, "WEB-INF/web.xml").isFile()) { + war = f; + break; + } + } + assertNotNull(war); + rewriteWebXml(war); + + File bootstrap = new File("target", "bootstrap.properties"); + bootstrap.delete(); + + File baseDir = new File("target", "tomcat"); + FileUtils.deleteQuietly(baseDir); + + File repoDir = new File("target", "repository"); + FileUtils.deleteQuietly(repoDir); + + url = new URL("http://localhost:12856/"); + + tomcat = new Tomcat(); + tomcat.setSilent(true); + tomcat.setBaseDir(baseDir.getPath()); + tomcat.setHostname(url.getHost()); + tomcat.setPort(url.getPort()); + + tomcat.addWebapp("", war.getAbsolutePath()); + + tomcat.start(); + + client = new WebClient(); + } + + public void testTomcat() throws Exception { + HtmlPage page = client.getPage(url); + assertEquals("Content Repository Setup", page.getTitleText()); + + page = submitNewRepositoryForm(page); + assertEquals("Content Repository Ready", page.getTitleText()); + + page = page.getAnchorByText("home").click(); + assertEquals("Apache Jackrabbit JCR Server", page.getTitleText()); + } + + private HtmlPage submitNewRepositoryForm(HtmlPage page) throws IOException { + for (HtmlForm form : page.getForms()) { + for (HtmlInput mode : form.getInputsByName("mode")) { + if ("new".equals(mode.getValueAttribute())) { + for (HtmlInput home : form.getInputsByName("repository_home")) { + home.setValueAttribute("target/repository"); + for (HtmlElement submit : form.getElementsByAttribute("input", "type", "submit")) { + return submit.click(); + } + } + } + } + } + fail(); + return null; + } + + private void rewriteWebXml(File war) throws IOException { + File webXml = new File(war, new File("WEB-INF","web.xml").getPath()); + assertTrue(webXml.exists()); + List lines = Files.readLines(webXml, StandardCharsets.UTF_8); + BufferedWriter writer = Files.newWriter(webXml, StandardCharsets.UTF_8); + try { + for (String line : lines) { + line = line.replace("jackrabbit/bootstrap.properties", + "target/bootstrap.properties"); + writer.write(line); + writer.write(System.lineSeparator()); + } + } finally { + writer.close(); + } + } + + protected void tearDown() throws Exception { + client.close(); + + tomcat.stop(); + } + +} Property changes on: jackrabbit-webapp-project/jackrabbit-webapp/src/test/java/org/apache/jackrabbit/j2ee/TomcatIT.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webapp-project/jackrabbit-webapp/src/test/resources/compatibility.zip =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Property changes on: jackrabbit-webapp-project/jackrabbit-webapp/src/test/resources/compatibility.zip ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: jackrabbit-webapp-project/jackrabbit-webapp/src/test/resources/logback-test.xml =================================================================== --- jackrabbit-webapp-project/jackrabbit-webapp/src/test/resources/logback-test.xml (nonexistent) +++ jackrabbit-webapp-project/jackrabbit-webapp/src/test/resources/logback-test.xml (working copy) @@ -0,0 +1,31 @@ + + + + + + target/jcr.log + + %date{HH:mm:ss.SSS} %-5level %-40([%thread] %F:%L) %msg%n + + + + + + + + Property changes on: jackrabbit-webapp-project/jackrabbit-webapp/src/test/resources/logback-test.xml ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webapp-project/jackrabbit-webapp =================================================================== --- jackrabbit-webapp-project/jackrabbit-webapp (nonexistent) +++ jackrabbit-webapp-project/jackrabbit-webapp (working copy) Property changes on: jackrabbit-webapp-project/jackrabbit-webapp ___________________________________________________________________ Added: svn:ignore ## -0,0 +1,5 ## +target +.* +*.iws +*.ipr +*.iml Index: jackrabbit-webapp-project/jackrabbit-webapp-jakarta/.classpath =================================================================== --- jackrabbit-webapp-project/jackrabbit-webapp-jakarta/.classpath (nonexistent) +++ jackrabbit-webapp-project/jackrabbit-webapp-jakarta/.classpath (working copy) @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Index: jackrabbit-webapp-project/jackrabbit-webapp-jakarta/.project =================================================================== --- jackrabbit-webapp-project/jackrabbit-webapp-jakarta/.project (nonexistent) +++ jackrabbit-webapp-project/jackrabbit-webapp-jakarta/.project (working copy) @@ -0,0 +1,23 @@ + + + jackrabbit-webapp-jakarta + + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.m2e.core.maven2Builder + + + + + + org.eclipse.jdt.core.javanature + org.eclipse.m2e.core.maven2Nature + + Index: jackrabbit-webapp-project/jackrabbit-webapp-jakarta/.settings/org.eclipse.core.resources.prefs =================================================================== --- jackrabbit-webapp-project/jackrabbit-webapp-jakarta/.settings/org.eclipse.core.resources.prefs (nonexistent) +++ jackrabbit-webapp-project/jackrabbit-webapp-jakarta/.settings/org.eclipse.core.resources.prefs (working copy) @@ -0,0 +1,6 @@ +eclipse.preferences.version=1 +encoding//src/main/java=UTF-8 +encoding//src/main/resources=UTF-8 +encoding//src/test/java=UTF-8 +encoding//src/test/resources=UTF-8 +encoding/=UTF-8 Index: jackrabbit-webapp-project/jackrabbit-webapp-jakarta/.settings/org.eclipse.jdt.core.prefs =================================================================== --- jackrabbit-webapp-project/jackrabbit-webapp-jakarta/.settings/org.eclipse.jdt.core.prefs (nonexistent) +++ jackrabbit-webapp-project/jackrabbit-webapp-jakarta/.settings/org.eclipse.jdt.core.prefs (working copy) @@ -0,0 +1,8 @@ +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 +org.eclipse.jdt.core.compiler.compliance=1.8 +org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled +org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning +org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=ignore +org.eclipse.jdt.core.compiler.release=disabled +org.eclipse.jdt.core.compiler.source=1.8 Index: jackrabbit-webapp-project/jackrabbit-webapp-jakarta/.settings/org.eclipse.m2e.core.prefs =================================================================== --- jackrabbit-webapp-project/jackrabbit-webapp-jakarta/.settings/org.eclipse.m2e.core.prefs (nonexistent) +++ jackrabbit-webapp-project/jackrabbit-webapp-jakarta/.settings/org.eclipse.m2e.core.prefs (working copy) @@ -0,0 +1,4 @@ +activeProfiles= +eclipse.preferences.version=1 +resolveWorkspaceProjects=true +version=1 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-webapp-project/jackrabbit-webapp-jakarta/target/.plxarc =================================================================== --- jackrabbit-webapp-project/jackrabbit-webapp-jakarta/target/.plxarc (nonexistent) +++ jackrabbit-webapp-project/jackrabbit-webapp-jakarta/target/.plxarc (working copy) @@ -0,0 +1 @@ +maven-shared-archive-resources \ No newline at end of file Index: jackrabbit-webapp-project/jackrabbit-webapp-jakarta/target/classes/META-INF/DEPENDENCIES =================================================================== --- jackrabbit-webapp-project/jackrabbit-webapp-jakarta/target/classes/META-INF/DEPENDENCIES (nonexistent) +++ jackrabbit-webapp-project/jackrabbit-webapp-jakarta/target/classes/META-INF/DEPENDENCIES (working copy) @@ -0,0 +1,253 @@ +// ------------------------------------------------------------------ +// Transitive dependencies of this project determined from the +// maven pom organized by organization. +// ------------------------------------------------------------------ + +jackrabbit-webapp-jakarta + + +From: 'an unknown organization' + - parso (https://github.com/epam/parso) com.epam:parso:jar:2.0.14 + License: Apache License v2 (http://www.apache.org/licenses/LICENSE-2.0.html) + - Java Unrar (https://github.com/junrar/junrar) com.github.junrar:junrar:jar:7.5.2 + License: UnRar License (https://github.com/junrar/junrar/LICENSE.md) + - curvesapi (https://github.com/virtuald/curvesapi) com.github.virtuald:curvesapi:jar:1.07 + License: BSD License (http://opensource.org/licenses/BSD-3-Clause) + - juniversalchardet (http://juniversalchardet.googlecode.com/) com.googlecode.juniversalchardet:juniversalchardet:jar:1.0.3 + License: Mozilla Public License 1.1 (MPL 1.1) (http://www.mozilla.org/MPL/MPL-1.1.html) + - dd-plist (http://www.github.com/3breadt/dd-plist) com.googlecode.plist:dd-plist:jar:1.23 + License: MIT License (http://opensource.org/licenses/mit) + - java-libpst (https://github.com/rjohnsondev/java-libpst) com.pff:java-libpst:jar:0.9.3 + License: The Apache Software License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt) + - rome (http://rometools.com/rome) com.rometools:rome:jar:1.18.0 + License: The Apache Software License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt) + - rome-utils (http://rometools.com/rome-utils) com.rometools:rome-utils:jar:1.18.0 + License: The Apache Software License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt) + - Bouncy Castle S/MIME API (https://www.bouncycastle.org/java.html) org.bouncycastle:bcmail-jdk15on:jar:1.70 + License: Bouncy Castle Licence (https://www.bouncycastle.org/licence.html) + - Bouncy Castle PKIX, CMS, EAC, TSP, PKCS, OCSP, CMP, and CRMF APIs (https://www.bouncycastle.org/java.html) org.bouncycastle:bcpkix-jdk15on:jar:1.70 + License: Bouncy Castle Licence (https://www.bouncycastle.org/licence.html) + - Bouncy Castle Provider (https://www.bouncycastle.org/java.html) org.bouncycastle:bcprov-jdk15on:jar:1.70 + License: Bouncy Castle Licence (https://www.bouncycastle.org/licence.html) + - Bouncy Castle ASN.1 Extension and Utility APIs (https://www.bouncycastle.org/java.html) org.bouncycastle:bcutil-jdk15on:jar:1.70 + License: Bouncy Castle Licence (https://www.bouncycastle.org/licence.html) + - org.brotli:dec (http://brotli.org/dec) org.brotli:dec:jar:0.1.2 + License: MIT License (http://www.opensource.org/licenses/mit-license.php) + - TagSoup (http://home.ccil.org/~cowan/XML/tagsoup/) org.ccil.cowan.tagsoup:tagsoup:jar:1.2.1 + License: Apache License 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt) + - JHighlight (https://github.com/codelibs/jhighlight) org.codelibs:jhighlight:jar:1.1.0 + License: CDDL, v1.0 (http://www.opensource.org/licenses/cddl1.php) License: LGPL, v2.1 or later (http://www.opensource.org/licenses/lgpl-license.php) + - Ogg and Vorbis for Java, Core (https://github.com/Gagravarr/VorbisJava) org.gagravarr:vorbis-java-core:jar:0.8 + License: The Apache Software License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Tika plugin for Ogg, Vorbis and FLAC (https://github.com/Gagravarr/VorbisJava) org.gagravarr:vorbis-java-tika:jar:0.8 + License: The Apache Software License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt) + - jwarc (https://github.com/iipc/jwarc) org.netpreserve:jwarc:jar:0.18.1 + License: Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt) + - JMatIO (https://github.com/tballison/jmatio) org.tallison:jmatio:jar:1.5 + License: BSD (http://www.linfo.org/bsdlicense.html) + - XZ for Java (https://tukaani.org/xz/java.html) org.tukaani:xz:jar:1.9 + License: Public Domain + - Xerces2-j (https://xerces.apache.org/xerces2-j/) xerces:xercesImpl:jar:2.12.2 + License: The Apache Software License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt) + - XML Commons External Components XML APIs (http://xml.apache.org/commons/components/external/) xml-apis:xml-apis:jar:1.4.01 + License: The Apache Software License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt) License: The SAX License (http://www.saxproject.org/copying.html) License: The W3C License (http://www.w3.org/TR/2004/REC-DOM-Level-3-Core-20040407/java-binding.zip) + +From: 'Apache Software Foundation' (http://db.apache.org/) + - Apache Derby Database Engine and Embedded JDBC Driver (http://db.apache.org/derby/) org.apache.derby:derby:jar:10.14.2.0 + License: Apache 2 (http://www.apache.org/licenses/LICENSE-2.0.txt) + +From: 'Apache Software Foundation' (http://www.apache.org/) + - Apache POI - Common (https://poi.apache.org/) org.apache.poi:poi:jar:5.2.2 + License: Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache POI - API based on OPC and OOXML schemas (https://poi.apache.org/) org.apache.poi:poi-ooxml:jar:5.2.2 + License: Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache POI (https://poi.apache.org/) org.apache.poi:poi-ooxml-lite:jar:5.2.2 + License: Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache POI (https://poi.apache.org/) org.apache.poi:poi-scratchpad:jar:5.2.2 + License: Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt) + +From: 'Day Software' (http://www.day.com) + - Content Repository for JavaTM Technology API (http://www.jcp.org/en/jsr/detail?id=283) javax.jcr:jcr:jar:2.0 + License: Day Specification License (http://www.day.com/dam/day/downloads/jsr283/day-spec-license.htm) License: Day Specification License addendum (http://www.day.com/content/dam/day/downloads/jsr283/LICENSE.txt) + +From: 'Dough Lea' (http://gee.cs.oswego.edu/dl/classes/EDU/oswego/cs/dl/util/concurrent/intro.html) + - Dough Lea's util.concurrent package concurrent:concurrent:jar:1.3.4 + License: Public domain, Sun Microsoystems (>http://gee.cs.oswego.edu/dl/classes/EDU/oswego/cs/dl/util/concurrent/intro.html) + +From: 'Eclipse Foundation' (https://www.eclipse.org) + - Jakarta Activation (https://github.com/eclipse-ee4j/jaf/jakarta.activation) com.sun.activation:jakarta.activation:jar:1.2.2 + License: EDL 1.0 (http://www.eclipse.org/org/documents/edl-v10.php) + - istack common utility code runtime (https://projects.eclipse.org/projects/ee4j/istack-commons/istack-commons-runtime) com.sun.istack:istack-commons-runtime:jar:3.0.12 + License: Eclipse Distribution License - v 1.0 (http://www.eclipse.org/org/documents/edl-v10.php) + - Jakarta XML Binding API (https://github.com/eclipse-ee4j/jaxb-api/jakarta.xml.bind-api) jakarta.xml.bind:jakarta.xml.bind-api:jar:2.3.3 + License: Eclipse Distribution License - v 1.0 (http://www.eclipse.org/org/documents/edl-v10.php) + - JAXB Runtime (https://eclipse-ee4j.github.io/jaxb-ri/) org.glassfish.jaxb:jaxb-runtime:jar:2.3.6 + License: Eclipse Distribution License - v 1.0 (http://www.eclipse.org/org/documents/edl-v10.php) + - TXW2 Runtime (https://eclipse-ee4j.github.io/jaxb-ri/) org.glassfish.jaxb:txw2:jar:2.3.6 + License: Eclipse Distribution License - v 1.0 (http://www.eclipse.org/org/documents/edl-v10.php) + +From: 'jai-imageio GitHub group' (https://github.com/jai-imageio/) + - Java Advanced Imaging Image I/O Tools API core (standalone) (https://github.com/jai-imageio/jai-imageio-core) com.github.jai-imageio:jai-imageio-core:bundle:1.4.0 + License: BSD 3-clause License w/nuclear disclaimer (LICENSE.txt) + +From: 'JDOM' (http://www.jdom.org) + - JDOM (http://www.jdom.org) org.jdom:jdom2:jar:2.0.6.1 + License: Similar to Apache License but with the acknowledgment clause removed (https://raw.github.com/hunterhacker/jdom/master/LICENSE.txt) + +From: 'OpenHMS' (https://openhms.sourceforge.io/) + - Jackcess (https://jackcess.sourceforge.io) com.healthmarketscience.jackcess:jackcess:jar:4.0.1 + License: Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt) + - Jackcess Encrypt (http://jackcessencrypt.sf.net) com.healthmarketscience.jackcess:jackcess-encrypt:jar:4.0.1 + License: Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt) + +From: 'OW2' (http://www.ow2.org/) + - asm (http://asm.ow2.io/) org.ow2.asm:asm:jar:9.3 + License: BSD-3-Clause (https://asm.ow2.io/license.html) + +From: 'QOS.ch' (http://www.qos.ch) + - Logback Classic Module (http://logback.qos.ch/logback-classic) ch.qos.logback:logback-classic:jar:1.2.11 + License: Eclipse Public License - v 1.0 (http://www.eclipse.org/legal/epl-v10.html) License: GNU Lesser General Public License (http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html) + - Logback Core Module (http://logback.qos.ch/logback-core) ch.qos.logback:logback-core:jar:1.2.11 + License: Eclipse Public License - v 1.0 (http://www.eclipse.org/legal/epl-v10.html) License: GNU Lesser General Public License (http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html) + - JCL 1.2 implemented over SLF4J (http://www.slf4j.org) org.slf4j:jcl-over-slf4j:jar:1.7.36 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - SLF4J API Module (http://www.slf4j.org) org.slf4j:slf4j-api:jar:1.7.36 + License: MIT License (http://www.opensource.org/licenses/mit-license.php) + +From: 'The Apache Software Foundation' (http://pdfbox.apache.org) + - Apache FontBox (http://pdfbox.apache.org/) org.apache.pdfbox:fontbox:bundle:2.0.26 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - PDFBox JBIG2 ImageIO plugin (https://www.apache.org/jbig2-imageio/) org.apache.pdfbox:jbig2-imageio:jar:3.0.4 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache JempBox (http://www.apache.org/pdfbox-parent/jempbox/) org.apache.pdfbox:jempbox:bundle:1.8.16 + License: Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache PDFBox (https://www.apache.org/pdfbox-parent/pdfbox/) org.apache.pdfbox:pdfbox:bundle:2.0.26 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache PDFBox Debugger (https://www.apache.org/pdfbox-parent/pdfbox-debugger/) org.apache.pdfbox:pdfbox-debugger:jar:2.0.26 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache PDFBox tools (https://www.apache.org/pdfbox-parent/pdfbox-tools/) org.apache.pdfbox:pdfbox-tools:jar:2.0.26 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache XmpBox (https://www.apache.org/pdfbox-parent/xmpbox/) org.apache.pdfbox:xmpbox:bundle:2.0.26 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + +From: 'The Apache Software Foundation' (http://www.apache.org) + - Apache Tika core (https://tika.apache.org/) org.apache.tika:tika-core:bundle:2.4.1 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + +From: 'The Apache Software Foundation' (http://www.apache.org/) + - Apache Commons Collections (http://commons.apache.org/collections/) commons-collections:commons-collections:jar:3.2.2 + License: Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt) + - Commons DBCP (http://commons.apache.org/dbcp/) commons-dbcp:commons-dbcp:jar:1.4 + License: The Apache Software License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Commons Logging (http://commons.apache.org/proper/commons-logging/) commons-logging:commons-logging:jar:1.2 + License: The Apache Software License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt) + - Commons Pool (http://commons.apache.org/pool/) commons-pool:commons-pool:jar:1.5.4 + License: The Apache Software License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Commons Exec (http://commons.apache.org/proper/commons-exec/) org.apache.commons:commons-exec:jar:1.3 + License: Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Commons Math (http://commons.apache.org/proper/commons-math/) org.apache.commons:commons-math3:jar:3.6.1 + License: Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache HttpClient (http://hc.apache.org/httpcomponents-client-ga) org.apache.httpcomponents:httpclient:jar:4.5.14 + License: Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache HttpCore (http://hc.apache.org/httpcomponents-core-ga) org.apache.httpcomponents:httpcore:jar:4.4.16 + License: Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt) + - Lucene Core (http://lucene.apache.org/java/lucene-parent/lucene-core) org.apache.lucene:lucene-core:jar:3.6.0 + License: Apache 2 (http://www.apache.org/licenses/LICENSE-2.0.txt) + +From: 'The Apache Software Foundation' (https://www.apache.org/) + - Apache Commons BeanUtils (https://commons.apache.org/proper/commons-beanutils/) commons-beanutils:commons-beanutils:jar:1.9.4 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Commons Codec (https://commons.apache.org/proper/commons-codec/) commons-codec:commons-codec:jar:1.15 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Commons FileUpload (https://commons.apache.org/proper/commons-fileupload/) commons-fileupload:commons-fileupload:jar:1.5 + License: Apache-2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Commons IO (https://commons.apache.org/proper/commons-io/) commons-io:commons-io:jar:2.11.0 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Commons Collections (https://commons.apache.org/proper/commons-collections/) org.apache.commons:commons-collections4:jar:4.4 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Commons CSV (https://commons.apache.org/proper/commons-csv/) org.apache.commons:commons-csv:jar:1.9.0 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Commons Lang (https://commons.apache.org/proper/commons-lang/) org.apache.commons:commons-lang3:jar:3.12.0 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Jackrabbit Core (http://jackrabbit.apache.org/jackrabbit-core/) org.apache.jackrabbit:jackrabbit-core:jar:2.21.16-SNAPSHOT + License: Apache-2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Jackrabbit Data (http://jackrabbit.apache.org/jackrabbit-data/) org.apache.jackrabbit:jackrabbit-data:bundle:2.21.16-SNAPSHOT + License: Apache-2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Jackrabbit JCR Commons (http://jackrabbit.apache.org/jackrabbit-jcr-commons/) org.apache.jackrabbit:jackrabbit-jcr-commons:bundle:2.21.16-SNAPSHOT + License: Apache-2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Jackrabbit JCR-RMI (http://jackrabbit.apache.org/jackrabbit-jcr-rmi/) org.apache.jackrabbit:jackrabbit-jcr-rmi:bundle:2.21.16-SNAPSHOT + License: Apache-2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - jackrabbit-jcr-server-jakarta (http://jackrabbit.apache.org/jackrabbit-jcr-server-project/jackrabbit-jcr-server-jakarta/) org.apache.jackrabbit:jackrabbit-jcr-server-jakarta:jar:2.21.16-SNAPSHOT + License: Apache-2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - jackrabbit-jcr-servlet-jakarta (http://jackrabbit.apache.org/jackrabbit-jcr-servlet-project/jackrabbit-jcr-servlet-jakarta/) org.apache.jackrabbit:jackrabbit-jcr-servlet-jakarta:jar:2.21.16-SNAPSHOT + License: Apache-2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Jackrabbit SPI (http://jackrabbit.apache.org/jackrabbit-spi/) org.apache.jackrabbit:jackrabbit-spi:bundle:2.21.16-SNAPSHOT + License: Apache-2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Jackrabbit SPI Commons (http://jackrabbit.apache.org/jackrabbit-spi-commons/) org.apache.jackrabbit:jackrabbit-spi-commons:bundle:2.21.16-SNAPSHOT + License: Apache-2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - jackrabbit-webdav-jakarta (http://jackrabbit.apache.org/jackrabbit-webdav-project/jackrabbit-webdav-jakarta/) org.apache.jackrabbit:jackrabbit-webdav-jakarta:jar:2.21.16-SNAPSHOT + License: Apache-2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Jackrabbit API (http://jackrabbit.apache.org/oak-jackrabbit-api/) org.apache.jackrabbit:oak-jackrabbit-api:bundle:1.48.0 + License: Apache-2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Log4j API (https://logging.apache.org/log4j/2.x/log4j-api/) org.apache.logging.log4j:log4j-api:jar:2.17.2 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Tika Apple parser module (https://tika.apache.org/tika-parser-apple-module/) org.apache.tika:tika-parser-apple-module:jar:2.4.1 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Tika audiovideo parser module (https://tika.apache.org/tika-parser-audiovideo-module/) org.apache.tika:tika-parser-audiovideo-module:jar:2.4.1 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Tika cad parser module (https://tika.apache.org/tika-parser-cad-module/) org.apache.tika:tika-parser-cad-module:jar:2.4.1 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Tika code parser module (https://tika.apache.org/tika-parser-code-module/) org.apache.tika:tika-parser-code-module:jar:2.4.1 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Tika crypto parser module (https://tika.apache.org/tika-parser-crypto-module/) org.apache.tika:tika-parser-crypto-module:jar:2.4.1 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Tika digest commons (https://tika.apache.org/tika-parser-digest-commons/) org.apache.tika:tika-parser-digest-commons:jar:2.4.1 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Tika font parser module (https://tika.apache.org/tika-parser-font-module/) org.apache.tika:tika-parser-font-module:jar:2.4.1 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Tika html commons (https://tika.apache.org/tika-parser-html-commons/) org.apache.tika:tika-parser-html-commons:jar:2.4.1 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Tika html parser module (https://tika.apache.org/tika-parser-html-module/) org.apache.tika:tika-parser-html-module:jar:2.4.1 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Tika image parser module (https://tika.apache.org/tika-parser-image-module/) org.apache.tika:tika-parser-image-module:jar:2.4.1 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Tika mail commons (https://tika.apache.org/tika-parser-mail-commons/) org.apache.tika:tika-parser-mail-commons:jar:2.4.1 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Tika mail parser module (https://tika.apache.org/tika-parser-mail-module/) org.apache.tika:tika-parser-mail-module:jar:2.4.1 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Tika Microsoft parser module (https://tika.apache.org/tika-parser-microsoft-module/) org.apache.tika:tika-parser-microsoft-module:jar:2.4.1 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Tika miscellaneous office format parser module (https://tika.apache.org/tika-parser-miscoffice-module/) org.apache.tika:tika-parser-miscoffice-module:jar:2.4.1 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Tika news parser module (https://tika.apache.org/tika-parser-news-module/) org.apache.tika:tika-parser-news-module:jar:2.4.1 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Tika OCR parser module (https://tika.apache.org/tika-parser-ocr-module/) org.apache.tika:tika-parser-ocr-module:jar:2.4.1 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Tika PDF parser module (https://tika.apache.org/tika-parser-pdf-module/) org.apache.tika:tika-parser-pdf-module:jar:2.4.1 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Tika package parser module (https://tika.apache.org/tika-parser-pkg-module/) org.apache.tika:tika-parser-pkg-module:jar:2.4.1 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Tika text parser module (https://tika.apache.org/tika-parser-text-module/) org.apache.tika:tika-parser-text-module:jar:2.4.1 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Tika WARC parser module (https://tika.apache.org/tika-parser-webarchive-module/) org.apache.tika:tika-parser-webarchive-module:jar:2.4.1 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Tika XML parser module (https://tika.apache.org/tika-parser-xml-module/) org.apache.tika:tika-parser-xml-module:jar:2.4.1 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Tika XMP commons (https://tika.apache.org/tika-parser-xmp-commons/) org.apache.tika:tika-parser-xmp-commons:jar:2.4.1 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Tika ZIP commons (https://tika.apache.org/tika-parser-zip-commons/) org.apache.tika:tika-parser-zip-commons:jar:2.4.1 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Tika standard parser package (https://tika.apache.org/tika-parsers/tika-parsers-standard/tika-parsers-standard-package/) org.apache.tika:tika-parsers-standard-package:jar:2.4.1 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + +From: 'XmlBeans' (https://xmlbeans.apache.org/) + - XmlBeans (https://xmlbeans.apache.org/) org.apache.xmlbeans:xmlbeans:jar:5.0.3 + License: The Apache Software License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt) + +From: 'Zaxxer.com' (https://github.com/brettwooldridge/SparseBitSet) + - SparseBitSet (https://github.com/brettwooldridge/SparseBitSet) com.zaxxer:SparseBitSet:jar:1.2 + License: The Apache Software License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt) + + + + Index: jackrabbit-webapp-project/jackrabbit-webapp-jakarta/target/classes/META-INF/LICENSE =================================================================== --- jackrabbit-webapp-project/jackrabbit-webapp-jakarta/target/classes/META-INF/LICENSE (nonexistent) +++ jackrabbit-webapp-project/jackrabbit-webapp-jakarta/target/classes/META-INF/LICENSE (working copy) @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed 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. Index: jackrabbit-webapp-project/jackrabbit-webapp-jakarta/target/classes/META-INF/NOTICE =================================================================== --- jackrabbit-webapp-project/jackrabbit-webapp-jakarta/target/classes/META-INF/NOTICE (nonexistent) +++ jackrabbit-webapp-project/jackrabbit-webapp-jakarta/target/classes/META-INF/NOTICE (working copy) @@ -0,0 +1,8 @@ + +jackrabbit-webapp-jakarta +Copyright 2004-1970 The Apache Software Foundation + +This product includes software developed at +The Apache Software Foundation (http://www.apache.org/). + + Index: jackrabbit-webapp-project/jackrabbit-webapp-jakarta/target/classes/META-INF/maven/org.apache.jackrabbit/jackrabbit-webapp-jakarta/pom.properties =================================================================== --- jackrabbit-webapp-project/jackrabbit-webapp-jakarta/target/classes/META-INF/maven/org.apache.jackrabbit/jackrabbit-webapp-jakarta/pom.properties (nonexistent) +++ jackrabbit-webapp-project/jackrabbit-webapp-jakarta/target/classes/META-INF/maven/org.apache.jackrabbit/jackrabbit-webapp-jakarta/pom.properties (working copy) @@ -0,0 +1,7 @@ +#Generated by Maven Integration for Eclipse +#Wed Mar 01 12:30:08 CET 2023 +m2e.projectLocation=C\:\\Development\\JackRabbit\\trunk\\jackrabbit-webapp-project\\jackrabbit-webapp-jakarta +m2e.projectName=jackrabbit-webapp-jakarta +groupId=org.apache.jackrabbit +artifactId=jackrabbit-webapp-jakarta +version=2.21.16-SNAPSHOT Index: jackrabbit-webapp-project/jackrabbit-webapp-jakarta/target/classes/META-INF/maven/org.apache.jackrabbit/jackrabbit-webapp-jakarta/pom.xml =================================================================== --- jackrabbit-webapp-project/jackrabbit-webapp-jakarta/target/classes/META-INF/maven/org.apache.jackrabbit/jackrabbit-webapp-jakarta/pom.xml (nonexistent) +++ jackrabbit-webapp-project/jackrabbit-webapp-jakarta/target/classes/META-INF/maven/org.apache.jackrabbit/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-webapp-project/jackrabbit-webapp-jakarta/target/jackrabbit-webapp-jakarta-2.21.16-SNAPSHOT.jar =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Property changes on: jackrabbit-webapp-project/jackrabbit-webapp-jakarta/target/jackrabbit-webapp-jakarta-2.21.16-SNAPSHOT.jar ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: jackrabbit-webapp-project/jackrabbit-webapp-jakarta/target/maven-shared-archive-resources/META-INF/DEPENDENCIES =================================================================== --- jackrabbit-webapp-project/jackrabbit-webapp-jakarta/target/maven-shared-archive-resources/META-INF/DEPENDENCIES (nonexistent) +++ jackrabbit-webapp-project/jackrabbit-webapp-jakarta/target/maven-shared-archive-resources/META-INF/DEPENDENCIES (working copy) @@ -0,0 +1,253 @@ +// ------------------------------------------------------------------ +// Transitive dependencies of this project determined from the +// maven pom organized by organization. +// ------------------------------------------------------------------ + +jackrabbit-webapp-jakarta + + +From: 'an unknown organization' + - parso (https://github.com/epam/parso) com.epam:parso:jar:2.0.14 + License: Apache License v2 (http://www.apache.org/licenses/LICENSE-2.0.html) + - Java Unrar (https://github.com/junrar/junrar) com.github.junrar:junrar:jar:7.5.2 + License: UnRar License (https://github.com/junrar/junrar/LICENSE.md) + - curvesapi (https://github.com/virtuald/curvesapi) com.github.virtuald:curvesapi:jar:1.07 + License: BSD License (http://opensource.org/licenses/BSD-3-Clause) + - juniversalchardet (http://juniversalchardet.googlecode.com/) com.googlecode.juniversalchardet:juniversalchardet:jar:1.0.3 + License: Mozilla Public License 1.1 (MPL 1.1) (http://www.mozilla.org/MPL/MPL-1.1.html) + - dd-plist (http://www.github.com/3breadt/dd-plist) com.googlecode.plist:dd-plist:jar:1.23 + License: MIT License (http://opensource.org/licenses/mit) + - java-libpst (https://github.com/rjohnsondev/java-libpst) com.pff:java-libpst:jar:0.9.3 + License: The Apache Software License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt) + - rome (http://rometools.com/rome) com.rometools:rome:jar:1.18.0 + License: The Apache Software License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt) + - rome-utils (http://rometools.com/rome-utils) com.rometools:rome-utils:jar:1.18.0 + License: The Apache Software License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt) + - Bouncy Castle S/MIME API (https://www.bouncycastle.org/java.html) org.bouncycastle:bcmail-jdk15on:jar:1.70 + License: Bouncy Castle Licence (https://www.bouncycastle.org/licence.html) + - Bouncy Castle PKIX, CMS, EAC, TSP, PKCS, OCSP, CMP, and CRMF APIs (https://www.bouncycastle.org/java.html) org.bouncycastle:bcpkix-jdk15on:jar:1.70 + License: Bouncy Castle Licence (https://www.bouncycastle.org/licence.html) + - Bouncy Castle Provider (https://www.bouncycastle.org/java.html) org.bouncycastle:bcprov-jdk15on:jar:1.70 + License: Bouncy Castle Licence (https://www.bouncycastle.org/licence.html) + - Bouncy Castle ASN.1 Extension and Utility APIs (https://www.bouncycastle.org/java.html) org.bouncycastle:bcutil-jdk15on:jar:1.70 + License: Bouncy Castle Licence (https://www.bouncycastle.org/licence.html) + - org.brotli:dec (http://brotli.org/dec) org.brotli:dec:jar:0.1.2 + License: MIT License (http://www.opensource.org/licenses/mit-license.php) + - TagSoup (http://home.ccil.org/~cowan/XML/tagsoup/) org.ccil.cowan.tagsoup:tagsoup:jar:1.2.1 + License: Apache License 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt) + - JHighlight (https://github.com/codelibs/jhighlight) org.codelibs:jhighlight:jar:1.1.0 + License: CDDL, v1.0 (http://www.opensource.org/licenses/cddl1.php) License: LGPL, v2.1 or later (http://www.opensource.org/licenses/lgpl-license.php) + - Ogg and Vorbis for Java, Core (https://github.com/Gagravarr/VorbisJava) org.gagravarr:vorbis-java-core:jar:0.8 + License: The Apache Software License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Tika plugin for Ogg, Vorbis and FLAC (https://github.com/Gagravarr/VorbisJava) org.gagravarr:vorbis-java-tika:jar:0.8 + License: The Apache Software License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt) + - jwarc (https://github.com/iipc/jwarc) org.netpreserve:jwarc:jar:0.18.1 + License: Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt) + - JMatIO (https://github.com/tballison/jmatio) org.tallison:jmatio:jar:1.5 + License: BSD (http://www.linfo.org/bsdlicense.html) + - XZ for Java (https://tukaani.org/xz/java.html) org.tukaani:xz:jar:1.9 + License: Public Domain + - Xerces2-j (https://xerces.apache.org/xerces2-j/) xerces:xercesImpl:jar:2.12.2 + License: The Apache Software License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt) + - XML Commons External Components XML APIs (http://xml.apache.org/commons/components/external/) xml-apis:xml-apis:jar:1.4.01 + License: The Apache Software License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt) License: The SAX License (http://www.saxproject.org/copying.html) License: The W3C License (http://www.w3.org/TR/2004/REC-DOM-Level-3-Core-20040407/java-binding.zip) + +From: 'Apache Software Foundation' (http://db.apache.org/) + - Apache Derby Database Engine and Embedded JDBC Driver (http://db.apache.org/derby/) org.apache.derby:derby:jar:10.14.2.0 + License: Apache 2 (http://www.apache.org/licenses/LICENSE-2.0.txt) + +From: 'Apache Software Foundation' (http://www.apache.org/) + - Apache POI - Common (https://poi.apache.org/) org.apache.poi:poi:jar:5.2.2 + License: Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache POI - API based on OPC and OOXML schemas (https://poi.apache.org/) org.apache.poi:poi-ooxml:jar:5.2.2 + License: Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache POI (https://poi.apache.org/) org.apache.poi:poi-ooxml-lite:jar:5.2.2 + License: Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache POI (https://poi.apache.org/) org.apache.poi:poi-scratchpad:jar:5.2.2 + License: Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt) + +From: 'Day Software' (http://www.day.com) + - Content Repository for JavaTM Technology API (http://www.jcp.org/en/jsr/detail?id=283) javax.jcr:jcr:jar:2.0 + License: Day Specification License (http://www.day.com/dam/day/downloads/jsr283/day-spec-license.htm) License: Day Specification License addendum (http://www.day.com/content/dam/day/downloads/jsr283/LICENSE.txt) + +From: 'Dough Lea' (http://gee.cs.oswego.edu/dl/classes/EDU/oswego/cs/dl/util/concurrent/intro.html) + - Dough Lea's util.concurrent package concurrent:concurrent:jar:1.3.4 + License: Public domain, Sun Microsoystems (>http://gee.cs.oswego.edu/dl/classes/EDU/oswego/cs/dl/util/concurrent/intro.html) + +From: 'Eclipse Foundation' (https://www.eclipse.org) + - Jakarta Activation (https://github.com/eclipse-ee4j/jaf/jakarta.activation) com.sun.activation:jakarta.activation:jar:1.2.2 + License: EDL 1.0 (http://www.eclipse.org/org/documents/edl-v10.php) + - istack common utility code runtime (https://projects.eclipse.org/projects/ee4j/istack-commons/istack-commons-runtime) com.sun.istack:istack-commons-runtime:jar:3.0.12 + License: Eclipse Distribution License - v 1.0 (http://www.eclipse.org/org/documents/edl-v10.php) + - Jakarta XML Binding API (https://github.com/eclipse-ee4j/jaxb-api/jakarta.xml.bind-api) jakarta.xml.bind:jakarta.xml.bind-api:jar:2.3.3 + License: Eclipse Distribution License - v 1.0 (http://www.eclipse.org/org/documents/edl-v10.php) + - JAXB Runtime (https://eclipse-ee4j.github.io/jaxb-ri/) org.glassfish.jaxb:jaxb-runtime:jar:2.3.6 + License: Eclipse Distribution License - v 1.0 (http://www.eclipse.org/org/documents/edl-v10.php) + - TXW2 Runtime (https://eclipse-ee4j.github.io/jaxb-ri/) org.glassfish.jaxb:txw2:jar:2.3.6 + License: Eclipse Distribution License - v 1.0 (http://www.eclipse.org/org/documents/edl-v10.php) + +From: 'jai-imageio GitHub group' (https://github.com/jai-imageio/) + - Java Advanced Imaging Image I/O Tools API core (standalone) (https://github.com/jai-imageio/jai-imageio-core) com.github.jai-imageio:jai-imageio-core:bundle:1.4.0 + License: BSD 3-clause License w/nuclear disclaimer (LICENSE.txt) + +From: 'JDOM' (http://www.jdom.org) + - JDOM (http://www.jdom.org) org.jdom:jdom2:jar:2.0.6.1 + License: Similar to Apache License but with the acknowledgment clause removed (https://raw.github.com/hunterhacker/jdom/master/LICENSE.txt) + +From: 'OpenHMS' (https://openhms.sourceforge.io/) + - Jackcess (https://jackcess.sourceforge.io) com.healthmarketscience.jackcess:jackcess:jar:4.0.1 + License: Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt) + - Jackcess Encrypt (http://jackcessencrypt.sf.net) com.healthmarketscience.jackcess:jackcess-encrypt:jar:4.0.1 + License: Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt) + +From: 'OW2' (http://www.ow2.org/) + - asm (http://asm.ow2.io/) org.ow2.asm:asm:jar:9.3 + License: BSD-3-Clause (https://asm.ow2.io/license.html) + +From: 'QOS.ch' (http://www.qos.ch) + - Logback Classic Module (http://logback.qos.ch/logback-classic) ch.qos.logback:logback-classic:jar:1.2.11 + License: Eclipse Public License - v 1.0 (http://www.eclipse.org/legal/epl-v10.html) License: GNU Lesser General Public License (http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html) + - Logback Core Module (http://logback.qos.ch/logback-core) ch.qos.logback:logback-core:jar:1.2.11 + License: Eclipse Public License - v 1.0 (http://www.eclipse.org/legal/epl-v10.html) License: GNU Lesser General Public License (http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html) + - JCL 1.2 implemented over SLF4J (http://www.slf4j.org) org.slf4j:jcl-over-slf4j:jar:1.7.36 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - SLF4J API Module (http://www.slf4j.org) org.slf4j:slf4j-api:jar:1.7.36 + License: MIT License (http://www.opensource.org/licenses/mit-license.php) + +From: 'The Apache Software Foundation' (http://pdfbox.apache.org) + - Apache FontBox (http://pdfbox.apache.org/) org.apache.pdfbox:fontbox:bundle:2.0.26 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - PDFBox JBIG2 ImageIO plugin (https://www.apache.org/jbig2-imageio/) org.apache.pdfbox:jbig2-imageio:jar:3.0.4 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache JempBox (http://www.apache.org/pdfbox-parent/jempbox/) org.apache.pdfbox:jempbox:bundle:1.8.16 + License: Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache PDFBox (https://www.apache.org/pdfbox-parent/pdfbox/) org.apache.pdfbox:pdfbox:bundle:2.0.26 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache PDFBox Debugger (https://www.apache.org/pdfbox-parent/pdfbox-debugger/) org.apache.pdfbox:pdfbox-debugger:jar:2.0.26 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache PDFBox tools (https://www.apache.org/pdfbox-parent/pdfbox-tools/) org.apache.pdfbox:pdfbox-tools:jar:2.0.26 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache XmpBox (https://www.apache.org/pdfbox-parent/xmpbox/) org.apache.pdfbox:xmpbox:bundle:2.0.26 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + +From: 'The Apache Software Foundation' (http://www.apache.org) + - Apache Tika core (https://tika.apache.org/) org.apache.tika:tika-core:bundle:2.4.1 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + +From: 'The Apache Software Foundation' (http://www.apache.org/) + - Apache Commons Collections (http://commons.apache.org/collections/) commons-collections:commons-collections:jar:3.2.2 + License: Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt) + - Commons DBCP (http://commons.apache.org/dbcp/) commons-dbcp:commons-dbcp:jar:1.4 + License: The Apache Software License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Commons Logging (http://commons.apache.org/proper/commons-logging/) commons-logging:commons-logging:jar:1.2 + License: The Apache Software License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt) + - Commons Pool (http://commons.apache.org/pool/) commons-pool:commons-pool:jar:1.5.4 + License: The Apache Software License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Commons Exec (http://commons.apache.org/proper/commons-exec/) org.apache.commons:commons-exec:jar:1.3 + License: Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Commons Math (http://commons.apache.org/proper/commons-math/) org.apache.commons:commons-math3:jar:3.6.1 + License: Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache HttpClient (http://hc.apache.org/httpcomponents-client-ga) org.apache.httpcomponents:httpclient:jar:4.5.14 + License: Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache HttpCore (http://hc.apache.org/httpcomponents-core-ga) org.apache.httpcomponents:httpcore:jar:4.4.16 + License: Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt) + - Lucene Core (http://lucene.apache.org/java/lucene-parent/lucene-core) org.apache.lucene:lucene-core:jar:3.6.0 + License: Apache 2 (http://www.apache.org/licenses/LICENSE-2.0.txt) + +From: 'The Apache Software Foundation' (https://www.apache.org/) + - Apache Commons BeanUtils (https://commons.apache.org/proper/commons-beanutils/) commons-beanutils:commons-beanutils:jar:1.9.4 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Commons Codec (https://commons.apache.org/proper/commons-codec/) commons-codec:commons-codec:jar:1.15 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Commons FileUpload (https://commons.apache.org/proper/commons-fileupload/) commons-fileupload:commons-fileupload:jar:1.5 + License: Apache-2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Commons IO (https://commons.apache.org/proper/commons-io/) commons-io:commons-io:jar:2.11.0 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Commons Collections (https://commons.apache.org/proper/commons-collections/) org.apache.commons:commons-collections4:jar:4.4 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Commons CSV (https://commons.apache.org/proper/commons-csv/) org.apache.commons:commons-csv:jar:1.9.0 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Commons Lang (https://commons.apache.org/proper/commons-lang/) org.apache.commons:commons-lang3:jar:3.12.0 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Jackrabbit Core (http://jackrabbit.apache.org/jackrabbit-core/) org.apache.jackrabbit:jackrabbit-core:jar:2.21.16-SNAPSHOT + License: Apache-2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Jackrabbit Data (http://jackrabbit.apache.org/jackrabbit-data/) org.apache.jackrabbit:jackrabbit-data:bundle:2.21.16-SNAPSHOT + License: Apache-2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Jackrabbit JCR Commons (http://jackrabbit.apache.org/jackrabbit-jcr-commons/) org.apache.jackrabbit:jackrabbit-jcr-commons:bundle:2.21.16-SNAPSHOT + License: Apache-2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Jackrabbit JCR-RMI (http://jackrabbit.apache.org/jackrabbit-jcr-rmi/) org.apache.jackrabbit:jackrabbit-jcr-rmi:bundle:2.21.16-SNAPSHOT + License: Apache-2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - jackrabbit-jcr-server-jakarta (http://jackrabbit.apache.org/jackrabbit-jcr-server-project/jackrabbit-jcr-server-jakarta/) org.apache.jackrabbit:jackrabbit-jcr-server-jakarta:jar:2.21.16-SNAPSHOT + License: Apache-2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - jackrabbit-jcr-servlet-jakarta (http://jackrabbit.apache.org/jackrabbit-jcr-servlet-project/jackrabbit-jcr-servlet-jakarta/) org.apache.jackrabbit:jackrabbit-jcr-servlet-jakarta:jar:2.21.16-SNAPSHOT + License: Apache-2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Jackrabbit SPI (http://jackrabbit.apache.org/jackrabbit-spi/) org.apache.jackrabbit:jackrabbit-spi:bundle:2.21.16-SNAPSHOT + License: Apache-2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Jackrabbit SPI Commons (http://jackrabbit.apache.org/jackrabbit-spi-commons/) org.apache.jackrabbit:jackrabbit-spi-commons:bundle:2.21.16-SNAPSHOT + License: Apache-2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - jackrabbit-webdav-jakarta (http://jackrabbit.apache.org/jackrabbit-webdav-project/jackrabbit-webdav-jakarta/) org.apache.jackrabbit:jackrabbit-webdav-jakarta:jar:2.21.16-SNAPSHOT + License: Apache-2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Jackrabbit API (http://jackrabbit.apache.org/oak-jackrabbit-api/) org.apache.jackrabbit:oak-jackrabbit-api:bundle:1.48.0 + License: Apache-2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Log4j API (https://logging.apache.org/log4j/2.x/log4j-api/) org.apache.logging.log4j:log4j-api:jar:2.17.2 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Tika Apple parser module (https://tika.apache.org/tika-parser-apple-module/) org.apache.tika:tika-parser-apple-module:jar:2.4.1 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Tika audiovideo parser module (https://tika.apache.org/tika-parser-audiovideo-module/) org.apache.tika:tika-parser-audiovideo-module:jar:2.4.1 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Tika cad parser module (https://tika.apache.org/tika-parser-cad-module/) org.apache.tika:tika-parser-cad-module:jar:2.4.1 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Tika code parser module (https://tika.apache.org/tika-parser-code-module/) org.apache.tika:tika-parser-code-module:jar:2.4.1 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Tika crypto parser module (https://tika.apache.org/tika-parser-crypto-module/) org.apache.tika:tika-parser-crypto-module:jar:2.4.1 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Tika digest commons (https://tika.apache.org/tika-parser-digest-commons/) org.apache.tika:tika-parser-digest-commons:jar:2.4.1 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Tika font parser module (https://tika.apache.org/tika-parser-font-module/) org.apache.tika:tika-parser-font-module:jar:2.4.1 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Tika html commons (https://tika.apache.org/tika-parser-html-commons/) org.apache.tika:tika-parser-html-commons:jar:2.4.1 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Tika html parser module (https://tika.apache.org/tika-parser-html-module/) org.apache.tika:tika-parser-html-module:jar:2.4.1 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Tika image parser module (https://tika.apache.org/tika-parser-image-module/) org.apache.tika:tika-parser-image-module:jar:2.4.1 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Tika mail commons (https://tika.apache.org/tika-parser-mail-commons/) org.apache.tika:tika-parser-mail-commons:jar:2.4.1 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Tika mail parser module (https://tika.apache.org/tika-parser-mail-module/) org.apache.tika:tika-parser-mail-module:jar:2.4.1 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Tika Microsoft parser module (https://tika.apache.org/tika-parser-microsoft-module/) org.apache.tika:tika-parser-microsoft-module:jar:2.4.1 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Tika miscellaneous office format parser module (https://tika.apache.org/tika-parser-miscoffice-module/) org.apache.tika:tika-parser-miscoffice-module:jar:2.4.1 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Tika news parser module (https://tika.apache.org/tika-parser-news-module/) org.apache.tika:tika-parser-news-module:jar:2.4.1 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Tika OCR parser module (https://tika.apache.org/tika-parser-ocr-module/) org.apache.tika:tika-parser-ocr-module:jar:2.4.1 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Tika PDF parser module (https://tika.apache.org/tika-parser-pdf-module/) org.apache.tika:tika-parser-pdf-module:jar:2.4.1 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Tika package parser module (https://tika.apache.org/tika-parser-pkg-module/) org.apache.tika:tika-parser-pkg-module:jar:2.4.1 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Tika text parser module (https://tika.apache.org/tika-parser-text-module/) org.apache.tika:tika-parser-text-module:jar:2.4.1 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Tika WARC parser module (https://tika.apache.org/tika-parser-webarchive-module/) org.apache.tika:tika-parser-webarchive-module:jar:2.4.1 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Tika XML parser module (https://tika.apache.org/tika-parser-xml-module/) org.apache.tika:tika-parser-xml-module:jar:2.4.1 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Tika XMP commons (https://tika.apache.org/tika-parser-xmp-commons/) org.apache.tika:tika-parser-xmp-commons:jar:2.4.1 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Tika ZIP commons (https://tika.apache.org/tika-parser-zip-commons/) org.apache.tika:tika-parser-zip-commons:jar:2.4.1 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Tika standard parser package (https://tika.apache.org/tika-parsers/tika-parsers-standard/tika-parsers-standard-package/) org.apache.tika:tika-parsers-standard-package:jar:2.4.1 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + +From: 'XmlBeans' (https://xmlbeans.apache.org/) + - XmlBeans (https://xmlbeans.apache.org/) org.apache.xmlbeans:xmlbeans:jar:5.0.3 + License: The Apache Software License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt) + +From: 'Zaxxer.com' (https://github.com/brettwooldridge/SparseBitSet) + - SparseBitSet (https://github.com/brettwooldridge/SparseBitSet) com.zaxxer:SparseBitSet:jar:1.2 + License: The Apache Software License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt) + + + + Index: jackrabbit-webapp-project/jackrabbit-webapp-jakarta/target/maven-shared-archive-resources/META-INF/LICENSE =================================================================== --- jackrabbit-webapp-project/jackrabbit-webapp-jakarta/target/maven-shared-archive-resources/META-INF/LICENSE (nonexistent) +++ jackrabbit-webapp-project/jackrabbit-webapp-jakarta/target/maven-shared-archive-resources/META-INF/LICENSE (working copy) @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed 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. Index: jackrabbit-webapp-project/jackrabbit-webapp-jakarta/target/maven-shared-archive-resources/META-INF/NOTICE =================================================================== --- jackrabbit-webapp-project/jackrabbit-webapp-jakarta/target/maven-shared-archive-resources/META-INF/NOTICE (nonexistent) +++ jackrabbit-webapp-project/jackrabbit-webapp-jakarta/target/maven-shared-archive-resources/META-INF/NOTICE (working copy) @@ -0,0 +1,8 @@ + +jackrabbit-webapp-jakarta +Copyright 2004-1970 The Apache Software Foundation + +This product includes software developed at +The Apache Software Foundation (http://www.apache.org/). + + Index: jackrabbit-webapp-project/jackrabbit-webapp-jakarta/target/maven-status/maven-compiler-plugin/compile/default-compile/createdFiles.lst =================================================================== Index: jackrabbit-webapp-project/jackrabbit-webapp-jakarta/target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst =================================================================== Index: jackrabbit-webapp-project/jackrabbit-webapp-jakarta/target/maven-status/maven-compiler-plugin/testCompile/default-testCompile/createdFiles.lst =================================================================== Index: jackrabbit-webapp-project/jackrabbit-webapp-jakarta/target/maven-status/maven-compiler-plugin/testCompile/default-testCompile/inputFiles.lst =================================================================== Index: jackrabbit-webapp-project/jackrabbit-webapp-jakarta/target/test-classes/META-INF/DEPENDENCIES =================================================================== --- jackrabbit-webapp-project/jackrabbit-webapp-jakarta/target/test-classes/META-INF/DEPENDENCIES (nonexistent) +++ jackrabbit-webapp-project/jackrabbit-webapp-jakarta/target/test-classes/META-INF/DEPENDENCIES (working copy) @@ -0,0 +1,253 @@ +// ------------------------------------------------------------------ +// Transitive dependencies of this project determined from the +// maven pom organized by organization. +// ------------------------------------------------------------------ + +jackrabbit-webapp-jakarta + + +From: 'an unknown organization' + - parso (https://github.com/epam/parso) com.epam:parso:jar:2.0.14 + License: Apache License v2 (http://www.apache.org/licenses/LICENSE-2.0.html) + - Java Unrar (https://github.com/junrar/junrar) com.github.junrar:junrar:jar:7.5.2 + License: UnRar License (https://github.com/junrar/junrar/LICENSE.md) + - curvesapi (https://github.com/virtuald/curvesapi) com.github.virtuald:curvesapi:jar:1.07 + License: BSD License (http://opensource.org/licenses/BSD-3-Clause) + - juniversalchardet (http://juniversalchardet.googlecode.com/) com.googlecode.juniversalchardet:juniversalchardet:jar:1.0.3 + License: Mozilla Public License 1.1 (MPL 1.1) (http://www.mozilla.org/MPL/MPL-1.1.html) + - dd-plist (http://www.github.com/3breadt/dd-plist) com.googlecode.plist:dd-plist:jar:1.23 + License: MIT License (http://opensource.org/licenses/mit) + - java-libpst (https://github.com/rjohnsondev/java-libpst) com.pff:java-libpst:jar:0.9.3 + License: The Apache Software License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt) + - rome (http://rometools.com/rome) com.rometools:rome:jar:1.18.0 + License: The Apache Software License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt) + - rome-utils (http://rometools.com/rome-utils) com.rometools:rome-utils:jar:1.18.0 + License: The Apache Software License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt) + - Bouncy Castle S/MIME API (https://www.bouncycastle.org/java.html) org.bouncycastle:bcmail-jdk15on:jar:1.70 + License: Bouncy Castle Licence (https://www.bouncycastle.org/licence.html) + - Bouncy Castle PKIX, CMS, EAC, TSP, PKCS, OCSP, CMP, and CRMF APIs (https://www.bouncycastle.org/java.html) org.bouncycastle:bcpkix-jdk15on:jar:1.70 + License: Bouncy Castle Licence (https://www.bouncycastle.org/licence.html) + - Bouncy Castle Provider (https://www.bouncycastle.org/java.html) org.bouncycastle:bcprov-jdk15on:jar:1.70 + License: Bouncy Castle Licence (https://www.bouncycastle.org/licence.html) + - Bouncy Castle ASN.1 Extension and Utility APIs (https://www.bouncycastle.org/java.html) org.bouncycastle:bcutil-jdk15on:jar:1.70 + License: Bouncy Castle Licence (https://www.bouncycastle.org/licence.html) + - org.brotli:dec (http://brotli.org/dec) org.brotli:dec:jar:0.1.2 + License: MIT License (http://www.opensource.org/licenses/mit-license.php) + - TagSoup (http://home.ccil.org/~cowan/XML/tagsoup/) org.ccil.cowan.tagsoup:tagsoup:jar:1.2.1 + License: Apache License 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt) + - JHighlight (https://github.com/codelibs/jhighlight) org.codelibs:jhighlight:jar:1.1.0 + License: CDDL, v1.0 (http://www.opensource.org/licenses/cddl1.php) License: LGPL, v2.1 or later (http://www.opensource.org/licenses/lgpl-license.php) + - Ogg and Vorbis for Java, Core (https://github.com/Gagravarr/VorbisJava) org.gagravarr:vorbis-java-core:jar:0.8 + License: The Apache Software License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Tika plugin for Ogg, Vorbis and FLAC (https://github.com/Gagravarr/VorbisJava) org.gagravarr:vorbis-java-tika:jar:0.8 + License: The Apache Software License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt) + - jwarc (https://github.com/iipc/jwarc) org.netpreserve:jwarc:jar:0.18.1 + License: Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt) + - JMatIO (https://github.com/tballison/jmatio) org.tallison:jmatio:jar:1.5 + License: BSD (http://www.linfo.org/bsdlicense.html) + - XZ for Java (https://tukaani.org/xz/java.html) org.tukaani:xz:jar:1.9 + License: Public Domain + - Xerces2-j (https://xerces.apache.org/xerces2-j/) xerces:xercesImpl:jar:2.12.2 + License: The Apache Software License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt) + - XML Commons External Components XML APIs (http://xml.apache.org/commons/components/external/) xml-apis:xml-apis:jar:1.4.01 + License: The Apache Software License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt) License: The SAX License (http://www.saxproject.org/copying.html) License: The W3C License (http://www.w3.org/TR/2004/REC-DOM-Level-3-Core-20040407/java-binding.zip) + +From: 'Apache Software Foundation' (http://db.apache.org/) + - Apache Derby Database Engine and Embedded JDBC Driver (http://db.apache.org/derby/) org.apache.derby:derby:jar:10.14.2.0 + License: Apache 2 (http://www.apache.org/licenses/LICENSE-2.0.txt) + +From: 'Apache Software Foundation' (http://www.apache.org/) + - Apache POI - Common (https://poi.apache.org/) org.apache.poi:poi:jar:5.2.2 + License: Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache POI - API based on OPC and OOXML schemas (https://poi.apache.org/) org.apache.poi:poi-ooxml:jar:5.2.2 + License: Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache POI (https://poi.apache.org/) org.apache.poi:poi-ooxml-lite:jar:5.2.2 + License: Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache POI (https://poi.apache.org/) org.apache.poi:poi-scratchpad:jar:5.2.2 + License: Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt) + +From: 'Day Software' (http://www.day.com) + - Content Repository for JavaTM Technology API (http://www.jcp.org/en/jsr/detail?id=283) javax.jcr:jcr:jar:2.0 + License: Day Specification License (http://www.day.com/dam/day/downloads/jsr283/day-spec-license.htm) License: Day Specification License addendum (http://www.day.com/content/dam/day/downloads/jsr283/LICENSE.txt) + +From: 'Dough Lea' (http://gee.cs.oswego.edu/dl/classes/EDU/oswego/cs/dl/util/concurrent/intro.html) + - Dough Lea's util.concurrent package concurrent:concurrent:jar:1.3.4 + License: Public domain, Sun Microsoystems (>http://gee.cs.oswego.edu/dl/classes/EDU/oswego/cs/dl/util/concurrent/intro.html) + +From: 'Eclipse Foundation' (https://www.eclipse.org) + - Jakarta Activation (https://github.com/eclipse-ee4j/jaf/jakarta.activation) com.sun.activation:jakarta.activation:jar:1.2.2 + License: EDL 1.0 (http://www.eclipse.org/org/documents/edl-v10.php) + - istack common utility code runtime (https://projects.eclipse.org/projects/ee4j/istack-commons/istack-commons-runtime) com.sun.istack:istack-commons-runtime:jar:3.0.12 + License: Eclipse Distribution License - v 1.0 (http://www.eclipse.org/org/documents/edl-v10.php) + - Jakarta XML Binding API (https://github.com/eclipse-ee4j/jaxb-api/jakarta.xml.bind-api) jakarta.xml.bind:jakarta.xml.bind-api:jar:2.3.3 + License: Eclipse Distribution License - v 1.0 (http://www.eclipse.org/org/documents/edl-v10.php) + - JAXB Runtime (https://eclipse-ee4j.github.io/jaxb-ri/) org.glassfish.jaxb:jaxb-runtime:jar:2.3.6 + License: Eclipse Distribution License - v 1.0 (http://www.eclipse.org/org/documents/edl-v10.php) + - TXW2 Runtime (https://eclipse-ee4j.github.io/jaxb-ri/) org.glassfish.jaxb:txw2:jar:2.3.6 + License: Eclipse Distribution License - v 1.0 (http://www.eclipse.org/org/documents/edl-v10.php) + +From: 'jai-imageio GitHub group' (https://github.com/jai-imageio/) + - Java Advanced Imaging Image I/O Tools API core (standalone) (https://github.com/jai-imageio/jai-imageio-core) com.github.jai-imageio:jai-imageio-core:bundle:1.4.0 + License: BSD 3-clause License w/nuclear disclaimer (LICENSE.txt) + +From: 'JDOM' (http://www.jdom.org) + - JDOM (http://www.jdom.org) org.jdom:jdom2:jar:2.0.6.1 + License: Similar to Apache License but with the acknowledgment clause removed (https://raw.github.com/hunterhacker/jdom/master/LICENSE.txt) + +From: 'OpenHMS' (https://openhms.sourceforge.io/) + - Jackcess (https://jackcess.sourceforge.io) com.healthmarketscience.jackcess:jackcess:jar:4.0.1 + License: Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt) + - Jackcess Encrypt (http://jackcessencrypt.sf.net) com.healthmarketscience.jackcess:jackcess-encrypt:jar:4.0.1 + License: Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt) + +From: 'OW2' (http://www.ow2.org/) + - asm (http://asm.ow2.io/) org.ow2.asm:asm:jar:9.3 + License: BSD-3-Clause (https://asm.ow2.io/license.html) + +From: 'QOS.ch' (http://www.qos.ch) + - Logback Classic Module (http://logback.qos.ch/logback-classic) ch.qos.logback:logback-classic:jar:1.2.11 + License: Eclipse Public License - v 1.0 (http://www.eclipse.org/legal/epl-v10.html) License: GNU Lesser General Public License (http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html) + - Logback Core Module (http://logback.qos.ch/logback-core) ch.qos.logback:logback-core:jar:1.2.11 + License: Eclipse Public License - v 1.0 (http://www.eclipse.org/legal/epl-v10.html) License: GNU Lesser General Public License (http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html) + - JCL 1.2 implemented over SLF4J (http://www.slf4j.org) org.slf4j:jcl-over-slf4j:jar:1.7.36 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - SLF4J API Module (http://www.slf4j.org) org.slf4j:slf4j-api:jar:1.7.36 + License: MIT License (http://www.opensource.org/licenses/mit-license.php) + +From: 'The Apache Software Foundation' (http://pdfbox.apache.org) + - Apache FontBox (http://pdfbox.apache.org/) org.apache.pdfbox:fontbox:bundle:2.0.26 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - PDFBox JBIG2 ImageIO plugin (https://www.apache.org/jbig2-imageio/) org.apache.pdfbox:jbig2-imageio:jar:3.0.4 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache JempBox (http://www.apache.org/pdfbox-parent/jempbox/) org.apache.pdfbox:jempbox:bundle:1.8.16 + License: Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache PDFBox (https://www.apache.org/pdfbox-parent/pdfbox/) org.apache.pdfbox:pdfbox:bundle:2.0.26 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache PDFBox Debugger (https://www.apache.org/pdfbox-parent/pdfbox-debugger/) org.apache.pdfbox:pdfbox-debugger:jar:2.0.26 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache PDFBox tools (https://www.apache.org/pdfbox-parent/pdfbox-tools/) org.apache.pdfbox:pdfbox-tools:jar:2.0.26 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache XmpBox (https://www.apache.org/pdfbox-parent/xmpbox/) org.apache.pdfbox:xmpbox:bundle:2.0.26 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + +From: 'The Apache Software Foundation' (http://www.apache.org) + - Apache Tika core (https://tika.apache.org/) org.apache.tika:tika-core:bundle:2.4.1 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + +From: 'The Apache Software Foundation' (http://www.apache.org/) + - Apache Commons Collections (http://commons.apache.org/collections/) commons-collections:commons-collections:jar:3.2.2 + License: Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt) + - Commons DBCP (http://commons.apache.org/dbcp/) commons-dbcp:commons-dbcp:jar:1.4 + License: The Apache Software License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Commons Logging (http://commons.apache.org/proper/commons-logging/) commons-logging:commons-logging:jar:1.2 + License: The Apache Software License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt) + - Commons Pool (http://commons.apache.org/pool/) commons-pool:commons-pool:jar:1.5.4 + License: The Apache Software License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Commons Exec (http://commons.apache.org/proper/commons-exec/) org.apache.commons:commons-exec:jar:1.3 + License: Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Commons Math (http://commons.apache.org/proper/commons-math/) org.apache.commons:commons-math3:jar:3.6.1 + License: Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache HttpClient (http://hc.apache.org/httpcomponents-client-ga) org.apache.httpcomponents:httpclient:jar:4.5.14 + License: Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache HttpCore (http://hc.apache.org/httpcomponents-core-ga) org.apache.httpcomponents:httpcore:jar:4.4.16 + License: Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt) + - Lucene Core (http://lucene.apache.org/java/lucene-parent/lucene-core) org.apache.lucene:lucene-core:jar:3.6.0 + License: Apache 2 (http://www.apache.org/licenses/LICENSE-2.0.txt) + +From: 'The Apache Software Foundation' (https://www.apache.org/) + - Apache Commons BeanUtils (https://commons.apache.org/proper/commons-beanutils/) commons-beanutils:commons-beanutils:jar:1.9.4 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Commons Codec (https://commons.apache.org/proper/commons-codec/) commons-codec:commons-codec:jar:1.15 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Commons FileUpload (https://commons.apache.org/proper/commons-fileupload/) commons-fileupload:commons-fileupload:jar:1.5 + License: Apache-2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Commons IO (https://commons.apache.org/proper/commons-io/) commons-io:commons-io:jar:2.11.0 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Commons Collections (https://commons.apache.org/proper/commons-collections/) org.apache.commons:commons-collections4:jar:4.4 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Commons CSV (https://commons.apache.org/proper/commons-csv/) org.apache.commons:commons-csv:jar:1.9.0 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Commons Lang (https://commons.apache.org/proper/commons-lang/) org.apache.commons:commons-lang3:jar:3.12.0 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Jackrabbit Core (http://jackrabbit.apache.org/jackrabbit-core/) org.apache.jackrabbit:jackrabbit-core:jar:2.21.16-SNAPSHOT + License: Apache-2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Jackrabbit Data (http://jackrabbit.apache.org/jackrabbit-data/) org.apache.jackrabbit:jackrabbit-data:bundle:2.21.16-SNAPSHOT + License: Apache-2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Jackrabbit JCR Commons (http://jackrabbit.apache.org/jackrabbit-jcr-commons/) org.apache.jackrabbit:jackrabbit-jcr-commons:bundle:2.21.16-SNAPSHOT + License: Apache-2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Jackrabbit JCR-RMI (http://jackrabbit.apache.org/jackrabbit-jcr-rmi/) org.apache.jackrabbit:jackrabbit-jcr-rmi:bundle:2.21.16-SNAPSHOT + License: Apache-2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - jackrabbit-jcr-server-jakarta (http://jackrabbit.apache.org/jackrabbit-jcr-server-project/jackrabbit-jcr-server-jakarta/) org.apache.jackrabbit:jackrabbit-jcr-server-jakarta:jar:2.21.16-SNAPSHOT + License: Apache-2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - jackrabbit-jcr-servlet-jakarta (http://jackrabbit.apache.org/jackrabbit-jcr-servlet-project/jackrabbit-jcr-servlet-jakarta/) org.apache.jackrabbit:jackrabbit-jcr-servlet-jakarta:jar:2.21.16-SNAPSHOT + License: Apache-2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Jackrabbit SPI (http://jackrabbit.apache.org/jackrabbit-spi/) org.apache.jackrabbit:jackrabbit-spi:bundle:2.21.16-SNAPSHOT + License: Apache-2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Jackrabbit SPI Commons (http://jackrabbit.apache.org/jackrabbit-spi-commons/) org.apache.jackrabbit:jackrabbit-spi-commons:bundle:2.21.16-SNAPSHOT + License: Apache-2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - jackrabbit-webdav-jakarta (http://jackrabbit.apache.org/jackrabbit-webdav-project/jackrabbit-webdav-jakarta/) org.apache.jackrabbit:jackrabbit-webdav-jakarta:jar:2.21.16-SNAPSHOT + License: Apache-2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Jackrabbit API (http://jackrabbit.apache.org/oak-jackrabbit-api/) org.apache.jackrabbit:oak-jackrabbit-api:bundle:1.48.0 + License: Apache-2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Log4j API (https://logging.apache.org/log4j/2.x/log4j-api/) org.apache.logging.log4j:log4j-api:jar:2.17.2 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Tika Apple parser module (https://tika.apache.org/tika-parser-apple-module/) org.apache.tika:tika-parser-apple-module:jar:2.4.1 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Tika audiovideo parser module (https://tika.apache.org/tika-parser-audiovideo-module/) org.apache.tika:tika-parser-audiovideo-module:jar:2.4.1 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Tika cad parser module (https://tika.apache.org/tika-parser-cad-module/) org.apache.tika:tika-parser-cad-module:jar:2.4.1 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Tika code parser module (https://tika.apache.org/tika-parser-code-module/) org.apache.tika:tika-parser-code-module:jar:2.4.1 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Tika crypto parser module (https://tika.apache.org/tika-parser-crypto-module/) org.apache.tika:tika-parser-crypto-module:jar:2.4.1 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Tika digest commons (https://tika.apache.org/tika-parser-digest-commons/) org.apache.tika:tika-parser-digest-commons:jar:2.4.1 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Tika font parser module (https://tika.apache.org/tika-parser-font-module/) org.apache.tika:tika-parser-font-module:jar:2.4.1 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Tika html commons (https://tika.apache.org/tika-parser-html-commons/) org.apache.tika:tika-parser-html-commons:jar:2.4.1 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Tika html parser module (https://tika.apache.org/tika-parser-html-module/) org.apache.tika:tika-parser-html-module:jar:2.4.1 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Tika image parser module (https://tika.apache.org/tika-parser-image-module/) org.apache.tika:tika-parser-image-module:jar:2.4.1 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Tika mail commons (https://tika.apache.org/tika-parser-mail-commons/) org.apache.tika:tika-parser-mail-commons:jar:2.4.1 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Tika mail parser module (https://tika.apache.org/tika-parser-mail-module/) org.apache.tika:tika-parser-mail-module:jar:2.4.1 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Tika Microsoft parser module (https://tika.apache.org/tika-parser-microsoft-module/) org.apache.tika:tika-parser-microsoft-module:jar:2.4.1 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Tika miscellaneous office format parser module (https://tika.apache.org/tika-parser-miscoffice-module/) org.apache.tika:tika-parser-miscoffice-module:jar:2.4.1 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Tika news parser module (https://tika.apache.org/tika-parser-news-module/) org.apache.tika:tika-parser-news-module:jar:2.4.1 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Tika OCR parser module (https://tika.apache.org/tika-parser-ocr-module/) org.apache.tika:tika-parser-ocr-module:jar:2.4.1 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Tika PDF parser module (https://tika.apache.org/tika-parser-pdf-module/) org.apache.tika:tika-parser-pdf-module:jar:2.4.1 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Tika package parser module (https://tika.apache.org/tika-parser-pkg-module/) org.apache.tika:tika-parser-pkg-module:jar:2.4.1 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Tika text parser module (https://tika.apache.org/tika-parser-text-module/) org.apache.tika:tika-parser-text-module:jar:2.4.1 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Tika WARC parser module (https://tika.apache.org/tika-parser-webarchive-module/) org.apache.tika:tika-parser-webarchive-module:jar:2.4.1 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Tika XML parser module (https://tika.apache.org/tika-parser-xml-module/) org.apache.tika:tika-parser-xml-module:jar:2.4.1 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Tika XMP commons (https://tika.apache.org/tika-parser-xmp-commons/) org.apache.tika:tika-parser-xmp-commons:jar:2.4.1 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Tika ZIP commons (https://tika.apache.org/tika-parser-zip-commons/) org.apache.tika:tika-parser-zip-commons:jar:2.4.1 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Tika standard parser package (https://tika.apache.org/tika-parsers/tika-parsers-standard/tika-parsers-standard-package/) org.apache.tika:tika-parsers-standard-package:jar:2.4.1 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + +From: 'XmlBeans' (https://xmlbeans.apache.org/) + - XmlBeans (https://xmlbeans.apache.org/) org.apache.xmlbeans:xmlbeans:jar:5.0.3 + License: The Apache Software License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt) + +From: 'Zaxxer.com' (https://github.com/brettwooldridge/SparseBitSet) + - SparseBitSet (https://github.com/brettwooldridge/SparseBitSet) com.zaxxer:SparseBitSet:jar:1.2 + License: The Apache Software License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt) + + + + Index: jackrabbit-webapp-project/jackrabbit-webapp-jakarta/target/test-classes/META-INF/LICENSE =================================================================== --- jackrabbit-webapp-project/jackrabbit-webapp-jakarta/target/test-classes/META-INF/LICENSE (nonexistent) +++ jackrabbit-webapp-project/jackrabbit-webapp-jakarta/target/test-classes/META-INF/LICENSE (working copy) @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed 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. Index: jackrabbit-webapp-project/jackrabbit-webapp-jakarta/target/test-classes/META-INF/NOTICE =================================================================== --- jackrabbit-webapp-project/jackrabbit-webapp-jakarta/target/test-classes/META-INF/NOTICE (nonexistent) +++ jackrabbit-webapp-project/jackrabbit-webapp-jakarta/target/test-classes/META-INF/NOTICE (working copy) @@ -0,0 +1,8 @@ + +jackrabbit-webapp-jakarta +Copyright 2004-1970 The Apache Software Foundation + +This product includes software developed at +The Apache Software Foundation (http://www.apache.org/). + + Index: jackrabbit-webapp-project/pom.xml =================================================================== --- jackrabbit-webapp-project/pom.xml (nonexistent) +++ jackrabbit-webapp-project/pom.xml (working copy) @@ -0,0 +1,108 @@ + + 4.0.0 + + org.apache.jackrabbit + jackrabbit-parent + 2.21.16-SNAPSHOT + ../jackrabbit-parent/pom.xml + + jackrabbit-webapp-project + pom + + jackrabbit-webapp + jackrabbit-webapp-jakarta + + + 8.5.86 + + + + javax.jcr + jcr + compile + + + org.apache.jackrabbit + jackrabbit-core + ${project.version} + + + org.apache.tika + tika-parsers-standard-package + + + org.slf4j + jcl-over-slf4j + + + org.apache.jackrabbit + jackrabbit-jcr-rmi + ${project.version} + + + ch.qos.logback + logback-classic + + + commons-beanutils + commons-beanutils + + + org.apache.tomcat + tomcat-servlet-api + ${tomcat.version} + provided + + + junit + junit + test + + + org.apache.tomcat + tomcat-catalina + ${tomcat.version} + test + + + org.apache.tomcat + tomcat-coyote + ${tomcat.version} + test + + + org.apache.tomcat + tomcat-jasper + ${tomcat.version} + test + + + net.sourceforge.htmlunit + htmlunit + 2.67.0 + test + + + commons-logging + commons-logging + + + + + org.slf4j + jul-to-slf4j + ${slf4j.version} + test + + + com.google.guava + guava + 31.1-jre + test + + + org.apache.derby + derby + + + \ No newline at end of file Index: jackrabbit-webdav-project/jackrabbit-webdav/README.txt =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/README.txt (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/README.txt (working copy) @@ -0,0 +1,81 @@ +==================================== +Welcome to Jackrabbit WebDAV Library +==================================== + +This is the WebDAV Library component of the Apache Jackrabbit project. +This component provides interfaces and common utility classes used for +building a WebDAV server or client. The following RFC have been integrated: + + * RFC 2518 (WebDAV - HTTP Extensions for Distributed Authoring) + * RFC 3253 (DeltaV - Versioning Extensions to WebDAV) + * RFC 3648 (Ordered Collections Protocol) + * RFC 3744 (Access Control Protocol) + * DAV Searching and Locating (DASL) + * Binding Extensions to Web Distributed Authoring and Versioning (WebDAV) (experimental) + +In addition this library defines (unspecified) + + * Observation + * Bundling multiple request with extensions to locking + +Common Questions +================ + +Q: Which WebDAV features are supported? +A: DAV 1, 2, DeltaV, Ordering, Access Control, Search, Bind + +Q: This this WebDAV library provide a full dav server? +A: This library only defines interfaces, utilities and common + classes used for a dav server/client. + A JCR specific implementation can be found in the 'jcr-server' + and the 'webapp' project. + +Q: How do a get a deployable Jackrabbit installation with WebDAV and + optional RMI support? +A: The 'webdav' project only serves as library. In order to access + a Jackrabbit repository please follow the instructions present + with the 'webapp' project. + +Q: Does the WebDAV library has dependency to JSR170 +A: No, the library can be used as generic webdav library in any + other project. There exists a dependency to the jackrabbit-commons + library for utility classes only. + +Things to do +============ + +------------------------------------------------------------------- +todo webdav/version +------------------------------------------------------------------- + +- review: compliance to deltaV +- reconsider feature-sets (see also JCR-394) +- CHECKOUT may contain request body (working-resource, activity, checkout-in-place) +- CHECKIN may contain request body (working-resource, checkout-in-place) +- VERSION-CONTROL may contain request body (workspace f.) +- BASELINE: creation of Baseline resources is not yet supported + (TODO within AbstractWebDAVServlet) + +------------------------------------------------------------------- +todo webdav/ordering +------------------------------------------------------------------- + +- respect Position header with creation of new collection members by + PUT, COPY, MKCOL requests + +------------------------------------------------------------------- +todo webdav/search +------------------------------------------------------------------- + +- SearchResource should extend DavResource +- Library misses support for the DAV:basicsearch + +------------------------------------------------------------------- +todo webdav/transaction +------------------------------------------------------------------- + +- review naming of the lock scopes. 'global','local' are not correct in + this context. +- j2ee explicitely requires any usertransaction to be completed + upon the end of the servletes service method. + general review necessary. Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/README.txt ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +author date id revision \ No newline at end of property 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-webdav-project/jackrabbit-webdav/src/main/appended-resources/META-INF/NOTICE =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/appended-resources/META-INF/NOTICE (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/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-webdav-project/jackrabbit-webdav/src/main/appended-resources/META-INF/NOTICE ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +author date id revision \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/AbstractLocatorFactory.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/AbstractLocatorFactory.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/AbstractLocatorFactory.java (working copy) @@ -0,0 +1,403 @@ +/* + * 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.webdav; + +import org.apache.jackrabbit.webdav.util.EncodeUtil; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * {@code AbstractLocatorFactory} is an implementation of the DavLocatorFactory + * interface that defines how a given URI is split to workspace path and + * resource path and how it's implementation of {@code DavResourceLocator} + * builds the href. In contrast, the conversion from repository path to + * resource path and vice versa is left to subclasses. + */ +public abstract class AbstractLocatorFactory implements DavLocatorFactory { + + private static Logger log = LoggerFactory.getLogger(AbstractLocatorFactory.class); + + private final String pathPrefix; + + /** + * Create a new factory + * + * @param pathPrefix Prefix, that needs to be removed in order to retrieve + * the path of the repository item from a given {@code DavResourceLocator}. + */ + public AbstractLocatorFactory(String pathPrefix) { + this.pathPrefix = pathPrefix; + } + + //--------------------------------------------------< DavLocatorFactory >--- + /** + * Create a new {@code DavResourceLocator}. Any leading prefix and + * path-prefix (as defined with the constructor) are removed from the + * given request handle. The same applies for trailing '/'. The remaining + * String is called the 'resource handle' and it's first segment is treated + * as workspace name. If resource handle (and therefore workspace name) + * are missing, both values are set to {@code null}. + *

+ * Examples: + * + *

+     * http://www.foo.bar/ (path prefix missing)
+     * -> workspace path = null
+     * -> resource path  = null
+     * -> href           = http://www.foo.bar/pathPrefix/
+     *
+     * http://www.foo.bar/pathPrefix/
+     * -> workspace path = null
+     * -> resource path  = null
+     * -> href           = http://www.foo.bar/pathPrefix/
+     *
+     * http://www.foo.bar/pathPrefix/wspName
+     * -> workspace path = /wspName
+     * -> resource path  = /wspName
+     * -> href           = http://www.foo.bar/pathPrefix/wspName
+     *
+     * http://www.foo.bar/pathPrefix/wspName/anypath
+     * -> workspace path = /wspName
+     * -> resource path  = /wspName/anypath
+     * -> href           = http://www.foo.bar/pathPrefix/wspName/anypath
+     * 
+ * + * NOTE: If the given href is an absolute URI it must start with the + * specified prefix. + * + * @param prefix + * @param href + * @return a new {@code DavResourceLocator} + * @throws IllegalArgumentException if the given href is {@code null} + */ + public DavResourceLocator createResourceLocator(String prefix, String href) { + if (href == null) { + throw new IllegalArgumentException("Request handle must not be null."); + } + + // build prefix string and remove all prefixes from the given href. + StringBuffer b = new StringBuffer(""); + if (prefix != null && prefix.length() > 0) { + b.append(prefix); + if (href.startsWith(prefix)) { + href = href.substring(prefix.length()); + } + } + if (pathPrefix != null && pathPrefix.length() > 0) { + if (!b.toString().endsWith(pathPrefix)) { + b.append(pathPrefix); + } + if (href.startsWith(pathPrefix)) { + href = href.substring(pathPrefix.length()); + } + } + + // remove trailing "/" that is present with collections + if (href.endsWith("/")) { + href = href.substring(0, href.length() - 1); + } + + String resourcePath; + String workspacePath; + + // an empty requestHandle (after removal of the "/") signifies a request + // to the root that does not represent a repository item. + if ("".equals(href)) { + resourcePath = null; + workspacePath = null; + } else { + resourcePath = EncodeUtil.unescape(href); + // retrieve wspPath: look for the first slash ignoring the leading one + int pos = href.indexOf('/', 1); + if (pos == -1) { + // request to a 'workspace' resource + workspacePath = resourcePath; + } else { + // separate the workspace path from the resource path. + workspacePath = EncodeUtil.unescape(href.substring(0, pos)); + } + } + + log.trace("createResourceLocator: prefix='" + prefix + "' href='" + href + "' -> prefix='" + b.toString() + + "' workspacePath='" + workspacePath + "' resourcePath='" + resourcePath + "'"); + return new DavResourceLocatorImpl(b.toString(), workspacePath, resourcePath, this); + } + + /** + * Like {@link #createResourceLocator(String, String)}, but by setting + * {@code forDestination} to {@code true} any special processing of URI + * suffixes can be disabled. + */ + public DavResourceLocator createResourceLocator(String prefix, String href, boolean forDestination) { + return createResourceLocator(prefix, href); + } + + /** + * Create a new {@code DavResourceLocator} from the specified prefix, + * workspace path and resource path, without modifying the specified Strings. + * Note, that it is expected that the resource path starts with the + * given workspace path unless both values are {@code null}. + * + * @param prefix + * @param workspacePath path or the workspace containing this resource or + * {@code null}. + * @param resourcePath Path of the resource or {@code null}. Any non + * null value must start with the specified workspace path. + * @return a new {@code DavResourceLocator} + * @see DavLocatorFactory#createResourceLocator(String, String, String) + */ + public DavResourceLocator createResourceLocator(String prefix, String workspacePath, String resourcePath) { + return createResourceLocator(prefix, workspacePath, resourcePath, true); + } + + /** + * Create a new {@code DavResourceLocator} from the specified prefix, + * workspace path and resource path. If {@code isResourcePath} is set + * to {@code false}, the given 'resourcePath' is converted by calling + * {@link #getResourcePath(String, String)}. Otherwise the same restriction + * applies as for {@link #createResourceLocator(String, String, String)}. + * + * @param prefix + * @param workspacePath + * @param path + * @param isResourcePath + * @return + * @see DavLocatorFactory#createResourceLocator(String, String, String, boolean) + */ + public DavResourceLocator createResourceLocator(String prefix, String workspacePath, String path, boolean isResourcePath) { + String resourcePath = (isResourcePath) ? path : getResourcePath(path, workspacePath); + return new DavResourceLocatorImpl(prefix, workspacePath, resourcePath, this); + } + + //-------------------------------------------------------------------------- + /** + * Subclasses must defined how the repository path is built from the given + * resource and workspace path. + * + * @param resourcePath + * @param wspPath + * @return + */ + protected abstract String getRepositoryPath(String resourcePath, String wspPath); + + /** + * Subclasses must defined how the resource path is built from the given + * repository and workspace path. + * + * @param repositoryPath + * @param wspPath + * @return + */ + protected abstract String getResourcePath(String repositoryPath, String wspPath); + + //--------------------------------------------------------< DavResource >--- + /** + * Private inner class {@code DavResourceLocatorImpl} implementing + * the {@code DavResourceLocator} interface. + */ + private class DavResourceLocatorImpl implements DavResourceLocator { + + private final String prefix; + private final String workspacePath; + private final String resourcePath; + private final AbstractLocatorFactory factory; + + private final String href; + + /** + * Create a new {@code DavResourceLocatorImpl}. + * + * @param prefix + * @param workspacePath + * @param resourcePath + */ + private DavResourceLocatorImpl(String prefix, String workspacePath, String resourcePath, AbstractLocatorFactory factory) { + + this.prefix = prefix; + this.workspacePath = workspacePath; + this.resourcePath = resourcePath; + this.factory = factory; + + StringBuffer buf = new StringBuffer(prefix); + // NOTE: no need to append the workspace path, since it must + // be part of the resource path. + if (resourcePath != null && resourcePath.length() > 0) { + // check if condition is really met + if (!resourcePath.startsWith(workspacePath)) { + throw new IllegalArgumentException("Resource path '" + resourcePath + "' does not start with workspace path '" + workspacePath + "'."); + } + buf.append(EncodeUtil.escapePath(resourcePath)); + } + int length = buf.length(); + if (length == 0 || (length > 0 && buf.charAt(length - 1) != '/')) { + buf.append("/"); + } + this.href = buf.toString(); + } + + /** + * Return the prefix used to build the href String. This includes the initial + * hrefPrefix as well a the path prefix. + * + * @return prefix String used to build the href. + */ + public String getPrefix() { + return prefix; + } + + /** + * Returns the resource path which always starts with the workspace + * path, if a workspace resource exists. For the top most resource + * (request handle '/'), {@code null} is returned. + * + * @return resource path or {@code null} + * @see org.apache.jackrabbit.webdav.DavResourceLocator#getResourcePath() + */ + public String getResourcePath() { + return resourcePath; + } + + /** + * Return the workspace path or {@code null} if this locator object + * represents the '/' request handle. + * + * @return workspace path or {@code null} + * @see org.apache.jackrabbit.webdav.DavResourceLocator#getWorkspacePath() + */ + public String getWorkspacePath() { + return workspacePath; + } + + /** + * Return the workspace name or {@code null} if this locator object + * represents the '/' request handle, which does not contain a workspace + * path. + * + * @return workspace name or {@code null} + * @see org.apache.jackrabbit.webdav.DavResourceLocator#getWorkspaceName() + */ + public String getWorkspaceName() { + if (workspacePath != null && workspacePath.length() > 0) { + return workspacePath.substring(1); + } + return null; + } + + /** + * Returns true if the specified locator object refers to a resource within + * the same workspace. + * + * @param locator + * @return true if the workspace name obtained from the given locator + * refers to the same workspace as the workspace name of this locator. + * @see DavResourceLocator#isSameWorkspace(org.apache.jackrabbit.webdav.DavResourceLocator) + */ + public boolean isSameWorkspace(DavResourceLocator locator) { + return (locator == null) ? false : isSameWorkspace(locator.getWorkspaceName()); + } + + /** + * Returns true if the specified string equals to this workspace name or + * if both names are null. + * + * @param workspaceName + * @return true if the workspace name is equal to this workspace name. + * @see DavResourceLocator#isSameWorkspace(String) + */ + public boolean isSameWorkspace(String workspaceName) { + String thisWspName = getWorkspaceName(); + return (thisWspName == null) ? workspaceName == null : thisWspName.equals(workspaceName); + } + + /** + * Returns an 'href' consisting of prefix and resource path (which starts + * with the workspace path). It assures a trailing '/' in case the href + * is used for collection. Note, that the resource path is + * {@link org.apache.jackrabbit.webdav.util.EncodeUtil#escapePath(String) escaped}. + * + * @param isCollection + * @return href String representing the text of the href element + * @see org.apache.jackrabbit.webdav.DavConstants#XML_HREF + * @see DavResourceLocator#getHref(boolean) + */ + public String getHref(boolean isCollection) { + return (isCollection) ? href : href.substring(0, href.length() - 1); + } + + /** + * Returns true if the 'workspacePath' field is {@code null}. + * + * @return true if the 'workspacePath' field is {@code null}. + * @see org.apache.jackrabbit.webdav.DavResourceLocator#isRootLocation() + */ + public boolean isRootLocation() { + return getWorkspacePath() == null; + } + + /** + * Return the factory that created this locator. + * + * @return factory + * @see org.apache.jackrabbit.webdav.DavResourceLocator#getFactory() + */ + public DavLocatorFactory getFactory() { + return factory; + } + + /** + * Uses {@link AbstractLocatorFactory#getRepositoryPath(String, String)} + * to build the repository path. + * + * @see DavResourceLocator#getRepositoryPath() + */ + public String getRepositoryPath() { + return factory.getRepositoryPath(getResourcePath(), getWorkspacePath()); + } + + /** + * Computes the hash code from the href, that is built from the prefix, + * the workspace name and the resource path all of them representing + * final instance fields. + * + * @return the hash code + */ + @Override + public int hashCode() { + return href.hashCode(); + } + + /** + * Returns true, if the given object is a {@code DavResourceLocatorImpl} + * with the same hash code. + * + * @param obj the object to compare to + * @return {@code true} if the 2 objects are equal; + * {@code false} otherwise + */ + @Override + public boolean equals(Object obj) { + if (obj == this) { + return true; + } + if (obj instanceof DavResourceLocatorImpl) { + DavResourceLocatorImpl other = (DavResourceLocatorImpl) obj; + return hashCode() == other.hashCode(); + } + return false; + } + } +} Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/AbstractLocatorFactory.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-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/ContentCodingAwareRequest.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/ContentCodingAwareRequest.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/ContentCodingAwareRequest.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.webdav; + +import java.util.List; + +import javax.xml.namespace.QName; + +public interface ContentCodingAwareRequest { + + /** + * Element name for signaling "must be supported content coding" + */ + public final QName PRECONDITION_SUPPORTED = new QName("http://www.day.com/jcr/webdav/1.0", "supported-content-coding", "dcr"); + + /** + * @return value suitable for Accept response field + */ + public String getAcceptableCodings(); + + /** + * @return content codings used in request + */ + public List getRequestContentCodings(); +} Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/ContentCodingAwareRequest.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/DavCompliance.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/DavCompliance.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/DavCompliance.java (working copy) @@ -0,0 +1,72 @@ +/* + * 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.webdav; + +/** + * DavCompliance defines constants for the various compliance + * classes defined RFC 2518, RFC 4918 and it's extensions. + */ +public final class DavCompliance { + + /** + * Avoid instantiation + */ + private DavCompliance() {} + + // RFC 2518 + public static final String _1_ = "1"; + public static final String _2_ = "2"; + + // RFC 4918 + public static final String _3_ = "3"; + + // RFC 3253 + public static final String ACTIVITY = "activity"; + public static final String BASELINE = "baseline"; + public static final String CHECKOUT_IN_PLACE = "checkout-in-place"; + public static final String LABEL = "label"; + public static final String MERGE = "merge"; + public static final String UPDATE = "update"; + public static final String VERSION_CONTROL = "version-control"; + public static final String VERSION_CONTROLLED_COLLECTION = "version-controlled-collection"; + public static final String VERSION_HISTORY = "version-history"; + public static final String WORKING_RESOURCE = "working-resource"; + public static final String WORKSPACE = "workspace"; + + // RFC 3648 + public static final String ORDERED_COLLECTIONS = "ordered-collections"; + + // RFC 3744 + public static final String ACCESS_CONTROL = "access-control"; + + // RFC 5842 + public static final String BIND = "bind"; + + // no RFC + public static final String OBSERVATION = "observation"; + + public static String concatComplianceClasses(String[] complianceClasses) { + StringBuffer b = new StringBuffer(); + for (int i = 0; i < complianceClasses.length; i++) { + if (i > 0) { + b.append(","); + } + b.append(complianceClasses[i]); + } + return b.toString(); + } +} \ No newline at end of file Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/DavCompliance.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-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/DavConstants.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/DavConstants.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/DavConstants.java (working copy) @@ -0,0 +1,154 @@ +/* + * 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.webdav; + +import org.apache.jackrabbit.webdav.util.HttpDateFormat; +import org.apache.jackrabbit.webdav.xml.Namespace; + +import java.text.DateFormat; + +/** + * DavConstants provide constants for request and response + * headers, XML elements and property names defined by + * RFC 2518. In addition, + * common date formats (creation date and modification time) are included. + */ +public interface DavConstants { + + /** + * Default Namespace constant + */ + public static final Namespace NAMESPACE = Namespace.getNamespace("D", "DAV:"); + + //--------------------------------< Headers (Names and Value Constants) >--- + public static final String HEADER_DAV = "DAV"; + public static final String HEADER_DESTINATION = "Destination"; + public static final String HEADER_IF = "If"; + public static final String HEADER_AUTHORIZATION = "Authorization"; + public static final String HEADER_CONTENT_TYPE = "Content-Type"; + public static final String HEADER_CONTENT_LENGTH = "Content-Length"; + public static final String HEADER_CONTENT_LANGUAGE = "Content-Language"; + public static final String HEADER_ETAG = "ETag"; + public static final String HEADER_LAST_MODIFIED = "Last-Modified"; + + //--------------------------------------------------< Lock-Token Header >--- + public static final String HEADER_LOCK_TOKEN = "Lock-Token"; + public static final String OPAQUE_LOCK_TOKEN_PREFIX = "opaquelocktoken:"; + + //-----------------------------------------------------< Timeout Header >--- + public static final String HEADER_TIMEOUT = "Timeout"; + public static final String TIMEOUT_INFINITE = "Infinite"; + // RFC 2518: timeout value for TimeType "Second" MUST NOT be greater than 2^32-1 + public static final long INFINITE_TIMEOUT = Integer.MAX_VALUE; + public static final long UNDEFINED_TIMEOUT = Integer.MIN_VALUE; + + //---------------------------------------------------< Overwrite Header >--- + public static final String HEADER_OVERWRITE = "Overwrite"; + + //-------------------------------------------------------< Depth Header >--- + public static final String HEADER_DEPTH = "Depth"; + public static final String DEPTH_INFINITY_S = "infinity"; + public static final int DEPTH_INFINITY = Integer.MAX_VALUE; + public static final int DEPTH_0 = 0; + public static final int DEPTH_1 = 1; + + //---< XML Element, Attribute Names >--------------------------------------- + public static final String XML_ALLPROP = "allprop"; + public static final String XML_COLLECTION = "collection"; + public static final String XML_DST = "dst"; + public static final String XML_HREF = "href"; + public static final String XML_INCLUDE = "include"; + public static final String XML_KEEPALIVE = "keepalive"; + public static final String XML_LINK = "link"; + public static final String XML_MULTISTATUS = "multistatus"; + public static final String XML_OMIT = "omit"; + public static final String XML_PROP = "prop"; + public static final String XML_PROPERTYBEHAVIOR = "propertybehavior"; + public static final String XML_PROPERTYUPDATE = "propertyupdate"; + public static final String XML_PROPFIND = "propfind"; + public static final String XML_PROPNAME = "propname"; + public static final String XML_PROPSTAT = "propstat"; + public static final String XML_REMOVE = "remove"; + public static final String XML_RESPONSE = "response"; + public static final String XML_RESPONSEDESCRIPTION = "responsedescription"; + public static final String XML_SET = "set"; + public static final String XML_SOURCE = "source"; + public static final String XML_STATUS = "status"; + + //------------------------------------------------------------< locking >--- + public static final String XML_ACTIVELOCK = "activelock"; + public static final String XML_DEPTH = "depth"; + public static final String XML_LOCKTOKEN = "locktoken"; + public static final String XML_TIMEOUT = "timeout"; + public static final String XML_LOCKSCOPE = "lockscope"; + public static final String XML_EXCLUSIVE = "exclusive"; + public static final String XML_SHARED = "shared"; + public static final String XML_LOCKENTRY = "lockentry"; + public static final String XML_LOCKINFO = "lockinfo"; + public static final String XML_LOCKTYPE = "locktype"; + public static final String XML_WRITE = "write"; + public static final String XML_OWNER = "owner"; + /** + * The lockroot XML element + * @see RFC 4918 + */ + public static final String XML_LOCKROOT = "lockroot"; + + //-----------------------------------------------------< Property Names >--- + /* + * Webdav property names as defined by RFC 2518
+ * Note: Microsoft webdav clients as well as Webdrive request additional + * property (e.g. href, name, owner, isRootLocation, isCollection) within the + * default namespace, which are are ignored by this implementation, except + * for the 'isCollection' property, needed for XP built-in clients. + */ + public static final String PROPERTY_CREATIONDATE = "creationdate"; + public static final String PROPERTY_DISPLAYNAME = "displayname"; + public static final String PROPERTY_GETCONTENTLANGUAGE = "getcontentlanguage"; + public static final String PROPERTY_GETCONTENTLENGTH = "getcontentlength"; + public static final String PROPERTY_GETCONTENTTYPE = "getcontenttype"; + public static final String PROPERTY_GETETAG = "getetag"; + public static final String PROPERTY_GETLASTMODIFIED = "getlastmodified"; + public static final String PROPERTY_LOCKDISCOVERY = "lockdiscovery"; + public static final String PROPERTY_RESOURCETYPE = "resourcetype"; + public static final String PROPERTY_SOURCE = "source"; + public static final String PROPERTY_SUPPORTEDLOCK = "supportedlock"; + + //-------------------------------------------------< PropFind Constants >--- + public static final int PROPFIND_BY_PROPERTY = 0; + public static final int PROPFIND_ALL_PROP = 1; + public static final int PROPFIND_PROPERTY_NAMES = 2; + public static final int PROPFIND_ALL_PROP_INCLUDE = 3; // RFC 4918, Section 9.1 + + //----------------------------------------------< Date Format Constants >--- + /** + * Marker for undefined modification or creation time. + */ + public static long UNDEFINED_TIME = -1; + + /** + * modificationDate date format per RFC 1123.
+ * NOTE: Access to DateFormat isn't thread save. + */ + public static DateFormat modificationDateFormat = HttpDateFormat.modificationDateFormat(); + + /** + * Simple date format for the creation date ISO representation (partial).
+ * NOTE: Access to DateFormat isn't thread save. + */ + public static DateFormat creationDateFormat = HttpDateFormat.creationDateFormat(); +} Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/DavConstants.java ___________________________________________________________________ Added: svn Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/DavException.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/DavException.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/DavException.java (working copy) @@ -0,0 +1,175 @@ +/* + * 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.webdav; + +import org.apache.jackrabbit.webdav.xml.DomUtil; +import org.apache.jackrabbit.webdav.xml.XmlSerializable; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +import java.io.IOException; +import java.util.Properties; + +/** + * DavException extends the {@link Exception} class in order + * to simplify handling of exceptional situations occurring during processing + * of WebDAV requests and provides possibility to retrieve an Xml representation + * of the error. + */ +public class DavException extends Exception implements XmlSerializable { + + private static Logger log = LoggerFactory.getLogger(DavException.class); + private static Properties statusPhrases = new Properties(); + static { + try { + statusPhrases.load(DavException.class.getResourceAsStream("statuscode.properties")); + } catch (IOException e) { + log.error("Failed to load status properties: " + e.getMessage()); + } + } + + public static final String XML_ERROR = "error"; + + private int errorCode = DavServletResponse.SC_INTERNAL_SERVER_ERROR; + private Element errorCondition; + + /** + * Create a new DavException. + * + * @param errorCode integer specifying any of the status codes defined by + * {@link DavServletResponse}. + * @param message Human readable error message. + * @see DavException#DavException(int, String, Throwable, Element) + */ + public DavException(int errorCode, String message) { + this(errorCode, message, null, null); + } + + /** + * Create a new DavException. + * + * @param errorCode integer specifying any of the status codes defined by + * {@link DavServletResponse}. + * @param cause Cause of this DavException + * @see DavException#DavException(int, String, Throwable, Element) + */ + public DavException(int errorCode, Throwable cause) { + this(errorCode, null, cause, null); + } + + /** + * Create a new DavException. + * + * @param errorCode integer specifying any of the status codes defined by + * {@link DavServletResponse}. + * @see DavException#DavException(int, String, Throwable, Element) + */ + public DavException(int errorCode) { + this(errorCode, statusPhrases.getProperty(String.valueOf(errorCode)), null, null); + } + + /** + * Create a new DavException. + * + * @param errorCode integer specifying any of the status codes defined by + * {@link DavServletResponse}. + * @param message Human readable error message. + * @param cause Cause of this DavException. + * @param errorCondition Xml element providing detailed information about + * the error. If the condition is not null, {@link #toXml(Document)} + */ + public DavException(int errorCode, String message, Throwable cause, Element errorCondition) { + super(message, cause); + this.errorCode = errorCode; + this.errorCondition = errorCondition; + log.debug("DavException: (" + errorCode + ") " + message); + } + + /** + * Return the error code attached to this DavException. + * + * @return errorCode + */ + public int getErrorCode() { + return errorCode; + } + + /** + * Return the status phrase corresponding to the error code attached to + * this DavException. + * + * @return status phrase corresponding to the error code. + * @see #getErrorCode() + */ + public String getStatusPhrase() { + return getStatusPhrase(errorCode); + } + + /** + * Returns the status phrase for the given error code. + * + * @param errorCode + * @return status phrase corresponding to the given error code. + */ + public static String getStatusPhrase(int errorCode) { + return statusPhrases.getProperty(errorCode + ""); + } + + /** + * @return true if a error condition has been specified, false otherwise. + */ + public boolean hasErrorCondition() { + return errorCondition != null; + } + + /** + * Return the error condition attached to this DavException. + * + * @return errorCondition + */ + public Element getErrorCondition() { + return errorCondition; + } + + /** + * Returns a DAV:error element containing the error condition or + * null if no specific condition is available. See + * RFC 3253 + * Section 1.6 "Method Preconditions and Postconditions" for additional + * information. + * + * @param document + * @return A DAV:error element indicating the error cause or null. + * @see org.apache.jackrabbit.webdav.xml.XmlSerializable#toXml(Document) + */ + public Element toXml(Document document) { + if (hasErrorCondition()) { + Element error; + if (DomUtil.matches(errorCondition, XML_ERROR, DavConstants.NAMESPACE)) { + error = (Element) document.importNode(errorCondition, true); + } else { + error = DomUtil.createElement(document, XML_ERROR, DavConstants.NAMESPACE); + error.appendChild(document.importNode(errorCondition, true)); + } + return error; + } else { + return null; + } + } +} Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/DavException.java ___________________________________________________________________ Added: svn Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/DavLocatorFactory.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/DavLocatorFactory.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/DavLocatorFactory.java (working copy) @@ -0,0 +1,72 @@ +/* + * 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.webdav; + +/** + * DavLocatorFactory... + */ +public interface DavLocatorFactory { + + /** + * Create a new DavResourceLocator. + * + * @param prefix String consisting of [scheme:][//authority][path] where + * path defines the (imaginary) path to the {@link DavResourceLocator#isRootLocation root location}. + * @param href of the resource to be created. The given string may start with + * the 'prefix'. Please note, that in contrast to + * {@link DavLocatorFactory#createResourceLocator(String, String, String)} the + * href is expected to be URL encoded. + * @return a new resource locator. + */ + public DavResourceLocator createResourceLocator(String prefix, String href); + + /** + * Create a new DavResourceLocator. This methods corresponds to + * {@link DavLocatorFactory#createResourceLocator(String, String, String, boolean)} + * with the flag set to true. + * + * @param prefix String consisting of [scheme:][//authority][path] where + * path defines the path to the {@link DavResourceLocator#isRootLocation root location}. + * @param workspacePath the first segment of the URIs path indicating the + * workspace. The implementation may allow a empty String if workspaces + * are not supported. + * @param resourcePath the URL decoded resource path. + * @return a new resource locator. + */ + public DavResourceLocator createResourceLocator(String prefix, String workspacePath, String resourcePath); + + /** + * + * @param prefix String consisting of [scheme:][//authority][path] where + * path defines the path to the {@link DavResourceLocator#isRootLocation root location}. + * @param workspacePath the first segment of the URIs path indicating the + * workspace. The implementation may allow a empty String if workspaces + * are not supported. + * @param path the URL decoded path. + * @param isResourcePath If true this method returns the same as + * {@link DavLocatorFactory#createResourceLocator(String, String, String)}, + * otherwise the given path is treated as internal repository path. + * The implementation may choose to implement a conversion of the repository + * path to a valid resource path, e.g. (un)escaping of certain characters, due + * to incompatibility with the URI definition (or vice versa). Note that + * {@link DavResourceLocator#getRepositoryPath()} should in this case implement + * the reverse operation. + * @return a new resource locator. + * @see DavResourceLocator#getRepositoryPath() + */ + public DavResourceLocator createResourceLocator(String prefix, String workspacePath, String path, boolean isResourcePath); +} \ No newline at end of file Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/DavLocatorFactory.java ___________________________________________________________________ Added: svn Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/DavMethods.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/DavMethods.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/DavMethods.java (working copy) @@ -0,0 +1,409 @@ +/* + * 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.webdav; + +import java.util.HashMap; +import java.util.Map; + +/** + * DavMethods defines constants for the WebDAV METHODS. + */ +public final class DavMethods { + + /** + * Avoid instantiation + */ + private DavMethods() {} + + /** + * A map of WebDAV METHODS + */ + private static Map methodMap = new HashMap(); + + /** + * An array of method codes that are affected by a Label header + * @see org.apache.jackrabbit.webdav.version.DeltaVConstants#HEADER_LABEL + */ + private static int[] labelMethods; + + /** + * An array of method codes defined by RFC 3253 (deltaV) + */ + private static int[] deltaVMethods; + + /** + * The webdav OPTIONS method and public constant + */ + public static final int DAV_OPTIONS = 1; + public static final String METHOD_OPTIONS = "OPTIONS"; + + /** + * The webdav GET method and public constant + */ + public static final int DAV_GET = DAV_OPTIONS + 1; + public static final String METHOD_GET = "GET"; + + /** + * The webdav HEAD method and public constant + */ + public static final int DAV_HEAD = DAV_GET + 1; + public static final String METHOD_HEAD = "HEAD"; + + + /** + * The webdav POST method and public constant + */ + public static final int DAV_POST = DAV_HEAD + 1; + public static final String METHOD_POST = "POST"; + + + /** The webdav DELETE method and public constant */ + public static final int DAV_DELETE = DAV_POST + 1; + public static final String METHOD_DELETE = "DELETE"; + + + /** The webdav PUT method and public constant */ + public static final int DAV_PUT = DAV_DELETE + 1; + public static final String METHOD_PUT = "PUT"; + + + /** + * The webdav PROPFIND method and public constant as defined by + * RFC 2518. + */ + public static final int DAV_PROPFIND = DAV_PUT + 1; + public static final String METHOD_PROPFIND = "PROPFIND"; + + + /** + * The webdav PROPPATCH method and public constant as defined by + * RFC 2518 + */ + public static final int DAV_PROPPATCH = DAV_PROPFIND + 1; + public static final String METHOD_PROPPATCH = "PROPPATCH"; + + + /** + * The webdav MKCOL (make collection) method and public constant as defined by + * RFC 2518 + */ + public static final int DAV_MKCOL = DAV_PROPPATCH + 1; + public static final String METHOD_MKCOL = "MKCOL"; + + + /** + * The webdav COPY method and public constant as defined by + * RFC 2518 + */ + public static final int DAV_COPY = DAV_MKCOL + 1; + public static final String METHOD_COPY = "COPY"; + + + /** + * The webdav MOVE method and public constant as defined by + * RFC 2518 + */ + public static final int DAV_MOVE = DAV_COPY + 1; + public static final String METHOD_MOVE = "MOVE"; + + + /** + * The webdav LOCK method and public constant as defined by + * RFC 2518 + */ + public static final int DAV_LOCK = DAV_MOVE + 1; + public static final String METHOD_LOCK = "LOCK"; + + + /** + * The webdav UNLOCK method and public constant as defined by + * RFC 2518 + */ + public static final int DAV_UNLOCK = DAV_LOCK + 1; + public static final String METHOD_UNLOCK = "UNLOCK"; + + + /** + * The webdav ORDERPATCH method and public constant + * defined by RFC 3648. + */ + public static final int DAV_ORDERPATCH = DAV_UNLOCK + 1; + public static final String METHOD_ORDERPATCH = "ORDERPATCH"; + + + /** + * The webdav SUBSCRIBE method and public constant.
+ * NOTE: This method is not defined by any of the Webdav RFCs + */ + public static final int DAV_SUBSCRIBE = DAV_ORDERPATCH + 1; + public static final String METHOD_SUBSCRIBE = "SUBSCRIBE"; + + + /** + * The webdav UNSUBSCRIBE method and public constant
+ * NOTE: This method is not defined by any of the Webdav RFCs + */ + public static final int DAV_UNSUBSCRIBE = DAV_SUBSCRIBE + 1; + public static final String METHOD_UNSUBSCRIBE = "UNSUBSCRIBE"; + + + /** + * The webdav POLL method and public constant
+ * NOTE: This method is not defined by any of the Webdav RFCs + */ + public static final int DAV_POLL = DAV_UNSUBSCRIBE + 1; + public static final String METHOD_POLL = "POLL"; + + + /** + * The webdav SEARCH method and public constant as defined by the + * Webdav Search internet draft. + */ + public static final int DAV_SEARCH = DAV_POLL + 1; + public static final String METHOD_SEARCH = "SEARCH"; + + + /** + * The webdav REPORT method and public constant defined by + * RFC 3253 + */ + public static final int DAV_REPORT = DAV_SEARCH + 1; + public static final String METHOD_REPORT = "REPORT"; + + + /** + * The webdav VERSION-CONTROL method and public constant defined by + * RFC 3253 + */ + public static final int DAV_VERSION_CONTROL = DAV_REPORT + 1; + public static final String METHOD_VERSION_CONTROL = "VERSION-CONTROL"; + + /** + * The webdav CHECKIN method and public constant defined by + * RFC 3253 + */ + public static final int DAV_CHECKIN = DAV_VERSION_CONTROL + 1; + public static final String METHOD_CHECKIN = "CHECKIN"; + + /** + * The webdav CHECKOUT method and public constant defined by + * RFC 3253 + */ + public static final int DAV_CHECKOUT = DAV_CHECKIN + 1; + public static final String METHOD_CHECKOUT = "CHECKOUT"; + + /** + * The webdav UNCHECKOUT method and public constant defined by + * RFC 3253 + */ + public static final int DAV_UNCHECKOUT = DAV_CHECKOUT + 1; + public static final String METHOD_UNCHECKOUT = "UNCHECKOUT"; + + /** + * The webdav LABEL method and public constant defined by + * RFC 3253 + */ + public static final int DAV_LABEL = DAV_UNCHECKOUT + 1; + public static final String METHOD_LABEL = "LABEL"; + + /** + * The webdav MERGE method and public constant defined by + * RFC 3253 + */ + public static final int DAV_MERGE = DAV_LABEL + 1; + public static final String METHOD_MERGE = "MERGE"; + + /** + * The webdav UPDATE method and public constant defined by + * RFC 3253 + */ + public static final int DAV_UPDATE = DAV_MERGE + 1; + public static final String METHOD_UPDATE = "UPDATE"; + + /** + * The webdav MKWORKSPACE method and public constant defined by + * RFC 3253 + */ + public static final int DAV_MKWORKSPACE = DAV_UPDATE + 1; + public static final String METHOD_MKWORKSPACE = "MKWORKSPACE"; + + /** + * The webdav BASELINE-CONTROL method and public constant defined by + * RFC 3253 + */ + public static final int DAV_BASELINE_CONTROL = DAV_MKWORKSPACE + 1; + public static final String METHOD_BASELINE_CONTROL = "BASELINE-CONTROL"; + + /** + * The webdav MKACTIVITY method and public constant defined by + * RFC 3253 + */ + public static final int DAV_MKACTIVITY = DAV_BASELINE_CONTROL + 1; + public static final String METHOD_MKACTIVITY = "MKACTIVITY"; + + /** + * The webdav ACL method and public constant defined by + * RFC 3744 + */ + public static final int DAV_ACL = DAV_MKACTIVITY + 1; + public static final String METHOD_ACL = "ACL"; + + /** + * The webdav REBIND method and public constant defined by + * the BIND specification + */ + public static final int DAV_REBIND = DAV_ACL + 1; + public static final String METHOD_REBIND = "REBIND"; + + /** + * The webdav UNBIND method and public constant defined by + * the BIND specification + */ + public static final int DAV_UNBIND = DAV_REBIND + 1; + public static final String METHOD_UNBIND = "UNBIND"; + + /** + * The webdav BIND method and public constant defined by + * the BIND specification + */ + public static final int DAV_BIND = DAV_UNBIND + 1; + public static final String METHOD_BIND = "BIND"; + + /** + * Returns webdav method type code, error result <= 0 + * Valid type codes > 0 + */ + public static int getMethodCode(String method) { + Integer code = methodMap.get(method.toUpperCase()); + if (code != null) { + return code; + } + return 0; + } + + /** + * Static initializer for methodTable map + */ + private static void addMethodCode(String method, int code) { + methodMap.put(method, code); + } + + /** + * Webdav Method table + */ + static { + addMethodCode(METHOD_OPTIONS, DAV_OPTIONS); + addMethodCode(METHOD_GET, DAV_GET); + addMethodCode(METHOD_HEAD, DAV_HEAD); + addMethodCode(METHOD_POST, DAV_POST); + addMethodCode(METHOD_PUT, DAV_PUT); + addMethodCode(METHOD_DELETE, DAV_DELETE); + addMethodCode(METHOD_PROPFIND, DAV_PROPFIND); + addMethodCode(METHOD_PROPPATCH, DAV_PROPPATCH); + addMethodCode(METHOD_MKCOL, DAV_MKCOL); + addMethodCode(METHOD_COPY, DAV_COPY); + addMethodCode(METHOD_MOVE, DAV_MOVE); + addMethodCode(METHOD_LOCK, DAV_LOCK); + addMethodCode(METHOD_UNLOCK, DAV_UNLOCK); + addMethodCode(METHOD_ORDERPATCH, DAV_ORDERPATCH); + addMethodCode(METHOD_SUBSCRIBE, DAV_SUBSCRIBE); + addMethodCode(METHOD_UNSUBSCRIBE, DAV_UNSUBSCRIBE); + addMethodCode(METHOD_POLL, DAV_POLL); + addMethodCode(METHOD_SEARCH, DAV_SEARCH); + addMethodCode(METHOD_REPORT, DAV_REPORT); + addMethodCode(METHOD_VERSION_CONTROL, DAV_VERSION_CONTROL); + addMethodCode(METHOD_CHECKIN, DAV_CHECKIN); + addMethodCode(METHOD_CHECKOUT, DAV_CHECKOUT); + addMethodCode(METHOD_UNCHECKOUT, DAV_UNCHECKOUT); + addMethodCode(METHOD_LABEL, DAV_LABEL); + addMethodCode(METHOD_MERGE, DAV_MERGE); + addMethodCode(METHOD_UPDATE, DAV_UPDATE); + addMethodCode(METHOD_MKWORKSPACE, DAV_MKWORKSPACE); + addMethodCode(METHOD_BASELINE_CONTROL, DAV_BASELINE_CONTROL); + addMethodCode(METHOD_MKACTIVITY, DAV_MKACTIVITY); + addMethodCode(METHOD_ACL, DAV_ACL); + addMethodCode(METHOD_REBIND, DAV_REBIND); + addMethodCode(METHOD_UNBIND, DAV_UNBIND); + addMethodCode(METHOD_BIND, DAV_BIND); + + labelMethods = new int[] { DAV_GET, DAV_HEAD, DAV_OPTIONS, DAV_PROPFIND, + DAV_LABEL, DAV_COPY }; + + deltaVMethods = new int[] { DAV_REPORT, DAV_VERSION_CONTROL, DAV_CHECKIN, + DAV_CHECKOUT, DAV_UNCHECKOUT, DAV_LABEL, + DAV_MERGE, DAV_UPDATE, DAV_MKWORKSPACE, + DAV_BASELINE_CONTROL, DAV_MKACTIVITY }; + } + + /** + * Returns true if the request is to create a resource. + * True for PUT, POST, MKCOL + * and MKWORKSPACE requests. + * + * @return true if request method is to create (or replace) a resource + */ + public static boolean isCreateRequest(DavServletRequest request) { + int methodCode = getMethodCode(request.getMethod()); + return ( methodCode == DAV_PUT || + methodCode == DAV_POST || + methodCode == DAV_MKCOL || + methodCode == DAV_MKWORKSPACE); + } + + /** + * Returns true if the request is to create a collection resource. + * True for MKCOL and MKWORKSPACE requests. + * + * @return true if request method is to create a new collection resource + */ + public static boolean isCreateCollectionRequest(DavServletRequest request) { + int methodCode = getMethodCode(request.getMethod()); + return (methodCode == DAV_MKCOL || methodCode == DAV_MKWORKSPACE); + } + + /** + * Returns true, if the specified method is affected by a Label header + * + * @param request + * @return + */ + public static boolean isMethodAffectedByLabel(DavServletRequest request) { + int code = getMethodCode(request.getMethod()); + for (int labelMethod : labelMethods) { + if (code == labelMethod) { + return true; + } + } + return false; + } + + /** + * Returns true, if the specified method is defined by RFC 3253 + * + * @param request + * @return true, if the specified method is defined by RFC 3253 + */ + public static boolean isDeltaVMethod(DavServletRequest request) { + int code = getMethodCode(request.getMethod()); + for (int deltaVMethod : deltaVMethods) { + if (code == deltaVMethod) { + return true; + } + } + return false; + } +} Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/DavMethods.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/DavResource.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/DavResource.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/DavResource.java (working copy) @@ -0,0 +1,334 @@ +/* + * 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.webdav; + +import org.apache.jackrabbit.webdav.io.InputContext; +import org.apache.jackrabbit.webdav.io.OutputContext; +import org.apache.jackrabbit.webdav.lock.ActiveLock; +import org.apache.jackrabbit.webdav.lock.LockInfo; +import org.apache.jackrabbit.webdav.lock.LockManager; +import org.apache.jackrabbit.webdav.lock.Scope; +import org.apache.jackrabbit.webdav.lock.Type; +import org.apache.jackrabbit.webdav.property.DavProperty; +import org.apache.jackrabbit.webdav.property.DavPropertyName; +import org.apache.jackrabbit.webdav.property.DavPropertySet; +import org.apache.jackrabbit.webdav.property.PropEntry; + +import java.io.IOException; +import java.util.List; + +/** + * DavResource provides standard WebDAV functionality as specified + * by RFC 2518. + */ +public interface DavResource { + + /** + * String constant representing the WebDAV 1 and 2 method set. + */ + public static final String METHODS = "OPTIONS, GET, HEAD, TRACE, PROPFIND, PROPPATCH, MKCOL, COPY, PUT, DELETE, MOVE, LOCK, UNLOCK"; + + /** + * Returns a comma separated list of all compliance classes the given + * resource is fulfilling. + * + * @return compliance classes + */ + public String getComplianceClass(); + + /** + * Returns a comma separated list of all METHODS supported by the given + * resource. + * + * @return METHODS supported by this resource. + */ + public String getSupportedMethods(); + + /** + * Returns true if this webdav resource represents an existing repository item. + * + * @return true, if the resource represents an existing repository item. + */ + public boolean exists(); + + /** + * Returns true if this webdav resource has the resourcetype 'collection'. + * + * @return true if the resource represents a collection resource. + */ + public boolean isCollection(); + + /** + * Returns the display name of this resource. + * + * @return display name. + */ + public String getDisplayName(); + + /** + * Returns the {@link DavResourceLocator locator} object for this webdav resource, + * which encapsulates the information for building the complete 'href'. + * + * @return the locator for this resource. + * @see #getResourcePath() + * @see #getHref() + */ + public DavResourceLocator getLocator(); + + /** + * Returns the path of the hierarchy element defined by this DavResource. + * This method is a shortcut for DavResource.getLocator().getResourcePath(). + * + * @return path of the element defined by this DavResource. + */ + public String getResourcePath(); + + /** + * Returns the absolute href of this resource as returned in the + * multistatus response body. + * + * @return href + */ + public String getHref(); + + /** + * Return the time of the last modification or -1 if the modification time + * could not be retrieved. + * + * @return time of last modification or -1. + */ + public long getModificationTime(); + + /** + * Spools the resource properties and ev. content to the specified context + * (e.g. to respond to a 'GET' or 'HEAD' request). The context could e.g. + * wrap the servlet response. + * + * @param outputContext The output context. + * @throws IOException If an error occurs. + */ + public void spool(OutputContext outputContext) throws IOException; + + /** + * Returns an array of all {@link DavPropertyName property names} available + * on this resource. + * + * @return an array of property names. + */ + public DavPropertyName[] getPropertyNames(); + + /** + * Return the webdav property with the specified name. + * + * @param name name of the webdav property + * @return the {@link DavProperty} with the given name or null + * if the property does not exist. + */ + public DavProperty getProperty(DavPropertyName name); + + /** + * Returns all webdav properties present on this resource that will be + * return upon a {@link DavConstants#PROPFIND_ALL_PROP} request. The + * implementation may in addition expose other (protected or calculated) + * properties which should be marked accordingly (see also + * {@link org.apache.jackrabbit.webdav.property.DavProperty#isInvisibleInAllprop()}. + * + * @return a {@link DavPropertySet} containing at least all properties + * of this resource that are exposed in 'allprop' PROPFIND request. + */ + public DavPropertySet getProperties(); + + /** + * Add/Set the specified property on this resource. + * + * @param property + * @throws DavException if an error occurs + */ + public void setProperty(DavProperty property) throws DavException; + + /** + * Remove the specified property from this resource. + * + * @param propertyName + * @throws DavException if an error occurs + */ + public void removeProperty(DavPropertyName propertyName) throws DavException; + + /** + * Set/add and remove the specified properties from this resource. + * + * @param changeList list containing {@link DavPropertyName} objects (for + * properties to be removed) and {@link DavProperty} objects (for + * properties to be added/set). + * @return multistatus response listing the status resulting from + * setting and/or removing the specified properties, in order to allow a + * detailed multistatus response. + * @throws DavException if an error occurred. This may be the case if the + * general state of the resource prevents any properties to be set or removed + * (e.g. due to a lock). + */ + public MultiStatusResponse alterProperties(List changeList) throws DavException; + + /** + * Retrieve the resource this resource is internal member of. + * + * @return resource this resource is an internal member of. In case this resource + * is the root null is returned. + */ + public DavResource getCollection(); + + /** + * Add the given resource as an internal member to this resource. + * + * @param resource {@link DavResource} to be added as internal member. + * @param inputContext Context providing the properties and content for the + * internal member to be created or replaced. + * @throws DavException + */ + public void addMember(DavResource resource, InputContext inputContext) throws DavException; + + /** + * Returns an iterator over all internal members. + * + * @return a {@link DavResourceIterator} over all internal members. + */ + public DavResourceIterator getMembers(); + + /** + * Removes the specified member from this resource. + * + * @throws DavException + */ + public void removeMember(DavResource member) throws DavException; + + /** + * Move this DavResource to the given destination resource + * + * @param destination + * @throws DavException + */ + public void move(DavResource destination) throws DavException; + + /** + * Copy this DavResource to the given destination resource + * + * @param destination + * @param shallow + * @throws DavException + */ + public void copy(DavResource destination, boolean shallow) throws DavException; + + /** + * Returns true, if the this resource allows locking. NOTE, that this method + * does not define, whether a lock/unlock can be successfully executed. + * + * @return true, if this resource supports any locking. + * @param type + * @param scope + */ + public boolean isLockable(Type type, Scope scope); + + /** + * Returns true if a lock applies to this resource. This may be either a + * lock on this resource itself or a deep lock inherited from a collection + * above this resource.
+ * Note, that true is returned whenever a lock applies to that resource even + * if the lock is expired or not effective due to the fact that the request + * provides the proper lock token. + * + * @return true if a lock applies to this resource. + * @param type + */ + public boolean hasLock(Type type, Scope scope); + + /** + * Return the lock present on this webdav resource or null + * if the resource is either not locked or not lockable at all. Note, that + * a resource may have a lock that is inherited by a deep lock enforced on + * one of its 'parent' resources. + * + * @return lock information of this resource or null if this + * resource has no lock applying it. If an error occurs while retrieving the + * lock information null is returned as well. + * @param type + */ + public ActiveLock getLock(Type type, Scope scope) ; + + /** + * Returns an array of all locks applied to the given resource. + * + * @return array of locks. The array is empty if there are no locks applied + * to this resource. + */ + public ActiveLock[] getLocks(); + + /** + * Lock this webdav resource with the information retrieve from the request + * and return the resulting lockdiscovery object. + * + * @param reqLockInfo lock info as retrieved from the request. + * @return lockdiscovery object to be returned in the response. If the lock + * could not be obtained a DavException is thrown. + * @throws DavException if the lock could not be obtained. + */ + public ActiveLock lock(LockInfo reqLockInfo) throws DavException; + + /** + * Refresh an existing lock by resetting the timeout. + * + * @param reqLockInfo lock info as retrieved from the request. + * @param lockToken identifying the lock to be refreshed. + * @return lockdiscovery object to be returned in the response body. If the lock + * could not be refreshed a DavException is thrown. + * @throws DavException if the lock could not be refreshed. + */ + public ActiveLock refreshLock(LockInfo reqLockInfo, String lockToken) throws DavException; + + /** + * Remove the lock identified by the included lock token from this resource. + * This method will return false if the unlocking did not succeed. + * + * @param lockToken identifying the lock to be removed. + * @throws DavException if the lock could not be removed. + */ + public void unlock(String lockToken) throws DavException; + + /** + * Add an external {@link LockManager} to this resource. This method may + * throw {@link UnsupportedOperationException} if the resource does handle + * locking itself. + * + * @param lockmgr + * @see LockManager + */ + public void addLockManager(LockManager lockmgr); + + /** + * Return the DavResourceFactory that created this resource. + * + * @return the factory that created this resource. + */ + public DavResourceFactory getFactory(); + + /** + * Retrieve the DavSession associated with this resource. + * + * @return session object associated with this resource. + */ + public DavSession getSession(); +} + Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/DavResource.java ___________________________________________________________________ Added: svn Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/DavResourceFactory.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/DavResourceFactory.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/DavResourceFactory.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.webdav; + +/** + * DavResourceFactory interface defines a single method for creating + * {@link DavResource} objects. + */ +public interface DavResourceFactory { + + /** + * Create a {@link DavResource} object from the given locator, request and response + * objects. + * + * @param locator locator of the resource + * @param request + * @param response + * @return a new DavResource object. + * @throws DavException + */ + public DavResource createResource(DavResourceLocator locator, DavServletRequest request, DavServletResponse response) throws DavException; + + /** + * Create a new {@link DavResource} object from the given locator and session. + * + * @param locator + * @param session + * @return a new DavResource object. + * @throws DavException + */ + public DavResource createResource(DavResourceLocator locator, DavSession session) throws DavException; +} \ No newline at end of file Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/DavResourceFactory.java ___________________________________________________________________ Added: svn Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/DavResourceIterator.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/DavResourceIterator.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/DavResourceIterator.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.webdav; + +import java.util.Iterator; + +/** + * DavResourceIterator extends the Iterator interface. Additional + * METHODS allow to retrieve the next {@link DavResource} from the iterator + * and the iterators size. + */ +public interface DavResourceIterator extends Iterator { + + /** + * Returns the next {@link DavResource} in the iterator + * @return the next {@link DavResource} + */ + public DavResource nextResource(); + + /** + * Return the number of {@link DavResource}s in the iterator. + * @return number of elements in the iterator. + */ + public int size(); +} Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/DavResourceIterator.java ___________________________________________________________________ Added: svn Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/DavResourceIteratorImpl.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/DavResourceIteratorImpl.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/DavResourceIteratorImpl.java (working copy) @@ -0,0 +1,85 @@ +/* + * 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.webdav; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.Iterator; +import java.util.List; +import java.util.Collections; + +/** + * DavResourceIteratorImpl implementation of the {@link DavResourceIterator} + * interface.
+ * NOTE: {@link #remove()} is not implemented. + */ +public class DavResourceIteratorImpl implements DavResourceIterator { + + private static Logger log = LoggerFactory.getLogger(DavResourceIteratorImpl.class); + + public static final DavResourceIterator EMPTY = new DavResourceIteratorImpl(Collections.emptyList()); + + private Iterator it; + private int size; + + /** + * Create a new DavResourceIterator from the specified list. + * @param list + */ + public DavResourceIteratorImpl(List list) { + it = list.iterator(); + size = list.size(); + } + + /** + * @see DavResourceIterator#hasNext() + */ + public boolean hasNext() { + return it.hasNext(); + } + + /** + * @see DavResourceIterator#next() + */ + public DavResource next() { + return it.next(); + } + + /** + * @see DavResourceIterator#nextResource() + */ + public DavResource nextResource() { + return next(); + } + + /** + * Returns the size of the initial list. + * + * @see DavResourceIterator#size() + */ + public int size() { + return size; + } + + /** + * @see DavResourceIterator#remove() + */ + public void remove() { + throw new UnsupportedOperationException("Remove not allowed with DavResourceIteratorImpl"); + } +} Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/DavResourceIteratorImpl.java ___________________________________________________________________ Added: svn Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/DavResourceLocator.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/DavResourceLocator.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/DavResourceLocator.java (working copy) @@ -0,0 +1,115 @@ +/* + * 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.webdav; + +/** + * DavResourceLocator... + */ +public interface DavResourceLocator { + + /** + * Return the prefix used to build the complete href of the resource as + * required for the {@link DavConstants#XML_HREF href Xml} element. + * This includes scheme and host information as well as constant prefixes. + * However, this must not include workspace prefix. + * + * @return prefix needed in order to build the href from a resource path. + * @see #getResourcePath() + */ + public String getPrefix(); + + /** + * Return the resource path. + * + * @return resource path + */ + public String getResourcePath(); + + /** + * Return the path of the workspace the resource identified by this + * locator is member of. + * + * @return path of the workspace + */ + public String getWorkspacePath(); + + /** + * Return the name of the workspace the resource identified by this + * locator is member of. + * + * @return workspace name + */ + public String getWorkspaceName(); + + /** + * Returns true if the specified locator refers to a resource within the + * same workspace. + * + * @param locator + * @return true if both paths are in the same workspace. + */ + public boolean isSameWorkspace(DavResourceLocator locator); + + /** + * Returns true if the specified workspace name equals to the workspace + * name defined with this locator. + * + * @param workspaceName + * @return true if workspace names are equal. + */ + public boolean isSameWorkspace(String workspaceName); + + /** + * Return the 'href' representation of this locator object. The implementation + * should perform an URL encoding of the resource path. + * + * @param isCollection + * @return 'href' representation of this path + * @see DavConstants#XML_HREF + * @see DavResource#getHref() + */ + public String getHref(boolean isCollection); + + /** + * Returns true if this DavResourceLocator represents the root + * locator that would be requested with 'hrefPrefix'+'pathPrefix' with or + * without a trailing '/'. + * + * @return true if this locator object belongs to the root resource. + */ + public boolean isRootLocation(); + + /** + * Return the locator factory that created this locator. + * + * @return the locator factory + */ + public DavLocatorFactory getFactory(); + + /** + * An implementation may choose to circumvent the incompatibility of a + * repository path with the URI path by applying an appropriate conversion. + * This utility method allows to retrieve this transformed repository path. + * By default this method should return the same as {@link #getResourcePath()} + * + * @return a repository compatible form if the resource path. + * @see DavLocatorFactory#createResourceLocator(String, String, String, boolean) + * that allows to build a valid DavResourceLocator from a given + * repository path. + */ + public String getRepositoryPath(); +} \ No newline at end of file Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/DavResourceLocator.java ___________________________________________________________________ Added: svn Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/DavServletRequest.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/DavServletRequest.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/DavServletRequest.java (working copy) @@ -0,0 +1,199 @@ +/* + * 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.webdav; + +import org.apache.jackrabbit.webdav.lock.LockInfo; +import org.apache.jackrabbit.webdav.property.DavPropertyNameSet; +import org.apache.jackrabbit.webdav.property.DavProperty; +import org.apache.jackrabbit.webdav.property.DavPropertyName; +import org.apache.jackrabbit.webdav.property.PropEntry; +import org.w3c.dom.Document; + +import javax.servlet.http.HttpServletRequest; +import java.util.List; + +/** + * DavServletRequest extends the HttpServletRequest by Webdav + * specific METHODS. + */ +public interface DavServletRequest extends HttpServletRequest { + + /** + * Sets the DavSession to this request. + * + * @param session + */ + public void setDavSession(DavSession session); + + /** + * Returns the {@link DavSession} created for this request. + * + * @return session for this resource + */ + public DavSession getDavSession(); + + /** + * Return the locator of the requested {@link DavResource resource}. + * + * @return locator of the requested {@link DavResource resource}. + */ + public DavResourceLocator getRequestLocator(); + + /** + * Parse the {@link DavConstants#HEADER_DESTINATION Destination header} + * and return the locator of the corresponding {@link DavResource resource}. + * + * @return locator of the resource specified with the Destination header. + * @see DavConstants#HEADER_DESTINATION + */ + public DavResourceLocator getDestinationLocator() throws DavException; + + /** + * Returns true if the {@link DavConstants#HEADER_OVERWRITE Overwrite header} + * is set to 'T' thus instructing the server to overwrite the state of a + * non-null destination resource during a COPY or MOVE. A Overwrite header + * value of 'F' will return false. + * + * @return true if the Overwrite header is set to 'T', false if it is set + * to 'F'. + * @see DavConstants#HEADER_OVERWRITE + */ + public boolean isOverwrite(); + + /** + * Return the integer representation of the given {@link DavConstants#HEADER_DEPTH + * Depth header}. 'Infinity' is represented by {@link DavConstants#DEPTH_INFINITY}. + * + * @return integer representation of the {@link DavConstants#HEADER_DEPTH + * Depth header}. + * @see DavConstants#HEADER_DEPTH + */ + public int getDepth(); + + /** + * Returns the integer representation of the {@link DavConstants#HEADER_DEPTH + * Depth header} or the given defaultValue, if the Depth header is missing. + * + * @param defaultValue to be returned if no Depth header is present. + * @return integer representation of the {@link DavConstants#HEADER_DEPTH + * Depth header} or the given defaultValue. + * @see DavConstants#HEADER_DEPTH + */ + public int getDepth(int defaultValue); + + /** + * Returns the token present in the {@link DavConstants#HEADER_LOCK_TOKEN + * Lock-Token Header} or null if no such header is available.
+ * Note: The 'Lock-Token' header is sent with UNLOCK requests and with + * lock responses only. For any other request that may be affected by a lock + * the 'If' header field is responsible. + * + * @return the token present in the Lock-Token header. + * @see DavConstants#HEADER_LOCK_TOKEN + */ + public String getLockToken(); + + /** + * Return the timeout requested in the {@link DavConstants#HEADER_TIMEOUT + * Timeout header} as long. The representation of the + * 'Infinite' timeout is left to the implementation. + * + * @return long value representation of the Timeout header. + * @see DavConstants#HEADER_TIMEOUT + * @see DavConstants#TIMEOUT_INFINITE + */ + public long getTimeout(); + + /** + * Parse the Xml request body and return a {@link org.w3c.dom.Document}. + * + * @return Document representing the Xml request body or null + * if no request body is present. + * @throws DavException If the request body cannot be parsed into an Xml + * Document. + */ + public Document getRequestDocument() throws DavException; + + /** + * Return the type of PROPFIND request as indicated by the PROPFIND request + * body. + * + * @return type of PROPFIND request + * @see DavConstants#PROPFIND_ALL_PROP + * @see DavConstants#PROPFIND_BY_PROPERTY + * @see DavConstants#PROPFIND_PROPERTY_NAMES + * @see DavConstants#PROPFIND_ALL_PROP_INCLUDE + * @throws DavException If the propfind type could not be determined due to + * an invalid request body. + */ + public int getPropFindType() throws DavException; + + /** + * Return the set of properties the client requested with a PROPFIND request + * or an empty set if the type of PROPFIND request was {@link DavConstants#PROPFIND_ALL_PROP} + * or {@link DavConstants#PROPFIND_PROPERTY_NAMES}. + * + * @return set of properties the client requested with a PROPFIND request + * @throws DavException In case of invalid request body + */ + public DavPropertyNameSet getPropFindProperties() throws DavException; + + /** + * Return a {@link List} of property change operations. Each entry + * is either of type {@link DavPropertyName}, indicating a <remove> + * operation, or of type {@link DavProperty}, indicating a <set> + * operation. Note that ordering is significant here. + * + * @return {@link List} of property change operations + * @throws DavException In case of invalid request body + */ + public List getPropPatchChangeList() throws DavException; + + /** + * Return the parsed 'lockinfo' request body, the {@link DavConstants#HEADER_TIMEOUT + * Timeout header} and the {@link DavConstants#HEADER_DEPTH Depth header} + * of a LOCK request as LockInfo object. + * + * @return LockInfo object encapsulating the information + * present in the LOCK request. + * @see DavConstants#HEADER_TIMEOUT + * @see DavConstants#HEADER_DEPTH + * @see DavConstants#XML_LOCKINFO + * @throws DavException + */ + public LockInfo getLockInfo() throws DavException; + + /** + * Returns true, if the {@link DavConstants#HEADER_IF If header} present + * with the request matches the given resource. + * + * @param resource + * @return true, if the test is successful, false otherwise. + */ + public boolean matchesIfHeader(DavResource resource); + + /** + * Returns true, if the {@link DavConstants#HEADER_IF If header} present + * with the request matches to the given href, token and eTag. + * + * @param href + * @param token + * @param eTag + * @return true, if the test is successful, false otherwise. + */ + public boolean matchesIfHeader(String href, String token, String eTag); +} Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/DavServletRequest.java ___________________________________________________________________ Added: svn Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/DavServletResponse.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/DavServletResponse.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/DavServletResponse.java (working copy) @@ -0,0 +1,149 @@ +/* + * 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.webdav; + +import org.apache.jackrabbit.webdav.lock.ActiveLock; +import org.apache.jackrabbit.webdav.xml.XmlSerializable; + +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.util.List; + +/** + * WebdavResponse extends the HttpServletResponse by + * Webdav specific status codes and METHODS. + */ +public interface DavServletResponse extends HttpServletResponse { + + /** + * The 102 (Processing) status code is an interim response used to + * inform the client that the server has accepted the complete request, + * but has not yet completed it. + */ + int SC_PROCESSING = 102; + + /** + * Status code (207) indicating that the response requires + * providing status for multiple independent operations. + */ + int SC_MULTI_STATUS = 207; + + /** + * The 422 (Unprocessable Entity) status code means the server understands + * the content type of the request entity (hence a 415(Unsupported Media Type) + * status code is inappropriate), and the syntax of the request entity is + * correct (thus a 400 (Bad Request) status code is inappropriate) but was + * unable to process the contained instructions. For example, this error + * condition may occur if an XML request body contains well-formed (i.e., + * syntactically correct), but semantically erroneous XML instructions. + */ + int SC_UNPROCESSABLE_ENTITY = 422; + + /** + * Status code (423) indicating the destination resource of a + * method is locked, and either the request did not contain a + * valid Lock-Info header, or the Lock-Info header identifies + * a lock held by another principal. + */ + int SC_LOCKED = 423; + + /** + * Status code (424) indicating that the method could not be + * performed on the resource, because the requested action depended + * on another action which failed. + */ + int SC_FAILED_DEPENDENCY = 424; + + /** + * Status code (507) indicating that the resource does not have + * sufficient space to record the state of the resource after the + * execution of this method. + */ + int SC_INSUFFICIENT_SPACE_ON_RESOURCE = 507; + + /** + * Send a response body given more detailed information about the error + * occurred. + * + * @param error + * @throws IOException + */ + public void sendError(DavException error) throws IOException; + + /** + * Send the multistatus response to the client. A multistatus response + * is returned in response to a successful PROPFIND and PROPPATCH request. + * In addition multistatus response is required response in case a COPY, + * MOVE, DELETE, LOCK or PROPPATCH request fails. + * + * @param multistatus + * @throws IOException + * @see #SC_MULTI_STATUS + */ + public void sendMultiStatus(MultiStatus multistatus) throws IOException; + + /** + * Send the multistatus response to the client. A multistatus response + * is returned in response to a successful PROPFIND and PROPPATCH request. + * In addition multistatus response is required response in case a COPY, + * MOVE, DELETE, LOCK or PROPPATCH request fails. + * + * @param multistatus + * @param acceptableContentCodings content codings accepted by the client + * @throws IOException + * @see #SC_MULTI_STATUS + */ + default void sendMultiStatus(MultiStatus multistatus, List acceptableContentCodings) throws IOException { + sendMultiStatus(multistatus); + } + + /** + * Send the lock response for a successful LOCK request, that was intended + * to refresh an existing lock. The locks array must contain at least + * a single element; the ActiveLock objects are then + * included in the lockdiscovery property of the response body as required + * by RFC 2518. + * + * @param locks + * @throws IOException + * @see DavConstants#PROPERTY_LOCKDISCOVERY + */ + public void sendRefreshLockResponse(ActiveLock[] locks) throws IOException; + + /** + * Generic method to return an Xml response body. + * + * @param serializable object that can be converted to the root Xml element + * of the document to be sent as response body. + * @param status Status code to be used with {@link #setStatus(int)}. + * @throws IOException + */ + public void sendXmlResponse(XmlSerializable serializable, int status) throws IOException; + + /** + * Generic method to return an Xml response body. + * + * @param serializable object that can be converted to the root Xml element + * of the document to be sent as response body. + * @param status Status code to be used with {@link #setStatus(int)}. + * @param acceptableContentCodings content codings accepted by the client + * @throws IOException + */ + default void sendXmlResponse(XmlSerializable serializable, int status, List acceptableContentCodings) throws IOException { + sendXmlResponse(serializable, status); + } +} \ No newline at end of file Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/DavServletResponse.java ___________________________________________________________________ Added: svn Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/DavSession.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/DavSession.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/DavSession.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.webdav; + +/** + * DavSession allows to pass session information between request, + * response and resource(s). + */ +public interface DavSession { + + /** + * Adds a reference to this DavSession indicating that this + * session must not be discarded after completion of the current request. + * + * @param reference to be added. + */ + public void addReference(Object reference); + + /** + * Releasing a reference to this DavSession. If no more + * references are present, this session may be discarded. + * + * @param reference to be removed. + */ + public void removeReference(Object reference); + + /** + * Adds a lock token to this DavSession. + * + * @param token + */ + public void addLockToken(String token); + + /** + * Returns the lock tokens of this DavSession. + * + * @return + */ + public String[] getLockTokens(); + + /** + * Removes a lock token from this DavSession. + * + * @param token + */ + public void removeLockToken(String token); + +} \ No newline at end of file Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/DavSession.java ___________________________________________________________________ Added: svn Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/DavSessionProvider.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/DavSessionProvider.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/DavSessionProvider.java (working copy) @@ -0,0 +1,48 @@ +/* + * 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.webdav; + +/** + * DavSessionProvider is an interface for components that + * can initiate and complete {@link DavSession}s. A provider is + * responsible for supplying references from a {@link WebdavRequest} + * to a {@link DavSession} when acquired and removing the references + * when released. + + */ +public interface DavSessionProvider { + + /** + * Acquires a DavSession. Upon success, the WebdavRequest will + * reference that session. + * + * A session will not be available if an exception is thrown. + * + * @param request + * @return true if the session was attached to the request; + * false otherwise. + * @throws DavException if a problem occurred while obtaining the session + */ + public boolean attachSession(WebdavRequest request) throws DavException; + + /** + * Releases the reference from the request to the session. + * + * @param request + */ + public void releaseSession(WebdavRequest request); +} Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/DavSessionProvider.java ___________________________________________________________________ Added: svn Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/MultiStatus.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/MultiStatus.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/MultiStatus.java (working copy) @@ -0,0 +1,193 @@ +/* + * 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.webdav; + +import org.apache.jackrabbit.webdav.property.DavPropertyNameSet; +import org.apache.jackrabbit.webdav.xml.DomUtil; +import org.apache.jackrabbit.webdav.xml.ElementIterator; +import org.apache.jackrabbit.webdav.xml.XmlSerializable; +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +import java.util.LinkedHashMap; +import java.util.Map; + +/** + * MultiStatus representing the content of a multistatus response body and + * allows to retrieve the Xml representation. + */ +public class MultiStatus implements DavConstants, XmlSerializable { + + /** + * Map collecting the responses for this multistatus, where every href must + * only occur one single time. + */ + private Map responses = new LinkedHashMap(); + + /** + * A general response description at the multistatus top level is used to + * provide a general message describing the overarching nature of the response. + * If this value is available an application may use it instead of + * presenting the individual response descriptions contained within the + * responses. + */ + private String responseDescription; + + /** + * Add response(s) to this multistatus, in order to build a multistatus for + * responding to a PROPFIND request. + * + * @param resource The resource to add property from + * @param propNameSet The requested property names of the PROPFIND request + * @param propFindType + * @param depth + */ + public void addResourceProperties(DavResource resource, DavPropertyNameSet propNameSet, + int propFindType, int depth) { + addResponse(new MultiStatusResponse(resource, propNameSet, propFindType)); + if (depth > 0 && resource.isCollection()) { + DavResourceIterator iter = resource.getMembers(); + while (iter.hasNext()) { + addResourceProperties(iter.nextResource(), propNameSet, propFindType, depth-1); + } + } + } + + /** + * Add response(s) to this multistatus, in order to build a multistatus e.g. + * in order to respond to a PROPFIND request. Please note, that in terms + * of PROPFIND, this method would correspond to a + * {@link DavConstants#PROPFIND_BY_PROPERTY} propfind type. + * + * @param resource The resource to add property from + * @param propNameSet The requested property names of the PROPFIND request + * @param depth + * @see #addResourceProperties(DavResource, DavPropertyNameSet, int, int) for + * the corresponding method that allows to specify the type. + */ + public void addResourceProperties(DavResource resource, DavPropertyNameSet propNameSet, + int depth) { + addResourceProperties(resource, propNameSet, PROPFIND_BY_PROPERTY, depth); + } + + /** + * Add response(s) to this multistatus, in order to build a multistatus + * as returned for COPY, MOVE, LOCK or DELETE requests resulting in an error + * with a resource other than the resource identified in the Request-URI. + * + * @param resource + * @param status + * @param depth + */ + public void addResourceStatus(DavResource resource, int status, int depth) { + addResponse(new MultiStatusResponse(resource.getHref(), status)); + if (depth > 0 && resource.isCollection()) { + DavResourceIterator iter = resource.getMembers(); + while (iter.hasNext()) { + addResourceStatus(iter.nextResource(), status, depth-1); + } + } + } + + /** + * Add a MultiStatusResponse element to this MultiStatus + *

+ * This method is synchronized to avoid the problem described in + * JCR-2755. + * + * @param response + */ + public synchronized void addResponse(MultiStatusResponse response) { + responses.put(response.getHref(), response); + } + + /** + * Returns the multistatus responses present as array. + *

+ * This method is synchronized to avoid the problem described in + * JCR-2755. + * + * @return array of all {@link MultiStatusResponse responses} present in this + * multistatus. + */ + public synchronized MultiStatusResponse[] getResponses() { + return responses.values().toArray(new MultiStatusResponse[responses.size()]); + } + + /** + * Set the response description. + * + * @param responseDescription + */ + public void setResponseDescription(String responseDescription) { + this.responseDescription = responseDescription; + } + + /** + * Returns the response description. + * + * @return responseDescription + */ + public String getResponseDescription() { + return responseDescription; + } + + /** + * Return the Xml representation of this MultiStatus. + * + * @return Xml document + * @param document + */ + public Element toXml(Document document) { + Element multistatus = DomUtil.createElement(document, XML_MULTISTATUS, NAMESPACE); + for (MultiStatusResponse resp : getResponses()) { + multistatus.appendChild(resp.toXml(document)); + } + if (responseDescription != null) { + Element respDesc = DomUtil.createElement(document, XML_RESPONSEDESCRIPTION, NAMESPACE, responseDescription); + multistatus.appendChild(respDesc); + } + return multistatus; + } + + /** + * Build a MultiStatus from the specified xml element. + * + * @param multistatusElement + * @return new MultiStatus instance. + * @throws IllegalArgumentException if the given document is null + * or does not provide the required element. + */ + public static MultiStatus createFromXml(Element multistatusElement) { + if (!DomUtil.matches(multistatusElement, XML_MULTISTATUS, NAMESPACE)) { + throw new IllegalArgumentException("DAV:multistatus element expected."); + } + + MultiStatus multistatus = new MultiStatus(); + + ElementIterator it = DomUtil.getChildren(multistatusElement, XML_RESPONSE, NAMESPACE); + while (it.hasNext()) { + Element respElem = it.nextElement(); + MultiStatusResponse response = MultiStatusResponse.createFromXml(respElem); + multistatus.addResponse(response); + } + + // optional response description on the multistatus element + multistatus.setResponseDescription(DomUtil.getChildText(multistatusElement, XML_RESPONSEDESCRIPTION, NAMESPACE)); + return multistatus; + } +} Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/MultiStatus.java ___________________________________________________________________ Added: svn Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/MultiStatusResponse.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/MultiStatusResponse.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/MultiStatusResponse.java (working copy) @@ -0,0 +1,486 @@ +/* + * 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.webdav; + +import org.apache.jackrabbit.webdav.property.DavProperty; +import org.apache.jackrabbit.webdav.property.DavPropertyName; +import org.apache.jackrabbit.webdav.property.DavPropertyNameSet; +import org.apache.jackrabbit.webdav.property.DavPropertySet; +import org.apache.jackrabbit.webdav.property.DefaultDavProperty; +import org.apache.jackrabbit.webdav.property.PropContainer; +import org.apache.jackrabbit.webdav.xml.DomUtil; +import org.apache.jackrabbit.webdav.xml.ElementIterator; +import org.apache.jackrabbit.webdav.xml.XmlSerializable; +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.Set; + +/** + * MultiStatusResponse represents the DAV:multistatus element defined + * by RFC 2518: + *

+ * <!ELEMENT response (href, ((href*, status)|(propstat+)), responsedescription?) >
+ * <!ELEMENT status (#PCDATA) >
+ * <!ELEMENT propstat (prop, status, responsedescription?) >
+ * <!ELEMENT responsedescription (#PCDATA) >
+ * <!ELEMENT prop ANY >
+ * 
+ */ +public class MultiStatusResponse implements XmlSerializable, DavConstants { + + private static final int TYPE_PROPSTAT = 0; + private static final int TYPE_HREFSTATUS = 1; + + /** + * The type of MultiStatusResponse + */ + private final int type; + + /** + * The content the 'href' element for this response + */ + private final String href; + + /** + * An optional response description. + */ + private final String responseDescription; + + /** + * Type of MultiStatus response: Href + Status + */ + private Status status; + + /** + * Type of MultiStatus response: PropStat Hashmap containing all status + */ + private HashMap statusMap = new HashMap(); + + private MultiStatusResponse(String href, String responseDescription, int type) { + if (!isValidHref(href)) { + throw new IllegalArgumentException("Invalid href ('" + href + "')"); + } + this.href = href; + this.responseDescription = responseDescription; + this.type = type; + } + + /** + * Constructs an WebDAV multistatus response + * + * @param href + * @param status + * @param responseDescription + */ + public MultiStatusResponse(String href, Status status, String responseDescription) { + this(href, responseDescription, TYPE_HREFSTATUS); + if (status == null) { + throw new IllegalArgumentException("Status must not be null in case of a multistatus reponse that consists of href + status only."); + } + this.status = status; + } + + /** + * Constructs an WebDAV multistatus response for a given resource. This + * would be used by COPY, MOVE, DELETE, LOCK that require a multistatus in + * case of error with a resource other than the resource identified in the + * Request-URI.
+ * The response description is set to null. + * + * @param href + * @param statusCode + */ + public MultiStatusResponse(String href, int statusCode) { + this(href, statusCode, null); + } + + /** + * Constructs an WebDAV multistatus response for a given resource. This + * would be used by COPY, MOVE, DELETE, LOCK that require a multistatus in + * case of error with a resource other than the resource identified in the + * Request-URI. + * + * @param href + * @param statusCode + * @param responseDescription + */ + public MultiStatusResponse(String href, int statusCode, String responseDescription) { + this(href, new Status(statusCode), responseDescription); + } + + /** + * Constructs an empty WebDAV multistatus response of type 'PropStat' + */ + public MultiStatusResponse(String href, String responseDescription) { + this(href, responseDescription, TYPE_PROPSTAT); + } + + /** + * Constructs a WebDAV multistatus response and retrieves the resource + * properties according to the given DavPropertyNameSet. + * + * @param resource + * @param propNameSet + */ + public MultiStatusResponse(DavResource resource, DavPropertyNameSet propNameSet) { + this(resource, propNameSet, PROPFIND_BY_PROPERTY); + } + + /** + * Constructs a WebDAV multistatus response and retrieves the resource + * properties according to the given DavPropertyNameSet. It + * adds all known property to the '200' set, while unknown properties are + * added to the '404' set. + *

+ * Note, that the set of property names is ignored in case of a {@link + * #PROPFIND_ALL_PROP} and {@link #PROPFIND_PROPERTY_NAMES} propFindType. + * + * @param resource The resource to retrieve the property from + * @param propNameSet The property name set as obtained from the request + * body. + * @param propFindType any of the following values: {@link + * #PROPFIND_ALL_PROP}, {@link #PROPFIND_BY_PROPERTY}, {@link + * #PROPFIND_PROPERTY_NAMES}, {@link #PROPFIND_ALL_PROP_INCLUDE} + */ + public MultiStatusResponse( + DavResource resource, DavPropertyNameSet propNameSet, + int propFindType) { + this(resource.getHref(), null, TYPE_PROPSTAT); + + if (propFindType == PROPFIND_PROPERTY_NAMES) { + // only property names requested + PropContainer status200 = getPropContainer(DavServletResponse.SC_OK, true); + for (DavPropertyName propName : resource.getPropertyNames()) { + status200.addContent(propName); + } + } else { + // all or a specified set of property and their values requested. + PropContainer status200 = getPropContainer(DavServletResponse.SC_OK, false); + + // Collection of missing property names for 404 responses + Set missing = new HashSet(propNameSet.getContent()); + + // Add requested properties or all non-protected properties, + // or non-protected properties plus requested properties (allprop/include) + if (propFindType == PROPFIND_BY_PROPERTY) { + // add explicitly requested properties (proptected or non-protected) + for (DavPropertyName propName : propNameSet) { + DavProperty prop = resource.getProperty(propName); + if (prop != null) { + status200.addContent(prop); + missing.remove(propName); + } + } + } else { + // add all non-protected properties + for (DavProperty property : resource.getProperties()) { + boolean allDeadPlusRfc4918LiveProperties = + propFindType == PROPFIND_ALL_PROP + || propFindType == PROPFIND_ALL_PROP_INCLUDE; + boolean wasRequested = missing.remove(property.getName()); + + if ((allDeadPlusRfc4918LiveProperties + && !property.isInvisibleInAllprop()) + || wasRequested) { + status200.addContent(property); + } + } + + // try if missing properties specified in the include section + // can be obtained using resource.getProperty + if (propFindType == PROPFIND_ALL_PROP_INCLUDE && !missing.isEmpty()) { + for (DavPropertyName propName : new HashSet(missing)) { + DavProperty prop = resource.getProperty(propName); + if (prop != null) { + status200.addContent(prop); + missing.remove(propName); + } + } + } + } + + if (!missing.isEmpty() && propFindType != PROPFIND_ALL_PROP) { + PropContainer status404 = getPropContainer(DavServletResponse.SC_NOT_FOUND, true); + for (DavPropertyName propName : missing) { + status404.addContent(propName); + } + } + } + } + + /** + * Returns the href + * + * @return href + * @see MultiStatusResponse#getHref() + */ + public String getHref() { + return href; + } + + /** + * @return responseDescription + * @see MultiStatusResponse#getResponseDescription() + */ + public String getResponseDescription() { + return responseDescription; + } + + /** + * Return an array listing all 'status' available is this response object. + * Note, that a the array contains a single element if this + * MultiStatusResponse defines an response consisting of + * href and status elements. + * + * @return + */ + public Status[] getStatus() { + Status[] sts; + if (type == TYPE_PROPSTAT) { + sts = new Status[statusMap.size()]; + Iterator iter = statusMap.keySet().iterator(); + for (int i = 0; iter.hasNext(); i++) { + Integer statusKey = iter.next(); + sts[i] = new Status(statusKey); + } + } else { + sts = new Status[] {status}; + } + return sts; + } + + /** + * @return {@code true} if the response is of type "propstat" (containing information about individual properties) + */ + public boolean isPropStat() { + return this.type == TYPE_PROPSTAT; + } + + /** + * @param document + * @see org.apache.jackrabbit.webdav.xml.XmlSerializable#toXml(org.w3c.dom.Document) + */ + public Element toXml(Document document) { + Element response = DomUtil.createElement(document, XML_RESPONSE, NAMESPACE); + // add '' + response.appendChild(DomUtil.hrefToXml(getHref(), document)); + if (type == TYPE_PROPSTAT) { + // add '' elements + for (Integer statusKey : statusMap.keySet()) { + Status st = new Status(statusKey); + PropContainer propCont = statusMap.get(statusKey); + if (!propCont.isEmpty()) { + Element propstat = DomUtil.createElement(document, XML_PROPSTAT, NAMESPACE); + propstat.appendChild(propCont.toXml(document)); + propstat.appendChild(st.toXml(document)); + response.appendChild(propstat); + } + } + } else { + // add a single '' element + // NOTE: a href+status response cannot be created with 'null' status + response.appendChild(status.toXml(document)); + } + // add the optional '' element + String description = getResponseDescription(); + if (description != null) { + Element desc = DomUtil.createElement(document, XML_RESPONSEDESCRIPTION, NAMESPACE); + DomUtil.setText(desc, description); + response.appendChild(desc); + } + return response; + } + //----------------------------------------------< type specific methods >--- + /** + * Adds a property to this response '200' propstat set. + * + * @param property the property to add + */ + public void add(DavProperty property) { + checkType(TYPE_PROPSTAT); + PropContainer status200 = getPropContainer(DavServletResponse.SC_OK, false); + status200.addContent(property); + } + + /** + * Adds a property name to this response '200' propstat set. + * + * @param propertyName the property name to add + */ + public void add(DavPropertyName propertyName) { + checkType(TYPE_PROPSTAT); + PropContainer status200 = getPropContainer(DavServletResponse.SC_OK, true); + status200.addContent(propertyName); + } + + /** + * Adds a property to this response + * + * @param property the property to add + * @param status the status of the response set to select + */ + public void add(DavProperty property, int status) { + checkType(TYPE_PROPSTAT); + PropContainer propCont = getPropContainer(status, false); + propCont.addContent(property); + } + + /** + * Adds a property name to this response + * + * @param propertyName the property name to add + * @param status the status of the response set to select + */ + public void add(DavPropertyName propertyName, int status) { + checkType(TYPE_PROPSTAT); + PropContainer propCont = getPropContainer(status, true); + propCont.addContent(propertyName); + } + + /** + * @param status + * @return + */ + private PropContainer getPropContainer(int status, boolean forNames) { + PropContainer propContainer = statusMap.get(status); + if (propContainer == null) { + if (forNames) { + propContainer = new DavPropertyNameSet(); + } else { + propContainer = new DavPropertySet(); + } + statusMap.put(status, propContainer); + } + return propContainer; + } + + private void checkType(int type) { + if (this.type != type) { + throw new IllegalStateException("The given MultiStatusResponse is not of the required type."); + } + } + + /** + * Get properties present in this response for the given status code. In + * case this MultiStatusResponse does not represent a 'propstat' response, + * always an empty {@link DavPropertySet} will be returned. + * + * @param status + * @return property set + */ + public DavPropertySet getProperties(int status) { + if (statusMap.containsKey(status)) { + PropContainer mapEntry = statusMap.get(status); + if (mapEntry != null && mapEntry instanceof DavPropertySet) { + return (DavPropertySet) mapEntry; + } + } + return new DavPropertySet(); + } + + /** + * Get property names present in this response for the given status code. In + * case this MultiStatusResponse does not represent a 'propstat' response, + * always an empty {@link DavPropertyNameSet} will be returned. + * + * @param status + * @return property names + */ + public DavPropertyNameSet getPropertyNames(int status) { + if (statusMap.containsKey(status)) { + PropContainer mapEntry = statusMap.get(status); + if (mapEntry != null) { + if (mapEntry instanceof DavPropertySet) { + DavPropertyNameSet set = new DavPropertyNameSet(); + for (DavPropertyName name : ((DavPropertySet) mapEntry).getPropertyNames()) { + set.add(name); + } + return set; + } else { + // is already a DavPropertyNameSet + return (DavPropertyNameSet) mapEntry; + } + } + } + return new DavPropertyNameSet(); + } + + /** + * Build a new response object from the given xml element. + * + * @param responseElement + * @return new MultiStatusResponse instance + * @throws IllegalArgumentException if the specified element is + * null or not a DAV:response element or if the mandatory + * DAV:href child is missing. + */ + public static MultiStatusResponse createFromXml(Element responseElement) { + if (!DomUtil.matches(responseElement, XML_RESPONSE, NAMESPACE)) { + throw new IllegalArgumentException("DAV:response element required."); + } + String href = DomUtil.getChildTextTrim(responseElement, XML_HREF, NAMESPACE); + if (href == null) { + throw new IllegalArgumentException("DAV:response element must contain a DAV:href element expected."); + } + String statusLine = DomUtil.getChildText(responseElement, XML_STATUS, NAMESPACE); + String responseDescription = DomUtil.getChildText(responseElement, XML_RESPONSEDESCRIPTION, NAMESPACE); + + MultiStatusResponse response; + if (statusLine != null) { + Status status = Status.parse(statusLine); + response = new MultiStatusResponse(href, status, responseDescription); + } else { + response = new MultiStatusResponse(href, responseDescription, TYPE_PROPSTAT); + // read propstat elements + ElementIterator it = DomUtil.getChildren(responseElement, XML_PROPSTAT, NAMESPACE); + while (it.hasNext()) { + Element propstat = it.nextElement(); + String propstatus = DomUtil.getChildText(propstat, XML_STATUS, NAMESPACE); + Element prop = DomUtil.getChildElement(propstat, XML_PROP, NAMESPACE); + if (propstatus != null && prop != null) { + int statusCode = Status.parse(propstatus).getStatusCode(); + ElementIterator propIt = DomUtil.getChildren(prop); + while (propIt.hasNext()) { + Element el = propIt.nextElement(); + /* + always build dav property from the given element, since + distinction between prop-names and properties not having + a value is not possible. + retrieval of the set of 'property names' is possible from + the given prop-set by calling DavPropertySet#getPropertyNameSet() + */ + DavProperty property = DefaultDavProperty.createFromXml(el); + response.add(property, statusCode); + } + } + } + } + return response; + } + + /** + * @param href + * @return false if the given href is null or empty string. + */ + private static boolean isValidHref(String href) { + return href != null && !"".equals(href); + } +} Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/MultiStatusResponse.java ___________________________________________________________________ Added: svn Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/Status.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/Status.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/Status.java (working copy) @@ -0,0 +1,123 @@ +/* + * 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.webdav; + +import org.apache.jackrabbit.webdav.xml.DomUtil; +import org.apache.jackrabbit.webdav.xml.XmlSerializable; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +/** + * Status encapsulating the 'status' present in multistatus + * responses. + */ +public class Status implements DavConstants, XmlSerializable{ + + private static Logger log = LoggerFactory.getLogger(Status.class); + + private final String version; + private final int code; + private final String phrase; + + public Status(int code) { + version = "HTTP/1.1"; + this.code = code; + phrase = DavException.getStatusPhrase(code); + } + + public Status(String version, int code, String phrase) { + this.version = version; + this.code = code; + this.phrase = phrase; + } + + public int getStatusCode() { + return code; + } + + /** + * @see XmlSerializable#toXml(Document) + */ + public Element toXml(Document document) { + String statusLine = version + " " + code + " " + phrase; + Element e = DomUtil.createElement(document, XML_STATUS, NAMESPACE); + DomUtil.setText(e, statusLine); + return e; + } + + /** + * Parse the given status line and return a new Status object. + * + * @param statusLine + * @return a new Status + */ + public static Status parse(String statusLine) { + if (statusLine == null) { + throw new IllegalArgumentException("Unable to parse status line from null xml element."); + } + Status status; + + // code copied from org.apache.commons.httpclient.StatusLine + int length = statusLine.length(); + int at = 0; + int start = 0; + try { + while (Character.isWhitespace(statusLine.charAt(at))) { + ++at; + ++start; + } + if (!"HTTP".equals(statusLine.substring(at, at += 4))) { + log.warn("Status-Line '" + statusLine + "' does not start with HTTP"); + } + //handle the HTTP-Version + at = statusLine.indexOf(' ', at); + if (at <= 0) { + log.warn("Unable to parse HTTP-Version from the status line: '" + statusLine + "'"); + } + String version = (statusLine.substring(start, at)).toUpperCase(); + //advance through spaces + while (statusLine.charAt(at) == ' ') { + at++; + } + //handle the Status-Code + int code; + int to = statusLine.indexOf(' ', at); + if (to < 0) { + to = length; + } + try { + code = Integer.parseInt(statusLine.substring(at, to)); + } catch (NumberFormatException e) { + throw new IllegalArgumentException("Unable to parse status code from status line: '" + statusLine + "'"); + } + //handle the Reason-Phrase + String phrase = ""; + at = to + 1; + if (at < length) { + phrase = statusLine.substring(at).trim(); + } + + status = new Status(version, code, phrase); + + } catch (StringIndexOutOfBoundsException e) { + throw new IllegalArgumentException("Status-Line '" + statusLine + "' is not valid"); + } + return status; + } +} \ No newline at end of file Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/Status.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-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/WebdavRequest.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/WebdavRequest.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/WebdavRequest.java (working copy) @@ -0,0 +1,36 @@ +/* + * 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.webdav; + +import org.apache.jackrabbit.webdav.observation.ObservationDavServletRequest; +import org.apache.jackrabbit.webdav.ordering.OrderingDavServletRequest; +import org.apache.jackrabbit.webdav.transaction.TransactionDavServletRequest; +import org.apache.jackrabbit.webdav.version.DeltaVServletRequest; +import org.apache.jackrabbit.webdav.bind.BindServletRequest; + +/** + * The empty WebdavRequest interface collects the functionality + * defined by {@link org.apache.jackrabbit.webdav.DavServletRequest} encapsulating + * the core Webdav specification (RFC 2518) as well as the various extensions + * used for observation and transaction support, ordering of collections, search + * and versioning. + */ +public interface WebdavRequest extends DavServletRequest, + ObservationDavServletRequest, OrderingDavServletRequest, + TransactionDavServletRequest, DeltaVServletRequest, + BindServletRequest { +} Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/WebdavRequest.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/WebdavRequestContext.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/WebdavRequestContext.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/WebdavRequestContext.java (working copy) @@ -0,0 +1,30 @@ +/* + * 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.webdav; + +/** + * Interface providing the minimum WebDAV request information associated with the current thread of execution. + */ +public interface WebdavRequestContext { + + /** + * Return the current {@link WebdavRequest} instance associated with the current thread of execution. + * @return the current {@link WebdavRequest} instance associated with the current thread of execution + */ + public WebdavRequest getRequest(); + +} Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/WebdavRequestContext.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/WebdavRequestImpl.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/WebdavRequestImpl.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/WebdavRequestImpl.java (working copy) @@ -0,0 +1,1312 @@ +/* + * 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.webdav; + +import java.io.BufferedInputStream; +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.UnsupportedEncodingException; +import java.net.URI; +import java.net.URISyntaxException; +import java.security.Principal; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Enumeration; +import java.util.Iterator; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.zip.GZIPInputStream; +import java.util.zip.InflaterInputStream; + +import javax.servlet.AsyncContext; +import javax.servlet.DispatcherType; +import javax.servlet.ReadListener; +import javax.servlet.RequestDispatcher; +import javax.servlet.ServletContext; +import javax.servlet.ServletException; +import javax.servlet.ServletInputStream; +import javax.servlet.ServletRequest; +import javax.servlet.ServletResponse; +import javax.servlet.http.Cookie; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.servlet.http.HttpSession; +import javax.servlet.http.HttpUpgradeHandler; +import javax.servlet.http.Part; +import javax.xml.parsers.ParserConfigurationException; + +import org.apache.jackrabbit.webdav.bind.BindInfo; +import org.apache.jackrabbit.webdav.bind.RebindInfo; +import org.apache.jackrabbit.webdav.bind.UnbindInfo; +import org.apache.jackrabbit.webdav.header.CodedUrlHeader; +import org.apache.jackrabbit.webdav.header.DepthHeader; +import org.apache.jackrabbit.webdav.header.IfHeader; +import org.apache.jackrabbit.webdav.header.LabelHeader; +import org.apache.jackrabbit.webdav.header.OverwriteHeader; +import org.apache.jackrabbit.webdav.header.PollTimeoutHeader; +import org.apache.jackrabbit.webdav.header.TimeoutHeader; +import org.apache.jackrabbit.webdav.lock.LockInfo; +import org.apache.jackrabbit.webdav.lock.Scope; +import org.apache.jackrabbit.webdav.lock.Type; +import org.apache.jackrabbit.webdav.observation.ObservationConstants; +import org.apache.jackrabbit.webdav.observation.SubscriptionInfo; +import org.apache.jackrabbit.webdav.ordering.OrderPatch; +import org.apache.jackrabbit.webdav.ordering.OrderingConstants; +import org.apache.jackrabbit.webdav.ordering.Position; +import org.apache.jackrabbit.webdav.property.DavProperty; +import org.apache.jackrabbit.webdav.property.DavPropertyName; +import org.apache.jackrabbit.webdav.property.DavPropertyNameSet; +import org.apache.jackrabbit.webdav.property.DavPropertySet; +import org.apache.jackrabbit.webdav.property.DefaultDavProperty; +import org.apache.jackrabbit.webdav.property.PropEntry; +import org.apache.jackrabbit.webdav.server.AbstractWebdavServlet; +import org.apache.jackrabbit.webdav.transaction.TransactionConstants; +import org.apache.jackrabbit.webdav.transaction.TransactionInfo; +import org.apache.jackrabbit.webdav.version.LabelInfo; +import org.apache.jackrabbit.webdav.version.MergeInfo; +import org.apache.jackrabbit.webdav.version.OptionsInfo; +import org.apache.jackrabbit.webdav.version.UpdateInfo; +import org.apache.jackrabbit.webdav.version.report.ReportInfo; +import org.apache.jackrabbit.webdav.xml.DomUtil; +import org.apache.jackrabbit.webdav.xml.ElementIterator; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.xml.sax.SAXException; + +/** + * WebdavRequestImpl... + */ +public class WebdavRequestImpl implements WebdavRequest, DavConstants, ContentCodingAwareRequest { + + private static Logger log = LoggerFactory.getLogger(WebdavRequestImpl.class); + + private final HttpServletRequest httpRequest; + private final DavLocatorFactory factory; + private final IfHeader ifHeader; + private final String hrefPrefix; + + private DavSession session; + + private int propfindType = PROPFIND_ALL_PROP; + private DavPropertyNameSet propfindProps; + private DavPropertySet proppatchSet; + private List proppatchList; + + /** + * Creates a new DavServletRequest with the given parameters. + */ + public WebdavRequestImpl(HttpServletRequest httpRequest, DavLocatorFactory factory) { + this(httpRequest, factory, true); + } + + /** + * Creates a new DavServletRequest with the given parameters. + * + * @param httpRequest + * @param factory + * @param createAbsoluteURI defines if we must create a absolute URI. if false a absolute path will be created + */ + public WebdavRequestImpl(HttpServletRequest httpRequest, DavLocatorFactory factory, boolean createAbsoluteURI) { + this.httpRequest = httpRequest; + this.factory = factory; + this.ifHeader = new IfHeader(httpRequest); + + String host = getHeader("Host"); + String scheme = getScheme(); + String uriPrefix = scheme + "://" + host + getContextPath(); + this.hrefPrefix = createAbsoluteURI ? uriPrefix : getContextPath(); + } + + /** + * Sets the session field and adds all lock tokens present with either the + * Lock-Token header or the If header to the given session object. + * + * @param session + * @see DavServletRequest#setDavSession(DavSession) + */ + public void setDavSession(DavSession session) { + this.session = session; + // set lock-tokens from header to the current session + if (session != null) { + String lt = getLockToken(); + if (lt != null) { + session.addLockToken(lt); + } + // add all token present in the the If header to the session as well. + Iterator it = ifHeader.getAllTokens(); + while (it.hasNext()) { + String ifHeaderToken = it.next(); + session.addLockToken(ifHeaderToken); + } + } + } + + /** + * @see DavServletRequest#getDavSession() + */ + public DavSession getDavSession() { + return session; + } + + /** + * Return a DavResourceLocator representing the request handle. + * + * @return locator of the requested resource + * @see DavServletRequest#getRequestLocator() + */ + public DavResourceLocator getRequestLocator() { + String path = getRequestURI(); + String ctx = getContextPath(); + if (path.startsWith(ctx)) { + path = path.substring(ctx.length()); + } + return factory.createResourceLocator(hrefPrefix, path); + } + + /** + * Parse the destination header field and return the path of the destination + * resource. + * + * @return path of the destination resource. + * @throws DavException + * @see #HEADER_DESTINATION + * @see DavServletRequest#getDestinationLocator + */ + public DavResourceLocator getDestinationLocator() throws DavException { + return getHrefLocator(httpRequest.getHeader(HEADER_DESTINATION), true); + } + + private DavResourceLocator getHrefLocator(String href, boolean forDestination) throws DavException { + String ref = href; + if (ref != null) { + //href should be a Simple-ref production as defined in RFC4918, so it is either an absolute URI + //or an absolute path + try { + URI uri = new URI(ref).normalize(); // normalize path (see JCR-3174) + String auth = uri.getAuthority(); + ref = uri.getRawPath(); + if (auth == null) { + //verify that href is an absolute path + if (ref.startsWith("//") || !ref.startsWith("/")) { + log.warn("expected absolute path but found " + ref); + throw new DavException(DavServletResponse.SC_BAD_REQUEST); + } + } else if (!auth.equals(httpRequest.getHeader("Host"))) { + //this looks like an unsupported cross-server operation, but of course a reverse-proxy + //might have rewritten the Host header. Since we can't find out, we have to reject anyway. + //Better use absolute paths in DAV:href elements! + throw new DavException(DavServletResponse.SC_FORBIDDEN); + } + } catch (URISyntaxException e) { + log.warn("malformed uri: " + href, e); + throw new DavException(DavServletResponse.SC_BAD_REQUEST); + } + // cut off the context path + String contextPath = httpRequest.getContextPath(); + if (ref.startsWith(contextPath)) { + ref = ref.substring(contextPath.length()); + } else { + //absolute path has to start with context path + throw new DavException(DavServletResponse.SC_FORBIDDEN); + } + } + if (factory instanceof AbstractLocatorFactory) { + return ((AbstractLocatorFactory)factory).createResourceLocator(hrefPrefix, ref, forDestination); + } + else { + return factory.createResourceLocator(hrefPrefix, ref); + } + } + + /** + * Parse a href and return the path of the resource. + * + * @return path of the resource identified by the href. + * @see org.apache.jackrabbit.webdav.bind.BindServletRequest#getHrefLocator + */ + public DavResourceLocator getHrefLocator(String href) throws DavException { + return getHrefLocator(href, false); + } + + /** + * Returns the path of the member resource of the request resource which is identified by the segment parameter. + * + * @return path of internal member resource. + */ + public DavResourceLocator getMemberLocator(String segment) { + String path = (this.getRequestLocator().getHref(true) + segment).substring(hrefPrefix.length()); + return factory.createResourceLocator(hrefPrefix, path); + } + + /** + * Return true if the overwrite header does not inhibit overwriting. + * + * @return true if the overwrite header requests 'overwriting' + * @see #HEADER_OVERWRITE + * @see DavServletRequest#isOverwrite() + */ + public boolean isOverwrite() { + return new OverwriteHeader(httpRequest).isOverwrite(); + } + + /** + * @see DavServletRequest#getDepth(int) + */ + public int getDepth(int defaultValue) { + return DepthHeader.parse(httpRequest, defaultValue).getDepth(); + } + + /** + * @see DavServletRequest#getDepth() + */ + public int getDepth() { + return getDepth(DEPTH_INFINITY); + } + + /** + * Parse the Timeout header and return a long representing the value. + * {@link #UNDEFINED_TIMEOUT} is used as default value if no header + * is available or if the parsing fails. + * + * @return milliseconds indicating length of the timeout. + * @see DavServletRequest#getTimeout() + * @see TimeoutHeader#parse(javax.servlet.http.HttpServletRequest, long) + */ + public long getTimeout() { + return TimeoutHeader.parse(httpRequest, UNDEFINED_TIMEOUT).getTimeout(); + } + + /** + * Retrieve the lock token from the 'Lock-Token' header. + * + * @return String representing the lock token sent in the Lock-Token header. + * @throws IllegalArgumentException If the value has not the correct format. + * @see #HEADER_LOCK_TOKEN + * @see DavServletRequest#getLockToken() + */ + public String getLockToken() { + return CodedUrlHeader.parse(httpRequest, HEADER_LOCK_TOKEN).getCodedUrl(); + } + + /** + * @see DavServletRequest#getRequestDocument() + */ + public Document getRequestDocument() throws DavException { + Document requestDocument = null; + /* + Don't attempt to parse the body if the content length header is 0. + NOTE: a value of -1 indicates that the length is unknown, thus we have + to parse the body. Note that http1.1 request using chunked transfer + coding will therefore not be detected here. + */ + if (httpRequest.getContentLength() == 0) { + return requestDocument; + } + // try to parse the request body + try { + InputStream in = getDecodedInputStream(); + if (in != null) { + // use a buffered input stream to find out whether there actually + // is a request body + InputStream bin = new BufferedInputStream(in); + bin.mark(1); + boolean isEmpty = -1 == bin.read(); + bin.reset(); + if (!isEmpty) { + requestDocument = DomUtil.parseDocument(bin); + } + } + } catch (IOException e) { + if (log.isDebugEnabled()) { + log.debug("Unable to build an XML Document from the request body: " + e.getMessage()); + } + Throwable cause = e.getCause(); + throw (cause instanceof DavException) ? (DavException) cause : new DavException(DavServletResponse.SC_BAD_REQUEST); + } catch (ParserConfigurationException e) { + if (log.isDebugEnabled()) { + log.debug("Unable to build an XML Document from the request body: " + e.getMessage()); + } + throw new DavException(DavServletResponse.SC_INTERNAL_SERVER_ERROR); + } catch (SAXException e) { + if (log.isDebugEnabled()) { + log.debug("Unable to build an XML Document from the request body: " + e.getMessage()); + } + throw new DavException(DavServletResponse.SC_BAD_REQUEST); + } + return requestDocument; + } + + /** + * Returns the type of PROPFIND as indicated by the request body. + * + * @return type of the PROPFIND request. Default value is {@link #PROPFIND_ALL_PROP allprops} + * @see DavServletRequest#getPropFindType() + */ + public int getPropFindType() throws DavException { + if (propfindProps == null) { + parsePropFindRequest(); + } + return propfindType; + } + + /** + * Returns the set of properties requested by the PROPFIND body or an + * empty set if the {@link #getPropFindType type} is either 'allprop' or + * 'propname'. + * + * @return set of properties requested by the PROPFIND body or an empty set. + * @see DavServletRequest#getPropFindProperties() + */ + public DavPropertyNameSet getPropFindProperties() throws DavException { + if (propfindProps == null) { + parsePropFindRequest(); + } + return propfindProps; + } + + private InputStream getDecodedInputStream() throws IOException { + List contentCodings = getRequestContentCodings(); + int len = contentCodings.size(); + + log.trace("content codings: " + contentCodings); + InputStream result = httpRequest.getInputStream(); + + for (int i = 1; i <= len; i++) { + String s = contentCodings.get(len - i); + log.trace("decoding: " + s); + if ("gzip".equals(s)) { + result = new GZIPInputStream(result); + } else if ("deflate".equals(s)) { + result = new InflaterInputStream(result); + } else { + String message = "Unsupported content coding: " + s; + try { + Element condition = DomUtil.createElement(DomUtil.createDocument(), PRECONDITION_SUPPORTED); + throw new IOException( + new DavException(HttpServletResponse.SC_UNSUPPORTED_MEDIA_TYPE, message, null, condition)); + } catch (ParserConfigurationException ex) { + throw new IOException(message); + } + } + } + + return result; + } + + private List requestContentCodings = null; + + @Override + public List getRequestContentCodings() { + if (requestContentCodings == null) { + requestContentCodings = AbstractWebdavServlet.getContentCodings(httpRequest); + } + + return requestContentCodings; + } + + @Override + public String getAcceptableCodings() { + return "deflate, gzip"; + } + + /** + * Parse the propfind request body in order to determine the type of the propfind + * and the set of requested property. + * NOTE: An empty 'propfind' request body will be treated as request for all + * property according to the specification. + */ + private void parsePropFindRequest() throws DavException { + propfindProps = new DavPropertyNameSet(); + Document requestDocument = getRequestDocument(); + // propfind httpRequest with empty body >> retrieve all property + if (requestDocument == null) { + return; + } + + // propfind httpRequest with invalid body + Element root = requestDocument.getDocumentElement(); + if (!XML_PROPFIND.equals(root.getLocalName())) { + log.info("PropFind-Request has no tag."); + throw new DavException(DavServletResponse.SC_BAD_REQUEST, "PropFind-Request has no tag."); + } + + DavPropertyNameSet include = null; + + ElementIterator it = DomUtil.getChildren(root); + int propfindTypeFound = 0; + + while (it.hasNext()) { + Element child = it.nextElement(); + String nodeName = child.getLocalName(); + if (NAMESPACE.getURI().equals(child.getNamespaceURI())) { + if (XML_PROP.equals(nodeName)) { + propfindType = PROPFIND_BY_PROPERTY; + propfindProps = new DavPropertyNameSet(child); + propfindTypeFound += 1; + } + else if (XML_PROPNAME.equals(nodeName)) { + propfindType = PROPFIND_PROPERTY_NAMES; + propfindTypeFound += 1; + } + else if (XML_ALLPROP.equals(nodeName)) { + propfindType = PROPFIND_ALL_PROP; + propfindTypeFound += 1; + } + else if (XML_INCLUDE.equals(nodeName)) { + include = new DavPropertyNameSet(); + ElementIterator pit = DomUtil.getChildren(child); + while (pit.hasNext()) { + include.add(DavPropertyName.createFromXml(pit.nextElement())); + } + } + } + } + + if (propfindTypeFound > 1) { + log.info("Multiple top-level propfind instructions"); + throw new DavException(DavServletResponse.SC_BAD_REQUEST, "Multiple top-level propfind instructions"); + } + + if (include != null) { + if (propfindType == PROPFIND_ALL_PROP) { + // special case: allprop with include extension + propfindType = PROPFIND_ALL_PROP_INCLUDE; + propfindProps = include; + } + else { + throw new DavException(DavServletResponse.SC_BAD_REQUEST, " goes only with "); + + } + } + } + + /** + * Return a {@link List} of property change operations. Each entry + * is either of type {@link DavPropertyName}, indicating a <remove> + * operation, or of type {@link DavProperty}, indicating a <set> + * operation. Note that ordering is significant here. + * + * @return the list of change operations entries in the PROPPATCH request body + * @see DavServletRequest#getPropPatchChangeList() + */ + public List getPropPatchChangeList() throws DavException { + if (proppatchList == null) { + parsePropPatchRequest(); + } + return proppatchList; + } + + /** + * Parse the PROPPATCH request body. + */ + private void parsePropPatchRequest() throws DavException { + + proppatchSet = new DavPropertySet(); + proppatchList = new ArrayList(); + + Document requestDocument = getRequestDocument(); + + if (requestDocument == null) { + throw new DavException(DavServletResponse.SC_BAD_REQUEST, "Invalid request body."); + } + + Element root = requestDocument.getDocumentElement(); + if (!DomUtil.matches(root, XML_PROPERTYUPDATE, NAMESPACE)) { + log.warn("PropPatch-Request has no tag."); + throw new DavException(DavServletResponse.SC_BAD_REQUEST, "PropPatch-Request has no tag."); + } + + ElementIterator it = DomUtil.getChildren(root); + while (it.hasNext()) { + Element el = it.nextElement(); + if (DomUtil.matches(el, XML_SET, NAMESPACE)) { + Element propEl = DomUtil.getChildElement(el, XML_PROP, NAMESPACE); + if (propEl != null) { + ElementIterator properties = DomUtil.getChildren(propEl); + while (properties.hasNext()) { + DavProperty davProp = DefaultDavProperty.createFromXml(properties.nextElement()); + proppatchSet.add(davProp); + proppatchList.add(davProp); + } + } + } else if (DomUtil.matches(el, XML_REMOVE, NAMESPACE)) { + Element propEl = DomUtil.getChildElement(el, XML_PROP, NAMESPACE); + if (propEl != null) { + ElementIterator properties = DomUtil.getChildren(propEl); + while (properties.hasNext()) { + DavProperty davProp = DefaultDavProperty.createFromXml(properties.nextElement()); + proppatchSet.add(davProp); + proppatchList.add(davProp.getName()); + } + } + } else { + log.debug("Unknown element in DAV:propertyupdate: " + el.getNodeName()); + // unknown child elements are ignored + } + } + } + + /** + * {@link LockInfo} object encapsulating the information passed with a LOCK + * request if the LOCK request body was valid. If the request body is + * missing a 'refresh lock' request is assumed. The {@link LockInfo} + * then only provides timeout and isDeep property and returns true on + * {@link org.apache.jackrabbit.webdav.lock.LockInfo#isRefreshLock()} + * + * @return lock info object or null if an error occurred while + * parsing the request body. + * @throws DavException throws a 400 (Bad Request) DavException if a request + * body is present but does not start with a DAV:lockinfo element. Note however, + * that a non-existing request body is a valid request used to refresh + * an existing lock. + * @see DavServletRequest#getLockInfo() + */ + public LockInfo getLockInfo() throws DavException { + LockInfo lockInfo; + boolean isDeep = (getDepth(DEPTH_INFINITY) == DEPTH_INFINITY); + Document requestDocument = getRequestDocument(); + // check if XML request body is present. It SHOULD have one for + // 'create Lock' request and missing for a 'refresh Lock' request + if (requestDocument != null) { + Element root = requestDocument.getDocumentElement(); + if (root.getLocalName().equals(XML_LOCKINFO)) { + lockInfo = new LockInfo(root, getTimeout(), isDeep); + } else { + log.debug("Lock request body must start with a DAV:lockinfo element."); + throw new DavException(DavServletResponse.SC_BAD_REQUEST); + } + } else { + lockInfo = new LockInfo(null, getTimeout(), isDeep); + } + return lockInfo; + } + + /** + * Test if the if header matches the given resource. The comparison is + * made with the {@link DavResource#getHref() + * resource href} and the token returned from an exclusive write lock present on + * the resource.
+ * NOTE: If either the If header or the resource is null or if + * the resource has not applied an exclusive write lock the preconditions are met. + * If in contrast the lock applied to the given resource returns a + * null lock token (e.g. for security reasons) or a lock token + * that does not match, the method will return false. + * + * @param resource Webdav resources being operated on + * @return true if the test is successful and the preconditions for the + * request processing are fulfilled. + * @see DavServletRequest#matchesIfHeader(DavResource) + * @see IfHeader#matches(String, String, String) + * @see DavResource#hasLock(org.apache.jackrabbit.webdav.lock.Type, org.apache.jackrabbit.webdav.lock.Scope) + * @see org.apache.jackrabbit.webdav.lock.ActiveLock#getToken() + */ + public boolean matchesIfHeader(DavResource resource) { + // no ifheader, no resource or no write lock on resource + // >> preconditions ok so far + if (!ifHeader.hasValue() || resource == null || !resource.hasLock(Type.WRITE, Scope.EXCLUSIVE)) { + return true; + } + + boolean isMatching = false; + String lockToken = resource.getLock(Type.WRITE, Scope.EXCLUSIVE).getToken(); + if (lockToken != null) { + isMatching = matchesIfHeader(resource.getHref(), lockToken, getStrongETag(resource)); + } // else: lockToken is null >> the if-header will not match. + + return isMatching; + } + + /** + * @see DavServletRequest#matchesIfHeader(String, String, String) + * @see IfHeader#matches(String, String, String) + */ + public boolean matchesIfHeader(String href, String token, String eTag) { + return ifHeader.matches(href, token, isStrongETag(eTag) ? eTag : ""); + } + + /** + * Returns the strong etag present on the given resource or empty string + * if either the resource does not provide any etag or if the etag is weak. + * + * @param resource + * @return strong etag or empty string. + */ + private String getStrongETag(DavResource resource) { + DavProperty prop = resource.getProperty(DavPropertyName.GETETAG); + if (prop != null && prop.getValue() != null) { + String etag = prop.getValue().toString(); + if (isStrongETag(etag)) { + return etag; + } + } + // no strong etag available + return ""; + } + + /** + * Returns true if the given string represents a strong etag. + * + * @param eTag + * @return true, if its a strong etag + */ + private static boolean isStrongETag(String eTag) { + return eTag != null && eTag.length() > 0 && !eTag.startsWith("W\\"); + } + + //-----------------------------< TransactionDavServletRequest Interface >--- + /** + * @see org.apache.jackrabbit.webdav.transaction.TransactionDavServletRequest#getTransactionId() + */ + public String getTransactionId() { + return CodedUrlHeader.parse(httpRequest, TransactionConstants.HEADER_TRANSACTIONID).getCodedUrl(); + } + + /** + * @see org.apache.jackrabbit.webdav.transaction.TransactionDavServletRequest#getTransactionInfo() + */ + public TransactionInfo getTransactionInfo() throws DavException { + Document requestDocument = getRequestDocument(); + if (requestDocument != null) { + return new TransactionInfo(requestDocument.getDocumentElement()); + } + return null; + } + + //-----------------------------< ObservationDavServletRequest Interface >--- + /** + * @see org.apache.jackrabbit.webdav.observation.ObservationDavServletRequest#getSubscriptionId() + */ + public String getSubscriptionId() { + return CodedUrlHeader.parse(httpRequest, ObservationConstants.HEADER_SUBSCRIPTIONID).getCodedUrl(); + } + + /** + * @see org.apache.jackrabbit.webdav.observation.ObservationDavServletRequest#getPollTimeout() + */ + public long getPollTimeout() { + return PollTimeoutHeader.parseHeader(httpRequest, 0).getTimeout(); + } + + /** + * @see org.apache.jackrabbit.webdav.observation.ObservationDavServletRequest#getSubscriptionInfo() + */ + public SubscriptionInfo getSubscriptionInfo() throws DavException { + Document requestDocument = getRequestDocument(); + if (requestDocument != null) { + Element root = requestDocument.getDocumentElement(); + if (ObservationConstants.XML_SUBSCRIPTIONINFO.equals(root.getLocalName())) { + int depth = getDepth(DEPTH_0); + return new SubscriptionInfo(root, getTimeout(), depth == DEPTH_INFINITY); + } + } + return null; + } + + //--------------------------------< OrderingDavServletRequest Interface >--- + /** + * @see org.apache.jackrabbit.webdav.ordering.OrderingDavServletRequest#getOrderingType() + */ + public String getOrderingType() { + return getHeader(OrderingConstants.HEADER_ORDERING_TYPE); + } + + /** + * @see org.apache.jackrabbit.webdav.ordering.OrderingDavServletRequest#getPosition() + */ + public Position getPosition() { + String h = getHeader(OrderingConstants.HEADER_POSITION); + Position pos = null; + if (h != null) { + String[] typeNSegment = h.split("\\s"); + if (typeNSegment.length == 2) { + try { + pos = new Position(typeNSegment[0], typeNSegment[1]); + } catch (IllegalArgumentException e) { + log.error("Cannot parse Position header: " + e.getMessage()); + } + } + } + return pos; + } + + /** + * @return OrderPatch object representing the orderpatch request + * body or null if the + * @see org.apache.jackrabbit.webdav.ordering.OrderingDavServletRequest#getOrderPatch() + */ + public OrderPatch getOrderPatch() throws DavException { + OrderPatch op = null; + Document requestDocument = getRequestDocument(); + if (requestDocument != null) { + Element root = requestDocument.getDocumentElement(); + op = OrderPatch.createFromXml(root); + } else { + log.error("Error while building xml document from ORDERPATH request body."); + } + return op; + } + + //-------------------------------------< DeltaVServletRequest interface >--- + /** + * @see org.apache.jackrabbit.webdav.version.DeltaVServletRequest#getLabel() + */ + public String getLabel() { + LabelHeader label = LabelHeader.parse(this); + if (label != null) { + return label.getLabel(); + } + return null; + } + + /** + * @see org.apache.jackrabbit.webdav.version.DeltaVServletRequest#getLabelInfo() + */ + public LabelInfo getLabelInfo() throws DavException { + LabelInfo lInfo = null; + Document requestDocument = getRequestDocument(); + if (requestDocument != null) { + Element root = requestDocument.getDocumentElement(); + int depth = getDepth(DEPTH_0); + lInfo = new LabelInfo(root, depth); + } + return lInfo; + } + + /** + * @see org.apache.jackrabbit.webdav.version.DeltaVServletRequest#getMergeInfo() + */ + public MergeInfo getMergeInfo() throws DavException { + MergeInfo mInfo = null; + Document requestDocument = getRequestDocument(); + if (requestDocument != null) { + mInfo = new MergeInfo(requestDocument.getDocumentElement()); + } + return mInfo; + } + + /** + * @see org.apache.jackrabbit.webdav.version.DeltaVServletRequest#getUpdateInfo() + */ + public UpdateInfo getUpdateInfo() throws DavException { + UpdateInfo uInfo = null; + Document requestDocument = getRequestDocument(); + if (requestDocument != null) { + uInfo = new UpdateInfo(requestDocument.getDocumentElement()); + } + return uInfo; + } + + /** + * @see org.apache.jackrabbit.webdav.version.DeltaVServletRequest#getReportInfo() + */ + public ReportInfo getReportInfo() throws DavException { + ReportInfo rInfo = null; + Document requestDocument = getRequestDocument(); + if (requestDocument != null) { + rInfo = new ReportInfo(requestDocument.getDocumentElement(), getDepth(DEPTH_0)); + } + return rInfo; + } + + /** + * @see org.apache.jackrabbit.webdav.version.DeltaVServletRequest#getOptionsInfo() + */ + public OptionsInfo getOptionsInfo() throws DavException { + OptionsInfo info = null; + Document requestDocument = getRequestDocument(); + if (requestDocument != null) { + info = OptionsInfo.createFromXml(requestDocument.getDocumentElement()); + } + return info; + } + + /** + * @see org.apache.jackrabbit.webdav.bind.BindServletRequest#getRebindInfo() + */ + public RebindInfo getRebindInfo() throws DavException { + RebindInfo info = null; + Document requestDocument = getRequestDocument(); + if (requestDocument != null) { + info = RebindInfo.createFromXml(requestDocument.getDocumentElement()); + } + return info; + } + + /** + * @see org.apache.jackrabbit.webdav.bind.BindServletRequest#getUnbindInfo() + */ + public UnbindInfo getUnbindInfo() throws DavException { + UnbindInfo info = null; + Document requestDocument = getRequestDocument(); + if (requestDocument != null) { + info = UnbindInfo.createFromXml(requestDocument.getDocumentElement()); + } + return info; + } + + /** + * @see org.apache.jackrabbit.webdav.bind.BindServletRequest#getBindInfo() + */ + public BindInfo getBindInfo() throws DavException { + BindInfo info = null; + Document requestDocument = getRequestDocument(); + if (requestDocument != null) { + info = BindInfo.createFromXml(requestDocument.getDocumentElement()); + } + return info; + } + + //---------------------------------------< HttpServletRequest interface >--- + + @Override + public String getAuthType() { + return httpRequest.getAuthType(); + } + + @Override + public Cookie[] getCookies() { + return httpRequest.getCookies(); + } + + @Override + public long getDateHeader(String s) { + return httpRequest.getDateHeader(s); + } + + @Override + public String getHeader(String s) { + return httpRequest.getHeader(s); + } + + @Override + public Enumeration getHeaders(String s) { + return httpRequest.getHeaders(s); + } + + @Override + public Enumeration getHeaderNames() { + return httpRequest.getHeaderNames(); + } + + @Override + public int getIntHeader(String s) { + return httpRequest.getIntHeader(s); + } + + @Override + public String getMethod() { + return httpRequest.getMethod(); + } + + @Override + public String getPathInfo() { + return httpRequest.getPathInfo(); + } + + @Override + public String getPathTranslated() { + return httpRequest.getPathTranslated(); + } + + @Override + public String getContextPath() { + return httpRequest.getContextPath(); + } + + @Override + public String getQueryString() { + return httpRequest.getQueryString(); + } + + @Override + public String getRemoteUser() { + return httpRequest.getRemoteUser(); + } + + @Override + public boolean isUserInRole(String s) { + return httpRequest.isUserInRole(s); + } + + @Override + public Principal getUserPrincipal() { + return httpRequest.getUserPrincipal(); + } + + @Override + public String getRequestedSessionId() { + return httpRequest.getRequestedSessionId(); + } + + @Override + public String getRequestURI() { + return httpRequest.getRequestURI(); + } + + @Override + public StringBuffer getRequestURL() { + return httpRequest.getRequestURL(); + } + + @Override + public String getServletPath() { + return httpRequest.getServletPath(); + } + + @Override + public HttpSession getSession(boolean b) { + return httpRequest.getSession(b); + } + + @Override + public HttpSession getSession() { + return httpRequest.getSession(); + } + + @Override + public boolean isRequestedSessionIdValid() { + return httpRequest.isRequestedSessionIdValid(); + } + + @Override + public boolean isRequestedSessionIdFromCookie() { + return httpRequest.isRequestedSessionIdFromCookie(); + } + + @Override + public boolean isRequestedSessionIdFromURL() { + return httpRequest.isRequestedSessionIdFromURL(); + } + + @Override + public boolean isRequestedSessionIdFromUrl() { + return httpRequest.isRequestedSessionIdFromUrl(); + } + + @Override + public Object getAttribute(String s) { + return httpRequest.getAttribute(s); + } + + @Override + public Enumeration getAttributeNames() { + return httpRequest.getAttributeNames(); + } + + @Override + public String getCharacterEncoding() { + return httpRequest.getCharacterEncoding(); + } + + @Override + public void setCharacterEncoding(String s) throws UnsupportedEncodingException { + httpRequest.setCharacterEncoding(s); + } + + @Override + public int getContentLength() { + return httpRequest.getContentLength(); + } + + @Override + public String getContentType() { + return httpRequest.getContentType(); + } + + @Override + public ServletInputStream getInputStream() throws IOException { + return new MyServletInputStream(getDecodedInputStream()); + } + + @Override + public String getParameter(String s) { + return httpRequest.getParameter(s); + } + + @Override + public Enumeration getParameterNames() { + return httpRequest.getParameterNames(); + } + + @Override + public String[] getParameterValues(String s) { + return httpRequest.getParameterValues(s); + } + + @Override + public Map getParameterMap() { + return httpRequest.getParameterMap(); + } + + @Override + public String getProtocol() { + return httpRequest.getProtocol(); + } + + @Override + public String getScheme() { + return httpRequest.getScheme(); + } + + @Override + public String getServerName() { + return httpRequest.getServerName(); + } + + @Override + public int getServerPort() { + return httpRequest.getServerPort(); + } + + @Override + public BufferedReader getReader() throws IOException { + return httpRequest.getReader(); + } + + @Override + public String getRemoteAddr() { + return httpRequest.getRemoteAddr(); + } + + @Override + public String getRemoteHost() { + return httpRequest.getRemoteHost(); + } + + @Override + public void setAttribute(String s, Object o) { + httpRequest.setAttribute(s, o); + } + + @Override + public void removeAttribute(String s) { + httpRequest.removeAttribute(s); + } + + @Override + public Locale getLocale() { + return httpRequest.getLocale(); + } + + @Override + public Enumeration getLocales() { + return httpRequest.getLocales(); + } + + @Override + public boolean isSecure() { + return httpRequest.isSecure(); + } + + @Override + public RequestDispatcher getRequestDispatcher(String s) { + return httpRequest.getRequestDispatcher(s); + } + + @Override + public String getRealPath(String s) { + return httpRequest.getRealPath(s); + } + + @Override + public int getRemotePort() { + return httpRequest.getRemotePort(); + } + + @Override + public String getLocalName() { + return httpRequest.getLocalName(); + } + + @Override + public String getLocalAddr() { + return httpRequest.getLocalAddr(); + } + + @Override + public int getLocalPort() { + return httpRequest.getLocalPort(); + } + + @Override + public String changeSessionId() { + return httpRequest.changeSessionId(); + } + + @Override + public boolean authenticate(HttpServletResponse response) throws IOException, ServletException { + return httpRequest.authenticate(response); + } + + @Override + public void login(String username, String password) throws ServletException { + httpRequest.login(username, password); + } + + @Override + public void logout() throws ServletException { + httpRequest.logout(); + } + + @Override + public Collection getParts() throws IOException, ServletException { + return httpRequest.getParts(); + } + + @Override + public Part getPart(String name) throws IOException, ServletException { + return httpRequest.getPart(name); + } + + @Override + public T upgrade(Class handlerClass) throws IOException, ServletException { + return httpRequest.upgrade(handlerClass); + } + + @Override + public long getContentLengthLong() { + return httpRequest.getContentLengthLong(); + } + + @Override + public ServletContext getServletContext() { + return httpRequest.getServletContext(); + } + + @Override + public AsyncContext startAsync() throws IllegalStateException { + return httpRequest.startAsync(); + } + + @Override + public AsyncContext startAsync(ServletRequest servletRequest, ServletResponse servletResponse) throws IllegalStateException { + return httpRequest.startAsync(servletRequest, servletResponse); + } + + @Override + public boolean isAsyncStarted() { + return httpRequest.isAsyncStarted(); + } + + @Override + public boolean isAsyncSupported() { + return httpRequest.isAsyncSupported(); + } + + @Override + public AsyncContext getAsyncContext() { + return httpRequest.getAsyncContext(); + } + + @Override + public DispatcherType getDispatcherType() { + return httpRequest.getDispatcherType(); + } + + private static class MyServletInputStream extends ServletInputStream { + + private final InputStream delegate; + + public MyServletInputStream(InputStream delegate) { + this.delegate = delegate; + } + + @Override + public int available() throws IOException { + return delegate.available(); + } + + @Override + public void close() throws IOException { + delegate.close(); + } + + @Override + public boolean equals(Object other) { + return delegate.equals(other); + } + + @Override + public int hashCode() { + return delegate.hashCode(); + } + + @Override + public void mark(int readlimit) { + delegate.mark(readlimit); + } + + @Override + public boolean markSupported() { + return delegate.markSupported(); + } + + @Override + public int read() throws IOException { + return delegate.read(); + } + + @Override + public int read(byte[] b, int off, int len) throws IOException { + return delegate.read(b, off, len); + } + + @Override + public int read(byte[] b) throws IOException { + return delegate.read(b); + } + + @Override + public int readLine(byte[] b, int off, int len) throws IOException { + throw new UnsupportedOperationException(); + } + + @Override + public void reset() throws IOException { + delegate.reset(); + } + + @Override + public long skip(long n) throws IOException { + return delegate.skip(n); + } + + @Override + public String toString() { + return delegate.toString(); + } + + @Override + public boolean isFinished() { + throw new UnsupportedOperationException(); + } + + @Override + public boolean isReady() { + throw new UnsupportedOperationException(); + } + + @Override + public void setReadListener(ReadListener readListener) { + throw new UnsupportedOperationException(); + } + } +} Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/WebdavRequestImpl.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/WebdavResponse.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/WebdavResponse.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/WebdavResponse.java (working copy) @@ -0,0 +1,42 @@ +/* + * 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.webdav; + +import java.util.Map; +import java.util.function.Supplier; + +import org.apache.jackrabbit.webdav.observation.ObservationDavServletResponse; + +/** + * The empty WebdavResponse interface collects the functionality + * defined by {@link org.apache.jackrabbit.webdav.DavServletResponse} + * encapsulating for the core WebDAV specification (RFC 2518) as well as the + * various extensions used for observation and transaction support, ordering of + * collections, search and versioning. + */ +public interface WebdavResponse extends DavServletResponse, ObservationDavServletResponse { + + // can be removed when we move to Servlet API 4.0 + public default void setTrailerFields(Supplier> supplier) { + // nop + } + + // can be removed when we move to Servlet API 4.0 + public default Supplier> getTrailerFields() { + return null; + } +} \ No newline at end of file Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/WebdavResponse.java ___________________________________________________________________ Added: svn Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/WebdavResponseImpl.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/WebdavResponseImpl.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/WebdavResponseImpl.java (working copy) @@ -0,0 +1,407 @@ +/* + * 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.webdav; + +import org.apache.jackrabbit.webdav.header.CodedUrlHeader; +import org.apache.jackrabbit.webdav.header.Header; +import org.apache.jackrabbit.webdav.lock.ActiveLock; +import org.apache.jackrabbit.webdav.lock.LockDiscovery; +import org.apache.jackrabbit.webdav.observation.EventDiscovery; +import org.apache.jackrabbit.webdav.observation.ObservationConstants; +import org.apache.jackrabbit.webdav.observation.Subscription; +import org.apache.jackrabbit.webdav.observation.SubscriptionDiscovery; +import org.apache.jackrabbit.webdav.property.DavPropertySet; +import org.apache.jackrabbit.webdav.xml.DomUtil; +import org.apache.jackrabbit.webdav.xml.XmlSerializable; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.w3c.dom.Document; +import org.xml.sax.SAXException; + +import javax.servlet.ServletOutputStream; +import javax.servlet.http.Cookie; +import javax.servlet.http.HttpServletResponse; +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.transform.TransformerException; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.io.PrintWriter; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.function.Supplier; +import java.util.zip.GZIPOutputStream; + +/** + * WebdavResponseImpl implements the WebdavResponse interface. + */ +public class WebdavResponseImpl implements WebdavResponse { + + private static Logger log = LoggerFactory.getLogger(WebdavResponseImpl.class); + + private HttpServletResponse httpResponse; + + /** + * Create a new WebdavResponse + * + * @param httpResponse + */ + public WebdavResponseImpl(HttpServletResponse httpResponse) { + this(httpResponse, false); + } + + /** + * Create a new WebdavResponse + * + * @param httpResponse + * @param noCache + */ + public WebdavResponseImpl(HttpServletResponse httpResponse, boolean noCache) { + this.httpResponse = httpResponse; + if (noCache) { + /* set cache control headers */ + addHeader("Pragma", "No-cache"); // http1.0 + addHeader("Cache-Control", "no-cache"); // http1.1 + } + } + + /** + * If the specifid exception provides an error condition an Xml response body + * is sent providing more detailed information about the error. Otherwise only + * the error code and status phrase is sent back. + * + * @param exception + * @throws IOException + * @see DavServletResponse#sendError(org.apache.jackrabbit.webdav.DavException) + * @see #sendError(int, String) + * @see #sendXmlResponse(XmlSerializable, int) + */ + public void sendError(DavException exception) throws IOException { + if (!exception.hasErrorCondition()) { + httpResponse.sendError(exception.getErrorCode(), exception.getStatusPhrase()); + } else { + sendXmlResponse(exception, exception.getErrorCode()); + } + } + + @Override + public void sendMultiStatus(MultiStatus multistatus) throws IOException { + sendXmlResponse(multistatus, SC_MULTI_STATUS); + } + + @Override + public void sendMultiStatus(MultiStatus multistatus, List acceptableContentCodings) throws IOException { + sendXmlResponse(multistatus, SC_MULTI_STATUS, acceptableContentCodings); + } + + /** + * Send response body for a lock request that was intended to refresh one + * or several locks. + * + * @param locks + * @throws java.io.IOException + * @see DavServletResponse#sendRefreshLockResponse(org.apache.jackrabbit.webdav.lock.ActiveLock[]) + */ + public void sendRefreshLockResponse(ActiveLock[] locks) throws IOException { + DavPropertySet propSet = new DavPropertySet(); + propSet.add(new LockDiscovery(locks)); + sendXmlResponse(propSet, SC_OK); + } + + @Override + public void sendXmlResponse(XmlSerializable serializable, int status) throws IOException { + sendXmlResponse(serializable, status, Collections.emptyList()); + } + + @Override + public void sendXmlResponse(XmlSerializable serializable, int status, List acceptableContentCodings) throws IOException { + httpResponse.setStatus(status); + + if (serializable != null) { + try { + ByteArrayOutputStream out = new ByteArrayOutputStream(); + Document doc = DomUtil.createDocument(); + doc.appendChild(serializable.toXml(doc)); + DomUtil.transformDocument(doc, out); + out.close(); + + httpResponse.setContentType("text/xml; charset=UTF-8"); + + // use GZIP iff accepted by client and content size >= 256 octets + if (out.size() < 256 || !acceptableContentCodings.contains("gzip")) { + httpResponse.setContentLength(out.size()); + out.writeTo(httpResponse.getOutputStream()); + } else { + httpResponse.setHeader("Content-Encoding", "gzip"); + try (OutputStream os = new GZIPOutputStream(httpResponse.getOutputStream())) { + out.writeTo(os); + } + } + } catch (ParserConfigurationException e) { + log.error(e.getMessage()); + throw new IOException(e.getMessage()); + } catch (TransformerException e) { + log.error(e.getMessage()); + throw new IOException(e.getMessage()); + } catch (SAXException e) { + log.error(e.getMessage()); + throw new IOException(e.getMessage()); + } + } + } + + //----------------------------< ObservationDavServletResponse Interface >--- + /** + * + * @param subscription + * @throws IOException + * @see org.apache.jackrabbit.webdav.observation.ObservationDavServletResponse#sendSubscriptionResponse(org.apache.jackrabbit.webdav.observation.Subscription) + */ + public void sendSubscriptionResponse(Subscription subscription) throws IOException { + String id = subscription.getSubscriptionId(); + if (id != null) { + Header h = new CodedUrlHeader(ObservationConstants.HEADER_SUBSCRIPTIONID, id); + httpResponse.setHeader(h.getHeaderName(), h.getHeaderValue()); + } + DavPropertySet propSet = new DavPropertySet(); + propSet.add(new SubscriptionDiscovery(subscription)); + sendXmlResponse(propSet, SC_OK); + } + + /** + * + * @param eventDiscovery + * @throws IOException + * @see org.apache.jackrabbit.webdav.observation.ObservationDavServletResponse#sendPollResponse(org.apache.jackrabbit.webdav.observation.EventDiscovery) + */ + public void sendPollResponse(EventDiscovery eventDiscovery) throws IOException { + sendXmlResponse(eventDiscovery, SC_OK); + } + + //--------------------------------------< HttpServletResponse interface >--- + + @Override + public void addCookie(Cookie cookie) { + httpResponse.addCookie(cookie); + } + + @Override + public boolean containsHeader(String s) { + return httpResponse.containsHeader(s); + } + + @Override + public String encodeURL(String s) { + return httpResponse.encodeRedirectURL(s); + } + + @Override + public String encodeRedirectURL(String s) { + return httpResponse.encodeRedirectURL(s); + } + + @Override + public String encodeUrl(String s) { + return httpResponse.encodeUrl(s); + } + + @Override + public String encodeRedirectUrl(String s) { + return httpResponse.encodeRedirectURL(s); + } + + @Override + public void sendError(int i, String s) throws IOException { + httpResponse.sendError(i, s); + } + + @Override + public void sendError(int i) throws IOException { + httpResponse.sendError(i); + } + + @Override + public void sendRedirect(String s) throws IOException { + httpResponse.sendRedirect(s); + } + + @Override + public void setDateHeader(String s, long l) { + httpResponse.setDateHeader(s, l); + } + + @Override + public void addDateHeader(String s, long l) { + httpResponse.addDateHeader(s, l); + } + + @Override + public void setHeader(String s, String s1) { + httpResponse.setHeader(s, s1); + } + + @Override + public void addHeader(String s, String s1) { + httpResponse.addHeader(s, s1); + } + + @Override + public void setIntHeader(String s, int i) { + httpResponse.setIntHeader(s, i); + } + + @Override + public void addIntHeader(String s, int i) { + httpResponse.addIntHeader(s, i); + } + + @Override + public void setStatus(int i) { + httpResponse.setStatus(i); + } + + @Override + public void setStatus(int i, String s) { + httpResponse.setStatus(i, s); + } + + @Override + public String getCharacterEncoding() { + return httpResponse.getCharacterEncoding(); + } + + @Override + public ServletOutputStream getOutputStream() throws IOException { + return httpResponse.getOutputStream(); + } + + @Override + public PrintWriter getWriter() throws IOException { + return httpResponse.getWriter(); + } + + @Override + public void setContentLength(int i) { + httpResponse.setContentLength(i); + } + + @Override + public void setContentType(String s) { + httpResponse.setContentType(s); + } + + @Override + public void setBufferSize(int i) { + httpResponse.setBufferSize(i); + } + + @Override + public int getBufferSize() { + return httpResponse.getBufferSize(); + } + + @Override + public void flushBuffer() throws IOException { + httpResponse.flushBuffer(); + } + + @Override + public void resetBuffer() { + httpResponse.resetBuffer(); + } + + @Override + public boolean isCommitted() { + return httpResponse.isCommitted(); + } + + @Override + public void reset() { + httpResponse.reset(); + } + + @Override + public void setLocale(Locale locale) { + httpResponse.setLocale(locale); + } + + @Override + public Locale getLocale() { + return httpResponse.getLocale(); + } + + @Override + public String getContentType() { + return httpResponse.getContentType(); + } + + @Override + public void setCharacterEncoding(String charset) { + httpResponse.setCharacterEncoding(charset); + } + + @Override + public int getStatus() { + return httpResponse.getStatus(); + } + + @Override + public String getHeader(String name) { + return httpResponse.getHeader(name); + } + + @Override + public Collection getHeaders(String name) { + return httpResponse.getHeaders(name); + } + + @Override + public Collection getHeaderNames() { + return httpResponse.getHeaderNames(); + } + + @Override + public void setContentLengthLong(long len) { + httpResponse.setContentLengthLong(len); + } + + // Servlet 4.0 API support for trailers, for now using reflection + + public void setTrailerFields(Supplier> supplier) { + try { + java.lang.reflect.Method stf = httpResponse.getClass().getDeclaredMethod("setTrailerFields", Supplier.class); + stf.invoke(httpResponse, supplier); + } catch (IllegalAccessException | java.lang.reflect.InvocationTargetException | NoSuchMethodException + | SecurityException ex) { + throw new UnsupportedOperationException("no servlet 4.0 support on: " + httpResponse.getClass(), ex); + } + } + + @SuppressWarnings("unchecked") + public Supplier> getTrailerFields() { + try { + java.lang.reflect.Method stf = httpResponse.getClass().getDeclaredMethod("getTrailerFields"); + return (Supplier>) stf.invoke(httpResponse); + } catch (IllegalAccessException | java.lang.reflect.InvocationTargetException | NoSuchMethodException + | SecurityException ex) { + throw new UnsupportedOperationException("no servlet 4.0 support on: " + httpResponse.getClass(), ex); + } + } +} Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/WebdavResponseImpl.java ___________________________________________________________________ Added: svn Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/bind/BindConstants.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/bind/BindConstants.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/bind/BindConstants.java (working copy) @@ -0,0 +1,52 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.jackrabbit.webdav.bind; + +import org.apache.jackrabbit.webdav.xml.Namespace; +import org.apache.jackrabbit.webdav.DavConstants; +import org.apache.jackrabbit.webdav.property.DavPropertyName; + +/** + * BindConstants provide constants for request and response + * headers, Xml elements and property names defined by + * the BIND specification. + */ +public interface BindConstants { + + /** + * The namespace + */ + public static final Namespace NAMESPACE = DavConstants.NAMESPACE; + + /** + * local names of XML elements used in the request bodies of the methods BIND, REBIND and UNBIND. + */ + public static final String XML_BIND = "bind"; + public static final String XML_REBIND = "rebind"; + public static final String XML_UNBIND = "unbind"; + public static final String XML_SEGMENT = "segment"; + public static final String XML_HREF = "href"; + public static final String XML_PARENT = "parent"; + + public static final String METHODS = "BIND, REBIND, UNBIND"; + + /* + * Webdav properties defined by the BIND specification. + */ + public static final DavPropertyName RESOURCEID = DavPropertyName.create("resource-id"); + public static final DavPropertyName PARENTSET = DavPropertyName.create("parent-set"); +} Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/bind/BindConstants.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/bind/BindInfo.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/bind/BindInfo.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/bind/BindInfo.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.webdav.bind; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.apache.jackrabbit.webdav.DavServletResponse; +import org.apache.jackrabbit.webdav.DavException; +import org.apache.jackrabbit.webdav.xml.DomUtil; +import org.apache.jackrabbit.webdav.xml.ElementIterator; +import org.apache.jackrabbit.webdav.xml.XmlSerializable; +import org.w3c.dom.Element; +import org.w3c.dom.Document; + +public class BindInfo implements XmlSerializable { + + private static Logger log = LoggerFactory.getLogger(BindInfo.class); + + private String segment; + private String href; + + public BindInfo(String href, String segment) { + this.href = href; + this.segment = segment; + } + + public String getHref() { + return this.href; + } + + public String getSegment() { + return this.segment; + } + + /** + * Build an BindInfo object from the root element present + * in the request body. + * + * @param root the root element of the request body + * @return a BindInfo object containing segment and href + * @throws org.apache.jackrabbit.webdav.DavException if the BIND request is malformed + */ + public static BindInfo createFromXml(Element root) throws DavException { + if (!DomUtil.matches(root, BindConstants.XML_BIND, BindConstants.NAMESPACE)) { + log.warn("DAV:bind element expected"); + throw new DavException(DavServletResponse.SC_BAD_REQUEST); + } + String href = null; + String segment = null; + ElementIterator it = DomUtil.getChildren(root); + while (it.hasNext()) { + Element elt = it.nextElement(); + if (DomUtil.matches(elt, BindConstants.XML_SEGMENT, BindConstants.NAMESPACE)) { + if (segment == null) { + segment = DomUtil.getText(elt); + } else { + log.warn("unexpected multiple occurrence of DAV:segment element"); + throw new DavException(DavServletResponse.SC_BAD_REQUEST); + } + } else if (DomUtil.matches(elt, BindConstants.XML_HREF, BindConstants.NAMESPACE)) { + if (href == null) { + href = DomUtil.getText(elt); + } else { + log.warn("unexpected multiple occurrence of DAV:href element"); + throw new DavException(DavServletResponse.SC_BAD_REQUEST); + } + } else { + log.warn("unexpected element " + elt.getLocalName()); + throw new DavException(DavServletResponse.SC_BAD_REQUEST); + } + } + if (href == null) { + log.warn("DAV:href element expected"); + throw new DavException(DavServletResponse.SC_BAD_REQUEST); + } + if (segment == null) { + log.warn("DAV:segment element expected"); + throw new DavException(DavServletResponse.SC_BAD_REQUEST); + } + return new BindInfo(href, segment); + } + + /** + * @see org.apache.jackrabbit.webdav.xml.XmlSerializable#toXml(org.w3c.dom.Document) + */ + public Element toXml(Document document) { + Element bindElt = DomUtil.createElement(document, BindConstants.XML_BIND, BindConstants.NAMESPACE); + Element hrefElt = DomUtil.createElement(document, BindConstants.XML_HREF, BindConstants.NAMESPACE, this.href); + Element segElt = DomUtil.createElement(document, BindConstants.XML_SEGMENT, BindConstants.NAMESPACE, this.segment); + bindElt.appendChild(hrefElt); + bindElt.appendChild(segElt); + return bindElt; + } +} Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/bind/BindInfo.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/bind/BindServletRequest.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/bind/BindServletRequest.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/bind/BindServletRequest.java (working copy) @@ -0,0 +1,65 @@ +/* + * 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.webdav.bind; + +import org.apache.jackrabbit.webdav.DavException; +import org.apache.jackrabbit.webdav.DavResourceLocator; + +/** + * BindServletRequest provides extension useful for functionality + * related to BIND specification. + */ +public interface BindServletRequest { + + /** + * Returns the {@link RebindInfo} present with the request + * + * @return {@link RebindInfo} object + * @throws org.apache.jackrabbit.webdav.DavException in case of an invalid or missing request body + */ + public RebindInfo getRebindInfo() throws DavException; + + /** + * Returns the {@link UnbindInfo} present with the request + * + * @return {@link UnbindInfo} object + * @throws org.apache.jackrabbit.webdav.DavException in case of an invalid or missing request body + */ + public UnbindInfo getUnbindInfo() throws DavException; + + /** + * Returns the {@link BindInfo} present with the request + * + * @return {@link BindInfo} object + * @throws org.apache.jackrabbit.webdav.DavException in case of an invalid or missing request body + */ + public BindInfo getBindInfo() throws DavException; + + /** + * Parses a href and returns the path of the resource. + * + * @return path of the resource identified by the href. + */ + public DavResourceLocator getHrefLocator(String href) throws DavException; + + /** + * Returns the path of the member resource of the request resource which is identified by the segment parameter. + * + * @return path of internal member resource. + */ + public DavResourceLocator getMemberLocator(String segment); +} Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/bind/BindServletRequest.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/bind/BindableResource.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/bind/BindableResource.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/bind/BindableResource.java (working copy) @@ -0,0 +1,50 @@ +/* + * 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.webdav.bind; + +import java.util.Set; + +import org.apache.jackrabbit.webdav.DavException; +import org.apache.jackrabbit.webdav.DavResource; + +public interface BindableResource { + + /** + * Will add a new binding to the given collection referencing this resource. + * + * @param collection the collection to create the new binding in. + * @param newBinding the new binding + */ + public void bind(DavResource collection, DavResource newBinding) throws DavException; + + /** + * Will rebind the resource to the given collection. By definition, this is + * an atomic move operation. + * + * @param collection the collection to create the new binding in. + * @param newBinding the new binding + */ + public void rebind(DavResource collection, DavResource newBinding) throws DavException; + + /** + * Will retrieve a collection of parent elements of the bindable resource + * representing the parent set. + * + * @return newBinding the new binding + */ + public Set getParentElements(); +} Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/bind/BindableResource.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/bind/ParentElement.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/bind/ParentElement.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/bind/ParentElement.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.webdav.bind; + +import org.apache.jackrabbit.webdav.xml.XmlSerializable; +import org.apache.jackrabbit.webdav.xml.DomUtil; +import org.apache.jackrabbit.webdav.xml.ElementIterator; +import org.apache.jackrabbit.webdav.DavException; +import org.apache.jackrabbit.webdav.DavServletResponse; +import org.w3c.dom.Element; +import org.w3c.dom.Document; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * ParentElement wraps en element of the parent set of a resource. A java.util.Set of + * ParentElement objects may serve as the value object of the ParentSet DavProperty. + */ +public class ParentElement implements XmlSerializable { + + private static Logger log = LoggerFactory.getLogger(ParentElement.class); + + private final String href; + private final String segment; + + public ParentElement(String href, String segment) { + this.href = href; + this.segment = segment; + } + + public String getHref() { + return this.href; + } + + public String getSegment() { + return this.segment; + } + + /** + * Build an ParentElement object from an XML element DAV:parent + * + * @param root the DAV:parent element + * @return a ParentElement object + * @throws org.apache.jackrabbit.webdav.DavException if the DAV:parent element is malformed + */ + public static ParentElement createFromXml(Element root) throws DavException { + if (!DomUtil.matches(root, BindConstants.XML_PARENT, BindConstants.NAMESPACE)) { + log.warn("DAV:paret element expected"); + throw new DavException(DavServletResponse.SC_BAD_REQUEST); + } + String href = null; + String segment = null; + ElementIterator it = DomUtil.getChildren(root); + while (it.hasNext()) { + Element elt = it.nextElement(); + if (DomUtil.matches(elt, BindConstants.XML_SEGMENT, BindConstants.NAMESPACE)) { + if (segment == null) { + segment = DomUtil.getText(elt); + } else { + log.warn("unexpected multiple occurrence of DAV:segment element"); + throw new DavException(DavServletResponse.SC_BAD_REQUEST); + } + } else if (DomUtil.matches(elt, BindConstants.XML_HREF, BindConstants.NAMESPACE)) { + if (href == null) { + href = DomUtil.getText(elt); + } else { + log.warn("unexpected multiple occurrence of DAV:href element"); + throw new DavException(DavServletResponse.SC_BAD_REQUEST); + } + } else { + log.warn("unexpected element " + elt.getLocalName()); + throw new DavException(DavServletResponse.SC_BAD_REQUEST); + } + } + if (href == null) { + log.warn("DAV:href element expected"); + throw new DavException(DavServletResponse.SC_BAD_REQUEST); + } + if (segment == null) { + log.warn("DAV:segment element expected"); + throw new DavException(DavServletResponse.SC_BAD_REQUEST); + } + return new ParentElement(href, segment); + } + + /** + * @see org.apache.jackrabbit.webdav.xml.XmlSerializable#toXml(org.w3c.dom.Document) + */ + public Element toXml(Document document) { + Element parentElt = DomUtil.createElement(document, BindConstants.XML_PARENT, BindConstants.NAMESPACE); + Element hrefElt = DomUtil.createElement(document, BindConstants.XML_HREF, BindConstants.NAMESPACE, this.href); + Element segElt = DomUtil.createElement(document, BindConstants.XML_SEGMENT, BindConstants.NAMESPACE, this.segment); + parentElt.appendChild(hrefElt); + parentElt.appendChild(segElt); + return parentElt; + } +} Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/bind/ParentElement.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/bind/ParentSet.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/bind/ParentSet.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/bind/ParentSet.java (working copy) @@ -0,0 +1,45 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.jackrabbit.webdav.bind; + +import org.apache.jackrabbit.webdav.property.AbstractDavProperty; + +import java.util.Collection; + +/** + * ParentSet represents a DAV:parent-set property. + */ +public class ParentSet extends AbstractDavProperty> { + + private final Collection parents; + + /** + * Creates a new ParentSet from a collection of ParentElement objects. + * @param parents + */ + public ParentSet(Collection parents) { + super(BindConstants.PARENTSET, true); + this.parents = parents; + } + + /** + * @see org.apache.jackrabbit.webdav.property.AbstractDavProperty#getValue() + */ + public Collection getValue() { + return this.parents; + } +} Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/bind/ParentSet.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/bind/RebindInfo.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/bind/RebindInfo.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/bind/RebindInfo.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.webdav.bind; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.apache.jackrabbit.webdav.DavServletResponse; +import org.apache.jackrabbit.webdav.DavException; +import org.apache.jackrabbit.webdav.xml.DomUtil; +import org.apache.jackrabbit.webdav.xml.ElementIterator; +import org.apache.jackrabbit.webdav.xml.XmlSerializable; +import org.w3c.dom.Element; +import org.w3c.dom.Document; + +public class RebindInfo implements XmlSerializable { + + private static Logger log = LoggerFactory.getLogger(RebindInfo.class); + + private String segment; + private String href; + + public RebindInfo(String href, String segment) { + this.href = href; + this.segment = segment; + } + + public String getHref() { + return this.href; + } + + public String getSegment() { + return this.segment; + } + + /** + * Build an RebindInfo object from the root element present + * in the request body. + * + * @param root the root element of the request body + * @return a RebindInfo object containing segment and href + * @throws org.apache.jackrabbit.webdav.DavException if the REBIND request is malformed + */ + public static RebindInfo createFromXml(Element root) throws DavException { + if (!DomUtil.matches(root, BindConstants.XML_REBIND, BindConstants.NAMESPACE)) { + log.warn("DAV:rebind element expected"); + throw new DavException(DavServletResponse.SC_BAD_REQUEST); + } + String href = null; + String segment = null; + ElementIterator it = DomUtil.getChildren(root); + while (it.hasNext()) { + Element elt = it.nextElement(); + if (DomUtil.matches(elt, BindConstants.XML_SEGMENT, BindConstants.NAMESPACE)) { + if (segment == null) { + segment = DomUtil.getText(elt); + } else { + log.warn("unexpected multiple occurrence of DAV:segment element"); + throw new DavException(DavServletResponse.SC_BAD_REQUEST); + } + } else if (DomUtil.matches(elt, BindConstants.XML_HREF, BindConstants.NAMESPACE)) { + if (href == null) { + href = DomUtil.getText(elt); + } else { + log.warn("unexpected multiple occurrence of DAV:href element"); + throw new DavException(DavServletResponse.SC_BAD_REQUEST); + } + } else { + log.warn("unexpected element " + elt.getLocalName()); + throw new DavException(DavServletResponse.SC_BAD_REQUEST); + } + } + if (href == null) { + log.warn("DAV:href element expected"); + throw new DavException(DavServletResponse.SC_BAD_REQUEST); + } + if (segment == null) { + log.warn("DAV:segment element expected"); + throw new DavException(DavServletResponse.SC_BAD_REQUEST); + } + return new RebindInfo(href, segment); + } + + /** + * @see org.apache.jackrabbit.webdav.xml.XmlSerializable#toXml(org.w3c.dom.Document) + */ + public Element toXml(Document document) { + Element rebindElt = DomUtil.createElement(document, BindConstants.XML_REBIND, BindConstants.NAMESPACE); + Element hrefElt = DomUtil.createElement(document, BindConstants.XML_HREF, BindConstants.NAMESPACE, this.href); + Element segElt = DomUtil.createElement(document, BindConstants.XML_SEGMENT, BindConstants.NAMESPACE, this.segment); + rebindElt.appendChild(hrefElt); + rebindElt.appendChild(segElt); + return rebindElt; + } +} Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/bind/RebindInfo.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/bind/UnbindInfo.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/bind/UnbindInfo.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/bind/UnbindInfo.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.webdav.bind; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.apache.jackrabbit.webdav.DavServletResponse; +import org.apache.jackrabbit.webdav.DavException; +import org.apache.jackrabbit.webdav.xml.DomUtil; +import org.apache.jackrabbit.webdav.xml.ElementIterator; +import org.apache.jackrabbit.webdav.xml.XmlSerializable; +import org.w3c.dom.Element; +import org.w3c.dom.Document; + +public class UnbindInfo implements XmlSerializable { + + private static Logger log = LoggerFactory.getLogger(UnbindInfo.class); + + private String segment; + + private UnbindInfo() {} + + public UnbindInfo(String segment) { + this.segment = segment; + } + + public String getSegment() { + return this.segment; + } + + /** + * Build an UnbindInfo object from the root element present + * in the request body. + * + * @param root the root element of the request body + * @return a UnbindInfo object containing a segment identifier + * @throws org.apache.jackrabbit.webdav.DavException if the UNBIND request is malformed + */ + public static UnbindInfo createFromXml(Element root) throws DavException { + if (!DomUtil.matches(root, BindConstants.XML_UNBIND, BindConstants.NAMESPACE)) { + log.warn("DAV:unbind element expected"); + throw new DavException(DavServletResponse.SC_BAD_REQUEST); + } + String segment = null; + ElementIterator it = DomUtil.getChildren(root); + while (it.hasNext()) { + Element elt = it.nextElement(); + if (DomUtil.matches(elt, BindConstants.XML_SEGMENT, BindConstants.NAMESPACE)) { + if (segment == null) { + segment = DomUtil.getText(elt); + } else { + log.warn("unexpected multiple occurrence of DAV:segment element"); + throw new DavException(DavServletResponse.SC_BAD_REQUEST); + } + } else { + log.warn("unexpected element " + elt.getLocalName()); + throw new DavException(DavServletResponse.SC_BAD_REQUEST); + } + } + if (segment == null) { + log.warn("DAV:segment element expected"); + throw new DavException(DavServletResponse.SC_BAD_REQUEST); + } + return new UnbindInfo(segment); + } + + /** + * @see org.apache.jackrabbit.webdav.xml.XmlSerializable#toXml(org.w3c.dom.Document) + */ + public Element toXml(Document document) { + Element unbindElt = DomUtil.createElement(document, BindConstants.XML_UNBIND, BindConstants.NAMESPACE); + Element segElt = DomUtil.createElement(document, BindConstants.XML_SEGMENT, BindConstants.NAMESPACE, this.segment); + unbindElt.appendChild(segElt); + return unbindElt; + } +} Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/bind/UnbindInfo.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/bind/package-info.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/bind/package-info.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/bind/package-info.java (working copy) @@ -0,0 +1,18 @@ +/* + * 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. + */ +@org.osgi.annotation.versioning.Version("1.0.0") +package org.apache.jackrabbit.webdav.bind; Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/bind/package-info.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/BaseDavRequest.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/BaseDavRequest.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/BaseDavRequest.java (working copy) @@ -0,0 +1,219 @@ +/* + * 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.webdav.client.methods; + +import java.io.IOException; +import java.io.InputStream; +import java.net.URI; + +import javax.xml.parsers.ParserConfigurationException; + +import org.apache.http.HttpEntity; +import org.apache.http.HttpResponse; +import org.apache.http.StatusLine; +import org.apache.http.client.methods.HttpEntityEnclosingRequestBase; +import org.apache.jackrabbit.webdav.DavConstants; +import org.apache.jackrabbit.webdav.DavException; +import org.apache.jackrabbit.webdav.MultiStatus; +import org.apache.jackrabbit.webdav.lock.LockDiscovery; +import org.apache.jackrabbit.webdav.observation.EventDiscovery; +import org.apache.jackrabbit.webdav.observation.ObservationConstants; +import org.apache.jackrabbit.webdav.observation.Subscription; +import org.apache.jackrabbit.webdav.observation.SubscriptionDiscovery; +import org.apache.jackrabbit.webdav.xml.DomUtil; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.xml.sax.SAXException; + +/** + * Base class for HTTP request classes defined in this package. + */ +public abstract class BaseDavRequest extends HttpEntityEnclosingRequestBase { + + private static Logger log = LoggerFactory.getLogger(BaseDavRequest.class); + + public BaseDavRequest(URI uri) { + super(); + super.setURI(uri); + } + + /** + * Gets a {@link Document} representing the response body. + * @return document or {@code null} for null entity + * @throws IOException in case of I/O or XMP pasting problems + */ + public Document getResponseBodyAsDocument(HttpEntity entity) throws IOException { + + if (entity == null) { + return null; + } else { + // read response and try to build a xml document + InputStream in = entity.getContent(); + try { + return DomUtil.parseDocument(in); + } catch (ParserConfigurationException ex) { + throw new IOException("XML parser configuration error", ex); + } catch (SAXException ex) { + throw new IOException("XML parsing error", ex); + } finally { + in.close(); + } + } + } + + /** + * Return response body as {@link MultiStatus} object. + * @throws IllegalStateException when response does not represent a {@link MultiStatus} + * @throws DavException for failures in obtaining/parsing the response body + */ + public MultiStatus getResponseBodyAsMultiStatus(HttpResponse response) throws DavException { + try { + Document doc = getResponseBodyAsDocument(response.getEntity()); + if (doc == null) { + throw new DavException(response.getStatusLine().getStatusCode(), "no response body"); + } + return MultiStatus.createFromXml(doc.getDocumentElement()); + } catch (IOException ex) { + throw new DavException(response.getStatusLine().getStatusCode(), ex); + } + } + + /** + * Return response body as {@link LockDiscovery} object. + * @throws IllegalStateException when response does not represent a {@link LockDiscovery} + * @throws DavException for failures in obtaining/parsing the response body + */ + public LockDiscovery getResponseBodyAsLockDiscovery(HttpResponse response) throws DavException { + try { + Document doc = getResponseBodyAsDocument(response.getEntity()); + if (doc == null) { + throw new DavException(response.getStatusLine().getStatusCode(), "no response body"); + } + Element root = doc.getDocumentElement(); + + if (!DomUtil.matches(root, DavConstants.XML_PROP, DavConstants.NAMESPACE) + && DomUtil.hasChildElement(root, DavConstants.PROPERTY_LOCKDISCOVERY, DavConstants.NAMESPACE)) { + throw new DavException(response.getStatusLine().getStatusCode(), + "Missing DAV:prop response body in LOCK response."); + } + + Element lde = DomUtil.getChildElement(root, DavConstants.PROPERTY_LOCKDISCOVERY, DavConstants.NAMESPACE); + if (!DomUtil.hasChildElement(lde, DavConstants.XML_ACTIVELOCK, DavConstants.NAMESPACE)) { + throw new DavException(response.getStatusLine().getStatusCode(), + "The DAV:lockdiscovery must contain a least a single DAV:activelock in response to a successful LOCK request."); + } + + return LockDiscovery.createFromXml(lde); + } catch (IOException ex) { + throw new DavException(response.getStatusLine().getStatusCode(), ex); + } + } + + /** + * Return response body as {@link SubscriptionDiscovery} object. + * @throws IllegalStateException when response does not represent a {@link SubscriptionDiscovery} + * @throws DavException for failures in obtaining/parsing the response body + */ + public SubscriptionDiscovery getResponseBodyAsSubscriptionDiscovery(HttpResponse response) throws DavException { + try { + Document doc = getResponseBodyAsDocument(response.getEntity()); + if (doc == null) { + throw new DavException(response.getStatusLine().getStatusCode(), "no response body"); + } + Element root = doc.getDocumentElement(); + + if (!DomUtil.matches(root, DavConstants.XML_PROP, DavConstants.NAMESPACE) + && DomUtil.hasChildElement(root, ObservationConstants.SUBSCRIPTIONDISCOVERY.getName(), + ObservationConstants.SUBSCRIPTIONDISCOVERY.getNamespace())) { + throw new DavException(response.getStatusLine().getStatusCode(), + "Missing DAV:prop response body in SUBSCRIBE response."); + } + + Element sde = DomUtil.getChildElement(root, ObservationConstants.SUBSCRIPTIONDISCOVERY.getName(), + ObservationConstants.SUBSCRIPTIONDISCOVERY.getNamespace()); + SubscriptionDiscovery sd = SubscriptionDiscovery.createFromXml(sde); + if (((Subscription[]) sd.getValue()).length > 0) { + return sd; + } else { + throw new DavException(response.getStatusLine().getStatusCode(), + "Missing 'subscription' elements in SUBSCRIBE response body. At least a single subscription must be present if SUBSCRIBE was successful."); + } + } catch (IOException ex) { + throw new DavException(response.getStatusLine().getStatusCode(), ex); + } + } + + /** + * Return response body as {@link EventDiscovery} object. + * @throws IllegalStateException when response does not represent a {@link EventDiscovery} + * @throws DavException for failures in obtaining/parsing the response body + */ + public EventDiscovery getResponseBodyAsEventDiscovery(HttpResponse response) throws DavException { + try { + Document doc = getResponseBodyAsDocument(response.getEntity()); + if (doc == null) { + throw new DavException(response.getStatusLine().getStatusCode(), "no response body"); + } + return EventDiscovery.createFromXml(doc.getDocumentElement()); + } catch (IOException ex) { + throw new DavException(response.getStatusLine().getStatusCode(), ex); + } + } + + /** + * Check the response and throw when it is considered to represent a failure. + */ + public void checkSuccess(HttpResponse response) throws DavException { + if (!succeeded(response)) { + throw getResponseException(response); + } + } + + /** + * Obtain a {@link DavException} representing the response. + * @throws IllegalStateException when the response is considered to be successful + */ + public DavException getResponseException(HttpResponse response) { + if (succeeded(response)) { + String msg = "Cannot retrieve exception from successful response."; + log.warn(msg); + throw new IllegalStateException(msg); + } + + StatusLine st = response.getStatusLine(); + Element responseRoot = null; + try { + responseRoot = getResponseBodyAsDocument(response.getEntity()).getDocumentElement(); + } catch (IOException e) { + // non-parseable body -> use null element + } + + return new DavException(st.getStatusCode(), st.getReasonPhrase(), null, responseRoot); + } + + /** + * Check the provided {@link HttpResponse} for successful execution. The default implementation treats all + * 2xx status codes (RFC 7231, Section 6.3). + * Implementations can further restrict the accepted range of responses (or even check the response body). + */ + public boolean succeeded(HttpResponse response) { + int status = response.getStatusLine().getStatusCode(); + return status >= 200 && status <= 299; + } +} Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/BaseDavRequest.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpBind.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpBind.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpBind.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.webdav.client.methods; + +import java.io.IOException; +import java.net.URI; + +import org.apache.http.HttpResponse; +import org.apache.jackrabbit.webdav.DavMethods; +import org.apache.jackrabbit.webdav.DavServletResponse; +import org.apache.jackrabbit.webdav.bind.BindInfo; + +/** + * Represents an HTTP BIND request. + * + * @see RFC 5842, Section 4 + * @since 2.13.6 + */ +public class HttpBind extends BaseDavRequest { + + public HttpBind(URI uri, BindInfo info) throws IOException { + super(uri); + super.setEntity(XmlEntity.create(info)); + } + + public HttpBind(String uri, BindInfo info) throws IOException { + this(URI.create(uri), info); + } + + @Override + public String getMethod() { + return DavMethods.METHOD_BIND; + } + + @Override + public boolean succeeded(HttpResponse response) { + int statusCode = response.getStatusLine().getStatusCode(); + return statusCode == DavServletResponse.SC_OK || statusCode == DavServletResponse.SC_CREATED; + } +} \ No newline at end of file Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpBind.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpCheckin.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpCheckin.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpCheckin.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.webdav.client.methods; + +import java.net.URI; + +import org.apache.http.HttpResponse; +import org.apache.jackrabbit.webdav.DavMethods; +import org.apache.jackrabbit.webdav.DavServletResponse; + +/** + * Represents an HTTP CHECKIN request. + * + * @see RFC 3253, Section 4.4 + * @since 2.13.6 + */ +public class HttpCheckin extends BaseDavRequest { + + public HttpCheckin(URI uri) { + super(uri); + } + + public HttpCheckin(String uri) { + this(URI.create(uri)); + } + + @Override + public String getMethod() { + return DavMethods.METHOD_CHECKIN; + } + + @Override + public boolean succeeded(HttpResponse response) { + int statusCode = response.getStatusLine().getStatusCode(); + return statusCode == DavServletResponse.SC_CREATED; + } +} Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpCheckin.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpCheckout.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpCheckout.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpCheckout.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.webdav.client.methods; + +import java.net.URI; + +import org.apache.http.HttpResponse; +import org.apache.jackrabbit.webdav.DavMethods; +import org.apache.jackrabbit.webdav.DavServletResponse; + +/** + * Represents an HTTP CHECKOUT request. + * + * @see RFC 3253, Section 4.3 + * @since 2.13.6 + */ +public class HttpCheckout extends BaseDavRequest { + + public HttpCheckout(URI uri) { + super(uri); + } + + public HttpCheckout(String uri) { + this(URI.create(uri)); + } + + @Override + public String getMethod() { + return DavMethods.METHOD_CHECKOUT; + } + + @Override + public boolean succeeded(HttpResponse response) { + int statusCode = response.getStatusLine().getStatusCode(); + return statusCode == DavServletResponse.SC_OK; + } +} Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpCheckout.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpCopy.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpCopy.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpCopy.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.webdav.client.methods; + +import java.net.URI; + +import org.apache.http.HttpResponse; +import org.apache.jackrabbit.webdav.DavConstants; +import org.apache.jackrabbit.webdav.DavMethods; +import org.apache.jackrabbit.webdav.DavServletResponse; + +/** + * Represents an HTTP COPY request. + * + * @see RFC 4918, Section 9.8 + * @since 2.13.6 + */ +public class HttpCopy extends BaseDavRequest { + + public HttpCopy(URI uri, URI dest, boolean overwrite, boolean shallow) { + super(uri); + super.setHeader(DavConstants.HEADER_DESTINATION, dest.toASCIIString()); + if (!overwrite) { + super.setHeader(DavConstants.HEADER_OVERWRITE, "F"); + } + if (shallow) { + super.setHeader("Depth", "0"); + } + } + + public HttpCopy(String uri, String dest, boolean overwrite, boolean shallow) { + this(URI.create(uri), URI.create(dest), overwrite, shallow); + } + + @Override + public String getMethod() { + return DavMethods.METHOD_COPY; + } + + @Override + public boolean succeeded(HttpResponse response) { + int statusCode = response.getStatusLine().getStatusCode(); + return statusCode == DavServletResponse.SC_CREATED || statusCode == DavServletResponse.SC_NO_CONTENT; + } +} Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpCopy.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpDelete.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpDelete.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpDelete.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.webdav.client.methods; + +import java.net.URI; + +import org.apache.jackrabbit.webdav.DavMethods; + +/** + * Represents an HTTP DELETE request. + * + * @see RFC 7231, Section 4.3.5 + * @since 2.13.6 + */ +public class HttpDelete extends BaseDavRequest { + + public HttpDelete(URI uri){ + super(uri); + } + + public HttpDelete(String uri) { + this(URI.create(uri)); + } + + @Override + public String getMethod() { + return DavMethods.METHOD_DELETE; + } +} \ No newline at end of file Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpDelete.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpLabel.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpLabel.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpLabel.java (working copy) @@ -0,0 +1,57 @@ +/* + * 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.webdav.client.methods; + +import java.io.IOException; +import java.net.URI; + +import org.apache.http.HttpResponse; +import org.apache.jackrabbit.webdav.DavMethods; +import org.apache.jackrabbit.webdav.DavServletResponse; +import org.apache.jackrabbit.webdav.header.DepthHeader; +import org.apache.jackrabbit.webdav.version.LabelInfo; + +/** + * Represents an HTTP LABEL request. + * + * @see RFC 3253, Section 8.2 + * @since 2.13.6 + */ +public class HttpLabel extends BaseDavRequest { + + public HttpLabel(URI uri, LabelInfo labelInfo) throws IOException { + super(uri); + DepthHeader dh = new DepthHeader(labelInfo.getDepth()); + super.setHeader(dh.getHeaderName(), dh.getHeaderValue()); + super.setEntity(XmlEntity.create(labelInfo)); + } + + public HttpLabel(String uri, LabelInfo labelInfo) throws IOException { + this(URI.create(uri), labelInfo); + } + + @Override + public String getMethod() { + return DavMethods.METHOD_LABEL; + } + + @Override + public boolean succeeded(HttpResponse response) { + int statusCode = response.getStatusLine().getStatusCode(); + return statusCode == DavServletResponse.SC_OK; + } +} Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpLabel.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpLock.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpLock.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpLock.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.webdav.client.methods; + +import java.io.IOException; +import java.net.URI; +import java.util.Arrays; + +import org.apache.http.Header; +import org.apache.http.HttpResponse; +import org.apache.jackrabbit.webdav.DavConstants; +import org.apache.jackrabbit.webdav.DavMethods; +import org.apache.jackrabbit.webdav.DavServletResponse; +import org.apache.jackrabbit.webdav.header.DepthHeader; +import org.apache.jackrabbit.webdav.header.IfHeader; +import org.apache.jackrabbit.webdav.header.TimeoutHeader; +import org.apache.jackrabbit.webdav.lock.LockInfo; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Represents an HTTP LOCK request. + * + * @see RFC 4918, Section 9.10 + * @since 2.13.6 + */ +public class HttpLock extends BaseDavRequest { + + private static final Logger LOG = LoggerFactory.getLogger(HttpLock.class); + + private final boolean isRefresh; + + public HttpLock(URI uri, LockInfo lockInfo) throws IOException { + super(uri); + + TimeoutHeader th = new TimeoutHeader(lockInfo.getTimeout()); + super.setHeader(th.getHeaderName(), th.getHeaderValue()); + DepthHeader dh = new DepthHeader(lockInfo.isDeep()); + super.setHeader(dh.getHeaderName(), dh.getHeaderValue()); + + super.setEntity(XmlEntity.create(lockInfo)); + + isRefresh = false; + } + + public HttpLock(String uri, LockInfo lockInfo) throws IOException { + this(URI.create(uri), lockInfo); + } + + public HttpLock(URI uri, long timeout, String[] lockTokens) { + super(uri); + + TimeoutHeader th = new TimeoutHeader(timeout); + super.setHeader(th.getHeaderName(), th.getHeaderValue()); + IfHeader ifh = new IfHeader(lockTokens); + super.setHeader(ifh.getHeaderName(), ifh.getHeaderValue()); + isRefresh = true; + } + + public HttpLock(String uri, long timeout, String[] lockTokens) { + this(URI.create(uri), timeout, lockTokens); + } + + @Override + public String getMethod() { + return DavMethods.METHOD_LOCK; + } + + public String getLockToken(HttpResponse response) { + Header[] ltHeader = response.getHeaders(DavConstants.HEADER_LOCK_TOKEN); + if (ltHeader == null || ltHeader.length == 0) { + return null; + } else if (ltHeader.length != 1) { + LOG.debug("Multiple 'Lock-Token' header fields in response for " + getURI() + ": " + Arrays.asList(ltHeader)); + return null; + } else { + String v = ltHeader[0].getValue().trim(); + if (!v.startsWith("<") || !v.endsWith(">")) { + LOG.debug("Invalid 'Lock-Token' header field in response for " + getURI() + ": " + Arrays.asList(ltHeader)); + return null; + } else { + return v.substring(1, v.length() - 1); + } + } + } + + @Override + public boolean succeeded(HttpResponse response) { + int statusCode = response.getStatusLine().getStatusCode(); + boolean lockTokenHeaderOk = isRefresh || null != getLockToken(response); + return lockTokenHeaderOk && (statusCode == DavServletResponse.SC_OK || statusCode == DavServletResponse.SC_CREATED); + } +} \ No newline at end of file Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpLock.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpMerge.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpMerge.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpMerge.java (working copy) @@ -0,0 +1,55 @@ +/* + * 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.webdav.client.methods; + +import java.io.IOException; +import java.net.URI; + +import org.apache.http.HttpResponse; +import org.apache.jackrabbit.webdav.DavMethods; +import org.apache.jackrabbit.webdav.DavServletResponse; +import org.apache.jackrabbit.webdav.version.MergeInfo; + +/** + * Represents an HTTP MERGE request. + * + * @see RFC 3253, Section 11.2 + * @since 2.13.6 + */ +public class HttpMerge extends BaseDavRequest { + + public HttpMerge(URI uri, MergeInfo mergeInfo) throws IOException { + super(uri); + super.setEntity(XmlEntity.create(mergeInfo)); + } + + public HttpMerge(String uri, MergeInfo mergeInfo) throws IOException { + this(URI.create(uri), mergeInfo); + } + + @Override + public String getMethod() { + return DavMethods.METHOD_MERGE; + } + + @Override + public boolean succeeded(HttpResponse response) { + int statusCode = response.getStatusLine().getStatusCode(); + // TODO: is this correct? + return statusCode == DavServletResponse.SC_MULTI_STATUS; + } +} Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpMerge.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpMkcol.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpMkcol.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpMkcol.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.webdav.client.methods; + +import java.net.URI; + +import org.apache.http.HttpResponse; +import org.apache.jackrabbit.webdav.DavMethods; +import org.apache.jackrabbit.webdav.DavServletResponse; + +/** + * Represents an HTTP MKCOL request. + * + * @see RFC 4918, Section 9.3 + * @since 2.13.6 + */ +public class HttpMkcol extends BaseDavRequest { + + public HttpMkcol(URI uri) { + super(uri); + } + + public HttpMkcol(String uri) { + this(URI.create(uri)); + } + + @Override + public String getMethod() { + return DavMethods.METHOD_MKCOL; + } + + @Override + public boolean succeeded(HttpResponse response) { + int statusCode = response.getStatusLine().getStatusCode(); + return statusCode == DavServletResponse.SC_CREATED; + } +} Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpMkcol.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpMkworkspace.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpMkworkspace.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpMkworkspace.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.webdav.client.methods; + +import java.net.URI; + +import org.apache.http.HttpResponse; +import org.apache.jackrabbit.webdav.DavMethods; +import org.apache.jackrabbit.webdav.DavServletResponse; + +/** + * Represents an HTTP MKWORKSPACE request. + * + * @see RFC 3253, Section 6.3 + * @since 2.13.6 + */ +public class HttpMkworkspace extends BaseDavRequest { + + public HttpMkworkspace(URI uri) { + super(uri); + } + + public HttpMkworkspace(String uri) { + this(URI.create(uri)); + } + + @Override + public String getMethod() { + return DavMethods.METHOD_MKWORKSPACE; + } + + @Override + public boolean succeeded(HttpResponse response) { + int statusCode = response.getStatusLine().getStatusCode(); + return statusCode == DavServletResponse.SC_CREATED; + } +} Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpMkworkspace.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpMove.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpMove.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpMove.java (working copy) @@ -0,0 +1,56 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.jackrabbit.webdav.client.methods; + +import java.net.URI; + +import org.apache.http.HttpResponse; +import org.apache.jackrabbit.webdav.DavConstants; +import org.apache.jackrabbit.webdav.DavMethods; +import org.apache.jackrabbit.webdav.DavServletResponse; + +/** + * Represents an HTTP MOVE request. + * + * @see RFC 4918, Section 9.9 + * @since 2.13.6 + */ +public class HttpMove extends BaseDavRequest { + + public HttpMove(URI uri, URI dest, boolean overwrite) { + super(uri); + super.setHeader(DavConstants.HEADER_DESTINATION, dest.toASCIIString()); + if (!overwrite) { + super.setHeader(DavConstants.HEADER_OVERWRITE, "F"); + } + } + + public HttpMove(String uri, String dest, boolean overwrite) { + this(URI.create(uri), URI.create(dest), overwrite); + } + + @Override + public String getMethod() { + return DavMethods.METHOD_MOVE; + } + + @Override + public boolean succeeded(HttpResponse response) { + int statusCode = response.getStatusLine().getStatusCode(); + return statusCode == DavServletResponse.SC_CREATED || statusCode == DavServletResponse.SC_NO_CONTENT; + } +} Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpMove.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpOptions.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpOptions.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpOptions.java (working copy) @@ -0,0 +1,79 @@ +/* + * 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.webdav.client.methods; + +import java.net.URI; +import java.util.Collections; +import java.util.HashSet; +import java.util.Set; + +import org.apache.http.Header; +import org.apache.http.HttpResponse; +import org.apache.jackrabbit.webdav.DavConstants; +import org.apache.jackrabbit.webdav.header.FieldValueParser; +import org.apache.jackrabbit.webdav.search.SearchConstants; + +/** + * Represents an HTTP OPTIONS request. + * + * @see RFC 7231, Section 4.3.7 + * @since 2.13.6 + */ +public class HttpOptions extends org.apache.http.client.methods.HttpOptions { + + public HttpOptions(URI uri) { + super(uri); + } + + public HttpOptions(String uri) { + super(URI.create(uri)); + } + + /** + * Compute the set of compliance classes returned in the "dav" header field + */ + public Set getDavComplianceClasses(HttpResponse response) { + Header[] headers = response.getHeaders(DavConstants.HEADER_DAV); + return parseTokenOrCodedUrlheaderField(headers, false); + } + + /** + * Compute set of search grammars returned in the "dasl" header field + */ + public Set getSearchGrammars(HttpResponse response) { + Header[] headers = response.getHeaders(SearchConstants.HEADER_DASL); + return parseTokenOrCodedUrlheaderField(headers, true); + } + + private Set parseTokenOrCodedUrlheaderField(Header[] headers, boolean removeBrackets) { + if (headers == null) { + return Collections.emptySet(); + } + else { + Set result = new HashSet(); + for (Header h : headers) { + for (String s : FieldValueParser.tokenizeList(h.getValue())) { + if (removeBrackets && s.startsWith("<") && s.endsWith(">")) { + s = s.substring(1, s.length() - 1); + } + result.add(s.trim()); + } + } + return Collections.unmodifiableSet(result); + } + } +} Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpOptions.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpOrderpatch.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpOrderpatch.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpOrderpatch.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.webdav.client.methods; + +import java.io.IOException; +import java.net.URI; + +import org.apache.http.HttpResponse; +import org.apache.jackrabbit.webdav.DavMethods; +import org.apache.jackrabbit.webdav.DavServletResponse; +import org.apache.jackrabbit.webdav.ordering.OrderPatch; + +/** + * Represents an HTTP ORDERPATCH request. + * + * @see RFC 3648, Section 5 + * @since 2.13.6 + */ +public class HttpOrderpatch extends BaseDavRequest { + + public HttpOrderpatch(URI uri, OrderPatch info) throws IOException { + super(uri); + super.setEntity(XmlEntity.create(info)); + } + + public HttpOrderpatch(String uri, OrderPatch info) throws IOException { + this(URI.create(uri), info); + } + + @Override + public String getMethod() { + return DavMethods.METHOD_ORDERPATCH; + } + + @Override + public boolean succeeded(HttpResponse response) { + return response.getStatusLine().getStatusCode() == DavServletResponse.SC_OK; + } +} \ No newline at end of file Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpOrderpatch.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpPoll.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpPoll.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpPoll.java (working copy) @@ -0,0 +1,58 @@ +/* + * 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.webdav.client.methods; + +import java.net.URI; + +import org.apache.http.HttpResponse; +import org.apache.jackrabbit.webdav.DavMethods; +import org.apache.jackrabbit.webdav.DavServletResponse; +import org.apache.jackrabbit.webdav.header.PollTimeoutHeader; +import org.apache.jackrabbit.webdav.observation.ObservationConstants; + +/** + * Represents an HTTP POLL request. + *

+ * Note that "POLL" is a custom HTTP extension, not defined in a standards paper. + * @since 2.13.6 + */ +public class HttpPoll extends BaseDavRequest { + + public HttpPoll(URI uri, String subscriptionId, long timeout) { + super(uri); + super.setHeader(ObservationConstants.HEADER_SUBSCRIPTIONID, subscriptionId); + if (timeout > 0) { + PollTimeoutHeader th = new PollTimeoutHeader(timeout); + super.setHeader(th.getHeaderName(), th.getHeaderValue()); + } + } + + public HttpPoll(String uri, String subscriptionId, long timeout) { + this(URI.create(uri), subscriptionId, timeout); + } + + @Override + public String getMethod() { + return DavMethods.METHOD_POLL; + } + + @Override + public boolean succeeded(HttpResponse response) { + int statusCode = response.getStatusLine().getStatusCode(); + return statusCode == DavServletResponse.SC_OK; + } +} \ No newline at end of file Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpPoll.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpPropfind.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpPropfind.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpPropfind.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.webdav.client.methods; + +import java.io.IOException; +import java.net.URI; + +import org.apache.http.HttpResponse; +import org.apache.jackrabbit.webdav.DavConstants; +import org.apache.jackrabbit.webdav.DavMethods; +import org.apache.jackrabbit.webdav.DavServletResponse; +import org.apache.jackrabbit.webdav.header.DepthHeader; +import org.apache.jackrabbit.webdav.property.DavPropertyNameSet; +import org.apache.jackrabbit.webdav.property.PropfindInfo; + +/** + * Represents an HTTP PROPFIND request. + * + * @see RFC 4918, Section 9.1 + * @since 2.13.6 + */ +public class HttpPropfind extends BaseDavRequest { + + public HttpPropfind(URI uri, int propfindType, DavPropertyNameSet names, int depth) throws IOException { + super(uri); + + DepthHeader dh = new DepthHeader(depth); + super.setHeader(dh.getHeaderName(), dh.getHeaderValue()); + + PropfindInfo info = new PropfindInfo(propfindType, names); + super.setEntity(XmlEntity.create(info)); + } + + public HttpPropfind(URI uri, DavPropertyNameSet names, int depth) throws IOException { + this(uri, DavConstants.PROPFIND_BY_PROPERTY, names, depth); + } + + public HttpPropfind(URI uri, int propfindType, int depth) throws IOException { + this(uri, propfindType, new DavPropertyNameSet(), depth); + } + + public HttpPropfind(String uri, int propfindType, int depth) throws IOException { + this(URI.create(uri), propfindType, depth); + } + + public HttpPropfind(String uri, int propfindType, DavPropertyNameSet names, int depth) throws IOException { + this(URI.create(uri), propfindType, names, depth); + } + + public HttpPropfind(String uri, DavPropertyNameSet names, int depth) throws IOException { + this(URI.create(uri), names, depth); + } + + @Override + public String getMethod() { + return DavMethods.METHOD_PROPFIND; + } + + @Override + public boolean succeeded(HttpResponse response) { + return response.getStatusLine().getStatusCode() == DavServletResponse.SC_MULTI_STATUS; + } +} \ No newline at end of file Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpPropfind.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpProppatch.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpProppatch.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpProppatch.java (working copy) @@ -0,0 +1,104 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.jackrabbit.webdav.client.methods; + +import java.io.IOException; +import java.net.URI; +import java.util.List; + +import org.apache.http.HttpResponse; +import org.apache.jackrabbit.webdav.DavMethods; +import org.apache.jackrabbit.webdav.DavServletResponse; +import org.apache.jackrabbit.webdav.property.DavPropertyNameSet; +import org.apache.jackrabbit.webdav.property.DavPropertySet; +import org.apache.jackrabbit.webdav.property.PropEntry; +import org.apache.jackrabbit.webdav.property.ProppatchInfo; + +/** + * Represents an HTTP PROPPATCH request. + * + * @see RFC 4918, Section 9.2 + * @since 2.13.6 + */ +public class HttpProppatch extends BaseDavRequest { + + // private DavPropertyNameSet propertyNames; + + public HttpProppatch(URI uri, ProppatchInfo info) throws IOException { + super(uri); + super.setEntity(XmlEntity.create(info)); + // this.propertyNames = info.getAffectedProperties(); + } + + public HttpProppatch(URI uri, List changeList) throws IOException { + this(uri, new ProppatchInfo(changeList)); + } + + public HttpProppatch(URI uri, DavPropertySet setProperties, DavPropertyNameSet removeProperties) throws IOException { + this(uri, new ProppatchInfo(setProperties, removeProperties)); + } + + public HttpProppatch(String uri, List changeList) throws IOException { + this(URI.create(uri), new ProppatchInfo(changeList)); + } + + public HttpProppatch(String uri, DavPropertySet setProperties, DavPropertyNameSet removeProperties) throws IOException { + this(URI.create(uri), new ProppatchInfo(setProperties, removeProperties)); + } + + @Override + public String getMethod() { + return DavMethods.METHOD_PROPPATCH; + } + + @Override + public boolean succeeded(HttpResponse response) { + return response.getStatusLine().getStatusCode() == DavServletResponse.SC_MULTI_STATUS; + + // disabled code that fails for current PROPPATCH behavior of Jackrabbit +// MultiStatusResponse responses[] = super.getResponseBodyAsMultiStatus(response).getResponses(); +// if (responses.length != 1) { +// throw new DavException(DavServletResponse.SC_MULTI_STATUS, +// "PROPPATCH failed: Expected exactly one multistatus response element, but got " + responses.length); +// } +// DavPropertyNameSet okSet = responses[0].getPropertyNames(DavServletResponse.SC_OK); +// if (okSet.isEmpty()) { +// throw new DavException(DavServletResponse.SC_MULTI_STATUS, +// "PROPPATCH failed: No 'OK' response found for resource " + responses[0].getHref()); +// } else { +// DavPropertyNameIterator it = propertyNames.iterator(); +// while (it.hasNext()) { +// DavPropertyName pn = it.nextPropertyName(); +// boolean success = okSet.remove(pn); +// if (!success) { +// throw new DavException(DavServletResponse.SC_MULTI_STATUS, +// "PROPPATCH failed: Property name not present in multistatus response: " + pn); +// } +// } +// } +// if (!okSet.isEmpty()) { +// StringBuilder b = new StringBuilder(); +// DavPropertyNameIterator it = okSet.iterator(); +// while (it.hasNext()) { +// b.append(it.nextPropertyName().toString()).append("; "); +// } +// throw new DavException(DavServletResponse.SC_MULTI_STATUS, +// "PROPPATCH failed: The following properties outside of the original request where set or removed: " + b.toString()); +// } +// return true; + } +} \ No newline at end of file Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpProppatch.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpRebind.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpRebind.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpRebind.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.webdav.client.methods; + +import java.io.IOException; +import java.net.URI; + +import org.apache.http.HttpResponse; +import org.apache.jackrabbit.webdav.DavMethods; +import org.apache.jackrabbit.webdav.DavServletResponse; +import org.apache.jackrabbit.webdav.bind.RebindInfo; + +/** + * Represents an HTTP REBIND request. + * + * @see RFC 5842, Section 6 + * @since 2.13.6 + */ +public class HttpRebind extends BaseDavRequest { + + public HttpRebind(URI uri, RebindInfo info) throws IOException { + super(uri); + super.setEntity(XmlEntity.create(info)); + } + + public HttpRebind(String uri, RebindInfo info) throws IOException { + this(URI.create(uri), info); + } + + @Override + public String getMethod() { + return DavMethods.METHOD_REBIND; + } + + @Override + public boolean succeeded(HttpResponse response) { + int statusCode = response.getStatusLine().getStatusCode(); + return statusCode == DavServletResponse.SC_OK || statusCode == DavServletResponse.SC_CREATED; + } +} \ No newline at end of file Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpRebind.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpReport.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpReport.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpReport.java (working copy) @@ -0,0 +1,66 @@ +/* + * 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.webdav.client.methods; + +import java.io.IOException; +import java.net.URI; + +import org.apache.http.HttpResponse; +import org.apache.jackrabbit.webdav.DavConstants; +import org.apache.jackrabbit.webdav.DavMethods; +import org.apache.jackrabbit.webdav.DavServletResponse; +import org.apache.jackrabbit.webdav.header.DepthHeader; +import org.apache.jackrabbit.webdav.version.report.ReportInfo; + +/** + * Represents an HTTP REPORT request. + * + * @see RFC 3253, Section 3.6 + * @since 2.13.6 + */ +public class HttpReport extends BaseDavRequest { + + private final boolean isDeep; + + public HttpReport(URI uri, ReportInfo reportInfo) throws IOException { + super(uri); + DepthHeader dh = new DepthHeader(reportInfo.getDepth()); + isDeep = reportInfo.getDepth() > DavConstants.DEPTH_0; + super.setHeader(dh.getHeaderName(), dh.getHeaderValue()); + super.setEntity(XmlEntity.create(reportInfo)); + } + + public HttpReport(String uri, ReportInfo reportInfo) throws IOException { + this(URI.create(uri), reportInfo); + } + + @Override + public String getMethod() { + return DavMethods.METHOD_REPORT; + } + + @Override + public boolean succeeded(HttpResponse response) { + int statusCode = response.getStatusLine().getStatusCode(); + if (isDeep) { + return statusCode == DavServletResponse.SC_MULTI_STATUS; + } else { + return statusCode == DavServletResponse.SC_OK || statusCode == DavServletResponse.SC_MULTI_STATUS; + } + + } +} \ No newline at end of file Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpReport.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpSearch.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpSearch.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpSearch.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.webdav.client.methods; + +import java.io.IOException; +import java.net.URI; + +import org.apache.http.HttpResponse; +import org.apache.jackrabbit.webdav.DavMethods; +import org.apache.jackrabbit.webdav.DavServletResponse; +import org.apache.jackrabbit.webdav.search.SearchInfo; + +/** + * Represents an HTTP SEARCH request. + * + * @see RFC 5323, Section 2 + * @since 2.13.6 + */ +public class HttpSearch extends BaseDavRequest { + + public HttpSearch(URI uri, SearchInfo searchInfo) throws IOException { + super(uri); + super.setEntity(XmlEntity.create(searchInfo)); + } + + public HttpSearch(String uri, SearchInfo searchInfo) throws IOException { + this(URI.create(uri), searchInfo); + } + + @Override + public String getMethod() { + return DavMethods.METHOD_SEARCH; + } + + @Override + public boolean succeeded(HttpResponse response) { + int statusCode = response.getStatusLine().getStatusCode(); + return statusCode == DavServletResponse.SC_MULTI_STATUS; + } +} \ No newline at end of file Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpSearch.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpSubscribe.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpSubscribe.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpSubscribe.java (working copy) @@ -0,0 +1,88 @@ +/* + * 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.webdav.client.methods; + +import java.io.IOException; +import java.net.URI; + +import org.apache.http.HttpResponse; +import org.apache.jackrabbit.webdav.DavConstants; +import org.apache.jackrabbit.webdav.DavMethods; +import org.apache.jackrabbit.webdav.DavServletResponse; +import org.apache.jackrabbit.webdav.header.CodedUrlHeader; +import org.apache.jackrabbit.webdav.header.DepthHeader; +import org.apache.jackrabbit.webdav.header.TimeoutHeader; +import org.apache.jackrabbit.webdav.observation.ObservationConstants; +import org.apache.jackrabbit.webdav.observation.SubscriptionInfo; + +/** + * Represents an HTTP SUBSCRIBE request. + *

+ * Note that "SUBSCRIBE" is a custom HTTP extension, not defined in a standards paper. + * @since 2.13.6 + */ +public class HttpSubscribe extends BaseDavRequest { + + public HttpSubscribe(URI uri, SubscriptionInfo info, String subscriptionId) throws IOException { + super(uri); + if (info == null) { + throw new IllegalArgumentException("SubscriptionInfo must not be null."); + } + // optional subscriptionId (only required to modify an existing + // subscription) + if (subscriptionId != null) { + CodedUrlHeader h = new CodedUrlHeader(ObservationConstants.HEADER_SUBSCRIPTIONID, subscriptionId); + super.setHeader(h.getHeaderName(), h.getHeaderValue()); + } + // optional timeout header + long to = info.getTimeOut(); + if (to != DavConstants.UNDEFINED_TIMEOUT) { + TimeoutHeader h = new TimeoutHeader(info.getTimeOut()); + super.setHeader(h.getHeaderName(), h.getHeaderValue()); + } + // always set depth header since value is boolean flag + DepthHeader dh = new DepthHeader(info.isDeep()); + super.setHeader(dh.getHeaderName(), dh.getHeaderValue()); + super.setEntity(XmlEntity.create(info)); + } + + public HttpSubscribe(String uri, SubscriptionInfo info, String subscriptionId) throws IOException { + this(URI.create(uri), info, subscriptionId); + } + + public String getSubscriptionId(HttpResponse response) { + org.apache.http.Header sbHeader = response.getFirstHeader(ObservationConstants.HEADER_SUBSCRIPTIONID); + if (sbHeader != null) { + CodedUrlHeader cuh = new CodedUrlHeader(ObservationConstants.HEADER_SUBSCRIPTIONID, sbHeader.getValue()); + return cuh.getCodedUrl(); + } + else { + return null; + } + } + + @Override + public String getMethod() { + return DavMethods.METHOD_SUBSCRIBE; + } + + @Override + public boolean succeeded(HttpResponse response) { + int statusCode = response.getStatusLine().getStatusCode(); + return statusCode == DavServletResponse.SC_OK; + } +} \ No newline at end of file Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpSubscribe.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpUnbind.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpUnbind.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpUnbind.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.webdav.client.methods; + +import java.io.IOException; +import java.net.URI; + +import org.apache.http.HttpResponse; +import org.apache.jackrabbit.webdav.DavMethods; +import org.apache.jackrabbit.webdav.DavServletResponse; +import org.apache.jackrabbit.webdav.bind.UnbindInfo; + +/** + * Represents an HTTP UNBIND request. + * + * @see RFC 5842, Section 5 + * @since 2.13.6 + */ +public class HttpUnbind extends BaseDavRequest { + + public HttpUnbind(URI uri, UnbindInfo info) throws IOException { + super(uri); + super.setEntity(XmlEntity.create(info)); + } + + public HttpUnbind(String uri, UnbindInfo info) throws IOException { + this(URI.create(uri), info); + } + + @Override + public String getMethod() { + return DavMethods.METHOD_UNBIND; + } + + @Override + public boolean succeeded(HttpResponse response) { + int statusCode = response.getStatusLine().getStatusCode(); + return statusCode == DavServletResponse.SC_OK || statusCode == DavServletResponse.SC_NO_CONTENT; + } +} \ No newline at end of file Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpUnbind.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpUnlock.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpUnlock.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpUnlock.java (working copy) @@ -0,0 +1,55 @@ +/* + * 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.webdav.client.methods; + +import java.net.URI; + +import org.apache.http.HttpResponse; +import org.apache.jackrabbit.webdav.DavConstants; +import org.apache.jackrabbit.webdav.DavMethods; +import org.apache.jackrabbit.webdav.DavServletResponse; +import org.apache.jackrabbit.webdav.header.CodedUrlHeader; + +/** + * Represents an HTTP UNLOCK request. + * + * @see RFC 4918, Section 9.11 + * @since 2.13.6 + */ +public class HttpUnlock extends BaseDavRequest { + + public HttpUnlock(URI uri, String lockToken) { + super(uri); + CodedUrlHeader lth = new CodedUrlHeader(DavConstants.HEADER_LOCK_TOKEN, lockToken); + super.setHeader(lth.getHeaderName(), lth.getHeaderValue()); + } + + public HttpUnlock(String uri, String lockToken) { + this(URI.create(uri), lockToken); + } + + @Override + public String getMethod() { + return DavMethods.METHOD_UNLOCK; + } + + @Override + public boolean succeeded(HttpResponse response) { + int statusCode = response.getStatusLine().getStatusCode(); + return statusCode == DavServletResponse.SC_OK || statusCode == DavServletResponse.SC_NO_CONTENT; + } +} \ No newline at end of file Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpUnlock.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpUnsubscribe.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpUnsubscribe.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpUnsubscribe.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.webdav.client.methods; + +import java.net.URI; + +import org.apache.http.HttpResponse; +import org.apache.jackrabbit.webdav.DavMethods; +import org.apache.jackrabbit.webdav.DavServletResponse; +import org.apache.jackrabbit.webdav.observation.ObservationConstants; + +/** + * Represents an HTTP UNSUBSCRIBE request. + *

+ * Note that "UNSUBSCRIBE" is a custom HTTP extension, not defined in a standards paper. + * @since 2.13.6 + */ +public class HttpUnsubscribe extends BaseDavRequest { + + public HttpUnsubscribe(URI uri, String subscriptionId) { + super(uri); + super.setHeader(ObservationConstants.HEADER_SUBSCRIPTIONID, subscriptionId); + } + + public HttpUnsubscribe(String uri, String subscriptionId) { + this(URI.create(uri), subscriptionId); + } + + @Override + public String getMethod() { + return DavMethods.METHOD_UNSUBSCRIBE; + } + + @Override + public boolean succeeded(HttpResponse response) { + int statusCode = response.getStatusLine().getStatusCode(); + return statusCode == DavServletResponse.SC_NO_CONTENT; + } +} \ No newline at end of file Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpUnsubscribe.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpUpdate.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpUpdate.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpUpdate.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.webdav.client.methods; + +import java.io.IOException; +import java.net.URI; + +import org.apache.http.HttpResponse; +import org.apache.jackrabbit.webdav.DavMethods; +import org.apache.jackrabbit.webdav.DavServletResponse; +import org.apache.jackrabbit.webdav.version.UpdateInfo; + +/** + * Represents an HTTP UPDATE request. + * + * @see RFC 3253, Section 7.1 + * @since 2.13.6 + */ +public class HttpUpdate extends BaseDavRequest { + + public HttpUpdate(URI uri, UpdateInfo updateInfo) throws IOException { + super(uri); + super.setEntity(XmlEntity.create(updateInfo)); + } + + public HttpUpdate(String uri, UpdateInfo updateInfo) throws IOException { + this(URI.create(uri), updateInfo); + } + + @Override + public String getMethod() { + return DavMethods.METHOD_UPDATE; + } + + @Override + public boolean succeeded(HttpResponse response) { + int statusCode = response.getStatusLine().getStatusCode(); + return statusCode == DavServletResponse.SC_MULTI_STATUS; + } +} Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpUpdate.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpVersionControl.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpVersionControl.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpVersionControl.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.webdav.client.methods; + +import java.net.URI; + +import org.apache.http.HttpResponse; +import org.apache.jackrabbit.webdav.DavMethods; +import org.apache.jackrabbit.webdav.DavServletResponse; + +/** + * Represents an HTTP VERSION-CONTROL request. + * + * @see RFC 3253, Section 3.5 + * @since 2.13.6 + */ +public class HttpVersionControl extends BaseDavRequest { + + public HttpVersionControl(URI uri) { + super(uri); + } + + public HttpVersionControl(String uri) { + this(URI.create(uri)); + } + + @Override + public String getMethod() { + return DavMethods.METHOD_VERSION_CONTROL; + } + + @Override + public boolean succeeded(HttpResponse response) { + int statusCode = response.getStatusLine().getStatusCode(); + return statusCode == DavServletResponse.SC_OK; + } +} Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/HttpVersionControl.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/XmlEntity.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/XmlEntity.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/XmlEntity.java (working copy) @@ -0,0 +1,68 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.jackrabbit.webdav.client.methods; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; + +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.transform.TransformerException; + +import org.apache.http.HttpEntity; +import org.apache.http.entity.ByteArrayEntity; +import org.apache.http.entity.ContentType; +import org.apache.jackrabbit.webdav.xml.DomUtil; +import org.apache.jackrabbit.webdav.xml.XmlSerializable; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.w3c.dom.Document; +import org.xml.sax.SAXException; + +/** + * Utility methods for creating request entities from {@link Document}s or {@link XmlSerializable}s. + */ +public class XmlEntity { + + private static Logger LOG = LoggerFactory.getLogger(XmlEntity.class); + + private static ContentType CT = ContentType.create("application/xml", "UTF-8"); + + public static HttpEntity create(Document doc) throws IOException { + try { + ByteArrayOutputStream xml = new ByteArrayOutputStream(); + DomUtil.transformDocument(doc, xml); + return new ByteArrayEntity(xml.toByteArray(), CT); + } catch (TransformerException ex) { + LOG.error(ex.getMessage()); + throw new IOException(ex); + } catch (SAXException ex) { + LOG.error(ex.getMessage()); + throw new IOException(ex); + } + } + + public static HttpEntity create(XmlSerializable payload) throws IOException { + try { + Document doc = DomUtil.createDocument(); + doc.appendChild(payload.toXml(doc)); + return create(doc); + } catch (ParserConfigurationException ex) { + LOG.error(ex.getMessage()); + throw new IOException(ex); + } + } +} Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/XmlEntity.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/package-info.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/package-info.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/package-info.java (working copy) @@ -0,0 +1,31 @@ +/* + * 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. + */ + +/** + * Provides classes for use with the Apache HttpClient, supporting WebDAV + * request methods. + *

+ * This version also contains classes for use with the obsolete "Commons + * HttpClient"; they have been marked "deprecated" and will be removed in the + * next major release. + * + * @see JCR-2406 + * @see https://hc.apache.org/httpcomponents-client-4.5.x/ + */ +@org.osgi.annotation.versioning.Version("2.0.0") +package org.apache.jackrabbit.webdav.client.methods; Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/package-info.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/header/CodedUrlHeader.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/header/CodedUrlHeader.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/header/CodedUrlHeader.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.webdav.header; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.servlet.http.HttpServletRequest; + +/** + * CodedUrlHeader... + */ +public class CodedUrlHeader implements Header { + + private static Logger log = LoggerFactory.getLogger(CodedUrlHeader.class); + + private final String headerName; + private final String headerValue; + + public CodedUrlHeader(String headerName, String headerValue) { + this.headerName = headerName; + if (headerValue != null && !(headerValue.startsWith("<") && headerValue.endsWith(">"))) { + headerValue = "<" + headerValue + ">"; + } + this.headerValue = headerValue; + } + + /** + * Return the name of the header + * + * @return header name + * @see Header#getHeaderName() + */ + public String getHeaderName() { + return headerName; + } + + /** + * Return the value of the header + * + * @return value + * @see Header#getHeaderValue() + */ + public String getHeaderValue() { + return headerValue; + } + + /** + * Returns the token present in the header value or null. + * If the header contained multiple tokens separated by ',' the first value + * is returned. + * + * @return token present in the CodedURL header or null if + * the header is not present. + * @see #getCodedUrls() + */ + public String getCodedUrl() { + String[] codedUrls = getCodedUrls(); + return (codedUrls != null) ? codedUrls[0] : null; + } + + /** + * Return an array of coded urls as present in the header value or null if + * no value is present. + * + * @return array of coded urls + */ + public String[] getCodedUrls() { + String[] codedUrls = null; + if (headerValue != null) { + String[] values = headerValue.split(","); + codedUrls = new String[values.length]; + for (int i = 0; i < values.length; i++) { + int p1 = values[i].indexOf('<'); + if (p1<0) { + throw new IllegalArgumentException("Invalid CodedURL header value:" + values[i]); + } + int p2 = values[i].indexOf('>', p1); + if (p2<0) { + throw new IllegalArgumentException("Invalid CodedURL header value:" + values[i]); + } + codedUrls[i] = values[i].substring(p1+1, p2); + } + } + return codedUrls; + } + + /** + * Retrieves the header with the given name and builds a new CodedUrlHeader. + * + * @param request + * @param headerName + * @return new CodedUrlHeader instance + */ + public static CodedUrlHeader parse(HttpServletRequest request, String headerName) { + String headerValue = request.getHeader(headerName); + return new CodedUrlHeader(headerName, headerValue); + } +} \ No newline at end of file Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/header/CodedUrlHeader.java ___________________________________________________________________ Added: svn Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/header/DepthHeader.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/header/DepthHeader.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/header/DepthHeader.java (working copy) @@ -0,0 +1,128 @@ +/* + * 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.webdav.header; + +import org.apache.jackrabbit.webdav.DavConstants; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.servlet.http.HttpServletRequest; + +/** + * DepthHeader... + */ +public class DepthHeader implements Header, DavConstants { + + private static Logger log = LoggerFactory.getLogger(DepthHeader.class); + + private final int depth; + + /** + * Create a new DepthHeader from the given integer. + * + * @param depth + */ + public DepthHeader(int depth) { + if (depth == DEPTH_0 || depth == DEPTH_1 || depth == DEPTH_INFINITY) { + this.depth = depth; + } else { + throw new IllegalArgumentException("Invalid depth: " + depth); + } + } + + /** + * Create a new DepthHeader with either value {@link #DEPTH_0 0} + * or {@link #DEPTH_INFINITY infinity}. + * + * @param isDeep + */ + public DepthHeader(boolean isDeep) { + this.depth = (isDeep) ? DEPTH_INFINITY : DEPTH_0; + } + + /** + * @return integer representation of the depth indicated by the given header. + */ + public int getDepth() { + return depth; + } + + /** + * Return {@link DavConstants#HEADER_DEPTH Depth} + * + * @return {@link DavConstants#HEADER_DEPTH Depth} + * @see DavConstants#HEADER_DEPTH + * @see Header#getHeaderName() + */ + public String getHeaderName() { + return DavConstants.HEADER_DEPTH; + } + + /** + * Returns the header value. + * + * @return header value + * @see Header#getHeaderValue() + */ + public String getHeaderValue() { + if (depth == DavConstants.DEPTH_0 || depth == DavConstants.DEPTH_1) { + return String.valueOf(depth); + } else { + return DavConstants.DEPTH_INFINITY_S; + } + } + + /** + * Retrieve the Depth header from the given request object and parse the + * value. If no header is present or the value is empty String, the + * defaultValue is used ot build a new DepthHeader instance. + * + * @param request + * @param defaultValue + * @return a new DepthHeader instance + */ + public static DepthHeader parse(HttpServletRequest request, int defaultValue) { + String headerValue = request.getHeader(HEADER_DEPTH); + if (headerValue == null || "".equals(headerValue)) { + return new DepthHeader(defaultValue); + } else { + return new DepthHeader(depthToInt(headerValue)); + } + } + + /** + * Convert the String depth value to an integer. + * + * @param depth + * @return integer representation of the given depth String + * @throws IllegalArgumentException if the String does not represent a valid + * depth. + */ + private static int depthToInt(String depth) { + int d; + if (depth.equalsIgnoreCase(DavConstants.DEPTH_INFINITY_S)) { + d = DavConstants.DEPTH_INFINITY; + } else if (depth.equals(DavConstants.DEPTH_0+"")) { + d = DavConstants.DEPTH_0; + } else if (depth.equals(DavConstants.DEPTH_1+"")) { + d = DavConstants.DEPTH_1; + } else { + throw new IllegalArgumentException("Invalid depth value: " + depth); + } + return d; + } +} \ No newline at end of file Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/header/DepthHeader.java ___________________________________________________________________ Added: svn Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/header/FieldValueParser.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/header/FieldValueParser.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/header/FieldValueParser.java (working copy) @@ -0,0 +1,55 @@ +/* + * 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.webdav.header; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +public class FieldValueParser { + + /** + * Tokenize lists of token and quoted-url + * @param list field value + */ + public static List tokenizeList(String list) { + + String[] split = list.split(","); + if (split.length == 1) { + return Collections.singletonList(split[0].trim()); + } else { + List result = new ArrayList(); + String inCodedUrl = null; + for (String t : split) { + String trimmed = t.trim(); + // handle quoted-url containing "," + if (trimmed.startsWith("<") && !trimmed.endsWith(">")) { + inCodedUrl = trimmed + ","; + } else if (inCodedUrl != null && trimmed.endsWith(">")) { + inCodedUrl += trimmed; + result.add(inCodedUrl); + inCodedUrl = null; + } else { + if (trimmed.length() != 0) { + result.add(trimmed); + } + } + } + return Collections.unmodifiableList(result); + } + } +} Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/header/FieldValueParser.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/header/Header.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/header/Header.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/header/Header.java (working copy) @@ -0,0 +1,27 @@ +/* + * 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.webdav.header; + +/** + * Header... + */ +public interface Header { + + public String getHeaderName(); + + public String getHeaderValue(); +} \ No newline at end of file Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/header/Header.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-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/header/IfHeader.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/header/IfHeader.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/header/IfHeader.java (working copy) @@ -0,0 +1,888 @@ +/* + * 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.webdav.header; + +import org.apache.jackrabbit.webdav.DavConstants; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.servlet.http.HttpServletRequest; +import java.io.IOException; +import java.io.Reader; +import java.io.StringReader; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; + +/** + * The IfHeader class represents the state lists defined + * through the HTTP If header, which is specified in RFC 2518 as + * follows : + *

+     If = "If" ":" ( 1*No-tag-list | 1*Tagged-list)
+     No-tag-list = List
+     Tagged-list = Resource 1*List
+     Resource = Coded-URL
+     List = "(" 1*(["Not"](State-etag | "[" entity-tag "]")) ")"
+     State-etag = Coded-URL
+     Coded-URL = "<" absoluteURI ">"
+ * 
+ *

+ * Reformulating this specification into proper EBNF as specified by N. Wirth + * we get the following productions, which map to the parse METHODS of this + * class. Any whitespace is ignored except for white space surrounding and + * within words which is considered significant. + *

+     If = "If:" ( Tagged | Untagged ).
+     Tagged = { "<" Word ">" Untagged } .
+     Untagged = { "(" IfList ")" } .
+     IfList = { [ "Not" ] ( ("<" Word ">" ) | ( "[" Word "]" ) ) } .
+     Word = characters .
+ * 
+ *

+ * An If header either contains untagged IfList entries or + * tagged IfList entries but not a mixture of both. An If + * header containing tagged entries is said to be of tagged type while + * an If header containing untagged entries is said to be of + * untagged type. + *

+ * An IfList is a list of tokens - words enclosed in < > + * - and etags - words enclosed in [ ]. An IfList matches a + * (token, etag) tuple if all entries in the list match. If an entry in the list + * is prefixed with the word Not (parsed case insensitively) the entry + * must not match the concrete token or etag. + *

+ * Example: The ifList (<token> [etag]) only matches + * if the concret token has the value token and the conrete etag + * has the value etag. On the other hand, the ifList + * (Not <notoken>) matches any token which is not + * notoken (in this case the concrete value of the etag is + * not taken into consideration). + * + * @author Felix Meschberger + */ +public class IfHeader implements Header { + + /** + * default logger + */ + private static final Logger log = LoggerFactory.getLogger(IfHeader.class); + + /** + * The string representation of the header value + */ + private final String headerValue; + + /** + * The list of untagged state entries + */ + private final IfHeaderInterface ifHeader; + + /** + * The list of all positive tokens present in the If header. + */ + private List allTokens = new ArrayList(); + /** + * The list of all NOT tokens present in the If header. + */ + private List allNotTokens = new ArrayList(); + + /** + * Create a Untagged IfHeader if the given lock tokens. + * + * @param tokens + */ + public IfHeader(String[] tokens) { + allTokens.addAll(Arrays.asList(tokens)); + StringBuffer b = new StringBuffer(); + for (String token : tokens) { + b.append("(").append("<"); + b.append(token); + b.append(">").append(")"); + } + headerValue = b.toString(); + ifHeader = parse(); + } + + /** + * Parses the If header and creates and internal representation + * which is easy to query. + * + * @param req The request object + */ + public IfHeader(HttpServletRequest req) { + headerValue = req.getHeader(DavConstants.HEADER_IF); + ifHeader = parse(); + } + + /** + * Return {@link DavConstants#HEADER_IF If} + * + * @return {@link DavConstants#HEADER_IF If} + * @see DavConstants#HEADER_IF + */ + public String getHeaderName() { + return DavConstants.HEADER_IF; + } + + /** + * Return the String representation of the If header present on + * the given request or null. + * + * @return If header value as String or null. + */ + public String getHeaderValue() { + return headerValue; + } + + /** + * Returns true if an If header was present in the given request. False otherwise. + * + * @return true if an If header was present. + */ + public boolean hasValue() { + return ifHeader != null; + } + + /** + * Tries to match the contents of the If header with the given + * token and etag values with the restriction to only check for the tag. + *

+ * If the If header is of untagged type, the untagged IfList + * is matched against the token and etag given: A match of the token and + * etag is found if at least one of the IfList entries match the + * token and etag tuple. + * + * @param tag The tag to identify the IfList to match the token + * and etag against. + * @param token The token to compare. + * @param etag The ETag value to compare. + * + * @return If the If header is of untagged type the result is + * true if any of the IfList entries matches + * the token and etag values. For tagged type If header the + * result is true if either no entry for the given tag + * exists in the If header or if the IfList for the + * given tag matches the token and etag given. + */ + public boolean matches(String tag, String token, String etag) { + if (ifHeader == null) { + log.debug("matches: No If header, assume match"); + return true; + } else { + return ifHeader.matches(tag, token, etag); + } + } + + /** + * @return an iterator over all tokens present in the if header, that were + * not denied by a leading NOT statement. + */ + public Iterator getAllTokens() { + return allTokens.iterator(); + } + + /** + * @return an iterator over all NOT tokens present in the if header, that + * were explicitly denied. + */ + public Iterator getAllNotTokens() { + return allNotTokens.iterator(); + } + + /** + * Parse the original header value and build the internal IfHeaderInterface + * object that is easy to query. + */ + private IfHeaderInterface parse() { + IfHeaderInterface ifHeader; + if (headerValue != null && headerValue.length() > 0) { + StringReader reader = null; + int firstChar = 0; + + try { + reader = new StringReader(headerValue); + // get the first character to decide - expect '(' or '<' + try { + reader.mark(1); + firstChar = readWhiteSpace(reader); + reader.reset(); + } catch (IOException ignore) { + // may be thrown according to API but is only thrown by the + // StringReader class if the reader is already closed. + } + + if (firstChar == '(') { + ifHeader = parseUntagged(reader); + } else if (firstChar == '<') { + ifHeader = parseTagged(reader); + } else { + logIllegalState("If", firstChar, "(<", null); + ifHeader = null; + } + + } finally { + if (reader != null) { + reader.close(); + } + } + + } else { + log.debug("IfHeader: No If header in request"); + ifHeader = null; + } + return ifHeader; + } + + //---------- internal IF header parser ------------------------------------- + /** + * Parses a tagged type If header. This method implements the + * Tagged production given in the class comment : + *

+         Tagged = { "<" Word ">" Untagged } .
+     * 
+ * + * @param reader + * @return + */ + private IfHeaderMap parseTagged(StringReader reader) { + IfHeaderMap map = new IfHeaderMap(); + try { + while (true) { + // read next non-white space + int c = readWhiteSpace(reader); + if (c < 0) { + // end of input, no more entries + break; + } else if (c == '<') { + // start a tag with an IfList + String resource = readWord(reader, '>'); + if (resource != null) { + // go to untagged after reading the resource + map.put(resource, parseUntagged(reader)); + } else { + break; + } + } else { + // unexpected character + // catchup to end of input or start of a tag + logIllegalState("Tagged", c, "<", reader); + } + } + } catch (IOException ioe) { + log.error("parseTagged: Problem parsing If header: "+ioe.toString()); + } + + return map; + } + + /** + * Parses an untagged type If header. This method implements the + * Untagged production given in the class comment : + *
+         Untagged = { "(" IfList ")" } .
+     * 
+ * + * @param reader The StringReader to read from for parsing + * + * @return An ArrayList of {@link IfList} entries. + */ + private IfHeaderList parseUntagged(StringReader reader) { + IfHeaderList list = new IfHeaderList(); + try { + while (true) { + // read next non white space + reader.mark(1); + int c = readWhiteSpace(reader); + if (c < 0) { + // end of input, no more IfLists + break; + + } else if (c == '(') { + // start of an IfList, parse + list.add(parseIfList(reader)); + + } else if (c == '<') { + // start of a tag, return current list + reader.reset(); + break; + + } else { + // unexpected character + // catchup to end of input or start of an IfList + logIllegalState("Untagged", c, "(", reader); + } + } + } catch (IOException ioe) { + log.error("parseUntagged: Problem parsing If header: "+ioe.toString()); + } + return list; + } + + /** + * Parses an IfList in the If header. This method + * implements the Tagged production given in the class comment : + *
+         IfList = { [ "Not" ] ( ("<" Word ">" ) | ( "[" Word "]" ) ) } .
+     * 
+ * + * @param reader The StringReader to read from for parsing + * + * @return The {@link IfList} for the input IfList. + * + * @throws IOException if a problem occurs during reading. + */ + private IfList parseIfList(StringReader reader) throws IOException { + IfList res = new IfList(); + boolean positive = true; + String word; + + ReadLoop: + while (true) { + int nextChar = readWhiteSpace(reader); + switch (nextChar) { + case 'N': + case 'n': + // read not + + // check whether o or O + int not = reader.read(); + if (not != 'o' && not != 'O') { + logIllegalState("IfList-Not", not, "o", null); + break; + } + + // check whether t or T + not = reader.read(); + if (not !='t' && not != 'T') { + logIllegalState("IfList-Not", not, "t", null); + break; + } + + // read Not ok + positive = false; + break; + + case '<': + // state token + word = readWord(reader, '>'); + if (word != null) { + res.add(new IfListEntryToken(word, positive)); + // also add the token to the list of all tokens + if (positive) { + allTokens.add(word); + } else { + allNotTokens.add(word); + } + positive = true; + } + break; + + case '[': + // etag + word = readWord(reader, ']'); + if (word != null) { + res.add(new IfListEntryEtag(word, positive)); + positive = true; + } + break; + + case ')': + // correct end of list, end the loop + log.debug("parseIfList: End of If list, terminating loop"); + break ReadLoop; + + default: + logIllegalState("IfList", nextChar, "nN<[)", reader); + + // abort loop if EOF + if (nextChar < 0) { + break ReadLoop; + } + + break; + } + } + + // return the current list anyway + return res; + } + + /** + * Returns the first non-whitespace character from the reader or -1 if + * the end of the reader is encountered. + * + * @param reader The Reader to read from + * + * @return The first non-whitespace character or -1 in case of EOF. + * + * @throws IOException if a problem occurs during reading. + */ + private int readWhiteSpace(Reader reader) throws IOException { + int c = reader.read(); + while (c >= 0 && Character.isWhitespace((char) c)) { + c = reader.read(); + } + return c; + } + + /** + * Reads from the input until the end character is encountered and returns + * the string up to but not including this end character. If the end of input + * is reached before reading the end character null is + * returned. + *

+ * Note that this method does not support any escaping. + * + * @param reader The Reader to read from + * @param end The ending character limiting the word. + * + * @return The string read up to but not including the ending character or + * null if the end of input is reached before the ending + * character has been read. + * + * @throws IOException if a problem occurs during reading. + */ + private String readWord(Reader reader, char end) throws IOException { + StringBuffer buf = new StringBuffer(); + + // read the word value + int c = reader.read(); + for (; c >= 0 && c != end; c=reader.read()) { + buf.append((char) c); + } + + // check whether we succeeded + if (c < 0) { + log.error("readWord: Unexpected end of input reading word"); + return null; + } + + // build the string and return it + return buf.toString(); + } + + /** + * Logs an unexpected character with the corresponding state and list of + * expected characters. If the reader parameter is not null, characters + * are read until either the end of the input is reached or any of the + * characters in the expChar string is read. + * + * @param state The name of the current parse state. This method logs this + * name in the message. The intended value would probably be the + * name of the EBNF production during which the error occurs. + * @param effChar The effective character read. + * @param expChar The list of characters acceptable in the current state. + * @param reader The reader to be caught up to any of the expected + * characters. If null the input is not caught up to + * any of the expected characters (of course ;-). + */ + private void logIllegalState(String state, int effChar, String expChar, + StringReader reader) { + + // format the effective character to be logged + String effString = (effChar < 0) ? "" : String.valueOf((char) effChar); + + // log the error + log.error("logIllegalState: Unexpected character '"+effString+"' in state "+state+", expected any of "+expChar); + + // catch up if a reader is given + if (reader != null && effChar >= 0) { + try { + log.debug("logIllegalState: Catch up to any of "+expChar); + do { + reader.mark(1); + effChar = reader.read(); + } while (effChar >= 0 && expChar.indexOf(effChar) < 0); + if (effChar >= 0) { + reader.reset(); + } + } catch (IOException ioe) { + log.error("logIllegalState: IO Problem catching up to any of "+expChar); + } + } + } + + //---------- internal If header structure ---------------------------------- + + /** + * The IfListEntry abstract class is the base class for + * entries in an IfList production. This abstract base class + * provides common functionality to both types of entries, namely tokens + * enclosed in angle brackets (< >) and etags enclosed + * in square brackets ([ ]). + */ + private static abstract class IfListEntry { + + /** + * The entry string value - the semantics of this value depends on the + * implementing class. + */ + protected final String value; + + /** Flag to indicate, whether this is a positive match or not */ + protected final boolean positive; + + /** The cached result of the {@link #toString} method. */ + protected String stringValue; + + /** + * Sets up the final fields of this abstract class. The meaning of + * value parameter depends solely on the implementing class. From the + * point of view of this abstract class, it is simply a string value. + * + * @param value The string value of this instance + * @param positive true if matches are positive + */ + protected IfListEntry(String value, boolean positive) { + this.value = value; + this.positive = positive; + } + + /** + * Matches the value from the parameter to the internal string value. + * If the parameter and the {@link #value} field match, the method + * returns true for positive matches and false + * for negative matches. + *

+ * This helper method can be called by implementations to evaluate the + * concrete match on the correct value parameter. See + * {@link #match(String, String)} for the external API method. + * + * @param value The string value to compare to the {@link #value} + * field. + * + * @return true if the value parameter and the + * {@link #value} field match and the {@link #positive} field is + * true or if the values do not match and the + * {@link #positive} field is false. + */ + protected boolean match(String value) { + return positive == this.value.equals(value); + } + + /** + * Matches the entry's value to the the token or etag. Depending on the + * concrete implementation, only one of the parameters may be evaluated + * while the other may be ignored. + *

+ * Implementing METHODS may call the helper method {@link #match(String)} + * for the actual matching. + * + * @param token The token value to compare + * @param etag The etag value to compare + * + * @return true if the token/etag matches the IfList + * entry. + */ + public abstract boolean match(String token, String etag); + + /** + * Returns a short type name for the implementation. This method is + * used by the {@link #toString} method to build the string representation + * if the instance. + * + * @return The type name of the implementation. + */ + protected abstract String getType(); + + /** + * Returns the value of this entry. + * + * @return the value + */ + protected String getValue() { + return value; + } + + /** + * Returns the String representation of this entry. This method uses the + * {@link #getType} to build the string representation. + * + * @return the String representation of this entry. + */ + @Override + public String toString() { + if (stringValue == null) { + stringValue = getType() + ": " + (positive?"":"!") + value; + } + return stringValue; + } + } + + /** + * The IfListEntryToken extends the {@link IfListEntry} + * abstract class to represent an entry for token matching. + */ + private static class IfListEntryToken extends IfListEntry { + + /** + * Creates a token matching entry. + * + * @param token The token value pertinent to this instance. + * @param positive true if this is a positive match entry. + */ + IfListEntryToken(String token, boolean positive) { + super(token, positive); + } + + /** + * Matches the token parameter to the stored token value and returns + * true if the values match and if the match is positive. + * true is also returned for negative matches if the values + * do not match. + * + * @param token The token value to compare + * @param etag The etag value to compare, which is ignored in this + * implementation. + * + * @return true if the token matches the IfList + * entry's token value. + */ + @Override + public boolean match(String token, String etag) { + return super.match(token); + } + + /** + * Returns the type name of this implementation, which is fixed to + * be Token. + * + * @return The fixed string Token as the type name. + */ + @Override + protected String getType() { + return "Token"; + } + } + + /** + * The IfListEntryToken extends the {@link IfListEntry} + * abstract class to represent an entry for etag matching. + */ + private static class IfListEntryEtag extends IfListEntry { + + /** + * Creates an etag matching entry. + * + * @param etag The etag value pertinent to this instance. + * @param positive true if this is a positive match entry. + */ + IfListEntryEtag(String etag, boolean positive) { + super(etag, positive); + } + + /** + * Matches the etag parameter to the stored etag value and returns + * true if the values match and if the match is positive. + * true is also returned for negative matches if the values + * do not match. + * + * @param token The token value to compare, which is ignored in this + * implementation. + * @param etag The etag value to compare + * + * @return true if the etag matches the IfList + * entry's etag value. + */ + @Override + public boolean match(String token, String etag) { + return super.match(etag); + } + + /** + * Returns the type name of this implementation, which is fixed to + * be ETag. + * + * @return The fixed string ETag as the type name. + */ + @Override + protected String getType() { + return "ETag"; + } + } + + /** + * The IfList class extends the ArrayList class + * with the limitation to only support adding {@link IfListEntry} objects + * and adding a {@link #match} method. + *

+ * This class is a container for data contained in the If + * production IfList + *

+         IfList = { [ "Not" ] ( ("<" Word ">" ) | ( "[" Word "]" ) ) } .
+     * 
+ *

+ */ + private static class IfList extends ArrayList { + + /** + * Adds the {@link IfListEntry} at the end of the list. + * + * @param entry The {@link IfListEntry} to add to the list + * + * @return true (as per the general contract of Collection.add). + */ + @Override + public boolean add(IfListEntry entry) { + return super.add(entry); + } + + /** + * Adds the {@link IfListEntry} at the indicated position of the list. + * + * @param index + * @param entry + * + * @throws IndexOutOfBoundsException if index is out of range + * (index < 0 || index > size()). + */ + @Override + public void add(int index, IfListEntry entry) { + super.add(index, entry); + } + + /** + * Returns true if all {@link IfListEntry} objects in the + * list match the given token and etag. If the list is entry, it is + * considered to match the token and etag. + * + * @param token The token to compare. + * @param etag The etag to compare. + * + * @return true if all entries in the list match the + * given tag and token. + */ + public boolean match(String token, String etag) { + log.debug("match: Trying to match token="+token+", etag="+etag); + for (int i=0; i < size(); i++) { + IfListEntry ile = get(i); + if (!ile.match(token, etag)) { + log.debug("match: Entry "+i+"-"+ile+" does not match"); + return false; + } + } + // invariant: all entries matched + + return true; + } + } + + /** + * The IfHeaderInterface interface abstracts away the difference of + * tagged and untagged If header lists. The single method provided + * by this interface is to check whether a request may be applied to a + * resource with given token and etag. + */ + private static interface IfHeaderInterface { + + /** + * Matches the resource, token, and etag against this + * IfHeaderInterface instance. + * + * @param resource The resource to match this instance against. This + * must be absolute URI of the resource as defined in Section 3 + * (URI Syntactic Components) of RFC 2396 Uniform Resource + * Identifiers (URI): Generic Syntax. + * @param token The resource's lock token to match + * @param etag The resource's etag to match + * + * @return true if the header matches the resource with + * token and etag, which means that the request is applicable + * to the resource according to the If header. + */ + public boolean matches(String resource, String token, String etag); + } + + /** + * The IfHeaderList class implements the {@link IfHeaderInterface} + * interface to support untagged lists of {@link IfList}s. This class + * implements the data container for the production : + *

+         Untagged = { "(" IfList ")" } .
+     * 
+ */ + private static class IfHeaderList extends ArrayList implements IfHeaderInterface { + + /** + * Matches a list of {@link IfList}s against the token and etag. If any of + * the {@link IfList}s matches, the method returns true. + * On the other hand false is only returned if non of the + * {@link IfList}s match. + * + * @param resource The resource to match, which is ignored by this + * implementation. A value of null is therefor + * acceptable. + * @param token The token to compare. + * @param etag The ETag value to compare. + * + * @return True if any of the {@link IfList}s matches the token + * and etag, else false is returned. + */ + public boolean matches(String resource, String token, String etag) { + log.debug("matches: Trying to match token="+token+", etag="+etag); + + for (IfList il : this) { + if (il.match(token, etag)) { + log.debug("matches: Found match with " + il); + return true; + } + } + // invariant: no match found + + return false; + } + } + + /** + * The IfHeaderMap class implements the {@link IfHeaderInterface} + * interface to support tagged lists of {@link IfList}s. This class + * implements the data container for the production : + *
+         Tagged = { "<" Word ">" "(" IfList ")" } .
+     * 
+ */ + private static class IfHeaderMap extends HashMap implements IfHeaderInterface { + + /** + * Matches the token and etag for the given resource. If the resource is + * not mentioned in the header, a match is assumed and true + * is returned in this case. + * + * @param resource The absolute URI of the resource for which to find + * a match. + * @param token The token to compare. + * @param etag The etag to compare. + * + * @return true if either no entry exists for the resource + * or if the entry for the resource matches the token and etag. + */ + public boolean matches(String resource, String token, String etag) { + log.debug("matches: Trying to match resource="+resource+", token="+token+","+etag); + + IfHeaderList list = get(resource); + if (list == null) { + log.debug("matches: No entry for tag "+resource+", assuming match"); + return true; + } else { + return list.matches(resource, token, etag); + } + } + } +} Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/header/IfHeader.java ___________________________________________________________________ Added: svn Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/header/LabelHeader.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/header/LabelHeader.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/header/LabelHeader.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.webdav.header; + +import org.apache.jackrabbit.webdav.WebdavRequest; +import org.apache.jackrabbit.webdav.util.EncodeUtil; +import org.apache.jackrabbit.webdav.version.DeltaVConstants; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * LabelHeader... + */ +public class LabelHeader implements Header { + + private static Logger log = LoggerFactory.getLogger(LabelHeader.class); + + private final String label; + + public LabelHeader(String label) { + if (label == null) { + throw new IllegalArgumentException("null is not a valid label."); + } + this.label = label; + } + + public String getLabel() { + return label; + } + + public String getHeaderName() { + return DeltaVConstants.HEADER_LABEL; + } + + public String getHeaderValue() { + return EncodeUtil.escape(label); + } + + public static LabelHeader parse(WebdavRequest request) { + String hv = request.getHeader(DeltaVConstants.HEADER_LABEL); + if (hv == null) { + return null; + } else { + return new LabelHeader(EncodeUtil.unescape(hv)); + } + } +} \ No newline at end of file Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/header/LabelHeader.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-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/header/OverwriteHeader.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/header/OverwriteHeader.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/header/OverwriteHeader.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.webdav.header; + +import org.apache.jackrabbit.webdav.DavConstants; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.servlet.http.HttpServletRequest; + +/** + * OverwriteHeader... + */ +public class OverwriteHeader implements Header { + + private static Logger log = LoggerFactory.getLogger(OverwriteHeader.class); + + public static final String OVERWRITE_TRUE = "T"; + public static final String OVERWRITE_FALSE = "F"; + + /** + * Set 'doOverwrite' to true by default. See RFC 2518: + * "If the overwrite header is not included in a COPY or MOVE request then + * the resource MUST treat the request as if it has an overwrite header of + * value {@link #OVERWRITE_TRUE}". + */ + private final boolean doOverwrite; + + public OverwriteHeader(boolean doOverwrite) { + this.doOverwrite = doOverwrite; + } + + /** + * Create a new OverwriteHeader for the given request object. + * If the latter does not contain an "Overwrite" header field, the default + * applies, which is {@link #OVERWRITE_TRUE} according to RFC 2518. + * + * @param request + */ + public OverwriteHeader(HttpServletRequest request) { + String overwriteHeader = request.getHeader(DavConstants.HEADER_OVERWRITE); + if (overwriteHeader != null) { + doOverwrite = overwriteHeader.equalsIgnoreCase(OVERWRITE_TRUE); + } else { + // no Overwrite header -> default is 'true' + doOverwrite = true; + } + } + + public String getHeaderName() { + return DavConstants.HEADER_OVERWRITE; + } + + public String getHeaderValue() { + return (doOverwrite) ? OVERWRITE_TRUE : OVERWRITE_FALSE; + } + + public boolean isOverwrite() { + return doOverwrite; + } +} \ No newline at end of file Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/header/OverwriteHeader.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-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/header/PollTimeoutHeader.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/header/PollTimeoutHeader.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/header/PollTimeoutHeader.java (working copy) @@ -0,0 +1,52 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.jackrabbit.webdav.header; + +import org.apache.jackrabbit.webdav.observation.ObservationConstants; + +import javax.servlet.http.HttpServletRequest; + +/** + * PollTimeoutHeader implements a timeout header for subscription + * polling. + */ +public class PollTimeoutHeader extends TimeoutHeader { + + public PollTimeoutHeader(long timeout) { + super(timeout); + } + + @Override + public String getHeaderName() { + return ObservationConstants.HEADER_POLL_TIMEOUT; + } + + /** + * Parses the request timeout header and converts it into a new + * PollTimeoutHeader object.
The default value is used as + * fallback if the String is not parseable. + * + * @param request + * @param defaultValue + * @return a new PollTimeoutHeader object. + */ + public static PollTimeoutHeader parseHeader(HttpServletRequest request, long defaultValue) { + String timeoutStr = request.getHeader(ObservationConstants.HEADER_POLL_TIMEOUT); + long timeout = parse(timeoutStr, defaultValue); + return new PollTimeoutHeader(timeout); + } +} Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/header/PollTimeoutHeader.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/header/TimeoutHeader.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/header/TimeoutHeader.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/header/TimeoutHeader.java (working copy) @@ -0,0 +1,104 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.jackrabbit.webdav.header; + +import org.apache.jackrabbit.webdav.DavConstants; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.servlet.http.HttpServletRequest; + +/** + * TimeoutHeader... + */ +public class TimeoutHeader implements Header, DavConstants { + + private static Logger log = LoggerFactory.getLogger(TimeoutHeader.class); + + private final long timeout; + + public TimeoutHeader(long timeout) { + this.timeout = timeout; + } + + public String getHeaderName() { + return DavConstants.HEADER_TIMEOUT; + } + + public String getHeaderValue() { + if (timeout == INFINITE_TIMEOUT) { + return TIMEOUT_INFINITE; + } else { + return "Second-" + (timeout / 1000); + } + } + + public long getTimeout() { + return timeout; + } + + /** + * Parses the request timeout header and converts it into a new + * TimeoutHeader object.
The default value is used as + * fallback if the String is not parseable. + * + * @param request + * @param defaultValue + * @return a new TimeoutHeader object. + */ + public static TimeoutHeader parse(HttpServletRequest request, long defaultValue) { + String timeoutStr = request.getHeader(HEADER_TIMEOUT); + long timeout = parse(timeoutStr, defaultValue); + return new TimeoutHeader(timeout); + } + + /** + * Parses the given timeout String and converts the timeout value + * into a long indicating the number of milliseconds until expiration time + * is reached.
+ * NOTE: If the timeout String equals to {@link #TIMEOUT_INFINITE 'infinite'} + * {@link Integer#MAX_VALUE} is returned. If the Sting is invalid or is in an + * invalid format that cannot be parsed, the default value is returned. + * + * @param timeoutStr + * @param defaultValue + * @return long representing the timeout present in the header or the default + * value if the header is missing or could not be parsed. + */ + public static long parse(String timeoutStr, long defaultValue) { + long timeout = defaultValue; + if (timeoutStr != null && timeoutStr.length() > 0) { + int secondsInd = timeoutStr.indexOf("Second-"); + if (secondsInd >= 0) { + secondsInd += 7; // read over "Second-" + int i = secondsInd; + while (i < timeoutStr.length() && Character.isDigit(timeoutStr.charAt(i))) { + i++; + } + try { + timeout = 1000L * Long.parseLong(timeoutStr.substring(secondsInd, i)); + } catch (NumberFormatException ignore) { + // ignore and return 'undefined' timeout + log.error("Invalid timeout format: " + timeoutStr); + } + } else if (timeoutStr.equalsIgnoreCase(TIMEOUT_INFINITE)) { + timeout = INFINITE_TIMEOUT; + } + } + return timeout; + } +} \ No newline at end of file Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/header/TimeoutHeader.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-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/header/package-info.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/header/package-info.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/header/package-info.java (working copy) @@ -0,0 +1,18 @@ +/* + * 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. + */ +@org.osgi.annotation.versioning.Version("1.1.0") +package org.apache.jackrabbit.webdav.header; Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/header/package-info.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/io/InputContext.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/io/InputContext.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/io/InputContext.java (working copy) @@ -0,0 +1,78 @@ +/* + * 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.webdav.io; + +import java.io.InputStream; + +/** + * InputContext... + */ +public interface InputContext { + + /** + * Return true, if there are any data to be imported (and not only properties) + * + * @return + */ + public boolean hasStream(); + + /** + * Returns the input stream of the resource to import. + * + * @return the input stream. + */ + 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 -1 if the contentlength could not be + * determined. + * + * @return the content length + */ + public long getContentLength(); + + /** + * Return the content type or null + * + * @return + */ + public String getContentType(); + + /** + * Returns the value of the given property or null if this property does + * not exist. + * + * @param propertyName + * @return String property value or null + */ + public String getProperty(String propertyName); +} Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/io/InputContext.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 \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/io/InputContextImpl.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/io/InputContextImpl.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/io/InputContextImpl.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.webdav.io; + +import org.apache.jackrabbit.webdav.DavConstants; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.servlet.http.HttpServletRequest; +import java.io.InputStream; +import java.util.Date; + +/** + * InputContextImpl class encapsulates the InputStream + * and some header values as present in the POST, PUT or MKCOL request. + */ +public class InputContextImpl implements InputContext { + + private static Logger log = LoggerFactory.getLogger(InputContextImpl.class); + + private final HttpServletRequest request; + private final InputStream in; + + public InputContextImpl(HttpServletRequest request, InputStream in) { + if (request == null) { + throw new IllegalArgumentException("DavResource and Request must not be null."); + } + + this.request = request; + this.in = in; + } + + public boolean hasStream() { + return in != null; + } + + /** + * Returns the input stream of the resource to import. + * + * @return the input stream. + */ + public InputStream getInputStream() { + return in; + } + + public long getModificationTime() { + return new Date().getTime(); + } + + /** + * Returns the content language or null. + * + * @return contentLanguage + */ + public String getContentLanguage() { + return request.getHeader(DavConstants.HEADER_CONTENT_LANGUAGE); + } + + /** + * @return content length or -1 when unknown + */ + public long getContentLength() { + String length = request.getHeader(DavConstants.HEADER_CONTENT_LENGTH); + if (length == null) { + // header not present + return -1; + } else { + try { + return Long.parseLong(length); + } catch (NumberFormatException ex) { + log.error("broken Content-Length header: " + length); + return -1; + } + } + } + + public String getContentType() { + return request.getHeader(DavConstants.HEADER_CONTENT_TYPE); + } + + public String getProperty(String propertyName) { + return request.getHeader(propertyName); + } +} Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/io/InputContextImpl.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-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/io/OutputContext.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/io/OutputContext.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/io/OutputContext.java (working copy) @@ -0,0 +1,82 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.jackrabbit.webdav.io; + +import java.io.OutputStream; + +/** + * OutputContext... + */ +public interface OutputContext { + + /** + * Return true if the given export context can provide an output stream + */ + public boolean hasStream(); + + /** + * Return the output stream to be used for the export or null + * + * @return + */ + public OutputStream getOutputStream(); + + /** + * Sets the content language. + * + * @param contentLanguage + */ + public void setContentLanguage(String contentLanguage); + + /** + * Sets the length of the data. + * + * @param contentLength the content length + */ + public void setContentLength(long contentLength); + + /** + * Set the content type for the resource content + * + * @param contentType + */ + public void setContentType(String contentType); + + /** + * 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); + + /** + * Allows to set additional properties that are not covered by an extra setter + * method. + * + * @param propertyName + * @param propertyValue + */ + public void setProperty(String propertyName, String propertyValue); +} Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/io/OutputContext.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-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/io/OutputContextImpl.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/io/OutputContextImpl.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/io/OutputContextImpl.java (working copy) @@ -0,0 +1,88 @@ +/* + * 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.webdav.io; + +import org.apache.jackrabbit.webdav.DavConstants; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.servlet.http.HttpServletResponse; +import java.io.OutputStream; + +/** + * OutputContextImpl... + */ +public class OutputContextImpl implements OutputContext { + + private static Logger log = LoggerFactory.getLogger(OutputContextImpl.class); + + private final HttpServletResponse response; + private final OutputStream out; + + public OutputContextImpl(HttpServletResponse response, OutputStream out) { + if (response == null) { + throw new IllegalArgumentException("Response must not be null."); + } + + this.response = response; + this.out = out; + } + + public boolean hasStream() { + return out != null; + } + + public OutputStream getOutputStream() { + return out; + } + + public void setContentLanguage(String contentLanguage) { + if (contentLanguage != null) { + response.setHeader(DavConstants.HEADER_CONTENT_LANGUAGE, contentLanguage); + } + } + + public void setContentLength(long contentLength) { + if (contentLength >= 0) { + response.setContentLengthLong(contentLength); + } // else: negative content length -> ignore. + } + + public void setContentType(String contentType) { + if (contentType != null) { + response.setContentType(contentType); + } + } + + public void setModificationTime(long modificationTime) { + if (modificationTime >= 0) { + response.addDateHeader(DavConstants.HEADER_LAST_MODIFIED, modificationTime); + } + } + + public void setETag(String etag) { + if (etag != null) { + response.setHeader(DavConstants.HEADER_ETAG, etag); + } + } + + public void setProperty(String propertyName, String propertyValue) { + if (propertyName != null && propertyValue != null) { + response.setHeader(propertyName, propertyValue); + } + } +} \ No newline at end of file Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/io/OutputContextImpl.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-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/io/package-info.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/io/package-info.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/io/package-info.java (working copy) @@ -0,0 +1,18 @@ +/* + * 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. + */ +@org.osgi.annotation.versioning.Version("1.0.1") +package org.apache.jackrabbit.webdav.io; Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/io/package-info.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/lock/AbstractActiveLock.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/lock/AbstractActiveLock.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/lock/AbstractActiveLock.java (working copy) @@ -0,0 +1,86 @@ +/* + * 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.webdav.lock; + +import org.apache.jackrabbit.webdav.DavConstants; +import org.apache.jackrabbit.webdav.xml.DomUtil; +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +/** + * AbstractActiveLock... + */ +public abstract class AbstractActiveLock implements ActiveLock, DavConstants { + + private String lockroot; + + /** + * @see ActiveLock#getLockroot() + */ + public String getLockroot() { + return lockroot; + } + + /** + * @see ActiveLock#setLockroot(String) + */ + public void setLockroot(String lockroot) { + this.lockroot = lockroot; + } + + /** + * Returns the default Xml representation of the 'activelock' element + * as defined by RFC 4918. + * + * @return Xml representation + * @param document + */ + public Element toXml(Document document) { + Element activeLock = DomUtil.createElement(document, XML_ACTIVELOCK, NAMESPACE); + + // lockscope property + activeLock.appendChild(getScope().toXml(document)); + // locktype property + activeLock.appendChild(getType().toXml(document)); + // depth + activeLock.appendChild(DomUtil.depthToXml(isDeep(), document)); + // timeout + long timeout = getTimeout(); + if (!isExpired() && timeout != UNDEFINED_TIMEOUT) { + activeLock.appendChild(DomUtil.timeoutToXml(timeout, document)); + } + + // owner + if (getOwner() != null) { + DomUtil.addChildElement(activeLock, XML_OWNER, NAMESPACE, getOwner()); + } + + // locktoken + if (getToken() != null) { + Element lToken = DomUtil.addChildElement(activeLock, XML_LOCKTOKEN, NAMESPACE); + lToken.appendChild(DomUtil.hrefToXml(getToken(), document)); + } + + // lock root + if (getLockroot() != null) { + Element lroot = DomUtil.addChildElement(activeLock, XML_LOCKROOT, NAMESPACE); + lroot.appendChild(DomUtil.hrefToXml(getLockroot(), document)); + } + return activeLock; + } + +} \ No newline at end of file Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/lock/AbstractActiveLock.java ___________________________________________________________________ Added: svn Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/lock/AbstractLockEntry.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/lock/AbstractLockEntry.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/lock/AbstractLockEntry.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.webdav.lock; + +import org.apache.jackrabbit.webdav.DavConstants; +import org.apache.jackrabbit.webdav.xml.DomUtil; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +/** + * AbstractLockEntry provides the generic {@link org.apache.jackrabbit.webdav.xml.XmlSerializable#toXml} method. + */ +public abstract class AbstractLockEntry implements LockEntry, DavConstants { + + private static Logger log = LoggerFactory.getLogger(AbstractLockEntry.class); + + /** + * Returns the Xml representation of this LockEntry. + * + * @return Xml representation + * @see org.apache.jackrabbit.webdav.xml.XmlSerializable#toXml(Document) + * @param document + */ + public Element toXml(Document document) { + Element entry = DomUtil.createElement(document, XML_LOCKENTRY, NAMESPACE); + entry.appendChild(getScope().toXml(document)); + entry.appendChild(getType().toXml(document)); + return entry; + } + +} \ No newline at end of file Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/lock/AbstractLockEntry.java ___________________________________________________________________ Added: svn Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/lock/ActiveLock.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/lock/ActiveLock.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/lock/ActiveLock.java (working copy) @@ -0,0 +1,124 @@ +/* + * 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.webdav.lock; + +import org.apache.jackrabbit.webdav.xml.XmlSerializable; + +/** + * ActiveLock encapsulates the lock information for a + * {@link org.apache.jackrabbit.webdav.DavResource}. + */ +public interface ActiveLock extends XmlSerializable { + + /** + * Return true, if the given token matches the lock token present in this + * lock thus indicating that any lock relevant operation should not fail + * due to a lock. + * + * @param lockToken to be checked + * @return true if the given lock token matches. + */ + public boolean isLockedByToken(String lockToken); + + /** + * Returns true, if this lock is already expired. + * + * @return true if the lock is expired + */ + public boolean isExpired(); + + /** + * Return the lock token. + * + * @return token string representing the lock token. + */ + public String getToken(); + + /** + * Return the name (or id) of the lock owner. + * + * @return name (or id) of the lock owner. + */ + public String getOwner(); + + /** + * Set the name (or id) of the lock owner + * + * @param owner + */ + public void setOwner(String owner); + + /** + * Return the number of milliseconds the lock will live until it is expired + * or -1 if the timeout is not available (or the client is not allowed + * to retrieve it). + * + * @return number of milliseconds. + */ + public long getTimeout(); + + /** + * Defines the number of milliseconds until the timeout is reached. + * + * @param timeout + */ + public void setTimeout(long timeout); + + /** + * Return true if the lock is deep. + * + * @return true if the lock is deep. + */ + public boolean isDeep(); + + /** + * Set the lock deepness. + * + * @param isDeep + */ + public void setIsDeep(boolean isDeep); + + /** + * Returns the lockroot. + * + * @return lockroot + * @see RFC 4918 + */ + public String getLockroot(); + + /** + * Set the lockroot. + * + * @param lockroot + * @see RFC 4918 + */ + public void setLockroot(String lockroot); + + /** + * Return the type of this lock. + * + * @return type + */ + public Type getType(); + + /** + * Return the scope of this lock. + * + * @return scope + */ + public Scope getScope(); +} Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/lock/ActiveLock.java ___________________________________________________________________ Added: svn Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/lock/DefaultActiveLock.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/lock/DefaultActiveLock.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/lock/DefaultActiveLock.java (working copy) @@ -0,0 +1,147 @@ +/* + * 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.webdav.lock; + +import java.util.UUID; + +import org.apache.jackrabbit.webdav.DavConstants; + +/** + * DefaultActiveLock implements the ActiveLock interface + * and represents an exclusive write lock with a random uuid lock token. + * Lock owner, timeout and depth is retrieved from the {@link LockInfo} object + * passed in the constructor. If the lockinfo is null, the following default + * values are set:
+ * - timeout is set to infinity.
+ * - isDeep is set to true.
+ * 
+ */ +public class DefaultActiveLock extends AbstractActiveLock { + + private final String token = DavConstants.OPAQUE_LOCK_TOKEN_PREFIX + UUID.randomUUID(); + private String owner; + private boolean isDeep = true; // deep by default + private long expirationTime = DavConstants.INFINITE_TIMEOUT; // never expires by default; + + /** + * Create a new DefaultActiveLock with default values. + */ + public DefaultActiveLock() { + } + + /** + * Create a new lock + * + * @param lockInfo + * @throws IllegalArgumentException if either scope or type is invalid. + */ + public DefaultActiveLock(LockInfo lockInfo) { + if (lockInfo != null) { + if (!(Type.WRITE.equals(lockInfo.getType()) && Scope.EXCLUSIVE.equals(lockInfo.getScope()))) { + throw new IllegalArgumentException("Only 'exclusive write' lock is allowed scope/type pair."); + } + owner = lockInfo.getOwner(); + isDeep = lockInfo.isDeep(); + setTimeout(lockInfo.getTimeout()); + } + } + + /** + * @see ActiveLock#isLockedByToken(String) + */ + public boolean isLockedByToken(String lockToken) { + return (token != null) && token.equals(lockToken); + } + + /** + * @see ActiveLock#isExpired() + */ + public boolean isExpired() { + return System.currentTimeMillis() > expirationTime; + } + + /** + * @see ActiveLock#getToken() + */ + public String getToken() { + return token; + } + + /** + * @see ActiveLock#getOwner() + */ + public String getOwner() { + return owner; + } + + /** + * @see ActiveLock#setOwner(String) + */ + public void setOwner(String owner) { + this.owner = owner; + } + + /** + * @see ActiveLock#getTimeout() + */ + public long getTimeout() { + return expirationTime - System.currentTimeMillis(); + } + + /** + * @see ActiveLock#setTimeout(long) + */ + public void setTimeout(long timeout) { + if (timeout > 0) { + expirationTime = System.currentTimeMillis() + timeout; + } + } + + /** + * @see ActiveLock#isDeep() + */ + public boolean isDeep() { + return isDeep; + } + + /** + * @see ActiveLock#setIsDeep(boolean) + */ + public void setIsDeep(boolean isDeep) { + this.isDeep = isDeep; + } + + /** + * This is always a write lock. + * + * @return the lock type + * @see Type#WRITE + */ + public Type getType() { + return Type.WRITE; + } + + /** + * This is always an exclusive lock. + * + * @return the lock scope. + * @see Scope#EXCLUSIVE + */ + public Scope getScope() { + return Scope.EXCLUSIVE; + } +} Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/lock/DefaultActiveLock.java ___________________________________________________________________ Added: svn Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/lock/LockDiscovery.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/lock/LockDiscovery.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/lock/LockDiscovery.java (working copy) @@ -0,0 +1,233 @@ +/* + * 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.webdav.lock; + +import org.apache.jackrabbit.webdav.property.AbstractDavProperty; +import org.apache.jackrabbit.webdav.property.DavPropertyName; +import org.apache.jackrabbit.webdav.xml.DomUtil; +import org.apache.jackrabbit.webdav.xml.ElementIterator; +import org.apache.jackrabbit.webdav.header.TimeoutHeader; +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +import java.util.ArrayList; +import java.util.List; + +/** + * The LockDiscovery class encapsulates the webdav lock discovery + * property that is sent in the request body (PROPFIND and LOCK) and received + * in a LOCK response body. + */ +public class LockDiscovery extends AbstractDavProperty> { + + /** + * Listing of existing locks applied to the resource this discovery was + * requested for. Each entry reveals, who has a lock, what type of lock he has, + * the timeout type and the time remaining on the timeout, and the lock-type. + * NOTE, that any of the information listed may be not available for the + * server is free to withhold any or all of this information. + */ + private List activeLocks = new ArrayList(); + + /** + * Creates a new empty LockDiscovery property + */ + public LockDiscovery() { + super(DavPropertyName.LOCKDISCOVERY, false); + } + + /** + * Create a new LockDiscovery property + * + * @param lock + */ + public LockDiscovery(ActiveLock lock) { + super(DavPropertyName.LOCKDISCOVERY, false); + addActiveLock(lock); + } + + /** + * Create a new LockDiscovery property + * + * @param locks + */ + public LockDiscovery(ActiveLock[] locks) { + super(DavPropertyName.LOCKDISCOVERY, false); + for (ActiveLock lock : locks) { + addActiveLock(lock); + } + } + + private void addActiveLock(ActiveLock lock) { + if (lock != null) { + activeLocks.add(lock); + } + } + + /** + * Returns the list of active locks. + * + * @return list of active locks + * @see org.apache.jackrabbit.webdav.property.DavProperty#getValue() + */ + public List getValue() { + return activeLocks; + } + + /** + * Creates a <lockdiscovery> element in response + * to a LOCK request or to the lockdiscovery property of a PROPFIND request.
+ * NOTE: if the {@link #activeLocks} list is empty an empty lockdiscovery + * property is created ( <lockdiscovery/>) + * @return A <lockdiscovery> element. + * @param document + */ + @Override + public Element toXml(Document document) { + Element lockdiscovery = getName().toXml(document); + for (ActiveLock lock : activeLocks) { + lockdiscovery.appendChild(lock.toXml(document)); + } + return lockdiscovery; + } + + //---------------------------------------------------< factory from xml >--- + /** + * Builds a new LockDiscovery object from the given xml element. + * + * @param lockDiscoveryElement + * @return + * @throws IllegalArgumentException if the given xml element is not a + * DAV:lockdiscovery element. + */ + public static LockDiscovery createFromXml(Element lockDiscoveryElement) { + if (!DomUtil.matches(lockDiscoveryElement, PROPERTY_LOCKDISCOVERY, NAMESPACE)) { + throw new IllegalArgumentException("DAV:lockdiscovery element expected."); + } + + List activeLocks = new ArrayList(); + ElementIterator it = DomUtil.getChildren(lockDiscoveryElement, XML_ACTIVELOCK, NAMESPACE); + while (it.hasNext()) { + Element al = it.nextElement(); + activeLocks.add(new ALockImpl(al)); + } + + return new LockDiscovery(activeLocks.toArray(new ActiveLock[activeLocks.size()])); + } + + //------< inner class >----------------------------------------------------- + /** + * Simple implementation of ActiveLock interface, that retrieves + * the values from the DAV:activelock XML element.
+ * Note, that all set-methods as well as {@link #isExpired()} are not + * implemented. + */ + private static class ALockImpl implements ActiveLock { + + private final Element alElement; + + private ALockImpl(Element alElement) { + if (!DomUtil.matches(alElement, XML_ACTIVELOCK, NAMESPACE)) { + throw new IllegalArgumentException("DAV:activelock element expected."); + } + this.alElement = alElement; + } + + public boolean isLockedByToken(String lockToken) { + String lt = getToken(); + if (lt == null) { + return false; + } else { + return lt.equals(lockToken); + } + } + + public boolean isExpired() { + throw new UnsupportedOperationException("Not implemented"); + } + + public String getToken() { + Element ltEl = DomUtil.getChildElement(alElement, XML_LOCKTOKEN, NAMESPACE); + if (ltEl != null) { + return DomUtil.getChildText(ltEl, XML_HREF, NAMESPACE); + } + return null; + } + + public String getOwner() { + String owner = null; + Element ow = DomUtil.getChildElement(alElement, XML_OWNER, NAMESPACE); + if (ow != null) { + if (DomUtil.hasChildElement(ow, XML_HREF, NAMESPACE)) { + owner = DomUtil.getChildTextTrim(ow, XML_HREF, NAMESPACE); + } else { + owner = DomUtil.getTextTrim(ow); + } + } + return owner; + } + + public void setOwner(String owner) { + throw new UnsupportedOperationException("Not implemented"); + } + + public long getTimeout() { + // get timeout string. if no DAV:timeout element is present, + // 't' will be 'null' and the undefined timeout will be returned. + String t = DomUtil.getChildTextTrim(alElement, XML_TIMEOUT, NAMESPACE); + return TimeoutHeader.parse(t, UNDEFINED_TIMEOUT); + } + + public void setTimeout(long timeout) { + throw new UnsupportedOperationException("Not implemented"); + } + + public boolean isDeep() { + String depth = DomUtil.getChildTextTrim(alElement, XML_DEPTH, NAMESPACE); + return DEPTH_INFINITY_S.equalsIgnoreCase(depth); + } + + public void setIsDeep(boolean isDeep) { + throw new UnsupportedOperationException("Not implemented"); + } + + public String getLockroot() { + Element root = DomUtil.getChildElement(alElement, XML_LOCKROOT, NAMESPACE); + if (root != null) { + return DomUtil.getChildTextTrim(root, XML_HREF, NAMESPACE); + } + // no lockroot element + return null; + } + + public void setLockroot(String lockroot) { + throw new UnsupportedOperationException("Not implemented"); + } + + public Type getType() { + return Type.createFromXml(DomUtil.getChildElement(alElement, XML_LOCKTYPE, NAMESPACE)); + } + + public Scope getScope() { + return Scope.createFromXml(DomUtil.getChildElement(alElement, XML_LOCKSCOPE, NAMESPACE)); + } + + public Element toXml(Document document) { + return (Element) document.importNode(alElement, true); + } + } +} Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/lock/LockDiscovery.java ___________________________________________________________________ Added: svn Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/lock/LockEntry.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/lock/LockEntry.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/lock/LockEntry.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.webdav.lock; + +import org.apache.jackrabbit.webdav.xml.XmlSerializable; + +/** + * LockEntry... + */ +public interface LockEntry extends XmlSerializable { + + /** + * Returns the type of this lock entry + * + * @return type of this lock entry. + */ + public Type getType(); + + /** + * Returns the scope of this lock entry. + * + * @return scope of this lock entry. + */ + public Scope getScope(); +} \ No newline at end of file Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/lock/LockEntry.java ___________________________________________________________________ Added: svn Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/lock/LockInfo.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/lock/LockInfo.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/lock/LockInfo.java (working copy) @@ -0,0 +1,237 @@ +/* + * 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.webdav.lock; + +import org.apache.jackrabbit.webdav.DavConstants; +import org.apache.jackrabbit.webdav.DavException; +import org.apache.jackrabbit.webdav.DavServletResponse; +import org.apache.jackrabbit.webdav.xml.DomUtil; +import org.apache.jackrabbit.webdav.xml.ElementIterator; +import org.apache.jackrabbit.webdav.xml.XmlSerializable; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +/** + * LockInfo is a simple utility class encapsulating the information + * passed with a LOCK request. It combines both the request body (which if present + * is required to by a 'lockinfo' Xml element) and the lock relevant request + * headers '{@link DavConstants#HEADER_TIMEOUT Timeout}' and + * '{@link DavConstants#HEADER_DEPTH Depth}'.
+ * Note that is class is not intended to perform any validation of the information + * given, since this left to those objects responsible for the lock creation + * on the requested resource. + */ +public class LockInfo implements DavConstants, XmlSerializable { + + private static Logger log = LoggerFactory.getLogger(LockInfo.class); + + private Type type; + private Scope scope; + private String owner; + private boolean isDeep; + private long timeout; + + private boolean isRefreshLock; + + /** + * Create a new LockInfo used for refreshing an existing lock. + * + * @param timeout + */ + public LockInfo(long timeout) { + this.timeout = (timeout > 0) ? timeout : INFINITE_TIMEOUT; + this.isRefreshLock = true; + } + + /** + * Create a new LockInfo + * + * @param scope + * @param type + * @param owner + * @param timeout + * @param isDeep + */ + public LockInfo(Scope scope, Type type, String owner, long timeout, boolean isDeep) { + this.timeout = (timeout > 0) ? timeout : INFINITE_TIMEOUT; + this.isDeep = isDeep; + + if (scope == null || type == null) { + this.isRefreshLock = true; + } else { + this.scope = scope; + this.type = type; + this.owner = owner; + } + } + + /** + * Create a new LockInfo object from the given information. If + * liElement is null this lockinfo is assumed to + * be issued from a 'Refresh Lock' request. + * + * @param liElement 'lockinfo' element present in the request body of a LOCK request + * or null if the request was intended to refresh an existing lock. + * @param timeout Requested timespan until the lock should expire. A LOCK + * request MUST contain a '{@link DavConstants#HEADER_TIMEOUT Timeout}' + * according to RFC 2518. + * @param isDeep boolean value indicating whether the lock should be applied + * with depth infinity or only to the requested resource. + * @throws DavException if the liElement is not + * null but does not start with an 'lockinfo' element. + */ + public LockInfo(Element liElement, long timeout, boolean isDeep) throws DavException { + this.timeout = (timeout > 0) ? timeout : INFINITE_TIMEOUT; + this.isDeep = isDeep; + + if (liElement != null) { + if (!DomUtil.matches(liElement, XML_LOCKINFO, NAMESPACE)) { + log.warn("'DAV:lockinfo' element expected."); + throw new DavException(DavServletResponse.SC_BAD_REQUEST); + } + + ElementIterator it = DomUtil.getChildren(liElement); + while (it.hasNext()) { + Element child = it.nextElement(); + String childName = child.getLocalName(); + if (XML_LOCKTYPE.equals(childName)) { + type = Type.createFromXml(child); + } else if (XML_LOCKSCOPE.equals(childName)) { + scope = Scope.createFromXml(child); + } else if (XML_OWNER.equals(childName)) { + // first try if 'owner' is inside a href element + owner = DomUtil.getChildTextTrim(child, XML_HREF, NAMESPACE); + if (owner==null) { + // otherwise: assume owner is a simple text element + owner = DomUtil.getTextTrim(child); + } + } + } + isRefreshLock = false; + } else { + isRefreshLock = true; + } + } + + /** + * Returns the lock type or null if no 'lockinfo' element was + * passed to the constructor or did not contain an 'type' element and the + * type has not been set otherwise. + * + * @return type or null + */ + public Type getType() { + return type; + } + + /** + * Set the lock type. + * + * @param type + */ + public void setType(Type type) { + this.type = type; + } + + /** + * Return the lock scope or null if no 'lockinfo' element was + * passed to the constructor or did not contain an 'scope' element and the + * scope has not been set otherwise. + * + * @return scope or null + */ + public Scope getScope() { + return scope; + } + + /** + * Set the lock scope. + * + * @param scope + */ + public void setScope(Scope scope) { + this.scope = scope; + } + + /** + * Return the owner indicated by the corresponding child element from the + * 'lockinfo' element or null if no 'lockinfo' element was + * passed to the constructor or did not contain an 'owner' element. + * + * @return owner or null + */ + public String getOwner() { + return owner; + } + + /** + * Returns true if the lock must be applied with depth infinity. + * + * @return true if a deep lock must be created. + */ + public boolean isDeep() { + return isDeep; + } + + /** + * Returns the time until the lock is requested to expire. + * + * @return time until the lock should expire. + */ + public long getTimeout() { + return timeout; + } + + /** + * Returns true if this LockInfo was created for a LOCK + * request intended to refresh an existing lock rather than creating a + * new one. + * + * @return true if the corresponding LOCK request was intended to refresh + * an existing lock. + */ + public boolean isRefreshLock() { + return isRefreshLock; + } + + /** + * Returns the xml representation of this lock info.
+ * NOTE however, that the depth and the timeout are not included + * in the xml. They will be passed to the server using the corresponding + * request headers. + * + * @param document + * @return xml representation of this lock info. + * @see org.apache.jackrabbit.webdav.xml.XmlSerializable#toXml(Document) + */ + public Element toXml(Document document) { + if (isRefreshLock) { + return null; + } else { + Element lockInfo = DomUtil.createElement(document, XML_LOCKINFO, NAMESPACE); + lockInfo.appendChild(scope.toXml(document)); + lockInfo.appendChild(type.toXml(document)); + if (owner != null) { + DomUtil.addChildElement(lockInfo, XML_OWNER, NAMESPACE, owner); + } + return lockInfo; + } + } + +} \ No newline at end of file Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/lock/LockInfo.java ___________________________________________________________________ Added: svn Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/lock/LockManager.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/lock/LockManager.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/lock/LockManager.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.webdav.lock; + +import org.apache.jackrabbit.webdav.DavException; +import org.apache.jackrabbit.webdav.DavResource; + +/** + * The LockManager interface. + */ +public interface LockManager { + + /** + * Create a new lock for the given {@link org.apache.jackrabbit.webdav.DavResource resource}. + * + * @param lockInfo + * @param resource + * @return + * @throws DavException + */ + public ActiveLock createLock(LockInfo lockInfo, DavResource resource) + throws DavException; + + /** + * Refresh the lock identified by the given lockToken and initially created + * on the specified resource. The update information can be retrieved from + * the lockInfo object passes. + * + * @param lockInfo + * @param lockToken + * @param resource + * @return + * @throws DavException + */ + public ActiveLock refreshLock(LockInfo lockInfo, String lockToken, DavResource resource) + throws DavException; + + /** + * Release the lock identified by the given lockToken and initially created + * on the specified resource. + * + * @param lockToken + * @param resource + * @throws DavException + */ + public void releaseLock(String lockToken, DavResource resource) + throws DavException; + + /** + * Retrieve the lock with the given type and scope that is applied to the + * given resource. The lock may be either initially created on this resource + * or might be inherited from an ancestor resource that hold a deep lock. + * If no such lock applies to the given resource null must be + * returned. + * + * @param type + * @param scope + * @param resource + * @return lock with the given type and scope applied to the resource or + * null if no lock applies. + */ + public ActiveLock getLock(Type type, Scope scope, DavResource resource); + + /** + * Returns true, if the the manager contains a lock for the given + * resource, that is hold by the specified token. + * + * @param lockToken + * @param resource + * @return true if the resource is locked by the specified token. + */ + public boolean hasLock(String lockToken, DavResource resource); +} \ No newline at end of file Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/lock/LockManager.java ___________________________________________________________________ Added: svn Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/lock/Scope.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/lock/Scope.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/lock/Scope.java (working copy) @@ -0,0 +1,122 @@ +/* + * 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.webdav.lock; + +import org.apache.jackrabbit.webdav.DavConstants; +import org.apache.jackrabbit.webdav.xml.DomUtil; +import org.apache.jackrabbit.webdav.xml.Namespace; +import org.apache.jackrabbit.webdav.xml.XmlSerializable; +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +import java.util.HashMap; +import java.util.Map; + +/** + * The Scope class abstracts the lock scope as defined by RFC 2518. + */ +public class Scope implements XmlSerializable { + + private static final Map scopes = new HashMap(); + + public static final Scope EXCLUSIVE = Scope.create(DavConstants.XML_EXCLUSIVE, DavConstants.NAMESPACE); + public static final Scope SHARED = Scope.create(DavConstants.XML_SHARED, DavConstants.NAMESPACE); + + private final String localName; + private final Namespace namespace; + + /** + * Private constructor + * + * @param localName + * @param namespace + */ + private Scope(String localName, Namespace namespace) { + this.localName = localName; + this.namespace = namespace; + } + + /** + * Return the Xml representation of the lock scope object as present in + * the LOCK request and response body and in the {@link LockDiscovery}. + * + * @return Xml representation + * @see org.apache.jackrabbit.webdav.xml.XmlSerializable#toXml(Document) + */ + public Element toXml(Document document) { + Element lockScope = DomUtil.createElement(document, DavConstants.XML_LOCKSCOPE, DavConstants.NAMESPACE); + DomUtil.addChildElement(lockScope, localName, namespace); + return lockScope; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + localName.hashCode(); + result = prime * result + namespace.hashCode(); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } else if (obj instanceof Scope) { + Scope other = (Scope) obj; + return localName.equals(other.localName) && namespace.equals(other.namespace); + } else { + return false; + } + } + + /** + * Create a Scope object from the given Xml element. + * + * @param lockScope + * @return Scope object. + */ + public static Scope createFromXml(Element lockScope) { + if (lockScope != null && DavConstants.XML_LOCKSCOPE.equals(lockScope.getLocalName())) { + // we have the parent element and must retrieve the scope first + lockScope = DomUtil.getFirstChildElement(lockScope); + } + if (lockScope == null) { + throw new IllegalArgumentException("'null' is not a valid lock scope entry."); + } + Namespace namespace = Namespace.getNamespace(lockScope.getPrefix(), lockScope.getNamespaceURI()); + return create(lockScope.getLocalName(), namespace); + } + + /** + * Create a Scope object from the given name and namespace. + * + * @param localName + * @param namespace + * @return Scope object. + */ + public static Scope create(String localName, Namespace namespace) { + String key = DomUtil.getExpandedName(localName, namespace); + if (scopes.containsKey(key)) { + return scopes.get(key); + } else { + Scope scope = new Scope(localName, namespace); + scopes.put(key, scope); + return scope; + } + } +} Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/lock/Scope.java ___________________________________________________________________ Added: svn Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/lock/SimpleLockManager.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/lock/SimpleLockManager.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/lock/SimpleLockManager.java (working copy) @@ -0,0 +1,233 @@ +/* + * 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.webdav.lock; + +import org.apache.jackrabbit.webdav.DavException; +import org.apache.jackrabbit.webdav.DavResource; +import org.apache.jackrabbit.webdav.DavResourceIterator; +import org.apache.jackrabbit.webdav.DavServletResponse; + +import java.util.HashMap; +import java.util.Map; + +/** + * Simple manager for webdav locks.
+ */ +public class SimpleLockManager implements LockManager { + + /** map of locks */ + private Map locks = new HashMap(); + + /** + * + * @param lockToken + * @param resource + * @return + * @see LockManager#hasLock(String, org.apache.jackrabbit.webdav.DavResource) + */ + public boolean hasLock(String lockToken, DavResource resource) { + ActiveLock lock = locks.get(resource.getResourcePath()); + if (lock != null && lock.getToken().equals(lockToken)) { + return true; + } + return false; + } + + /** + * Returns the lock applying to the given resource or null if + * no lock can be found. + * + * @param type + * @param scope + * @param resource + * @return lock that applies to the given resource or null. + */ + public synchronized ActiveLock getLock(Type type, Scope scope, DavResource resource) { + if (!(Type.WRITE.equals(type) && Scope.EXCLUSIVE.equals(scope))) { + return null; + } + return getLock(resource.getResourcePath()); + } + + /** + * Looks for a valid lock at the given path or a deep lock present with + * a parent path. + * + * @param path + * @return + */ + private ActiveLock getLock(String path) { + ActiveLock lock = locks.get(path); + if (lock != null) { + // check if not expired + if (lock.isExpired()) { + lock = null; + } + } + if (lock == null) { + // check, if child of deep locked parent + if (!path.equals("/")) { + ActiveLock parentLock = getLock(getParentPath(path)); + if (parentLock != null && parentLock.isDeep()) { + lock = parentLock; + } + } + } + return lock; + } + + /** + * Adds the lock for the given resource, replacing any existing lock. + * + * @param lockInfo + * @param resource being the lock holder + */ + public synchronized ActiveLock createLock(LockInfo lockInfo, + DavResource resource) + throws DavException { + if (lockInfo == null || resource == null) { + throw new IllegalArgumentException("Neither lockInfo nor resource must be null."); + } + + String resourcePath = resource.getResourcePath(); + // test if there is already a lock present on this resource + ActiveLock lock = locks.get(resourcePath); + if (lock != null && lock.isExpired()) { + locks.remove(resourcePath); + lock = null; + } + if (lock != null) { + throw new DavException(DavServletResponse.SC_LOCKED, "Resource '" + resource.getResourcePath() + "' already holds a lock."); + } + // test if the new lock would conflict with any lock inherited from the + // collection or with a lock present on any member resource. + for (String key : locks.keySet()) { + // TODO: is check for lock on internal-member correct? + if (isDescendant(key, resourcePath)) { + ActiveLock l = locks.get(key); + if (l.isDeep() || (key.equals(getParentPath(resourcePath)) && !resource.isCollection())) { + throw new DavException(DavServletResponse.SC_LOCKED, "Resource '" + resource.getResourcePath() + "' already inherits a lock by its collection."); + } + } else if (isDescendant(resourcePath, key)) { + if (lockInfo.isDeep() || isInternalMember(resource, key)) { + throw new DavException(DavServletResponse.SC_CONFLICT, "Resource '" + resource.getResourcePath() + "' cannot be locked due to a lock present on the member resource '" + key + "'."); + } + + } + } + lock = new DefaultActiveLock(lockInfo); + locks.put(resource.getResourcePath(), lock); + return lock; + } + + /** + * + * @param lockInfo + * @param lockToken + * @param resource + * @return + * @throws DavException + * @see DavResource#refreshLock(org.apache.jackrabbit.webdav.lock.LockInfo, String) + */ + public ActiveLock refreshLock(LockInfo lockInfo, String lockToken, DavResource resource) + throws DavException { + ActiveLock lock = getLock(lockInfo.getType(), lockInfo.getScope(), resource); + if (lock == null) { + throw new DavException(DavServletResponse.SC_PRECONDITION_FAILED); + } else if (!lock.getToken().equals(lockToken)) { + throw new DavException(DavServletResponse.SC_LOCKED); + } + lock.setTimeout(lockInfo.getTimeout()); + return lock; + } + + /** + * Remove the lock hold by the given resource. + * + * @param lockToken + * @param resource that is the lock holder + */ + public synchronized void releaseLock(String lockToken, DavResource resource) + throws DavException { + if (!locks.containsKey(resource.getResourcePath())) { + throw new DavException(DavServletResponse.SC_PRECONDITION_FAILED); + } + ActiveLock lock = locks.get(resource.getResourcePath()); + if (lock.getToken().equals(lockToken)) { + locks.remove(resource.getResourcePath()); + } else { + throw new DavException(DavServletResponse.SC_LOCKED); + } + } + + /** + * Return true, if the resource with the given memberPath is a internal + * non-collection member of the given resource, thus affected by a + * non-deep lock present on the resource. + * + * @param resource + * @param memberPath + * @return + */ + private static boolean isInternalMember(DavResource resource, String memberPath) { + if (resource.getResourcePath().equals(getParentPath(memberPath))) { + // find the member with the given path + DavResourceIterator it = resource.getMembers(); + while (it.hasNext()) { + DavResource member = it.nextResource(); + if (member.getResourcePath().equals(memberPath)) { + // return true if that member is not a collection + return !member.isCollection(); + } + } + } + return false; + } + + /** + * @param path Path to retrieve the parent path for. + * @return empty string if the specified path contains no '/', "/" if the + * last index of '/' is zero. Otherwise the last segment is cut off the + * specified path. + */ + private static String getParentPath(String path) { + int idx = path.lastIndexOf('/'); + switch (idx) { + case -1: + return ""; + case 0: + return "/"; + default: + return path.substring(0, idx); + } + } + + /** + * Determines if the descendant path is hierarchical a + * descendant of path. + * + * @param path the current path + * @param descendant the potential descendant + * @return true if the descendant is a descendant; + * false otherwise. + */ + private static boolean isDescendant(String path, String descendant) { + String pattern = path.endsWith("/") ? path : path + "/"; + return !pattern.equals(descendant) && descendant.startsWith(pattern); + } +} + Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/lock/SimpleLockManager.java ___________________________________________________________________ Added: svn Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/lock/SupportedLock.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/lock/SupportedLock.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/lock/SupportedLock.java (working copy) @@ -0,0 +1,166 @@ +/* + * 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.webdav.lock; + +import org.apache.jackrabbit.webdav.property.AbstractDavProperty; +import org.apache.jackrabbit.webdav.property.DavPropertyName; +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +/** + * The SupportedLock class encapsulates the lock capabilities + * of a resource. It is mainly responsible for generating the <supportedlock> + * property. + */ +public class SupportedLock extends AbstractDavProperty> { + + /** the list of lock entries */ + private final List entries = new ArrayList(); + + /** + * Creates a new empty SupportedLock property. + */ + public SupportedLock() { + super(DavPropertyName.SUPPORTEDLOCK, false); + } + + /** + * Adds a capability to this lock support. + * + * @param type Can currently only be 'write' + * @param scope Can currently only be 'exclusive' or 'shared' + * + * @throws IllegalArgumentException If an argument contains invalid string + */ + public void addEntry(Type type, Scope scope) { + entries.add(new WriteLockEntry(type, scope)); + } + + /** + * Adds a capability to this lock support. + * + * @param entry specifying the type of lock that is supported by this entry. + * @see LockEntry + */ + public void addEntry(LockEntry entry) { + if (entry == null) { + throw new IllegalArgumentException("The lock entry cannot be null."); + } + entries.add(entry); + } + + /** + * Returns true if this a lock with the given type and scope is supported. + * + * @param type + * @param scope + * @return true if applying a lock with the given type and scope is basically + * supported. + */ + public boolean isSupportedLock(Type type, Scope scope) { + for (LockEntry le : entries) { + if (le.getType().equals(type) && le.getScope().equals(scope)) { + return true; + } + } + return false; + } + + /** + * Returns an iterator over all supported locks. + * + * @return an iterator over all supported locks + */ + public Iterator getSupportedLocks() { + return entries.iterator(); + } + + /** + * Creates an XML element that represents the <supportedlock> tag. + * + * @return An XML element of this lock support. + * @param document + */ + @Override + public Element toXml(Document document) { + Element support = getName().toXml(document); + for (LockEntry le : entries) { + support.appendChild(le.toXml(document)); + } + return support; + } + + /** + * Returns the list of supported lock entries. + * + * @return list of supported lock. + * @see org.apache.jackrabbit.webdav.property.DavProperty#getValue() + */ + public List getValue() { + return entries; + } + + /** + * Class representing the default lock entries defined by + * RFC 2518. + */ + private final static class WriteLockEntry extends AbstractLockEntry { + + /** the lock scope */ + private final Scope scope; + + /** + * Creates a new WriteLockEntry + * + * @param type Can currently only be + * {@link Type#WRITE write} + * @param scope Can currently only be {@link Scope#EXCLUSIVE exclusive} + * or {@link Scope#SHARED shared}. + * + * @throws IllegalArgumentException If an argument contains invalid string + */ + WriteLockEntry(Type type, Scope scope) { + if (!Type.WRITE.equals(type)) { + throw new IllegalArgumentException("Invalid Type:" + type); + } + if (!Scope.EXCLUSIVE.equals(scope) && !Scope.SHARED.equals(scope)) { + throw new IllegalArgumentException("Invalid scope:" +scope); + } + this.scope = scope; + } + + /** + * @return always returns {@link Type#WRITE write}. + * @see LockEntry#getType() + */ + public Type getType() { + return Type.WRITE; + } + + /** + * @return returns {@link Scope#EXCLUSIVE} or {@link Scope#SHARED}. + * @see LockEntry#getScope() + */ + public Scope getScope() { + return scope; + } + } +} Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/lock/SupportedLock.java ___________________________________________________________________ Added: svn Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/lock/Type.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/lock/Type.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/lock/Type.java (working copy) @@ -0,0 +1,129 @@ +/* + * 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.webdav.lock; + +import org.apache.jackrabbit.webdav.DavConstants; +import org.apache.jackrabbit.webdav.xml.DomUtil; +import org.apache.jackrabbit.webdav.xml.Namespace; +import org.apache.jackrabbit.webdav.xml.XmlSerializable; +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +import java.util.HashMap; +import java.util.Map; + +/** + * The Type class encapsulates the lock type as defined by RFC 2518. + */ +public class Type implements XmlSerializable { + + private static Map types = new HashMap(); + + public static final Type WRITE = Type.create(DavConstants.XML_WRITE, DavConstants.NAMESPACE); + + private final String localName; + private final Namespace namespace; + + private int hashCode = -1; + + /** + * Private constructor. + * + * @param name + * @param namespace + */ + private Type(String name, Namespace namespace) { + this.localName = name; + this.namespace = namespace; + } + + /** + * Returns the Xml representation of this lock Type. + * + * @return Xml representation + * @see org.apache.jackrabbit.webdav.xml.XmlSerializable#toXml(Document) + */ + public Element toXml(Document document) { + Element lockType = DomUtil.createElement(document, DavConstants.XML_LOCKTYPE, DavConstants.NAMESPACE); + DomUtil.addChildElement(lockType, localName, namespace); + return lockType; + } + + @Override + public int hashCode() { + if (hashCode == -1) { + StringBuilder b = new StringBuilder(); + b.append("LockType : {").append(namespace).append("}").append(localName); + hashCode = b.toString().hashCode(); + } + return hashCode; + } + + /** + * Returns true if this Type is equal to the given one. + * + * @param obj + * @return + */ + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj instanceof Type) { + Type other = (Type) obj; + return localName.equals(other.localName) && namespace.equals(other.namespace); + } + return false; + } + + /** + * Create a Type object from the given Xml element. + * + * @param lockType + * @return Type object. + */ + public static Type createFromXml(Element lockType) { + if (lockType != null && DavConstants.XML_LOCKTYPE.equals(lockType.getLocalName())) { + // we have the parent element and must retrieve the type first + lockType = DomUtil.getFirstChildElement(lockType); + } + if (lockType == null) { + throw new IllegalArgumentException("'null' is not valid lock type entry."); + } + Namespace namespace = Namespace.getNamespace(lockType.getPrefix(), lockType.getNamespaceURI()); + return create(lockType.getLocalName(), namespace); + } + + /** + * Create a Type object from the given localName and namespace. + * + * @param localName + * @param namespace + * @return Type object. + */ + public static Type create(String localName, Namespace namespace) { + String key = DomUtil.getExpandedName(localName, namespace); + if (types.containsKey(key)) { + return types.get(key); + } else { + Type type = new Type(localName, namespace); + types.put(key, type); + return type; + } + } +} Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/lock/Type.java ___________________________________________________________________ Added: svn Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/lock/package-info.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/lock/package-info.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/lock/package-info.java (working copy) @@ -0,0 +1,18 @@ +/* + * 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. + */ +@org.osgi.annotation.versioning.Version("1.0.1") +package org.apache.jackrabbit.webdav.lock; Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/lock/package-info.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/observation/DefaultEventType.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/observation/DefaultEventType.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/observation/DefaultEventType.java (working copy) @@ -0,0 +1,148 @@ +/* + * 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.webdav.observation; + +import org.apache.jackrabbit.webdav.xml.Namespace; +import org.apache.jackrabbit.webdav.xml.DomUtil; +import org.apache.jackrabbit.webdav.xml.XmlSerializable; +import org.apache.jackrabbit.webdav.xml.ElementIterator; +import org.w3c.dom.Element; +import org.w3c.dom.Document; + +import java.util.Map; +import java.util.HashMap; +import java.util.List; +import java.util.ArrayList; + +/** + * DefaultEventType defines a simple EventType implementation that + * only consists of a qualified event name consisting of namespace plus local + * name. + */ +public class DefaultEventType implements EventType { + + private static final Map eventTypes = new HashMap(); + + private final String localName; + private final Namespace namespace; + + /** + * Avoid instantiation of DefaultEventType. Since the amount + * of available (and registered) events is considered to be limited, the + * static {@link #create(String, Namespace) method is defined. + * + * @param localName + * @param namespace + */ + private DefaultEventType(String localName, Namespace namespace) { + this.localName = localName; + this.namespace = namespace; + } + + /** + * Factory method to create a new EventType. + * + * @param localName + * @param namespace + * @return + */ + public static EventType create(String localName, Namespace namespace) { + if (localName == null || "".equals(localName)) { + throw new IllegalArgumentException("null and '' are not valid local names of an event type."); + } + String key = DomUtil.getExpandedName(localName, namespace); + if (eventTypes.containsKey(key)) { + return eventTypes.get(key); + } else { + EventType type = new DefaultEventType(localName, namespace); + eventTypes.put(key, type); + return type; + } + } + + /** + * Factory method to create an array of new EventType for the + * specified localNames and the specified namespace. + * + * @param localNames + * @param namespace + * @return An array of event types. + */ + public static EventType[] create(String[] localNames, Namespace namespace) { + EventType[] types = new EventType[localNames.length]; + for (int i = 0; i < localNames.length; i++) { + types[i] = create(localNames[i], namespace); + } + return types; + } + + /** + * Retrieves one or multiple EventTypes from the 'eventtype' + * Xml element. While a subscription may register multiple types (thus + * the 'eventtype' contains multiple child elements), a single event may only + * refer to one single type. + * + * @param eventType + * @return + */ + public static EventType[] createFromXml(Element eventType) { + if (!DomUtil.matches(eventType, ObservationConstants.XML_EVENTTYPE, ObservationConstants.NAMESPACE)) { + throw new IllegalArgumentException("'eventtype' element expected which contains a least a single child element."); + } + + List etypes = new ArrayList(); + ElementIterator it = DomUtil.getChildren(eventType); + while (it.hasNext()) { + Element el = it.nextElement(); + etypes.add(create(el.getLocalName(), DomUtil.getNamespace(el))); + } + return etypes.toArray(new EventType[etypes.size()]); + } + + //----------------------------------------------------------< EventType >--- + /** + * @see EventType#getName() + */ + public String getName() { + return localName; + } + + /** + * @see EventType#getNamespace() + */ + public Namespace getNamespace() { + return namespace; + } + + //----------------------------------------------------< XmlSerializable >--- + /** + * Returns a single empty Xml element where namespace and local name of this + * event type define the elements name. + *
+     * EventType.create("someevent", Namespace.getNamespace("F", "http://www.foo.bar/eventtypes"));
+     *
+     * returns the following element upon call of toXml:
+     *
+     * <F:someevent xmlns:F="http://www.foo.bar/eventtypes" />
+     * 
+ * + * @see XmlSerializable#toXml(Document) + */ + public Element toXml(Document document) { + return DomUtil.createElement(document, localName, namespace); + } +} Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/observation/DefaultEventType.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-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/observation/EventBundle.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/observation/EventBundle.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/observation/EventBundle.java (working copy) @@ -0,0 +1,29 @@ +/* + * 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.webdav.observation; + +import org.apache.jackrabbit.webdav.xml.XmlSerializable; + +/** + * EventBundle defines an empty interface used to represent a bundle + * of events. + * + * @see EventDiscovery#addEventBundle(EventBundle) + */ +public interface EventBundle extends XmlSerializable { + +} \ No newline at end of file Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/observation/EventBundle.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-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/observation/EventDiscovery.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/observation/EventDiscovery.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/observation/EventDiscovery.java (working copy) @@ -0,0 +1,121 @@ +/* + * 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.webdav.observation; + +import org.apache.jackrabbit.webdav.xml.DomUtil; +import org.apache.jackrabbit.webdav.xml.ElementIterator; +import org.apache.jackrabbit.webdav.xml.XmlSerializable; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +/** + * EventDiscovery represents the request body of a successful + * POLL request. It reveals all events that occurred since the last POLL. The + * definition what events that particular subscription is interested in was + * specified with the initial SUBSCRIPTION that started the event listening. + */ +public class EventDiscovery implements ObservationConstants, XmlSerializable { + + private static Logger log = LoggerFactory.getLogger(EventDiscovery.class); + + private final List bundles = new ArrayList(); + + /** + * Add the Xml representation of an single 'eventBundle' listing the + * events that resulted from a change in the server, filtered by the + * restrictions present in the corresponding subscription. + * + * @param eventBundle + * @see Subscription + */ + public void addEventBundle(EventBundle eventBundle) { + if (eventBundle != null) { + bundles.add(eventBundle); + } + } + + /** + * Returns an iterator over the {@link EventBundle event bundles} currently + * present on this discovery. + * + * @return iterator over event bundles present. + */ + public Iterator getEventBundles() { + return bundles.iterator(); + } + + /** + * Returns true, if this event discovery does not report any events (thus + * {@link #getEventBundles()} would return an empty iterator. + * + * @return true if {@link #getEventBundles()} would return an empty iterator, + * false otherwise. + */ + public boolean isEmpty() { + return bundles.isEmpty(); + } + + /** + * Returns the Xml representation of this EventDiscovery as + * being present in the POLL response body. + * + * @return Xml representation + * @see org.apache.jackrabbit.webdav.xml.XmlSerializable#toXml(Document) + * @param document + */ + public Element toXml(Document document) { + Element ed = DomUtil.createElement(document, XML_EVENTDISCOVERY, NAMESPACE); + for (EventBundle bundle : bundles) { + ed.appendChild(bundle.toXml(document)); + } + return ed; + } + + /** + * Build a EventDiscovery from the specified xml element. + * + * @param eventDiscoveryElement + * @return new EventDiscovery instance. + * @throws IllegalArgumentException if the given document is null + * or does not provide the required element. + */ + public static EventDiscovery createFromXml(Element eventDiscoveryElement) { + if (!DomUtil.matches(eventDiscoveryElement, XML_EVENTDISCOVERY, ObservationConstants.NAMESPACE)) { + throw new IllegalArgumentException( + "{" + ObservationConstants.NAMESPACE + "}" + XML_EVENTDISCOVERY + " element expected, but got: {" + + eventDiscoveryElement.getNamespaceURI() + "}" + eventDiscoveryElement.getLocalName()); + } + EventDiscovery eventDiscovery = new EventDiscovery(); + ElementIterator it = DomUtil.getChildren(eventDiscoveryElement, XML_EVENTBUNDLE, ObservationConstants.NAMESPACE); + while (it.hasNext()) { + final Element ebElement = it.nextElement(); + EventBundle eb = new EventBundle() { + public Element toXml(Document document) { + return (Element) document.importNode(ebElement, true); + } + }; + eventDiscovery.addEventBundle(eb); + } + return eventDiscovery; + } +} Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/observation/EventDiscovery.java ___________________________________________________________________ Added: svn Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/observation/EventType.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/observation/EventType.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/observation/EventType.java (working copy) @@ -0,0 +1,30 @@ +/* + * 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.webdav.observation; + +import org.apache.jackrabbit.webdav.xml.Namespace; +import org.apache.jackrabbit.webdav.xml.XmlSerializable; + +/** + * EventType... + */ +public interface EventType extends XmlSerializable { + + public String getName(); + + public Namespace getNamespace(); +} \ No newline at end of file Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/observation/EventType.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-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/observation/Filter.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/observation/Filter.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/observation/Filter.java (working copy) @@ -0,0 +1,74 @@ +/* + * 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.webdav.observation; + +import org.apache.jackrabbit.webdav.xml.DomUtil; +import org.apache.jackrabbit.webdav.xml.Namespace; +import org.apache.jackrabbit.webdav.xml.XmlSerializable; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +/** + * Filter... + */ +public class Filter implements XmlSerializable { + + private static Logger log = LoggerFactory.getLogger(Filter.class); + + private final String filterName; + private final Namespace filterNamespace; + private final String filterValue; + + public Filter(String filterName, Namespace filterNamespace, String filterValue) { + if (filterName == null) { + throw new IllegalArgumentException("filterName must not be null."); + } + this.filterName = filterName; + this.filterNamespace = filterNamespace; + this.filterValue = filterValue; + } + + public Filter(Element filterElem) { + filterName = filterElem.getLocalName(); + filterNamespace = DomUtil.getNamespace(filterElem); + filterValue = DomUtil.getTextTrim(filterElem); + } + + public String getName() { + return filterName; + } + + public Namespace getNamespace() { + return filterNamespace; + } + + public String getValue() { + return filterValue; + } + + public boolean isMatchingFilter(String localName, Namespace namespace) { + boolean matchingNsp = (filterNamespace == null) ? namespace == null : filterNamespace.equals(namespace); + return filterName.equals(localName) && matchingNsp; + } + + public Element toXml(Document document) { + return DomUtil.createElement(document, filterName, filterNamespace, filterValue); + } + +} \ No newline at end of file Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/observation/Filter.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-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/observation/ObservationConstants.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/observation/ObservationConstants.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/observation/ObservationConstants.java (working copy) @@ -0,0 +1,101 @@ +/* + * 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.webdav.observation; + +import javax.xml.namespace.QName; + +import org.apache.jackrabbit.webdav.property.DavPropertyName; +import org.apache.jackrabbit.webdav.xml.Namespace; + +/** + * ObservationConstants interface provide constants for request + * and response headers, Xml elements and property names used for handling + * observation over WebDAV. There exists no public standard for this + * functionality. + */ +public interface ObservationConstants { + + /** + * The namespace + */ + public static final Namespace NAMESPACE = Namespace.getNamespace("dcr", "http://www.day.com/jcr/webdav/1.0"); + + //---< Headers >------------------------------------------------------------ + /** + * The SubscriptionId request header
+ */ + public static final String HEADER_SUBSCRIPTIONID = "SubscriptionId"; + + /** + * The PollTimeout request header. + */ + public static final String HEADER_POLL_TIMEOUT = "PollTimeout"; + + //---< XML Element, Attribute Names >--------------------------------------- + /** + * subscription Xml element
+ * Mandatory element inside the {@link #SUBSCRIPTIONDISCOVERY subscriptiondiscovery} + * property indicating the event listeners present for this session.
+ * NOTE, that this will not reveal any subscription made by another session. + */ + public static final String XML_SUBSCRIPTION = "subscription"; + + /** + * Xml elements + */ + public static final String XML_SUBSCRIPTIONINFO = "subscriptioninfo"; + + public static final String XML_EVENTTYPE = "eventtype"; + public static final String XML_NOLOCAL = "nolocal"; + public static final String XML_FILTER = "filter"; + public static final String XML_SUBSCRIPTIONID = "subscriptionid"; + public static final String XML_EVENTSWITHTYPES = "eventswithnodetypes"; + public static final String XML_EVENTSWITHLOCALFLAG = "eventswithlocalflag"; + public static final String XML_UUID = "uuid"; + public static final String XML_NODETYPE_NAME = "nodetype-name"; + + public static final String XML_EVENTDISCOVERY = "eventdiscovery"; + public static final String XML_EVENTBUNDLE = "eventbundle"; + public static final String XML_EVENT_TRANSACTION_ID = "transactionid"; + public static final String XML_EVENT_LOCAL = "local"; + public static final String XML_EVENT = "event"; + public static final String XML_EVENTUSERID = "eventuserid"; + public static final String XML_EVENTUSERDATA = "eventuserdata"; + public static final String XML_EVENTDATE = "eventdate"; + public static final String XML_EVENTIDENTIFIER = "eventidentifier"; + public static final String XML_EVENTINFO = "eventinfo"; + public static final String XML_EVENTPRIMARNODETYPE = "eventprimarynodetype"; + public static final String XML_EVENTMIXINNODETYPE = "eventmixinnodetype"; + + public static final QName N_EVENT = new QName(NAMESPACE.getURI(), XML_EVENT); + public static final QName N_EVENTBUNDLE = new QName(NAMESPACE.getURI(), XML_EVENTBUNDLE); + public static final QName N_EVENTDATE = new QName(NAMESPACE.getURI(), XML_EVENTDATE); + public static final QName N_EVENTDISCOVERY = new QName(NAMESPACE.getURI(), XML_EVENTDISCOVERY); + public static final QName N_EVENTINFO = new QName(NAMESPACE.getURI(), XML_EVENTINFO); + public static final QName N_EVENTMIXINNODETYPE = new QName(NAMESPACE.getURI(), XML_EVENTMIXINNODETYPE); + public static final QName N_EVENTPRIMARYNODETYPE = new QName(NAMESPACE.getURI(), XML_EVENTPRIMARNODETYPE); + public static final QName N_EVENTTYPE = new QName(NAMESPACE.getURI(), XML_EVENTTYPE); + public static final QName N_EVENTUSERDATA = new QName(NAMESPACE.getURI(), XML_EVENTUSERDATA); + public static final QName N_EVENTUSERID = new QName(NAMESPACE.getURI(), XML_EVENTUSERID); + + //---< Property Names >----------------------------------------------------- + /** + * The protected subscription discovery property is used to find out about + * existing subscriptions present on the specified resource. + */ + public static final DavPropertyName SUBSCRIPTIONDISCOVERY = DavPropertyName.create("subscriptiondiscovery", NAMESPACE); +} Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/observation/ObservationConstants.java ___________________________________________________________________ Added: svn Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/observation/ObservationDavServletRequest.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/observation/ObservationDavServletRequest.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/observation/ObservationDavServletRequest.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.webdav.observation; + +import org.apache.jackrabbit.webdav.DavException; +import org.apache.jackrabbit.webdav.DavServletRequest; + +/** + * ObservationDavServletRequest provides extensions to the + * {@link DavServletRequest} interface used for dealing with observation. + */ +public interface ObservationDavServletRequest extends DavServletRequest { + + /** + * Return the {@link ObservationConstants#HEADER_SUBSCRIPTIONID SubscriptionId header} + * or null if no such header is present. + * + * @return the {@link ObservationConstants#HEADER_SUBSCRIPTIONID SubscriptionId header} + */ + public String getSubscriptionId(); + + /** + * Returns the {@link ObservationConstants#HEADER_POLL_TIMEOUT PollTimeout header} + * or 0 (zero) if no such header is present. + * + * @return milliseconds indicating length of the poll timeout. + */ + public long getPollTimeout(); + + /** + * Return a {@link SubscriptionInfo} object representing the subscription + * info present in the SUBSCRIBE request body or null if + * retrieving the subscription info fails. + * + * @return subscription info object encapsulating the SUBSCRIBE request body + * or null if the subscription info cannot be built. + * @throws DavException if an invalid request body was encountered. + */ + public SubscriptionInfo getSubscriptionInfo() throws DavException; +} \ No newline at end of file Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/observation/ObservationDavServletRequest.java ___________________________________________________________________ Added: svn Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/observation/ObservationDavServletResponse.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/observation/ObservationDavServletResponse.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/observation/ObservationDavServletResponse.java (working copy) @@ -0,0 +1,45 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.jackrabbit.webdav.observation; + +import org.apache.jackrabbit.webdav.DavServletResponse; + +import java.io.IOException; + +/** + * ObservationDavServletResponse provides extensions to the + * {@link DavServletResponse} interface used for dealing with observation. + */ +public interface ObservationDavServletResponse extends DavServletResponse { + + /** + * Send the response to a successful SUBSCRIBE request. + * + * @param subscription that needs to be represented in the response body. + * @throws IOException + */ + public void sendSubscriptionResponse(Subscription subscription) throws IOException; + + /** + * Send the response to a successful POLL request. + * + * @param eventDiscovery {@link EventDiscovery} object to be returned in + * the response body. + * @throws IOException + */ + public void sendPollResponse(EventDiscovery eventDiscovery) throws IOException; +} \ No newline at end of file Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/observation/ObservationDavServletResponse.java ___________________________________________________________________ Added: svn Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/observation/ObservationResource.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/observation/ObservationResource.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/observation/ObservationResource.java (working copy) @@ -0,0 +1,72 @@ +/* + * 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.webdav.observation; + +import org.apache.jackrabbit.webdav.DavException; +import org.apache.jackrabbit.webdav.DavResource; + +/** + * ObservationResource extends the {@link DavResource} interface by + * observation relevant METHODS. + */ +public interface ObservationResource extends DavResource { + + public String METHODS = "SUBSCRIBE, UNSUBSCRIBE, POLL"; + + /** + * Initializes this resource. + * + * @param subsMgr subscription manager object + */ + public void init(SubscriptionManager subsMgr); + + /** + * Subscribe this resource for event listening defined by the specified + * subscription info. A subscriptionId may be specified in case an existing + * subscription should be modified. + * + * @param info SubscriptionInfo object as defined by the + * request body and headers. + * @param subscriptionId or null if the + * {@link ObservationConstants#HEADER_SUBSCRIPTIONID SubscriptionId} header + * is missing. + * @return Subscription object in case the subscription was + * successful. + */ + public Subscription subscribe(SubscriptionInfo info, String subscriptionId) throws DavException; + + /** + * Unsubscribe the event listener with the given SubscriptionId. + * + * @param subscriptionId as present in the {@link ObservationConstants#HEADER_SUBSCRIPTIONID + * SubscriptionId} header. + */ + public void unsubscribe(String subscriptionId) throws DavException; + + /** + * Retrieve the list of events that where recorded for the event listener + * with the given SubscriptionId. + * + * @param subscriptionId as present in the + * {@link ObservationConstants#HEADER_SUBSCRIPTIONID SubscriptionId} header. + * @param timeout as present in the + * {@link ObservationConstants#HEADER_POLL_TIMEOUT} header or 0 (zero) if + * none is present. + * @return EventDiscovery object + */ + public EventDiscovery poll(String subscriptionId, long timeout) throws DavException; +} \ No newline at end of file Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/observation/ObservationResource.java ___________________________________________________________________ Added: svn Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/observation/Subscription.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/observation/Subscription.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/observation/Subscription.java (working copy) @@ -0,0 +1,49 @@ +/* + * 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.webdav.observation; + +import org.apache.jackrabbit.webdav.xml.XmlSerializable; + +/** + * Subscription represents public representation of the event + * listener created (or modified) by a successful SUBSCRIBE request.
+ * Please note that this interface extends the XmlSerializable + * interface. The Xml representation of a Subscription is + * returned in the response to a successful SUBSCRIBE request as well + * as in a PROPFIND request. In both cases the subscription is packed into + * a {@link SubscriptionDiscovery} property object. + */ +public interface Subscription extends XmlSerializable { + + /** + * Returns the id of this subscription, that must be used for un-subscribing + * as well as for event discovery later on. + * + * @return subscriptionId + */ + public String getSubscriptionId(); + + /** + * @return whether events will be returned with node type information + */ + public boolean eventsProvideNodeTypeInformation(); + + /** + * @return whether events will be returned with the "noLocal" flag + */ + public boolean eventsProvideNoLocalFlag(); +} \ No newline at end of file Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/observation/Subscription.java ___________________________________________________________________ Added: svn Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/observation/SubscriptionDiscovery.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/observation/SubscriptionDiscovery.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/observation/SubscriptionDiscovery.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.webdav.observation; + +import org.apache.jackrabbit.webdav.property.AbstractDavProperty; +import org.apache.jackrabbit.webdav.xml.DomUtil; +import org.apache.jackrabbit.webdav.xml.ElementIterator; +import org.apache.jackrabbit.webdav.xml.XmlSerializable; +import org.apache.jackrabbit.webdav.DavConstants; +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +import java.util.List; +import java.util.ArrayList; + +/** + * SubscriptionDiscovery encapsulates the 'subscriptiondiscovery' + * property of a webdav resource. + */ +public class SubscriptionDiscovery extends AbstractDavProperty { + + private final Subscription[] subscriptions; + + /** + * Create a new SubscriptionDiscovery that lists the given + * subscriptions. + * + * @param subscriptions + */ + public SubscriptionDiscovery(Subscription[] subscriptions) { + super(ObservationConstants.SUBSCRIPTIONDISCOVERY, true); + if (subscriptions != null) { + this.subscriptions = subscriptions; + } else { + this.subscriptions = new Subscription[0]; + } + } + + /** + * Create a new SubscriptionDiscovery that contains a single + * subscription entry. + * + * @param subscription + */ + public SubscriptionDiscovery(Subscription subscription) { + super(ObservationConstants.SUBSCRIPTIONDISCOVERY, true); + if (subscription != null) { + this.subscriptions = new Subscription[]{subscription}; + } else { + this.subscriptions = new Subscription[0]; + } + } + + /** + * Returns an array of {@link Subscription}s. + * + * @return an array of {@link Subscription}s + * @see org.apache.jackrabbit.webdav.property.DavProperty#getValue() + */ + public Subscription[] getValue() { + return subscriptions; + } + + /** + * Returns the Xml representation of the subscription discovery. + * + * @return Xml representation + * @see org.apache.jackrabbit.webdav.xml.XmlSerializable#toXml(Document) + * @param document + */ + @Override + public Element toXml(Document document) { + Element elem = getName().toXml(document); + for (Subscription subscription : subscriptions) { + elem.appendChild(subscription.toXml(document)); + } + return elem; + } + + //-----------------------------------------------------< static Factory >--- + public static SubscriptionDiscovery createFromXml(Element sDiscoveryElement) { + if (!DomUtil.matches(sDiscoveryElement, ObservationConstants.SUBSCRIPTIONDISCOVERY.getName(), ObservationConstants.SUBSCRIPTIONDISCOVERY.getNamespace())) { + throw new IllegalArgumentException("'subscriptiondiscovery' element expected."); + } + + List subscriptions = new ArrayList(); + ElementIterator it = DomUtil.getChildren(sDiscoveryElement, ObservationConstants.XML_SUBSCRIPTION, ObservationConstants.NAMESPACE); + while (it.hasNext()) { + final Element sb = it.nextElement(); + // anonymous inner class: Subscription interface + Subscription s = new Subscription() { + /** + * @see Subscription#getSubscriptionId() + */ + public String getSubscriptionId() { + Element ltEl = DomUtil.getChildElement(sb, ObservationConstants.XML_SUBSCRIPTIONID, ObservationConstants.NAMESPACE); + if (ltEl != null) { + return DomUtil.getChildText(sb, DavConstants.XML_HREF, DavConstants.NAMESPACE); + } + return null; + } + + public boolean eventsProvideNodeTypeInformation() { + String t = DomUtil.getChildText(sb, ObservationConstants.XML_EVENTSWITHTYPES, ObservationConstants.NAMESPACE); + return t == null ? false : Boolean.parseBoolean(t); + } + + public boolean eventsProvideNoLocalFlag() { + String t = DomUtil.getChildText(sb, ObservationConstants.XML_EVENTSWITHLOCALFLAG, ObservationConstants.NAMESPACE); + return t == null ? false : Boolean.parseBoolean(t); + } + + /** + * @see XmlSerializable#toXml(Document) + */ + public Element toXml(Document document) { + return (Element) document.importNode(sb, true); + } + }; + subscriptions.add(s); + } + + return new SubscriptionDiscovery(subscriptions.toArray(new Subscription[subscriptions.size()])); + } +} \ No newline at end of file Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/observation/SubscriptionDiscovery.java ___________________________________________________________________ Added: svn Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/observation/SubscriptionInfo.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/observation/SubscriptionInfo.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/observation/SubscriptionInfo.java (working copy) @@ -0,0 +1,242 @@ +/* + * 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.webdav.observation; + +import org.apache.jackrabbit.webdav.DavException; +import org.apache.jackrabbit.webdav.DavServletResponse; +import org.apache.jackrabbit.webdav.header.TimeoutHeader; +import org.apache.jackrabbit.webdav.header.DepthHeader; +import org.apache.jackrabbit.webdav.xml.DomUtil; +import org.apache.jackrabbit.webdav.xml.ElementIterator; +import org.apache.jackrabbit.webdav.xml.Namespace; +import org.apache.jackrabbit.webdav.xml.XmlSerializable; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +import java.util.ArrayList; +import java.util.List; + +/** + * SubscriptionInfo class encapsulates the subscription info + * that forms the request body of a SUBSCRIBE request.
+ * The following xml layout is defined for the subscription info: + *
+ * <!ELEMENT subscriptioninfo ( eventtype, nolocal?, filter? ) >
+ * <!ELEMENT eventtype ANY >
+ *
+ * ANY defines any sequence of elements where at least one defines a valid
+ * eventtype. Note that a single eventtype must not occur multiple times.
+
+ * <!ELEMENT nolocal EMPTY >
+ * <!ELEMENT filter ANY >
+ *
+ * ANY: any sequence of elements identifying a filter for event listening but
+ * at least a single element.
+ * 
+ * @see ObservationConstants#XML_SUBSCRIPTIONINFO + */ +public class SubscriptionInfo implements ObservationConstants, XmlSerializable { + + private static Logger log = LoggerFactory.getLogger(SubscriptionInfo.class); + + private final EventType[] eventTypes; + private final Filter[] filters; + private final boolean noLocal; + private final boolean isDeep; + private final long timeout; + + /** + * Create a new SubscriptionInfo + * + * @param eventTypes + * @param isDeep + * @param timeout + */ + public SubscriptionInfo(EventType[] eventTypes, boolean isDeep, long timeout) { + this(eventTypes, null, false, isDeep, timeout); + } + + /** + * Create a new SubscriptionInfo + * + * @param eventTypes + * @param filters + * @param noLocal + * @param isDeep + * @param timeout + */ + public SubscriptionInfo(EventType[] eventTypes, Filter[] filters, boolean noLocal, boolean isDeep, long timeout) { + if (eventTypes == null || eventTypes.length == 0) { + throw new IllegalArgumentException("'subscriptioninfo' must at least indicate a single event type."); + } + + this.eventTypes = eventTypes; + this.noLocal = noLocal; + + if (filters != null) { + this.filters = filters; + } else { + this.filters = new Filter[0]; + } + + this.isDeep = isDeep; + this.timeout = timeout; + } + + /** + * Create a new SubscriptionInfo from the given Xml element + * and from additional information that is transported within the request + * header: + *
    + *
  • {@link TimeoutHeader timeout},
  • + *
  • {@link DepthHeader isDeep}
  • + *
+ * @param reqInfo Xml element present in the request body. + * @param timeout as defined in the {@link org.apache.jackrabbit.webdav.DavConstants#HEADER_TIMEOUT timeout header}. + * @param isDeep as defined in the {@link org.apache.jackrabbit.webdav.DavConstants#HEADER_DEPTH depth header}. + * @throws IllegalArgumentException if the reqInfo element does not contain the mandatory elements. + */ + public SubscriptionInfo(Element reqInfo, long timeout, boolean isDeep) throws DavException { + if (!DomUtil.matches(reqInfo, XML_SUBSCRIPTIONINFO, NAMESPACE)) { + log.warn("Element with name 'subscriptioninfo' expected"); + throw new DavException(DavServletResponse.SC_BAD_REQUEST); + } + Element el = DomUtil.getChildElement(reqInfo, XML_EVENTTYPE, NAMESPACE); + if (el != null) { + eventTypes = DefaultEventType.createFromXml(el); + if (eventTypes.length == 0) { + log.warn("'subscriptioninfo' must at least indicate a single, valid event type."); + throw new DavException(DavServletResponse.SC_BAD_REQUEST); + } + } else { + log.warn("'subscriptioninfo' must contain an 'eventtype' child element."); + throw new DavException(DavServletResponse.SC_BAD_REQUEST); + } + + List filters = new ArrayList(); + el = DomUtil.getChildElement(reqInfo, XML_FILTER, NAMESPACE); + if (el != null) { + ElementIterator it = DomUtil.getChildren(el); + while (it.hasNext()) { + Filter f = new Filter(it.nextElement()); + filters.add(f); + } + } + this.filters = filters.toArray(new Filter[filters.size()]); + + this.noLocal = DomUtil.hasChildElement(reqInfo, XML_NOLOCAL, NAMESPACE); + this.isDeep = isDeep; + this.timeout = timeout; + } + + /** + * Return array of event type names present in the subscription info. + * + * @return array of String defining the names of the events this subscription + * should listen to. + * + */ + public EventType[] getEventTypes() { + return eventTypes; + } + + /** + * Return all filters defined for this SubscriptionInfo + * + * @return all filters or an empty Filter array. + */ + public Filter[] getFilters() { + return filters; + } + + /** + * Return array of filters with the specified name. + * + * @param localName the filter elements must provide. + * @param namespace + * @return array containing the text of the filter elements with the given + * name. + */ + public Filter[] getFilters(String localName, Namespace namespace) { + List l = new ArrayList(); + for (Filter filter : filters) { + if (filter.isMatchingFilter(localName, namespace)) { + l.add(filter); + } + } + return l.toArray(new Filter[l.size()]); + } + + /** + * Returns true if the {@link #XML_NOLOCAL} element is present in this + * subscription info. + * + * @return if {@link #XML_NOLOCAL} element is present. + */ + public boolean isNoLocal() { + return noLocal; + } + + /** + * Returns true if the {@link org.apache.jackrabbit.webdav.DavConstants#HEADER_DEPTH + * depths header} defined a depth other than '0'. + * + * @return true if this subscription info was created with isDeep + * true. + */ + public boolean isDeep() { + return isDeep; + } + + /** + * Return the timeout as retrieved from the request. + * + * @return timeout. + */ + public long getTimeOut() { + return timeout; + } + + /** + * Xml representation of this SubscriptionInfo. + * + * @return Xml representation + * @see org.apache.jackrabbit.webdav.xml.XmlSerializable#toXml(Document) + * @param document + */ + public Element toXml(Document document) { + Element subscrInfo = DomUtil.createElement(document, XML_SUBSCRIPTIONINFO, NAMESPACE); + Element eventType = DomUtil.addChildElement(subscrInfo, XML_EVENTTYPE, NAMESPACE); + for (EventType et : eventTypes) { + eventType.appendChild(et.toXml(document)); + } + + if (filters.length > 0) { + Element filter = DomUtil.addChildElement(subscrInfo, XML_FILTER, NAMESPACE); + for (Filter f : filters) { + filter.appendChild(f.toXml(document)); + } + } + + if (noLocal) { + DomUtil.addChildElement(subscrInfo, XML_NOLOCAL, NAMESPACE); + } + return subscrInfo; + } +} Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/observation/SubscriptionInfo.java ___________________________________________________________________ Added: svn Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/observation/SubscriptionManager.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/observation/SubscriptionManager.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/observation/SubscriptionManager.java (working copy) @@ -0,0 +1,69 @@ +/* + * 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.webdav.observation; + +import org.apache.jackrabbit.webdav.DavException; + +/** + * SubscriptionManager interface. + */ +public interface SubscriptionManager { + + /** + * Retrieve the {@link org.apache.jackrabbit.webdav.observation.SubscriptionDiscovery} object for the given + * resource. Note, that the discovery object will be empty if there are + * no subscriptions present. + * + * @param resource + */ + public SubscriptionDiscovery getSubscriptionDiscovery(ObservationResource resource); + + /** + * Create a new Subscription or update an existing Subscription.. + * + * @param info + * @param subscriptionId + * @param resource + * @return Subscription that has been created or updated + * @throws DavException if the subscription fails + */ + public Subscription subscribe(SubscriptionInfo info, String subscriptionId, + ObservationResource resource) + throws DavException; + + /** + * Unsubscribe the Subscription with the given id. + * + * @param subscriptionId + * @param resource + * @throws DavException + */ + public void unsubscribe(String subscriptionId, ObservationResource resource) + throws DavException; + + /** + * Retrieve the list of events that occurred since the last poll. + * + * @param subscriptionId identifier for the subscription + * @param timeout the time in milliseconds to wait at most for events + * if none is present currently. + * @param resource + * @return + */ + public EventDiscovery poll(String subscriptionId, long timeout, ObservationResource resource) + throws DavException; +} \ No newline at end of file Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/observation/SubscriptionManager.java ___________________________________________________________________ Added: svn Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/observation/package-info.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/observation/package-info.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/observation/package-info.java (working copy) @@ -0,0 +1,18 @@ +/* + * 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. + */ +@org.osgi.annotation.versioning.Version("1.1.0") +package org.apache.jackrabbit.webdav.observation; Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/observation/package-info.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/ordering/OrderPatch.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/ordering/OrderPatch.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/ordering/OrderPatch.java (working copy) @@ -0,0 +1,212 @@ +/* + * 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.webdav.ordering; + +import org.apache.jackrabbit.webdav.DavConstants; +import org.apache.jackrabbit.webdav.DavException; +import org.apache.jackrabbit.webdav.DavServletResponse; +import org.apache.jackrabbit.webdav.xml.DomUtil; +import org.apache.jackrabbit.webdav.xml.ElementIterator; +import org.apache.jackrabbit.webdav.xml.XmlSerializable; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +import java.util.ArrayList; +import java.util.List; + +/** + * OrderPatch represents the mandatory request body of an + * ORDERPATCH request. RFC 3648 defines the following structure for it:
+ *
+ * <!ELEMENT orderpatch (ordering-type?, order-member*) >
+ * <!ELEMENT order-member (segment, position) >
+ * <!ELEMENT position (first | last | before | after) >
+ * <!ELEMENT segment (#PCDATA) >
+ * <!ELEMENT first EMPTY >
+ * <!ELEMENT last EMPTY >
+ * <!ELEMENT before segment >
+ * <!ELEMENT after segment >
+ * 
+ */ +public class OrderPatch implements OrderingConstants, XmlSerializable { + + private static Logger log = LoggerFactory.getLogger(OrderPatch.class); + + private Member[] instructions; + private String orderingType; + + /** + * Create a new OrderPath object. + * + * @param orderingType + * @param instruction + */ + public OrderPatch(String orderingType, Member instruction) { + this(orderingType, new Member[] {instruction}); + } + + /** + * Create a new OrderPath object. + * + * @param orderingType + * @param instructions + */ + public OrderPatch(String orderingType, Member[] instructions) { + if (orderingType == null || instructions == null) { + throw new IllegalArgumentException("ordering type and instructions cannot be null."); + } + this.orderingType = orderingType; + this.instructions = instructions; + } + + /** + * Return the ordering type. + * + * @return ordering type + */ + public String getOrderingType() { + return orderingType; + } + + /** + * Return an array of {@link Member} objects defining the re-ordering + * instructions to be applied to the requested resource. + * + * @return ordering instructions. + */ + public Member[] getOrderInstructions() { + return instructions; + } + + //------------------------------------------< XmlSerializable interface >--- + /** + * + * @return + * @param document + */ + public Element toXml(Document document) { + Element orderPatch = DomUtil.createElement(document, XML_ORDERPATCH, NAMESPACE); + // add DAV:ordering-type below DAV:orderpatch + Element otype = DomUtil.addChildElement(orderPatch, XML_ORDERING_TYPE, NAMESPACE); + otype.appendChild(DomUtil.hrefToXml(orderingType, document)); + // add DAV:member elements below DAV:orderpatch + for (Member instruction : instructions) { + orderPatch.appendChild(instruction.toXml(document)); + } + return orderPatch; + } + + //------------------------------------------------------< static method >--- + /** + * Create a new OrderPath object. + * + * @param orderPatchElement + * @throws IllegalArgumentException if the specified Xml element was not valid. + */ + public static OrderPatch createFromXml(Element orderPatchElement) throws DavException { + if (!DomUtil.matches(orderPatchElement, XML_ORDERPATCH, NAMESPACE)) { + log.warn("ORDERPATH request body must start with an 'orderpatch' element."); + throw new DavException(DavServletResponse.SC_BAD_REQUEST); + } + + // retrieve the href of the orderingtype element + String orderingType; + Element otype = DomUtil.getChildElement(orderPatchElement, XML_ORDERING_TYPE, NAMESPACE); + if (otype != null) { + orderingType = DomUtil.getChildText(otype, DavConstants.XML_HREF, DavConstants.NAMESPACE); + } else { + log.warn("ORDERPATH request body must contain an 'ordering-type' child element."); + throw new DavException(DavServletResponse.SC_BAD_REQUEST); + } + + // set build the list of ordering instructions + List tmpList = new ArrayList(); + ElementIterator it = DomUtil.getChildren(orderPatchElement, XML_ORDER_MEMBER, NAMESPACE); + while (it.hasNext()) { + Element el = it.nextElement(); + try { + // retrieve text 'DAV:segment' child of this DAV:order-member element + String segment = DomUtil.getChildText(el, XML_SEGMENT, NAMESPACE); + // retrieve the 'DAV:position' child element + Position pos = Position.createFromXml(DomUtil.getChildElement(el, XML_POSITION, NAMESPACE)); + Member om = new Member(segment, pos); + tmpList.add(om); + } catch (IllegalArgumentException e) { + log.warn("Invalid element in 'orderpatch' request body: " + e.getMessage()); + throw new DavException(DavServletResponse.SC_BAD_REQUEST); + } + } + Member[] instructions = tmpList.toArray(new Member[tmpList.size()]); + return new OrderPatch(orderingType, instructions); + } + + //-------------------------------------------------------------------------- + /** + * Internal class Member represents the 'Order-Member' children + * elements of an 'OrderPatch' request body present in the ORDERPATCH request. + */ + public static class Member implements XmlSerializable { + + private String memberHandle; + private Position position; + + /** + * Create a new Member object. + * + * @param memberHandle + * @param position + */ + public Member(String memberHandle, Position position) { + this.memberHandle = memberHandle; + this.position = position; + } + + /** + * Return the handle of the internal member to be reordered. + * + * @return handle of the internal member. + */ + public String getMemberHandle() { + return memberHandle; + } + + /** + * Return the position where the internal member identified by the + * member handle should be placed. + * + * @return position for the member after the request. + * @see #getMemberHandle() + */ + public Position getPosition() { + return position; + } + + //--------------------------------------< XmlSerializable interface >--- + /** + * @see org.apache.jackrabbit.webdav.xml.XmlSerializable#toXml(Document) + */ + public Element toXml(Document document) { + Element memberElem = DomUtil.createElement(document, XML_ORDER_MEMBER, NAMESPACE); + DomUtil.addChildElement(memberElem, XML_SEGMENT, NAMESPACE, memberHandle); + memberElem.appendChild(position.toXml(document)); + return memberElem; + } + + } +} Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/ordering/OrderPatch.java ___________________________________________________________________ Added: svn Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/ordering/OrderingConstants.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/ordering/OrderingConstants.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/ordering/OrderingConstants.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.webdav.ordering; + +import org.apache.jackrabbit.webdav.DavConstants; +import org.apache.jackrabbit.webdav.property.DavPropertyName; +import org.apache.jackrabbit.webdav.xml.Namespace; + +/** + * OrderingConstants provide constants for request and response + * headers, Xml elements and property names defined by + * RFC 3648. + */ +public interface OrderingConstants { + + /** + * The namespace + */ + public static final Namespace NAMESPACE = DavConstants.NAMESPACE; + + /** + * Constant representing the DAV:custom ordering type URI, which indicates + * that the collection is not ordered. + */ + public static final String ORDERING_TYPE_CUSTOM = "DAV:custom"; + + /** + * Constant representing the DAV:unordered ordering type URI, which indicates + * that the collection is to be ordered, but the semantics of the ordering + * is not being advertised. + */ + public static final String ORDERING_TYPE_UNORDERED = "DAV:unordered"; + + //---< Headers >------------------------------------------------------------ + /** + * The "Ordering-Type" request header. + */ + public static final String HEADER_ORDERING_TYPE = "Ordering-Type"; + + /** + * When a new member is added to a collection with a client-maintained + * ordering (for example, with PUT, COPY, or MKCOL), its position in the + * ordering can be set with the new Position header.

+ * + * Position = "Position" ":" ("first" | "last" | (("before" | "after") segment)) + * + *

NOTE: segment is defined in section 3.3 of RFC2396. + */ + public static final String HEADER_POSITION = "Position"; + + //---< XML Element, Attribute Names >--------------------------------------- + /** + * Xml elements used for reordering internal members of a collection. + */ + public static final String XML_ORDERPATCH = "orderpatch"; + public static final String XML_ORDERING_TYPE = "ordering-type"; + public static final String XML_ORDER_MEMBER = "order-member"; + public static final String XML_POSITION = "position"; + public static final String XML_SEGMENT = "segment"; + + public static final String XML_FIRST = "first"; + public static final String XML_LAST = "last"; + public static final String XML_BEFORE = "before"; + public static final String XML_AFTER = "after"; + + //---< XML Element, Attribute Names >--------------------------------------- + /** + * The DAV:ordering-type property indicates whether the collection is + * ordered and, if so, uniquely identifies the semantics of the ordering. + * + * @see OrderingType + */ + public static final DavPropertyName ORDERING_TYPE = DavPropertyName.create("ordering-type", DavConstants.NAMESPACE); + + /** + * Required live property for resources that honor the 'ordered-collections' + * compliance class defined by RFC 3648.
+ * The supported-method-set property has been introduced with RFC 3253. + * + * @see org.apache.jackrabbit.webdav.version.DeltaVConstants#SUPPORTED_METHOD_SET + */ + public static final DavPropertyName SUPPORTED_METHOD_SET = DavPropertyName.create("supported-method-set", DavConstants.NAMESPACE); + + /** + * Required live property for resources that honor the 'ordered-collections' + * compliance class defined by RFC 3648.
+ * The supported-live-property-set property has been introduced with RFC 3253. + * + * @see org.apache.jackrabbit.webdav.version.DeltaVConstants#SUPPORTED_LIVE_PROPERTY_SET + */ + public static final DavPropertyName SUPPORTED_LIVE_PROPERTY_SET = DavPropertyName.create("supported-live-property-set", DavConstants.NAMESPACE); +} \ No newline at end of file Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/ordering/OrderingConstants.java ___________________________________________________________________ Added: svn Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/ordering/OrderingDavServletRequest.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/ordering/OrderingDavServletRequest.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/ordering/OrderingDavServletRequest.java (working copy) @@ -0,0 +1,55 @@ +/* + * 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.webdav.ordering; + +import org.apache.jackrabbit.webdav.DavException; +import org.apache.jackrabbit.webdav.DavServletRequest; + +/** + * OrderingDavServletRequest provides extensions to the + * {@link DavServletRequest} interface used for ordering members of orderable + * collections. + */ +public interface OrderingDavServletRequest extends DavServletRequest { + + /** + * Returns the {@link OrderingConstants#HEADER_ORDERING_TYPE Ordering-Type header}. + * + * @return the String value of the {@link OrderingConstants#HEADER_ORDERING_TYPE Ordering-Type header}. + */ + public String getOrderingType(); + + /** + * Return a Position object encapsulating the {@link OrderingConstants#HEADER_POSITION + * Position header} field or null if no Position header is present + * or does not contain a valid format. + * + * @return Position object encapsulating the {@link OrderingConstants#HEADER_POSITION + * Position header} + */ + public Position getPosition(); + + /** + * Return a OrderPatch object encapsulating the request body + * of an ORDERPATCH request or null if the request body was + * either missing or could not be parsed. + * + * @return OrderPatch object encapsulating the request body. + */ + public OrderPatch getOrderPatch() throws DavException; + +} \ No newline at end of file Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/ordering/OrderingDavServletRequest.java ___________________________________________________________________ Added: svn Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/ordering/OrderingResource.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/ordering/OrderingResource.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/ordering/OrderingResource.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.webdav.ordering; + +import org.apache.jackrabbit.webdav.DavException; +import org.apache.jackrabbit.webdav.DavResource; + +/** + * OrderingResource extends the {@link DavResource} interface by + * METHODS relating to ordering functionality defined by + * RFC 3648. + */ +public interface OrderingResource extends DavResource { + + public String METHODS = "ORDERPATCH"; + + /** + * Returns true if this resources allows ordering of its internal members. + * + * @return true if internal members are orderable. + */ + public boolean isOrderable(); + + /** + * Reorders the internal members of this resource according to the + * instructions present in the specified {@link OrderPatch} object. + * + * @param orderPatch as present in the ORDERPATCH request body. + * @throws DavException + */ + public void orderMembers(OrderPatch orderPatch) throws DavException; + +} \ No newline at end of file Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/ordering/OrderingResource.java ___________________________________________________________________ Added: svn Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/ordering/OrderingType.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/ordering/OrderingType.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/ordering/OrderingType.java (working copy) @@ -0,0 +1,52 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.jackrabbit.webdav.ordering; + +import org.apache.jackrabbit.webdav.property.HrefProperty; + +/** + * OrderingType represents the {@link #ORDERING_TYPE + * DAV:ordering-type} property as defined by + * RFC 3648. This property is + * protected cannot be set using PROPPATCH. Its value may only be set by + * including the Ordering-Type header with a MKCOL request or by submitting an + * ORDERPATCH request. + * + * @see org.apache.jackrabbit.webdav.property.DavProperty#isInvisibleInAllprop() + */ +public class OrderingType extends HrefProperty implements OrderingConstants { + + /** + * Creates a OrderingType with the default type (e.g. default + * value). The default value is specified to be {@link #ORDERING_TYPE_UNORDERED}. + */ + public OrderingType() { + this(null); + } + + /** + * Create an OrderingType with the given ordering.
+ * NOTE: the ordering-type property is defined to be protected. + * + * @param href + * @see org.apache.jackrabbit.webdav.property.DavProperty#isInvisibleInAllprop() + */ + public OrderingType(String href) { + // spec requires that the default value is 'DAV:unordered' + super(ORDERING_TYPE, (href != null) ? href : ORDERING_TYPE_UNORDERED, true); + } +} Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/ordering/OrderingType.java ___________________________________________________________________ Added: svn Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/ordering/Position.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/ordering/Position.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/ordering/Position.java (working copy) @@ -0,0 +1,164 @@ +/* + * 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.webdav.ordering; + +import org.apache.jackrabbit.webdav.xml.DomUtil; +import org.apache.jackrabbit.webdav.xml.ElementIterator; +import org.apache.jackrabbit.webdav.xml.XmlSerializable; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +import java.util.HashSet; +import java.util.Set; + +/** + * Position encapsulates the position in ordering information + * contained in a Webdav request. This includes both the + * {@link OrderingConstants#HEADER_POSITION Position header} and the position + * Xml element present in the request body of an ORDERPATCH request. + * + * @see OrderingConstants#HEADER_POSITION + * @see OrderingConstants#XML_POSITION + * @see OrderPatch + */ +public class Position implements OrderingConstants, XmlSerializable { + + private static Logger log = LoggerFactory.getLogger(Position.class); + + private static final Set VALID_TYPES = new HashSet(); + static { + VALID_TYPES.add(XML_FIRST); + VALID_TYPES.add(XML_LAST); + VALID_TYPES.add(XML_AFTER); + VALID_TYPES.add(XML_BEFORE); + } + + private final String type; + private final String segment; + + /** + * Create a new Position object with the specified type. + * Since any type except for {@link #XML_FIRST first} and {@link #XML_LAST last} + * must be combined with a segment, only the mentioned types are valid + * arguments. + * + * @param type {@link #XML_FIRST first} or {@link #XML_LAST last} + * @throws IllegalArgumentException if the given type is other than {@link #XML_FIRST} + * or {@link #XML_LAST}. + */ + public Position(String type) { + if (!VALID_TYPES.contains(type)) { + throw new IllegalArgumentException("Invalid type: " + type); + } + if (!(XML_FIRST.equals(type) || XML_LAST.equals(type))) { + throw new IllegalArgumentException("If type is other than 'first' or 'last' a segment must be specified"); + } + this.type = type; + this.segment = null; + } + + /** + * Create a new Position object with the specified type and + * segment. + * + * @param type + * @param segment + * @throws IllegalArgumentException if the specified type and segment do not + * form a valid pair. + */ + public Position(String type, String segment) { + if (!VALID_TYPES.contains(type)) { + throw new IllegalArgumentException("Invalid type: " + type); + } + if ((XML_AFTER.equals(type) || XML_BEFORE.equals(type)) && (segment == null || "".equals(segment))) { + throw new IllegalArgumentException("If type is other than 'first' or 'last' a segment must be specified"); + } + this.type = type; + this.segment = segment; + } + + /** + * Return the type of this Position object, which may be any + * of the following valid types: {@link #XML_FIRST first}, + * {@link #XML_LAST last}, {@link #XML_AFTER after}, {@link #XML_BEFORE before} + * + * @return type + */ + public String getType() { + return type; + } + + /** + * Returns the segment used to create this Position object or + * null if no segment is present with the type. + * + * @return segment or null + * @see #getType() + */ + public String getSegment() { + return segment; + } + + //------------------------------------------< XmlSerializable interface >--- + /** + * @see org.apache.jackrabbit.webdav.xml.XmlSerializable#toXml(Document) + * @param document + */ + public Element toXml(Document document) { + Element positionElement = DomUtil.createElement(document, XML_POSITION, NAMESPACE); + Element typeElement = DomUtil.addChildElement(positionElement, type, NAMESPACE); + if (segment != null) { + DomUtil.addChildElement(typeElement, XML_SEGMENT, NAMESPACE, segment); + } + return positionElement; + } + + //-----------------------------------------------------< static methods >--- + /** + * Create a new Position object from the specified position + * element. The element must fulfill the following structure:
+ *
+     * <!ELEMENT position (first | last | before | after) >
+     * <!ELEMENT segment (#PCDATA) >
+     * <!ELEMENT first EMPTY >
+     * <!ELEMENT last EMPTY >
+     * <!ELEMENT before segment >
+     * <!ELEMENT after segment >
+     * 
+ * + * @param positionElement Xml element defining the position. + * @throws IllegalArgumentException if the given Xml element is not valid. + */ + public static Position createFromXml(Element positionElement) { + if (!DomUtil.matches(positionElement, XML_POSITION, NAMESPACE)) { + throw new IllegalArgumentException("The 'DAV:position' element required."); + } + ElementIterator it = DomUtil.getChildren(positionElement); + if (it.hasNext()) { + Element el = it.nextElement(); + String type = el.getLocalName(); + // read the text of DAV:segment child element inside the type + String segmentText = DomUtil.getChildText(el, XML_SEGMENT, NAMESPACE); + // stop after the first iteration + return new Position(type, segmentText); + } else { + throw new IllegalArgumentException("The 'DAV:position' element required with exact one child indicating the type."); + } + } +} Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/ordering/Position.java ___________________________________________________________________ Added: svn Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/ordering/package-info.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/ordering/package-info.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/ordering/package-info.java (working copy) @@ -0,0 +1,18 @@ +/* + * 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. + */ +@org.osgi.annotation.versioning.Version("1.0.0") +package org.apache.jackrabbit.webdav.ordering; Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/ordering/package-info.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/package-info.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/package-info.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/package-info.java (working copy) @@ -0,0 +1,18 @@ +/* + * 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. + */ +@org.osgi.annotation.versioning.Version("1.4.0") +package org.apache.jackrabbit.webdav; Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/package-info.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/property/AbstractDavProperty.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/property/AbstractDavProperty.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/property/AbstractDavProperty.java (working copy) @@ -0,0 +1,163 @@ +/* + * 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.webdav.property; + +import org.apache.jackrabbit.webdav.DavConstants; +import org.apache.jackrabbit.webdav.xml.DomUtil; +import org.apache.jackrabbit.webdav.xml.XmlSerializable; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.Node; + +import java.util.Collection; + +/** + * AbstractDavProperty provides generic METHODS used by various + * implementations of the {@link DavProperty} interface. + */ +public abstract class AbstractDavProperty implements DavProperty { + + private static Logger log = LoggerFactory.getLogger(AbstractDavProperty.class); + + private final DavPropertyName name; + private final boolean isInvisibleInAllprop; + + /** + * Create a new AbstractDavProperty with the given {@link DavPropertyName} + * and a boolean flag indicating whether this property should be suppressed + * in PROPFIND/allprop responses. + */ + public AbstractDavProperty(DavPropertyName name, boolean isInvisibleInAllprop) { + this.name = name; + this.isInvisibleInAllprop = isInvisibleInAllprop; + } + + /** + * Computes the hash code using this property's name and value. + * + * @return the hash code + */ + @Override + public int hashCode() { + int hashCode = getName().hashCode(); + if (getValue() != null) { + hashCode += getValue().hashCode(); + } + return hashCode % Integer.MAX_VALUE; + } + + /** + * Checks if this property has the same {@link DavPropertyName name} + * and value as the given one. + * + * @param obj the object to compare to + * @return true if the 2 objects are equal; + * false otherwise + */ + @Override + public boolean equals(Object obj) { + if (obj instanceof DavProperty) { + DavProperty prop = (DavProperty) obj; + boolean equalName = getName().equals(prop.getName()); + boolean equalValue = (getValue() == null) ? prop.getValue() == null : getValue().equals(prop.getValue()); + return equalName && equalValue; + } + return false; + } + + + /** + * Return a XML element representation of this property. The value of the + * property will be added as text or as child element. + *
+     * new DavProperty("displayname", "WebDAV Directory").toXml
+     * gives a element like:
+     * <D:displayname>WebDAV Directory</D:displayname>
+     *
+     * new DavProperty("resourcetype", new Element("collection")).toXml
+     * gives a element like:
+     * <D:resourcetype><D:collection/></D:resourcetype>
+     *
+     * Element[] customVals = { new Element("bla", customNamespace), new Element("bli", customNamespace) };
+     * new DavProperty("custom-property", customVals, customNamespace).toXml
+     * gives an element like
+     * <Z:custom-property>
+     *    <Z:bla/>
+     *    <Z:bli/>
+     * </Z:custom-property>
+     * 
+ * + * @return a XML element of this property + * @see org.apache.jackrabbit.webdav.xml.XmlSerializable#toXml(Document) + * @param document + */ + public Element toXml(Document document) { + Element elem = getName().toXml(document); + T value = getValue(); + // todo: improve.... + if (value != null) { + if (value instanceof XmlSerializable) { + elem.appendChild(((XmlSerializable)value).toXml(document)); + } else if (value instanceof Node) { + Node n = document.importNode((Node)value, true); + elem.appendChild(n); + } else if (value instanceof Node[]) { + for (int i = 0; i < ((Node[])value).length; i++) { + Node n = document.importNode(((Node[])value)[i], true); + elem.appendChild(n); + } + } else if (value instanceof Collection) { + for (Object entry : ((Collection) value)) { + if (entry instanceof XmlSerializable) { + elem.appendChild(((XmlSerializable) entry).toXml(document)); + } else if (entry instanceof Node) { + Node n = document.importNode((Node) entry, true); + elem.appendChild(n); + } else { + DomUtil.setText(elem, entry.toString()); + } + } + } else { + DomUtil.setText(elem, value.toString()); + } + } + return elem; + } + + /** + * Returns the name of this property. + * + * @return name + * @see DavProperty#getName() + */ + public DavPropertyName getName() { + return name; + } + + /** + * Return true if this property should be suppressed + * in a PROPFIND/{@link DavConstants#PROPFIND_ALL_PROP DAV:allprop} + * response. See RFC 4918, Section 9.1. + * + * @see org.apache.jackrabbit.webdav.property.DavProperty#isInvisibleInAllprop() + */ + public boolean isInvisibleInAllprop() { + return isInvisibleInAllprop; + } +} Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/property/AbstractDavProperty.java ___________________________________________________________________ Added: svn Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/property/DavProperty.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/property/DavProperty.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/property/DavProperty.java (working copy) @@ -0,0 +1,71 @@ +/* + * 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.webdav.property; + +import org.apache.jackrabbit.webdav.DavConstants; +import org.apache.jackrabbit.webdav.xml.XmlSerializable; + +/** + * The Property class represents a Property of a WebDAV + * resource. The {@link Object#hashCode()} and {@link Object#equals(Object)} methods are + * overridden in a way, such that the name and value of the property are + * respected. This means, a property is equal to another if the names + * and values are equal.
+ * The XML representation of a DavProperty: + *
+ * new DavProperty("displayname", "WebDAV Directory").toXml
+ * gives a element like:
+ * <D:displayname>WebDAV Directory</D:displayname>
+ *
+ * new DavProperty("resourcetype", new Element("collection")).toXml
+ * gives a element like:
+ * <D:resourcetype><D:collection/></D:resourcetype>
+ *
+ * Element[] customVals = { new Element("bla", customNamespace), new Element("bli", customNamespace) };
+ * new DavProperty("custom-property", customVals, customNamespace).toXml
+ * gives an element like
+ * <Z:custom-property>
+ *    <Z:bla/>
+ *    <Z:bli/>
+ * </Z:custom-property>
+ * 
+ */ +public interface DavProperty extends XmlSerializable, DavConstants, PropEntry { + + /** + * Returns the name of this property + * + * @return the name of this property + */ + public DavPropertyName getName(); + + /** + * Returns the value of this property + * + * @return the value of this property + */ + public T getValue(); + + /** + * Return true if this property should be suppressed + * in a PROPFIND/{@link DavConstants#PROPFIND_ALL_PROP DAV:allprop} + * response. See RFC 4918, Section 9.1. + * + * @return true, if this property should be suppressed in a PROPFIND/allprop response + */ + public boolean isInvisibleInAllprop(); +} Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/property/DavProperty.java ___________________________________________________________________ Added: svn Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/property/DavPropertyIterator.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/property/DavPropertyIterator.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/property/DavPropertyIterator.java (working copy) @@ -0,0 +1,34 @@ +/* + * 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.webdav.property; + +import java.util.Iterator; +import java.util.NoSuchElementException; + +/** + * The DavPropertyIterator extends the Iterator by + * a property specific next() method. + */ +public interface DavPropertyIterator extends Iterator> { + /** + * Returns the next Property. + * + * @return the next Property in the iteration. + * @throws java.util.NoSuchElementException if iteration has no more elements. + */ + public DavProperty nextProperty() throws NoSuchElementException; +} Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/property/DavPropertyIterator.java ___________________________________________________________________ Added: svn Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/property/DavPropertyName.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/property/DavPropertyName.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/property/DavPropertyName.java (working copy) @@ -0,0 +1,206 @@ +/* + * 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.webdav.property; + +import org.apache.jackrabbit.webdav.DavConstants; +import org.apache.jackrabbit.webdav.xml.DomUtil; +import org.apache.jackrabbit.webdav.xml.Namespace; +import org.apache.jackrabbit.webdav.xml.XmlSerializable; +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +import java.util.HashMap; +import java.util.Map; + +/** + * The DavPropertyName class reflects a WebDAV property name. It + * holds together the local name of the property and its namespace. + */ +public class DavPropertyName implements DavConstants, XmlSerializable, PropEntry { + + /** internal 'cache' of created property names */ + private static final Map> cache = new HashMap>(); + + /* some standard webdav property (that have #PCDATA) */ + public static final DavPropertyName CREATIONDATE = DavPropertyName.create(PROPERTY_CREATIONDATE); + public static final DavPropertyName DISPLAYNAME = DavPropertyName.create(PROPERTY_DISPLAYNAME); + public static final DavPropertyName GETCONTENTLANGUAGE = DavPropertyName.create(PROPERTY_GETCONTENTLANGUAGE); + public static final DavPropertyName GETCONTENTLENGTH = DavPropertyName.create(PROPERTY_GETCONTENTLENGTH); + public static final DavPropertyName GETCONTENTTYPE = DavPropertyName.create(PROPERTY_GETCONTENTTYPE); + public static final DavPropertyName GETETAG = DavPropertyName.create(PROPERTY_GETETAG); + public static final DavPropertyName GETLASTMODIFIED = DavPropertyName.create(PROPERTY_GETLASTMODIFIED); + + /* some standard webdav property (that have other elements) */ + public static final DavPropertyName LOCKDISCOVERY = DavPropertyName.create(PROPERTY_LOCKDISCOVERY); + public static final DavPropertyName RESOURCETYPE = DavPropertyName.create(PROPERTY_RESOURCETYPE); + public static final DavPropertyName SOURCE = DavPropertyName.create(PROPERTY_SOURCE); + public static final DavPropertyName SUPPORTEDLOCK = DavPropertyName.create(PROPERTY_SUPPORTEDLOCK); + + /* property use by microsoft that are not specified in the RFC 2518 */ + public static final DavPropertyName ISCOLLECTION = DavPropertyName.create("iscollection"); + + /** the name of the property */ + private final String name; + + /** the namespace of the property */ + private final Namespace namespace; + + /** + * Creates a new DavPropertyName with the given name and + * Namespace. + * + * @param name The local name of the new property name + * @param namespace The namespace of the new property name + * + * @return The WebDAV property name + */ + public synchronized static DavPropertyName create(String name, Namespace namespace) { + + // get (or create) map for the given namespace + Map map = cache.get(namespace); + if (map == null) { + map = new HashMap(); + cache.put(namespace, map); + } + // get (or create) property name object + DavPropertyName ret = map.get(name); + if (ret == null) { + if (namespace.equals(NAMESPACE)) { + // ensure prefix for default 'DAV:' namespace + namespace = NAMESPACE; + } + ret = new DavPropertyName(name, namespace); + map.put(name, ret); + } + return ret; + } + + /** + * Creates a new DavPropertyName with the given local name + * and the default WebDAV {@link DavConstants#NAMESPACE namespace}. + * + * @param name The local name of the new property name + * + * @return The WebDAV property name + */ + public synchronized static DavPropertyName create(String name) { + return create(name, NAMESPACE); + } + + /** + * Create a new DavPropertyName with the name and namespace + * of the given Xml element. + * + * @param nameElement + * @return DavPropertyName instance + */ + public synchronized static DavPropertyName createFromXml(Element nameElement) { + if (nameElement == null) { + throw new IllegalArgumentException("Cannot build DavPropertyName from a 'null' element."); + } + String ns = nameElement.getNamespaceURI(); + if (ns == null) { + return create(nameElement.getLocalName(), Namespace.EMPTY_NAMESPACE); + } else { + return create(nameElement.getLocalName(), Namespace.getNamespace(nameElement.getPrefix(), ns)); + } + } + + /** + * Creates a new DavPropertyName with the given name and + * Namespace. + * + * @param name The local name of the new property name + * @param namespace The namespace of the new property name + */ + private DavPropertyName(String name, Namespace namespace) { + if (name == null || namespace == null) { + throw new IllegalArgumentException("Name and namespace must not be 'null' for a DavPropertyName."); + } + this.name = name; + this.namespace = namespace; + } + + /** + * Return the name of this DavPropertyName. + * + * @return name + */ + public String getName() { + return name; + } + + /** + * Return the namespace of this DavPropertyName. + * + * @return namespace + */ + public Namespace getNamespace() { + return namespace; + } + + /** + * Computes the hash code using this properties name and namespace. + * + * @return the hash code + */ + @Override + public int hashCode() { + return (name.hashCode() + namespace.hashCode()) % Integer.MAX_VALUE; + } + + /** + * Checks if this property has the same name and namespace as the + * given one. + * + * @param obj the object to compare to + * + * @return true if the 2 objects are equal; + * false otherwise + */ + @Override + public boolean equals(Object obj) { + if (obj instanceof DavPropertyName) { + DavPropertyName propName = (DavPropertyName) obj; + return name.equals(propName.name) && namespace.equals(propName.namespace); + } + return false; + } + + /** + * Returns a string representation of this property suitable for debugging + * + * @return a human readable string representation + */ + @Override + public String toString() { + return DomUtil.getExpandedName(name, namespace); + } + + /** + * Creates a element with the name and namespace of this + * DavPropertyName. + * + * @return A element with the name and namespace of this + * DavPropertyName. + * @param document + */ + public Element toXml(Document document) { + return DomUtil.createElement(document, name, namespace); + } +} + Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/property/DavPropertyName.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/property/DavPropertyNameIterator.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/property/DavPropertyNameIterator.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/property/DavPropertyNameIterator.java (working copy) @@ -0,0 +1,28 @@ +/* + * 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.webdav.property; + +import java.util.Iterator; + +/** + * DavPropertyNameIterator... + */ +public interface DavPropertyNameIterator extends Iterator { + + public DavPropertyName nextPropertyName(); + +} Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/property/DavPropertyNameIterator.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-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/property/DavPropertyNameSet.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/property/DavPropertyNameSet.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/property/DavPropertyNameSet.java (working copy) @@ -0,0 +1,203 @@ +/* + * 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.webdav.property; + +import org.apache.jackrabbit.webdav.xml.DomUtil; +import org.apache.jackrabbit.webdav.xml.ElementIterator; +import org.apache.jackrabbit.webdav.xml.Namespace; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.w3c.dom.Element; + +import java.util.Collection; +import java.util.HashSet; +import java.util.Iterator; +import java.util.Set; + +/** + * DavPropertyNameSet represents a Set of {@link DavPropertyName} + * objects. + */ +public class DavPropertyNameSet extends PropContainer + implements Iterable { + + private static Logger log = LoggerFactory.getLogger(DavPropertyNameSet.class); + private final Set set = new HashSet(); + + /** + * Create a new empty set. + */ + public DavPropertyNameSet() { + } + + /** + * Create a new DavPropertyNameSet with the given initial values. + * + * @param initialSet + */ + public DavPropertyNameSet(DavPropertyNameSet initialSet) { + addAll(initialSet); + } + + /** + * Create a new DavPropertyNameSet from the given DAV:prop + * element. + * + * @param propElement + * @throws IllegalArgumentException if the specified element is null + * or is not a DAV:prop element. + */ + public DavPropertyNameSet(Element propElement) { + if (!DomUtil.matches(propElement, XML_PROP, NAMESPACE)) { + throw new IllegalArgumentException("'DAV:prop' element expected."); + } + + // fill the set + ElementIterator it = DomUtil.getChildren(propElement); + while (it.hasNext()) { + add(DavPropertyName.createFromXml(it.nextElement())); + } + } + + /** + * Adds the specified {@link DavPropertyName} object to this + * set if it is not already present. + * + * @param propertyName element to be added to this set. + * @return {@code true} if the set did not already contain the specified + * element. + */ + public boolean add(DavPropertyName propertyName) { + return set.add(propertyName); + } + + /** + * Creates a DavPropertyName from the given parameters and add it to this set. + * + * @param localName + * @param namespace + * @return {@code true} if the set did not already contain the specified + * property name. + */ + public boolean add(String localName, Namespace namespace) { + return set.add(DavPropertyName.create(localName, namespace)); + } + + /** + * Add the property names contained in the specified set to this set. + * + * @param propertyNames + * @return true if the set has been modified by this call. + */ + public boolean addAll(DavPropertyNameSet propertyNames) { + return set.addAll(propertyNames.set); + } + + /** + * Removes the specified {@link DavPropertyName} object from this set. + * + * @param propertyName + * @return true if the given property name could be removed. + * @see HashSet#remove(Object) + */ + public boolean remove(DavPropertyName propertyName) { + return set.remove(propertyName); + } + + /** + * @return Iterator over all DavPropertyNames contained in this + * set. + */ + public DavPropertyNameIterator iterator() { + return new PropertyNameIterator(); + } + + //------------------------------------------------------< PropContainer >--- + /** + * @see PropContainer#contains(DavPropertyName) + */ + @Override + public boolean contains(DavPropertyName name) { + return set.contains(name); + } + + /** + * @param contentEntry NOTE that an instance of DavPropertyName + * in order to successfully add the given entry. + * @return true if contentEntry is an instance of DavPropertyName + * that could be added to this set. False otherwise. + * @see PropContainer#addContent(Object) + */ + @Override + public boolean addContent(PropEntry contentEntry) { + if (contentEntry instanceof DavPropertyName) { + return add((DavPropertyName) contentEntry); + } + log.debug("DavPropertyName object expected. Found: " + contentEntry.getClass().toString()); + return false; + } + + /** + * @see PropContainer#isEmpty() + */ + @Override + public boolean isEmpty() { + return set.isEmpty(); + } + + /** + * @see PropContainer#getContentSize() + */ + @Override + public int getContentSize() { + return set.size(); + } + + /** + * @see PropContainer#getContent() + */ + @Override + public Collection getContent() { + return set; + } + + //--------------------------------------------------------< inner class >--- + private class PropertyNameIterator implements DavPropertyNameIterator { + + private Iterator iter; + + private PropertyNameIterator() { + this.iter = set.iterator(); + } + + public DavPropertyName nextPropertyName() { + return iter.next(); + } + + public void remove() { + iter.remove(); + } + + public boolean hasNext() { + return iter.hasNext(); + } + + public DavPropertyName next() { + return iter.next(); + } + } +} Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/property/DavPropertyNameSet.java ___________________________________________________________________ Added: svn Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/property/DavPropertySet.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/property/DavPropertySet.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/property/DavPropertySet.java (working copy) @@ -0,0 +1,300 @@ +/* + * 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.webdav.property; + +import org.apache.jackrabbit.webdav.xml.Namespace; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.Collection; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; +import java.util.NoSuchElementException; + +/** + * The DavPropertySet class represents a set of WebDAV + * property. + */ +public class DavPropertySet extends PropContainer + implements Iterable> { + + private static Logger log = LoggerFactory.getLogger(DavPropertySet.class); + + /** + * the set of property + */ + private final Map> map = new HashMap>(); + + /** + * Adds a new property to this set. + * + * @param property The property to add + * + * @return The previously assigned property or null. + */ + public DavProperty add(DavProperty property) { + return map.put(property.getName(), property); + } + + /** + * + * @param pset Properties to add + */ + public void addAll(DavPropertySet pset) { + map.putAll(pset.map); + } + + /** + * Retrieves the property with the specified name and the + * default WebDAV {@link org.apache.jackrabbit.webdav.DavConstants#NAMESPACE namespace}. + * + * @param name The name of the property to retrieve + * + * @return The desired property or null + */ + public DavProperty get(String name) { + return get(DavPropertyName.create(name)); + } + + /** + * Retrieves the property with the specified name and + * namespace. + * + * @param name The name of the property to retrieve + * @param namespace The namespace of the property to retrieve + * + * @return The desired property or null + */ + public DavProperty get(String name, Namespace namespace) { + return get(DavPropertyName.create(name, namespace)); + } + + /** + * Retrieves the property with the specified name + * + * @param name The webdav property name of the property to retrieve + * + * @return The desired property or null + */ + public DavProperty get(DavPropertyName name) { + return map.get(name); + } + + + /** + * Removes the indicated property from this set. + * + * @param name The webdav property name to remove + * + * @return The removed property or null + */ + public DavProperty remove(DavPropertyName name) { + return map.remove(name); + } + + /** + * Removes the property with the specified name and the + * default WebDAV {@link org.apache.jackrabbit.webdav.DavConstants#NAMESPACE namespace}. + * + * @param name The name of the property to remove + * + * @return The removed property or null + */ + public DavProperty remove(String name) { + return remove(DavPropertyName.create(name)); + } + + /** + * Removes the property with the specified name and + * namespace from this set. + * + * @param name The name of the property to remove + * @param namespace The namespace of the property to remove + * + * @return The removed property or null + */ + public DavProperty remove(String name, Namespace namespace) { + return remove(DavPropertyName.create(name, namespace)); + } + + /** + * Returns an iterator over all property in this set. + * + * @return An iterator over {@link DavProperty}. + */ + public DavPropertyIterator iterator() { + return new PropIter(); + } + + /** + * Returns an iterator over all those property in this set, that have the + * indicated namespace. + * + * @param namespace The namespace of the property in the iteration. + * + * @return An iterator over {@link DavProperty}. + */ + public DavPropertyIterator iterator(Namespace namespace) { + return new PropIter(namespace); + } + + /** + * Return the names of all properties present in this set. + * + * @return array of {@link DavPropertyName property names} present in this set. + */ + public DavPropertyName[] getPropertyNames() { + return map.keySet().toArray(new DavPropertyName[map.keySet().size()]); + } + + //------------------------------------------------------< PropContainer >--- + /** + * Checks if this set contains the property with the specified name. + * + * @param name The name of the property + * @return true if this set contains the property; + * false otherwise. + * @see PropContainer#contains(DavPropertyName) + */ + @Override + public boolean contains(DavPropertyName name) { + return map.containsKey(name); + } + + /** + * @param contentEntry NOTE, that the given object must be an instance of + * DavProperty in order to be successfully added to this set. + * @return true if the specified object is an instance of DavProperty + * and false otherwise. + * @see PropContainer#addContent(PropEntry) + */ + @Override + public boolean addContent(PropEntry contentEntry) { + if (contentEntry instanceof DavProperty) { + add((DavProperty) contentEntry); + return true; + } + log.debug("DavProperty object expected. Found: " + contentEntry.getClass().toString()); + return false; + } + + /** + * @see PropContainer#isEmpty() + */ + @Override + public boolean isEmpty() { + return map.isEmpty(); + } + + /** + * @see PropContainer#getContentSize() + */ + @Override + public int getContentSize() { + return map.size(); + } + + /** + * @see PropContainer#getContent() + */ + @Override + public Collection getContent() { + return map.values(); + } + + //---------------------------------------------------------- Inner class --- + /** + * Implementation of a DavPropertyIterator that returns webdav property. + * Additionally, it can only return property with the given namespace. + */ + private class PropIter implements DavPropertyIterator { + + /** the namespace to match against */ + private final Namespace namespace; + + /** the internal iterator */ + private final Iterator> iterator; + + /** the next property to return */ + private DavProperty next; + + /** + * Creates a new property iterator. + */ + private PropIter() { + this(null); + } + + /** + * Creates a new iterator with the given namespace + * @param namespace The namespace to match against + */ + private PropIter(Namespace namespace) { + this.namespace = namespace; + iterator = map.values().iterator(); + seek(); + } + + /** + * @see DavPropertyIterator#nextProperty(); + */ + public DavProperty nextProperty() throws NoSuchElementException { + if (next==null) { + throw new NoSuchElementException(); + } + DavProperty ret = next; + seek(); + return ret; + } + + /** + * @see DavPropertyIterator#hasNext(); + */ + public boolean hasNext() { + return next!=null; + } + + /** + * @see DavPropertyIterator#next(); + */ + public DavProperty next() { + return nextProperty(); + } + + /** + * @see DavPropertyIterator#remove(); + */ + public void remove() { + throw new UnsupportedOperationException(); + } + + /** + * Seeks for the next valid property + */ + private void seek() { + while (iterator.hasNext()) { + next = iterator.next(); + if (namespace == null || namespace.equals(next.getName().getNamespace())) { + return; + } + } + next = null; + } + } +} + Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/property/DavPropertySet.java ___________________________________________________________________ Added: svn Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/property/DefaultDavProperty.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/property/DefaultDavProperty.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/property/DefaultDavProperty.java (working copy) @@ -0,0 +1,144 @@ +/* + * 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.webdav.property; + +import org.apache.jackrabbit.webdav.xml.DomUtil; +import org.apache.jackrabbit.webdav.xml.Namespace; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.w3c.dom.Element; +import org.w3c.dom.Node; + +import java.util.List; + +/** + * DefaultDavProperty... + */ +public class DefaultDavProperty extends AbstractDavProperty { + + private static Logger log = LoggerFactory.getLogger(DefaultDavProperty.class); + + /** + * the value of the property + */ + private final T value; + + /** + * Creates a new WebDAV property with the given namespace, name and value. + * If the property is intended to be protected the isProtected flag must + * be set to true. + * + * @param name the name of the property + * @param value the value of the property + * @param namespace the namespace of the property + * @param isInvisibleInAllprop A value of true, defines this property to be protected. + * It will not be returned in a {@link org.apache.jackrabbit.webdav.DavConstants#PROPFIND_ALL_PROP DAV:allprop} + * PROPFIND request and cannot be set/removed with a PROPPATCH request. + */ + public DefaultDavProperty(String name, T value, Namespace namespace, boolean isInvisibleInAllprop) { + super(DavPropertyName.create(name, namespace), isInvisibleInAllprop); + this.value = value; + } + + /** + * Creates a new non-protected WebDAV property with the given namespace, name + * and value. + * + * @param name the name of the property + * @param value the value of the property + * @param namespace the namespace of the property + */ + public DefaultDavProperty(String name, T value, Namespace namespace) { + this(name, value, namespace, false); + } + + /** + * Creates a new WebDAV property with the given DavPropertyName + * and value. If the property is meant to be protected the 'isProtected' + * flag must be set to true. + * + * @param name the name of the property + * @param value the value of the property + * @param isInvisibleInAllprop A value of true, defines this property to be protected. + * It will not be returned in a {@link org.apache.jackrabbit.webdav.DavConstants#PROPFIND_ALL_PROP DAV:allprop} + * PROPFIND request and cannot be set/removed with a PROPPATCH request. + */ + public DefaultDavProperty(DavPropertyName name, T value, boolean isInvisibleInAllprop) { + super(name, isInvisibleInAllprop); + this.value = value; + } + + /** + * Creates a new non- protected WebDAV property with the given + * DavPropertyName and value. + * + * @param name the name of the property + * @param value the value of the property + */ + public DefaultDavProperty(DavPropertyName name, T value) { + this(name, value, false); + } + + /** + * Returns the value of this property + * + * @return the value of this property + */ + public T getValue() { + return value; + } + + /** + * Create a new DefaultDavProperty instance from the given Xml + * element. Name and namespace of the element are building the {@link DavPropertyName}, + * while the element's content forms the property value. The following logic + * is applied: + *
+     * - empty Element           -> null value
+     * - single Text content     -> String value
+     * - single non-Text content -> Element.getContent(0) is used as value
+     * - other: List obtained from Element.getContent() is used as value
+     * 
+ * + * @param propertyElement + * @return + */ + public static DefaultDavProperty createFromXml(Element propertyElement) { + if (propertyElement == null) { + throw new IllegalArgumentException("Cannot create a new DavProperty from a 'null' element."); + } + DavPropertyName name = DavPropertyName.createFromXml(propertyElement); + DefaultDavProperty prop; + + if (!DomUtil.hasContent(propertyElement)) { + prop = new DefaultDavProperty(name, null, false); + } else { + List c = DomUtil.getContent(propertyElement); + if (c.size() == 1) { + Node n = c.get(0); + if (n instanceof Element) { + prop = new DefaultDavProperty(name, (Element) n, false); + } else { + prop = new DefaultDavProperty(name, n.getNodeValue(), false); + } + } else /* size > 1 */ { + prop = new DefaultDavProperty>(name, c, false); + } + } + return prop; + } +} \ No newline at end of file Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/property/DefaultDavProperty.java ___________________________________________________________________ Added: svn Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/property/HrefProperty.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/property/HrefProperty.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/property/HrefProperty.java (working copy) @@ -0,0 +1,159 @@ +/* + * 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.webdav.property; + +import org.apache.jackrabbit.webdav.xml.DomUtil; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +/** + * HrefProperty is an extension to the common {@link DavProperty}. + * The String representation of the property value is always displayed as text + * inside an extra 'href' element. If the value is a String array each array + * element is added as text to a separate 'href' element. + * + * @see org.apache.jackrabbit.webdav.DavConstants#XML_HREF + * @see org.apache.jackrabbit.webdav.property.DavProperty#getValue() + */ +public class HrefProperty extends AbstractDavProperty { + + private static Logger log = LoggerFactory.getLogger(HrefProperty.class); + + private final String[] value; + + /** + * Creates a new WebDAV property with the given DavPropertyName + * + * @param name the name of the property + * @param value the value of the property + * @param isInvisibleInAllprop A value of true, defines this property to be invisible in PROPFIND/allprop + * It will not be returned in a {@link org.apache.jackrabbit.webdav.DavConstants#PROPFIND_ALL_PROP DAV:allprop} + * PROPFIND request. + */ + public HrefProperty(DavPropertyName name, String value, boolean isInvisibleInAllprop) { + super(name, isInvisibleInAllprop); + this.value = new String[]{value}; + } + + /** + * Creates a new WebDAV property with the given DavPropertyName + * + * @param name the name of the property + * @param value the value of the property + * @param isInvisibleInAllprop A value of true, defines this property to be invisible in PROPFIND/allprop + * It will not be returned in a {@link org.apache.jackrabbit.webdav.DavConstants#PROPFIND_ALL_PROP DAV:allprop} + * PROPFIND request. + */ + public HrefProperty(DavPropertyName name, String[] value, boolean isInvisibleInAllprop) { + super(name, isInvisibleInAllprop); + this.value = value; + } + + /** + * Create a new HrefProperty from the specified property. + * Please note, that the property must have a List value + * object, consisting of {@link #XML_HREF href} Element entries. + * + * @param prop + */ + public HrefProperty(DavProperty prop) { + super(prop.getName(), prop.isInvisibleInAllprop()); + if (prop instanceof HrefProperty) { + // already an HrefProperty: no parsing required + this.value = ((HrefProperty)prop).value; + } else { + // assume property has be built from xml + ArrayList hrefList = new ArrayList(); + Object val = prop.getValue(); + if (val instanceof List) { + for (Object entry : ((List) val)) { + if (entry instanceof Element && XML_HREF.equals(((Element) entry).getLocalName())) { + String href = DomUtil.getText((Element) entry); + if (href != null) { + hrefList.add(href); + } else { + log.warn("Valid DAV:href element expected instead of " + entry.toString()); + } + } else { + log.warn("DAV: href element expected in the content of " + getName().toString()); + } + } + } else if (val instanceof Element && XML_HREF.equals(((Element)val).getLocalName())) { + String href = DomUtil.getTextTrim((Element)val); + if (href != null) { + hrefList.add(href); + } else { + log.warn("Valid DAV:href element expected instead of " + val.toString()); + } + } + value = hrefList.toArray(new String[hrefList.size()]); + } + } + + /** + * Returns an Xml element with the following form: + *
+     * <Z:name>
+     *    <DAV:href>value</DAV:href/>
+     * </Z:name>
+     * 
+ * where Z: represents the prefix of the namespace defined with the initial + * webdav property name. + * + * @return Xml representation + * @see org.apache.jackrabbit.webdav.xml.DomUtil#hrefToXml(String,org.w3c.dom.Document) + * @param document + */ + @Override + public Element toXml(Document document) { + Element elem = getName().toXml(document); + String[] value = getValue(); + if (value != null) { + for (String href : value) { + elem.appendChild(DomUtil.hrefToXml(href, document)); + } + } + return elem; + } + + /** + * Returns an array of String. + * + * @return an array of String. + * @see DavProperty#getValue() + */ + public String[] getValue() { + return value; + } + + /** + * Return an list of String containing the text of those DAV:href elements + * that would be returned as child elements of this property on + * {@link org.apache.jackrabbit.webdav.xml.XmlSerializable#toXml(Document)} + * + * @return list of href String + */ + public List getHrefs() { + return (value != null) ? Arrays.asList(value) : new ArrayList(); + } +} Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/property/HrefProperty.java ___________________________________________________________________ Added: svn Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/property/PropContainer.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/property/PropContainer.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/property/PropContainer.java (working copy) @@ -0,0 +1,119 @@ +/* + * 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.webdav.property; + +import org.apache.jackrabbit.webdav.DavConstants; +import org.apache.jackrabbit.webdav.xml.DomUtil; +import org.apache.jackrabbit.webdav.xml.XmlSerializable; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +import java.util.Collection; + +/** + * PropContainer... + */ +public abstract class PropContainer implements XmlSerializable, DavConstants { + + private static Logger log = LoggerFactory.getLogger(PropContainer.class); + + /** + * Tries to add the specified object to the PropContainer and + * returns a boolean indicating whether the content could be added to the + * internal set/map. + * + * @param contentEntry + * @return true if the object could be added; false otherwise + * @deprecated Use {@link #addContent(PropEntry)} instead. + */ + public boolean addContent(Object contentEntry) { + if (contentEntry instanceof PropEntry) { + return addContent((PropEntry) contentEntry); + } else { + return false; + } + } + + /** + * Tries to add the specified entry to the PropContainer and + * returns a boolean indicating whether the content could be added to the + * internal set/map. + * + * @param contentEntry + * @return true if the object could be added; false otherwise + */ + public abstract boolean addContent(PropEntry contentEntry); + + /** + * Returns true if the PropContainer does not yet contain any content elements. + * + * @return true if this container is empty. + */ + public abstract boolean isEmpty(); + + /** + * Returns the number of property related content elements that are present + * in this PropContainer. + * + * @return number of content elements + */ + public abstract int getContentSize(); + + /** + * Returns the collection that contains all the content elements of this + * PropContainer. + * + * @return collection representing the contents of this PropContainer. + */ + public abstract Collection getContent(); + + /** + * Returns true if this PropContainer contains a content element + * that matches the given DavPropertyName. + * + * @param name + * @return true if any of the content elements (be it a DavProperty or a + * DavPropertyName only) matches the given name. + */ + public abstract boolean contains(DavPropertyName name); + + /** + * Returns the xml representation of a property related set with the + * following format: + *
+     * <!ELEMENT prop (ANY) >
+     * where ANY consists of a list of elements each reflecting the xml
+     * representation of the entries returned by {@link #getContent()}.
+     * 
+ * + * @see XmlSerializable#toXml(Document) + */ + public Element toXml(Document document) { + Element prop = DomUtil.createElement(document, XML_PROP, NAMESPACE); + for (Object content : getContent()) { + if (content instanceof XmlSerializable) { + prop.appendChild(((XmlSerializable) content).toXml(document)); + } else { + log.debug("Unexpected content in PropContainer: should be XmlSerializable."); + } + } + return prop; + } + +} Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/property/PropContainer.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-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/property/PropEntry.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/property/PropEntry.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/property/PropEntry.java (working copy) @@ -0,0 +1,25 @@ +/* + * 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.webdav.property; + +/** + * Marker interface used to flag the different types of entries that form + * part of a PROPPATCH request and define the possible entries for a + * PropContainer. + */ +public interface PropEntry { +} Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/property/PropEntry.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-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/property/PropfindInfo.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/property/PropfindInfo.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/property/PropfindInfo.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.webdav.property; + +import org.apache.jackrabbit.webdav.DavConstants; +import org.apache.jackrabbit.webdav.xml.DomUtil; +import org.apache.jackrabbit.webdav.xml.XmlSerializable; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.Node; + +public class PropfindInfo implements XmlSerializable { + + private final int propfindType; + private final DavPropertyNameSet propNameSet; + + public PropfindInfo(int propfindType, DavPropertyNameSet propNameSet) { + this.propfindType = propfindType; + this.propNameSet = propNameSet; + } + + @Override + public Element toXml(Document document) { + Element propfind = DomUtil.createElement(document, DavConstants.XML_PROPFIND, DavConstants.NAMESPACE); + + // fill the propfind element + switch (propfindType) { + case DavConstants.PROPFIND_ALL_PROP: + propfind.appendChild(DomUtil.createElement(document, DavConstants.XML_ALLPROP, DavConstants.NAMESPACE)); + break; + + case DavConstants.PROPFIND_PROPERTY_NAMES: + propfind.appendChild(DomUtil.createElement(document, DavConstants.XML_PROPNAME, DavConstants.NAMESPACE)); + break; + + case DavConstants.PROPFIND_BY_PROPERTY: + if (propNameSet == null) { + // name set missing, ask for a property that is known to + // exist + Element prop = DomUtil.createElement(document, DavConstants.XML_PROP, DavConstants.NAMESPACE); + Element resourcetype = DomUtil.createElement(document, DavConstants.PROPERTY_RESOURCETYPE, + DavConstants.NAMESPACE); + prop.appendChild(resourcetype); + propfind.appendChild(prop); + } else { + propfind.appendChild(propNameSet.toXml(document)); + } + break; + + case DavConstants.PROPFIND_ALL_PROP_INCLUDE: + propfind.appendChild(DomUtil.createElement(document, DavConstants.XML_ALLPROP, DavConstants.NAMESPACE)); + if (propNameSet != null && !propNameSet.isEmpty()) { + Element include = DomUtil.createElement(document, DavConstants.XML_INCLUDE, DavConstants.NAMESPACE); + Element prop = propNameSet.toXml(document); + for (Node c = prop.getFirstChild(); c != null; c = c.getNextSibling()) { + // copy over the children of to + // element + include.appendChild(c.cloneNode(true)); + } + propfind.appendChild(include); + } + break; + + default: + throw new IllegalArgumentException("unknown propfind type"); + } + + return propfind; + } +} Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/property/PropfindInfo.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/property/ProppatchInfo.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/property/ProppatchInfo.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/property/ProppatchInfo.java (working copy) @@ -0,0 +1,128 @@ +/* + * 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.webdav.property; + +import java.util.List; + +import org.apache.jackrabbit.webdav.DavConstants; +import org.apache.jackrabbit.webdav.xml.DomUtil; +import org.apache.jackrabbit.webdav.xml.XmlSerializable; +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +public class ProppatchInfo implements XmlSerializable { + + private final List changeList; + private final DavPropertySet setProperties; + private final DavPropertyNameSet removeProperties; + + private final DavPropertyNameSet propertyNames = new DavPropertyNameSet(); + + public ProppatchInfo(List changeList) { + if (changeList == null || changeList.isEmpty()) { + throw new IllegalArgumentException("PROPPATCH cannot be executed without properties to be set or removed."); + } + this.changeList = changeList; + this.setProperties = null; + this.removeProperties = null; + for (PropEntry entry : changeList) { + if (entry instanceof DavPropertyName) { + // DAV:remove + this.propertyNames.add((DavPropertyName) entry); + } else if (entry instanceof DavProperty) { + // DAV:set + DavProperty setProperty = (DavProperty) entry; + this.propertyNames.add(setProperty.getName()); + } else { + throw new IllegalArgumentException("ChangeList may only contain DavPropertyName and DavProperty elements."); + } + } + } + + public ProppatchInfo(DavPropertySet setProperties, DavPropertyNameSet removeProperties) { + if (setProperties == null || removeProperties == null) { + throw new IllegalArgumentException("Neither setProperties nor removeProperties must be null."); + } + if (setProperties.isEmpty() && removeProperties.isEmpty()) { + throw new IllegalArgumentException("Either setProperties or removeProperties can be empty; not both of them."); + } + this.changeList = null; + this.setProperties = setProperties; + this.removeProperties = removeProperties; + this.propertyNames.addAll(removeProperties); + for (DavPropertyName setName : setProperties.getPropertyNames()) { + this.propertyNames.add(setName); + } + } + + public DavPropertyNameSet getAffectedProperties() { + if (this.propertyNames.isEmpty()) { + throw new IllegalStateException("must be called after toXml()"); + } + return this.propertyNames; + } + + @Override + public Element toXml(Document document) { + Element proppatch = DomUtil.createElement(document, DavConstants.XML_PROPERTYUPDATE, DavConstants.NAMESPACE); + + if (changeList != null) { + Element propElement = null; + boolean isSet = false; + for (Object entry : changeList) { + if (entry instanceof DavPropertyName) { + // DAV:remove + DavPropertyName removeName = (DavPropertyName) entry; + if (propElement == null || isSet) { + isSet = false; + propElement = getPropElement(proppatch, false); + } + propElement.appendChild(removeName.toXml(document)); + } else if (entry instanceof DavProperty) { + // DAV:set + DavProperty setProperty = (DavProperty) entry; + if (propElement == null || !isSet) { + isSet = true; + propElement = getPropElement(proppatch, true); + } + propElement.appendChild(setProperty.toXml(document)); + } else { + throw new IllegalArgumentException("ChangeList may only contain DavPropertyName and DavProperty elements."); + } + } + } else { + // DAV:set + if (!setProperties.isEmpty()) { + Element set = DomUtil.addChildElement(proppatch, DavConstants.XML_SET, DavConstants.NAMESPACE); + set.appendChild(setProperties.toXml(document)); + } + // DAV:remove + if (!removeProperties.isEmpty()) { + Element remove = DomUtil.addChildElement(proppatch, DavConstants.XML_REMOVE, DavConstants.NAMESPACE); + remove.appendChild(removeProperties.toXml(document)); + } + } + + return proppatch; + } + + private Element getPropElement(Element propUpdate, boolean isSet) { + Element updateEntry = DomUtil.addChildElement(propUpdate, isSet ? DavConstants.XML_SET : DavConstants.XML_REMOVE, + DavConstants.NAMESPACE); + return DomUtil.addChildElement(updateEntry, DavConstants.XML_PROP, DavConstants.NAMESPACE); + } +} Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/property/ProppatchInfo.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/property/ResourceType.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/property/ResourceType.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/property/ResourceType.java (working copy) @@ -0,0 +1,205 @@ +/* + * 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.webdav.property; + +import org.apache.jackrabbit.webdav.version.DeltaVConstants; +import org.apache.jackrabbit.webdav.xml.DomUtil; +import org.apache.jackrabbit.webdav.xml.Namespace; +import org.apache.jackrabbit.webdav.xml.XmlSerializable; +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +/** + * The ResourceType class represents the webdav resource + * type property. The property may contain multiple resource type + * values. Predefined resource types are those defined by RFC2518 and RFC3253: + *
    + *
  • {@link #DEFAULT_RESOURCE the empty default resource type},
  • + *
  • '{@link #COLLECTION DAV:collection}',
  • + *
  • '{@link #VERSION_HISTORY DAV:version-history}',
  • + *
  • '{@link #ACTIVITY DAV:activity}',
  • + *
  • '{@link #BASELINE DAV:baseline}',
  • + *
+ */ +public class ResourceType extends AbstractDavProperty> { + + /** + * The default resource type + */ + public static final int DEFAULT_RESOURCE = 0; + + /** + * The collection resource type + */ + public static final int COLLECTION = DEFAULT_RESOURCE + 1; + + /** + * The version-history resource type + */ + public static final int VERSION_HISTORY = COLLECTION + 1; + + /** + * The activity resource type + */ + public static final int ACTIVITY = VERSION_HISTORY + 1; + + /** + * The baseline resource type + */ + public static final int BASELINE = ACTIVITY + 1; + + /** + * Array containing all possible resourcetype elements + */ + private static final List NAMES = new ArrayList(); + static { + NAMES.add(null); + NAMES.add(new TypeName(XML_COLLECTION, NAMESPACE)); + NAMES.add(new TypeName(DeltaVConstants.XML_VERSION_HISTORY, DeltaVConstants.NAMESPACE)); + NAMES.add(new TypeName(DeltaVConstants.XML_ACTIVITY, DeltaVConstants.NAMESPACE)); + NAMES.add(new TypeName(DeltaVConstants.XML_BASELINE, DeltaVConstants.NAMESPACE)); + } + + private final int[] resourceTypes; + + /** + * Create a single-valued resource type property + */ + public ResourceType(int resourceType) { + this(new int[] { resourceType }); + } + + /** + * Create a multi-valued resource type property + */ + public ResourceType(int[] resourceTypes) { + super(DavPropertyName.RESOURCETYPE, false); + for (int resourceType : resourceTypes) { + if (!isValidResourceType(resourceType)) { + throw new IllegalArgumentException("Invalid resource type '" + resourceType + "'."); + } + } + this.resourceTypes = resourceTypes; + } + + /** + * Returns a Set of resource types each implementing the XmlSerializable + * interface. + * + * @return a Set of resource types representing this property. + * @see DavProperty#getValue() + */ + public Set getValue() { + Set rTypes = new HashSet(); + for (int resourceType : resourceTypes) { + TypeName n = NAMES.get(resourceType); + if (n != null) { + rTypes.add(n); + } + } + return rTypes; + } + + /** + * Returns the resource types specified with the constructor. + * + * @return resourceTypes + */ + public int[] getResourceTypes() { + return resourceTypes; + } + + /** + * Returns true if the given integer defines a valid resource type. + * + * @param resourceType to be validated. + * @return true if this is one of the predefined resource types + */ + private static boolean isValidResourceType(int resourceType) { + if (resourceType < DEFAULT_RESOURCE || resourceType > NAMES.size()-1) { + return false; + } + return true; + } + + /** + * Register an additional resource type + * + * @param name + * @param namespace + * @return int to be used for creation of a new ResourceType property + * that contains this type. + * @throws IllegalArgumentException if the given element is null or + * if the registration fails for another reason. + */ + public static int registerResourceType(String name, Namespace namespace) { + if (name == null || namespace == null) { + throw new IllegalArgumentException("Cannot register a resourcetype"); + } + TypeName tn = new TypeName(name, namespace); + // avoid duplicate registrations + if (NAMES.contains(tn)) { + return NAMES.indexOf(tn); + } + // register new type + if (NAMES.add(tn)) { + return NAMES.size() - 1; + } else { + throw new IllegalArgumentException("Could not register resourcetype " + namespace.getPrefix() + name); + } + } + + //--------------------------------------------------------< inner class >--- + /** + * Private inner class used to register predefined and user defined resource + * types. + */ + private static class TypeName implements XmlSerializable { + + private final String localName; + private final Namespace namespace; + private final int hashCode; + + private TypeName(String localName, Namespace namespace) { + this.localName = localName; + this.namespace = namespace; + hashCode = DomUtil.getExpandedName(localName, namespace).hashCode(); + } + + @Override + public int hashCode() { + return hashCode; + } + + @Override + public boolean equals(Object o) { + if (o instanceof TypeName) { + return hashCode == ((TypeName)o).hashCode; + } + return false; + } + + public Element toXml(Document document) { + return DomUtil.createElement(document, localName, namespace); + } + } +} Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/property/ResourceType.java ___________________________________________________________________ Added: svn Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/property/package-info.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/property/package-info.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/property/package-info.java (working copy) @@ -0,0 +1,18 @@ +/* + * 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. + */ +@org.osgi.annotation.versioning.Version("1.0.0") +package org.apache.jackrabbit.webdav.property; Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/property/package-info.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/search/QueryGrammerSet.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/search/QueryGrammerSet.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/search/QueryGrammerSet.java (working copy) @@ -0,0 +1,144 @@ +/* + * 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.webdav.search; + +import org.apache.jackrabbit.webdav.property.AbstractDavProperty; +import org.apache.jackrabbit.webdav.property.DavProperty; +import org.apache.jackrabbit.webdav.xml.DomUtil; +import org.apache.jackrabbit.webdav.xml.Namespace; +import org.apache.jackrabbit.webdav.xml.XmlSerializable; +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +import java.util.HashSet; +import java.util.Set; + +/** + * QueryGrammerSet is a {@link DavProperty} that + * encapsulates the 'supported-query-grammer-set' as defined by the + * Webdav SEARCH internet draft. + */ +public class QueryGrammerSet extends AbstractDavProperty> implements SearchConstants { + + private final Set queryGrammers = new HashSet(); + + /** + * Create a new empty QueryGrammerSet. Supported query grammers + * may be added by calling {@link #addQueryLanguage(String, Namespace)}. + */ + public QueryGrammerSet() { + super(QUERY_GRAMMER_SET, true); + } + + /** + * Add another query queryGrammer to this set. + * + * @param grammerName + * @param namespace + */ + public void addQueryLanguage(String grammerName, Namespace namespace) { + queryGrammers.add(new Grammer(grammerName, namespace)); + } + + /** + * Return a String array containing the URIs of the query + * languages supported. + * + * @return names of the supported query languages + */ + public String[] getQueryLanguages() { + int size = queryGrammers.size(); + if (size > 0) { + String[] qLangStr = new String[size]; + Grammer[] grammers = queryGrammers.toArray(new Grammer[size]); + for (int i = 0; i < grammers.length; i++) { + qLangStr[i] = grammers[i].namespace.getURI() + grammers[i].localName; + } + return qLangStr; + } else { + return new String[0]; + } + } + + /** + * Return the Xml representation of this property according to the definition + * of the 'supported-query-grammer-set'. + * + * @return Xml representation + * @see SearchConstants#QUERY_GRAMMER_SET + * @see org.apache.jackrabbit.webdav.xml.XmlSerializable#toXml(Document) + * @param document + */ + @Override + public Element toXml(Document document) { + Element elem = getName().toXml(document); + for (Grammer qGrammer : queryGrammers) { + elem.appendChild(qGrammer.toXml(document)); + } + return elem; + } + + /** + * Returns the set of supported query grammers. + * + * @return list of supported query languages. + * @see org.apache.jackrabbit.webdav.property.DavProperty#getValue() + */ + public Set getValue() { + return queryGrammers; + } + + + private class Grammer implements XmlSerializable { + + private final String localName; + private final Namespace namespace; + private final int hashCode; + + Grammer(String localName, Namespace namespace) { + this.localName = localName; + this.namespace = namespace; + hashCode = DomUtil.getExpandedName(localName, namespace).hashCode(); + } + + @Override + public int hashCode() { + return hashCode; + } + + @Override + public boolean equals(Object obj) { + if (obj == this) { + return true; + } + if (obj instanceof Grammer) { + return obj.hashCode() == hashCode(); + } + return false; + } + + /** + * @see XmlSerializable#toXml(org.w3c.dom.Document) + */ + public Element toXml(Document document) { + Element sqg = DomUtil.createElement(document, XML_QUERY_GRAMMAR, SearchConstants.NAMESPACE); + Element grammer = DomUtil.addChildElement(sqg, XML_GRAMMER, SearchConstants.NAMESPACE); + DomUtil.addChildElement(grammer, localName, namespace); + return sqg; + } + } +} \ No newline at end of file Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/search/QueryGrammerSet.java ___________________________________________________________________ Added: svn Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/search/SearchConstants.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/search/SearchConstants.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/search/SearchConstants.java (working copy) @@ -0,0 +1,91 @@ +/* + * 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.webdav.search; + +import org.apache.jackrabbit.webdav.DavConstants; +import org.apache.jackrabbit.webdav.property.DavPropertyName; +import org.apache.jackrabbit.webdav.xml.Namespace; + +/** + * SearchConstants interface provide constants for request + * and response headers, Xml elements and property names used for WebDAV + * search. + */ +public interface SearchConstants { + + /** + * Namespace definition.
+ * NOTE: For convenience reasons, the namespace is defined to be the default + * {@link DavConstants#NAMESPACE DAV:} namespace. This is not correct for the + * underlying specification is still in a draft state. See also the editorial + * note inside the + * Internet Draft WebDAV Search + * document. + */ + public static final Namespace NAMESPACE = DavConstants.NAMESPACE; + + /** + * Predefined basic query grammer. + */ + public static final String BASICSEARCH = NAMESPACE.getPrefix()+"basicsearch"; + + //---< Headers >------------------------------------------------------------ + /** + * The DASL response header specifying the query languages supported by + * the requested resource. + */ + public static final String HEADER_DASL = "DASL"; + + //---< XML Element, Attribute Names >--------------------------------------- + /** + * Xml element name for a single query grammar element inside + * the {@link #QUERY_GRAMMER_SET supported-query-grammer-set property}. + */ + public static final String XML_QUERY_GRAMMAR = "supported-query-grammar"; + + /** + * Name constant for the 'DAV:grammar' element, which is used inside the + * {@link #XML_QUERY_GRAMMAR} element. + */ + public static final String XML_GRAMMER = "grammar"; + + /** + * Xml element name for the required request body of a SEARCH request. + * + * @see SearchInfo + * @see SearchResource#search(SearchInfo) + */ + public static final String XML_SEARCHREQUEST = "searchrequest"; + + /** + * Optional Xml element name used in the SEARCH request body instead of {@link #XML_SEARCHREQUEST} + * in order to access a given query schema. + */ + public static final String XML_QUERY_SCHEMA_DISCOVERY = "query-schema-discovery"; + + //---< Property Names >----------------------------------------------------- + /** + * Property indicating the set of query languages the given resource is + * able deal with. The property has the following definition:
+ *
+     * <!ELEMENT supported-query-grammar-set (supported-query-grammar*)>
+     * <!ELEMENT supported-query-grammar grammar>
+     * <!ELEMENT grammar ANY>
+     * 
+ */ + public static final DavPropertyName QUERY_GRAMMER_SET = DavPropertyName.create("supported-query-grammar-set", NAMESPACE); +} \ No newline at end of file Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/search/SearchConstants.java ___________________________________________________________________ Added: svn Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/search/SearchInfo.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/search/SearchInfo.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/search/SearchInfo.java (working copy) @@ -0,0 +1,271 @@ +/* + * 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.webdav.search; + +import org.apache.jackrabbit.webdav.DavException; +import org.apache.jackrabbit.webdav.DavServletResponse; +import org.apache.jackrabbit.webdav.DavConstants; +import org.apache.jackrabbit.webdav.xml.DomUtil; +import org.apache.jackrabbit.webdav.xml.Namespace; +import org.apache.jackrabbit.webdav.xml.XmlSerializable; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.Attr; + +import java.util.Map; +import java.util.HashMap; +import java.util.Collections; +import java.util.Set; +import java.util.HashSet; + +/** + * SearchInfo parses the 'searchrequest' element of a SEARCH + * request body and performs basic validation. Both query language and the + * query itself can be access from the resulting object.
+ * NOTE: The query is expected to be represented by the text contained in the + * Xml element specifying the query language, thus the 'basicsearch' defined + * by the Webdav Search Internet Draft is not supported by this implementation. + *

+ * + * Example of a valid 'searchrequest' body + *

+ * <d:searchrequest xmlns:d="DAV:" dcr:="http://www.day.com/jcr/webdav/1.0" >
+ *    <dcr:xpath>//sv:node[@sv:name='myapp:paragraph'][1]</dcr:xpath>
+ * </d:searchrequest>
+ * 
+ * + * Would return the following values: + *
+ *    getLanguageName() -> xpath
+ *    getQuery()        -> //sv:node[@sv:name='myapp:paragraph'][1]
+ * 
+ * + */ +public class SearchInfo implements SearchConstants, XmlSerializable { + + private static Logger log = LoggerFactory.getLogger(SearchInfo.class); + + public static final long NRESULTS_UNDEFINED = -1; + public static final long OFFSET_UNDEFINED = -1; + + private static final String LIMIT = "limit"; + private static final String NRESULTS = "nresults"; + private static final String OFFSET = "offset"; + + /** + * Set of namespace uri String which are ignored in the search request. + */ + private static final Set IGNORED_NAMESPACES; + + static { + Set s = new HashSet(); + s.add(Namespace.XMLNS_NAMESPACE.getURI()); + s.add(Namespace.XML_NAMESPACE.getURI()); + s.add(DavConstants.NAMESPACE.getURI()); + IGNORED_NAMESPACES = Collections.unmodifiableSet(s); + } + + private final String language; + private final Namespace languageNamespace; + private final String query; + private final Map namespaces; + + private long nresults = NRESULTS_UNDEFINED; + private long offset = OFFSET_UNDEFINED; + + /** + * Create a new SearchInfo instance. + * + * @param language + * @param languageNamespace + * @param query + * @param namespaces the re-mapped namespaces. Key=prefix, value=uri. + */ + public SearchInfo(String language, Namespace languageNamespace, String query, + Map namespaces) { + this.language = language; + this.languageNamespace = languageNamespace; + this.query = query; + this.namespaces = Collections.unmodifiableMap(new HashMap(namespaces)); + } + + /** + * Create a new SearchInfo instance. + * + * @param language + * @param languageNamespace + * @param query + */ + public SearchInfo(String language, Namespace languageNamespace, String query) { + this(language, languageNamespace, query, Collections.emptyMap()); + } + + /** + * Returns the name of the query language to be used. + * + * @return name of the query language + */ + public String getLanguageName() { + return language; + } + + /** + * Returns the namespace of the language specified with the search request element. + * + * @return namespace of the requested language. + */ + public Namespace getLanguageNameSpace() { + return languageNamespace; + } + + /** + * Return the query string. + * + * @return query string + */ + public String getQuery() { + return query; + } + + /** + * Returns the namespaces that have been re-mapped by the user. + * + * @return map of namespace to prefix mappings. Key=prefix, value=uri. + */ + public Map getNamespaces() { + return namespaces; + } + + /** + * Returns the maximal number of search results that should be returned. + * + * @return the maximal number of search results that should be returned. + */ + public long getNumberResults() { + return nresults; + } + + /** + * Sets the maximal number of search results that should be returned. + * + * @param nresults The maximal number of search results + */ + public void setNumberResults(long nresults) { + this.nresults = nresults; + } + + /** + * Returns the desired offset in the total result set. + * + * @return the desired offset in the total result set. + */ + public long getOffset() { + return offset; + } + + /** + * Sets the desired offset in the total result set. + * + * @param offset The desired offset in the total result set. + */ + public void setOffset(long offset) { + this.offset = offset; + } + + /** + * Return the xml representation of this SearchInfo instance. + * + * @return xml representation + * @param document + */ + public Element toXml(Document document) { + Element sRequestElem = DomUtil.createElement(document, XML_SEARCHREQUEST, NAMESPACE); + for (String prefix : namespaces.keySet()) { + String uri = namespaces.get(prefix); + DomUtil.setNamespaceAttribute(sRequestElem, prefix, uri); + } + DomUtil.addChildElement(sRequestElem, language, languageNamespace, query); + if (nresults != NRESULTS_UNDEFINED|| offset != OFFSET_UNDEFINED) { + Element limitE = DomUtil.addChildElement(sRequestElem, LIMIT, NAMESPACE); + if (nresults != NRESULTS_UNDEFINED) { + DomUtil.addChildElement(limitE, NRESULTS, NAMESPACE, nresults + ""); + } + if (offset != OFFSET_UNDEFINED) { + // TODO define reasonable namespace... + DomUtil.addChildElement(limitE, OFFSET, Namespace.EMPTY_NAMESPACE, offset + ""); + } + } + return sRequestElem; + } + + /** + * Create a new SearchInfo from the specifying document + * retrieved from the request body. + * + * @param searchRequest + * @throws DavException if the root element's name is other than + * 'searchrequest' or if it does not contain a single child element specifying + * the query language to be used. + */ + public static SearchInfo createFromXml(Element searchRequest) throws DavException { + if (searchRequest == null || !XML_SEARCHREQUEST.equals(searchRequest.getLocalName())) { + log.warn("The root element must be 'searchrequest'."); + throw new DavException(DavServletResponse.SC_BAD_REQUEST); + } + Element first = DomUtil.getFirstChildElement(searchRequest); + Attr[] nsAttributes = DomUtil.getNamespaceAttributes(searchRequest); + Map namespaces = new HashMap(); + for (Attr nsAttribute : nsAttributes) { + // filter out xmlns namespace and DAV namespace + if (!IGNORED_NAMESPACES.contains(nsAttribute.getValue())) { + namespaces.put(nsAttribute.getLocalName(), nsAttribute.getValue()); + } + } + SearchInfo sInfo; + if (first != null) { + sInfo = new SearchInfo(first.getLocalName(), DomUtil.getNamespace(first), DomUtil.getText(first), namespaces); + } else { + log.warn("A single child element is expected with the 'DAV:searchrequest'."); + throw new DavException(DavServletResponse.SC_BAD_REQUEST); + } + + Element limit = DomUtil.getChildElement(searchRequest, LIMIT, NAMESPACE); + if (limit != null) { + // try to get the value DAV:nresults element + String nresults = DomUtil.getChildTextTrim(limit, NRESULTS, NAMESPACE); + if (nresults != null) { + try { + sInfo.setNumberResults(Long.valueOf(nresults)); + } catch (NumberFormatException e) { + log.error("DAV:nresults cannot be parsed into a long -> ignore."); + } + } + // try of an offset is defined within the DAV:limit element. + String offset = DomUtil.getChildTextTrim(limit, OFFSET, Namespace.EMPTY_NAMESPACE); + if (offset != null) { + try { + sInfo.setOffset(Long.valueOf(offset)); + } catch (NumberFormatException e) { + log.error("'offset' cannot be parsed into a long -> ignore."); + } + } + } + return sInfo; + } +} Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/search/SearchInfo.java ___________________________________________________________________ Added: svn Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/search/SearchResource.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/search/SearchResource.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/search/SearchResource.java (working copy) @@ -0,0 +1,55 @@ +/* + * 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.webdav.search; + +import org.apache.jackrabbit.webdav.DavException; +import org.apache.jackrabbit.webdav.MultiStatus; + +/** + * SearchResource defines METHODS required in order to handle + * a SEARCH request. + */ +public interface SearchResource { + + /** + * The 'SEARCH' method + */ + public String METHODS = "SEARCH"; + + + /** + * Returns the protected DAV:supported-method-set property which is defined + * mandatory by RTF 3253. This method call is a shortcut for + * DavResource.getProperty(SearchConstants.QUERY_GRAMMER_SET). + * + * @return the DAV:supported-query-grammer-set + * @see SearchConstants#QUERY_GRAMMER_SET + */ + public QueryGrammerSet getQueryGrammerSet(); + + /** + * Runs a search with the language and query defined in the {@link SearchInfo} + * object specified and returns a {@link MultiStatus} object listing the + * results. + * + * @param sInfo SearchInfo element encapsulating the SEARCH + * request body. + * @return MultiStatus object listing the results. + * @throws DavException + */ + public MultiStatus search(SearchInfo sInfo) throws DavException; +} \ No newline at end of file Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/search/SearchResource.java ___________________________________________________________________ Added: svn Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/search/package-info.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/search/package-info.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/search/package-info.java (working copy) @@ -0,0 +1,18 @@ +/* + * 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. + */ +@org.osgi.annotation.versioning.Version("1.0.0") +package org.apache.jackrabbit.webdav.search; Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/search/package-info.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/security/AclProperty.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/security/AclProperty.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/security/AclProperty.java (working copy) @@ -0,0 +1,262 @@ +/* + * 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.webdav.security; + +import org.apache.jackrabbit.webdav.DavConstants; +import org.apache.jackrabbit.webdav.DavException; +import org.apache.jackrabbit.webdav.DavServletResponse; +import org.apache.jackrabbit.webdav.property.AbstractDavProperty; +import org.apache.jackrabbit.webdav.property.DavProperty; +import org.apache.jackrabbit.webdav.xml.DomUtil; +import org.apache.jackrabbit.webdav.xml.ElementIterator; +import org.apache.jackrabbit.webdav.xml.XmlSerializable; +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +/** + * AclProperty defines a protected property that specifies the list + * of access control entries (ACEs). The set of ACEs define the privileges granted + * or denied to principals on the resource a given property instance belongs to. + *
+ * RFC 3744 defines the following format for this property: + *
+ * <!ELEMENT acl (ace*) >
+ * <!ELEMENT ace ((principal | invert), (grant|deny), protected?, inherited?)>
+ * <!ELEMENT principal (href | all | authenticated | unauthenticated | property | self)>
+ * <!ELEMENT invert (principal)>
+ * <!ELEMENT grant (privilege+)>
+ * <!ELEMENT deny (privilege+)>
+ * <!ELEMENT protected EMPTY>
+ * <!ELEMENT inherited (href)>
+ * 
+ * + * @see Principal for details regarding DAV:principal + * @see Privilege for details regarding DAV:privilege + */ +public class AclProperty extends AbstractDavProperty> { + + private final List aces; + + /** + * Create a new AclProperty from the given ACEs. + * + * @see AclProperty#createGrantAce(Principal, Privilege[], boolean, boolean, AclResource) for a factory method to create a grant ACE. + * @see AclProperty#createDenyAce(Principal, Privilege[], boolean, boolean, AclResource) for a factory method to create a deny ACE. + */ + public AclProperty(Ace[] accessControlElements) { + this((accessControlElements == null) ? new ArrayList() : Arrays.asList(accessControlElements)); + } + + private AclProperty(List aces) { + super(SecurityConstants.ACL, true); + this.aces = aces; + } + + /** + * @return a List of Ace object. If this property defines no ACEs + * an empty list is returned. + * @see DavProperty#getValue() + */ + public List getValue() { + return aces; + } + + /** + * Build a new AclProperty object from the request body of the + * ACL method call. + * + * @param aclElement + * @return new AclProperty + * @throws DavException + */ + public static AclProperty createFromXml(Element aclElement) throws DavException { + if (!DomUtil.matches(aclElement, SecurityConstants.ACL.getName(), SecurityConstants.ACL.getNamespace())) { + throw new DavException(DavServletResponse.SC_BAD_REQUEST, "ACL request requires a DAV:acl body."); + } + List aces = new ArrayList(); + ElementIterator it = DomUtil.getChildren(aclElement, Ace.XML_ACE, SecurityConstants.NAMESPACE); + while (it.hasNext()) { + Element aceElem = it.nextElement(); + aces.add(Ace.createFromXml(aceElem)); + } + return new AclProperty(aces); + } + + public static Ace createGrantAce(Principal principal, Privilege[] privileges, boolean invert, boolean isProtected, AclResource inheritedFrom) { + return new Ace(principal, invert, privileges, true, isProtected, inheritedFrom); + } + + public static Ace createDenyAce(Principal principal, Privilege[] privileges, boolean invert, boolean isProtected, AclResource inheritedFrom) { + return new Ace(principal, invert, privileges, false, isProtected, inheritedFrom); + } + + //--------------------------------------------------------< inner class >--- + /** + * Simple WebDAV ACE implementation + */ + public static class Ace implements XmlSerializable, SecurityConstants { + + private static final String XML_ACE = "ace"; + private static final String XML_INVERT = "invert"; + private static final String XML_GRANT = "grant"; + private static final String XML_DENY = "deny"; + private static final String XML_PROTECTED = "protected"; + private static final String XML_INHERITED = "inherited"; + + private final Principal principal; + private final boolean invert; + private final Privilege[] privileges; + private final boolean grant; + private final boolean isProtected; + private final String inheritedHref; + + /** + * Private constructor + * + * @param principal + * @param invert + * @param privileges + * @param grant + * @param isProtected + * @param inherited + */ + private Ace(Principal principal, boolean invert, Privilege[] privileges, + boolean grant, boolean isProtected, AclResource inherited) { + this(principal, invert, privileges, grant, isProtected, + ((inherited != null) ? inherited.getHref() : null)); + } + + /** + * Private constructor + * + * @param principal + * @param invert + * @param privileges + * @param grant + * @param isProtected + * @param inheritedHref + */ + private Ace(Principal principal, boolean invert, Privilege[] privileges, + boolean grant, boolean isProtected, String inheritedHref) { + if (principal == null) { + throw new IllegalArgumentException("Cannot create a new ACE with 'null' principal."); + } + if (privileges == null || privileges.length == 0) { + throw new IllegalArgumentException("Cannot create a new ACE: at least a single privilege must be specified."); + } + this.principal = principal; + this.invert = invert; + this.privileges = privileges; + this.grant = grant; + this.isProtected = isProtected; + this.inheritedHref = inheritedHref; + } + + public Principal getPrincipal() { + return principal; + } + + public boolean isInvert() { + return invert; + } + + public Privilege[] getPrivileges() { + return privileges; + } + + public boolean isGrant() { + return grant; + } + + public boolean isDeny() { + return !grant; + } + + public boolean isProtected() { + return isProtected; + } + + public String getInheritedHref() { + return inheritedHref; + } + + /** + * @see XmlSerializable#toXml(Document) + */ + public Element toXml(Document document) { + Element ace = DomUtil.createElement(document, XML_ACE, SecurityConstants.NAMESPACE); + if (invert) { + Element inv = DomUtil.addChildElement(ace, XML_INVERT, SecurityConstants.NAMESPACE); + inv.appendChild(principal.toXml(document)); + } else { + ace.appendChild(principal.toXml(document)); + } + Element gd = DomUtil.addChildElement(ace, ((grant) ? XML_GRANT : XML_DENY), SecurityConstants.NAMESPACE); + for (Privilege privilege : privileges) { + gd.appendChild(privilege.toXml(document)); + } + if (isProtected) { + DomUtil.addChildElement(ace, XML_PROTECTED, SecurityConstants.NAMESPACE); + } + if (inheritedHref != null) { + Element inh = DomUtil.addChildElement(ace, XML_INHERITED, SecurityConstants.NAMESPACE); + inh.appendChild(DomUtil.hrefToXml(inheritedHref, document)); + } + return ace; + } + + private static Ace createFromXml(Element aceElement) throws DavException { + boolean invert = DomUtil.hasChildElement(aceElement, XML_INVERT, NAMESPACE); + Element pe; + if (invert) { + Element invertE = DomUtil.getChildElement(aceElement, XML_INVERT, NAMESPACE); + pe = DomUtil.getChildElement(invertE, Principal.XML_PRINCIPAL, NAMESPACE); + } else { + pe = DomUtil.getChildElement(aceElement, Principal.XML_PRINCIPAL, SecurityConstants.NAMESPACE); + } + Principal principal = Principal.createFromXml(pe); + + boolean grant = DomUtil.hasChildElement(aceElement, Ace.XML_GRANT, SecurityConstants.NAMESPACE); + Element gdElem; + if (grant) { + gdElem = DomUtil.getChildElement(aceElement, XML_GRANT, NAMESPACE); + } else { + gdElem = DomUtil.getChildElement(aceElement, XML_DENY, NAMESPACE); + } + List privilegeList = new ArrayList(); + ElementIterator privIt = DomUtil.getChildren(gdElem, Privilege.XML_PRIVILEGE, NAMESPACE); + while (privIt.hasNext()) { + Privilege pv = Privilege.getPrivilege(privIt.nextElement()); + privilegeList.add(pv); + } + Privilege[] privileges = privilegeList.toArray(new Privilege[privilegeList.size()]); + + boolean isProtected = DomUtil.hasChildElement(aceElement, XML_PROTECTED, NAMESPACE); + String inheritedHref = null; + if (DomUtil.hasChildElement(aceElement, XML_INHERITED, NAMESPACE)) { + Element inhE = DomUtil.getChildElement(aceElement, XML_INHERITED, NAMESPACE); + inheritedHref = DomUtil.getChildText(inhE, DavConstants.XML_HREF, DavConstants.NAMESPACE); + } + + return new Ace(principal, invert, privileges, grant, isProtected, inheritedHref); + } + } +} Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/security/AclProperty.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-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/security/AclResource.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/security/AclResource.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/security/AclResource.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.webdav.security; + +import org.apache.jackrabbit.webdav.DavException; +import org.apache.jackrabbit.webdav.DavResource; +import org.apache.jackrabbit.webdav.DavServletResponse; +import org.apache.jackrabbit.webdav.version.DeltaVResource; +import org.apache.jackrabbit.webdav.version.report.Report; +import org.apache.jackrabbit.webdav.version.report.ReportInfo; + +/** + * AclResource... + */ +public interface AclResource extends DavResource { + + /** + * The AclResource must support the ACL method and the REPORT method in order + * to retrieve various security related reports. + * + * @see DeltaVResource#METHODS + * @see org.apache.jackrabbit.webdav.DavResource#METHODS + */ + public String METHODS = "ACL, REPORT"; + + /** + * Modify the DAV:acl property of this resource object.
+ * Note: RFC 3744 limits modification of access control elements (ACEs) to + * elements that are neither inherited nor protected. + * + * @param aclProperty DAV:acl property listing the set of ACEs to be modified + * by this call. This may be a subset of all access control elements + * present on this resource object only. + * @throws DavException If the request fails. RFC 3744 defines a set of + * preconditions which must be met for a successful ACL request. + * If these conditions are violated, this method must fail with + * {@link DavServletResponse#SC_FORBIDDEN 403 (Forbidden)} or + * {@link DavServletResponse#SC_CONFLICT 409 (Conflict)} and should provide + * a detailed error condition in the response body. See + * RFC 3744 Section 8.1.1 + * (ACL Preconditions) for further details. + */ + public void alterAcl(AclProperty aclProperty) throws DavException; + + /** + * Same as {@link DeltaVResource#getReport(ReportInfo)}. + * + * @param reportInfo specifying the report details retrieved from the REPORT + * request. + * @return the requested report. + * @throws DavException in case an error occurred or if the specified + * ReportInfo is either not valid or cannot be run by this + * resource. + */ + public Report getReport(ReportInfo reportInfo) throws DavException; +} Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/security/AclResource.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-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/security/AclRestrictionsProperty.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/security/AclRestrictionsProperty.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/security/AclRestrictionsProperty.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.webdav.security; + +import org.apache.jackrabbit.webdav.property.AbstractDavProperty; +import org.apache.jackrabbit.webdav.property.DavProperty; +import org.apache.jackrabbit.webdav.xml.DomUtil; +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +/** + * AclRestrictionsProperty as defined by RFC 3744 Section 5.6. + * DAV:acl-restrictions: + *
+ * <!ELEMENT acl-restrictions (grant-only?, no-invert?, deny-before-grant?, required-principal?)>
+ * <!ELEMENT grant-only EMPTY>
+ * <!ELEMENT no-invert EMPTY>
+ * <!ELEMENT deny-before-grant EMPTY>
+ * <!ELEMENT required-principal (all? | authenticated? | unauthenticated? | self? | href* | property*)>
+ * 
+ * + * @see Principal + * @see AclProperty + */ +public class AclRestrictionsProperty extends AbstractDavProperty { + + // TODO: RFC 3744 defines a distinct structure for required-principal + // than for principal. Current 'normal' principal is used instead. + + private static final String XML_GRANT_ONLY = "grant-only"; + private static final String XML_NO_INVERT = "no-invert"; + private static final String XML_DENY_BEFORE_GRANT = "deny-before-grant"; + + private final boolean grantOnly; + private final boolean noInvert; + private final boolean denyBeforeGrant; + private final Principal requiredPrincipal; + + public AclRestrictionsProperty(boolean grantOnly, boolean noInvert, boolean denyBeforeGrant, Principal requiredPrincipal) { + super(SecurityConstants.ACL_RESTRICTIONS, true); + this.grantOnly = grantOnly; + this.noInvert = noInvert; + this.denyBeforeGrant = denyBeforeGrant; + this.requiredPrincipal = requiredPrincipal; + } + + /** + * Not implemented. + * + * @throws UnsupportedOperationException + */ + public Object getValue() { + throw new UnsupportedOperationException("Not implemented. Use the property specific methods instead."); + } + + /** + * @see DavProperty#toXml(Document) + */ + @Override + public Element toXml(Document document) { + Element elem = getName().toXml(document); + if (grantOnly) { + DomUtil.addChildElement(elem, XML_GRANT_ONLY, SecurityConstants.NAMESPACE); + } + if (noInvert) { + DomUtil.addChildElement(elem, XML_NO_INVERT, SecurityConstants.NAMESPACE); + } + if (denyBeforeGrant) { + DomUtil.addChildElement(elem, XML_DENY_BEFORE_GRANT, SecurityConstants.NAMESPACE); + } + if (requiredPrincipal != null) { + elem.appendChild(requiredPrincipal.toXml(document)); + } + return elem; + } + + public boolean isGrantOnly() { + return grantOnly; + } + + public boolean isNoInvert() { + return noInvert; + } + + public boolean isDenyBeforeGrant() { + return denyBeforeGrant; + } + + public Principal getRequiredPrincipal() { + // TODO: check of should be replaced by specific required-principal... + return requiredPrincipal; + } +} Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/security/AclRestrictionsProperty.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-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/security/CurrentUserPrivilegeSetProperty.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/security/CurrentUserPrivilegeSetProperty.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/security/CurrentUserPrivilegeSetProperty.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.webdav.security; + +import org.apache.jackrabbit.webdav.DavException; +import org.apache.jackrabbit.webdav.DavServletResponse; +import org.apache.jackrabbit.webdav.property.AbstractDavProperty; +import org.apache.jackrabbit.webdav.property.DavProperty; +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +import java.util.Collection; +import java.util.HashSet; +import java.util.Set; + +/** + * CurrentUserPrivilegeSetProperty... + */ +public class CurrentUserPrivilegeSetProperty extends AbstractDavProperty> { + + private final Set privileges; + + /** + * Create a new instance of this property. + * + * @param privileges array privileges. + */ + public CurrentUserPrivilegeSetProperty(Privilege[] privileges) { + super(SecurityConstants.CURRENT_USER_PRIVILEGE_SET, true); + + this.privileges = new HashSet(); + for (Privilege privilege : privileges) { + if (privilege != null) { + this.privileges.add(privilege); + } + } + } + + /** + * Create a new CurrentUserPrivilegeSetProperty from a DavProperty + * as obtained from a MultiStatusResponse. + * + * @param xmlDavProperty + * @throws DavException + */ + public CurrentUserPrivilegeSetProperty(DavProperty xmlDavProperty) throws DavException { + super(xmlDavProperty.getName(), true); + if (!SecurityConstants.CURRENT_USER_PRIVILEGE_SET.equals(getName())) { + throw new DavException(DavServletResponse.SC_BAD_REQUEST, "DAV:current-user-privilege-set expected."); + } + privileges = new HashSet(); + + // parse property value + Object value = xmlDavProperty.getValue(); + if (value != null) { + if (value instanceof Element) { + privileges.add(Privilege.getPrivilege((Element)value)); + } else if (value instanceof Collection) { + for (Object entry : ((Collection) value)) { + if (entry instanceof Element) { + privileges.add(Privilege.getPrivilege((Element) entry)); + } + } + } + } + } + + /** + * @return a Collection of Privilege objects use for xml serialization. + * @see DavProperty#getValue() + * @see AbstractDavProperty#toXml(Document) + */ + public Collection getValue() { + return privileges; + } +} \ No newline at end of file Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/security/CurrentUserPrivilegeSetProperty.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-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/security/Principal.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/security/Principal.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/security/Principal.java (working copy) @@ -0,0 +1,189 @@ +/* + * 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.webdav.security; + +import org.apache.jackrabbit.webdav.DavConstants; +import org.apache.jackrabbit.webdav.DavException; +import org.apache.jackrabbit.webdav.DavServletResponse; +import org.apache.jackrabbit.webdav.property.DavPropertyName; +import org.apache.jackrabbit.webdav.xml.DomUtil; +import org.apache.jackrabbit.webdav.xml.XmlSerializable; +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +import java.util.HashMap; +import java.util.Map; + +/** + * Principal encapsulates the DAV:principal element which identifies + * the principal to which this ACE applies. + * RFC 3744 defines the following structure for this element: + *
+ * <!ELEMENT principal (href | all | authenticated | unauthenticated | property | self)>
+ * 
+ */ +public class Principal implements XmlSerializable, SecurityConstants { + + public static final String XML_PRINCIPAL = "principal"; + + private static final String XML_ALL = "all"; + private static final String XML_AUTHENTICATED = "authenticated"; + private static final String XML_UNAUTHENTICATED = "unauthenticated"; + private static final String XML_SELF = "self"; + private static final String XML_PROPERTY = "property"; + + private static final int TYPE_ALL = 0; + private static final int TYPE_AUTHENTICATED = 1; + private static final int TYPE_UNAUTHENTICATED = 2; + private static final int TYPE_SELF = 3; + private static final int TYPE_PROPERTY = 4; + private static final int TYPE_HREF = 5; + + private static final Principal ALL_PRINCIPAL = new Principal(TYPE_ALL); + private static final Principal AUTHENTICATED_PRINCIPAL = new Principal(TYPE_AUTHENTICATED); + private static final Principal UNAUTHENTICATED_PRINCIPAL = new Principal(TYPE_UNAUTHENTICATED); + private static final Principal SELF_PRINCIPAL = new Principal(TYPE_SELF); + + private static final Map PROP_PRINCIPALS = new HashMap(); + + private final int type; + private DavPropertyName propertyName; + private String href; + + private Principal(int type) { + this.type = type; + } + + private Principal(DavPropertyName propertyName) { + this.type = TYPE_PROPERTY; + this.propertyName = propertyName; + } + + private Principal(String href) { + this.type = TYPE_HREF; + this.href = href; + } + + /** + * @return href if this Principal is a href-typed principal, null + * otherwise. + */ + public String getHref() { + return href; + } + + /** + * @return propertyName if this Principal is a property-principal, + * null otherwise. + */ + public DavPropertyName getPropertyName() { + return propertyName; + } + + /** + * @see XmlSerializable#toXml(Document) + */ + public Element toXml(Document document) { + Element pEl = DomUtil.createElement(document, XML_PRINCIPAL, NAMESPACE); + switch (type) { + case TYPE_ALL: + DomUtil.addChildElement(pEl, XML_ALL, NAMESPACE); + break; + case TYPE_AUTHENTICATED: + DomUtil.addChildElement(pEl, XML_AUTHENTICATED, NAMESPACE); + break; + case TYPE_UNAUTHENTICATED: + DomUtil.addChildElement(pEl, XML_UNAUTHENTICATED, NAMESPACE); + break; + case TYPE_SELF: + DomUtil.addChildElement(pEl, XML_SELF, NAMESPACE); + break; + case TYPE_PROPERTY: + Element prop = DomUtil.addChildElement(pEl, XML_PROPERTY, NAMESPACE); + prop.appendChild(propertyName.toXml(document)); + break; + case TYPE_HREF: + Element hrefEl = DomUtil.hrefToXml(href, document); + pEl.appendChild(hrefEl); + break; + // no default + } + return pEl; + } + + public static Principal getAllPrincipal() { + return ALL_PRINCIPAL; + } + + public static Principal getAuthenticatedPrincipal() { + return AUTHENTICATED_PRINCIPAL; + } + + public static Principal getUnauthenticatedPrincipal() { + return UNAUTHENTICATED_PRINCIPAL; + } + + public static Principal getSelfPrincipal() { + return SELF_PRINCIPAL; + } + + public static Principal getPropertyPrincipal(DavPropertyName propertyName) { + if (propertyName == null) { + throw new IllegalArgumentException("Property-Principal must contain a valid property name."); + } + // there is a limited amount of properties, that can be used + // for a Property-Principal + if (PROP_PRINCIPALS.containsKey(propertyName)) { + return PROP_PRINCIPALS.get(propertyName); + } else { + Principal p = new Principal(propertyName); + PROP_PRINCIPALS.put(propertyName, p); + return p; + } + } + + public static Principal getHrefPrincipal(String href) { + if (href == null) { + throw new IllegalArgumentException("Href-Principal must contain a valid href."); + } + return new Principal(href); + } + + public static Principal createFromXml(Element principalElement) throws DavException { + if (!DomUtil.matches(principalElement, XML_PRINCIPAL, NAMESPACE)) { + throw new DavException(DavServletResponse.SC_BAD_REQUEST, "DAV:principal element expected."); + } + if (DomUtil.hasChildElement(principalElement, XML_ALL, NAMESPACE)) { + return ALL_PRINCIPAL; + } else if (DomUtil.hasChildElement(principalElement, XML_SELF, NAMESPACE)) { + return SELF_PRINCIPAL; + } else if (DomUtil.hasChildElement(principalElement, XML_AUTHENTICATED, NAMESPACE)) { + return AUTHENTICATED_PRINCIPAL; + } else if (DomUtil.hasChildElement(principalElement, XML_UNAUTHENTICATED, NAMESPACE)) { + return UNAUTHENTICATED_PRINCIPAL; + } else if (DomUtil.hasChildElement(principalElement, DavConstants.XML_HREF, DavConstants.NAMESPACE)) { + String href = DomUtil.getChildText(principalElement, DavConstants.XML_HREF, DavConstants.NAMESPACE); + return getHrefPrincipal(href); + } else if (DomUtil.hasChildElement(principalElement, XML_PROPERTY, NAMESPACE)) { + Element propEl = DomUtil.getChildElement(principalElement, XML_PROPERTY, NAMESPACE); + DavPropertyName pn = DavPropertyName.createFromXml(DomUtil.getFirstChildElement(propEl)); + return getPropertyPrincipal(pn); + } else { + throw new DavException(DavServletResponse.SC_BAD_REQUEST, "Invalid structure inside DAV:principal element."); + } + } +} Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/security/Principal.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-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/security/Privilege.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/security/Privilege.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/security/Privilege.java (working copy) @@ -0,0 +1,204 @@ +/* + * 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.webdav.security; + +import org.apache.jackrabbit.webdav.DavException; +import org.apache.jackrabbit.webdav.DavServletResponse; +import org.apache.jackrabbit.webdav.xml.DomUtil; +import org.apache.jackrabbit.webdav.xml.Namespace; +import org.apache.jackrabbit.webdav.xml.XmlSerializable; +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +import java.util.HashMap; +import java.util.Map; + +/** + * Privilege + */ +public class Privilege implements XmlSerializable { + + public static final String XML_PRIVILEGE = "privilege"; + + /** + * Map for registered privileges + */ + private static final Map REGISTERED_PRIVILEGES = new HashMap(); + + //-------------------------------------< Privileges defined by RFC 3744 >--- + /** + * The read privilege controls methods that return information about the + * state of the resource, including the resource's properties. Affected + * methods include GET and PROPFIND and OPTIONS. + * + * @see RFC 3744 Section 3.1. DAV:read Privilege + */ + public static final Privilege PRIVILEGE_READ = getPrivilege("read", SecurityConstants.NAMESPACE); + /** + * The write privilege controls methods that lock a resource or modify the + * content, dead properties, or (in the case of a collection) membership of + * the resource, such as PUT and PROPPATCH. + * + * @see RFC 3744 Section 3.2. DAV:write Privilege + */ + public static final Privilege PRIVILEGE_WRITE = getPrivilege("write", SecurityConstants.NAMESPACE); + /** + * The DAV:write-properties privilege controls methods that modify the dead + * properties of the resource, such as PROPPATCH. Whether this privilege may + * be used to control access to any live properties is determined by the + * implementation. + * + * @see RFC 3744 Section 3.3. DAV:write-properties Privilege + */ + public static final Privilege PRIVILEGE_WRITE_PROPERTIES = getPrivilege("write-properties", SecurityConstants.NAMESPACE); + /** + * The DAV:write-content privilege controls methods that modify the content + * of an existing resource, such as PUT. + * + * @see RFC 3744 Section 3.4. DAV:write-content Privilege + */ + public static final Privilege PRIVILEGE_WRITE_CONTENT = getPrivilege("write-content", SecurityConstants.NAMESPACE); + /** + * The DAV:unlock privilege controls the use of the UNLOCK method by a + * principal other than the lock owner (the principal that created a lock + * can always perform an UNLOCK). + * + * @see RFC 3744 Section 3.5. DAV:unlock Privilege + */ + public static final Privilege PRIVILEGE_UNLOCK = getPrivilege("unlock", SecurityConstants.NAMESPACE); + /** + * The DAV:read-acl privilege controls the use of PROPFIND to retrieve the + * DAV:acl property of the resource. + * + * @see RFC 3744 Section 3.6. DAV:read-acl Privilege + */ + public static final Privilege PRIVILEGE_READ_ACL = getPrivilege("read-acl", SecurityConstants.NAMESPACE); + /** + * The DAV:read-current-user-privilege-set privilege controls the use of + * PROPFIND to retrieve the DAV:current-user-privilege-set property of the + * resource. + * + * @see RFC 3744 Section 3.7. DAV:"read-current-user-privilege-set Privilege + */ + public static final Privilege PRIVILEGE_READ_CURRENT_USER_PRIVILEGE_SET = getPrivilege("read-current-user-privilege-set", SecurityConstants.NAMESPACE); + /** + * The DAV:write-acl privilege controls use of the ACL method to modify the + * DAV:acl property of the resource. + * + * @see RFC 3744 Section 3.8. DAV:write-acl Privilege + */ + public static final Privilege PRIVILEGE_WRITE_ACL = getPrivilege("write-acl", SecurityConstants.NAMESPACE); + /** + * The DAV:bind privilege allows a method to add a new member URL to the + * specified collection (for example via PUT or MKCOL). It is ignored for + * resources that are not collections. + * + * @see RFC 3744 Section 3.9. DAV:bind Privilege + */ + public static final Privilege PRIVILEGE_BIND = getPrivilege("bind", SecurityConstants.NAMESPACE); + /** + * The DAV:unbind privilege allows a method to remove a member URL from the + * specified collection (for example via DELETE or MOVE). It is ignored for + * resources that are not collections. + * + * @see RFC 3744 Section 3.10. DAV:unbind Privilege + */ + public static final Privilege PRIVILEGE_UNBIND = getPrivilege("unbind", SecurityConstants.NAMESPACE); + /** + * DAV:all is an aggregate privilege that contains the entire set of + * privileges that can be applied to the resource. + * + * @see RFC 3744 Section 3.11. DAV:all Privilege + */ + public static final Privilege PRIVILEGE_ALL = getPrivilege("all", SecurityConstants.NAMESPACE); + + private final String privilege; + private final Namespace namespace; + + /** + * Private constructor + * + * @param privilege + * @param namespace + */ + private Privilege(String privilege, Namespace namespace) { + this.privilege = privilege; + this.namespace = namespace; + } + + /** + * @return The local name of this Privilege. + */ + public String getName() { + return privilege; + } + + /** + * @return The namespace of this Privilege. + */ + public Namespace getNamespace() { + return namespace; + } + + /** + * @see XmlSerializable#toXml(Document) + */ + public Element toXml(Document document) { + Element privEl = DomUtil.createElement(document, XML_PRIVILEGE, SecurityConstants.NAMESPACE); + DomUtil.addChildElement(privEl, privilege, namespace); + return privEl; + } + + /** + * Factory method to create/retrieve a Privilege. + * + * @param privilege + * @param namespace + * @return + */ + public static Privilege getPrivilege(String privilege, Namespace namespace) { + if (privilege == null) { + throw new IllegalArgumentException("'null' is not a valid privilege."); + } + if (namespace == null) { + namespace = Namespace.EMPTY_NAMESPACE; + } + String key = "{" + namespace.getURI() + "}" + privilege; + if (REGISTERED_PRIVILEGES.containsKey(key)) { + return REGISTERED_PRIVILEGES.get(key); + } else { + Privilege p = new Privilege(privilege, namespace); + REGISTERED_PRIVILEGES.put(key, p); + return p; + } + } + + /** + * Factory method to create/retrieve a Privilege from the given + * DAV:privilege element. + * + * @param privilege + * @return + */ + public static Privilege getPrivilege(Element privilege) throws DavException { + if (!DomUtil.matches(privilege, XML_PRIVILEGE, SecurityConstants.NAMESPACE)) { + throw new DavException(DavServletResponse.SC_BAD_REQUEST, "DAV:privilege element expected."); + } + Element el = DomUtil.getFirstChildElement(privilege); + return getPrivilege(el.getLocalName(), DomUtil.getNamespace(el)); + } +} Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/security/Privilege.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-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/security/SecurityConstants.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/security/SecurityConstants.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/security/SecurityConstants.java (working copy) @@ -0,0 +1,110 @@ +/* + * 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.webdav.security; + +import org.apache.jackrabbit.webdav.DavConstants; +import org.apache.jackrabbit.webdav.DavMethods; +import org.apache.jackrabbit.webdav.property.DavPropertyName; +import org.apache.jackrabbit.webdav.property.HrefProperty; +import org.apache.jackrabbit.webdav.property.ResourceType; +import org.apache.jackrabbit.webdav.xml.Namespace; + +/** + * SecurityConstants interface lists constants defined by + * RFC 3744 (WebDAV Access + * Control Protocol). + */ +public interface SecurityConstants { + + /** + * Default Namespace constant + */ + public static final Namespace NAMESPACE = DavConstants.NAMESPACE; + + /** + * Principal resources must define DAV:principal XML element in the value + * of the DAV:resourcetype property. + */ + public static int PRINCIPAL_RESOURCETYPE = ResourceType.registerResourceType("principal", NAMESPACE); + + //---< Property Names for Principal Resource >------------------------------ + /** + * Protected href property DAV:principal-URL for principal resources. + * @see HrefProperty + */ + public static final DavPropertyName PRINCIPAL_URL = DavPropertyName.create("principal-URL", NAMESPACE); + /** + * Protected href property DAV:alternate-URI-set for principal resources. + * @see HrefProperty + */ + public static final DavPropertyName ALTERNATE_URI_SET = DavPropertyName.create("alternate-URI-set", NAMESPACE); + /** + * Protected href property DAV:group-member-set for principal resources. + * @see HrefProperty + */ + public static final DavPropertyName GROUP_MEMBER_SET = DavPropertyName.create("group-member-set", NAMESPACE); + /** + * Protected href property DAV:group-membership for principal resources. + * @see HrefProperty + */ + public static final DavPropertyName GROUP_MEMBERSHIP = DavPropertyName.create("group-membership", NAMESPACE); + + //---< Property Names for DavResource >------------------------------------- + /** + * Protected href property DAV:owner + * @see HrefProperty + */ + public static final DavPropertyName OWNER = DavPropertyName.create("owner", NAMESPACE); + /** + * Protected href property DAV:group + * @see HrefProperty + */ + public static final DavPropertyName GROUP = DavPropertyName.create("group", NAMESPACE); + /** + * Protected property DAV:supported-privilege-set + * @see CurrentUserPrivilegeSetProperty + */ + public static final DavPropertyName SUPPORTED_PRIVILEGE_SET = DavPropertyName.create("supported-privilege-set", NAMESPACE); + /** + * Protected property DAV:current-user-privilege-set + * @see CurrentUserPrivilegeSetProperty + */ + public static final DavPropertyName CURRENT_USER_PRIVILEGE_SET = DavPropertyName.create("current-user-privilege-set", NAMESPACE); + /** + * Protected property DAV:acl. Note, that DAV:acl property may be altered + * with a ACL request. + * + * @see AclProperty + * @see DavMethods#METHOD_ACL + */ + public static final DavPropertyName ACL = DavPropertyName.create("acl", NAMESPACE); + /** + * Protected property DAV:acl-restrictions + * @see AclRestrictionsProperty + */ + public static final DavPropertyName ACL_RESTRICTIONS = DavPropertyName.create("acl-restrictions", NAMESPACE); + /** + * Protected href property DAV:inherited-acl-set + * @see HrefProperty + */ + public static final DavPropertyName INHERITED_ACL_SET = DavPropertyName.create("inherited-acl-set", NAMESPACE); + /** + * Protected href property DAV:principal-collection-set + * @see HrefProperty + */ + public static final DavPropertyName PRINCIPAL_COLLECTION_SET = DavPropertyName.create("principal-collection-set", NAMESPACE); +} Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/security/SecurityConstants.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-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/security/SupportedPrivilege.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/security/SupportedPrivilege.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/security/SupportedPrivilege.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.webdav.security; + +import java.util.ArrayList; +import java.util.List; + +import org.apache.jackrabbit.webdav.DavException; +import org.apache.jackrabbit.webdav.DavServletResponse; +import org.apache.jackrabbit.webdav.xml.DomUtil; +import org.apache.jackrabbit.webdav.xml.ElementIterator; +import org.apache.jackrabbit.webdav.xml.Namespace; +import org.apache.jackrabbit.webdav.xml.XmlSerializable; +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +/** + * SupportedPrivilege... + */ +public class SupportedPrivilege implements XmlSerializable { + + private static final String XML_SUPPORTED_PRIVILEGE = "supported-privilege"; + private static final String XML_ABSTRACT = "abstract"; + private static final String XML_DESCRIPTION = "description"; + + private final Privilege privilege; + private final boolean isAbstract; + private final String description; + private final String descriptionLanguage; + private final SupportedPrivilege[] supportedPrivileges; + + /** + * + * @param privilege + * @param description + * @param descriptionLanguage + * @param isAbstract + * @param supportedPrivileges + */ + public SupportedPrivilege(Privilege privilege, String description, + String descriptionLanguage, boolean isAbstract, + SupportedPrivilege[] supportedPrivileges) { + if (privilege == null) { + throw new IllegalArgumentException("DAV:supported-privilege element must contain a single privilege."); + } + this.privilege = privilege; + this.description = description; + this.descriptionLanguage = descriptionLanguage; + this.isAbstract = isAbstract; + this.supportedPrivileges = supportedPrivileges; + } + + /** + * @see XmlSerializable#toXml(Document) + */ + public Element toXml(Document document) { + Element spElem = DomUtil.createElement(document, XML_SUPPORTED_PRIVILEGE, SecurityConstants.NAMESPACE); + spElem.appendChild(privilege.toXml(document)); + if (isAbstract) { + DomUtil.addChildElement(spElem, XML_ABSTRACT, SecurityConstants.NAMESPACE); + } + if (description != null) { + Element desc = DomUtil.addChildElement(spElem, XML_DESCRIPTION, SecurityConstants.NAMESPACE, description); + if (descriptionLanguage != null) { + DomUtil.setAttribute(desc, "lang", Namespace.XML_NAMESPACE, descriptionLanguage); + } + } + if (supportedPrivileges != null) { + for (SupportedPrivilege supportedPrivilege : supportedPrivileges) { + spElem.appendChild(supportedPrivilege.toXml(document)); + } + } + return spElem; + } + + public Privilege getPrivilege() { + return privilege; + } + + public boolean isAbstract() { + return isAbstract; + } + + public SupportedPrivilege[] getSupportedPrivileges() { + return supportedPrivileges; + } + + /** + * Factory method to create/retrieve a SupportedPrivilege from the given + * DAV:privilege element. + * + * @param privilege + * @return + */ + static SupportedPrivilege getSupportedPrivilege(Element supportedPrivilege) throws DavException { + if (!DomUtil.matches(supportedPrivilege, XML_SUPPORTED_PRIVILEGE, SecurityConstants.NAMESPACE)) { + throw new DavException(DavServletResponse.SC_BAD_REQUEST, "DAV:supported-privilege element expected."); + } + boolean isAbstract = false; + Privilege privilege = null; + String description = null; + String descriptionLanguage = null; + List sp = new ArrayList(); + + ElementIterator children = DomUtil.getChildren(supportedPrivilege); + while (children.hasNext()) { + Element child = children.next(); + if (child.getLocalName().equals(XML_ABSTRACT)) { + isAbstract = true; + } else if (child.getLocalName().equals(Privilege.XML_PRIVILEGE)) { + privilege = Privilege.getPrivilege(child); + } else if (child.getLocalName().equals(XML_DESCRIPTION)) { + description = child.getLocalName(); + if (child.hasAttribute(descriptionLanguage)) { + descriptionLanguage = child.getAttribute(descriptionLanguage); + } + } else if (child.getLocalName().equals(XML_SUPPORTED_PRIVILEGE)) { + sp.add(getSupportedPrivilege(child)); + } + } + return new SupportedPrivilege(privilege, description, + descriptionLanguage, isAbstract, + sp.toArray(new SupportedPrivilege[sp.size()])); + } +} Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/security/SupportedPrivilege.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-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/security/SupportedPrivilegeSetProperty.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/security/SupportedPrivilegeSetProperty.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/security/SupportedPrivilegeSetProperty.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.webdav.security; + +import org.apache.jackrabbit.webdav.DavException; +import org.apache.jackrabbit.webdav.DavServletResponse; +import org.apache.jackrabbit.webdav.property.AbstractDavProperty; +import org.apache.jackrabbit.webdav.property.DavProperty; +import org.w3c.dom.Element; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.List; +import java.util.Collections; + +/** + * SupportedPrivilegeSetProperty defines the + * {@link SecurityConstants#SUPPORTED_PRIVILEGE_SET} property, used to identify + * the privileges defined for the resource. RFC 3744 defines the the following + * structure for this property: + *
+ * <!ELEMENT supported-privilege-set (supported-privilege*)>
+ * <!ELEMENT supported-privilege (privilege, abstract?, description, supported-privilege*)>
+ * <!ELEMENT privilege ANY>
+ * <!ELEMENT abstract EMPTY>
+ * <!ELEMENT description #PCDATA>
+ * 
+ * + * @see SupportedPrivilege + * @see Privilege + */ +public class SupportedPrivilegeSetProperty extends AbstractDavProperty> { + + private final SupportedPrivilege[] supportedPrivileges; + + /** + * Create a new SupportedPrivilegeSetProperty. + * + * @param supportedPrivileges + */ + public SupportedPrivilegeSetProperty(SupportedPrivilege[] supportedPrivileges) { + super(SecurityConstants.SUPPORTED_PRIVILEGE_SET, true); + this.supportedPrivileges = supportedPrivileges; + } + + public SupportedPrivilegeSetProperty(DavProperty p) throws DavException { + super(SecurityConstants.SUPPORTED_PRIVILEGE_SET, true); + if (!SecurityConstants.SUPPORTED_PRIVILEGE_SET.equals(getName())) { + throw new DavException(DavServletResponse.SC_BAD_REQUEST, "DAV:supported-privilege-set expected."); + } + + List supportedPrivs = new ArrayList(); + + for (Object obj : Collections.singletonList(p.getValue())) { + if (obj instanceof Element) { + supportedPrivs.add(SupportedPrivilege.getSupportedPrivilege((Element) obj)); + } else if (obj instanceof Collection) { + for (Object entry : ((Collection) obj)) { + if (entry instanceof Element) { + supportedPrivs.add(SupportedPrivilege.getSupportedPrivilege((Element) entry)); + } + } + } + } + supportedPrivileges = supportedPrivs.toArray(new SupportedPrivilege[supportedPrivs.size()]); + } + + /** + * @return List of {@link SupportedPrivilege}s. + */ + public List getValue() { + List l; + if (supportedPrivileges == null) { + l = Collections.emptyList(); + } else { + l = Arrays.asList(supportedPrivileges); + } + return l; + } +} \ No newline at end of file Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/security/SupportedPrivilegeSetProperty.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-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/security/package-info.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/security/package-info.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/security/package-info.java (working copy) @@ -0,0 +1,18 @@ +/* + * 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. + */ +@org.osgi.annotation.versioning.Version("1.0.0") +package org.apache.jackrabbit.webdav.security; Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/security/package-info.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/security/report/AbstractSecurityReport.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/security/report/AbstractSecurityReport.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/security/report/AbstractSecurityReport.java (working copy) @@ -0,0 +1,82 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.jackrabbit.webdav.security.report; + +import org.apache.jackrabbit.webdav.DavConstants; +import org.apache.jackrabbit.webdav.DavException; +import org.apache.jackrabbit.webdav.DavResource; +import org.apache.jackrabbit.webdav.DavServletResponse; +import org.apache.jackrabbit.webdav.MultiStatus; +import org.apache.jackrabbit.webdav.MultiStatusResponse; +import org.apache.jackrabbit.webdav.version.report.AbstractReport; +import org.apache.jackrabbit.webdav.version.report.Report; +import org.apache.jackrabbit.webdav.version.report.ReportInfo; +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +/** + * AbstractSecurityReport covers basic validation and utilities + * common to the majority of the reports defined within RFC 3744. + */ +public abstract class AbstractSecurityReport extends AbstractReport { + + protected MultiStatusResponse[] responses; + + /** + * Always returns true. + * + * @return true + */ + public boolean isMultiStatusReport() { + return true; + } + + /** + * Checks if the given resource and report info are not null, + * that the requested report type matches this implementation and that no + * other Depth header than 0 is present. + * + * @param resource + * @param info + * @throws DavException + */ + public void init(DavResource resource, ReportInfo info) throws DavException { + if (resource == null || info == null) { + throw new DavException(DavServletResponse.SC_BAD_REQUEST, "Unable to run report: WebDAV Resource and ReportInfo must not be null."); + } + if (!getType().isRequestedReportType(info)) { + throw new DavException(DavServletResponse.SC_BAD_REQUEST, "Expected report type: '" + getType().getReportName() + "', found: '" + info.getReportName() + ";" + "'."); + } + if (info.getDepth() > DavConstants.DEPTH_0) { + throw new DavException(DavServletResponse.SC_BAD_REQUEST, "Invalid Depth header: " + info.getDepth()); + } + } + + /** + * @return DAV:multistatus element listing the matching resources. + * @see Report#toXml(Document) + */ + public Element toXml(Document document) { + MultiStatus ms = new MultiStatus(); + if (responses != null) { + for (MultiStatusResponse response : responses) { + ms.addResponse(response); + } + } + return ms.toXml(document); + } +} Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/security/report/AbstractSecurityReport.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-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/security/report/AclPrincipalReport.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/security/report/AclPrincipalReport.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/security/report/AclPrincipalReport.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.webdav.security.report; + +import org.apache.jackrabbit.webdav.DavException; +import org.apache.jackrabbit.webdav.DavResource; +import org.apache.jackrabbit.webdav.DavResourceLocator; +import org.apache.jackrabbit.webdav.DavServletResponse; +import org.apache.jackrabbit.webdav.MultiStatusResponse; +import org.apache.jackrabbit.webdav.property.DavProperty; +import org.apache.jackrabbit.webdav.security.AclProperty; +import org.apache.jackrabbit.webdav.security.SecurityConstants; +import org.apache.jackrabbit.webdav.version.report.Report; +import org.apache.jackrabbit.webdav.version.report.ReportInfo; +import org.apache.jackrabbit.webdav.version.report.ReportType; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * The AclPrincipalReport report returns the requested property set + * for all principals in the DAV:acl property, that are identified by http(s) + * URLs or by a DAV:property principal. + *

+ * The request body MUST be a DAV:acl-principal-prop-set XML element: + *

+ * <!ELEMENT acl-principal-prop-set ANY>
+ * ANY value: a sequence of one or more elements, with at most one
+ *            DAV:prop element.
+ * prop: see RFC 2518, Section 12.11
+ * 
+ * The response body MUST be a DAV:multistatus element containing a + * DAV:response element for each principal identified by a http(s) URL listed + * in a DAV:principal XML element of an ACE within the DAV:acl property of the + * resource this report is requested for. + */ +public class AclPrincipalReport extends AbstractSecurityReport { + + public static final String REPORT_NAME = "acl-principal-prop-set"; + + /** + * The report type + */ + public static final ReportType REPORT_TYPE = ReportType.register(REPORT_NAME, SecurityConstants.NAMESPACE, AclPrincipalReport.class); + + /** + * @see Report#getType() + */ + public ReportType getType() { + return REPORT_TYPE; + } + + /** + * @see Report#init(DavResource, ReportInfo) + */ + @Override + public void init(DavResource resource, ReportInfo info) throws DavException { + super.init(resource, info); + // build the DAV:responses objects. + DavProperty acl = resource.getProperty(SecurityConstants.ACL); + if (!(acl instanceof AclProperty)) { + throw new DavException(DavServletResponse.SC_INTERNAL_SERVER_ERROR, "DAV:acl property expected."); + } + + DavResourceLocator loc = resource.getLocator(); + Map respMap = new HashMap(); + List list = (List) ((AclProperty)acl).getValue(); + for (AclProperty.Ace ace : list) { + String href = normalizeResourceHref(ace.getPrincipal().getHref()); + if (href == null || respMap.containsKey(href)) { + // ignore non-href principals and principals that have been listed before + continue; + } + // href-principal that has not been found before + DavResourceLocator princLocator = loc.getFactory().createResourceLocator(loc.getPrefix(), href); + DavResource principalResource = resource.getFactory().createResource(princLocator, resource.getSession()); + respMap.put(href, new MultiStatusResponse(principalResource, info.getPropertyNameSet())); + } + this.responses = respMap.values().toArray(new MultiStatusResponse[respMap.size()]); + } +} Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/security/report/AclPrincipalReport.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-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/security/report/PrincipalMatchReport.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/security/report/PrincipalMatchReport.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/security/report/PrincipalMatchReport.java (working copy) @@ -0,0 +1,115 @@ +/* + * 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.webdav.security.report; + +import org.apache.jackrabbit.webdav.DavException; +import org.apache.jackrabbit.webdav.DavResource; +import org.apache.jackrabbit.webdav.DavServletResponse; +import org.apache.jackrabbit.webdav.MultiStatusResponse; +import org.apache.jackrabbit.webdav.property.DavPropertyName; +import org.apache.jackrabbit.webdav.security.SecurityConstants; +import org.apache.jackrabbit.webdav.version.report.Report; +import org.apache.jackrabbit.webdav.version.report.ReportInfo; +import org.apache.jackrabbit.webdav.version.report.ReportType; +import org.apache.jackrabbit.webdav.xml.DomUtil; +import org.w3c.dom.Element; + +/** + * PrincipalMatchReport can be request for any collection resources. + * The resulting report identifies member resources that either represent the + * requesting principal ("principal resources") or contain a specified property + * that matches the requesting principal in its value. For the first match + * the request body must contain a DAV:self element, for the latter a + * DAV:principal-property element which in turn specifies the property to + * be examined. + *

+ * The request body MUST be a DAV:principal-match XML element: + *

+ * <!ELEMENT principal-match ((principal-property | self), prop?)>
+ * <!ELEMENT principal-property ANY>
+ * ANY value: an element whose value identifies a property. The value of this
+ * property typically contains an href element referring to a principal.
+ * <!ELEMENT self EMPTY>
+ * prop: see RFC 2518, Section 12.11
+ * 
+ * The response body of a successful report must contain a DAV:multistatus + * element. Each matching member is present with a separate DAV:response element. + */ +public class PrincipalMatchReport extends AbstractSecurityReport { + + public static final String XML_PRINCIPAL_PROPERTY = "principal-property"; + public static final String XML_SELF = "self"; + + /** + * The report name + */ + public static final String REPORT_NAME = "principal-match"; + + /** + * The report type + */ + public static final ReportType REPORT_TYPE = ReportType.register(REPORT_NAME, SecurityConstants.NAMESPACE, PrincipalMatchReport.class); + + private DavPropertyName principalPropertyName; + + /** + * @see Report#getType() + */ + public ReportType getType() { + return REPORT_TYPE; + } + + /** + * @see Report#init(DavResource, ReportInfo) + */ + @Override + public void init(DavResource resource, ReportInfo info) throws DavException { + super.init(resource, info); + if (info.containsContentElement(XML_PRINCIPAL_PROPERTY, SecurityConstants.NAMESPACE)) { + Element pp = info.getContentElement(XML_PRINCIPAL_PROPERTY, SecurityConstants.NAMESPACE); + principalPropertyName = DavPropertyName.createFromXml(DomUtil.getFirstChildElement(pp)); + } else if (info.containsContentElement(XML_SELF, SecurityConstants.NAMESPACE)) { + principalPropertyName = SecurityConstants.PRINCIPAL_URL; + } else { + throw new DavException(DavServletResponse.SC_BAD_REQUEST, "DAV:self or DAV:principal-property element required within report info."); + } + } + + //------------------------------------< implementation specific methods >--- + /** + * Retrieve the property name that indicates which property must be search + * for matching principals.
+ * Note, that the search result must be converted to {@link MultiStatusResponse}s + * that must be returned back to this report. + * + * @return property name which should be check for match with the current + * user. + * @see #setResponses(MultiStatusResponse[]) + */ + public DavPropertyName getPrincipalPropertyName() { + return principalPropertyName; + } + + /** + * Write the result(s) of the match back to the report. + * + * @param responses + */ + public void setResponses(MultiStatusResponse[] responses) { + this.responses = responses; + } +} Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/security/report/PrincipalMatchReport.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-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/security/report/PrincipalSearchReport.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/security/report/PrincipalSearchReport.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/security/report/PrincipalSearchReport.java (working copy) @@ -0,0 +1,184 @@ +/* + * 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.webdav.security.report; + +import org.apache.jackrabbit.webdav.DavConstants; +import org.apache.jackrabbit.webdav.DavException; +import org.apache.jackrabbit.webdav.DavResource; +import org.apache.jackrabbit.webdav.DavServletResponse; +import org.apache.jackrabbit.webdav.MultiStatusResponse; +import org.apache.jackrabbit.webdav.property.DavPropertyNameSet; +import org.apache.jackrabbit.webdav.property.HrefProperty; +import org.apache.jackrabbit.webdav.security.SecurityConstants; +import org.apache.jackrabbit.webdav.version.report.Report; +import org.apache.jackrabbit.webdav.version.report.ReportInfo; +import org.apache.jackrabbit.webdav.version.report.ReportType; +import org.apache.jackrabbit.webdav.xml.DomUtil; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.w3c.dom.Element; + +import java.util.List; + +/** + * The PrincipalSearchReport performs a search for all principals + * that match the search criteria specified in the request. + *

+ * The following XML structure is required in the request body: + *

+ * <!ELEMENT principal-property-search ((property-search+), prop?, apply-to-principal-collection-set?) >
+ * <!ELEMENT property-search (prop, match) >
+ *  prop: see RFC 2518, Section 12.11
+ * <!ELEMENT match #PCDATA >
+ * <!ELEMENT apply-to-principal-collection-set #EMPTY >
+ * 
+ * DAV:property-search contains lists the properties to be + * searched inside the DAV:prop element and the query string inside the DAV:match + * element. Multiple DAV:property-search elements or multiple elements within the + * DAV:prop element will be interpreted with a logical AND. + *

+ * DAV:prop lists the property names to be reported in the + * response for each of the principle resources found. + *

+ * DAV:apply-to-principal-collection-set: Optional empty element. + * If present in the request body the search will be executed over all members + * of the collections that are listed as values in the DAV:principal-collection-set + * property present on the resource the report has been requested for. + * Otherwise the search is limited to all members (at any depth) of that resource + * itself. + *

+ * The response body must contain a single DAV:multistatus XML element. + */ +public class PrincipalSearchReport extends AbstractSecurityReport { + + private static Logger log = LoggerFactory.getLogger(PrincipalSearchReport.class); + + public static final String XML_APPLY_TO_PRINCIPAL_COLLECTION_SET = "apply-to-principal-collection-set"; + public static final String XML_PROPERTY_SEARCH = "property-search"; + public static final String XML_MATCH = "match"; + + /** + * The report name + */ + public static final String REPORT_NAME = "principal-property-search"; + + /** + * The report type + */ + public static final ReportType REPORT_TYPE = ReportType.register(REPORT_NAME, SecurityConstants.NAMESPACE, PrincipalSearchReport.class); + + private String[] searchRoots; + private SearchArgument[] searchArguments; + + /** + * @see Report#getType() + */ + public ReportType getType() { + return REPORT_TYPE; + } + + /** + * @see Report#init(DavResource, ReportInfo) + */ + @Override + public void init(DavResource resource, ReportInfo info) throws DavException { + super.init(resource, info); + // make sure the request body contains all mandatory elements + if (!info.containsContentElement(XML_PROPERTY_SEARCH, SecurityConstants.NAMESPACE)) { + throw new DavException(DavServletResponse.SC_BAD_REQUEST, "Request body must contain at least a single DAV:property-search element."); + } + List psElements = info.getContentElements(XML_PROPERTY_SEARCH, SecurityConstants.NAMESPACE); + searchArguments = new SearchArgument[psElements.size()]; + int i = 0; + for (Element psElement : psElements) { + searchArguments[i++] = new SearchArgument(psElement); + } + + if (info.containsContentElement(XML_APPLY_TO_PRINCIPAL_COLLECTION_SET, SecurityConstants.NAMESPACE)) { + HrefProperty p = new HrefProperty(resource.getProperty(SecurityConstants.PRINCIPAL_COLLECTION_SET)); + searchRoots = p.getHrefs().toArray(new String[0]); + } else { + searchRoots = new String[] {resource.getHref()}; + } + } + + //------------------------------------< implementation specific methods >--- + /** + * Retrieve the the locations where the search should be performed.
+ * Note, that the search result must be converted to {@link MultiStatusResponse}s + * that must be returned back to this report. + * + * @return href of collections that act as start for the search. + * @see #setResponses(MultiStatusResponse[]) + */ + public String[] getSearchRoots() { + return searchRoots; + } + + /** + * Retrieve the search arguments used to run the search for principals.
+ * Note, that the search result must be converted to {@link MultiStatusResponse}s + * that must be returned back to this report. + * + * @return array of SearchArgument used to run the principal + * search. + * @see #setResponses(MultiStatusResponse[]) + */ + public SearchArgument[] getSearchArguments() { + return searchArguments; + } + + /** + * Write the search result back to the report. + * + * @param responses + */ + public void setResponses(MultiStatusResponse[] responses) { + this.responses = responses; + } + + //--------------------------------< implementation specific inner class >--- + /** + * Inner utility class preparing the query arguments present in the + * DAV:property-search element(s). + */ + protected class SearchArgument { + + private final DavPropertyNameSet searchProps; + private final String searchString; + + private SearchArgument(Element propSearch) { + searchProps = new DavPropertyNameSet(DomUtil.getChildElement(propSearch, DavConstants.XML_PROP, DavConstants.NAMESPACE)); + searchString = DomUtil.getChildText(propSearch, XML_MATCH, SecurityConstants.NAMESPACE); + } + + /** + * @return property name set used to restrict the search to a limited + * amount of properties. + */ + protected DavPropertyNameSet getSearchProperties() { + return searchProps; + } + + /** + * @return query string as present in the DAV:match element. + */ + protected String getSearchString() { + return searchString; + } + } +} Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/security/report/PrincipalSearchReport.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-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/security/report/SearchablePropertyReport.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/security/report/SearchablePropertyReport.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/security/report/SearchablePropertyReport.java (working copy) @@ -0,0 +1,204 @@ +/* + * 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.webdav.security.report; + +import java.util.HashSet; +import java.util.Set; + +import org.apache.jackrabbit.webdav.DavConstants; +import org.apache.jackrabbit.webdav.DavException; +import org.apache.jackrabbit.webdav.DavResource; +import org.apache.jackrabbit.webdav.DavServletResponse; +import org.apache.jackrabbit.webdav.property.DavPropertyName; +import org.apache.jackrabbit.webdav.property.DavPropertyNameSet; +import org.apache.jackrabbit.webdav.security.SecurityConstants; +import org.apache.jackrabbit.webdav.version.report.AbstractReport; +import org.apache.jackrabbit.webdav.version.report.Report; +import org.apache.jackrabbit.webdav.version.report.ReportInfo; +import org.apache.jackrabbit.webdav.version.report.ReportType; +import org.apache.jackrabbit.webdav.xml.DomUtil; +import org.apache.jackrabbit.webdav.xml.Namespace; +import org.apache.jackrabbit.webdav.xml.XmlSerializable; +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +/** + * SearchablePropertyReport identifies those properties that may be + * searched using the {@link PrincipalSearchReport DAV:principal-property-search REPORT}. + * This report must be supported on all collections identified in the value of + * a DAV:principal-collection-set property. + *

+ * The request body MUST be an empty DAV:principal-search-property-set element. + *

+ * The response body MUST be a DAV:principal-search-property-set XML element + * with the following structure: + *

+ *  <!ELEMENT principal-search-property-set (principal-search-property*) >
+ *  <!ELEMENT principal-search-property (prop, description) >
+ *  prop: see RFC 2518, Section 12.11
+ *  <!ELEMENT description #PCDATA >
+ *  Human readable description. Note, that the language of the description must
+ *  be indicated by the xml:lang attribute.
+ * 
+ * + * Note that a DAV:principal-search-property XML element is required for each + * property that may be searched with the DAV:principal-property-search REPORT. + */ +public class SearchablePropertyReport extends AbstractReport { + + /** + * The report name + */ + public static final String REPORT_NAME = "principal-search-property-set"; + + /** + * The report type + */ + public static final ReportType REPORT_TYPE = ReportType.register(REPORT_NAME, SecurityConstants.NAMESPACE, SearchablePropertyReport.class); + + /** + * Constant used for the DAV:principal-search-property-set response element. + */ + public static final String XML_PRINCIPAL_SEARCH_PROPERTY_SET = "principal-search-property-set"; + + /** + * Set collecting the DAV:principal-search-property entries. + */ + private final Set searchPropertySet = new HashSet(); + + /** + * @see Report#getType() + */ + public ReportType getType() { + return REPORT_TYPE; + } + + /** + * @return false Status code of after a successful completion must be + * {@link DavServletResponse#SC_OK 200 (ok)}. + * @see Report#isMultiStatusReport() + */ + public boolean isMultiStatusReport() { + return false; + } + + /** + * @see Report#init(DavResource, ReportInfo) + */ + public void init(DavResource resource, ReportInfo info) throws DavException { + if (resource == null || info == null) { + throw new DavException(DavServletResponse.SC_BAD_REQUEST, "Unable to run report: WebDAV Resource and ReportInfo must not be null."); + } + if (!getType().isRequestedReportType(info)) { + throw new DavException(DavServletResponse.SC_BAD_REQUEST, "Expected report type: '" + getType().getReportName() + "', found: '" + info.getReportName() + ";" + "'."); + } + if (info.getDepth() > DavConstants.DEPTH_0) { + throw new DavException(DavServletResponse.SC_BAD_REQUEST, "Invalid Depth header: " + info.getDepth()); + } + } + + /** + * @see Report#toXml(Document) + */ + public Element toXml(Document document) { + Element rootElem = DomUtil.createElement(document, XML_PRINCIPAL_SEARCH_PROPERTY_SET, SecurityConstants.NAMESPACE); + for (PrincipalSearchProperty psp : searchPropertySet) { + rootElem.appendChild(psp.toXml(document)); + } + return rootElem; + } + + //-----------------------------------------------------< implementation >--- + /** + * Add a property name that should be listed in the DAV:principal-search-property-set. + * + * @param propName a property name that may be searched in the {@link PrincipalSearchReport}. + * @param description Human readable description of the searchable property. + * @param language defines in which language the description is written. + * @throws IllegalArgumentException if propName is null. + */ + public void addPrincipalSearchProperty(DavPropertyName propName, + String description, String language) { + searchPropertySet.add(new PrincipalSearchProperty(propName, description, language)); + } + + //--------------------------------------------------------< inner class >--- + /** + * Inner class encapsulating the DAV:principal-search-property + */ + private class PrincipalSearchProperty implements XmlSerializable { + + private static final String XML_PRINCIPAL_SEARCH_PROPERTY = "principal-search-property"; + private static final String XML_DESCRIPTION = "description"; + private static final String ATTR_LANG = "lang"; + + private final DavPropertyName propName; + private final String description; + private final String language; + private final int hashCode; + + private PrincipalSearchProperty(DavPropertyName propName, + String description, + String language) { + if (propName == null) { + throw new IllegalArgumentException("null is not a valid DavPropertyName for the DAV:principal-search-property."); + } + this.propName = propName; + this.description = description; + this.language = language; + hashCode = propName.hashCode(); + } + + /** + * @see XmlSerializable#toXml(Document) + */ + public Element toXml(Document document) { + Element psElem = DomUtil.createElement(document, XML_PRINCIPAL_SEARCH_PROPERTY, SecurityConstants.NAMESPACE); + // create property set from the single property name + DavPropertyNameSet pnSet = new DavPropertyNameSet(); + pnSet.add(propName); + psElem.appendChild(pnSet.toXml(document)); + // append description if present + if (description != null) { + Element desc = DomUtil.addChildElement(psElem, XML_DESCRIPTION, SecurityConstants.NAMESPACE, description); + if (language != null) { + DomUtil.setAttribute(desc, ATTR_LANG, Namespace.XML_NAMESPACE, language); + } + } + return psElem; + } + + //---------------------------------------------------------< Object >--- + @Override + public boolean equals(Object obj) { + if (obj == this) { + return true; + } + if (obj instanceof PrincipalSearchProperty) { + PrincipalSearchProperty other = (PrincipalSearchProperty)obj; + // ignore the optional description/language + return hashCode == other.hashCode; + } + return false; + } + + @Override + public int hashCode() { + return hashCode; + } + } +} Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/security/report/SearchablePropertyReport.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-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/security/report/package-info.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/security/report/package-info.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/security/report/package-info.java (working copy) @@ -0,0 +1,18 @@ +/* + * 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. + */ +@org.osgi.annotation.versioning.Version("1.1.0") +package org.apache.jackrabbit.webdav.security.report; Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/security/report/package-info.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/server/AbstractWebdavServlet.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/server/AbstractWebdavServlet.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/server/AbstractWebdavServlet.java (working copy) @@ -0,0 +1,1557 @@ +/* + * 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.webdav.server; + +import org.apache.jackrabbit.webdav.ContentCodingAwareRequest; +import org.apache.jackrabbit.webdav.DavCompliance; +import org.apache.jackrabbit.webdav.DavConstants; +import org.apache.jackrabbit.webdav.DavException; +import org.apache.jackrabbit.webdav.DavLocatorFactory; +import org.apache.jackrabbit.webdav.DavMethods; +import org.apache.jackrabbit.webdav.DavResource; +import org.apache.jackrabbit.webdav.DavResourceFactory; +import org.apache.jackrabbit.webdav.DavServletRequest; +import org.apache.jackrabbit.webdav.DavServletResponse; +import org.apache.jackrabbit.webdav.DavSessionProvider; +import org.apache.jackrabbit.webdav.MultiStatus; +import org.apache.jackrabbit.webdav.MultiStatusResponse; +import org.apache.jackrabbit.webdav.WebdavRequest; +import org.apache.jackrabbit.webdav.WebdavRequestImpl; +import org.apache.jackrabbit.webdav.WebdavResponse; +import org.apache.jackrabbit.webdav.WebdavResponseImpl; +import org.apache.jackrabbit.webdav.bind.RebindInfo; +import org.apache.jackrabbit.webdav.bind.UnbindInfo; +import org.apache.jackrabbit.webdav.bind.BindableResource; +import org.apache.jackrabbit.webdav.bind.BindInfo; +import org.apache.jackrabbit.webdav.header.CodedUrlHeader; +import org.apache.jackrabbit.webdav.io.InputContext; +import org.apache.jackrabbit.webdav.io.InputContextImpl; +import org.apache.jackrabbit.webdav.io.OutputContext; +import org.apache.jackrabbit.webdav.io.OutputContextImpl; +import org.apache.jackrabbit.webdav.lock.ActiveLock; +import org.apache.jackrabbit.webdav.lock.LockDiscovery; +import org.apache.jackrabbit.webdav.lock.LockInfo; +import org.apache.jackrabbit.webdav.observation.EventDiscovery; +import org.apache.jackrabbit.webdav.observation.ObservationResource; +import org.apache.jackrabbit.webdav.observation.Subscription; +import org.apache.jackrabbit.webdav.observation.SubscriptionInfo; +import org.apache.jackrabbit.webdav.ordering.OrderPatch; +import org.apache.jackrabbit.webdav.ordering.OrderingResource; +import org.apache.jackrabbit.webdav.property.DavProperty; +import org.apache.jackrabbit.webdav.property.DavPropertyName; +import org.apache.jackrabbit.webdav.property.DavPropertyNameSet; +import org.apache.jackrabbit.webdav.property.DavPropertySet; +import org.apache.jackrabbit.webdav.property.PropEntry; +import org.apache.jackrabbit.webdav.search.SearchConstants; +import org.apache.jackrabbit.webdav.search.SearchInfo; +import org.apache.jackrabbit.webdav.search.SearchResource; +import org.apache.jackrabbit.webdav.security.AclProperty; +import org.apache.jackrabbit.webdav.security.AclResource; +import org.apache.jackrabbit.webdav.transaction.TransactionInfo; +import org.apache.jackrabbit.webdav.transaction.TransactionResource; +import org.apache.jackrabbit.webdav.util.CSRFUtil; +import org.apache.jackrabbit.webdav.util.HttpDateTimeFormatter; +import org.apache.jackrabbit.webdav.version.ActivityResource; +import org.apache.jackrabbit.webdav.version.DeltaVConstants; +import org.apache.jackrabbit.webdav.version.DeltaVResource; +import org.apache.jackrabbit.webdav.version.LabelInfo; +import org.apache.jackrabbit.webdav.version.MergeInfo; +import org.apache.jackrabbit.webdav.version.OptionsInfo; +import org.apache.jackrabbit.webdav.version.OptionsResponse; +import org.apache.jackrabbit.webdav.version.UpdateInfo; +import org.apache.jackrabbit.webdav.version.VersionControlledResource; +import org.apache.jackrabbit.webdav.version.VersionResource; +import org.apache.jackrabbit.webdav.version.VersionableResource; +import org.apache.jackrabbit.webdav.version.report.Report; +import org.apache.jackrabbit.webdav.version.report.ReportInfo; +import org.apache.jackrabbit.webdav.xml.DomUtil; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.time.format.DateTimeParseException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Enumeration; +import java.util.List; +import java.util.Locale; + +/** + * AbstractWebdavServlet + *

+ */ +abstract public class AbstractWebdavServlet extends HttpServlet implements DavConstants { + + // todo respect Position header + /** + * default logger + */ + private static Logger log = LoggerFactory.getLogger(AbstractWebdavServlet.class); + + /** the 'missing-auth-mapping' init parameter */ + public final static String INIT_PARAM_MISSING_AUTH_MAPPING = "missing-auth-mapping"; + + /** + * Name of the optional init parameter that defines the value of the + * 'WWW-Authenticate' header. + *

+ * If the parameter is omitted the default value + * {@link #DEFAULT_AUTHENTICATE_HEADER "Basic Realm=Jackrabbit Webdav Server"} + * is used. + * + * @see #getAuthenticateHeaderValue() + */ + public static final String INIT_PARAM_AUTHENTICATE_HEADER = "authenticate-header"; + + /** + * Default value for the 'WWW-Authenticate' header, that is set, if request + * results in a {@link DavServletResponse#SC_UNAUTHORIZED 401 (Unauthorized)} + * error. + * + * @see #getAuthenticateHeaderValue() + */ + public static final String DEFAULT_AUTHENTICATE_HEADER = "Basic realm=\"Jackrabbit Webdav Server\""; + + /** + * Name of the parameter that specifies the configuration of the CSRF protection. + * May contain a comma-separated list of allowed referrer hosts. + * If the parameter is omitted or left empty the behaviour is to only allow requests which have an empty referrer + * or a referrer host equal to the server host. + * If the parameter is set to 'disabled' no referrer checks will be performed at all. + */ + public static final String INIT_PARAM_CSRF_PROTECTION = "csrf-protection"; + + /** + * Name of the 'createAbsoluteURI' init parameter that defines whether hrefs + * should be created with a absolute URI or as absolute Path (ContextPath). + * The value should be 'true' or 'false'. The default value if not set is true. + */ + public final static String INIT_PARAM_CREATE_ABSOLUTE_URI = "createAbsoluteURI"; + + + /** + * Header value as specified in the {@link #INIT_PARAM_AUTHENTICATE_HEADER} parameter. + */ + private String authenticate_header; + + /** + * CSRF protection utility + */ + private CSRFUtil csrfUtil; + + /** + * Create per default absolute URI hrefs + */ + private boolean createAbsoluteURI = true; + + @Override + public void init() throws ServletException { + super.init(); + + // authenticate header + authenticate_header = getInitParameter(INIT_PARAM_AUTHENTICATE_HEADER); + if (authenticate_header == null) { + authenticate_header = DEFAULT_AUTHENTICATE_HEADER; + } + log.info(INIT_PARAM_AUTHENTICATE_HEADER + " = " + authenticate_header); + + // read csrf protection params + String csrfParam = getInitParameter(INIT_PARAM_CSRF_PROTECTION); + csrfUtil = new CSRFUtil(csrfParam); + log.info(INIT_PARAM_CSRF_PROTECTION + " = " + csrfParam); + + //create absolute URI hrefs.. + String param = getInitParameter(INIT_PARAM_CREATE_ABSOLUTE_URI); + if (param != null) { + createAbsoluteURI = Boolean.parseBoolean(param); + } + log.info(INIT_PARAM_CREATE_ABSOLUTE_URI + " = " + createAbsoluteURI); + } + + /** + * Checks if the precondition for this request and resource is valid. + * + * @param request + * @param resource + * @return + */ + abstract protected boolean isPreconditionValid(WebdavRequest request, DavResource resource); + + /** + * Returns the DavSessionProvider. + * + * @return the session provider + */ + abstract public DavSessionProvider getDavSessionProvider(); + + /** + * Returns the DavSessionProvider. + * + * @param davSessionProvider + */ + abstract public void setDavSessionProvider(DavSessionProvider davSessionProvider); + + /** + * Returns the DavLocatorFactory. + * + * @return the locator factory + */ + abstract public DavLocatorFactory getLocatorFactory(); + + /** + * Sets the DavLocatorFactory. + * + * @param locatorFactory + */ + abstract public void setLocatorFactory(DavLocatorFactory locatorFactory); + + /** + * Returns the DavResourceFactory. + * + * @return the resource factory + */ + abstract public DavResourceFactory getResourceFactory(); + + /** + * Sets the DavResourceFactory. + * + * @param resourceFactory + */ + abstract public void setResourceFactory(DavResourceFactory resourceFactory); + + /** + * Returns the value of the 'WWW-Authenticate' header, that is returned in + * case of 401 error: the value is retrireved from the corresponding init + * param or defaults to {@link #DEFAULT_AUTHENTICATE_HEADER}. + * + * @return corresponding init parameter or {@link #DEFAULT_AUTHENTICATE_HEADER}. + * @see #INIT_PARAM_AUTHENTICATE_HEADER + */ + public String getAuthenticateHeaderValue() { + return authenticate_header; + } + + /** + * Returns if a absolute URI should be created for hrefs. + * + * @return absolute URI hrefs + */ + protected boolean isCreateAbsoluteURI() { + return createAbsoluteURI; + } + + /** + * Service the given request. + * + * @param request + * @param response + * @throws ServletException + * @throws IOException + */ + @Override + protected void service(HttpServletRequest request, HttpServletResponse response) + throws ServletException, IOException { + + WebdavRequest webdavRequest = new WebdavRequestImpl(request, getLocatorFactory(), isCreateAbsoluteURI()); + // DeltaV requires 'Cache-Control' header for all methods except 'VERSION-CONTROL' and 'REPORT'. + int methodCode = DavMethods.getMethodCode(request.getMethod()); + boolean noCache = DavMethods.isDeltaVMethod(webdavRequest) && !(DavMethods.DAV_VERSION_CONTROL == methodCode || DavMethods.DAV_REPORT == methodCode); + WebdavResponse webdavResponse = new WebdavResponseImpl(response, noCache); + + try { + WebdavRequestContextHolder.setContext(new WebdavRequestContextImpl(webdavRequest)); + + // make sure there is a authenticated user + if (!getDavSessionProvider().attachSession(webdavRequest)) { + return; + } + + // perform referrer host checks if CSRF protection is enabled + if (!csrfUtil.isValidRequest(webdavRequest)) { + webdavResponse.sendError(HttpServletResponse.SC_FORBIDDEN); + return; + } + + // JCR-4165: reject any content-coding in request until we can + // support it (see JCR-4166) + if (!(webdavRequest instanceof ContentCodingAwareRequest)) { + List ces = getContentCodings(request); + if (!ces.isEmpty()) { + webdavResponse.setStatus(HttpServletResponse.SC_UNSUPPORTED_MEDIA_TYPE); + webdavResponse.setHeader("Accept-Encoding", "identity"); + webdavResponse.setContentType("text/plain; charset=UTF-8"); + webdavResponse.getWriter().println("Content-Encodings not supported, but received: " + ces); + webdavResponse.getWriter().flush(); + } + } + + // check matching if=header for lock-token relevant operations + DavResource resource = getResourceFactory().createResource(webdavRequest.getRequestLocator(), webdavRequest, webdavResponse); + if (!isPreconditionValid(webdavRequest, resource)) { + webdavResponse.sendError(HttpServletResponse.SC_PRECONDITION_FAILED); + return; + } + if (!execute(webdavRequest, webdavResponse, methodCode, resource)) { + super.service(request, response); + } + } catch (DavException e) { + handleDavException(webdavRequest, webdavResponse, e); + } catch (IOException ex) { + Throwable cause = ex.getCause(); + if (cause instanceof DavException) { + handleDavException(webdavRequest, webdavResponse, (DavException) cause); + } else { + throw ex; + } + } finally { + WebdavRequestContextHolder.clearContext(); + getDavSessionProvider().releaseSession(webdavRequest); + } + } + + private void handleDavException(WebdavRequest webdavRequest, WebdavResponse webdavResponse, DavException ex) + throws IOException { + if (ex.getErrorCode() == HttpServletResponse.SC_UNAUTHORIZED) { + sendUnauthorized(webdavRequest, webdavResponse, ex); + } else { + Element condition = ex.getErrorCondition(); + if (DomUtil.matches(condition, ContentCodingAwareRequest.PRECONDITION_SUPPORTED)) { + if (webdavRequest instanceof ContentCodingAwareRequest) { + webdavResponse.setHeader("Accept-Encoding", ((ContentCodingAwareRequest) webdavRequest).getAcceptableCodings()); + } + } + webdavResponse.sendError(ex); + } + } + + /** + * If request payload was uncompressed, hint about acceptable content codings (RFC 7694) + */ + private void addHintAboutPotentialRequestEncodings(WebdavRequest webdavRequest, WebdavResponse webdavResponse) { + if (webdavRequest instanceof ContentCodingAwareRequest) { + ContentCodingAwareRequest ccr = (ContentCodingAwareRequest)webdavRequest; + List ces = ccr.getRequestContentCodings(); + if (ces.isEmpty()) { + webdavResponse.setHeader("Accept-Encoding", ccr.getAcceptableCodings()); + } + } + } + + /** + * Sets the "WWW-Authenticate" header and writes the appropriate error + * to the given webdav response. + * + * @param request The webdav request. + * @param response The webdav response. + * @param error The DavException that leads to the unauthorized response. + * @throws IOException + */ + protected void sendUnauthorized(WebdavRequest request, + WebdavResponse response, DavException error) throws IOException { + response.setHeader("WWW-Authenticate", getAuthenticateHeaderValue()); + if (error == null || error.getErrorCode() != HttpServletResponse.SC_UNAUTHORIZED) { + response.sendError(HttpServletResponse.SC_UNAUTHORIZED); + } else { + response.sendError(error.getErrorCode(), error.getStatusPhrase()); + } + } + + /** + * Executes the respective method in the given webdav context + * + * @param request + * @param response + * @param method + * @param resource + * @throws ServletException + * @throws IOException + * @throws DavException + */ + protected boolean execute(WebdavRequest request, WebdavResponse response, + int method, DavResource resource) + throws ServletException, IOException, DavException { + + switch (method) { + case DavMethods.DAV_GET: + doGet(request, response, resource); + break; + case DavMethods.DAV_HEAD: + doHead(request, response, resource); + break; + case DavMethods.DAV_PROPFIND: + doPropFind(request, response, resource); + break; + case DavMethods.DAV_PROPPATCH: + doPropPatch(request, response, resource); + break; + case DavMethods.DAV_POST: + doPost(request, response, resource); + break; + case DavMethods.DAV_PUT: + doPut(request, response, resource); + break; + case DavMethods.DAV_DELETE: + doDelete(request, response, resource); + break; + case DavMethods.DAV_COPY: + doCopy(request, response, resource); + break; + case DavMethods.DAV_MOVE: + doMove(request, response, resource); + break; + case DavMethods.DAV_MKCOL: + doMkCol(request, response, resource); + break; + case DavMethods.DAV_OPTIONS: + doOptions(request, response, resource); + break; + case DavMethods.DAV_LOCK: + doLock(request, response, resource); + break; + case DavMethods.DAV_UNLOCK: + doUnlock(request, response, resource); + break; + case DavMethods.DAV_ORDERPATCH: + doOrderPatch(request, response, resource); + break; + case DavMethods.DAV_SUBSCRIBE: + doSubscribe(request, response, resource); + break; + case DavMethods.DAV_UNSUBSCRIBE: + doUnsubscribe(request, response, resource); + break; + case DavMethods.DAV_POLL: + doPoll(request, response, resource); + break; + case DavMethods.DAV_SEARCH: + doSearch(request, response, resource); + break; + case DavMethods.DAV_VERSION_CONTROL: + doVersionControl(request, response, resource); + break; + case DavMethods.DAV_LABEL: + doLabel(request, response, resource); + break; + case DavMethods.DAV_REPORT: + doReport(request, response, resource); + break; + case DavMethods.DAV_CHECKIN: + doCheckin(request, response, resource); + break; + case DavMethods.DAV_CHECKOUT: + doCheckout(request, response, resource); + break; + case DavMethods.DAV_UNCHECKOUT: + doUncheckout(request, response, resource); + break; + case DavMethods.DAV_MERGE: + doMerge(request, response, resource); + break; + case DavMethods.DAV_UPDATE: + doUpdate(request, response, resource); + break; + case DavMethods.DAV_MKWORKSPACE: + doMkWorkspace(request, response, resource); + break; + case DavMethods.DAV_MKACTIVITY: + doMkActivity(request, response, resource); + break; + case DavMethods.DAV_BASELINE_CONTROL: + doBaselineControl(request, response, resource); + break; + case DavMethods.DAV_ACL: + doAcl(request, response, resource); + break; + case DavMethods.DAV_REBIND: + doRebind(request, response, resource); + break; + case DavMethods.DAV_UNBIND: + doUnbind(request, response, resource); + break; + case DavMethods.DAV_BIND: + doBind(request, response, resource); + break; + default: + // any other method + return false; + } + return true; + } + + /** + * The OPTION method + * + * @param request + * @param response + * @param resource + */ + protected void doOptions(WebdavRequest request, WebdavResponse response, + DavResource resource) throws IOException, DavException { + response.addHeader(DavConstants.HEADER_DAV, resource.getComplianceClass()); + response.addHeader("Allow", resource.getSupportedMethods()); + response.addHeader("MS-Author-Via", DavConstants.HEADER_DAV); + if (resource instanceof SearchResource) { + String[] langs = ((SearchResource) resource).getQueryGrammerSet().getQueryLanguages(); + for (String lang : langs) { + response.addHeader(SearchConstants.HEADER_DASL, "<" + lang + ">"); + } + } + // with DeltaV the OPTIONS request may contain a Xml body. + OptionsResponse oR = null; + OptionsInfo oInfo = request.getOptionsInfo(); + if (oInfo != null && resource instanceof DeltaVResource) { + oR = ((DeltaVResource) resource).getOptionResponse(oInfo); + } + if (oR == null) { + response.setStatus(DavServletResponse.SC_OK); + } else { + response.sendXmlResponse(oR, DavServletResponse.SC_OK); + } + } + + /** + * The HEAD method + * + * @param request + * @param response + * @param resource + * @throws IOException + */ + protected void doHead(WebdavRequest request, WebdavResponse response, + DavResource resource) throws IOException { + spoolResource(request, response, resource, false); + } + + /** + * The GET method + * + * @param request + * @param response + * @param resource + * @throws IOException + */ + protected void doGet(WebdavRequest request, WebdavResponse response, + DavResource resource) throws IOException, DavException { + spoolResource(request, response, resource, true); + } + + /** + * @param request + * @param response + * @param resource + * @param sendContent + * @throws IOException + */ + private void spoolResource(WebdavRequest request, WebdavResponse response, + DavResource resource, boolean sendContent) + throws IOException { + + if (!resource.exists()) { + response.sendError(HttpServletResponse.SC_NOT_FOUND); + return; + } + + long modSince = UNDEFINED_TIME; + try { + // will throw if multiple field lines present + String value = getSingletonField(request, "If-Modified-Since"); + if (value != null) { + modSince = HttpDateTimeFormatter.parse(value); + } + } catch (IllegalArgumentException | DateTimeParseException ex) { + log.debug("illegal value for if-modified-since ignored: " + ex.getMessage()); + } + + if (modSince > UNDEFINED_TIME) { + long modTime = resource.getModificationTime(); + // test if resource has been modified. note that formatted modification + // time lost the milli-second precision + if (modTime != UNDEFINED_TIME && (modTime / 1000 * 1000) <= modSince) { + // resource has not been modified since the time indicated in the + // 'If-Modified-Since' header. + + DavProperty etagProp = resource.getProperty(DavPropertyName.GETETAG); + if (etagProp != null) { + // 304 response MUST contain Etag when available + response.setHeader("etag", etagProp.getValue().toString()); + } + response.setStatus(HttpServletResponse.SC_NOT_MODIFIED); + return; + } + } + + // spool resource properties and eventually resource content. + OutputStream out = (sendContent) ? response.getOutputStream() : null; + resource.spool(getOutputContext(response, out)); + response.flushBuffer(); + } + + /** + * The PROPFIND method + * + * @param request + * @param response + * @param resource + * @throws IOException + */ + protected void doPropFind(WebdavRequest request, WebdavResponse response, + DavResource resource) throws IOException, DavException { + + if (!resource.exists()) { + response.sendError(DavServletResponse.SC_NOT_FOUND); + return; + } + + int depth = request.getDepth(DEPTH_INFINITY); + DavPropertyNameSet requestProperties = request.getPropFindProperties(); + int propfindType = request.getPropFindType(); + + MultiStatus mstatus = new MultiStatus(); + mstatus.addResourceProperties(resource, requestProperties, propfindType, depth); + + addHintAboutPotentialRequestEncodings(request, response); + + response.sendMultiStatus(mstatus, + acceptsGzipEncoding(request) ? Collections.singletonList("gzip") : Collections.emptyList()); + } + + /** + * The PROPPATCH method + * + * @param request + * @param response + * @param resource + * @throws IOException + */ + protected void doPropPatch(WebdavRequest request, WebdavResponse response, + DavResource resource) + throws IOException, DavException { + + List changeList = request.getPropPatchChangeList(); + if (changeList.isEmpty()) { + response.sendError(DavServletResponse.SC_BAD_REQUEST); + return; + } + + MultiStatus ms = new MultiStatus(); + MultiStatusResponse msr = resource.alterProperties(changeList); + ms.addResponse(msr); + + addHintAboutPotentialRequestEncodings(request, response); + + response.sendMultiStatus(ms); + } + + /** + * The POST method. Delegate to PUT + * + * @param request + * @param response + * @param resource + * @throws IOException + * @throws DavException + */ + protected void doPost(WebdavRequest request, WebdavResponse response, + DavResource resource) throws IOException, DavException { + response.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED); + } + + /** + * The PUT method + * + * @param request + * @param response + * @param resource + * @throws IOException + * @throws DavException + */ + protected void doPut(WebdavRequest request, WebdavResponse response, + DavResource resource) throws IOException, DavException { + + if (request.getHeader("Content-Range") != null) { + response.sendError(DavServletResponse.SC_BAD_REQUEST, "Content-Range in PUT request not supported"); + return; + } + + DavResource parentResource = resource.getCollection(); + if (parentResource == null || !parentResource.exists()) { + // parent does not exist + response.sendError(DavServletResponse.SC_CONFLICT); + return; + } + + int status; + // test if resource already exists + if (resource.exists()) { + status = DavServletResponse.SC_NO_CONTENT; + } else { + status = DavServletResponse.SC_CREATED; + } + + parentResource.addMember(resource, getInputContext(request, request.getInputStream())); + response.setStatus(status); + } + + /** + * The MKCOL method + * + * @param request + * @param response + * @param resource + * @throws IOException + * @throws DavException + */ + protected void doMkCol(WebdavRequest request, WebdavResponse response, + DavResource resource) throws IOException, DavException { + + DavResource parentResource = resource.getCollection(); + if (parentResource == null || !parentResource.exists() || !parentResource.isCollection()) { + // parent does not exist or is not a collection + response.sendError(DavServletResponse.SC_CONFLICT); + return; + } + // shortcut: mkcol is only allowed on deleted/non-existing resources + if (resource.exists()) { + response.sendError(DavServletResponse.SC_METHOD_NOT_ALLOWED); + return; + } + + if (request.getContentLength() > 0 || request.getHeader("Transfer-Encoding") != null) { + parentResource.addMember(resource, getInputContext(request, request.getInputStream())); + } else { + parentResource.addMember(resource, getInputContext(request, null)); + } + response.setStatus(DavServletResponse.SC_CREATED); + } + + /** + * The DELETE method + * + * @param request + * @param response + * @param resource + * @throws IOException + * @throws DavException + */ + protected void doDelete(WebdavRequest request, WebdavResponse response, + DavResource resource) throws IOException, DavException { + DavResource parent = resource.getCollection(); + if (parent != null) { + parent.removeMember(resource); + response.setStatus(DavServletResponse.SC_NO_CONTENT); + } else { + response.sendError(DavServletResponse.SC_FORBIDDEN, "Cannot remove the root resource."); + } + } + + /** + * The COPY method + * + * @param request + * @param response + * @param resource + * @throws IOException + * @throws DavException + */ + protected void doCopy(WebdavRequest request, WebdavResponse response, + DavResource resource) throws IOException, DavException { + + // only depth 0 and infinity is allowed + int depth = request.getDepth(DEPTH_INFINITY); + if (!(depth == DEPTH_0 || depth == DEPTH_INFINITY)) { + response.sendError(DavServletResponse.SC_BAD_REQUEST); + return; + } + + DavResource destResource = getResourceFactory().createResource(request.getDestinationLocator(), request, response); + int status = validateDestination(destResource, request, true); + if (status > DavServletResponse.SC_NO_CONTENT) { + response.sendError(status); + return; + } + + resource.copy(destResource, depth == DEPTH_0); + response.setStatus(status); + } + + /** + * The MOVE method + * + * @param request + * @param response + * @param resource + * @throws IOException + * @throws DavException + */ + protected void doMove(WebdavRequest request, WebdavResponse response, + DavResource resource) throws IOException, DavException { + + DavResource destResource = getResourceFactory().createResource(request.getDestinationLocator(), request, response); + int status = validateDestination(destResource, request, true); + if (status > DavServletResponse.SC_NO_CONTENT) { + response.sendError(status); + return; + } + + resource.move(destResource); + response.setStatus(status); + } + + /** + * The BIND method + * + * @param request + * @param response + * @param resource the collection resource to which a new member will be added + * @throws IOException + * @throws DavException + */ + protected void doBind(WebdavRequest request, WebdavResponse response, + DavResource resource) throws IOException, DavException { + + if (!resource.exists()) { + response.sendError(DavServletResponse.SC_NOT_FOUND); + } + BindInfo bindInfo = request.getBindInfo(); + DavResource oldBinding = getResourceFactory().createResource(request.getHrefLocator(bindInfo.getHref()), request, response); + if (!(oldBinding instanceof BindableResource)) { + response.sendError(DavServletResponse.SC_METHOD_NOT_ALLOWED); + return; + } + DavResource newBinding = getResourceFactory().createResource(request.getMemberLocator(bindInfo.getSegment()), request, response); + int status = validateDestination(newBinding, request, false); + if (status > DavServletResponse.SC_NO_CONTENT) { + response.sendError(status); + return; + } + ((BindableResource) oldBinding).bind(resource, newBinding); + response.setStatus(status); + } + + /** + * The REBIND method + * + * @param request + * @param response + * @param resource the collection resource to which a new member will be added + * @throws IOException + * @throws DavException + */ + protected void doRebind(WebdavRequest request, WebdavResponse response, + DavResource resource) throws IOException, DavException { + + if (!resource.exists()) { + response.sendError(DavServletResponse.SC_NOT_FOUND); + } + RebindInfo rebindInfo = request.getRebindInfo(); + DavResource oldBinding = getResourceFactory().createResource(request.getHrefLocator(rebindInfo.getHref()), request, response); + if (!(oldBinding instanceof BindableResource)) { + response.sendError(DavServletResponse.SC_METHOD_NOT_ALLOWED); + return; + } + DavResource newBinding = getResourceFactory().createResource(request.getMemberLocator(rebindInfo.getSegment()), request, response); + int status = validateDestination(newBinding, request, false); + if (status > DavServletResponse.SC_NO_CONTENT) { + response.sendError(status); + return; + } + ((BindableResource) oldBinding).rebind(resource, newBinding); + response.setStatus(status); + } + + /** + * The UNBIND method + * + * @param request + * @param response + * @param resource the collection resource from which a member will be removed + * @throws IOException + * @throws DavException + */ + protected void doUnbind(WebdavRequest request, WebdavResponse response, + DavResource resource) throws IOException, DavException { + + UnbindInfo unbindInfo = request.getUnbindInfo(); + DavResource srcResource = getResourceFactory().createResource(request.getMemberLocator(unbindInfo.getSegment()), request, response); + resource.removeMember(srcResource); + } + + /** + * Validate the given destination resource and return the proper status + * code: Any return value greater/equal than {@link DavServletResponse#SC_NO_CONTENT} + * indicates an error. + * + * @param destResource destination resource to be validated. + * @param request + * @param checkHeader flag indicating if the destination header must be present. + * @return status code indicating whether the destination is valid. + */ + protected int validateDestination(DavResource destResource, WebdavRequest request, boolean checkHeader) + throws DavException { + + if (checkHeader) { + String destHeader = request.getHeader(HEADER_DESTINATION); + if (destHeader == null || "".equals(destHeader)) { + return DavServletResponse.SC_BAD_REQUEST; + } + } + if (destResource.getLocator().equals(request.getRequestLocator())) { + return DavServletResponse.SC_FORBIDDEN; + } + + int status; + if (destResource.exists()) { + if (request.isOverwrite()) { + // matching if-header required for existing resources + if (!request.matchesIfHeader(destResource)) { + return DavServletResponse.SC_PRECONDITION_FAILED; + } else { + // overwrite existing resource + DavResource col; + try { + col = destResource.getCollection(); + } + catch (IllegalArgumentException ex) { + return DavServletResponse.SC_BAD_GATEWAY; + } + col.removeMember(destResource); + status = DavServletResponse.SC_NO_CONTENT; + } + } else { + // cannot copy/move to an existing item, if overwrite is not forced + return DavServletResponse.SC_PRECONDITION_FAILED; + } + } else { + // destination does not exist >> copy/move can be performed + status = DavServletResponse.SC_CREATED; + } + return status; + } + + /** + * The LOCK method + * + * @param request + * @param response + * @param resource + * @throws IOException + * @throws DavException + */ + protected void doLock(WebdavRequest request, WebdavResponse response, + DavResource resource) throws IOException, DavException { + + LockInfo lockInfo = request.getLockInfo(); + if (lockInfo.isRefreshLock()) { + // refresh any matching existing locks + ActiveLock[] activeLocks = resource.getLocks(); + List lList = new ArrayList(); + for (ActiveLock activeLock : activeLocks) { + // adjust lockinfo with type/scope retrieved from the lock. + lockInfo.setType(activeLock.getType()); + lockInfo.setScope(activeLock.getScope()); + + DavProperty etagProp = resource.getProperty(DavPropertyName.GETETAG); + String etag = etagProp != null ? String.valueOf(etagProp.getValue()) : ""; + if (request.matchesIfHeader(resource.getHref(), activeLock.getToken(), etag)) { + lList.add(resource.refreshLock(lockInfo, activeLock.getToken())); + } + } + if (lList.isEmpty()) { + throw new DavException(DavServletResponse.SC_PRECONDITION_FAILED); + } + ActiveLock[] refreshedLocks = lList.toArray(new ActiveLock[lList.size()]); + response.sendRefreshLockResponse(refreshedLocks); + } else { + int status = HttpServletResponse.SC_OK; + if (!resource.exists()) { + // lock-empty requires status code 201 (Created) + status = HttpServletResponse.SC_CREATED; + } + + // create a new lock + ActiveLock lock = resource.lock(lockInfo); + + CodedUrlHeader header = new CodedUrlHeader( + DavConstants.HEADER_LOCK_TOKEN, lock.getToken()); + response.setHeader(header.getHeaderName(), header.getHeaderValue()); + + DavPropertySet propSet = new DavPropertySet(); + propSet.add(new LockDiscovery(lock)); + response.sendXmlResponse(propSet, status); + } + } + + /** + * The UNLOCK method + * + * @param request + * @param response + * @param resource + * @throws DavException + */ + protected void doUnlock(WebdavRequest request, WebdavResponse response, + DavResource resource) throws DavException { + // get lock token from header + String lockToken = request.getLockToken(); + TransactionInfo tInfo = request.getTransactionInfo(); + if (tInfo != null) { + ((TransactionResource) resource).unlock(lockToken, tInfo); + } else { + resource.unlock(lockToken); + } + response.setStatus(DavServletResponse.SC_NO_CONTENT); + } + + /** + * The ORDERPATCH method + * + * @param request + * @param response + * @param resource + * @throws IOException + * @throws DavException + */ + protected void doOrderPatch(WebdavRequest request, + WebdavResponse response, + DavResource resource) + throws IOException, DavException { + + if (!(resource instanceof OrderingResource)) { + response.sendError(DavServletResponse.SC_METHOD_NOT_ALLOWED); + return; + } + + OrderPatch op = request.getOrderPatch(); + if (op == null) { + response.sendError(DavServletResponse.SC_BAD_REQUEST); + return; + } + // perform reordering of internal members + ((OrderingResource) resource).orderMembers(op); + response.setStatus(DavServletResponse.SC_OK); + } + + /** + * The SUBSCRIBE method + * + * @param request + * @param response + * @param resource + * @throws IOException + * @throws DavException + */ + protected void doSubscribe(WebdavRequest request, + WebdavResponse response, + DavResource resource) + throws IOException, DavException { + + if (!(resource instanceof ObservationResource)) { + response.sendError(DavServletResponse.SC_METHOD_NOT_ALLOWED); + return; + } + + SubscriptionInfo info = request.getSubscriptionInfo(); + if (info == null) { + response.sendError(DavServletResponse.SC_UNSUPPORTED_MEDIA_TYPE); + return; + } + Subscription subs = ((ObservationResource) resource).subscribe(info, request.getSubscriptionId()); + response.sendSubscriptionResponse(subs); + } + + /** + * The UNSUBSCRIBE method + * + * @param request + * @param response + * @param resource + * @throws IOException + * @throws DavException + */ + protected void doUnsubscribe(WebdavRequest request, + WebdavResponse response, + DavResource resource) + throws IOException, DavException { + + if (!(resource instanceof ObservationResource)) { + response.sendError(DavServletResponse.SC_METHOD_NOT_ALLOWED); + return; + } + ((ObservationResource) resource).unsubscribe(request.getSubscriptionId()); + response.setStatus(DavServletResponse.SC_NO_CONTENT); + } + + /** + * The POLL method + * + * @param request + * @param response + * @param resource + * @throws IOException + * @throws DavException + */ + protected void doPoll(WebdavRequest request, + WebdavResponse response, + DavResource resource) + throws IOException, DavException { + + if (!(resource instanceof ObservationResource)) { + response.sendError(DavServletResponse.SC_METHOD_NOT_ALLOWED); + return; + } + EventDiscovery ed = ((ObservationResource) resource).poll( + request.getSubscriptionId(), request.getPollTimeout()); + response.sendPollResponse(ed); + } + + /** + * The VERSION-CONTROL method + * + * @param request + * @param response + * @param resource + * @throws DavException + * @throws IOException + */ + protected void doVersionControl(WebdavRequest request, WebdavResponse response, + DavResource resource) + throws DavException, IOException { + if (!(resource instanceof VersionableResource)) { + response.sendError(DavServletResponse.SC_METHOD_NOT_ALLOWED); + return; + } + ((VersionableResource) resource).addVersionControl(); + } + + /** + * The LABEL method + * + * @param request + * @param response + * @param resource + * @throws DavException + * @throws IOException + */ + protected void doLabel(WebdavRequest request, WebdavResponse response, + DavResource resource) + throws DavException, IOException { + + LabelInfo labelInfo = request.getLabelInfo(); + if (resource instanceof VersionResource) { + ((VersionResource) resource).label(labelInfo); + } else if (resource instanceof VersionControlledResource) { + ((VersionControlledResource) resource).label(labelInfo); + } else { + // any other resource type that does not support a LABEL request + response.sendError(DavServletResponse.SC_METHOD_NOT_ALLOWED); + } + } + + /** + * The REPORT method + * + * @param request + * @param response + * @param resource + * @throws DavException + * @throws IOException + */ + protected void doReport(WebdavRequest request, WebdavResponse response, + DavResource resource) + throws DavException, IOException { + ReportInfo info = request.getReportInfo(); + Report report; + if (resource instanceof DeltaVResource) { + report = ((DeltaVResource) resource).getReport(info); + } else if (resource instanceof AclResource) { + report = ((AclResource) resource).getReport(info); + } else { + response.sendError(DavServletResponse.SC_METHOD_NOT_ALLOWED); + return; + } + + int statusCode = (report.isMultiStatusReport()) ? DavServletResponse.SC_MULTI_STATUS : DavServletResponse.SC_OK; + addHintAboutPotentialRequestEncodings(request, response); + response.sendXmlResponse(report, statusCode, acceptsGzipEncoding(request) ? Collections.singletonList("gzip") : Collections.emptyList()); + } + + /** + * The CHECKIN method + * + * @param request + * @param response + * @param resource + * @throws DavException + * @throws IOException + */ + protected void doCheckin(WebdavRequest request, WebdavResponse response, + DavResource resource) + throws DavException, IOException { + + if (!(resource instanceof VersionControlledResource)) { + response.sendError(DavServletResponse.SC_METHOD_NOT_ALLOWED); + return; + } + String versionHref = ((VersionControlledResource) resource).checkin(); + response.setHeader(DeltaVConstants.HEADER_LOCATION, versionHref); + response.setStatus(DavServletResponse.SC_CREATED); + } + + /** + * The CHECKOUT method + * + * @param request + * @param response + * @param resource + * @throws DavException + * @throws IOException + */ + protected void doCheckout(WebdavRequest request, WebdavResponse response, + DavResource resource) + throws DavException, IOException { + if (!(resource instanceof VersionControlledResource)) { + response.sendError(DavServletResponse.SC_METHOD_NOT_ALLOWED); + return; + } + ((VersionControlledResource) resource).checkout(); + } + + /** + * The UNCHECKOUT method + * + * @param request + * @param response + * @param resource + * @throws DavException + * @throws IOException + */ + protected void doUncheckout(WebdavRequest request, WebdavResponse response, + DavResource resource) + throws DavException, IOException { + if (!(resource instanceof VersionControlledResource)) { + response.sendError(DavServletResponse.SC_METHOD_NOT_ALLOWED); + return; + } + ((VersionControlledResource) resource).uncheckout(); + } + + /** + * The MERGE method + * + * @param request + * @param response + * @param resource + * @throws DavException + * @throws IOException + */ + protected void doMerge(WebdavRequest request, WebdavResponse response, + DavResource resource) throws DavException, IOException { + + if (!(resource instanceof VersionControlledResource)) { + response.sendError(DavServletResponse.SC_METHOD_NOT_ALLOWED); + return; + } + MergeInfo info = request.getMergeInfo(); + MultiStatus ms = ((VersionControlledResource) resource).merge(info); + response.sendMultiStatus(ms); + } + + /** + * The UPDATE method + * + * @param request + * @param response + * @param resource + * @throws DavException + * @throws IOException + */ + protected void doUpdate(WebdavRequest request, WebdavResponse response, + DavResource resource) throws DavException, IOException { + + if (!(resource instanceof VersionControlledResource)) { + response.sendError(DavServletResponse.SC_METHOD_NOT_ALLOWED); + return; + } + UpdateInfo info = request.getUpdateInfo(); + MultiStatus ms = ((VersionControlledResource) resource).update(info); + response.sendMultiStatus(ms); + } + + /** + * The MKWORKSPACE method + * + * @param request + * @param response + * @param resource + * @throws DavException + * @throws IOException + */ + protected void doMkWorkspace(WebdavRequest request, WebdavResponse response, + DavResource resource) throws DavException, IOException { + if (resource.exists()) { + AbstractWebdavServlet.log.warn("Cannot create a new workspace. Resource already exists."); + response.sendError(DavServletResponse.SC_FORBIDDEN); + return; + } + + DavResource parentResource = resource.getCollection(); + if (parentResource == null || !parentResource.exists() || !parentResource.isCollection()) { + // parent does not exist or is not a collection + response.sendError(DavServletResponse.SC_CONFLICT); + return; + } + if (!(parentResource instanceof DeltaVResource)) { + response.sendError(DavServletResponse.SC_METHOD_NOT_ALLOWED); + return; + } + ((DeltaVResource) parentResource).addWorkspace(resource); + response.setStatus(DavServletResponse.SC_CREATED); + } + + /** + * The MKACTIVITY method + * + * @param request + * @param response + * @param resource + * @throws DavException + * @throws IOException + */ + protected void doMkActivity(WebdavRequest request, WebdavResponse response, + DavResource resource) throws DavException, IOException { + if (resource.exists()) { + AbstractWebdavServlet.log.warn("Unable to create activity: A resource already exists at the request-URL " + request.getRequestURL()); + response.sendError(DavServletResponse.SC_FORBIDDEN); + return; + } + + DavResource parentResource = resource.getCollection(); + if (parentResource == null || !parentResource.exists() || !parentResource.isCollection()) { + // parent does not exist or is not a collection + response.sendError(DavServletResponse.SC_CONFLICT); + return; + } + // TODO: improve. see http://issues.apache.org/jira/browse/JCR-394 + if (!parentResource.getComplianceClass().contains(DavCompliance.ACTIVITY)) { + response.sendError(DavServletResponse.SC_METHOD_NOT_ALLOWED); + return; + } + + if (!(resource instanceof ActivityResource)) { + AbstractWebdavServlet.log.error("Unable to create activity: ActivityResource expected"); + response.sendError(DavServletResponse.SC_INTERNAL_SERVER_ERROR); + return; + } + + // try to add the new activity resource + parentResource.addMember(resource, getInputContext(request, request.getInputStream())); + + // Note: mandatory cache control header has already been set upon response creation. + response.setStatus(DavServletResponse.SC_CREATED); + } + + /** + * The BASELINECONTROL method + * + * @param request + * @param response + * @param resource + * @throws DavException + * @throws IOException + */ + protected void doBaselineControl(WebdavRequest request, WebdavResponse response, + DavResource resource) + throws DavException, IOException { + + if (!resource.exists()) { + AbstractWebdavServlet.log.warn("Unable to add baseline control. Resource does not exist " + resource.getHref()); + response.sendError(DavServletResponse.SC_NOT_FOUND); + return; + } + // TODO: improve. see http://issues.apache.org/jira/browse/JCR-394 + if (!(resource instanceof VersionControlledResource) || !resource.isCollection()) { + AbstractWebdavServlet.log.warn("BaselineControl is not supported by resource " + resource.getHref()); + response.sendError(DavServletResponse.SC_METHOD_NOT_ALLOWED); + return; + } + + // TODO : missing method on VersionControlledResource + throw new DavException(DavServletResponse.SC_NOT_IMPLEMENTED); + /* + ((VersionControlledResource) resource).addBaselineControl(request.getRequestDocument()); + // Note: mandatory cache control header has already been set upon response creation. + response.setStatus(DavServletResponse.SC_OK); + */ + } + + /** + * The SEARCH method + * + * @param request + * @param response + * @param resource + * @throws DavException + * @throws IOException + */ + protected void doSearch(WebdavRequest request, WebdavResponse response, + DavResource resource) throws DavException, IOException { + + if (!(resource instanceof SearchResource)) { + response.sendError(DavServletResponse.SC_METHOD_NOT_ALLOWED); + return; + } + Document doc = request.getRequestDocument(); + if (doc != null) { + SearchInfo sR = SearchInfo.createFromXml(doc.getDocumentElement()); + response.sendMultiStatus(((SearchResource) resource).search(sR)); + } else { + // request without request body is valid if requested resource + // is a 'query' resource. + response.sendMultiStatus(((SearchResource) resource).search(null)); + } + } + + /** + * The ACL method + * + * @param request + * @param response + * @param resource + * @throws DavException + * @throws IOException + */ + protected void doAcl(WebdavRequest request, WebdavResponse response, + DavResource resource) throws DavException, IOException { + if (!(resource instanceof AclResource)) { + response.sendError(DavServletResponse.SC_METHOD_NOT_ALLOWED); + return; + } + Document doc = request.getRequestDocument(); + if (doc == null) { + throw new DavException(DavServletResponse.SC_BAD_REQUEST, "ACL request requires a DAV:acl body."); + } + AclProperty acl = AclProperty.createFromXml(doc.getDocumentElement()); + ((AclResource)resource).alterAcl(acl); + } + + /** + * Return a new InputContext used for adding resource members + * + * @param request + * @param in + * @return + * @see #spoolResource(WebdavRequest, WebdavResponse, DavResource, boolean) + */ + protected InputContext getInputContext(DavServletRequest request, InputStream in) { + return new InputContextImpl(request, in); + } + + /** + * Return a new OutputContext used for spooling resource properties and + * the resource content + * + * @param response + * @param out + * @return + * @see #doPut(WebdavRequest, WebdavResponse, DavResource) + * @see #doMkCol(WebdavRequest, WebdavResponse, DavResource) + */ + protected OutputContext getOutputContext(DavServletResponse response, OutputStream out) { + return new OutputContextImpl(response, out); + } + + /** + * Obtain the (ordered!) list of content codings that have been used in the + * request + */ + public static List getContentCodings(HttpServletRequest request) { + return getListElementsFromHeaderField(request, "Content-Encoding"); + } + + /** + * Check whether recipient accepts GZIP content coding + */ + private static boolean acceptsGzipEncoding(HttpServletRequest request) { + List result = getListElementsFromHeaderField(request, "Accept-Encoding"); + for (String s : result) { + s = s.replace(" ", ""); + int semi = s.indexOf(';'); + if ("gzip".equals(s)) { + return true; + } else if (semi > 0) { + String enc = s.substring(0, semi); + String parm = s.substring(semi + 1); + if ("gzip".equals(enc) && parm.startsWith("q=")) { + float q = Float.valueOf(parm.substring(2)); + return q > 0; + } + } + } + return false; + } + + private static List getListElementsFromHeaderField(HttpServletRequest request, String fieldName) { + List result = Collections.emptyList(); + for (Enumeration ceh = request.getHeaders(fieldName); ceh.hasMoreElements();) { + for (String h : ceh.nextElement().split(",")) { + if (!h.trim().isEmpty()) { + if (result.isEmpty()) { + result = new ArrayList(); + } + result.add(h.trim().toLowerCase(Locale.ENGLISH)); + } + } + } + + return result; + } + + /** + * Get field value of a singleton field + * @param request HTTP request + * @param fieldName field name + * @return the field value (when there is indeed a single field line) or {@code null} when field not present + * @throws IllegalArgumentException when multiple field lines present + */ + protected static String getSingletonField(HttpServletRequest request, String fieldName) { + Enumeration lines = request.getHeaders(fieldName); + if (!lines.hasMoreElements()) { + return null; + } else { + String value = lines.nextElement(); + if (!lines.hasMoreElements()) { + return value; + } else { + List v = new ArrayList<>(); + v.add(value); + while (lines.hasMoreElements()) { + v.add(lines.nextElement()); + } + throw new IllegalArgumentException("Multiple field lines for '" + fieldName + "' header field: " + v); + } + } + } +} + Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/server/AbstractWebdavServlet.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-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/server/WebdavRequestContextHolder.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/server/WebdavRequestContextHolder.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/server/WebdavRequestContextHolder.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.webdav.server; + +import org.apache.jackrabbit.webdav.WebdavRequestContext; + +/** + * Associates a {@link WebdavRequestContext} with the current execution thread. + */ +public final class WebdavRequestContextHolder { + + private static ThreadLocal tlWebdavRequestContext = new ThreadLocal<>(); + + private WebdavRequestContextHolder() { + } + + /** + * Return the {@link WebdavRequestContext} with the current execution thread. + * @return the {@link WebdavRequestContext} with the current execution thread + */ + public static WebdavRequestContext getContext() { + return tlWebdavRequestContext.get(); + } + + static void setContext(WebdavRequestContext context) { + tlWebdavRequestContext.set(context); + } + + static void clearContext() { + tlWebdavRequestContext.remove(); + } +} Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/server/WebdavRequestContextHolder.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/server/WebdavRequestContextImpl.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/server/WebdavRequestContextImpl.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/server/WebdavRequestContextImpl.java (working copy) @@ -0,0 +1,35 @@ +/* + * 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.webdav.server; + +import org.apache.jackrabbit.webdav.WebdavRequest; +import org.apache.jackrabbit.webdav.WebdavRequestContext; + +class WebdavRequestContextImpl implements WebdavRequestContext { + + private final WebdavRequest request; + + WebdavRequestContextImpl(final WebdavRequest request) { + this.request = request; + } + + @Override + public WebdavRequest getRequest() { + return request; + } + +} Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/server/WebdavRequestContextImpl.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/server/package-info.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/server/package-info.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/server/package-info.java (working copy) @@ -0,0 +1,18 @@ +/* + * 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. + */ +@org.osgi.annotation.versioning.Version("1.2.0") +package org.apache.jackrabbit.webdav.server; Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/server/package-info.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/transaction/TransactionConstants.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/transaction/TransactionConstants.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/transaction/TransactionConstants.java (working copy) @@ -0,0 +1,125 @@ +/* + * 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.webdav.transaction; + +import org.apache.jackrabbit.webdav.DavConstants; +import org.apache.jackrabbit.webdav.lock.Scope; +import org.apache.jackrabbit.webdav.lock.Type; +import org.apache.jackrabbit.webdav.xml.Namespace; + +/** + * TransactionConstants interface provide constants for request + * and response headers, Xml elements and property names used for handling + * transactions over WebDAV. There exists no public standard for this functionality. + * + * todo: 'local' and 'global' are not accurate terms in the given context > replace + */ +public interface TransactionConstants { + + /** + * Namespace for transaction related xml elements + */ + public static final Namespace NAMESPACE = Namespace.getNamespace("dcr", "http://www.day.com/jcr/webdav/1.0"); + + //---< Headers >------------------------------------------------------------ + /** + * TransactionId Header + */ + public static final String HEADER_TRANSACTIONID = "TransactionId"; + + //---< XML Element, Attribute Names >--------------------------------------- + /** + * transaction XML element
+ * Used as element inside the {@link DavConstants#XML_LOCKTYPE locktype} + * element. + * @see DavConstants#XML_LOCKTYPE + */ + public static final String XML_TRANSACTION = "transaction"; + + /** + * global XML element
+ * Used as element inside of the {@link DavConstants#XML_LOCKSCOPE lockscope} element. + * + * @see DavConstants#XML_LOCKSCOPE + */ + public static final String XML_GLOBAL = "global"; + + /** + * local XML element
+ * Used as element inside of the {@link DavConstants#XML_LOCKSCOPE lockscope} element. + * It indicates the transaction to be local (e.g. transient changes to + * a repository). + * + * @see DavConstants#XML_LOCKSCOPE + */ + public static final String XML_LOCAL = "local"; + + /** + * transactioninfo XML element
+ * Mandatory element of the UNLOCK request body, if the unlock request + * is intended to complete a transaction. + */ + public static final String XML_TRANSACTIONINFO = "transactioninfo"; + + /** + * transactionstatus XML element
+ * Mandatory element inside the {@link #XML_TRANSACTIONINFO transactioninfo} + * element indicating how the transaction should be completed. + * @see #XML_TRANSACTIONINFO + */ + public static final String XML_TRANSACTIONSTATUS = "transactionstatus"; + + /** + * commit XML element
+ * Used as element inside of the {@link #XML_TRANSACTIONSTATUS transactionstatus} + * element. It indicates a completion by committing the transaction. + * @see #XML_TRANSACTIONSTATUS + */ + public static final String XML_COMMIT = "commit"; + + /** + * rollback XML element
+ * Used as element inside of the {@link #XML_TRANSACTIONSTATUS transactionstatus} + * element. It indicates a completion by roll backing the transaction. + * @see #XML_TRANSACTIONSTATUS + */ + public static final String XML_ROLLBACK = "rollback"; + + //---< Lock Type, Lock Scope >---------------------------------------------- + /** + * "transaction" lock type constant. + * @see #XML_TRANSACTION + * @see Type#create(String, Namespace) + */ + public static final Type TRANSACTION = Type.create(XML_TRANSACTION, TransactionConstants.NAMESPACE); + + /** + * "local" lock scope constant. + * + * @see #XML_LOCAL + * @see Scope#create(String, Namespace) + */ + public static final Scope LOCAL = Scope.create(XML_LOCAL, TransactionConstants.NAMESPACE); + + /** + * "global" lock scope constant. + * + * @see #XML_GLOBAL + * @see Scope#create(String, Namespace) + */ + public static final Scope GLOBAL = Scope.create(XML_GLOBAL, TransactionConstants.NAMESPACE); +} \ No newline at end of file Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/transaction/TransactionConstants.java ___________________________________________________________________ Added: svn Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/transaction/TransactionDavServletRequest.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/transaction/TransactionDavServletRequest.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/transaction/TransactionDavServletRequest.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.webdav.transaction; + +import org.apache.jackrabbit.webdav.DavException; +import org.apache.jackrabbit.webdav.DavServletRequest; + +/** + * TransactionDavServletRequest provides extensions to the + * {@link DavServletRequest} interface used for dealing with transaction lock + * requests. + */ +public interface TransactionDavServletRequest extends DavServletRequest { + + /** + * Retrieve the 'transactioninfo' request body that must be included with + * the UNLOCK request of a transaction lock. If the request body is does not + * provide the information required (either because it is missing or the + * Xml is not valid) null is returned. + * + * @return TransactionInfo object encapsulating the 'transactioninfo' + * Xml element present in the request body or null if no + * body is present or if it could not be parsed. + * @throws DavException if an invalid request body is present. + */ + public TransactionInfo getTransactionInfo() throws DavException; + + + /** + * Retrieve the transaction id from the + * {@link TransactionConstants#HEADER_TRANSACTIONID TransactionId header}. + * + * @return transaction id as present in the {@link TransactionConstants#HEADER_TRANSACTIONID TransactionId header} + * or null. + */ + public String getTransactionId(); +} \ No newline at end of file Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/transaction/TransactionDavServletRequest.java ___________________________________________________________________ Added: svn Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/transaction/TransactionInfo.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/transaction/TransactionInfo.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/transaction/TransactionInfo.java (working copy) @@ -0,0 +1,105 @@ +/* + * 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.webdav.transaction; + +import org.apache.jackrabbit.webdav.DavException; +import org.apache.jackrabbit.webdav.DavServletResponse; +import org.apache.jackrabbit.webdav.xml.DomUtil; +import org.apache.jackrabbit.webdav.xml.XmlSerializable; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +/** + * TransactionInfo class encapsulates the information present + * in the {@link #XML_TRANSACTIONINFO} element that forms the request body of + * the UNLOCk request for a transaction lock. + * + * @see TransactionConstants#XML_TRANSACTIONINFO + * @see TransactionConstants#XML_TRANSACTION + */ +public class TransactionInfo implements TransactionConstants, XmlSerializable { + + private static Logger log = LoggerFactory.getLogger(TransactionInfo.class); + + private final boolean isCommit; + + /** + * Creates a TransactionInfo object + * + * @param isCommit + */ + public TransactionInfo(boolean isCommit) { + this.isCommit = isCommit; + } + + /** + * Creates a TransactionInfo object from the given 'transactionInfo' + * element. The 'transactionInfo' must have the following form: + *

+     *
+     *  <!ELEMENT transactioninfo (transactionstatus) >
+     *  <!ELEMENT transactionstatus ( commit | rollback ) >
+     *  <!ELEMENT commit EMPTY >
+     *  <!ELEMENT rollback EMPTY >
+     * 
+ * @param transactionInfo as present in the UNLOCK request body. + * @throws IllegalArgumentException if the given transactionInfo element + * is not valid. + */ + public TransactionInfo(Element transactionInfo) throws DavException { + if (transactionInfo == null || !XML_TRANSACTIONINFO.equals(transactionInfo.getLocalName())) { + log.warn("'transactionInfo' element expected."); + throw new DavException(DavServletResponse.SC_BAD_REQUEST); + } + Element txStatus = DomUtil.getChildElement(transactionInfo, XML_TRANSACTIONSTATUS, NAMESPACE); + if (txStatus != null) { + // retrieve status: commit or rollback + isCommit = DomUtil.hasChildElement(txStatus, XML_COMMIT, NAMESPACE); + } else { + log.warn("transactionInfo must contain a single 'transactionstatus' element."); + throw new DavException(DavServletResponse.SC_BAD_REQUEST); + } + } + + /** + * Returns true, if this info requires a 'commit' action, false otherwise + * (i.e. 'rollback' is requested). + * + * @return true if a 'commit' element was present. false otherwise. + * @see #XML_COMMIT + * @see #XML_ROLLBACK + */ + public boolean isCommit() { + return isCommit; + } + + //------------------------------------------< XmlSerializable interface >--- + /** + * @see org.apache.jackrabbit.webdav.xml.XmlSerializable#toXml(Document) + * @param document + */ + public Element toXml(Document document) { + Element elem = DomUtil.createElement(document, XML_TRANSACTIONINFO, NAMESPACE); + Element st = DomUtil.addChildElement(elem, XML_TRANSACTIONSTATUS, NAMESPACE); + String lName = (isCommit) ? XML_COMMIT : XML_ROLLBACK; + DomUtil.addChildElement(st, lName, NAMESPACE); + return elem; + } + +} \ No newline at end of file Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/transaction/TransactionInfo.java ___________________________________________________________________ Added: svn Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/transaction/TransactionResource.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/transaction/TransactionResource.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/transaction/TransactionResource.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.webdav.transaction; + +import org.apache.jackrabbit.webdav.DavException; +import org.apache.jackrabbit.webdav.DavResource; + +/** + * TransactionResource extends the {@link DavResource} interface by + * transaction relevant METHODS. + */ +public interface TransactionResource extends DavResource { + + public static final String METHODS = ""; + + /** + * Initializes the TransactionResource. + * + * @param txMgr + * @param transactionId + */ + public void init(TxLockManager txMgr, String transactionId); + + /** + * The TransactionId or null according to the value of the + * corresponding request {@link TransactionConstants#HEADER_TRANSACTIONID header} + * field. + * + * @return TransactionId header or null + */ + public String getTransactionId(); + + /** + * Overloads the {@link DavResource#unlock unlock} method of the DavResource + * interface. + * + * @param lockToken lock token as present in the request header. + * @param info transaction info object as present in the UNLOCK request body. + * @throws DavException if an error occurs + * @see DavResource#unlock(String) + * @see TransactionDavServletRequest#getTransactionId() + * @see org.apache.jackrabbit.webdav.DavServletRequest#getLockToken() + */ + public void unlock(String lockToken, TransactionInfo info) throws DavException; +} \ No newline at end of file Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/transaction/TransactionResource.java ___________________________________________________________________ Added: svn Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/transaction/TxActiveLock.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/transaction/TxActiveLock.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/transaction/TxActiveLock.java (working copy) @@ -0,0 +1,93 @@ +/* + * 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.webdav.transaction; + +import org.apache.jackrabbit.webdav.lock.DefaultActiveLock; +import org.apache.jackrabbit.webdav.lock.LockInfo; +import org.apache.jackrabbit.webdav.lock.Scope; +import org.apache.jackrabbit.webdav.lock.Type; + +/** + * TxActiveLock represents the transaction lock present on a + * {@link TransactionResource}. + */ +public class TxActiveLock extends DefaultActiveLock implements TransactionConstants { + + public static final long DEFAULT_TIMEOUT = 300000; // 5 minutes + + private final Scope scope; + + /** + * Create a new transaction lock.
+ * If the lockInfo element is null the timeout defaults to + * half and hour. The default scope is 'local'. + * + * @param lockInfo + * @throws IllegalArgumentException if either scope or type is invalid or if + * a depth other than infinity is requested. + */ + public TxActiveLock(LockInfo lockInfo) { + if (lockInfo != null) { + if (!TRANSACTION.equals(lockInfo.getType())) { + throw new IllegalArgumentException("Only 'transaction' type is allowed for a transaction-activelock object."); + } + if (!(LOCAL.equals(lockInfo.getScope()) || GLOBAL.equals(lockInfo.getScope()))) { + throw new IllegalArgumentException("Only 'global' or 'local' are valid scopes within a transaction-activelock element."); + } + if (!lockInfo.isDeep()) { + throw new IllegalArgumentException("Only transaction locks can only be deep."); + } + setOwner(lockInfo.getOwner()); + setTimeout(lockInfo.getTimeout()); + scope = lockInfo.getScope(); + } else { + setTimeout(DEFAULT_TIMEOUT); + // local scope by default + scope = LOCAL; + } + } + + /** + * Always returns true. + * + * @return true + */ + @Override + public boolean isDeep() { + return true; + } + + /** + * Always returns the {@link #TRANSACTION} type. + * + * @return {@link #TRANSACTION} + */ + @Override + public Type getType() { + return TRANSACTION; + } + + /** + * Returns the scope of this lock which is either {@link #LOCAL} or {@link #GLOBAL}. + * + * @return {@link #LOCAL} or {@link #GLOBAL} + */ + @Override + public Scope getScope() { + return scope; + } +} Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/transaction/TxActiveLock.java ___________________________________________________________________ Added: svn Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/transaction/TxLockEntry.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/transaction/TxLockEntry.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/transaction/TxLockEntry.java (working copy) @@ -0,0 +1,72 @@ +/* + * 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.webdav.transaction; + +import org.apache.jackrabbit.webdav.lock.AbstractLockEntry; +import org.apache.jackrabbit.webdav.lock.Scope; +import org.apache.jackrabbit.webdav.lock.Type; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * TxLockEntry represents the lock entry objects allowed for + * a transaction lock. + */ +public final class TxLockEntry extends AbstractLockEntry implements TransactionConstants { + + private static Logger log = LoggerFactory.getLogger(TxLockEntry.class); + + private final Scope scope; + + /** + * Create a lock entry that identifies transaction lock. + * + * @param isLocal boolean value indicating whether this is a local or a global + * lock entry. + */ + public TxLockEntry(boolean isLocal) { + if (isLocal) { + scope = LOCAL; + } else { + scope = GLOBAL; + } + } + + /** + * Returns the {@link #TRANSACTION 'transaction'} lock type. + * + * @return always returns the 'transaction' type. + * @see org.apache.jackrabbit.webdav.lock.LockEntry#getType() + * @see #TRANSACTION + */ + public Type getType() { + return TRANSACTION; + } + + /** + * Returns either {@link #LOCAL local} or {@link #GLOBAL global} scope + * depending on the initial constructor value. + * + * @return returns 'global' or 'local' scope. + * @see org.apache.jackrabbit.webdav.lock.LockEntry#getScope() + * @see #GLOBAL + * @see #LOCAL + */ + public Scope getScope() { + return scope; + } +} \ No newline at end of file Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/transaction/TxLockEntry.java ___________________________________________________________________ Added: svn Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/transaction/TxLockManager.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/transaction/TxLockManager.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/transaction/TxLockManager.java (working copy) @@ -0,0 +1,65 @@ +/* + * 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.webdav.transaction; + +import org.apache.jackrabbit.webdav.DavException; +import org.apache.jackrabbit.webdav.lock.ActiveLock; +import org.apache.jackrabbit.webdav.lock.LockManager; +import org.apache.jackrabbit.webdav.lock.Scope; +import org.apache.jackrabbit.webdav.lock.Type; + +/** + * TxLockManager manages locks with locktype + * '{@link TransactionConstants#TRANSACTION dcr:transaction}'. + * + * todo: removing all expired locks + * todo: 'local' and 'global' are not accurate terms in the given context > replace + * todo: the usage of the 'global' transaction is not according to the JTA specification, + * which explicitly requires any transaction present on a servlet to be completed before + * the service method returns. Starting/completing transactions on the session object, + * which is possible with the jackrabbit implementation is a hack. + * todo: review of this transaction part is therefore required. Is there a use-case + * for those 'global' transactions at all... + */ +public interface TxLockManager extends LockManager { + + + /** + * Release the lock identified by the given lock token. + * + * @param lockInfo + * @param lockToken + * @param resource + * @throws org.apache.jackrabbit.webdav.DavException + */ + public void releaseLock(TransactionInfo lockInfo, String lockToken, + TransactionResource resource) throws DavException; + + + /** + * Return the lock applied to the given resource or null + * + * @param type + * @param scope + * @param resource + * @return lock applied to the given resource or null + * @see org.apache.jackrabbit.webdav.lock.LockManager#getLock(org.apache.jackrabbit.webdav.lock.Type, org.apache.jackrabbit.webdav.lock.Scope, org.apache.jackrabbit.webdav.DavResource) + */ + public ActiveLock getLock(Type type, Scope scope, TransactionResource resource); + + +} Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/transaction/TxLockManager.java ___________________________________________________________________ Added: svn Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/transaction/package-info.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/transaction/package-info.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/transaction/package-info.java (working copy) @@ -0,0 +1,18 @@ +/* + * 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. + */ +@org.osgi.annotation.versioning.Version("1.0.0") +package org.apache.jackrabbit.webdav.transaction; Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/transaction/package-info.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/util/CSRFUtil.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/util/CSRFUtil.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/util/CSRFUtil.java (working copy) @@ -0,0 +1,168 @@ +/* + * 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.webdav.util; + +import java.net.URI; +import java.net.URISyntaxException; +import java.util.Arrays; +import java.util.Collections; +import java.util.Enumeration; +import java.util.HashSet; +import java.util.Locale; +import java.util.Set; + +import javax.servlet.http.HttpServletRequest; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * CSRFUtil... + */ +public class CSRFUtil { + + /** + * Constant used to + */ + public static final String DISABLED = "disabled"; + + /** + * Request content types for CSRF checking, see JCR-3909, JCR-4002, and JCR-4009 + */ + public static final Set CONTENT_TYPES = Collections.unmodifiableSet(new HashSet( + Arrays.asList( + new String[] { + "application/x-www-form-urlencoded", + "multipart/form-data", + "text/plain" + } + ) + )); + + /** + * logger instance + */ + private static final Logger log = LoggerFactory.getLogger(CSRFUtil.class); + + /** + * Disable referrer based CSRF protection + */ + private final boolean disabled; + + /** + * Additional allowed referrer hosts for CSRF protection + */ + private final Set allowedReferrerHosts; + + /** + * Creates a new instance from the specified configuration, which defines + * the behaviour of the referrer based CSRF protection as follows: + *
    + *
  1. If config is null or empty string the default + * behaviour is to allow only requests with an empty referrer header or a + * referrer host equal to the server host
  2. + *
  3. A comma separated list of additional allowed referrer hosts which are + * valid in addition to default behaviour (see above).
  4. + *
  5. The value {@link #DISABLED} may be used to disable the referrer checking altogether
  6. + *
+ * + * @param config The configuration value which may be any of the following: + *
    + *
  • null or empty string for the default behaviour, which + * only allows requests with an empty referrer header or a + * referrer host equal to the server host
  • + *
  • A comma separated list of additional allowed referrer hosts which are + * valid in addition to default behaviour (see above).
  • + *
  • {@link #DISABLED} in order to disable the referrer checking altogether
  • + *
+ */ + public CSRFUtil(String config) { + if (config == null || config.length() == 0) { + disabled = false; + allowedReferrerHosts = Collections.emptySet(); + log.debug("CSRF protection disabled"); + } else { + if (DISABLED.equalsIgnoreCase(config.trim())) { + disabled = true; + allowedReferrerHosts = Collections.emptySet(); + } else { + disabled = false; + String[] allowed = config.split(","); + allowedReferrerHosts = new HashSet(allowed.length); + for (String entry : allowed) { + allowedReferrerHosts.add(entry.trim()); + } + } + log.debug("CSRF protection enabled, allowed referrers: " + allowedReferrerHosts); + } + } + + public boolean isValidRequest(HttpServletRequest request) { + + if (disabled) { + return true; + } else if (!"POST".equals(request.getMethod())) { + // protection only needed for POST + return true; + } else { + Enumeration cts = (Enumeration) request.getHeaders("Content-Type"); + String ct = null; + if (cts != null && cts.hasMoreElements()) { + String t = cts.nextElement(); + // prune parameters + int semicolon = t.indexOf(';'); + if (semicolon >= 0) { + t = t.substring(0, semicolon); + } + ct = t.trim().toLowerCase(Locale.ENGLISH); + } + if (cts != null && cts.hasMoreElements()) { + // reject if there are more header field instances + log.debug("request blocked because there were multiple content-type header fields"); + return false; + } + if (ct != null && !CONTENT_TYPES.contains(ct)) { + // type present and not in blacklist + return true; + } + + String refHeader = request.getHeader("Referer"); + // empty referrer headers are not allowed for POST + relevant + // content types (see JCR-3909) + if (refHeader == null) { + log.debug("POST with content type " + ct + " blocked due to missing referer header field"); + return false; + } + + try { + String host = new URI(refHeader).getHost(); + // test referrer-host equals server or + // if it is contained in the set of explicitly allowed host + // names + boolean ok = host == null || host.equals(request.getServerName()) || allowedReferrerHosts.contains(host); + if (!ok) { + log.debug("POST with content type " + ct + " blocked due to referer header field being: " + refHeader); + } + return ok; + } catch (URISyntaxException ex) { + // referrer malformed -> block access + log.debug("POST with content type " + ct + " blocked due to malformed referer header field: " + refHeader); + return false; + } + } + } +} \ No newline at end of file Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/util/CSRFUtil.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-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/util/EncodeUtil.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/util/EncodeUtil.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/util/EncodeUtil.java (working copy) @@ -0,0 +1,220 @@ +/* + * 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.webdav.util; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.ByteArrayOutputStream; +import java.io.UnsupportedEncodingException; +import java.nio.charset.StandardCharsets; +import java.util.BitSet; + +/** + * EncodeUtil provides helper methods for URL encoding and decoding + * (copied from jcr-commons jackrabbit.util.Text). + * + * @see JCR-2897. + */ +public final class EncodeUtil { + + /** + * logger instance + */ + private static final Logger log = LoggerFactory.getLogger(EncodeUtil.class); + + /** + * hextable used for {@link #escape(String, char, boolean)} + */ + public static final char[] hexTable = "0123456789abcdef".toCharArray(); + + /** + * The list of characters that are not encoded by the escape() + * and unescape() METHODS. They contains the characters as + * defined 'unreserved' in section 2.3 of the RFC 2396 'URI generic syntax': + *

+ *

+     * unreserved  = alphanum | mark
+     * mark        = "-" | "_" | "." | "!" | "~" | "*" | "'" | "(" | ")"
+     * 
+ */ + private static BitSet URISave; + + /** + * Same as {@link #URISave} but also contains the '/' + */ + private static BitSet URISaveEx; + + static { + URISave = new BitSet(256); + int i; + for (i = 'a'; i <= 'z'; i++) { + URISave.set(i); + } + for (i = 'A'; i <= 'Z'; i++) { + URISave.set(i); + } + for (i = '0'; i <= '9'; i++) { + URISave.set(i); + } + URISave.set('-'); + URISave.set('_'); + URISave.set('.'); + URISave.set('!'); + URISave.set('~'); + URISave.set('*'); + URISave.set('\''); + URISave.set('('); + URISave.set(')'); + + URISaveEx = (BitSet) URISave.clone(); + URISaveEx.set('/'); + } + + /** + * Does a URL encoding of the string. The characters that + * don't need encoding are those defined 'unreserved' in section 2.3 of + * the 'URI generic syntax' RFC 2396. + * + * @param string the string to encode + * @return the escaped string + * @throws NullPointerException if string is null. + */ + public static String escape(String string) { + return escape(string, '%', false); + } + + /** + * Does a URL encoding of the path. The characters that + * don't need encoding are those defined 'unreserved' in section 2.3 of + * the 'URI generic syntax' RFC 2396. In contrast to the + * {@link #escape(String)} method, not the entire path string is escaped, + * but every individual part (i.e. the slashes are not escaped). + * + * @param path the path to encode + * @return the escaped path + * @throws NullPointerException if path is null. + */ + public static String escapePath(String path) { + return escape(path, '%', true); + } + + /** + * Does an URL encoding of the string using the + * escape character. The characters that don't need encoding + * are those defined 'unreserved' in section 2.3 of the 'URI generic syntax' + * RFC 2396, but without the escape character. If isPath is + * true, additionally the slash '/' is ignored, too. + * + * @param string the string to encode. + * @param escape the escape character. + * @param isPath if true, the string is treated as path + * @return the escaped string + * @throws NullPointerException if string is null. + */ + private static String escape(String string, char escape, boolean isPath) { + BitSet validChars = isPath ? URISaveEx : URISave; + byte[] bytes = string.getBytes(StandardCharsets.UTF_8); + StringBuffer out = new StringBuffer(bytes.length); + for (byte aByte : bytes) { + int c = aByte & 0xff; + if (validChars.get(c) && c != escape) { + out.append((char) c); + } else { + out.append(escape); + out.append(hexTable[(c >> 4) & 0x0f]); + out.append(hexTable[(c) & 0x0f]); + } + } + return out.toString(); + } + + /** + * Does a URL decoding of the string. Please note that in + * opposite to the {@link java.net.URLDecoder} it does not transform the + + * into spaces. + * + * @param string the string to decode + * @return the decoded string + * @throws NullPointerException if string is null. + * @throws ArrayIndexOutOfBoundsException if not enough character follow an + * escape character + * @throws IllegalArgumentException if the 2 characters following the escape + * character do not represent a hex-number. + */ + public static String unescape(String string) { + return unescape(string, '%'); + } + + /** + * Does a URL decoding of the string using the + * escape character. Please note that in opposite to the + * {@link java.net.URLDecoder} it does not transform the + into spaces. + * + * @param string the string to decode + * @param escape the escape character + * @return the decoded string + * @throws NullPointerException if string is null. + * @throws IllegalArgumentException if the 2 characters following the escape + * character do not represent a hex-number + * or if not enough characters follow an + * escape character + */ + private static String unescape(String string, char escape) { + byte[] utf8 = string.getBytes(StandardCharsets.UTF_8); + + // Check whether escape occurs at invalid position + if ((utf8.length >= 1 && utf8[utf8.length - 1] == escape) || + (utf8.length >= 2 && utf8[utf8.length - 2] == escape)) { + throw new IllegalArgumentException("Premature end of escape sequence at end of input"); + } + + ByteArrayOutputStream out = new ByteArrayOutputStream(utf8.length); + for (int k = 0; k < utf8.length; k++) { + byte b = utf8[k]; + if (b == escape) { + out.write((decodeDigit(utf8[++k]) << 4) + decodeDigit(utf8[++k])); + } + else { + out.write(b); + } + } + + return new String(out.toByteArray(), StandardCharsets.UTF_8); + } + + private static byte decodeDigit(byte b) { + if (b >= 0x30 && b <= 0x39) { + return (byte) (b - 0x30); + } + else if (b >= 0x41 && b <= 0x46) { + return (byte) (b - 0x37); + } + else if (b >= 0x61 && b <= 0x66) { + return (byte) (b - 0x57); + } + else { + throw new IllegalArgumentException("Escape sequence is not hexadecimal: " + (char)b); + } + } + + /** + * Private constructor: avoid instantiation. + */ + private EncodeUtil() { + } +} \ No newline at end of file Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/util/EncodeUtil.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-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/util/HttpDateFormat.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/util/HttpDateFormat.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/util/HttpDateFormat.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.webdav.util; + +import java.text.SimpleDateFormat; +import java.util.Locale; +import java.util.TimeZone; + +/** + * HttpDateFormat... + */ +public class HttpDateFormat extends SimpleDateFormat { + + private static final TimeZone GMT_TIMEZONE = TimeZone.getTimeZone("GMT"); + + /** + * Pattern for the modification date as defined by RFC 1123 + */ + public static final String MODIFICATION_DATE_PATTERN = "EEE, dd MMM yyyy HH:mm:ss z"; + + /** + * Simple date format pattern for the creation date ISO representation (partial). + */ + public static final String CREATION_DATE_PATTERN = "yyyy-MM-dd'T'HH:mm:ss'Z'"; + + public HttpDateFormat(String pattern) { + super(pattern, Locale.ENGLISH); + super.setTimeZone(GMT_TIMEZONE); + } + + /** + * Creates a new HttpDateFormat using the + * {@link #MODIFICATION_DATE_PATTERN modifcation date pattern}. + * + * @return a new HttpDateFormat. + */ + public static HttpDateFormat modificationDateFormat() { + return new HttpDateFormat(MODIFICATION_DATE_PATTERN); + } + + /** + * Creates a new HttpDateFormat using the + * {@link #CREATION_DATE_PATTERN creation date pattern}. + * + * @return a new HttpDateFormat. + */ + public static HttpDateFormat creationDateFormat() { + return new HttpDateFormat(CREATION_DATE_PATTERN); + } +} \ No newline at end of file Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/util/HttpDateFormat.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-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/util/HttpDateTimeFormatter.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/util/HttpDateTimeFormatter.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/util/HttpDateTimeFormatter.java (working copy) @@ -0,0 +1,152 @@ +/* + * 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.webdav.util; + +import java.time.Instant; +import java.time.LocalDate; +import java.time.ZoneOffset; +import java.time.ZonedDateTime; +import java.time.format.DateTimeFormatter; +import java.time.format.DateTimeFormatterBuilder; +import java.time.format.DateTimeParseException; +import java.time.temporal.ChronoField; +import java.util.Locale; + +/** + * Parsers and Serializers for HTTP dates (RFC 7231, Section 7.1.1.1), using + * {@link DateTimeFormatter} (from Java 8). + */ +public class HttpDateTimeFormatter { + + private static DateTimeFormatter IMFFIXDATE = DateTimeFormatter.ofPattern("EEE, dd MMM yyyy HH:mm:ss 'GMT'", Locale.ENGLISH) + .withZone(ZoneOffset.UTC); + + // see + // https://greenbytes.de/tech/webdav/rfc7231.html#rfc.section.7.1.1.1.p.6 + private static DateTimeFormatter RFC850DATE = new DateTimeFormatterBuilder().appendPattern("EEEE, dd-MMM-") + .appendValueReduced(ChronoField.YEAR_OF_ERA, 2, 2, LocalDate.now().minusYears(50)).appendPattern(" HH:mm:ss 'GMT'") + .toFormatter().withLocale(Locale.ENGLISH).withZone(ZoneOffset.UTC); + + private static DateTimeFormatter ASCTIMEDATE = new DateTimeFormatterBuilder().appendPattern("EEE MMM ").padNext(2, ' ') + .appendValue(ChronoField.DAY_OF_MONTH).appendPattern(" HH:mm:ss yyyy").toFormatter().withLocale(Locale.ENGLISH) + .withZone(ZoneOffset.UTC); + + /** + * Parse HTTP "IMF-fixdate" format (see RFC 7231, Section 7.1.1.1) + * + * @param fieldValue + * string value + * @return ms since epoch throws DateTimeParseException on invalid input + */ + public static long parseImfFixedDate(String fieldValue) { + ZonedDateTime d = ZonedDateTime.parse(fieldValue, IMFFIXDATE); + return d.toInstant().toEpochMilli(); + } + + /** + * Parse HTTP "rfc850-date" format (see RFC 7231, Section 7.1.1.1) + * + * @param fieldValue + * string value + * @return ms since epoch throws DateTimeParseException on invalid input + */ + public static long parseRfc850Date(String fieldValue) { + ZonedDateTime d = ZonedDateTime.parse(fieldValue, RFC850DATE); + return d.toInstant().toEpochMilli(); + } + + /** + * Parse HTTP "asctime-date" format (see RFC 7231, Section 7.1.1.1) + * + * @param fieldValue + * string value + * @return ms since epoch throws DateTimeParseException on invalid input + */ + public static long parseAscTimeDate(String fieldValue) { + ZonedDateTime d = ZonedDateTime.parse(fieldValue, ASCTIMEDATE); + return d.toInstant().toEpochMilli(); + } + + /** + * Parse HTTP format, trying the three allowable formats defined in RFC + * 7231, Section 7.1.1.1 + * + * @param fieldValue + * string value + * @return ms since epoch throws DateTimeParseException on invalid input + */ + public static long parse(String fieldValue) { + try { + return parseImfFixedDate(fieldValue); + } catch (DateTimeParseException ex) { + try { + return parseRfc850Date(fieldValue); + } catch (DateTimeParseException ex2) { + try { + return parseAscTimeDate(fieldValue); + } catch (DateTimeParseException ex3) { + // if we get here, throw original exception for IMFFIXDATE + throw ex; + } + } + } + } + + /** + * Format as HTTP default date (IMF-fixdate) (see RFC 7231, Section 7.1.1.1) + * + * @param millisSinceEpoch + * ms since epoch + * @return string representation + */ + public static String format(long millisSinceEpoch) { + return IMFFIXDATE.format(Instant.ofEpochMilli(millisSinceEpoch)); + } + + /** + * Format as HTTP "IMF-fixdate" (see RFC 7231, Section 7.1.1.1) + * + * @param millisSinceEpoch + * ms since epoch + * @return string representation + */ + public static String formatImfFixed(long millisSinceEpoch) { + return IMFFIXDATE.format(Instant.ofEpochMilli(millisSinceEpoch)); + } + + /** + * Format as HTTP "rfc850-date" (see RFC 7231, Section 7.1.1.1) + * + * @param millisSinceEpoch + * ms since epoch + * @return string representation + */ + public static String formatRfc850(long millisSinceEpoch) { + return RFC850DATE.format(Instant.ofEpochMilli(millisSinceEpoch)); + } + + /** + * Format as HTTP "asctime-date" (see RFC 7231, Section 7.1.1.1) + * + * @param millisSinceEpoch + * ms since epoch + * @return string representation + */ + public static String formatAscTime(long millisSinceEpoch) { + return ASCTIMEDATE.format(Instant.ofEpochMilli(millisSinceEpoch)); + } +} Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/util/HttpDateTimeFormatter.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/util/LinkHeaderFieldParser.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/util/LinkHeaderFieldParser.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/util/LinkHeaderFieldParser.java (working copy) @@ -0,0 +1,197 @@ +/* + * 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.webdav.util; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.Enumeration; +import java.util.HashMap; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.apache.http.NameValuePair; +import org.apache.http.message.BasicHeaderValueParser; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Simple parser for HTTP Link header fields, as defined in RFC 5988. + */ +public class LinkHeaderFieldParser { + + /** + * the default logger + */ + private static Logger log = LoggerFactory.getLogger(LinkHeaderFieldParser.class); + + private final List relations; + + public LinkHeaderFieldParser(List fieldValues) { + List tmp = new ArrayList(); + if (fieldValues != null) { + for (String value : fieldValues) { + addFields(tmp, value); + } + } + relations = Collections.unmodifiableList(tmp); + } + + public LinkHeaderFieldParser(Enumeration en) { + if (en != null && en.hasMoreElements()) { + List tmp = new ArrayList(); + + while (en.hasMoreElements()) { + addFields(tmp, en.nextElement().toString()); + } + relations = Collections.unmodifiableList(tmp); + } else { + // optimize case of no Link headers + relations = Collections.emptyList(); + } + } + + public String getFirstTargetForRelation(String relationType) { + + for (LinkRelation lr : relations) { + + String relationNames = lr.getParameters().get("rel"); + if (relationNames != null) { + + // split rel value on whitespace + for (String rn : relationNames.toLowerCase(Locale.ENGLISH) + .split("\\s")) { + if (relationType.equals(rn)) { + return lr.getTarget(); + } + } + } + } + + return null; + } + + // A single header field instance can contain multiple, comma-separated + // fields. + private void addFields(List l, String fieldValue) { + + boolean insideAngleBrackets = false; + boolean insideDoubleQuotes = false; + + for (int i = 0; i < fieldValue.length(); i++) { + + char c = fieldValue.charAt(i); + + if (insideAngleBrackets) { + insideAngleBrackets = c != '>'; + } else if (insideDoubleQuotes) { + insideDoubleQuotes = c != '"'; + if (c == '\\' && i < fieldValue.length() - 1) { + // skip over next character + c = fieldValue.charAt(++i); + } + } else { + insideAngleBrackets = c == '<'; + insideDoubleQuotes = c == '"'; + + if (c == ',') { + String v = fieldValue.substring(0, i); + if (v.length() > 0) { + try { + l.add(new LinkRelation(v)); + } catch (Exception ex) { + log.warn("parse error in Link Header field value", + ex); + } + } + addFields(l, fieldValue.substring(i + 1)); + return; + } + } + } + + if (fieldValue.length() > 0) { + try { + l.add(new LinkRelation(fieldValue)); + } catch (Exception ex) { + log.warn("parse error in Link Header field value", ex); + } + } + } + + private static class LinkRelation { + + private static Pattern P = Pattern.compile("\\s*<(.*)>\\s*(.*)"); + + private String target; + private Map parameters; + + /** + * Parses a single link relation, consisting of and optional + * parameters. + * + * @param field + * field value + * @throws Exception + */ + public LinkRelation(String field) throws Exception { + + // find the link target using a regexp + Matcher m = P.matcher(field); + if (!m.matches()) { + throw new Exception("illegal Link header field value:" + field); + } + + target = m.group(1); + + // pass the remainder to the generic parameter parser + NameValuePair[] params = BasicHeaderValueParser.parseParameters(m.group(2), null); + + if (params.length == 0) { + parameters = Collections.emptyMap(); + } else if (params.length == 1) { + NameValuePair nvp = params[0]; + parameters = Collections.singletonMap(nvp.getName() + .toLowerCase(Locale.ENGLISH), nvp.getValue()); + } else { + parameters = new HashMap(); + for (NameValuePair p : params) { + if (null != parameters.put( + p.getName().toLowerCase(Locale.ENGLISH), + p.getValue())) { + throw new Exception("duplicate parameter + " + + p.getName() + " field ignored"); + } + } + } + } + + public String getTarget() { + return target; + } + + public Map getParameters() { + return parameters; + } + + public String toString() { + return target + " " + parameters; + } + } +} Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/util/LinkHeaderFieldParser.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/util/package-info.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/util/package-info.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/util/package-info.java (working copy) @@ -0,0 +1,18 @@ +/* + * 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. + */ +@org.osgi.annotation.versioning.Version("1.1.0") +package org.apache.jackrabbit.webdav.util; Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/util/package-info.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/ActivityResource.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/ActivityResource.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/ActivityResource.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.webdav.version; + +import org.apache.jackrabbit.webdav.property.DavPropertyName; + +/** + * An activity is a resource that selects a set of versions that are on a single + * "line of descent", where a line of descent is a sequence of versions connected + * by successor relationships. If an activity selects versions from multiple + * version histories, the versions selected in each version history must be on a + * single line of descent. + *

+ * RFC 3253 defines the following required live properties for an Activity + * resource. + *

    + *
  • {@link #ACTIVITY_VERSION_SET DAV:activity-version-set}
  • + *
  • {@link #ACTIVITY_CHECKOUT_SET DAV:activity-checkout-set}
  • + *
  • {@link #SUBACTIVITY_SET DAV:subactivity-set}
  • + *
  • {@link #CURRENT_WORKSPACE_SET DAV:current-workspace-set}
  • + *
  • all DeltaV-compliant resource properties}.
  • + *
  • Note, that the {@link org.apache.jackrabbit.webdav.DavConstants#PROPERTY_RESOURCETYPE DAV:resourcetype} + * property returned by an Activity resource must be + * {@link org.apache.jackrabbit.webdav.property.ResourceType#ACTIVITY DAV:activity}
  • + *
+ *

+ * The Activity resource must support all methods defined for a + * {@link DeltaVResource DeltaV-compliant resource}. Since no additional methods + * are required for an activity this interface mainly acts as marker. + *

+ * Please refer to RFC 3253 + * Section 13 for a complete description of this resource type. + */ +public interface ActivityResource extends DeltaVResource { + + /** + * The computed DAV:activity-version-set property identifies each version + * whose DAV:activity-set property identifies this activity. Multiple + * versions of a single version history can be selected by an activity's + * DAV:activity-version-set property, but all DAV:activity-version-set + * versions from a given version history must be on a single line of descent + * from the root version of that version history. + *

+ * Note that the DAV:activity-version-set represents a + * {@link org.apache.jackrabbit.webdav.property.HrefProperty HrefProperty} + */ + public static final DavPropertyName ACTIVITY_VERSION_SET = DavPropertyName.create("activity-version-set", DeltaVConstants.NAMESPACE); + + /** + * The computed DAV:activity-checkout-set property identifies each + * checked-out resource whose DAV:activity-set identifies this activity. + *

+ * Note that the DAV:activity-checkout-set represents a + * {@link org.apache.jackrabbit.webdav.property.HrefProperty HrefProperty} + */ + public static final DavPropertyName ACTIVITY_CHECKOUT_SET = DavPropertyName.create("activity-checkout-set", DeltaVConstants.NAMESPACE); + + /** + * The DAV:subactivity-set property identifies each activity that forms a + * part of the logical change being captured by this activity. An activity + * behaves as if its DAV:activity-version-set is extended by the + * DAV:activity-version-set of each activity identified in the + * DAV:subactivity-set. In particular, the versions in this extended set + * MUST be on a single line of descent, and when an activity selects a version + * for merging, the latest version in this extended set is the one that will + * be merged. + *

+ * A server MAY reject attempts to modify the DAV:subactivity-set of an activity. + * + * Note that the DAV:subactivity-set represents a + * {@link org.apache.jackrabbit.webdav.property.HrefProperty HrefProperty} + */ + public static final DavPropertyName SUBACTIVITY_SET = DavPropertyName.create("subactivity-set", DeltaVConstants.NAMESPACE); + + /** + * The computed DAV:current-workspace-set property identifies identifies + * each workspace whose DAV:current-activity-set identifies this activity. + *

+ * Note that the DAV:current-workspace-set represents a + * {@link org.apache.jackrabbit.webdav.property.HrefProperty HrefProperty} + */ + public static final DavPropertyName CURRENT_WORKSPACE_SET = DavPropertyName.create("current-workspace-set", DeltaVConstants.NAMESPACE); + +} \ No newline at end of file Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/ActivityResource.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-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/BaselineResource.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/BaselineResource.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/BaselineResource.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.webdav.version; + +import org.apache.jackrabbit.webdav.property.DavPropertyName; +import org.apache.jackrabbit.webdav.DavResource; +import org.apache.jackrabbit.webdav.DavException; + +/** + * BaselineResource represents the 'version' of a configuration + * which is represented by a 'version-controlled-configuration' (VCC) resource. + * Such as new versions are created by CHECKIN of a version-controlled + * resource, a new baseline is created, whenever the VCC resource, that + * represents a set of resources rather than a single resource, is checked-in. + *

+ * Since the baseline behaves like a VersionResource and only is + * defined to provide additional protected properties, this interface only adds + * a convenience method that allows to retrieve the baseline collection. + *

+ * Supported live properties: + *

+ * DAV:baseline-collection
+ * DAV:subbaseline-set
+ * all version properties.
+ * 
+ * + * Supported methods: + *
+ * all version methods.
+ * 
+ */ +public interface BaselineResource extends VersionResource { + + /** + * The protected DAV:baseline-collection property identifies a distinct + * collection that lists as members all version-controlled resources of + * the configuration this baseline belongs to (the baseline being one + * version of the corresponding vc-configuration-resource). In other words: + * each member in the list must correspond to a member of the baseline-controlled + * collection at the time this baseline (version) was created. + *

+ * + * Note that the DAV:baseline-collection represents a + * {@link org.apache.jackrabbit.webdav.property.HrefProperty HrefProperty} + */ + public static final DavPropertyName BASELINE_COLLECTION = DavPropertyName.create("baseline-collection", DeltaVConstants.NAMESPACE); + + /** + * The protected DAV:subbaseline-set property identifies a set of baseline + * resources. Note however, that the subbaselines of this resource are + * not only formed from the baseline resources listed in this property + * but also includes all subbaseline resources of the latter. + * + * Note that the DAV:subbaseline-set represents a + * {@link org.apache.jackrabbit.webdav.property.HrefProperty HrefProperty} + */ + public static final DavPropertyName SUBBASELINE_SET = DavPropertyName.create("subbaseline-set", DeltaVConstants.NAMESPACE); + + /** + * Return the resource that represents the baseline-collection of this + * baseline, which is identified the href present in the {@link #BASELINE_COLLECTION} + * property. + * + * @return baseline collection + */ + public DavResource getBaselineCollection() throws DavException; +} \ No newline at end of file Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/BaselineResource.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-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/DeltaVConstants.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/DeltaVConstants.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/DeltaVConstants.java (working copy) @@ -0,0 +1,374 @@ +/* + * 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.webdav.version; + +import org.apache.jackrabbit.webdav.DavConstants; +import org.apache.jackrabbit.webdav.property.DavPropertyName; +import org.apache.jackrabbit.webdav.xml.Namespace; + +/** + * DeltaVConstants defines the following headers and properties + * required for any resource that is compliant to + * RFC 3253:

+ * + * Headers: + *

+ * Label
+ * 
+ * + * Properties: + *
+ * DAV:comment
+ * DAV:creator-displayname
+ * DAV:supported-method-set
+ * DAV:supported-live-property-set
+ * DAV:supported-report-set
+ * 
+ * + * Some additional resource properties are defined by the various advanced + * version features: + *
+ * DAV:workspace (workspace feature)
+ * DAV:version-controlled-configuration (baseline)
+ * 
+ */ +public interface DeltaVConstants { + + /** + * The DAV: namespace. + */ + public static final Namespace NAMESPACE = DavConstants.NAMESPACE; + + //---< Headers >------------------------------------------------------------ + /** + * For certain METHODS, if the request-URL identifies a version-controlled + * resource, a label can be specified in a LabelInfo request header to cause the + * method to be applied to the version selected by that label.
+ * LabelInfo header MUST have no effect on a request whose request-URL does not + * identify a version-controlled resource. In particular, it MUST have no + * effect on a request whose request-URL identifies a version or a version + * history. + */ + public static final String HEADER_LABEL = "Label"; + + /** + * Location header as defined by + * RFC 2616. In the versioning + * context it is used to indicate the location of the new version created by a + * successful checkin in the response.

+ * From RFC 2616:
+ * The Location response-header field is used to redirect the recipient to a + * location other than the Request-URI for completion of the request or + * identification of a new resource.
+ * For 201 (Created) responses, the Location is that of the new resource + * which was created by the request. + */ + public static final String HEADER_LOCATION = "Location"; + + //---< Property Names >----------------------------------------------------- + /** + * The "DAV:comment" property is used to track a brief comment about a resource that is + * suitable for presentation to a user. The DAV:comment of a version can be + * used to indicate why that version was created. + */ + public static final DavPropertyName COMMENT = DavPropertyName.create("comment", NAMESPACE); + + /** + * The "DAV:creator-displayname" property contains a description of the creator of + * the resource that is suitable for presentation to a user. The + * DAV:creator-displayname of a version can be used to indicate who created + * that version. + */ + public static final DavPropertyName CREATOR_DISPLAYNAME = DavPropertyName.create("creator-displayname", NAMESPACE); + + /** + * Required protected live property for any resources being compliant with + * RFC 3253. Clients should classify a resource by examine the values of the + * DAV:supported-method-set and DAV:supported-live-property-set + * properties of that resource.
+ * Property structure: + *
+     * <!ELEMENT supported-method-set (supported-method*)>
+     * <!ELEMENT supported-method ANY>
+     * <!ATTLIST supported-method name NMTOKEN #REQUIRED>
+     * name value: a method name
+     * 
+ * + * @see #SUPPORTED_LIVE_PROPERTY_SET + */ + public static final DavPropertyName SUPPORTED_METHOD_SET = DavPropertyName.create("supported-method-set", NAMESPACE); + + /** + * Required protected live property for any resources being compliant with + * RFC 3253. Clients should classify a resource by examine the values of the + * DAV:supported-method-set and DAV:supported-live-property-set + * properties of that resource.
+ * Property structure: + *
+     * <!ELEMENT supported-live-property-set (supported-live-property*)>
+     * <!ELEMENT supported-live-property name>
+     * <!ELEMENT prop ANY>
+     * ANY value: a property element type
+     * 
+ * + * @see #SUPPORTED_METHOD_SET + */ + public static final DavPropertyName SUPPORTED_LIVE_PROPERTY_SET = DavPropertyName.create("supported-live-property-set", NAMESPACE); + + /** + * Protected "supported-report-set" property identifies the reports that are + * supported by the resource. + * + * @see #SUPPORTED_REPORT_SET + */ + public static final DavPropertyName SUPPORTED_REPORT_SET = DavPropertyName.create("supported-report-set", NAMESPACE); + + /** + * Protected "workspace" property indicating the workspace of a resource. + * This property is required for all resources if (but only if) the workspace + * feature is supported. + *

+ * Note that the DAV:activity-version-set represents a + * {@link org.apache.jackrabbit.webdav.property.HrefProperty HrefProperty}. + * It is defined to have the following format: + *

+     * <!ELEMENT workspace (href)>
+     * 
+ * + * @see WorkspaceResource + */ + public static final DavPropertyName WORKSPACE = DavPropertyName.create("workspace", NAMESPACE); + + /** + * The Baseline feature introduces the computed DAV:version-controlled-configuration + * property for all resources that are member of a version-controlled + * configuration. This may be the case if the resource is a collection under + * baseline control or is a member of a collection under baseline control. + *

+ * Note that the DAV:activity-version-set represents a + * {@link org.apache.jackrabbit.webdav.property.HrefProperty HrefProperty}. + * It is defined to have the following format: + *

+     * <!ELEMENT version-controlled-configuration (href)>
+     * 
+ */ + public static final DavPropertyName VERSION_CONTROLLED_CONFIGURATION = DavPropertyName.create("version-controlled-configuration", NAMESPACE); + + + //---< XML Element, Attribute Names >--------------------------------------- + /** + * Xml elements + */ + public static final String XML_ACTIVITY = "activity"; + public static final String XML_BASELINE = "baseline"; + + public static final String XML_SUPPORTED_METHOD = "supported-method"; + public static final String XML_VERSION_HISTORY = "version-history"; + public static final String XML_VERSION = "version"; + public static final String XML_WORKSPACE = "workspace"; + + // options + /** + * If the OPTIONS request contains a body, i must start with an DAV:options + * element. + * + * @see OptionsInfo + * @see #XML_VH_COLLECTION_SET + * @see #XML_WSP_COLLECTION_SET + * @see #XML_ACTIVITY_COLLECTION_SET + */ + public static final String XML_OPTIONS = "options"; + + /** + * If an XML response body for a successful request is included, it must be + * a DAV:options-response XML element. + * + * @see OptionsResponse + */ + public static final String XML_OPTIONS_RESPONSE = "options-response"; + + /** + * A DAV:version-history-collection-set element may be included in the OPTIONS + * request body to identify collections that may contain version history + * resources.
+ * The response body for a successful request must in consequence contain a + * DAV:version-history-collection-set element identifying collections that + * may contain version histories. An identified collection may be the root + * collection of a tree of collections, all of which may contain version + * histories. + * + *
+     * <!ELEMENT version-history-collection-set (href*)>
+     * 
+ */ + public static final String XML_VH_COLLECTION_SET = "version-history-collection-set"; + + /** + * A DAV:workspace-collection-set element may be included in the OPTIONS request + * body to identify collections that may contain workspace resources.
+ * The response body for a successful request must contain a + * DAV:workspace-collection-set element identifying collections that may + * contain workspaces. An identified collection may be the root collection + * of a tree of collections, all of which may contain workspaces. + * + *
+     * <!ELEMENT workspace-collection-set (href*)>
+     * 
+ */ + public static final String XML_WSP_COLLECTION_SET = "workspace-collection-set"; + + /** + * A DAV:workspace-collection-set element may be included in the OPTIONS request + * body to identify collections that may contain activity resources.
+ * The response body for a successful request must contain a + * DAV:workspace-collection-set element identifying collections that may + * contain activity resources. An identified collection may be the root collection + * of a tree of collections, all of which may contain activity resources. + * + *
+     * <!ELEMENT activity-collection-set (href*)>
+     * 
+ */ + public static final String XML_ACTIVITY_COLLECTION_SET = "activity-collection-set"; + + /** + * Name of Xml element contained in the {@link #SUPPORTED_REPORT_SET} property. + * + * @see #SUPPORTED_REPORT_SET + * @see org.apache.jackrabbit.webdav.version.report.SupportedReportSetProperty + */ + public static final String XML_SUPPORTED_REPORT = "supported-report"; + + /** + * Name of Xml child elements of {@link #XML_SUPPORTED_REPORT}. + * + * @see org.apache.jackrabbit.webdav.version.report.SupportedReportSetProperty + */ + public static final String XML_REPORT = "report"; + + /** + * Top element for the 'DAV:version-tree' report + */ + public static final String XML_VERSION_TREE = "version-tree"; + + /** + * Top element for the 'DAV:expand-property' report + */ + public static final String XML_EXPAND_PROPERTY = "expand-property"; + + /** + * 'DAV:property' element to be used inside the 'DAV:expand-property' element. + * + * @see #XML_EXPAND_PROPERTY + */ + public static final String XML_PROPERTY = "property"; + + /** + * 'DAV:name' attribute for the property element + * + * @see #XML_PROPERTY + */ + public static final String ATTR_NAME = "name"; + + /** + * 'DAV:namespace' attribute for the property element + * + * @see #XML_PROPERTY + */ + public static final String ATTR_NAMESPACE = "namespace"; + + /** + * Top element for the 'DAV:locate-by-history' report + */ + public static final String XML_LOCATE_BY_HISTORY = "locate-by-history"; + + /** + * 'DAV:version-history-set' to be used inside the 'DAV:locate-by-history' + * element + * + * @see #XML_LOCATE_BY_HISTORY + */ + public static final String XML_VERSION_HISTORY_SET = "version-history-set"; + + + /** + * Xml element representing the mandatory root element of a LABEL request + * body. + * + * @see #XML_LABEL_NAME + * @see #XML_LABEL_ADD + * @see #XML_LABEL_REMOVE + * @see #XML_LABEL_SET + * @see LabelInfo + */ + public static final String XML_LABEL = "label"; + public static final String XML_LABEL_NAME = "label-name"; + public static final String XML_LABEL_ADD = "add"; + public static final String XML_LABEL_REMOVE = "remove"; + public static final String XML_LABEL_SET = "set"; + + /** + * Xml element defining the top element in the UPDATE request body. RFC 3253 + * defines the following structure for the 'update' element. + *
+     * <!ELEMENT update ANY>
+     * ANY value: A sequence of elements with at most one DAV:version element
+     * and at most one DAV:prop element.
+     * <!ELEMENT version (href)>
+     * prop: see RFC 2518, Section 12.11
+     * 
+ */ + public static final String XML_UPDATE = "update"; + + // auto-version + /** + * Value for the DAV:auto-version property indicating that any modification + * (such as PUT/PROPPATCH) applied to a checked-in version-controlled + * resource will automatically be preceded by a checkout and followed by a + * checkin operation.
+ * See also RFC 3253 DAV:auto-version + */ + public static final String XML_CHECKOUT_CHECKIN = "checkout-checkin"; + /** + * Value for the DAV:auto-version property indicating that any modification + * (such as PUT/PROPPATCH) applied to a checked-in version-controlled + * resource will automatically be preceded by a checkout operation. + * If the resource is not write-locked, the request is automatically + * followed by a checkin operation.
+ * See also RFC 3253 DAV:auto-version + */ + public static final String XML_CHECKOUT_UNLOCK_CHECKIN = "checkout-unlocked-checkin"; + /** + * Value for the DAV:auto-version property indicating that any modification + * (such as PUT/PROPPATCH) applied to a checked-in version-controlled + * resource will automatically be preceded by a checkout operation.
+ * See also RFC 3253 DAV:auto-version + */ + public static final String XML_CHECKOUT = "checkout"; + /** + * Value for the DAV:auto-version property indicating that any modification + * (such as PUT/PROPPATCH) applied to a write-locked checked-in version-controlled + * resource will automatically be preceded by a checkout operation.
+ * See also RFC 3253 DAV:auto-version + */ + public static final String XML_LOCKED_CHECKIN = "locked-checkout"; + + // merge + public static final String XML_MERGE = "merge"; + public static final String XML_N0_AUTO_MERGE = "no-auto-merge"; + public static final String XML_N0_CHECKOUT = "no-checkout"; +} \ No newline at end of file Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/DeltaVConstants.java ___________________________________________________________________ Added: svn Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/DeltaVResource.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/DeltaVResource.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/DeltaVResource.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.webdav.version; + +import org.apache.jackrabbit.webdav.DavException; +import org.apache.jackrabbit.webdav.DavResource; +import org.apache.jackrabbit.webdav.property.DavPropertyName; +import org.apache.jackrabbit.webdav.version.report.Report; +import org.apache.jackrabbit.webdav.version.report.ReportInfo; + +/** + * The DeltaVResource encapsulates the functionality common to all + * DeltaV compliant resources. + *

+ * RFC 3253 defines the following required properties: + *

    + *
  • {@link DeltaVConstants#COMMENT DAV:comment}
  • + *
  • {@link DeltaVConstants#CREATOR_DISPLAYNAME DAV:creator-displayname}
  • + *
  • {@link DeltaVConstants#SUPPORTED_METHOD_SET DAV:supported-method-set}
  • + *
  • {@link DeltaVConstants#SUPPORTED_LIVE_PROPERTY_SET DAV:supported-live-property-set}
  • + *
  • {@link DeltaVConstants#SUPPORTED_REPORT_SET DAV:supported-report-set}
  • + *
  • all properties defined in WebDAV [RFC2518].
  • + *
+ *

+ * In addition a DeltaV compliant resource must support the following METHODS: + *

    + *
  • REPORT
  • + *
  • all METHODS defined in WebDAV [RFC2518]
  • + *
  • all METHODS defined in HTTP/1.1 [RFC2616].
  • + *
+ * + * @see DavResource + */ +public interface DeltaVResource extends DavResource { + + /** + * The generic deltaV compliant resource defines one additional method REPORT. + * + * @see org.apache.jackrabbit.webdav.DavResource#METHODS + */ + public String METHODS = "REPORT"; + + /** + * If the server support the Workspace featured defined by RFC 3253 certain + * DeltaVResources may also support the MKWORKSPACE method. + * + * @see #addWorkspace(DavResource) + */ + public String METHODS_INCL_MKWORKSPACE = "REPORT, MKWORKSPACE"; + + /** + * Retrieves the information requested in the OPTIONS request body and + * returns the corresponding values. + * + * @param optionsInfo + * @return object to be included to the OPTIONS response body or null + * if the specified optionsInfo was null or empty. + */ + public OptionsResponse getOptionResponse(OptionsInfo optionsInfo); + + /** + * Runs the report specified by the given ReportInfo. + * + * @param reportInfo + * @return the requested report. + * @throws DavException in case an error occurred or if the specified ReportInfo + * is either not valid or cannot be run by the given resource. + */ + public Report getReport(ReportInfo reportInfo) throws DavException; + + /** + * Add a new member to this resource, that represents a workspace.
+ * Please note that no resource must exist at the location of the new workspace. + * + * @param workspace resource representing the new workspace to be created as + * member of this resource. + * @throws DavException if creating the new workspace fails. + */ + // TODO: MKWORKSPACE may include an xml request body... + public void addWorkspace(DavResource workspace) throws DavException; + + /** + * Returns an array of DavResource objects that are referenced + * by the {@link org.apache.jackrabbit.webdav.property.HrefProperty} with + * the specified {@link DavPropertyName name}. + * + * @param hrefPropertyName + * @return An array of DavResources + * @throws DavException if the given hrefPropertyName does point to an + * unknown property or does not represent the name of a + * {@link org.apache.jackrabbit.webdav.property.HrefProperty href property}. + * Finally the exception may be caused if the property contains the href + * of a non-existing resource, which cannot be resolved. + * @see org.apache.jackrabbit.webdav.property.HrefProperty + */ + public DavResource[] getReferenceResources(DavPropertyName hrefPropertyName) throws DavException; +} \ No newline at end of file Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/DeltaVResource.java ___________________________________________________________________ Added: svn Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/DeltaVServletRequest.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/DeltaVServletRequest.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/DeltaVServletRequest.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.webdav.version; + +import org.apache.jackrabbit.webdav.DavException; +import org.apache.jackrabbit.webdav.DavServletRequest; +import org.apache.jackrabbit.webdav.version.report.ReportInfo; + +/** + * DeltaVServletRequest provides extension useful for functionality + * related to RFC 3253. + */ +public interface DeltaVServletRequest extends DavServletRequest { + + /** + * Returns the Label header or null + * + * @return label header or null + * @see DeltaVConstants#HEADER_LABEL + */ + public String getLabel(); + + /** + * Return the request body as LabelInfo object or null + * if parsing the request body or the creation of the label info failed. + * + * @return LabelInfo object or null + * @throws DavException in case of an invalid request body + */ + public LabelInfo getLabelInfo() throws DavException; + + /** + * Return the request body as MergeInfo object or null + * if the creation failed due to invalid format. + * + * @return MergeInfo object or null + * @throws DavException in case of an invalid request body + */ + public MergeInfo getMergeInfo() throws DavException; + + /** + * Parses the UPDATE request body a build the corresponding UpdateInfo + * object. If the request body is missing or does not of the required format + * null is returned. + * + * @return the parsed update request body or null + * @throws DavException in case of an invalid request body + */ + public UpdateInfo getUpdateInfo() throws DavException; + + /** + * Returns the request body and the Depth header as ReportInfo + * object. The default depth, if no {@link org.apache.jackrabbit.webdav.DavConstants#HEADER_DEPTH + * Depth header}, is {@link org.apache.jackrabbit.webdav.DavConstants#DEPTH_0}. + * If the request body could not be parsed into an {@link org.w3c.dom.Element} + * null is returned. + * + * @return ReportInfo or null + * @throws DavException in case of an invalid request body + */ + public ReportInfo getReportInfo() throws DavException; + + /** + * Returns the {@link OptionsInfo} present with the request or null. + * + * @return {@link OptionsInfo} or null + * @throws DavException in case of an invalid request body + */ + public OptionsInfo getOptionsInfo() throws DavException; +} \ No newline at end of file Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/DeltaVServletRequest.java ___________________________________________________________________ Added: svn Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/LabelInfo.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/LabelInfo.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/LabelInfo.java (working copy) @@ -0,0 +1,188 @@ +/* + * 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.webdav.version; + +import org.apache.jackrabbit.webdav.DavConstants; +import org.apache.jackrabbit.webdav.DavException; +import org.apache.jackrabbit.webdav.DavServletResponse; +import org.apache.jackrabbit.webdav.xml.DomUtil; +import org.apache.jackrabbit.webdav.xml.XmlSerializable; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +/** + * LabelInfo encapsulates the request body of a LABEL request + * used to add, set or remove a label from the requested version resource or + * from that version specified with the Label header in case the requested resource + * is a version-controlled resource.

+ * The request body (thus the 'labelElement' passed to the constructor must be + * a DAV:label element: + *
+ * <!ELEMENT label ANY>
+ * ANY value: A sequence of elements with at most one DAV:add,
+ * DAV:set, or DAV:remove element.
+ * <!ELEMENT add (label-name)>
+ * <!ELEMENT set (label-name)>
+ * <!ELEMENT remove (label-name)>
+ * <!ELEMENT label-name (#PCDATA)>
+ * PCDATA value: string
+ * 
+ * Please note, that the given implementation only recognizes the predefined elements 'add', + * 'set' and 'remove'. + */ +public class LabelInfo implements DeltaVConstants, XmlSerializable { + + private static Logger log = LoggerFactory.getLogger(LabelInfo.class); + + public static final int TYPE_SET = 0; + public static final int TYPE_REMOVE = 1; + public static final int TYPE_ADD = 2; + + public static String[] typeNames = new String[] { XML_LABEL_SET , XML_LABEL_REMOVE, XML_LABEL_ADD}; + + private final int depth; + private final int type; + private final String labelName; + + public LabelInfo(String labelName, String type) { + if (labelName == null) { + throw new IllegalArgumentException("Label name must not be null."); + } + boolean validType = false; + int i = 0; + while (i < typeNames.length) { + if (typeNames[i].equals(type)) { + validType = true; + break; + } + i++; + } + if (!validType) { + throw new IllegalArgumentException("Invalid type: " + type); + } + this.type = i; + this.labelName = labelName; + this.depth = DavConstants.DEPTH_0; + } + + public LabelInfo(String labelName, int type) { + this(labelName, type, DavConstants.DEPTH_0); + } + + public LabelInfo(String labelName, int type, int depth) { + if (labelName == null) { + throw new IllegalArgumentException("Label name must not be null."); + } + if (type < TYPE_SET || type > TYPE_ADD) { + throw new IllegalArgumentException("Invalid type: " + type); + } + this.labelName = labelName; + this.type = type; + this.depth = depth; + } + + /** + * Create a new LabelInfo from the given element and depth + * integer. If the specified Xml element does have a {@link DeltaVConstants#XML_LABEL} + * root element or no label name is specified with the action to perform + * the creation will fail. + * + * @param labelElement + * @param depth + * @throws DavException if the specified element does not + * start with a {@link DeltaVConstants#XML_LABEL} element or if the DAV:label + * element contains illegal instructions e.g. contains multiple DAV:add, DAV:set + * or DAV:remove elements. + */ + public LabelInfo(Element labelElement, int depth) throws DavException { + if (!DomUtil.matches(labelElement, DeltaVConstants.XML_LABEL, DeltaVConstants.NAMESPACE)) { + log.warn("DAV:label element expected"); + throw new DavException(DavServletResponse.SC_BAD_REQUEST); + } + + String label = null; + int type = -1; + for (int i = 0; i < typeNames.length && type == -1; i++) { + if (DomUtil.hasChildElement(labelElement, typeNames[i], NAMESPACE)) { + type = i; + Element el = DomUtil.getChildElement(labelElement, typeNames[i], NAMESPACE); + label = DomUtil.getChildText(el, XML_LABEL_NAME, NAMESPACE); + } + } + if (label == null) { + log.warn("DAV:label element must contain at least one set, add or remove element defining a label-name."); + throw new DavException(DavServletResponse.SC_BAD_REQUEST); + } + this.labelName = label; + this.type = type; + this.depth = depth; + } + + /** + * Create a new LabelInfo from the given element. As depth + * the default value 0 is assumed. + * + * @param labelElement + * @throws DavException + * @see #LabelInfo(org.w3c.dom.Element, int) + */ + public LabelInfo(Element labelElement) throws DavException { + this(labelElement, 0); + } + + /** + * Return the text present inside the 'DAV:label-name' element or null + * + * @return 'label-name' or null + */ + public String getLabelName() { + return labelName; + } + + /** + * Return the type of the LABEL request. This might either be {@link #TYPE_SET}, + * {@link #TYPE_ADD} or {@link #TYPE_REMOVE}. + * + * @return type + */ + public int getType() { + return type; + } + + /** + * Return the depth + * + * @return depth + */ + public int getDepth() { + return depth; + } + + /** + * @see org.apache.jackrabbit.webdav.xml.XmlSerializable#toXml(Document) + * @param document + */ + public Element toXml(Document document) { + Element label = DomUtil.createElement(document, XML_LABEL, NAMESPACE); + Element typeElem = DomUtil.addChildElement(label, typeNames[type], NAMESPACE); + DomUtil.addChildElement(typeElem, XML_LABEL_NAME, NAMESPACE, labelName); + return label; + } + +} \ No newline at end of file Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/LabelInfo.java ___________________________________________________________________ Added: svn Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/LabelSetProperty.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/LabelSetProperty.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/LabelSetProperty.java (working copy) @@ -0,0 +1,63 @@ +/* + * 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.webdav.version; + +import org.apache.jackrabbit.webdav.property.AbstractDavProperty; +import org.apache.jackrabbit.webdav.xml.DomUtil; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +/** + * LabelSetProperty... + */ +public class LabelSetProperty extends AbstractDavProperty { + + private static Logger log = LoggerFactory.getLogger(LabelSetProperty.class); + + private final String[] value; + + /** + * Create a new LabelSetProperty. + * + * @param labels + */ + public LabelSetProperty(String[] labels) { + super(VersionResource.LABEL_NAME_SET, true); + this.value = labels; + } + + + public String[] getValue() { + return value; + } + + /** + * @see org.apache.jackrabbit.webdav.xml.XmlSerializable#toXml(Document) + * @param document + */ + @Override + public Element toXml(Document document) { + Element elem = getName().toXml(document); + for (String str : value) { + DomUtil.addChildElement(elem, DeltaVConstants.XML_LABEL_NAME, DeltaVConstants.NAMESPACE, str); + } + return elem; + } + +} Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/LabelSetProperty.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-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/MergeInfo.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/MergeInfo.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/MergeInfo.java (working copy) @@ -0,0 +1,182 @@ +/* + * 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.webdav.version; + +import org.apache.jackrabbit.webdav.DavConstants; +import org.apache.jackrabbit.webdav.DavException; +import org.apache.jackrabbit.webdav.DavServletResponse; +import org.apache.jackrabbit.webdav.property.DavPropertyNameSet; +import org.apache.jackrabbit.webdav.xml.DomUtil; +import org.apache.jackrabbit.webdav.xml.ElementIterator; +import org.apache.jackrabbit.webdav.xml.XmlSerializable; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +import java.util.ArrayList; +import java.util.List; + +/** + * MergeInfo encapsulates the information present in the DAV:merge + * element, that forms the mandatory request body of a MERGE request.
+ * The DAV:merge element is specified to have the following form. + *
+ * <!ELEMENT merge ANY>
+ * ANY value: A sequence of elements with one DAV:source element, at most one
+ * DAV:no-auto-merge element, at most one DAV:no-checkout element, at most one
+ * DAV:prop element, and any legal set of elements that can occur in a DAV:checkout
+ * element.
+ * <!ELEMENT source (href+)>
+ * <!ELEMENT no-auto-merge EMPTY>
+ * <!ELEMENT no-checkout EMPTY>
+ * prop: see RFC 2518, Section 12.11
+ * 
+ */ +public class MergeInfo implements DeltaVConstants, XmlSerializable { + + private static Logger log = LoggerFactory.getLogger(MergeInfo.class); + + private final Element mergeElement; + private final DavPropertyNameSet propertyNameSet; + + /** + * Create a new MergeInfo + * + * @param mergeElement + * @throws DavException if the mergeElement is null + * or not a DAV:merge element. + */ + public MergeInfo(Element mergeElement) throws DavException { + if (!DomUtil.matches(mergeElement, XML_MERGE, NAMESPACE)) { + log.warn("'DAV:merge' element expected"); + throw new DavException(DavServletResponse.SC_BAD_REQUEST); + } + + // if property name set if present + Element propElem = DomUtil.getChildElement(mergeElement, DavConstants.XML_PROP, DavConstants.NAMESPACE); + if (propElem != null) { + propertyNameSet = new DavPropertyNameSet(propElem); + mergeElement.removeChild(propElem); + } else { + propertyNameSet = new DavPropertyNameSet(); + } + this.mergeElement = mergeElement; + } + + /** + * Returns the URL specified with the DAV:source element or null + * if no such child element is present in the DAV:merge element. + * + * @return href present in the DAV:source child element or null. + */ + public String[] getSourceHrefs() { + List sourceHrefs = new ArrayList(); + Element srcElem = DomUtil.getChildElement(mergeElement, DavConstants.XML_SOURCE, DavConstants.NAMESPACE); + if (srcElem != null) { + ElementIterator it = DomUtil.getChildren(srcElem, DavConstants.XML_HREF, DavConstants.NAMESPACE); + while (it.hasNext()) { + String href = DomUtil.getTextTrim(it.nextElement()); + if (href != null) { + sourceHrefs.add(href); + } + } + } + return sourceHrefs.toArray(new String[sourceHrefs.size()]); + } + + /** + * Returns true if the DAV:merge element contains a DAV:no-auto-merge child element. + * + * @return true if the DAV:merge element contains a DAV:no-auto-merge child. + */ + public boolean isNoAutoMerge() { + return DomUtil.hasChildElement(mergeElement, XML_N0_AUTO_MERGE, NAMESPACE); + } + + /** + * Returns true if the DAV:merge element contains a DAV:no-checkout child element. + * + * @return true if the DAV:merge element contains a DAV:no-checkout child + */ + public boolean isNoCheckout() { + return DomUtil.hasChildElement(mergeElement, XML_N0_CHECKOUT, NAMESPACE); + } + + /** + * Returns a {@link DavPropertyNameSet}. If the DAV:merge element contains + * a DAV:prop child element the properties specified therein are included + * in the set. Otherwise an empty set is returned.
+ * + * WARNING: modifying the DavPropertyNameSet returned by this method does + * not modify this UpdateInfo. + * + * @return set listing the properties specified in the DAV:prop element indicating + * those properties that must be reported in the response body. + */ + public DavPropertyNameSet getPropertyNameSet() { + return propertyNameSet; + } + + /** + * Returns the DAV:merge element used to create this MergeInfo + * object. + * + * @return DAV:merge element + */ + public Element getMergeElement() { + return mergeElement; + } + + /** + * @see org.apache.jackrabbit.webdav.xml.XmlSerializable#toXml(Document) + * @param document + */ + public Element toXml(Document document) { + Element elem = (Element)document.importNode(mergeElement, true); + if (!propertyNameSet.isEmpty()) { + elem.appendChild(propertyNameSet.toXml(document)); + } + return elem; + } + + + /** + * Factory method to create a minimal DAV:merge element to create a new + * MergeInfo object. + * + * @param mergeSource + * @param isNoAutoMerge + * @param isNoCheckout + * @param factory + * @return + */ + public static Element createMergeElement(String[] mergeSource, boolean isNoAutoMerge, boolean isNoCheckout, Document factory) { + Element mergeElem = DomUtil.createElement(factory, XML_MERGE, NAMESPACE); + Element source = DomUtil.addChildElement(mergeElem, DavConstants.XML_SOURCE, DavConstants.NAMESPACE); + for (String ms : mergeSource) { + source.appendChild(DomUtil.hrefToXml(ms, factory)); + } + if (isNoAutoMerge) { + DomUtil.addChildElement(mergeElem, XML_N0_AUTO_MERGE, NAMESPACE); + } + if (isNoCheckout) { + DomUtil.addChildElement(mergeElem, XML_N0_CHECKOUT, NAMESPACE); + } + return mergeElem; + } +} Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/MergeInfo.java ___________________________________________________________________ Added: svn Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/OptionsInfo.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/OptionsInfo.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/OptionsInfo.java (working copy) @@ -0,0 +1,126 @@ +/* + * 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.webdav.version; + +import org.apache.jackrabbit.webdav.DavException; +import org.apache.jackrabbit.webdav.DavServletResponse; +import org.apache.jackrabbit.webdav.xml.DomUtil; +import org.apache.jackrabbit.webdav.xml.ElementIterator; +import org.apache.jackrabbit.webdav.xml.Namespace; +import org.apache.jackrabbit.webdav.xml.XmlSerializable; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +import java.util.HashSet; +import java.util.Set; +import java.util.Arrays; + +/** + * OptionsInfo represents the Xml request body, that may be present + * with a OPTIONS request. + *
+ * The DAV:options element is specified to have the following form. + * + *
+ * <!ELEMENT options ANY>
+ * ANY value: A sequence of elements each at most once.
+ * 
+ * + * Note, that this is a simplified implementation of the very generic + * definition: We assume that the DAV:options element only contains empty child + * elements, such as e.g. {@link DeltaVConstants#XML_VH_COLLECTION_SET DAV:version-history-collection-set} + * or {@link DeltaVConstants#XML_WSP_COLLECTION_SET DAV:workspace-collection-set}. + * + * @see DeltaVConstants#XML_VH_COLLECTION_SET + * @see DeltaVConstants#XML_WSP_COLLECTION_SET + * @see DeltaVConstants#XML_ACTIVITY_COLLECTION_SET + */ +public class OptionsInfo implements XmlSerializable { + + private static Logger log = LoggerFactory.getLogger(OptionsInfo.class); + + private final Set entriesLocalNames = new HashSet(); + + /** + * Create a new OptionsInfo with the specified entries. Each entry will + * be converted to an empty Xml element when calling toXml. + * As namespace {@link DeltaVConstants#NAMESPACE} is used. + * + * @param entriesLocalNames + */ + public OptionsInfo(String[] entriesLocalNames) { + if (entriesLocalNames != null) { + this.entriesLocalNames.addAll(Arrays.asList(entriesLocalNames)); + } + } + + /** + * Private constructor used to create an OptionsInfo from Xml. + */ + private OptionsInfo() {} + + /** + * Returns true if a child element with the given name and namespace is present. + * + * @param localName + * @param namespace + * @return true if such a child element exists in the options element. + */ + public boolean containsElement(String localName, Namespace namespace) { + if (DeltaVConstants.NAMESPACE.equals(namespace)) { + return entriesLocalNames.contains(localName); + } + return false; + } + + /** + * @see org.apache.jackrabbit.webdav.xml.XmlSerializable#toXml(Document) + * @param document + */ + public Element toXml(Document document) { + Element optionsElem = DomUtil.createElement(document, DeltaVConstants.XML_OPTIONS, DeltaVConstants.NAMESPACE); + for (String localName : entriesLocalNames) { + DomUtil.addChildElement(optionsElem, localName, DeltaVConstants.NAMESPACE); + } + return optionsElem; + } + + /** + * Build an OptionsInfo object from the root element present + * in the request body. + * + * @param optionsElement + * @return + * @throws DavException if the optionsElement is null + * or not a DAV:options element. + */ + public static OptionsInfo createFromXml(Element optionsElement) throws DavException { + if (!DomUtil.matches(optionsElement, DeltaVConstants.XML_OPTIONS, DeltaVConstants.NAMESPACE)) { + log.warn("DAV:options element expected"); + throw new DavException(DavServletResponse.SC_BAD_REQUEST); + } + OptionsInfo oInfo = new OptionsInfo(); + ElementIterator it = DomUtil.getChildren(optionsElement); + while (it.hasNext()) { + // todo: not correct since assuming its the deltaV-namespace + oInfo.entriesLocalNames.add(it.nextElement().getLocalName()); + } + return oInfo; + } +} Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/OptionsInfo.java ___________________________________________________________________ Added: svn Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/OptionsResponse.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/OptionsResponse.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/OptionsResponse.java (working copy) @@ -0,0 +1,144 @@ +/* + * 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.webdav.version; + +import org.apache.jackrabbit.webdav.DavConstants; +import org.apache.jackrabbit.webdav.xml.DomUtil; +import org.apache.jackrabbit.webdav.xml.ElementIterator; +import org.apache.jackrabbit.webdav.xml.Namespace; +import org.apache.jackrabbit.webdav.xml.XmlSerializable; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * OptionsResponse encapsulates the DAV:options-response element + * present in the response body of a successful OPTIONS request (with body). + *
+ * The DAV:options-response element is defined to have the following format. + * + *
+ * <!ELEMENT options-response ANY>
+ * ANY value: A sequence of elements
+ * 
+ * + * Please note, that OptionsResponse represents a simplified implementation + * of the given structure. We assume, that there may only entries that consist + * of a qualified name and a set of href child elements. + * + * @see DeltaVConstants#XML_ACTIVITY_COLLECTION_SET + * @see DeltaVConstants#XML_VH_COLLECTION_SET + * @see DeltaVConstants#XML_WSP_COLLECTION_SET + */ +public class OptionsResponse implements DeltaVConstants, XmlSerializable { + + private static Logger log = LoggerFactory.getLogger(OptionsResponse.class); + + private final Map entries = new HashMap(); + + /** + * Add a new entry to this OptionsResponse and make each + * href present in the String array being a separate {@link org.apache.jackrabbit.webdav.DavConstants#XML_HREF DAV:href} + * element within the entry. + * + * @param localName + * @param namespace + * @param hrefs + */ + public void addEntry(String localName, Namespace namespace, String[] hrefs) { + Entry entry = new Entry(localName, namespace, hrefs); + entries.put(DomUtil.getExpandedName(localName, namespace), entry); + } + + /** + * + * @param localName + * @param namespace + * @return + */ + public String[] getHrefs(String localName, Namespace namespace) { + String key = DomUtil.getExpandedName(localName, namespace); + if (entries.containsKey(key)) { + return entries.get(key).hrefs; + } else { + return new String[0]; + } + } + + /** + * Return the Xml representation. + * + * @return Xml representation. + * @see org.apache.jackrabbit.webdav.xml.XmlSerializable#toXml(Document) + * @param document + */ + public Element toXml(Document document) { + Element optionsResponse = DomUtil.createElement(document, XML_OPTIONS_RESPONSE, NAMESPACE); + for (Entry entry : entries.values()) { + Element elem = DomUtil.addChildElement(optionsResponse, entry.localName, entry.namespace); + for (String href : entry.hrefs) { + elem.appendChild(DomUtil.hrefToXml(href, document)); + } + } + return optionsResponse; + } + + /** + * Build a new OptionsResponse object from the given xml element. + * + * @param orElem + * @return a new OptionsResponse object + * @throws IllegalArgumentException if the specified element is null + * or if its name is other than 'DAV:options-response'. + */ + public static OptionsResponse createFromXml(Element orElem) { + if (!DomUtil.matches(orElem, XML_OPTIONS_RESPONSE, NAMESPACE)) { + throw new IllegalArgumentException("DAV:options-response element expected"); + } + OptionsResponse oResponse = new OptionsResponse(); + ElementIterator it = DomUtil.getChildren(orElem); + while (it.hasNext()) { + Element el = it.nextElement(); + List hrefs = new ArrayList(); + ElementIterator hrefIt = DomUtil.getChildren(el, DavConstants.XML_HREF, DavConstants.NAMESPACE); + while (hrefIt.hasNext()) { + hrefs.add(DomUtil.getTextTrim(hrefIt.nextElement())); + } + oResponse.addEntry(el.getLocalName(), DomUtil.getNamespace(el), hrefs.toArray(new String[hrefs.size()])); + } + return oResponse; + } + + private static class Entry { + + private final String localName; + private final Namespace namespace; + private final String[] hrefs; + + private Entry(String localName, Namespace namespace, String[] hrefs) { + this.localName = localName; + this.namespace = namespace; + this.hrefs = hrefs; + } + } +} Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/OptionsResponse.java ___________________________________________________________________ Added: svn Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/SupportedMethodSetProperty.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/SupportedMethodSetProperty.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/SupportedMethodSetProperty.java (working copy) @@ -0,0 +1,63 @@ +/* + * 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.webdav.version; + +import org.apache.jackrabbit.webdav.property.AbstractDavProperty; +import org.apache.jackrabbit.webdav.xml.DomUtil; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +/** + * The SupportedMethodSetProperty + */ +public class SupportedMethodSetProperty extends AbstractDavProperty implements DeltaVConstants { + + private static Logger log = LoggerFactory.getLogger(SupportedMethodSetProperty.class); + + private final String[] methods; + + /** + * Create a new SupportedMethodSetProperty property. + * + * @param methods that are supported by the resource having this property. + */ + public SupportedMethodSetProperty(String[] methods) { + super(DeltaVConstants.SUPPORTED_METHOD_SET, true); + this.methods = methods; + } + + public String[] getValue() { + return methods; + } + + /** + * @see org.apache.jackrabbit.webdav.xml.XmlSerializable#toXml(Document) + * @param document + */ + @Override + public Element toXml(Document document) { + Element elem = getName().toXml(document); + for (String method : methods) { + Element methodElem = DomUtil.addChildElement(elem, XML_SUPPORTED_METHOD, DeltaVConstants.NAMESPACE); + DomUtil.setAttribute(methodElem, "name", DeltaVConstants.NAMESPACE, method); + } + return elem; + } + +} Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/SupportedMethodSetProperty.java ___________________________________________________________________ Added: svn Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/UpdateInfo.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/UpdateInfo.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/UpdateInfo.java (working copy) @@ -0,0 +1,243 @@ +/* + * 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.webdav.version; + +import org.apache.jackrabbit.webdav.DavConstants; +import org.apache.jackrabbit.webdav.DavException; +import org.apache.jackrabbit.webdav.DavServletResponse; +import org.apache.jackrabbit.webdav.property.DavPropertyNameSet; +import org.apache.jackrabbit.webdav.xml.DomUtil; +import org.apache.jackrabbit.webdav.xml.ElementIterator; +import org.apache.jackrabbit.webdav.xml.XmlSerializable; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +import java.util.ArrayList; +import java.util.List; + +/** + * UpdateInfo encapsulates the request body of an UPDATE request. + * RFC 3253 defines the request body as follows: + *
+ * <!ELEMENT update ANY>
+ * ANY value: A sequence of elements with at most one DAV:label-name or
+ * DAV:version element (but not both).
+ * In addition at one DAV:prop element can be present.
+ *
+ * <!ELEMENT version (href)>
+ * <!ELEMENT label-name (#PCDATA)> PCDATA value: string
+ * prop: see RFC 2518, Section 12.11
+ * 
+ * + * In order to reflect the complete range of version restoring and updating + * of nodes defined by JSR170 the definition has been extended: + *
+ * <!ELEMENT update ( (version | label-name | workspace ) , (prop)?, (removeExisting)? ) >
+ * <!ELEMENT version (href+) >
+ * <!ELEMENT label-name (#PCDATA) >
+ * <!ELEMENT workspace (href) >
+ * <!ELEMENT prop ANY >
+ * <!ELEMENT removeExisting EMPTY >
+ * 
+ */ +public class UpdateInfo implements DeltaVConstants, XmlSerializable { + + private static Logger log = LoggerFactory.getLogger(UpdateInfo.class); + + public static final int UPDATE_BY_VERSION = 0; + public static final int UPDATE_BY_LABEL = 1; + public static final int UPDATE_BY_WORKSPACE = 2; + + private Element updateElement; + + private DavPropertyNameSet propertyNameSet = new DavPropertyNameSet(); + private String[] source; + private int type; + + public UpdateInfo(String[] updateSource, int updateType, DavPropertyNameSet propertyNameSet) { + if (updateSource == null || updateSource.length == 0) { + throw new IllegalArgumentException("Version href array must not be null and have a minimal length of 1."); + } + if (updateType < UPDATE_BY_VERSION || updateType > UPDATE_BY_WORKSPACE) { + throw new IllegalArgumentException("Illegal type of UpdateInfo."); + } + this.type = updateType; + this.source = (updateType == UPDATE_BY_VERSION) ? updateSource : new String[] {updateSource[0]}; + if (propertyNameSet != null) { + this.propertyNameSet = propertyNameSet; + } + } + + /** + * Create a new UpdateInfo object. + * + * @param updateElement + * @throws DavException if the updateElement is null + * or not a DAV:update element or if the element does not match the required + * structure. + */ + public UpdateInfo(Element updateElement) throws DavException { + if (!DomUtil.matches(updateElement, XML_UPDATE, NAMESPACE)) { + log.warn("DAV:update element expected"); + throw new DavException(DavServletResponse.SC_BAD_REQUEST); + } + + boolean done = false; + if (DomUtil.hasChildElement(updateElement, XML_VERSION, NAMESPACE)) { + Element vEl = DomUtil.getChildElement(updateElement, XML_VERSION, NAMESPACE); + ElementIterator hrefs = DomUtil.getChildren(vEl, DavConstants.XML_HREF, DavConstants.NAMESPACE); + List hrefList = new ArrayList(); + while (hrefs.hasNext()) { + hrefList.add(DomUtil.getText(hrefs.nextElement())); + } + source = hrefList.toArray(new String[hrefList.size()]); + type = UPDATE_BY_VERSION; + done = true; + } + + // alternatively 'DAV:label-name' elements may be present. + if (!done && DomUtil.hasChildElement(updateElement, XML_LABEL_NAME, NAMESPACE)) { + source = new String[] {DomUtil.getChildText(updateElement, XML_LABEL_NAME, NAMESPACE)}; + type = UPDATE_BY_LABEL; + done = true; + } + + // last possibility: a DAV:workspace element + if (!done) { + Element wspElem = DomUtil.getChildElement(updateElement, XML_WORKSPACE, NAMESPACE); + if (wspElem != null) { + source = new String[] {DomUtil.getChildTextTrim(wspElem, DavConstants.XML_HREF, DavConstants.NAMESPACE)}; + type = UPDATE_BY_WORKSPACE; + } else { + log.warn("DAV:update element must contain either DAV:version, DAV:label-name or DAV:workspace child element."); + throw new DavException(DavServletResponse.SC_BAD_REQUEST); + } + } + + // if property name set if present + if (DomUtil.hasChildElement(updateElement, DavConstants.XML_PROP, DavConstants.NAMESPACE)) { + Element propEl = DomUtil.getChildElement(updateElement, DavConstants.XML_PROP, DavConstants.NAMESPACE); + propertyNameSet = new DavPropertyNameSet(propEl); + updateElement.removeChild(propEl); + } else { + propertyNameSet = new DavPropertyNameSet(); + } + this.updateElement = updateElement; + } + + /** + * + * @return + */ + public String[] getVersionHref() { + return (type == UPDATE_BY_VERSION) ? source : null; + } + + /** + * + * @return + */ + public String[] getLabelName() { + return (type == UPDATE_BY_LABEL) ? source : null; + } + + /** + * + * @return + */ + public String getWorkspaceHref() { + return (type == UPDATE_BY_WORKSPACE) ? source[0] : null; + } + + /** + * Returns a {@link DavPropertyNameSet}. If the DAV:update element contains + * a DAV:prop child element the properties specified therein are included + * in the set. Otherwise an empty set is returned. + *

+ * WARNING: modifying the DavPropertyNameSet returned by this method does + * not modify this UpdateInfo. + * + * @return set listing the properties specified in the DAV:prop element indicating + * those properties that must be reported in the response body. + */ + public DavPropertyNameSet getPropertyNameSet() { + return propertyNameSet; + } + + /** + * + * @return + */ + public Element getUpdateElement() { + return updateElement; + } + + /** + * @see org.apache.jackrabbit.webdav.xml.XmlSerializable#toXml(Document) + * @param document + */ + public Element toXml(Document document) { + Element elem; + if (updateElement != null) { + elem = (Element)document.importNode(updateElement, true); + } else { + elem = createUpdateElement(source, type, document); + } + if (!propertyNameSet.isEmpty()) { + elem.appendChild(propertyNameSet.toXml(document)); + } + return elem; + } + + /** + * Factory method to create the basic structure of an UpdateInfo + * object. + * + * @param updateSource + * @param updateType + * @param factory + * @return + */ + public static Element createUpdateElement(String[] updateSource, int updateType, Document factory) { + if (updateSource == null || updateSource.length == 0) { + throw new IllegalArgumentException("Update source must specific at least a single resource used to run the update."); + } + + Element elem = DomUtil.createElement(factory, XML_UPDATE, NAMESPACE); + switch (updateType) { + case UPDATE_BY_VERSION: + Element vE = DomUtil.addChildElement(elem, XML_VERSION, NAMESPACE); + for (String source : updateSource) { + vE.appendChild(DomUtil.hrefToXml(source, factory)); + } + break; + case UPDATE_BY_LABEL: + DomUtil.addChildElement(elem, XML_LABEL_NAME, NAMESPACE, updateSource[0]); + break; + case UPDATE_BY_WORKSPACE: + Element wspEl = DomUtil.addChildElement(elem, XML_WORKSPACE, NAMESPACE, updateSource[0]); + wspEl.appendChild(DomUtil.hrefToXml(updateSource[0], factory)); + break; + // no default. + default: + throw new IllegalArgumentException("Invalid update type: " + updateType); + } + return elem; + } +} Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/UpdateInfo.java ___________________________________________________________________ Added: svn Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/VersionControlledResource.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/VersionControlledResource.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/VersionControlledResource.java (working copy) @@ -0,0 +1,363 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.jackrabbit.webdav.version; + +import org.apache.jackrabbit.webdav.DavException; +import org.apache.jackrabbit.webdav.MultiStatus; +import org.apache.jackrabbit.webdav.property.DavPropertyName; + +/** + * The VersionControlledResource represents in contrast to the + * VersionableResource a resource, that has already been put + * under version-control. This resource can be checked-in, checked-out and + * has its own {@link VersionHistoryResource version history}. + *

+ * RFC 3253 defines the following required properties for a + * version-controlled resource (vc-resource): + *

    + *
  • DAV:auto-version
  • + *
  • DAV:version-history (version-history)
  • + *
  • DAV:workspace (workspace)
  • + *
  • DAV:version-controlled-configuration (baseline)
  • + *
  • all DeltaV-compliant resource properties.
  • + *
+ * + * checked-in vc-resource: + *
    + *
  • DAV:checked-in
  • + *
+ * + * checked-out vc-resource: + *
    + *
  • DAV:checked-out
  • + *
  • DAV:predecessor-set
  • + *
  • DAV:checkout-fork (in-place-checkout or working resource)
  • + *
  • DAV:checkin-fork (in-place-checkout or working resource)
  • + *
  • DAV:merge-set (merge)
  • + *
  • DAV:auto-merge-set (merge)
  • + *
  • DAV:unreserved (activity)
  • + *
  • DAV:activity-set (activity)
  • + *
+ * + * If the Version-Controlled-Collection feature is supported (see section 14 + * of RFC 3253) the following computed property is required: + *
    + *
  • DAV:eclipsed-set
  • + *
+ * + * If the Baseline feature is supported (see section 12 of RFC 3253), a version- + * controlled resource may represent a 'configuration' rather than a single + * resource. In this case the RFC defines the following required properties: + *
    + *
  • DAV:baseline-controlled-collection
  • + *
  • DAV:subbaseline-set (if the configuration resource is checked-out)
  • + *
+ * + *

+ * In addition a version-controlled resource must support the following METHODS: + *

    + *
  • VERSION-CONTROL
  • + *
  • MERGE (merge)
  • + *
  • all DeltaV-compliant resource METHODS.
  • + *
+ * + * checked-in vc-resource: + *
    + *
  • CHECKOUT (checkout-in-place)
  • + *
  • UPDATE (update)
  • + *
  • all version-controlled resource METHODS.
  • + *
+ * + * checked-out vc-resource: + *
    + *
  • CHECKIN (checkout-in-place or working-resource)
  • + *
  • UNCHECKOUT (checkout-in-place)
  • + *
  • all DeltaV-compliant resource METHODS.
  • + *
+ * + * @see DeltaVResource + * @see VersionableResource + */ +public interface VersionControlledResource extends VersionableResource { + + /** + * Methods defined for a checked-in version-controlled resource: CHECKOUT, UPDATE, MERGE, LABEL + */ + public String methods_checkedIn = "CHECKOUT, UPDATE, MERGE, LABEL"; + /** + * Methods defined for a checked-out version-controlled resource: CHECKIN, MERGE + */ + public String methods_checkedOut = "CHECKIN, MERGE"; + + /** + * The DAV:auto-version property determines how it responds to a method that + * attempts to modify its content or dead properties. Possible responses + * include various combinations of automated checkout, write lock and checkin + * as well as failure until the resource is explicitly checked-out.
+ * See RFC 3253 for a detailed + * description. + */ + public static final DavPropertyName AUTO_VERSION = DavPropertyName.create("auto-version", DeltaVConstants.NAMESPACE); + + /** + * The computed property DAV:version-history identifies the version history + * resource for the DAV:checked-in or DAV:checked-out version of this + * version-controlled resource.
+ * The property is defined to have the following format: + *
+     * <!ELEMENT version-history (href)>
+     * 
+ */ + public static final DavPropertyName VERSION_HISTORY = DavPropertyName.create("version-history", DeltaVConstants.NAMESPACE); + + /** + * The DAV:checked-in property appears on a checked-in version-controlled + * resource, and identifies the base version of this version-controlled + * resource. This property is removed when the resource is checked out, and + * then added back (identifying a new version) when the resource is checked + * back in.
+ * This property is defined to have the following format: + *
+     * <!ELEMENT checked-in (href)>
+     * 
+ */ + public static final DavPropertyName CHECKED_IN = DavPropertyName.create("checked-in", DeltaVConstants.NAMESPACE); + + /** + * The DAV:checked-out property identifies the base version of this resource. + * It is the same that was identified by the DAV:checked-in property at the + * time the resource was checked out. This property is removed when the + * resource is checked in.
+ * This property is defined to have the following format: + *
+     * <!ELEMENT checked-out (href)>
+     * 
+ * + * @see #CHECKED_IN + */ + public static final DavPropertyName CHECKED_OUT = DavPropertyName.create("checked-out", DeltaVConstants.NAMESPACE); + + /** + * The DAV:predecessor-set property of a version-controlled resource points + * to those version resources, that are scheduled to become the predecessors + * of this resource when it is back checked-in. This property is not + * protected, however a server may reject attempts to modify the + * DAV:predecessor-set of a version-controlled resource.
+ * This property is defined to have the following format: + *
+     * <!ELEMENT predecessor-set (href+)>
+     * 
+ * + * @see #checkin() + * @see VersionResource#PREDECESSOR_SET + */ + public static final DavPropertyName PREDECESSOR_SET = DavPropertyName.create("predecessor-set", DeltaVConstants.NAMESPACE); + + /** + * This property determines the DAV:checkin-fork property of the version + * that results from checking in this resource. + */ + public static final DavPropertyName CHECKIN_FORK = DavPropertyName.create("checkin-fork", DeltaVConstants.NAMESPACE); + + /** + * This property determines the DAV:checkout-fork property of the version + * that results from checking in this resource. + */ + public static final DavPropertyName CHECKOUT_FORK = DavPropertyName.create("checkout-fork", DeltaVConstants.NAMESPACE); + + /** + * This property identifies each version that is to be merged into this + * checked-out resource. This property is set, whenever a MERGE request + * with the DAV:no-auto-merge flag succeeded. The client then must confirm + * each single merge by removing the version from the DAV:merge-set or + * moving it the the versions DAV:predecessor-set.
+ * This property is defined to have the following format: + *
+     * <!ELEMENT merge-set (href*)>
+     * 
+ * + * @see #merge(MergeInfo) + */ + public static final DavPropertyName MERGE_SET = DavPropertyName.create("merge-set", DeltaVConstants.NAMESPACE); + + /** + * The DAV:auto-merge-set property identifies each version that the server + * has merged into this checked-out resource. The client should confirm that + * the merge has been performed correctly before moving a URL from the + * DAV:auto-merge-set to the DAV:predecessor-set of a checked-out resource.
+ * This property is defined to have the following format: + *
+     * <!ELEMENT auto-merge-set (href*)>
+     * 
+ * + * @see #merge(MergeInfo) + */ + public static final DavPropertyName AUTO_MERGE_SET = DavPropertyName.create("auto-merge-set", DeltaVConstants.NAMESPACE); + + /** + * DAV:unreserved is a property for a checked-out resource, if the server + * supports the activity feature.
+ * It indicates whether the DAV:activity-set of another checked-out resource + * associated with the version history of this version-controlled resource + * can have an activity that is in the DAV:activity-set property of this + * checked-out resource. + *
+ * A result of the requirement that an activity must form a single line of + * descent through a given version history is that if multiple checked-out + * resources for a given version history are checked out unreserved into a + * single activity, only the first CHECKIN will succeed. Before another of + * these checked-out resources can be checked in, the user will first have + * to merge into that checked-out resource the latest version selected by + * that activity from that version history, and then modify the + * DAV:predecessor-set of that checked-out resource to identify that version. + *

+ * This property is defined to have the following format: + *

+     * <!ELEMENT unreserved (#PCDATA)>
+     * PCDATA value: boolean
+     * 
+ * @see VersionResource#ACTIVITY_SET + */ + public static final DavPropertyName UNRESERVED = DavPropertyName.create("activity-set", DeltaVConstants.NAMESPACE); + + /** + * DAV:activity-set is a property for a checked-out resource, if the + * server supports the activity feature.
+ * This property determines the DAV:activity-set property of the version that + * results from checking in this resource. + * + * @see VersionResource#ACTIVITY_SET + */ + public static final DavPropertyName ACTIVITY_SET = DavPropertyName.create("activity-set", DeltaVConstants.NAMESPACE); + + /** + * If the 'Version-Controlled-Collection Feature' is supported the + * DAV:eclipsed-set property present on a collection identifies all + * internal members that are not version-controlled and hide a vc internal + * member with the same name. + *

+ * This property is defined to have the following format: + *

+     * <!ELEMENT eclipsed-set (binding-name*)>
+     * <!ELEMENT binding-name (#PCDATA)>
+     * PCDATA value: URL segment
+     * 
+ * + * @see VersionResource#VERSION_CONTROLLED_BINDING_SET + */ + public static final DavPropertyName ECLIPSED_SET = DavPropertyName.create("eclipsed-set", DeltaVConstants.NAMESPACE); + + /** + * If the 'Baseline' feature is supported, DAV:baseline-controlled-collection + * is a required property of any version-controlled resource, that represents + * a 'configuration'. It identifies the collection that contains the + * version-controlled resources whose versions are tracked by this + * configuration. + *

+ * This property is defined to have the following format: + *

+     * <!ELEMENT baseline-controlled-collection (href)>
+     * 
+ * Note that the DAV:baseline-controlled-collection represents a + * {@link org.apache.jackrabbit.webdav.property.HrefProperty HrefProperty} + * + * @see DeltaVConstants#VERSION_CONTROLLED_CONFIGURATION for the corresponding + * property, that is required for all resources that are contained in this + * version-controlled-configuration. + */ + public static final DavPropertyName BASELINE_CONTROLLED_COLLECTION = DavPropertyName.create("baseline-controlled-collection", DeltaVConstants.NAMESPACE); + + /** + * This property is mandatory for all checked-out version-controlled-configuration + * resources. It determines the DAV:subbaseline-set property of the baseline + * that results from checking in this resource. + *

+ * This property is defined to have the following format: + *

+     * <!ELEMENT subbaseline-set (href*)>
+     * 
+ * Note that the DAV:baseline-controlled-collection represents a + * {@link org.apache.jackrabbit.webdav.property.HrefProperty HrefProperty} + * @see BaselineResource#SUBBASELINE_SET + */ + public static final DavPropertyName SUBBASELINE_SET = DavPropertyName.create("subbaseline-set", DeltaVConstants.NAMESPACE); + + /** + * Perform a checkin on the version controlled resource. + * + * @return String representing the location of the version created by the + * checkin. + * @throws DavException if an error occurs. + */ + public String checkin() throws DavException; + + /** + * Perform a checkout on the version controlled resource. + * + * @throws DavException + */ + public void checkout() throws DavException; + + /** + * Perform an uncheckout on the version controlled resource. + * + * @throws DavException + */ + public void uncheckout() throws DavException; + + /** + * Perform an update on this resource using the specified {@link UpdateInfo}. + * + * @param updateInfo + * @return MultiStatus containing the list of resources that + * have been modified by this update call. + * @throws DavException + */ + public MultiStatus update(UpdateInfo updateInfo) throws DavException; + + /** + * Perform a merge on this resource using the specified {@link MergeInfo}. + * + * @param mergeInfo + * @return MultiStatus containing the list of resources that + * have been modified. + * @throws DavException + */ + public MultiStatus merge(MergeInfo mergeInfo) throws DavException; + + /** + * Modify the labels of the version referenced by the DAV:checked-in property + * of this checked-in version-controlled resource. If the resource is not + * checked-in the request must fail. + * + * @param labelInfo + * @throws org.apache.jackrabbit.webdav.DavException + * @see LabelInfo + * @see VersionResource#label(LabelInfo) for the pre- and postcondition of + * a successful LABEL request. + */ + public void label(LabelInfo labelInfo) throws DavException; + + /** + * Returns the VersionHistoryResource, that is referenced in the + * '{@link #VERSION_HISTORY version-history}' property. + * + * @return + * @throws DavException + */ + public VersionHistoryResource getVersionHistory() throws DavException; +} \ No newline at end of file Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/VersionControlledResource.java ___________________________________________________________________ Added: svn Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/VersionHistoryResource.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/VersionHistoryResource.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/VersionHistoryResource.java (working copy) @@ -0,0 +1,73 @@ +/* + * 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.webdav.version; + +import org.apache.jackrabbit.webdav.DavException; +import org.apache.jackrabbit.webdav.property.DavPropertyName; +import org.apache.jackrabbit.webdav.property.ResourceType; + +/** + * VersionHistoryResource represents a collection that has + * all versions of a given version-controlled resource as members. + *

+ * RFC 3253 defines the following required properties for a version history: + *

    + *
  • DAV:version-set
  • + *
  • DAV:root-version
  • + *
  • all DeltaV-compliant resource properties.
  • + *
+ *

+ * In addition a version history resource must support the following METHODS: + *

    + *
  • all DeltaV-compliant resource METHODS.
  • + *
+ * + * NOTE: the {@link org.apache.jackrabbit.webdav.DavConstants#PROPERTY_RESOURCETYPE DAV:resourcetype} + * property must indicate 'DAV:version-history'. + * + * @see DeltaVResource + * @see ResourceType#VERSION_HISTORY + */ +public interface VersionHistoryResource extends DeltaVResource { + + // supported METHODS: same as DeltaVResource > set to empty string + public static final String METHODS = ""; + + /** + * Computed (protected) property identifying the root version of this version + * history. + */ + public static final DavPropertyName ROOT_VERSION = DavPropertyName.create("root-version", DeltaVConstants.NAMESPACE); + + /** + * The protected property DAV:version-set identifies each version of this + * version history. + * + * @see #getVersions() + */ + public static final DavPropertyName VERSION_SET = DavPropertyName.create("version-set", DeltaVConstants.NAMESPACE); + + /** + * Returns an array of VersionResources containing all versions + * that are a member of this resource. + * + * @return all VersionResources that belong to this version history. + * @throws org.apache.jackrabbit.webdav.DavException + * @see #VERSION_SET + */ + public VersionResource[] getVersions() throws DavException; +} \ No newline at end of file Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/VersionHistoryResource.java ___________________________________________________________________ Added: svn Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/VersionResource.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/VersionResource.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/VersionResource.java (working copy) @@ -0,0 +1,213 @@ +/* + * 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.webdav.version; + +import org.apache.jackrabbit.webdav.DavException; +import org.apache.jackrabbit.webdav.property.DavPropertyName; + +/** + * VersionResource is a resource that contains a copy of a particular + * state of a version-controlled resource. A new version resource is created whenever + * a checked-out version-controlled resource is checked-in. The server allocates + * a distinct new URL for each new version, and this URL will never be used to + * identify any resource other than that version. The content and dead properties + * of a version never change. + *

+ * RFC 3253 defines the following required properties for a version resource: + *

    + *
  • DAV:predecessor-set (protected)
  • + *
  • DAV:successor-set (computed)
  • + *
  • DAV:checkout-set
  • + *
  • DAV:version-name
  • + *
  • DAV:checkout-fork (in-place-checkout or working resource)
  • + *
  • DAV:checkin-fork (in-place-checkout or working resource)
  • + *
  • DAV:version-history (version-history)
  • + *
  • DAV:label-name-set (label)
  • + *
  • DAV:activity-set (activity)
  • + *
  • all DeltaV-compliant resource properties.
  • + *
+ * + * If the 'Version-Controlled-Collection Feature' is supported (see section 14 + * of RFC 3253) the following protected property is defined for a version + * resource associated with a version-controlled collection. + *
    + *
  • DAV:version-controlled-binding-set
  • + *
+ * + *

+ * In addition a version resource must support the following METHODS: + *

    + *
  • LABEL (label)
  • + *
  • CHECKOUT (working-resource)
  • + *
  • all DeltaV-compliant resource METHODS.
  • + *
+ * + * @see DeltaVResource + */ +public interface VersionResource extends DeltaVResource { + + /** + * The version resource defines one additional method LABEL. + * + * @see DeltaVResource#METHODS + * @see org.apache.jackrabbit.webdav.DavResource#METHODS + */ + public String METHODS = "LABEL"; + + /** + * Required protected property 'DAV:label-name-set' for a version of a webdav + * resource introduced with the 'LabelInfo' feature. + * This property contains the labels that currently select this version.
+ * Property structure is defined as follows:
+ *
+     * <!ELEMENT label-name-set (label-name*)>
+     * <!ELEMENT label-name (#PCDATA)>
+     * PCDATA value: string
+     * 
+ */ + public static final DavPropertyName LABEL_NAME_SET = DavPropertyName.create("label-name-set", DeltaVConstants.NAMESPACE); + + /** + * The protected DAV:predecessor property identifies each predecessor of + * this version. Except for the root version, which has no predecessors, + * each version has at least one predecessor.
+ * The property is defined to have the following format: + *
+     * <!ELEMENT predecessor-set (href*)>
+     * 
+ */ + public static final DavPropertyName PREDECESSOR_SET = DavPropertyName.create("predecessor-set", DeltaVConstants.NAMESPACE); + + /** + * The computed property DAV:successor-set identifies each version whose + * DAV:predecessor-set identifies this version.
+ * The property is defined to have the following format: + *
+     * <!ELEMENT successor-set (href*)>
+     * 
+ * + */ + public static final DavPropertyName SUCCESSOR_SET = DavPropertyName.create("successor-set", DeltaVConstants.NAMESPACE); + + /** + * The computed property DAV:checkout-set identifies each checked-out + * resource whose DAV:checked-out property identifies this version.
+ * The property is defined to have the following format: + *
+     * <!ELEMENT checkout-set (href*)>
+     * 
+ * + * @see VersionControlledResource#CHECKED_OUT + */ + public static final DavPropertyName CHECKOUT_SET = DavPropertyName.create("checkout-set", DeltaVConstants.NAMESPACE); + + /** + * The protected property DAV:version-name defines a human readable id for + * this version. The id defined to be unique within the version-history this + * version belongs to.
+ * The property is defined to have the following format: + *
+     * <!ELEMENT version-name (#PCDATA)>
+     * PCDATA value: string
+     * 
+ */ + public static final DavPropertyName VERSION_NAME = DavPropertyName.create("version-name", DeltaVConstants.NAMESPACE); + + /** + * The computed property DAV:version-history identifies the version history + * that contains this version.
+ * The property is defined to have the following format: + *
+     * <!ELEMENT version-history (href)>
+     * 
+ */ + public static final DavPropertyName VERSION_HISTORY = DavPropertyName.create("version-history", DeltaVConstants.NAMESPACE); + + /** + * This property controls the behavior of CHECKOUT when a version already + * is checked out or has a successor. + */ + public static final DavPropertyName CHECKOUT_FORK = DavPropertyName.create("checkout-fork", DeltaVConstants.NAMESPACE); + + /** + * This property controls the behavior of CHECKIN when a version already + * has a successor. + */ + public static final DavPropertyName CHECKIN_FORK = DavPropertyName.create("checkin-fork", DeltaVConstants.NAMESPACE); + + /** + * DAV:activity-set is a required property for a version resource, if the + * server supports the activity feature.
+ * It identifies the activities that determine to which logical changes this + * version contributes, and on which lines of descent this version appears. + * A server MAY restrict the DAV:activity-set to identify a single activity. + * A server MAY refuse to allow the value of the DAV:activity-set property + * of a version to be modified. + *

+ * The property is defined to have the following format: + *

+     * <!ELEMENT activity-set (href*)>
+     * 
+ * Note that the DAV:activity-set represents a + * {@link org.apache.jackrabbit.webdav.property.HrefProperty HrefProperty} + */ + public static final DavPropertyName ACTIVITY_SET = DavPropertyName.create("activity-set", DeltaVConstants.NAMESPACE); + + /** + * If the 'Version-Controlled-Collection Feature' is supported the + * DAV:version-controlled-binding-set property identifies the name and the + * version history of all version-controlled internal members of the + * collection this version resource belongs to. + *

+ * This property is defined to have the following format: + *

+     * <!ELEMENT version-controlled-binding-set (version-controlled-binding*)>
+     * <!ELEMENT version-controlled-binding (binding-name, version-history)>
+     * <!ELEMENT binding-name (#PCDATA)>
+     * PCDATA value: URL segment
+     * <!ELEMENT version-history (href)>
+     * 
+ * + * @see VersionControlledResource#ECLIPSED_SET + */ + public static final DavPropertyName VERSION_CONTROLLED_BINDING_SET = DavPropertyName.create("version-controlled-binding-set", DeltaVConstants.NAMESPACE); + + /** + * Modify the labels of this version resource. The modifications (SET, ADD or + * REMOVE) are listed in the specified LabelInfo object.
+ * The case of a label name must be preserved when it is stored and retrieved. + *
If the type of modification is ADD, then the label must not yet occur on + * any other version within the same version history. In contrast a SET + * modification will move the indicated label to this version, if it existed + * with another version before. After a successful LABEL request the label + * must not appear with any other version in the same version history. + * + * @param labelInfo + * @throws org.apache.jackrabbit.webdav.DavException + * @see LabelInfo + */ + public void label(LabelInfo labelInfo) throws DavException; + + /** + * Returns the VersionHistoryResource, that is referenced in the + * {@link #VERSION_HISTORY DAV:version-history} property. + * + * @return + * @throws DavException + */ + public VersionHistoryResource getVersionHistory() throws DavException; +} \ No newline at end of file Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/VersionResource.java ___________________________________________________________________ Added: svn Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/VersionableResource.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/VersionableResource.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/VersionableResource.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.webdav.version; + +import org.apache.jackrabbit.webdav.DavException; + +/** + * VersionableResource represents an extension to the basic + * {@link DeltaVResource}, that allows to adding version-control support. By + * calling {@link #addVersionControl()} resource is put under version control, + * thus the versionable resource turns into a version controlled resource. + *

+ * RFC 3253 defines the following required properties for a versionable resource: + *

    + *
  • {@link DeltaVConstants#WORKSPACE DAV:workspace} (workspace feature)
  • + *
  • DAV:version-controlled-configuration (baseline feature)
  • + *
  • all DeltaV-compliant resource properties
  • + *
+ *

+ * In addition a versionable resource must support the following METHODS: + *

    + *
  • VERSION-CONTROL
  • + *
  • all DeltaV-compliant resource METHODS.
  • + *
+ * + * @see DeltaVResource + */ +public interface VersionableResource extends DeltaVResource { + + /** + * The versionable resource defines one additional method VERSION-CONTROL. + * + * @see DeltaVResource#METHODS + * @see org.apache.jackrabbit.webdav.DavResource#METHODS + */ + public String METHODS = "VERSION-CONTROL"; + + /** + * Converts this versionable resource into a version-controlled resource. If + * this resource is already version-controlled this resource is not affected. + * If however, this resource is not versionable an DavException + * (error code: {@link org.apache.jackrabbit.webdav.DavServletResponse#SC_METHOD_NOT_ALLOWED} + * is thrown. The same applies, if this resource is versionable but its + * current state does not allow to made it a version-controlled one or + * if any other error occurs. + * + * @throws org.apache.jackrabbit.webdav.DavException + */ + public void addVersionControl() throws DavException; +} \ No newline at end of file Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/VersionableResource.java ___________________________________________________________________ Added: svn Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/WorkspaceResource.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/WorkspaceResource.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/WorkspaceResource.java (working copy) @@ -0,0 +1,94 @@ +/* + * 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.webdav.version; + +import org.apache.jackrabbit.webdav.property.DavPropertyName; + +/** + * A workspace resource is a collection whose members are related + * version-controlled and non-version-controlled resources. + * + *

+ * RFC 3253 defines the following required live properties for an Workspace + * resource. + *

    + *
  • all DeltaV-compliant resource properties
  • + *
  • {@link #WORKSPACE_CHECKOUT_SET DAV:workspace-checkout-set}
  • + *
  • {@link #BASELINE_CONTROLLED_COLLECTION_SET DAV:baseline-controlled-collection-set} (baseline)
  • + *
  • {@link #CURRENT_ACTIVITY_SET DAV:current-activity-set} (activity)
  • + *
+ * Note, that RFC 3253 doesn't define a separate resource type for a workspace. + *

+ * The workspace resource must support all methods defined for a DeltaV-compliant + * collection. Since no additional methods are required for a workspace this + * interface mainly acts as marker. + *

+ * Please refer to RFC 3253 + * Section 6 for a complete description of this resource type. + */ +public interface WorkspaceResource extends DeltaVResource { + + /** + * The DAV:workspace-checkout-set property is the only required property + * which is additionally added to a workspace resource.
+ * This computed property identifies each checked-out resource whose + * DAV:workspace property identifies this workspace. + *

+ * Note that the DAV:workspace-checkout-set represents a + * {@link org.apache.jackrabbit.webdav.property.HrefProperty HrefProperty}. + */ + public static final DavPropertyName WORKSPACE_CHECKOUT_SET = DavPropertyName.create("workspace-checkout-set", DeltaVConstants.NAMESPACE); + + /** + * @deprecated Use {@link #CURRENT_ACTIVITY_SET} instead. + */ + public static final DavPropertyName CUURENT_ACTIVITY_SET = DavPropertyName.create("current-activity-set", DeltaVConstants.NAMESPACE); + + /** + * DAV:current-activity-set is a required property for a workspace resource, + * if the server supports the activity feature.
+ * It identifies the activities that currently are being performed in this + * workspace. When a member of this workspace is checked out, if no activity + * is specified in the checkout request, the DAV:current-activity-set will + * be used. This allows an activity-unaware client to update a workspace in + * which activity tracking is required. The DAV:current-activity-set MAY be + * restricted to identify at most one activity. + *

+ * The property is defined to have the following format: + *

+     * <!ELEMENT current-activity-set (href*)>
+     * 
+ * Note that the DAV:current-activity-set represents a + * {@link org.apache.jackrabbit.webdav.property.HrefProperty HrefProperty} + */ + public static final DavPropertyName CURRENT_ACTIVITY_SET = DavPropertyName.create("current-activity-set", DeltaVConstants.NAMESPACE); + + /** + * The Baseline feature (section 12) defines the following computed property + * for a workspace resource: DAV:baseline-controlled-collection-set lists + * all collections of this workspace, that are under baseline control. This + * list may include the workspace itself. + *

+ * The property is defined to have the following format: + *

+     * <!ELEMENT baseline-controlled-collection-set (href*)>
+     * 
+ * Note that the DAV:baseline-controlled-collection-set represents a + * {@link org.apache.jackrabbit.webdav.property.HrefProperty HrefProperty} + */ + public static final DavPropertyName BASELINE_CONTROLLED_COLLECTION_SET = DavPropertyName.create("baseline-controlled-collection-set", DeltaVConstants.NAMESPACE); +} \ No newline at end of file Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/WorkspaceResource.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-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/package-info.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/package-info.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/package-info.java (working copy) @@ -0,0 +1,18 @@ +/* + * 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. + */ +@org.osgi.annotation.versioning.Version("1.0.0") +package org.apache.jackrabbit.webdav.version; Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/package-info.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/report/AbstractReport.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/report/AbstractReport.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/report/AbstractReport.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.webdav.version.report; + +import org.apache.jackrabbit.webdav.WebdavRequest; +import org.apache.jackrabbit.webdav.WebdavRequestContext; +import org.apache.jackrabbit.webdav.server.WebdavRequestContextHolder; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Abstract Report. + */ +public abstract class AbstractReport implements Report { + + private static Logger log = LoggerFactory.getLogger(AbstractReport.class); + + /** + * Normalize the resource {@code href}. For example, remove contextPath prefix if found. + * @param href resource href + * @return normalized resource {@code href} + */ + protected String normalizeResourceHref(final String href) { + if (href == null) { + return href; + } + + final WebdavRequestContext requestContext = WebdavRequestContextHolder.getContext(); + final WebdavRequest request = (requestContext != null) ? requestContext.getRequest() : null; + + if (request == null) { + log.error("WebdavRequest is unavailable in the current execution context."); + return href; + } + + final String contextPath = request.getContextPath(); + + if (!contextPath.isEmpty() && href.startsWith(contextPath)) { + return href.substring(contextPath.length()); + } + + return href; + } + +} \ No newline at end of file Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/report/AbstractReport.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/report/CompareBaselineReport.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/report/CompareBaselineReport.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/report/CompareBaselineReport.java (working copy) @@ -0,0 +1,188 @@ +/* + * 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.webdav.version.report; + +import java.util.ArrayList; +import java.util.List; + +import org.apache.jackrabbit.webdav.DavConstants; +import org.apache.jackrabbit.webdav.DavException; +import org.apache.jackrabbit.webdav.DavResource; +import org.apache.jackrabbit.webdav.DavResourceIterator; +import org.apache.jackrabbit.webdav.DavResourceLocator; +import org.apache.jackrabbit.webdav.DavServletResponse; +import org.apache.jackrabbit.webdav.property.HrefProperty; +import org.apache.jackrabbit.webdav.version.BaselineResource; +import org.apache.jackrabbit.webdav.version.DeltaVConstants; +import org.apache.jackrabbit.webdav.version.VersionControlledResource; +import org.apache.jackrabbit.webdav.version.VersionResource; +import org.apache.jackrabbit.webdav.xml.DomUtil; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +/** + * CompareBaselineReport... + */ +public class CompareBaselineReport extends AbstractReport { + + private static Logger log = LoggerFactory.getLogger(CompareBaselineReport.class); + + private static final String XML_COMPARE_BASELINE = "compare-baseline"; + private static final String XML_COMPARE_BASELINE_REPORT = "compare-baseline-report"; + private static final String XML_ADDED_VERSION = "added-version"; + private static final String XML_DELETED_VERSION = "deleted-version"; + private static final String XML_CHANGED_VERSION = "changed-version"; + + public static final ReportType COMPARE_BASELINE = ReportType.register(XML_COMPARE_BASELINE, DeltaVConstants.NAMESPACE, CompareBaselineReport.class); + + private BaselineResource requestBaseline; + private BaselineResource compareBaseline; + + /** + * Returns {@link #COMPARE_BASELINE}. + * + * @see Report#getType() + */ + public ReportType getType() { + return COMPARE_BASELINE; + } + + /** + * Always returns false. + * + * @return false + * @see Report#isMultiStatusReport() + */ + public boolean isMultiStatusReport() { + return false; + } + + /** + * + * @param resource + * @param info + * @throws DavException + * @see Report#init(DavResource, ReportInfo) + */ + public void init(DavResource resource, ReportInfo info) throws DavException { + // validate info + if (!getType().isRequestedReportType(info)) { + throw new DavException(DavServletResponse.SC_BAD_REQUEST, "DAV:compare-baseline element expected."); + } + + // make sure the report is applied to a version history resource + if (resource != null && (resource instanceof BaselineResource)) { + this.requestBaseline = (BaselineResource) resource; + } else { + throw new DavException(DavServletResponse.SC_BAD_REQUEST, "DAV:compare-baseline report can only be created for a baseline resource."); + } + + // make sure the DAV:href element inside the request body points to + // an baseline resource (precondition for this report). + String compareHref = normalizeResourceHref(DomUtil.getText(info.getContentElement(DavConstants.XML_HREF, DavConstants.NAMESPACE))); + DavResourceLocator locator = resource.getLocator(); + DavResourceLocator compareLocator = locator.getFactory().createResourceLocator(locator.getPrefix(), compareHref); + + DavResource compRes = resource.getFactory().createResource(compareLocator, resource.getSession()); + if (compRes instanceof BaselineResource) { + compareBaseline = (BaselineResource) compRes; + } else { + throw new DavException(DavServletResponse.SC_BAD_REQUEST, "DAV:latest-activity-version report: The DAV:href in the request body MUST identify an activity."); + } + + // TODO: eventually add check for 'same-baseline-history' (RFC: "A server MAY require that the baselines being compared be from the same baseline history.") + } + + /** + * @see org.apache.jackrabbit.webdav.xml.XmlSerializable#toXml(Document) + */ + public Element toXml(Document document) { + Element el = DomUtil.createElement(document, XML_COMPARE_BASELINE_REPORT, DeltaVConstants.NAMESPACE); + try { + // TODO: check if correct + List requestVs = new ArrayList(); + getVersions(requestBaseline.getBaselineCollection(), requestVs); + + List compareVs = new ArrayList(); + getVersions(compareBaseline.getBaselineCollection(), compareVs); + + for (VersionResource requestV : requestVs) { + if (!compareVs.remove(requestV)) { + // check if another version of the same vh is present (change) + VersionResource changedV = findChangedVersion(requestV, compareVs); + if (changedV != null) { + // found a 'changed-version' entry + Element cv = DomUtil.addChildElement(el, XML_CHANGED_VERSION, DeltaVConstants.NAMESPACE); + cv.appendChild(DomUtil.hrefToXml(requestV.getHref(), document)); + cv.appendChild(DomUtil.hrefToXml(changedV.getHref(), document)); + } else { + // no corresponding version => 'deleted-version' + Element cv = DomUtil.addChildElement(el, XML_DELETED_VERSION, DeltaVConstants.NAMESPACE); + cv.appendChild(DomUtil.hrefToXml(requestV.getHref(), document)); + } + + } // else: both baseline contain a vc-resource with the same checked-in version + } + + // all remaining versions from the 'compare-baseline' can be considered + // to be added-versions. + for (VersionResource addedV : compareVs) { + Element cv = DomUtil.addChildElement(el, XML_ADDED_VERSION, DeltaVConstants.NAMESPACE); + cv.appendChild(DomUtil.hrefToXml(addedV.getHref(), document)); + } + } catch (DavException e) { + log.error("Internal error while building report", e); + } + return el; + } + + private void getVersions(DavResource collection, List vList) throws DavException { + DavResourceIterator it = collection.getMembers(); + while (it.hasNext()) { + DavResource member = it.nextResource(); + if (member instanceof VersionControlledResource) { + String href = new HrefProperty(member.getProperty(VersionControlledResource.CHECKED_IN)).getHrefs().get(0); + DavResourceLocator locator = member.getLocator(); + DavResourceLocator vLocator = locator.getFactory().createResourceLocator(locator.getPrefix(), href); + + DavResource v = member.getFactory().createResource(vLocator, member.getSession()); + if (v instanceof VersionResource) { + vList.add((VersionResource) v); + } else { + log.error("Internal error: DAV:checked-in property must point to a VersionResource."); + } + } + if (member.isCollection()) { + getVersions(member, vList); + } + } + } + + private VersionResource findChangedVersion(VersionResource requestV, List compareVs) throws DavException { + VersionResource[] vs = requestV.getVersionHistory().getVersions(); + for (VersionResource v : vs) { + if (compareVs.remove(v)) { + // another version of the same versionhistory is present among + // the compare-baseline versions. + return v; + } + } + return null; + } +} Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/report/CompareBaselineReport.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-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/report/ExpandPropertyReport.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/report/ExpandPropertyReport.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/report/ExpandPropertyReport.java (working copy) @@ -0,0 +1,266 @@ +/* + * 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.webdav.version.report; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import org.apache.jackrabbit.webdav.DavException; +import org.apache.jackrabbit.webdav.DavResource; +import org.apache.jackrabbit.webdav.DavResourceIterator; +import org.apache.jackrabbit.webdav.DavServletResponse; +import org.apache.jackrabbit.webdav.MultiStatus; +import org.apache.jackrabbit.webdav.MultiStatusResponse; +import org.apache.jackrabbit.webdav.property.AbstractDavProperty; +import org.apache.jackrabbit.webdav.property.DavProperty; +import org.apache.jackrabbit.webdav.property.DavPropertyName; +import org.apache.jackrabbit.webdav.property.HrefProperty; +import org.apache.jackrabbit.webdav.version.DeltaVConstants; +import org.apache.jackrabbit.webdav.version.DeltaVResource; +import org.apache.jackrabbit.webdav.xml.DomUtil; +import org.apache.jackrabbit.webdav.xml.ElementIterator; +import org.apache.jackrabbit.webdav.xml.Namespace; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +/** + * ExpandPropertyReport encapsulates the DAV:expand-property report, + * that provides a mechanism for retrieving in one request the properties from + * the resources identified by those DAV:href elements. It should be supported by + * all resources that support the REPORT method. + *

+ * RFC 3253 specifies the following required format for the request body: + *

+ * <!ELEMENT expand-property (property*)>
+ * <!ELEMENT property (property*)>
+ * <!ATTLIST property name NMTOKEN #REQUIRED>
+ * name value: a property element type
+ * <!ATTLIST property namespace NMTOKEN "DAV:">
+ * namespace value: an XML namespace
+ * 
+ * NOTE: any DAV:property elements defined in the request body, that does not + * represent {@link HrefProperty} is treated as in a common PROPFIND request. + * + * @see DeltaVConstants#XML_EXPAND_PROPERTY + * @see DeltaVConstants#XML_PROPERTY + */ +public class ExpandPropertyReport extends AbstractReport implements DeltaVConstants { + + private static Logger log = LoggerFactory.getLogger(ExpandPropertyReport.class); + + private DavResource resource; + private ReportInfo info; + private Iterator propertyElements; + + /** + * Returns {@link ReportType#EXPAND_PROPERTY}. + * + * @return + * @see Report#getType() + */ + public ReportType getType() { + return ReportType.EXPAND_PROPERTY; + } + + /** + * Always returns true. + * + * @return true + * @see org.apache.jackrabbit.webdav.version.report.Report#isMultiStatusReport() + */ + public boolean isMultiStatusReport() { + return true; + } + + /** + * @see Report#init(DavResource, ReportInfo) + */ + public void init(DavResource resource, ReportInfo info) throws DavException { + setResource(resource); + setInfo(info); + } + + /** + * Set the target resource. + * + * @param resource + * @throws DavException if the specified resource is null + */ + private void setResource(DavResource resource) throws DavException { + if (resource == null) { + throw new DavException(DavServletResponse.SC_BAD_REQUEST, "The resource specified must not be null."); + } + this.resource = resource; + } + + /** + * Set the ReportInfo. + * + * @param info + * @throws DavException if the given ReportInfo + * does not contain a DAV:expand-property element. + */ + private void setInfo(ReportInfo info) throws DavException { + if (info == null) { + throw new DavException(DavServletResponse.SC_BAD_REQUEST, "The report info specified must not be null."); + } + if (!getType().isRequestedReportType(info)) { + throw new DavException(DavServletResponse.SC_BAD_REQUEST, "DAV:expand-property element expected."); + } + this.info = info; + propertyElements = info.getContentElements(XML_PROPERTY, NAMESPACE).iterator(); + } + + /** + * Run the report + * + * @return Xml Document as defined by + * RFC 2518 + * @see org.apache.jackrabbit.webdav.xml.XmlSerializable#toXml(Document) + * @param document + */ + public Element toXml(Document document) { + return getMultiStatus().toXml(document); + } + + /** + * Retrieve the multistatus object that is returned in response to the + * expand-property report request. + * + * @return + * @throws NullPointerException if info and resource have not been set. + */ + private MultiStatus getMultiStatus() { + MultiStatus ms = new MultiStatus(); + addResponses(resource, info.getDepth(), ms); + return ms; + } + + /** + * Fills the specified MultiStatus object by generating a + * MultiStatusResponse for the given resource (and + * its member according to the depth value). + * + * @param res + * @param depth + * @param ms + * @see #getResponse(DavResource, Iterator) + */ + private void addResponses(DavResource res, int depth, MultiStatus ms) { + MultiStatusResponse response = getResponse(res, propertyElements); + ms.addResponse(response); + if (depth > 0 && res.isCollection()) { + DavResourceIterator it = res.getMembers(); + while (it.hasNext()) { + addResponses(it.nextResource(), depth-1, ms); + } + } + } + + /** + * Builds a MultiStatusResponse for the given resource respecting + * the properties specified. Any property that represents a {@link HrefProperty} + * is expanded: It's name equals the name of a valid {@link HrefProperty}. + * However the value of that given property (consisting of one or multiple DAV:href elements) + * is replaced by the Xml representation of a separate + * {@link MultiStatusResponse multistatus responses} for the + * resource referenced by the given DAV:href elements. The responses may + * themselves have properties, which are defined by the separate list. + * + * @param res + * @param propertyElements + * @return MultiStatusResponse for the given resource. + * @see ExpandProperty + */ + private MultiStatusResponse getResponse(DavResource res, Iterator propertyElements) { + MultiStatusResponse resp = new MultiStatusResponse(res.getHref(), null); + while (propertyElements.hasNext()) { + Element propertyElem = propertyElements.next(); + // retrieve the localName present in the "name" attribute + String nameAttr = propertyElem.getAttribute(ATTR_NAME); + if (nameAttr == null || "".equals(nameAttr)) { + // NOTE: this is not valid according to the DTD + continue; + } + // retrieve the namespace present in the "namespace" attribute + // NOTE: if this attribute is missing the DAV: namespace represents the default. + String namespaceAttr = propertyElem.getAttribute(ATTR_NAMESPACE); + Namespace namespace = (namespaceAttr != null) ? Namespace.getNamespace(namespaceAttr) : NAMESPACE; + + DavPropertyName propName = DavPropertyName.create(nameAttr, namespace); + DavProperty p = res.getProperty(propName); + if (p != null) { + if (p instanceof HrefProperty && res instanceof DeltaVResource) { + ElementIterator it = DomUtil.getChildren(propertyElem, XML_PROPERTY, NAMESPACE); + resp.add(new ExpandProperty((DeltaVResource)res, (HrefProperty)p, it)); + } else { + resp.add(p); + } + } else { + resp.add(propName, DavServletResponse.SC_NOT_FOUND); + } + } + return resp; + } + + //--------------------------------------------------------< inner class >--- + /** + * ExpandProperty extends DavProperty. It's name + * equals the name of a valid {@link HrefProperty}. However the value of + * that given property (consisting of one or multiple DAV:href elements) + * is replaced by the Xml representation of a separate + * {@link MultiStatusResponse multistatus responses} for the + * resource referenced to by the given DAV:href elements. The responses may + * themselves have properties, which are defined by the separate list. + */ + private class ExpandProperty extends AbstractDavProperty> { + + private List valueList = new ArrayList(); + + /** + * Create a new ExpandProperty. + * + * @param hrefProperty + * @param elementIter + */ + private ExpandProperty(DeltaVResource deltaVResource, HrefProperty hrefProperty, ElementIterator elementIter) { + super(hrefProperty.getName(), hrefProperty.isInvisibleInAllprop()); + try { + DavResource[] refResource = deltaVResource.getReferenceResources(hrefProperty.getName()); + for (DavResource res : refResource) { + MultiStatusResponse resp = getResponse(res, elementIter); + valueList.add(resp); + } + } catch (DavException e) { + // invalid references or unknown property + log.error(e.getMessage()); + } + } + + /** + * Returns a List of {@link MultiStatusResponse} objects. + * + * @return + */ + public List getValue() { + return valueList; + } + } +} Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/report/ExpandPropertyReport.java ___________________________________________________________________ Added: svn Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/report/LatestActivityVersionReport.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/report/LatestActivityVersionReport.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/report/LatestActivityVersionReport.java (working copy) @@ -0,0 +1,151 @@ +/* + * 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.webdav.version.report; + +import java.util.List; + +import org.apache.jackrabbit.webdav.DavConstants; +import org.apache.jackrabbit.webdav.DavException; +import org.apache.jackrabbit.webdav.DavResource; +import org.apache.jackrabbit.webdav.DavResourceLocator; +import org.apache.jackrabbit.webdav.DavServletResponse; +import org.apache.jackrabbit.webdav.property.HrefProperty; +import org.apache.jackrabbit.webdav.version.ActivityResource; +import org.apache.jackrabbit.webdav.version.DeltaVConstants; +import org.apache.jackrabbit.webdav.version.VersionHistoryResource; +import org.apache.jackrabbit.webdav.version.VersionResource; +import org.apache.jackrabbit.webdav.xml.DomUtil; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +/** + * LatestActivityVersionReport is applied to a version history to + * identify the latest version that is selected from that version history by a + * given activity. + */ +public class LatestActivityVersionReport extends AbstractReport { + + private static Logger log = LoggerFactory.getLogger(LatestActivityVersionReport.class); + + private static final String XML_LATEST_ACTIVITY_VERSION = "latest-activity-version"; + private static final String XML_LATEST_ACTIVITY_VERSION_REPORT = "latest-activity-version-report"; + + public static final ReportType LATEST_ACTIVITY_VERSION = ReportType.register(XML_LATEST_ACTIVITY_VERSION, DeltaVConstants.NAMESPACE, LatestActivityVersionReport.class); + + private VersionHistoryResource vhResource; + private DavResource activity; + + /** + * Returns {@link #LATEST_ACTIVITY_VERSION}. + * + * @see Report#getType() + */ + public ReportType getType() { + return LATEST_ACTIVITY_VERSION; + } + + /** + * Always returns false. + * + * @return false + * @see Report#isMultiStatusReport() + */ + public boolean isMultiStatusReport() { + return false; + } + + /** + * Check all the preconditions for this report. + * + * @throws DavException if a precondition is not met. + * @see Report#init(DavResource, ReportInfo) + */ + public void init(DavResource resource, ReportInfo info) throws DavException { + // validate info + if (!getType().isRequestedReportType(info)) { + throw new DavException(DavServletResponse.SC_BAD_REQUEST, "DAV:latest-activity-version element expected."); + } + + // make sure the report is applied to a vh-resource + if (resource != null && (resource instanceof VersionHistoryResource)) { + vhResource = (VersionHistoryResource) resource; + } else { + throw new DavException(DavServletResponse.SC_BAD_REQUEST, "DAV:latest-activity-version report can only be created for a version history resource."); + } + + // make sure the DAV:href element inside the request body points to + // an activity resource (precondition for this report). + String activityHref = normalizeResourceHref(DomUtil.getText(info.getContentElement(DavConstants.XML_HREF, DavConstants.NAMESPACE))); + DavResourceLocator vhLocator = resource.getLocator(); + DavResourceLocator activityLocator = vhLocator.getFactory().createResourceLocator(vhLocator.getPrefix(), activityHref); + + activity = resource.getFactory().createResource(activityLocator, resource.getSession()); + if (!(activity instanceof ActivityResource)) { + throw new DavException(DavServletResponse.SC_BAD_REQUEST, "DAV:latest-activity-version report: The DAV:href in the request body MUST identify an activity."); + } + } + + /** + * + * @see org.apache.jackrabbit.webdav.xml.XmlSerializable#toXml(Document) + */ + public Element toXml(Document document) { + String latestVersionHref = getLatestVersionHref(); + + Element el = DomUtil.createElement(document, XML_LATEST_ACTIVITY_VERSION_REPORT, DeltaVConstants.NAMESPACE); + el.appendChild(DomUtil.hrefToXml(latestVersionHref, document)); + return el; + } + + /** + * The latest-version-href MUST identify the version of the given + * version history that is a member of the DAV:activity-version-set of the + * given activity and has no descendant that is a member of the + * DAV:activity-version-set of that activity. + * + * @return href of the latest version or "" + */ + private String getLatestVersionHref() { + String latestVersionHref = ""; // not found (TODO: check if this valid according to the RFC) + try { + List versionHrefs = new HrefProperty(activity.getProperty(ActivityResource.ACTIVITY_VERSION_SET)).getHrefs(); + + for (VersionResource vr : vhResource.getVersions()) { + String href = vr.getHref(); + if (versionHrefs.contains(href)) { + if ("".equals(latestVersionHref)) { + // shortcut + latestVersionHref = href; + } else { + // if this vr is a descendant of the one already found, set latestVersion again + List predecessors = new HrefProperty(vr.getProperty(VersionResource.PREDECESSOR_SET)).getHrefs(); + if (predecessors.contains(latestVersionHref)) { + // version is a descendant of the vr identified by latestVersionHref + latestVersionHref = href; + } // else: version is predecessor -> nothing to do. + } + } + } + + } catch (DavException e) { + log.error("Unexpected error while retrieving href of latest version.", e); + } + return latestVersionHref; + } +} Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/report/LatestActivityVersionReport.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-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/report/LocateByHistoryReport.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/report/LocateByHistoryReport.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/report/LocateByHistoryReport.java (working copy) @@ -0,0 +1,175 @@ +/* + * 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.webdav.version.report; + +import java.util.HashSet; +import java.util.Set; + +import org.apache.jackrabbit.webdav.DavConstants; +import org.apache.jackrabbit.webdav.DavException; +import org.apache.jackrabbit.webdav.DavResource; +import org.apache.jackrabbit.webdav.DavResourceIterator; +import org.apache.jackrabbit.webdav.DavServletResponse; +import org.apache.jackrabbit.webdav.MultiStatus; +import org.apache.jackrabbit.webdav.property.DavPropertyNameSet; +import org.apache.jackrabbit.webdav.version.DeltaVConstants; +import org.apache.jackrabbit.webdav.version.VersionControlledResource; +import org.apache.jackrabbit.webdav.version.VersionHistoryResource; +import org.apache.jackrabbit.webdav.xml.DomUtil; +import org.apache.jackrabbit.webdav.xml.ElementIterator; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +/** + * LocateByHistoryReport encapsulates the DAV:locate-by-hisotry + * report, that may be used to locate a version-controlled resource for that + * version history. The DAV:locate-by-history report can be applied to a collection + * to locate the collection member that is a version-controlled resource for a + * specified version history resource. + * + *
+ * <!ELEMENT locate-by-history (version-history-set, prop)>
+ * <!ELEMENT version-history-set (href+)>
+ * 
+ */ +public class LocateByHistoryReport extends AbstractReport implements DeltaVConstants { + + private static Logger log = LoggerFactory.getLogger(LocateByHistoryReport.class); + + private ReportInfo info; + private Set vhHrefSet = new HashSet(); + private DavResource resource; + + /** + * Returns {@link ReportType#LOCATE_BY_HISTORY}. + * + * @see Report#getType() + */ + public ReportType getType() { + return ReportType.LOCATE_BY_HISTORY; + } + + /** + * @see Report#init(DavResource, ReportInfo) + */ + public void init(DavResource resource, ReportInfo info) throws DavException { + if (resource == null || !(resource instanceof VersionControlledResource)) { + throw new DavException(DavServletResponse.SC_BAD_REQUEST, "DAV:version-tree report can only be created for version-controlled resources and version resources."); + } + this.resource = resource; + setInfo(info); + } + + /** + * Set the ReportInfo + * + * @param info + * @throws DavException if the given ReportInfo + * does not contain a DAV:version-tree element. + */ + private void setInfo(ReportInfo info) throws DavException { + if (info == null || !getType().isRequestedReportType(info)) { + throw new DavException(DavServletResponse.SC_BAD_REQUEST, "DAV:locate-by-history element expected."); + } + Element versionHistorySet = info.getContentElement(XML_VERSION_HISTORY_SET, NAMESPACE); + if (versionHistorySet == null) { + throw new DavException(DavServletResponse.SC_BAD_REQUEST, "The DAV:locate-by-history element must contain a DAV:version-history-set child."); + } + ElementIterator it = DomUtil.getChildren(versionHistorySet, DavConstants.XML_HREF, DavConstants.NAMESPACE); + while (it.hasNext()) { + String href = DomUtil.getText(it.nextElement()); + if (href != null) { + vhHrefSet.add(href); + } + } + this.info = info; + } + + /** + * Always returns true. + * + * @return true + * @see org.apache.jackrabbit.webdav.version.report.Report#isMultiStatusReport() + */ + public boolean isMultiStatusReport() { + return true; + } + + /** + * Run the report. + * + * @return Xml Document representing the report in the required + * format. + * @see org.apache.jackrabbit.webdav.xml.XmlSerializable#toXml(Document) + * @param document + */ + public Element toXml(Document document) { + return getMultiStatus().toXml(document); + } + + /** + * Retrieve the MultiStatus that is returned in response to a locate-by-history + * report request. + * + * @return + * @throws NullPointerException if info or resource is null. + */ + private MultiStatus getMultiStatus() { + MultiStatus ms = new MultiStatus(); + buildResponse(resource, info.getPropertyNameSet(), info.getDepth(), ms); + return ms; + } + + /** + * Fill the MultiStatus with the MultiStatusResponses + * generated for the specified resource and its members according to the + * depth value. + * + * @param res + * @param propNameSet + * @param depth + * @param ms + */ + private void buildResponse(DavResource res, DavPropertyNameSet propNameSet, + int depth, MultiStatus ms) { + // loop over members first, since this report only list members + DavResourceIterator it = res.getMembers(); + while (!vhHrefSet.isEmpty() && it.hasNext()) { + DavResource childRes = it.nextResource(); + if (childRes instanceof VersionControlledResource) { + try { + VersionHistoryResource vhr = ((VersionControlledResource)childRes).getVersionHistory(); + if (vhHrefSet.remove(vhr.getHref())) { + if (propNameSet.isEmpty()) { + ms.addResourceStatus(childRes, DavServletResponse.SC_OK, 0); + } else { + ms.addResourceProperties(childRes, propNameSet, 0); + } + } + } catch (DavException e) { + log.info(e.getMessage()); + } + } + // traverse subtree + if (depth > 0) { + buildResponse(it.nextResource(), propNameSet, depth-1, ms); + } + } + } +} Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/report/LocateByHistoryReport.java ___________________________________________________________________ Added: svn Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/report/Report.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/report/Report.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/report/Report.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.webdav.version.report; + +import org.apache.jackrabbit.webdav.DavException; +import org.apache.jackrabbit.webdav.DavResource; +import org.apache.jackrabbit.webdav.version.DeltaVResource; +import org.apache.jackrabbit.webdav.xml.XmlSerializable; + +/** + * The Report interface defines METHODS needed in order to respond + * to a REPORT request. The REPORT method is a required feature to all + * DeltaV resources. + * + * @see DeltaVResource#getReport(ReportInfo) + */ +public interface Report extends XmlSerializable { + + /** + * Returns the registered type of this report. + * + * @return the type of this report. + */ + public ReportType getType(); + + /** + * Returns true if this Report will send a MultiStatus + * response.
+ * Please note that RFC 3253 that the the response must be a 207 Multi-Status, + * if a Depth request header is present. + * + * @return + */ + public boolean isMultiStatusReport(); + + /** + * Set the DeltaVResource for which this report was requested + * and the ReportInfo as specified by the REPORT request body, + * that defines the details for this report.
+ * Please note that this methods should perform basic validation checks + * in order to prevent exceptional situations during the xml serialization. + * + * @param resource + * @param info + * @throws DavException + */ + public void init(DavResource resource, ReportInfo info) throws DavException; +} \ No newline at end of file Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/report/Report.java ___________________________________________________________________ Added: svn Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/report/ReportInfo.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/report/ReportInfo.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/report/ReportInfo.java (working copy) @@ -0,0 +1,263 @@ +/* + * 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.webdav.version.report; + +import org.apache.jackrabbit.webdav.DavConstants; +import org.apache.jackrabbit.webdav.DavException; +import org.apache.jackrabbit.webdav.DavServletResponse; +import org.apache.jackrabbit.webdav.property.DavPropertyNameSet; +import org.apache.jackrabbit.webdav.xml.DomUtil; +import org.apache.jackrabbit.webdav.xml.ElementIterator; +import org.apache.jackrabbit.webdav.xml.Namespace; +import org.apache.jackrabbit.webdav.xml.XmlSerializable; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.Node; + +import java.util.ArrayList; +import java.util.List; + +/** + * The ReportInfo class encapsulates the body of a REPORT request. + * RFC 3253 the top Xml element + * being the name of the requested report. In addition a Depth header may + * be present (default value: {@link DavConstants#DEPTH_0}). + */ +public class ReportInfo implements XmlSerializable { + + private static Logger log = LoggerFactory.getLogger(ReportInfo.class); + + private final String typeLocalName; + private final Namespace typeNamespace; + private final int depth; + private final DavPropertyNameSet propertyNames; + private final List content = new ArrayList(); + + /** + * Create a new ReportInfo + * + * @param type + */ + public ReportInfo(ReportType type) { + this(type, DavConstants.DEPTH_0, null); + } + + /** + * Create a new ReportInfo + * + * @param type + * @param depth + */ + public ReportInfo(ReportType type, int depth) { + this(type, depth, null); + } + + /** + * Create a new ReportInfo + * + * @param type + * @param depth + * @param propertyNames + */ + public ReportInfo(ReportType type, int depth, DavPropertyNameSet propertyNames) { + this(type.getLocalName(), type.getNamespace(), depth, propertyNames); + } + + /** + * Create a new ReportInfo + * + * @param typeLocalName + * @param typeNamespace + */ + public ReportInfo(String typeLocalName, Namespace typeNamespace) { + this(typeLocalName, typeNamespace, DavConstants.DEPTH_0, null); + } + + /** + * Create a new ReportInfo + * + * @param typelocalName + * @param typeNamespace + * @param depth + * @param propertyNames + */ + public ReportInfo(String typelocalName, Namespace typeNamespace, int depth, DavPropertyNameSet propertyNames) { + this.typeLocalName = typelocalName; + this.typeNamespace = typeNamespace; + this.depth = depth; + if (propertyNames != null) { + this.propertyNames = new DavPropertyNameSet(propertyNames); + } else { + this.propertyNames = new DavPropertyNameSet(); + } + } + + /** + * Create a new ReportInfo object from the given Xml element. + * + * @param reportElement + * @param depth Depth value as retrieved from the {@link DavConstants#HEADER_DEPTH}. + * @throws DavException if the report element is null. + */ + public ReportInfo(Element reportElement, int depth) throws DavException { + if (reportElement == null) { + log.warn("Report request body must not be null."); + throw new DavException(DavServletResponse.SC_BAD_REQUEST); + } + + this.typeLocalName = reportElement.getLocalName(); + this.typeNamespace = DomUtil.getNamespace(reportElement); + this.depth = depth; + Element propElement = DomUtil.getChildElement(reportElement, DavConstants.XML_PROP, DavConstants.NAMESPACE); + if (propElement != null) { + propertyNames = new DavPropertyNameSet(propElement); + reportElement.removeChild(propElement); + } else { + propertyNames = new DavPropertyNameSet(); + } + + ElementIterator it = DomUtil.getChildren(reportElement); + while (it.hasNext()) { + Element el = it.nextElement(); + if (!DavConstants.XML_PROP.equals(el.getLocalName())) { + content.add(el); + } + } + } + + /** + * Returns the depth field. The request must be applied separately to the + * collection itself and to all members of the collection that satisfy the + * depth value. + * + * @return depth + */ + public int getDepth() { + return depth; + } + + /** + * Name of the report type that will be / has been requested. + * + * @return Name of the report type + */ + public String getReportName() { + return DomUtil.getExpandedName(typeLocalName, typeNamespace); + } + + /** + * Indicates whether this info contains an element with the given name/namespace. + * + * @param localName + * @param namespace + * @return true if an element with the given name/namespace is present in the + * body of the request info. + */ + public boolean containsContentElement(String localName, Namespace namespace) { + if (content.isEmpty()) { + return false; + } + for (Element elem : content) { + boolean sameNamespace = (namespace == null) ? elem.getNamespaceURI() == null : namespace.isSame(elem.getNamespaceURI()); + if (sameNamespace && elem.getLocalName().equals(localName)) { + return true; + } + } + return false; + } + + /** + * Retrieves the Xml element with the given name/namespace that is a child + * of this info. If no such child exists null is returned. If + * multiple elements with the same name exist, the first one is returned. + * + * @param localName + * @param namespace + * @return Xml element with the given name/namespace or null + */ + public Element getContentElement(String localName, Namespace namespace) { + List values = getContentElements(localName, namespace); + if (values.isEmpty()) { + return null; + } else { + return values.get(0); + } + } + + /** + * Returns a list containing all child Xml elements of this info that have + * the specified name/namespace. If this info contains no such element, + * an empty list is returned. + * + * @param localName + * @param namespace + * @return List contain all child elements with the given name/namespace + * or an empty list. + */ + public List getContentElements(String localName, Namespace namespace) { + List l = new ArrayList(); + for (Element elem : content) { + if (DomUtil.matches(elem, localName, namespace)) { + l.add(elem); + } + } + return l; + } + + /** + * Add the specified Xml element as child of this info. + * + * @param contentElement + */ + public void setContentElement(Element contentElement) { + content.add(contentElement); + } + + /** + * Returns a DavPropertyNameSet providing the property names present + * in an eventual {@link DavConstants#XML_PROP} child element. If no such + * child element is present an empty set is returned. + * + * @return {@link DavPropertyNameSet} providing the property names present + * in an eventual {@link DavConstants#XML_PROP DAV:prop} child element or an empty set. + */ + public DavPropertyNameSet getPropertyNameSet() { + return propertyNames; + } + + + /** + * @see org.apache.jackrabbit.webdav.xml.XmlSerializable#toXml(Document) + * @param document + */ + public Element toXml(Document document) { + Element reportElement = DomUtil.createElement(document, typeLocalName, typeNamespace); + if (!content.isEmpty()) { + for (Element contentEntry : content) { + Node n = document.importNode(contentEntry, true); + reportElement.appendChild(n); + } + } + if (!propertyNames.isEmpty()) { + reportElement.appendChild(propertyNames.toXml(document)); + } + return reportElement; + } + +} Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/report/ReportInfo.java ___________________________________________________________________ Added: svn Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/report/ReportType.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/report/ReportType.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/report/ReportType.java (working copy) @@ -0,0 +1,190 @@ +/* + * 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.webdav.version.report; + +import org.apache.jackrabbit.webdav.DavException; +import org.apache.jackrabbit.webdav.DavServletResponse; +import org.apache.jackrabbit.webdav.version.DeltaVConstants; +import org.apache.jackrabbit.webdav.version.DeltaVResource; +import org.apache.jackrabbit.webdav.xml.DomUtil; +import org.apache.jackrabbit.webdav.xml.Namespace; +import org.apache.jackrabbit.webdav.xml.XmlSerializable; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +import java.util.HashMap; + +/** + * ReportType... + */ +public class ReportType implements DeltaVConstants, XmlSerializable { + + private static Logger log = LoggerFactory.getLogger(ReportType.class); + + private static final HashMap types = new HashMap(); + + public static final ReportType VERSION_TREE = register(XML_VERSION_TREE, NAMESPACE, VersionTreeReport.class); + public static final ReportType EXPAND_PROPERTY = register(XML_EXPAND_PROPERTY, NAMESPACE, ExpandPropertyReport.class); + public static final ReportType LOCATE_BY_HISTORY = register(XML_LOCATE_BY_HISTORY, NAMESPACE, LocateByHistoryReport.class); + + private final String key; + private final String localName; + private final Namespace namespace; + private final Class reportClass; + + /** + * Private constructor + * + * @see ReportType#register(String, org.apache.jackrabbit.webdav.xml.Namespace, Class) + */ + private ReportType(String localName, Namespace namespace, String key, Class reportClass) { + this.localName = localName; + this.namespace = namespace; + this.key = key; + this.reportClass = reportClass; + } + + /** + * Creates a new {@link Report} with this type. + * + * @return + * @throws DavException + */ + public Report createReport(DeltaVResource resource, ReportInfo info) throws DavException { + try { + Report report = reportClass.newInstance(); + report.init(resource, info); + return report; + } catch (IllegalAccessException e) { + // should never occur + throw new DavException(DavServletResponse.SC_INTERNAL_SERVER_ERROR, "Failed to create new report (" + reportClass.getName() + ") from class: " + e.getMessage()); + } catch (InstantiationException e) { + // should never occur + throw new DavException(DavServletResponse.SC_INTERNAL_SERVER_ERROR, "Failed to create new report (" + reportClass.getName() + ") from class: " + e.getMessage()); + } + } + + /** + * Returns an Xml element representing this report type. It may be used to + * build the body for a REPORT request. + * + * @param document + * @return Xml representation + * @see XmlSerializable#toXml(org.w3c.dom.Document) + */ + public Element toXml(Document document) { + return DomUtil.createElement(document, localName, namespace); + } + + /** + * Returns true if this ReportType is requested by the given + * ReportInfo + * + * @param reqInfo + * @return + */ + public boolean isRequestedReportType(ReportInfo reqInfo) { + if (reqInfo != null) { + return getReportName().equals(reqInfo.getReportName()); + } + return false; + } + + /** + * Return the qualified name of this ReportType. + * + * @return qualified name + */ + public String getReportName() { + return key; + } + + /** + * + * @return + */ + public String getLocalName() { + return localName; + } + + /** + * + * @return + */ + public Namespace getNamespace() { + return namespace; + } + + /** + * Register the report type with the given name, namespace and class, that can + * run that report. + * + * @param localName + * @param namespace + * @param reportClass + * @return + * @throws IllegalArgumentException if either parameter is null or + * if the given class does not implement the {@link Report} interface or if + * it does not provide an empty constructor. + */ + public static ReportType register(String localName, Namespace namespace, Class reportClass) { + if (localName == null || namespace == null || reportClass == null) { + throw new IllegalArgumentException("A ReportType cannot be registered with a null name, namespace or report class"); + } + String key = DomUtil.getExpandedName(localName, namespace); + if (types.containsKey(key)) { + return types.get(key); + } else { + try { + Object report = reportClass.newInstance(); + if (!(report instanceof Report)) { + throw new IllegalArgumentException("Unable to register Report class: " + reportClass + " does not implement the Report interface."); + } + } catch (IllegalAccessException e) { + throw new IllegalArgumentException("Error while validating Report class: " + e.getMessage()); + } catch (InstantiationException e) { + throw new IllegalArgumentException("Error while validating Report class.: " + e.getMessage()); + } + + ReportType type = new ReportType(localName, namespace, key, reportClass); + types.put(key, type); + return type; + } + } + + /** + * Return the ReportType requested by the given report info object. + * + * @param reportInfo + * @return the requested ReportType + * @throws IllegalArgumentException if the reportInfo is null or + * if the requested report type has not been registered yet. + */ + public static ReportType getType(ReportInfo reportInfo) { + if (reportInfo == null) { + throw new IllegalArgumentException("ReportInfo must not be null."); + } + String key = reportInfo.getReportName(); + if (types.containsKey(key)) { + return types.get(key); + } else { + throw new IllegalArgumentException("The request report '"+key+"' has not been registered yet."); + } + } +} Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/report/ReportType.java ___________________________________________________________________ Added: svn Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/report/SupportedReportSetProperty.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/report/SupportedReportSetProperty.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/report/SupportedReportSetProperty.java (working copy) @@ -0,0 +1,119 @@ +/* + * 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.webdav.version.report; + +import org.apache.jackrabbit.webdav.property.AbstractDavProperty; +import org.apache.jackrabbit.webdav.version.DeltaVConstants; +import org.apache.jackrabbit.webdav.xml.DomUtil; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +import java.util.HashSet; +import java.util.Set; + +/** + * SupportedReportSetProperty represents the DAV:supported-report-set + * property defined by RFC 3253. It identifies the reports that are supported by + * the given resource. + *
+ * <!ELEMENT supported-report-set (supported-report*)>
+ * <!ELEMENT supported-report report>
+ * <!ELEMENT report ANY>
+ * ANY value: a report element type
+ * 
+ */ +public class SupportedReportSetProperty extends AbstractDavProperty> { + + private static Logger log = LoggerFactory.getLogger(SupportedReportSetProperty.class); + + private final Set reportTypes = new HashSet(); + + /** + * Create a new empty SupportedReportSetProperty. + */ + public SupportedReportSetProperty() { + super(DeltaVConstants.SUPPORTED_REPORT_SET, true); + } + + /** + * Create a new SupportedReportSetProperty property. + * + * @param reportTypes that are supported by the resource having this property. + */ + public SupportedReportSetProperty(ReportType[] reportTypes) { + super(DeltaVConstants.SUPPORTED_REPORT_SET, true); + for (ReportType reportType : reportTypes) { + addReportType(reportType); + } + } + + /** + * Add an additional report type to this property's value. + * + * @param reportType + */ + public void addReportType(ReportType reportType) { + reportTypes.add(reportType); + } + + /** + * Returns true if the report type indicated in the specified RequestInfo + * object is included in the supported reports. + * + * @param reqInfo + * @return true if the requested report is supported. + */ + public boolean isSupportedReport(ReportInfo reqInfo) { + for (ReportType reportType : reportTypes) { + if (reportType.isRequestedReportType(reqInfo)) { + return true; + } + } + return false; + } + + /** + * Returns a set of report types. + * + * @return set of {@link ReportType}. + * @see org.apache.jackrabbit.webdav.property.DavProperty#getValue() + */ + public Set getValue() { + return reportTypes; + } + + /** + * Returns the Xml representation of this property. + * + * @return Xml representation listing all supported reports + * @see org.apache.jackrabbit.webdav.xml.XmlSerializable#toXml(Document) + * @param document + */ + @Override + public Element toXml(Document document) { + Element elem = getName().toXml(document); + for (ReportType rt : reportTypes) { + Element sr = DomUtil.addChildElement(elem, DeltaVConstants.XML_SUPPORTED_REPORT, DeltaVConstants.NAMESPACE); + Element r = DomUtil.addChildElement(sr, DeltaVConstants.XML_REPORT, DeltaVConstants.NAMESPACE); + r.appendChild(rt.toXml(document)); + } + return elem; + } + +} Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/report/SupportedReportSetProperty.java ___________________________________________________________________ Added: svn Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/report/VersionTreeReport.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/report/VersionTreeReport.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/report/VersionTreeReport.java (working copy) @@ -0,0 +1,187 @@ +/* + * 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.webdav.version.report; + +import org.apache.jackrabbit.webdav.DavException; +import org.apache.jackrabbit.webdav.DavResource; +import org.apache.jackrabbit.webdav.DavResourceIterator; +import org.apache.jackrabbit.webdav.DavServletResponse; +import org.apache.jackrabbit.webdav.MultiStatus; +import org.apache.jackrabbit.webdav.property.DavPropertyNameSet; +import org.apache.jackrabbit.webdav.version.DeltaVConstants; +import org.apache.jackrabbit.webdav.version.VersionControlledResource; +import org.apache.jackrabbit.webdav.version.VersionResource; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +/** + * VersionTreeReport encapsulates the DAV:version-tree report. + * It describes the requested properties of all the versions in the version + * history of a version. The DAV:version-tree report must be supported by all + * version resources and all version-controlled resources. + */ +public class VersionTreeReport extends AbstractReport implements DeltaVConstants { + + private static Logger log = LoggerFactory.getLogger(VersionTreeReport.class); + + private ReportInfo info; + private DavResource resource; + + /** + * Returns {@link ReportType#VERSION_TREE} + * + * @return {@link ReportType#VERSION_TREE} + * @see Report#getType() + */ + public ReportType getType() { + return ReportType.VERSION_TREE; + } + + /** + * Always returns true. + * + * @return true + * @see org.apache.jackrabbit.webdav.version.report.Report#isMultiStatusReport() + */ + public boolean isMultiStatusReport() { + return true; + } + + /** + * Validates the specified resource and info objects. + * + * @param resource + * @param info + * @throws org.apache.jackrabbit.webdav.DavException + * @see Report#init(DavResource, ReportInfo) + */ + public void init(DavResource resource, ReportInfo info) throws DavException { + setResource(resource); + setInfo(info); + } + + /** + * Set the DeltaVResource used to register this report. + * + * @param resource + * @throws DavException if the given resource is neither + * {@link VersionControlledResource} nor {@link VersionResource}. + */ + private void setResource(DavResource resource) throws DavException { + if (resource != null && (resource instanceof VersionControlledResource || resource instanceof VersionResource)) { + this.resource = resource; + } else { + throw new DavException(DavServletResponse.SC_BAD_REQUEST, "DAV:version-tree report can only be created for version-controlled resources and version resources."); + } + } + + /** + * Set the ReportInfo as specified by the REPORT request body, + * that defines the details for this report. + * + * @param info + * @throws DavException if the given ReportInfo + * does not contain a DAV:version-tree element. + */ + private void setInfo(ReportInfo info) throws DavException { + if (!getType().isRequestedReportType(info)) { + throw new DavException(DavServletResponse.SC_BAD_REQUEST, "DAV:version-tree element expected."); + } + this.info = info; + } + + /** + * Runs the DAV:version-tree report. + * + * @return Xml Document representing the report in the required + * format. + * @see org.apache.jackrabbit.webdav.xml.XmlSerializable#toXml(Document) + * @param document + */ + public Element toXml(Document document) { + return getMultiStatus().toXml(document); + } + + /** + * Retrieve the MultiStatus that is returned in response to a locate-by-history + * report request. + * + * @return + * @throws NullPointerException if info or resource is null. + */ + private MultiStatus getMultiStatus() { + if (info == null || resource == null) { + throw new NullPointerException("Error while running DAV:version-tree report"); + } + + MultiStatus ms = new MultiStatus(); + buildResponse(resource, info.getPropertyNameSet(), info.getDepth(), ms); + return ms; + } + + /** + * + * @param res + * @param propNameSet + * @param depth + * @param ms + */ + private void buildResponse(DavResource res, DavPropertyNameSet propNameSet, + int depth, MultiStatus ms) { + try { + for (VersionResource version : getVersions(res)) { + if (propNameSet.isEmpty()) { + ms.addResourceStatus(version, DavServletResponse.SC_OK, 0); + } else { + ms.addResourceProperties(version, propNameSet, 0); + } + } + } catch (DavException e) { + log.error(e.toString()); + } + if (depth > 0 && res.isCollection()) { + DavResourceIterator it = res.getMembers(); + while (it.hasNext()) { + buildResponse(it.nextResource(), propNameSet, depth-1, ms); + } + } + } + + /** + * Retrieve all versions from the version history associated with the given + * resource. If the versions cannot be retrieved from the given resource + * an exception is thrown. + * + * @param res + * @return array of {@link VersionResource}s or an empty array if the versions + * could not be retrieved. + * @throws DavException if the version history could not be retrieved from + * the given resource or if an error occurs while accessing the versions + * from the version history resource. + */ + private static VersionResource[] getVersions(DavResource res) throws DavException { + VersionResource[] versions = new VersionResource[0]; + if (res instanceof VersionControlledResource) { + versions = ((VersionControlledResource)res).getVersionHistory().getVersions(); + } else if (res instanceof VersionResource) { + versions = ((VersionResource)res).getVersionHistory().getVersions(); + } + return versions; + } +} Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/report/VersionTreeReport.java ___________________________________________________________________ Added: svn Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/report/package-info.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/report/package-info.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/report/package-info.java (working copy) @@ -0,0 +1,18 @@ +/* + * 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. + */ +@org.osgi.annotation.versioning.Version("1.1.0") +package org.apache.jackrabbit.webdav.version.report; Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/version/report/package-info.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/xml/DavDocumentBuilderFactory.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/xml/DavDocumentBuilderFactory.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/xml/DavDocumentBuilderFactory.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.webdav.xml; + +import java.io.IOException; + +import javax.xml.XMLConstants; +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.xml.sax.EntityResolver; +import org.xml.sax.InputSource; +import org.xml.sax.helpers.DefaultHandler; + +/** + * Custom {@link DocumentBuilderFactory} extended for use in WebDAV. + */ +public class DavDocumentBuilderFactory { + + private static final Logger LOG = LoggerFactory.getLogger(DavDocumentBuilderFactory.class); + + private final DocumentBuilderFactory DEFAULT_FACTORY = createFactory(); + + private DocumentBuilderFactory BUILDER_FACTORY = DEFAULT_FACTORY; + + private DocumentBuilderFactory createFactory() { + DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); + factory.setNamespaceAware(true); + factory.setIgnoringComments(true); + factory.setIgnoringElementContentWhitespace(true); + factory.setCoalescing(true); + try { + factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true); + } catch (ParserConfigurationException e) { + LOG.warn("Secure XML processing is not supported", e); + } catch (AbstractMethodError e) { + LOG.warn("Secure XML processing is not supported", e); + } + return factory; + } + + public void setFactory(DocumentBuilderFactory documentBuilderFactory) { + LOG.debug("DocumentBuilderFactory changed to: " + documentBuilderFactory); + BUILDER_FACTORY = documentBuilderFactory != null ? documentBuilderFactory : DEFAULT_FACTORY; + } + + /** + * An entity resolver that does not allow external entity resolution. See + * RFC 4918, Section 20.6 + */ + private static final EntityResolver DEFAULT_ENTITY_RESOLVER = new EntityResolver() { + @Override + public InputSource resolveEntity(String publicId, String systemId) throws IOException { + LOG.debug("Resolution of external entities in XML payload not supported - publicId: " + publicId + ", systemId: " + + systemId); + throw new IOException("This parser does not support resolution of external entities (publicId: " + publicId + + ", systemId: " + systemId + ")"); + } + }; + + public DocumentBuilder newDocumentBuilder() throws ParserConfigurationException { + DocumentBuilder db = BUILDER_FACTORY.newDocumentBuilder(); + if (BUILDER_FACTORY == DEFAULT_FACTORY) { + // if this is the default factory: set the default entity resolver as well + db.setEntityResolver(DEFAULT_ENTITY_RESOLVER); + } + db.setErrorHandler(new DefaultHandler()); + return db; + } +} Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/xml/DavDocumentBuilderFactory.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/xml/DomUtil.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/xml/DomUtil.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/xml/DomUtil.java (working copy) @@ -0,0 +1,839 @@ +/* + * 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.webdav.xml; + +import org.apache.jackrabbit.webdav.DavConstants; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.w3c.dom.Attr; +import org.w3c.dom.CharacterData; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; +import org.w3c.dom.Text; +import org.w3c.dom.NamedNodeMap; +import org.xml.sax.SAXException; + +import javax.xml.namespace.QName; +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.transform.Transformer; +import javax.xml.transform.TransformerException; +import javax.xml.transform.TransformerFactory; +import javax.xml.transform.dom.DOMSource; +import javax.xml.transform.stream.StreamResult; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.Writer; +import java.util.ArrayList; +import java.util.List; + +/** + * DomUtil provides some common utility methods related to w3c-DOM. + */ +public class DomUtil { + + private static Logger log = LoggerFactory.getLogger(DomUtil.class); + + /** + * Constant for DavDocumentBuilderFactory which is used + * to create and parse DOM documents. + */ + private static final DavDocumentBuilderFactory BUILDER_FACTORY = new DavDocumentBuilderFactory(); + + /** + * Support the replacement of {@link #BUILDER_FACTORY}. This is useful + * for injecting a customized BuilderFactory, for example with one that + * uses a local catalog resolver. This is one technique for addressing + * this issue: + * http://www.w3.org/blog/systeam/2008/02/08/w3c_s_excessive_dtd_traffic + * + * @param documentBuilderFactory + */ + public static void setBuilderFactory( + DocumentBuilderFactory documentBuilderFactory) { + BUILDER_FACTORY.setFactory(documentBuilderFactory); + } + + /** + * Transformer factory + */ + private static TransformerFactory TRANSFORMER_FACTORY = TransformerFactory.newInstance(); + + /** + * Creates and returns a new empty DOM document. + * + * @return new DOM document + * @throws ParserConfigurationException if the document can not be created + */ + public static Document createDocument() + throws ParserConfigurationException { + return BUILDER_FACTORY.newDocumentBuilder().newDocument(); + } + + /** + * Parses the given input stream and returns the resulting DOM document. + * + * @param stream XML input stream + * @return parsed DOM document + * @throws ParserConfigurationException if the document can not be created + * @throws SAXException if the document can not be parsed + * @throws IOException if the input stream can not be read + */ + public static Document parseDocument(InputStream stream) + throws ParserConfigurationException, SAXException, IOException { + DocumentBuilder docBuilder = BUILDER_FACTORY.newDocumentBuilder(); + return docBuilder.parse(stream); + } + + /** + * Returns the value of the named attribute of the current element. + * + * @param parent + * @param localName attribute local name or 'nodeName' if no namespace is + * specified. + * @param namespace or null + * @return attribute value, or null if not found + */ + public static String getAttribute(Element parent, String localName, Namespace namespace) { + if (parent == null) { + return null; + } + Attr attribute; + if (namespace == null) { + attribute = parent.getAttributeNode(localName); + } else { + attribute = parent.getAttributeNodeNS(namespace.getURI(), localName); + } + if (attribute != null) { + return attribute.getValue(); + } else { + return null; + } + } + + /** + * Returns the namespace attributes of the given element. + * + * @param element + * @return the namespace attributes. + */ + public static Attr[] getNamespaceAttributes(Element element) { + NamedNodeMap attributes = element.getAttributes(); + List nsAttr = new ArrayList(); + for (int i = 0; i < attributes.getLength(); i++) { + Attr attr = (Attr) attributes.item(i); + if (Namespace.XMLNS_NAMESPACE.getURI().equals(attr.getNamespaceURI())) { + nsAttr.add(attr); + } + } + return nsAttr.toArray(new Attr[nsAttr.size()]); + } + + /** + * Concatenates the values of all child nodes of type 'Text' or 'CDATA'/ + * + * @param element + * @return String representing the value of all Text and CDATA child nodes or + * null if the length of the resulting String is 0. + * @see #isText(Node) + */ + public static String getText(Element element) { + StringBuffer content = new StringBuffer(); + if (element != null) { + NodeList nodes = element.getChildNodes(); + for (int i = 0; i < nodes.getLength(); i++) { + Node child = nodes.item(i); + if (isText(child)) { + // cast to super class that contains Text and CData + content.append(((CharacterData) child).getData()); + } + } + } + return (content.length()==0) ? null : content.toString(); + } + + /** + * Same as {@link #getText(Element)} except that 'defaultValue' is returned + * instead of null, if the element does not contain any text. + * + * @param element + * @param defaultValue + * @return the text contained in the specified element or + * defaultValue if the element does not contain any text. + */ + public static String getText(Element element, String defaultValue) { + String txt = getText(element); + return (txt == null) ? defaultValue : txt; + } + + /** + * Removes leading and trailing whitespace after calling {@link #getText(Element)}. + * + * @param element + * @return Trimmed text or null + */ + public static String getTextTrim(Element element) { + String txt = getText(element); + return (txt == null) ? txt : txt.trim(); + } + + /** + * Calls {@link #getText(Element)} on the first child element that matches + * the given local name and namespace. + * + * @param parent + * @param childLocalName + * @param childNamespace + * @return text contained in the first child that matches the given local name + * and namespace or null. + * @see #getText(Element) + */ + public static String getChildText(Element parent, String childLocalName, Namespace childNamespace) { + Element child = getChildElement(parent, childLocalName, childNamespace); + return (child == null) ? null : getText(child); + } + + /** + * Calls {@link #getTextTrim(Element)} on the first child element that matches + * the given local name and namespace. + * + * @param parent + * @param childLocalName + * @param childNamespace + * @return text contained in the first child that matches the given local name + * and namespace or null. Note, that leading and trailing whitespace + * is removed from the text. + * @see #getTextTrim(Element) + */ + public static String getChildTextTrim(Element parent, String childLocalName, Namespace childNamespace) { + Element child = getChildElement(parent, childLocalName, childNamespace); + return (child == null) ? null : getTextTrim(child); + } + + /** + * Calls {@link #getTextTrim(Element)} on the first child element that matches + * the given name. + * + * @param parent + * @param childName + * @return text contained in the first child that matches the given name + * or null. Note, that leading and trailing whitespace + * is removed from the text. + * @see #getTextTrim(Element) + */ + public static String getChildTextTrim(Element parent, QName childName) { + Element child = getChildElement(parent, childName); + return (child == null) ? null : getTextTrim(child); + } + + /** + * Returns true if the given parent node has a child element that matches + * the specified local name and namespace. + * + * @param parent + * @param childLocalName + * @param childNamespace + * @return returns true if a child element exists that matches the specified + * local name and namespace. + */ + public static boolean hasChildElement(Node parent, String childLocalName, Namespace childNamespace) { + return getChildElement(parent, childLocalName, childNamespace) != null; + } + + /** + * Returns the first child element that matches the given local name and + * namespace. If no child element is present or no child element matches, + * null is returned. + * + * @param parent + * @param childLocalName + * @param childNamespace + * @return first child element matching the specified names or null. + */ + public static Element getChildElement(Node parent, String childLocalName, Namespace childNamespace) { + if (parent != null) { + NodeList children = parent.getChildNodes(); + for (int i = 0; i < children.getLength(); i++) { + Node child = children.item(i); + if (isElement(child) && matches(child, childLocalName, childNamespace)) { + return (Element)child; + } + } + } + return null; + } + + /** + * Returns the first child element that matches the given {@link QName}. + * If no child element is present or no child element matches, + * null is returned. + * + * @param parent + * @param childName + * @return first child element matching the specified name or null. + */ + public static Element getChildElement(Node parent, QName childName) { + if (parent != null) { + NodeList children = parent.getChildNodes(); + for (int i = 0; i < children.getLength(); i++) { + Node child = children.item(i); + if (isElement(child) && matches(child, childName)) { + return (Element)child; + } + } + } + return null; + } + + /** + * Returns a ElementIterator containing all child elements of + * the given parent node that match the given local name and namespace. + * If the namespace is null only the localName is compared. + * + * @param parent the node the children elements should be retrieved from + * @param childLocalName + * @param childNamespace + * @return an ElementIterator giving access to all child elements + * that match the specified localName and namespace. + */ + public static ElementIterator getChildren(Element parent, String childLocalName, Namespace childNamespace) { + return new ElementIterator(parent, childLocalName, childNamespace); + } + + /** + * Returns a ElementIterator containing all child elements of + * the given parent node that match the given {@link QName}. + * + * @param parent + * the node the children elements should be retrieved from + * @param childName + * @return an ElementIterator giving access to all child + * elements that match the specified name. + */ + public static ElementIterator getChildren(Element parent, QName childName) { + return new ElementIterator(parent, childName); + } + + /** + * Return an ElementIterator over all child elements. + * + * @param parent + * @return + * @see #getChildren(Element, String, Namespace) for a method that only + * retrieves child elements that match a specific local name and namespace. + */ + public static ElementIterator getChildren(Element parent) { + return new ElementIterator(parent); + } + + /** + * Return the first child element + * + * @return the first child element or null if the given node has no + * child elements. + */ + public static Element getFirstChildElement(Node parent) { + if (parent != null) { + NodeList children = parent.getChildNodes(); + for (int i = 0; i < children.getLength(); i++) { + Node child = children.item(i); + if (isElement(child)) { + return (Element)child; + } + } + } + return null; + } + + /** + * Return true if the given parent contains any child that is + * either an Element, Text or CDATA. + * + * @param parent + * @return true if the given parent contains any child that is + * either an Element, Text or CDATA. + */ + public static boolean hasContent(Node parent) { + if (parent != null) { + NodeList children = parent.getChildNodes(); + for (int i = 0; i < children.getLength(); i++) { + Node child = children.item(i); + if (isAcceptedNode(child)) { + return true; + } + } + } + return false; + } + + /** + * Return a list of all child nodes that are either Element, Text or CDATA. + * + * @param parent + * @return a list of all child nodes that are either Element, Text or CDATA. + */ + public static List getContent(Node parent) { + List content = new ArrayList(); + if (parent != null) { + NodeList children = parent.getChildNodes(); + for (int i = 0; i < children.getLength(); i++) { + Node child = children.item(i); + if (isAcceptedNode(child)) { + content.add(child); + } + } + } + return content; + } + + /** + * Build a Namespace from the prefix and uri retrieved from the given element. + * + * @return the Namespace of the given element. + */ + public static Namespace getNamespace(Element element) { + String uri = element.getNamespaceURI(); + String prefix = element.getPrefix(); + if (uri == null) { + return Namespace.EMPTY_NAMESPACE; + } else { + return Namespace.getNamespace(prefix, uri); + } + } + + /** + * Returns true if the specified node matches the required names. Note, that + * that tests return true if the required name is null. + * + * @param node + * @param requiredLocalName + * @param requiredNamespace + * @return true if local name and namespace match the corresponding properties + * of the given DOM node. + */ + public static boolean matches(Node node, String requiredLocalName, Namespace requiredNamespace) { + if (node == null) { + return false; + } + boolean matchingNamespace = matchingNamespace(node, requiredNamespace); + return matchingNamespace && matchingLocalName(node, requiredLocalName); + } + + /** + * Returns true if the specified node matches the required {@link QName}. + * + * @param node + * @param requiredName + * @return true if local name and namespace match the corresponding properties + * of the given DOM node. + */ + public static boolean matches(Node node, QName requiredName) { + if (node == null) { + return false; + } else { + String nodens = node.getNamespaceURI() != null ? node.getNamespaceURI() : ""; + return nodens.equals(requiredName.getNamespaceURI()) + && node.getLocalName().equals(requiredName.getLocalPart()); + } + } + + /** + * @param node + * @param requiredNamespace + * @return true if the required namespace is null or matches + * the namespace of the specified node. + */ + private static boolean matchingNamespace(Node node, Namespace requiredNamespace) { + if (requiredNamespace == null) { + return true; + } else { + return requiredNamespace.isSame(node.getNamespaceURI()); + } + } + + /** + * @param node + * @param requiredLocalName + * @return true if the required local name is null or if the + * nodes local name matches. + */ + private static boolean matchingLocalName(Node node, String requiredLocalName) { + if (requiredLocalName == null) { + return true; + } else { + String localName = node.getLocalName(); + return requiredLocalName.equals(localName); + } + } + + /** + * @param node + * @return true if the specified node is either an element or Text or CDATA + */ + private static boolean isAcceptedNode(Node node) { + return isElement(node) || isText(node); + } + + /** + * @param node + * @return true if the given node is of type element. + */ + static boolean isElement(Node node) { + return node.getNodeType() == Node.ELEMENT_NODE; + } + + /** + * @param node + * @return true if the given node is of type text or CDATA. + */ + static boolean isText(Node node) { + int ntype = node.getNodeType(); + return ntype == Node.TEXT_NODE || ntype == Node.CDATA_SECTION_NODE; + } + + //----------------------------------------------------< factory methods >--- + /** + * Create a new DOM element with the specified local name and namespace. + * + * @param factory + * @param localName + * @param namespace + * @return a new DOM element + * @see Document#createElement(String) + * @see Document#createElementNS(String, String) + */ + public static Element createElement(Document factory, String localName, Namespace namespace) { + if (namespace != null) { + return factory.createElementNS(namespace.getURI(), getPrefixedName(localName, namespace)); + } else { + return factory.createElement(localName); + } + } + + /** + * Create a new DOM element with the specified local name and namespace. + * + * @param factory + * @param elementName + * @return a new DOM element + * @see Document#createElement(String) + * @see Document#createElementNS(String, String) + */ + public static Element createElement(Document factory, QName elementName) { + return factory.createElementNS(elementName.getNamespaceURI(), getPrefixedName(elementName)); + } + + /** + * Create a new DOM element with the specified local name and namespace and + * add the specified text as Text node to it. + * + * @param factory + * @param localName + * @param namespace + * @param text + * @return a new DOM element + * @see Document#createElement(String) + * @see Document#createElementNS(String, String) + * @see Document#createTextNode(String) + * @see Node#appendChild(org.w3c.dom.Node) + */ + public static Element createElement(Document factory, String localName, Namespace namespace, String text) { + Element elem = createElement(factory, localName, namespace); + setText(elem, text); + return elem; + } + + /** + * Add a new child element with the given local name and namespace to the + * specified parent. + * + * @param parent + * @param localName + * @param namespace + * @return the new element that was attached to the given parent. + */ + public static Element addChildElement(Element parent, String localName, Namespace namespace) { + Element elem = createElement(parent.getOwnerDocument(), localName, namespace); + parent.appendChild(elem); + return elem; + } + + /** + * Add a new child element with the given local name and namespace to the + * specified parent. + * + * @param parent + * @param localName + * @param namespace + * @return the new element that was attached to the given parent. + */ + public static Element addChildElement(Node parent, String localName, Namespace namespace) { + Document doc = parent.getOwnerDocument(); + if (parent instanceof Document) { + doc = (Document) parent; + } + Element elem = createElement(doc, localName, namespace); + parent.appendChild(elem); + return elem; + } + + /** + * Add a new child element with the given local name and namespace to the + * specified parent. The specified text is added as Text node to the created + * child element. + * + * @param parent + * @param localName + * @param namespace + * @param text + * @return child element that was added to the specified parent + * @see Document#createElement(String) + * @see Document#createElementNS(String, String) + * @see Document#createTextNode(String) + * @see Node#appendChild(org.w3c.dom.Node) + */ + public static Element addChildElement(Element parent, String localName, Namespace namespace, String text) { + Element elem = createElement(parent.getOwnerDocument(), localName, namespace, text); + parent.appendChild(elem); + return elem; + } + + /** + * Create a new text node and add it as child to the given element. + * + * @param element + * @param text + */ + public static void setText(Element element, String text) { + if (text == null || "".equals(text)) { + // ignore null/empty string text + return; + } + Text txt = element.getOwnerDocument().createTextNode(text); + element.appendChild(txt); + } + + /** + * Add an attribute node to the given element. + * + * @param element + * @param attrLocalName + * @param attrNamespace + * @param attrValue + */ + public static void setAttribute(Element element, String attrLocalName, Namespace attrNamespace, String attrValue) { + if (attrNamespace == null) { + Attr attr = element.getOwnerDocument().createAttribute(attrLocalName); + attr.setValue(attrValue); + element.setAttributeNode(attr); + } else { + Attr attr = element.getOwnerDocument().createAttributeNS(attrNamespace.getURI(), getPrefixedName(attrLocalName, attrNamespace)); + attr.setValue(attrValue); + element.setAttributeNodeNS(attr); + } + } + + /** + * Adds a namespace attribute on the given element. + * + * @param element + * @param prefix + * @param uri + */ + public static void setNamespaceAttribute(Element element, String prefix, String uri) { + if (Namespace.EMPTY_NAMESPACE.equals(Namespace.getNamespace(prefix, uri))) { + /** + * don't try to set the empty namespace which will fail + * see {@link org.w3c.dom.DOMException#NAMESPACE_ERR} + * TODO: correct? + */ + log.debug("Empty namespace -> omit attribute setting."); + return; + } + setAttribute(element, prefix, Namespace.XMLNS_NAMESPACE, uri); + } + + /** + * Converts the given timeout (long value defining the number of milli- + * second until timeout is reached) to its Xml representation as defined + * by RFC 4918.
+ * + * @param timeout number of milli-seconds until timeout is reached. + * @return 'timeout' Xml element + */ + public static Element timeoutToXml(long timeout, Document factory) { + boolean infinite = timeout / 1000 > Integer.MAX_VALUE || timeout == DavConstants.INFINITE_TIMEOUT; + String expString = infinite ? DavConstants.TIMEOUT_INFINITE : "Second-" + timeout / 1000; + return createElement(factory, DavConstants.XML_TIMEOUT, DavConstants.NAMESPACE, expString); + } + + /** + * Returns the Xml representation of a boolean isDeep, where false + * presents a depth value of '0', true a depth value of 'infinity'. + * + * @param isDeep + * @return Xml representation + */ + public static Element depthToXml(boolean isDeep, Document factory) { + return depthToXml(isDeep? "infinity" : "0", factory); + } + + /** + * Returns the Xml representation of a depth String. Webdav defines the + * following valid values for depths: 0, 1, infinity + * + * @param depth + * @return 'deep' XML element + */ + public static Element depthToXml(String depth, Document factory) { + return createElement(factory, DavConstants.XML_DEPTH, DavConstants.NAMESPACE, depth); + } + + /** + * Builds a 'DAV:href' Xml element from the given href. + *

+ * Note that the path present needs to be a valid URI or URI reference. + * + * @param href String representing the text of the 'href' Xml element + * @param factory the Document used as factory + * @return Xml representation of a 'href' according to RFC 2518. + */ + public static Element hrefToXml(String href, Document factory) { + return createElement(factory, DavConstants.XML_HREF, DavConstants.NAMESPACE, href); + } + + /** + * Same as {@link #getExpandedName(String, Namespace)}. + * + * @param localName + * @param namespace + * @return the expanded name of a DOM node consisting of "{" + namespace uri + "}" + * + localName. If the specified namespace is null or represents + * the empty namespace, the local name is returned. + * @deprecated As of 2.0. Please use {@link #getExpandedName(String, Namespace)} + * instead. This method was named according to usage of 'qualified name' in + * JSR 170 that conflicts with the terminology used in XMLNS. As of JCR 2.0 + * the String consisting of "{" + namespace uri + "}" + localName + * is called Expanded Name. + * + */ + public static String getQualifiedName(String localName, Namespace namespace) { + return getExpandedName(localName, namespace); + } + + /** + * Returns a string representation of the name of a DOM node consisting + * of "{" + namespace uri + "}" + localName. If the specified namespace is + * null or represents the empty namespace, the local name is + * returned. + * + * @param localName + * @param namespace + * @return String representation of the name of a DOM node consisting of "{" + namespace uri + "}" + * + localName. If the specified namespace is null or represents + * the empty namespace, the local name is returned. + * @since 2.0 Replaces the deprecated method {@link #getQualifiedName(String, Namespace)}. + */ + public static String getExpandedName(String localName, Namespace namespace) { + if (namespace == null || namespace.equals(Namespace.EMPTY_NAMESPACE)) { + return localName; + } + StringBuffer b = new StringBuffer("{"); + b.append(namespace.getURI()).append("}"); + b.append(localName); + return b.toString(); + } + + /** + * Return the qualified name of a DOM node consisting of + * namespace prefix + ":" + local name. If the specified namespace is null + * or contains an empty prefix, the local name is returned.
+ * NOTE, that this is the value to be used for the 'qualified Name' parameter + * expected with the namespace sensitive factory methods. + * + * @param localName + * @param namespace + * @return qualified name consisting of prefix, ':' and local name. + * @see Document#createAttributeNS(String, String) + * @see Document#createElementNS(String, String) + */ + public static String getPrefixedName(String localName, Namespace namespace) { + return getPrefixName(namespace.getURI(), namespace.getPrefix(), localName); + } + + /** + * Return the qualified name of a DOM node consisting of + * namespace prefix + ":" + local name. If the specified namespace is null + * or contains an empty prefix, the local name is returned.
+ * NOTE, that this is the value to be used for the 'qualified Name' parameter + * expected with the namespace sensitive factory methods. + * + * @param name + * @return qualified name consisting of prefix, ':' and local name. + * @see Document#createAttributeNS(String, String) + * @see Document#createElementNS(String, String) + */ + public static String getPrefixedName(QName name) { + return getPrefixName(name.getNamespaceURI(), name.getPrefix(), name.getLocalPart()); + } + + private static String getPrefixName(String namespaceURI, String prefix, String localName) { + if (namespaceURI == null || prefix == null || "".equals(namespaceURI) || "".equals(prefix)) { + return localName; + } else { + StringBuffer buf = new StringBuffer(prefix); + buf.append(":"); + buf.append(localName); + return buf.toString(); + } + } + + /** + * Uses a new Transformer instance to transform the specified xml document + * to the specified writer output target. + * + * @param xmlDoc XML document to create the transformation + * Source for. + * @param writer The writer used to create a new transformation + * Result for. + * @throws TransformerException + */ + public static void transformDocument(Document xmlDoc, Writer writer) throws TransformerException, SAXException { + Transformer transformer = TRANSFORMER_FACTORY.newTransformer(); + transformer.transform(new DOMSource(xmlDoc), ResultHelper.getResult(new StreamResult(writer))); + } + + /** + * Uses a new Transformer instance to transform the specified xml document + * to the specified writer output target. + * + * @param xmlDoc XML document to create the transformation + * Source for. + * @param out The stream used to create a new transformation + * Result for. + * @throws TransformerException + */ + public static void transformDocument(Document xmlDoc, OutputStream out) throws TransformerException, SAXException { + Transformer transformer = TRANSFORMER_FACTORY.newTransformer(); + transformer.transform(new DOMSource(xmlDoc), ResultHelper.getResult(new StreamResult(out))); + } +} Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/xml/DomUtil.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-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/xml/ElementIterator.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/xml/ElementIterator.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/xml/ElementIterator.java (working copy) @@ -0,0 +1,170 @@ +/* + * 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.webdav.xml; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.w3c.dom.Element; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; + +import java.util.Iterator; +import java.util.NoSuchElementException; + +import javax.xml.namespace.QName; + +/** + * ElementIterator... + */ +public class ElementIterator implements Iterator { + + private static Logger log = LoggerFactory.getLogger(ElementIterator.class); + + private final Namespace namespace; + private final String localName; + private final QName qName; + + private Element next; + + /** + * Create a new instance of ElementIterator with the given + * parent element. Only child elements that match the given local name + * and namespace will be respected by {@link #hasNext()} and {@link #nextElement()}. + * + * @param parent + * @param localName local name the child elements must match + * @param namespace namespace the child elements must match + */ + public ElementIterator(Element parent, String localName, Namespace namespace) { + this.localName = localName; + this.namespace = namespace; + this.qName = null; + seek(parent); + } + + /** + * Create a new instance of ElementIterator with the given + * parent element. Only child elements that match the given {@link QName} + * will be respected by {@link #hasNext()} and {@link #nextElement()}. + * + * @param parent + * @param qname name to match (exactly) + */ + public ElementIterator(Element parent, QName qname) { + this.localName = null; + this.namespace = null; + this.qName = qname; + seek(parent); + } + + /** + * Create a new instance of ElementIterator with the given + * parent element. No filtering is applied to child elements that are + * iterated. + * + * @param parent + */ + public ElementIterator(Element parent) { + this(parent, null, null); + } + + /** + * Not implemented + * + * @throws UnsupportedOperationException + */ + public void remove() { + throw new UnsupportedOperationException("Remove not implemented."); + } + + /** + * Returns true if there is a next Element + * + * @return true if a next Element is available. + */ + public boolean hasNext() { + return next != null; + } + + /** + * @see java.util.Iterator#next() + * @see #nextElement() + */ + public Element next() { + return nextElement(); + } + + /** + * Returns the next Element in the iterator. + * + * @return the next element + * @throws NoSuchElementException if there is no next element. + */ + public Element nextElement() { + if (next==null) { + throw new NoSuchElementException(); + } + Element ret = next; + seek(); + return ret; + } + + /** + * Seeks for the first matching child element + */ + private void seek(Element parent) { + NodeList nodeList = parent.getChildNodes(); + for (int i = 0; i < nodeList.getLength(); i++) { + Node n = nodeList.item(i); + if (matchesName(n)) { + next = (Element)n; + return; + } + } + } + + /** + * Seeks for the next valid element (i.e. the next valid sibling) + */ + private void seek() { + Node n = next.getNextSibling(); + while (n != null) { + if (matchesName(n)) { + next = (Element)n; + return; + } else { + n = n.getNextSibling(); + } + } + // no next element found -> set to null in order to leave the loop. + next = null; + } + + /** + * Matches the node name according to either {@link #qName} or the pair + * of {@link #localName) and {@link #namespace}. + */ + private boolean matchesName(Node n) { + if (!DomUtil.isElement(n)) { + return false; + } else if (qName != null) { + return DomUtil.matches(n, qName); + } else { + return DomUtil.matches(n, localName, namespace); + } + } +} Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/xml/ElementIterator.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-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/xml/Namespace.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/xml/Namespace.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/xml/Namespace.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.webdav.xml; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Namespace + */ +public class Namespace { + + private static Logger log = LoggerFactory.getLogger(Namespace.class); + + public static final Namespace EMPTY_NAMESPACE = new Namespace("",""); + public static final Namespace XML_NAMESPACE = new Namespace("xml", "http://www.w3.org/XML/1998/namespace"); + public static final Namespace XMLNS_NAMESPACE = new Namespace("xmlns", "http://www.w3.org/2000/xmlns/"); + + private final String prefix; + private final String uri; + + private Namespace(String prefix, String uri) { + this.prefix = prefix; + this.uri = uri; + } + + //-----------------------------------------------------------< creation >--- + + public static Namespace getNamespace(String prefix, String uri) { + if (prefix == null) { + prefix = EMPTY_NAMESPACE.getPrefix(); + } + if (uri == null) { + uri = EMPTY_NAMESPACE.getURI(); + } + return new Namespace(prefix, uri); + } + + public static Namespace getNamespace(String uri) { + return getNamespace("", uri); + } + + //-------------------------------------------------------------------------- + + public String getPrefix() { + return prefix; + } + + public String getURI() { + return uri; + } + + /** + * Returns true if the a Namespace built from the + * specified namespaceURI is equal to this namespace object. + * + * @param namespaceURI A namespace URI to be compared to this namespace instance. + * @return true if the a Namespace built from the + * specified namespaceURI is equal to this namespace object; + * false otherwise. + */ + public boolean isSame(String namespaceURI) { + Namespace other = getNamespace(namespaceURI); + return this.equals(other); + } + + //-------------------------------------------------------------< Object >--- + @Override + public int hashCode() { + return uri.hashCode(); + } + + @Override + public boolean equals(Object obj) { + if (obj == this) { + return true; + } + if (obj instanceof Namespace) { + return uri.equals(((Namespace)obj).uri); + } + return false; + } +} \ No newline at end of file Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/xml/Namespace.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-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/xml/ResultHelper.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/xml/ResultHelper.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/xml/ResultHelper.java (working copy) @@ -0,0 +1,458 @@ +/* + * 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.webdav.xml; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.xml.sax.Attributes; +import org.xml.sax.ContentHandler; +import org.xml.sax.Locator; +import org.xml.sax.SAXException; +import org.xml.sax.helpers.AttributesImpl; +import org.xml.sax.helpers.DefaultHandler; + +import javax.xml.transform.OutputKeys; +import javax.xml.transform.Result; +import javax.xml.transform.Transformer; +import javax.xml.transform.TransformerConfigurationException; +import javax.xml.transform.TransformerFactory; +import javax.xml.transform.sax.SAXResult; +import javax.xml.transform.sax.SAXTransformerFactory; +import javax.xml.transform.sax.TransformerHandler; +import javax.xml.transform.stream.StreamResult; +import java.io.StringWriter; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +/** + * ResultHelper is a utility to assert proper namespace handling + * due to misbehavior of certain implementations with respect to xmlns attributes. + * The code is copied and slightly modified from jcr-commons + * SerializingContentHandler + * + * @see JCR-2897. + */ +public final class ResultHelper { + + /** + * logger instance + */ + private static final Logger log = LoggerFactory.getLogger(ResultHelper.class); + + /** The URI for xml namespaces */ + private static final String XML = "http://www.w3.org/XML/1998/namespace"; + + /** + * The factory used to create serializing SAX transformers. + */ + private static final SAXTransformerFactory FACTORY = + // Note that the cast from below is strictly speaking only valid when + // the factory instance supports the SAXTransformerFactory.FEATURE + // feature. But since this class would be useless without this feature, + // it's no problem to fail with a ClassCastException here and prevent + // this class from even being loaded. AFAIK all common JAXP + // implementations do support this feature. + (SAXTransformerFactory) TransformerFactory.newInstance(); + + /** + * Flag that indicates whether we need to work around the issue of + * the serializer not automatically generating the required xmlns + * attributes for the namespaces used in the document. + */ + private static final boolean NEEDS_XMLNS_ATTRIBUTES = + needsXmlnsAttributes(); + + /** + * Probes the available XML serializer for xmlns support. Used to set + * the value of the {@link #NEEDS_XMLNS_ATTRIBUTES} flag. + * + * @return whether the XML serializer needs explicit xmlns attributes + */ + private static boolean needsXmlnsAttributes() { + try { + StringWriter writer = new StringWriter(); + TransformerHandler probe = FACTORY.newTransformerHandler(); + probe.setResult(new StreamResult(writer)); + probe.startDocument(); + probe.startPrefixMapping("p", "uri"); + probe.startElement("uri", "e", "p:e", new AttributesImpl()); + probe.endElement("uri", "e", "p:e"); + probe.endPrefixMapping("p"); + probe.endDocument(); + return writer.toString().indexOf("xmlns") == -1; + } catch (Exception e) { + throw new UnsupportedOperationException("XML serialization fails"); + } + } + + /** + * In case the underlying XML library doesn't properly handle xmlns attributes + * this method creates new content handler dealing with the misbehavior and + * returns an new instance of SAXResult. Otherwise the passed result + * is returned back. + * + * @param result + * @return A instance of Result that properly handles xmlns attributes. + * @throws SAXException + */ + public static Result getResult(Result result) throws SAXException { + try { + TransformerHandler handler = FACTORY.newTransformerHandler(); + handler.setResult(result); + + // Specify the output properties to avoid surprises especially in + // character encoding or the output method (might be html for some + // documents!) + Transformer transformer = handler.getTransformer(); + transformer.setOutputProperty(OutputKeys.METHOD, "xml"); + transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8"); + transformer.setOutputProperty(OutputKeys.INDENT, "no"); + + if (NEEDS_XMLNS_ATTRIBUTES) { + // The serializer does not output xmlns declarations, + // so we need to do it explicitly with this wrapper + return new SAXResult(new SerializingContentHandler(handler)); + } else { + return result; + } + } catch (TransformerConfigurationException e) { + throw new SAXException("Failed to initialize XML serializer", e); + } + } + + /** + * private constructor to avoid instantiation + */ + private ResultHelper() { + } + + /** + * Special content handler fixing issues with xmlns attraibutes handling. + */ + private static final class SerializingContentHandler extends DefaultHandler { + /** + * The prefixes of startPrefixMapping() declarations for the coming element. + */ + private List prefixList = new ArrayList(); + + /** + * The URIs of startPrefixMapping() declarations for the coming element. + */ + private List uriList = new ArrayList(); + + /** + * Maps of URI<->prefix mappings. Used to work around a bug in the Xalan + * serializer. + */ + private Map uriToPrefixMap = new HashMap(); + private Map prefixToUriMap = new HashMap(); + + /** + * True if there has been some startPrefixMapping() for the coming element. + */ + private boolean hasMappings = false; + + /** + * Stack of the prefixes of explicitly generated prefix mapping calls + * per each element level. An entry is appended at the beginning of each + * {@link #startElement(String, String, String, org.xml.sax.Attributes)} call and + * removed at the end of each {@link #endElement(String, String, String)} + * call. By default the entry for each element is null to + * avoid losing performance, but whenever the code detects a new prefix + * mapping that needs to be registered, the null entry is + * replaced with a list of explicitly registered prefixes for that node. + * When that element is closed, the listed prefixes get unmapped. + * + * @see #checkPrefixMapping(String, String) + * @see JCR-1767 + */ + private final List addedPrefixMappings = new ArrayList(); + + /** + * The adapted content handler instance. + */ + private final ContentHandler handler; + + private SerializingContentHandler(ContentHandler handler) { + this.handler = handler; + } + + @Override + public void characters(char[] ch, int start, int length) throws SAXException { + handler.characters(ch, start, length); + } + + @Override + public void startDocument() throws SAXException { + // Cleanup + this.uriToPrefixMap.clear(); + this.prefixToUriMap.clear(); + clearMappings(); + + handler.startDocument(); + } + + /** + * Track mappings to be able to add xmlns: attributes + * in startElement(). + */ + @Override + public void startPrefixMapping(String prefix, String uri) throws SAXException { + // Store the mappings to reconstitute xmlns:attributes + // except prefixes starting with "xml": these are reserved + // VG: (uri != null) fixes NPE in startElement + if (uri != null && !prefix.startsWith("xml")) { + this.hasMappings = true; + this.prefixList.add(prefix); + this.uriList.add(uri); + + // append the prefix colon now, in order to save concatenations later, but + // only for non-empty prefixes. + if (prefix.length() > 0) { + this.uriToPrefixMap.put(uri, prefix + ":"); + } else { + this.uriToPrefixMap.put(uri, prefix); + } + + this.prefixToUriMap.put(prefix, uri); + } + + handler.startPrefixMapping(prefix, uri); + } + + /** + * Checks whether a prefix mapping already exists for the given namespace + * and generates the required {@link #startPrefixMapping(String, String)} + * call if the mapping is not found. By default the registered prefix + * is taken from the given qualified name, but a different prefix is + * automatically selected if that prefix is already used. + * + * @see JCR-1767 + * @param uri namespace URI + * @param qname element name with the prefix, or null + * @throws SAXException if the prefix mapping can not be added + */ + private void checkPrefixMapping(String uri, String qname) + throws SAXException { + // Only add the prefix mapping if the URI is not already known + if (uri != null && uri.length() > 0 && !uri.startsWith("xml") + && !uriToPrefixMap.containsKey(uri)) { + // Get the prefix + String prefix = "ns"; + if (qname != null && qname.length() > 0) { + int colon = qname.indexOf(':'); + if (colon != -1) { + prefix = qname.substring(0, colon); + } + } + + // Make sure that the prefix is unique + String base = prefix; + for (int i = 2; prefixToUriMap.containsKey(prefix); i++) { + prefix = base + i; + } + + int last = addedPrefixMappings.size() - 1; + List prefixes = (List) addedPrefixMappings.get(last); + if (prefixes == null) { + prefixes = new ArrayList(); + addedPrefixMappings.set(last, prefixes); + } + prefixes.add(prefix); + + startPrefixMapping(prefix, uri); + } + } + + /** + * Ensure all namespace declarations are present as xmlns: attributes + * and add those needed before delegating the startElement method on the + * specified handler. This is a workaround for a Xalan bug + * (at least in version 2.0.1) : org.apache.xalan.serialize.SerializerToXML + * ignores start/endPrefixMapping(). + */ + @Override + public void startElement( + String eltUri, String eltLocalName, String eltQName, Attributes attrs) + throws SAXException { + // JCR-1767: Generate extra prefix mapping calls where needed + addedPrefixMappings.add(null); + checkPrefixMapping(eltUri, eltQName); + for (int i = 0; i < attrs.getLength(); i++) { + checkPrefixMapping(attrs.getURI(i), attrs.getQName(i)); + } + + // try to restore the qName. The map already contains the colon + if (null != eltUri && eltUri.length() != 0 && this.uriToPrefixMap.containsKey(eltUri)) { + eltQName = this.uriToPrefixMap.get(eltUri) + eltLocalName; + } + if (this.hasMappings) { + // Add xmlns* attributes where needed + + // New Attributes if we have to add some. + AttributesImpl newAttrs = null; + + int mappingCount = this.prefixList.size(); + int attrCount = attrs.getLength(); + + for (int mapping = 0; mapping < mappingCount; mapping++) { + + // Build infos for this namespace + String uri = (String) this.uriList.get(mapping); + String prefix = (String) this.prefixList.get(mapping); + String qName = prefix.equals("") ? "xmlns" : ("xmlns:" + prefix); + + // Search for the corresponding xmlns* attribute + boolean found = false; + for (int attr = 0; attr < attrCount; attr++) { + if (qName.equals(attrs.getQName(attr))) { + // Check if mapping and attribute URI match + if (!uri.equals(attrs.getValue(attr))) { + throw new SAXException("URI in prefix mapping and attribute do not match"); + } + found = true; + break; + } + } + + if (!found) { + // Need to add this namespace + if (newAttrs == null) { + // Need to test if attrs is empty or we go into an infinite loop... + // Well know SAX bug which I spent 3 hours to remind of :-( + if (attrCount == 0) { + newAttrs = new AttributesImpl(); + } else { + newAttrs = new AttributesImpl(attrs); + } + } + + if (prefix.equals("")) { + newAttrs.addAttribute(XML, qName, qName, "CDATA", uri); + } else { + newAttrs.addAttribute(XML, prefix, qName, "CDATA", uri); + } + } + } // end for mapping + + // Cleanup for the next element + clearMappings(); + + // Start element with new attributes, if any + handler.startElement(eltUri, eltLocalName, eltQName, newAttrs == null ? attrs : newAttrs); + } else { + // Normal job + handler.startElement(eltUri, eltLocalName, eltQName, attrs); + } + } + + + /** + * Receive notification of the end of an element. + * Try to restore the element qName. + */ + @Override + public void endElement(String eltUri, String eltLocalName, String eltQName) throws SAXException { + // try to restore the qName. The map already contains the colon + if (null != eltUri && eltUri.length() != 0 && this.uriToPrefixMap.containsKey(eltUri)) { + eltQName = this.uriToPrefixMap.get(eltUri) + eltLocalName; + } + + handler.endElement(eltUri, eltLocalName, eltQName); + + // JCR-1767: Generate extra prefix un-mapping calls where needed + int last = addedPrefixMappings.size() - 1; + List prefixes = (List) addedPrefixMappings.remove(last); + if (prefixes != null) { + Iterator iterator = prefixes.iterator(); + while (iterator.hasNext()) { + endPrefixMapping((String) iterator.next()); + } + } + } + + /** + * End the scope of a prefix-URI mapping: + * remove entry from mapping tables. + */ + @Override + public void endPrefixMapping(String prefix) throws SAXException { + // remove mappings for xalan-bug-workaround. + // Unfortunately, we're not passed the uri, but the prefix here, + // so we need to maintain maps in both directions. + if (this.prefixToUriMap.containsKey(prefix)) { + this.uriToPrefixMap.remove(this.prefixToUriMap.get(prefix)); + this.prefixToUriMap.remove(prefix); + } + + if (hasMappings) { + // most of the time, start/endPrefixMapping calls have an element event between them, + // which will clear the hasMapping flag and so this code will only be executed in the + // rather rare occasion when there are start/endPrefixMapping calls with no element + // event in between. If we wouldn't remove the items from the prefixList and uriList here, + // the namespace would be incorrectly declared on the next element following the + // endPrefixMapping call. + int pos = prefixList.lastIndexOf(prefix); + if (pos != -1) { + prefixList.remove(pos); + uriList.remove(pos); + } + } + + handler.endPrefixMapping(prefix); + } + + @Override + public void ignorableWhitespace(char[] ch, int start, int length) throws SAXException { + handler.ignorableWhitespace(ch, start, length); + } + + @Override + public void processingInstruction(String target, String data) throws SAXException { + handler.processingInstruction(target, data); + } + + @Override + public void setDocumentLocator(Locator locator) { + handler.setDocumentLocator(locator); + } + + @Override + public void skippedEntity(String name) throws SAXException { + handler.skippedEntity(name); + } + + @Override + public void endDocument() throws SAXException { + // Cleanup + this.uriToPrefixMap.clear(); + this.prefixToUriMap.clear(); + clearMappings(); + + handler.endDocument(); + } + + private void clearMappings() { + this.hasMappings = false; + this.prefixList.clear(); + this.uriList.clear(); + } + } +} \ No newline at end of file Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/xml/ResultHelper.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-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/xml/XmlSerializable.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/xml/XmlSerializable.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/xml/XmlSerializable.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.webdav.xml; + +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +/** + * XmlSerializable... + */ +public interface XmlSerializable { + + /** + * Returns the xml representation of the implementing object as + * {@link org.w3c.dom.Element}. The given Document is used + * as factory and represents the {@link org.w3c.dom.Element#getOwnerDocument() + * owner document} of the returned DOM element. + * + * @return a w3c element representing this object + * @param document to be used as factory. + */ + public Element toXml(Document document); + +} \ No newline at end of file Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/xml/XmlSerializable.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-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/xml/package-info.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/xml/package-info.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/xml/package-info.java (working copy) @@ -0,0 +1,18 @@ +/* + * 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. + */ +@org.osgi.annotation.versioning.Version("1.2.0") +package org.apache.jackrabbit.webdav.xml; Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/xml/package-info.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/javadoc/org/apache/jackrabbit/webdav/client/methods/package.html =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/javadoc/org/apache/jackrabbit/webdav/client/methods/package.html (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/javadoc/org/apache/jackrabbit/webdav/client/methods/package.html (working copy) @@ -0,0 +1,93 @@ + + +

+This package contains classes and utilities used to build a WebDAV client +implementation.
+Currently it consists of DAV-specific extensions to the +Jakarta Commons HttpClient, +namely a set of methods. +

+ +

+

How to use Jakarta Commons HttpClient

+Please refer to the + tutorial + present with Jakarta Commons HttpClient for detailed +instructions. +

+ +

+

Simple Example

+The following simple example illustrates the additional functionality exposed + by the DavMethod which serves as basic interface for all + WebDAV specific extensions:

+ +First you need to create the HostConfiguration which at least + must define the uri pointing to your WebDAV enabled server +
+    String uri = "http://your-webdav-server";
+    HostConfiguration hostConfig = new HostConfiguration();
+    hostConfig.setHost(uri);
+
+ +Define a HttpConnectionManager, which also is responsible + for eventual multithreading support: +
+    HttpConnectionManager connectionManager = new MultiThreadedHttpConnectionManager();
+    HttpConnectionManagerParams params = new HttpConnectionManagerParams();
+    int maxHostConnections = 20;
+    params.setMaxConnectionsPerHost(hostConfig, maxHostConnections);
+    connectionManager.setParams(params);
+
+ +Create the HttpClient object and eventually pass the Credentials: +
+    HttpClient client = new HttpClient(connectionManager);
+    client.setHostConfiguration(hostConfig);
+    Credentials creds = new UsernamePasswordCredentials("userId", "pw");
+    client.getState().setCredentials(AuthScope.ANY, creds);
+
+ +In order to execute a WebDAV request, choose the appropriate DavMethod. + For example, a PROPFIND request could look as follows: +
+    String propfindUri = "http://your-webdav-server/anyresource";
+    DavMethod method = new PropFindMethod(propfindUri, DavConstants.PROPFIND_ALL_PROP, DavConstants.DEPTH_1);
+    client.executeMethod(method);
+
+ +The DavMethod interface defines two methods that allows you to determine if the + request was successfully executed without need to evaluate the status line and + knowing about the required status codes: +
    +
  • DavMethod.checkSuccess()
  • +
  • DavMethod.succeeded()
  • +
+ +
+    method.checkSuccess();
+
+ +In case of success you can retrieve the response body in an appropriate formate + and process it according to you needs,
+ For a PROPFIND request use e.g. DavMethod.getResponseBodyAsMultiStatus(): +
+    MultiStatus multiStatus = method.getResponseBodyAsMultiStatus();
+
+

+ \ No newline at end of file Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/javadoc/org/apache/jackrabbit/webdav/client/methods/package.html ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/javadoc/org/apache/jackrabbit/webdav/lock/package.html =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/javadoc/org/apache/jackrabbit/webdav/lock/package.html (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/javadoc/org/apache/jackrabbit/webdav/lock/package.html (working copy) @@ -0,0 +1,19 @@ + + +Provides interfaces and classes for locking related issues. + Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/javadoc/org/apache/jackrabbit/webdav/lock/package.html ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/javadoc/org/apache/jackrabbit/webdav/observation/package.html =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/javadoc/org/apache/jackrabbit/webdav/observation/package.html (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/javadoc/org/apache/jackrabbit/webdav/observation/package.html (working copy) @@ -0,0 +1,20 @@ + + +Contains interfaces and classes related to observation, which is not covered +by the WebDAV protocol. + Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/javadoc/org/apache/jackrabbit/webdav/observation/package.html ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/javadoc/org/apache/jackrabbit/webdav/ordering/package.html =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/javadoc/org/apache/jackrabbit/webdav/ordering/package.html (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/javadoc/org/apache/jackrabbit/webdav/ordering/package.html (working copy) @@ -0,0 +1,21 @@ + + +Contains interfaces and classes used to cover the functionality defined by the +RFC 3648: Web Distributed Authoring +and Versioning (WebDAV) Ordered Collections Protocol . + Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/javadoc/org/apache/jackrabbit/webdav/ordering/package.html ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/javadoc/org/apache/jackrabbit/webdav/property/package.html =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/javadoc/org/apache/jackrabbit/webdav/property/package.html (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/javadoc/org/apache/jackrabbit/webdav/property/package.html (working copy) @@ -0,0 +1,19 @@ + + +Interfaces and classes related to WebDAV properties. + Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/javadoc/org/apache/jackrabbit/webdav/property/package.html ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/javadoc/org/apache/jackrabbit/webdav/search/package.html =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/javadoc/org/apache/jackrabbit/webdav/search/package.html (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/javadoc/org/apache/jackrabbit/webdav/search/package.html (working copy) @@ -0,0 +1,21 @@ + + +Contains interfaces and classes used to cover the functionality defined by the +Internet +Draft WebDAV Search. + Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/javadoc/org/apache/jackrabbit/webdav/search/package.html ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/javadoc/org/apache/jackrabbit/webdav/transaction/package.html =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/javadoc/org/apache/jackrabbit/webdav/transaction/package.html (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/javadoc/org/apache/jackrabbit/webdav/transaction/package.html (working copy) @@ -0,0 +1,19 @@ + + +Contains interfaces and classes related to transaction locks. + Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/javadoc/org/apache/jackrabbit/webdav/transaction/package.html ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/javadoc/org/apache/jackrabbit/webdav/util/package.html =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/javadoc/org/apache/jackrabbit/webdav/util/package.html (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/javadoc/org/apache/jackrabbit/webdav/util/package.html (working copy) @@ -0,0 +1,19 @@ + + +Common utility classes. + Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/javadoc/org/apache/jackrabbit/webdav/util/package.html ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/javadoc/org/apache/jackrabbit/webdav/version/package.html =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/javadoc/org/apache/jackrabbit/webdav/version/package.html (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/javadoc/org/apache/jackrabbit/webdav/version/package.html (working copy) @@ -0,0 +1,20 @@ + + +Interfaces and classes used to cover functionality defined by +RFC 3253: Versioning Extensions to WebDAV. + Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/javadoc/org/apache/jackrabbit/webdav/version/package.html ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/javadoc/org/apache/jackrabbit/webdav/version/report/package.html =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/javadoc/org/apache/jackrabbit/webdav/version/report/package.html (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/javadoc/org/apache/jackrabbit/webdav/version/report/package.html (working copy) @@ -0,0 +1,19 @@ + + +Report interface and inplementation for default reports defined by RFC 3253. + Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/javadoc/org/apache/jackrabbit/webdav/version/report/package.html ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/javadoc/org/apache/jackrabbit/webdav/xml/package.html =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/javadoc/org/apache/jackrabbit/webdav/xml/package.html (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/javadoc/org/apache/jackrabbit/webdav/xml/package.html (working copy) @@ -0,0 +1,19 @@ + + +Xml utility classes. + Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/javadoc/org/apache/jackrabbit/webdav/xml/package.html ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/main/resources/org/apache/jackrabbit/webdav/statuscode.properties =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/main/resources/org/apache/jackrabbit/webdav/statuscode.properties (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/main/resources/org/apache/jackrabbit/webdav/statuscode.properties (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. + +100=Continue +101=Switching Protocols +102=Processing +200=OK +201=Created +202=Accepted +203=Non-Authoritative Information +204=No Content +205=Reset Content +206=Partial Content +207=Multi-Status +300=Multiple Choices +301=Moved Permanently +302=Found +303=See Other +304=Not Modified +305=Use Proxy +307=Temporary Redirect +400=Bad Request +401=Unauthorized +402=Payment Required +403=Forbidden +404=Not Found +405=Method Not Allowed +406=Not Acceptable +407=Proxy Authentication Required +408=Request Time-out +409=Conflict +410=Gone +411=Length Required +412=Precondition Failed +413=Request Entity Too Large +414=Request-URI Too Large +415=Unsupported Media Type +416=Requested range not satisfiable +417=Expectation Failed +420=Method Failure +422=Unprocessable Entity +423=Locked +424=Failed Dependency +500=Internal Server Error +501=Not Implemented +502=Bad Gateway +503=Service Unavailable +504=Gateway Time-out +505=HTTP Version not supported +507=Insufficient Storage Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/main/resources/org/apache/jackrabbit/webdav/statuscode.properties ___________________________________________________________________ Added: svn Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/test/java/org/apache/jackrabbit/webdav/header/FieldValueParserTest.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/test/java/org/apache/jackrabbit/webdav/header/FieldValueParserTest.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/test/java/org/apache/jackrabbit/webdav/header/FieldValueParserTest.java (working copy) @@ -0,0 +1,42 @@ +/* + * 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.webdav.header; + +import java.util.List; + +import org.junit.Test; +import static org.junit.Assert.assertArrayEquals; + +import junit.framework.TestCase; + +public class FieldValueParserTest extends TestCase { + + @Test + public void testDavComplianceHeader() { + + List l; + + l = FieldValueParser.tokenizeList("1"); + assertArrayEquals(new String[]{"1"}, l.toArray()); + + l = FieldValueParser.tokenizeList("1,2,,,,,3,,bind,"); + assertArrayEquals(new String[]{"1","2","3","bind"}, l.toArray()); + + l = FieldValueParser.tokenizeList("1,2,"); + assertArrayEquals(new String[]{"1","2",""}, l.toArray()); + } +} Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/test/java/org/apache/jackrabbit/webdav/header/FieldValueParserTest.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/test/java/org/apache/jackrabbit/webdav/header/TestAll.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/test/java/org/apache/jackrabbit/webdav/header/TestAll.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/test/java/org/apache/jackrabbit/webdav/header/TestAll.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.webdav.header; + +import junit.framework.Test; +import junit.framework.TestCase; +import junit.framework.TestSuite; + +public class TestAll extends TestCase { + + public static Test suite() { + TestSuite suite = new TestSuite("WebDAV header tests"); + + suite.addTestSuite(FieldValueParserTest.class); + + return suite; + } +} \ No newline at end of file Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/test/java/org/apache/jackrabbit/webdav/header/TestAll.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/test/java/org/apache/jackrabbit/webdav/io/OutputContextImplTest.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/test/java/org/apache/jackrabbit/webdav/io/OutputContextImplTest.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/test/java/org/apache/jackrabbit/webdav/io/OutputContextImplTest.java (working copy) @@ -0,0 +1,186 @@ +/* + * 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.webdav.io; + +import junit.framework.TestCase; + +import javax.servlet.http.HttpServletResponse; +import javax.servlet.http.Cookie; +import javax.servlet.ServletOutputStream; +import java.io.IOException; +import java.io.PrintWriter; +import java.util.Collection; +import java.util.Locale; + +/** + * OutputContextImplTest... + */ +public class OutputContextImplTest extends TestCase { + + public void testSetContentLength() { + HttpServletResponse response = new DummyResponse() { + @Override + public void setContentLength(int len) { + assertTrue(len >= 0); + } + @Override + public void setHeader(String name, String value) { + assertTrue(Long.parseLong(value) > Integer.MAX_VALUE); + } + @Override + public String getContentType() { + return null; + } + @Override + public void setCharacterEncoding(String charset) { + } + @Override + public int getStatus() { + return 0; + } + @Override + public String getHeader(String name) { + return null; + } + @Override + public Collection getHeaders(String name) { + return null; + } + @Override + public Collection getHeaderNames() { + return null; + } + @Override + public void setContentLengthLong(long len) { + } + }; + + OutputContext ctx = new OutputContextImpl(response, null); + + ctx.setContentLength(Long.MAX_VALUE); + ctx.setContentLength(Long.MIN_VALUE); + ctx.setContentLength(Integer.MAX_VALUE); + ctx.setContentLength((long) Integer.MAX_VALUE + 1); + ctx.setContentLength(0); + ctx.setContentLength(-1); + ctx.setContentLength(12345); + } + + private abstract class DummyResponse implements HttpServletResponse { + + public void addCookie(Cookie cookie) { + } + + public boolean containsHeader(String name) { + return false; + } + + public String encodeURL(String url) { + return null; + } + + public String encodeRedirectURL(String url) { + return null; + } + + public String encodeUrl(String url) { + return null; + } + + public String encodeRedirectUrl(String url) { + return null; + } + + public void sendError(int sc, String msg) throws IOException { + } + + public void sendError(int sc) throws IOException { + } + + public void sendRedirect(String location) throws IOException { + } + + public void setDateHeader(String name, long date) { + } + + public void addDateHeader(String name, long date) { + } + + public void setHeader(String name, String value) { + } + + public void addHeader(String name, String value) { + } + + public void setIntHeader(String name, int value) { + } + + public void addIntHeader(String name, int value) { + } + + public void setStatus(int sc) { + } + + public void setStatus(int sc, String sm) { + } + + public String getCharacterEncoding() { + return null; + } + + public ServletOutputStream getOutputStream() throws IOException { + return null; + } + + public PrintWriter getWriter() throws IOException { + return null; + } + + public void setContentLength(int len) { + } + + public void setContentType(String type) { + } + + public void setBufferSize(int size) { + } + + public int getBufferSize() { + return 0; + } + + public void flushBuffer() throws IOException { + } + + public void resetBuffer() { + } + + public boolean isCommitted() { + return false; + } + + public void reset() { + } + + public void setLocale(Locale loc) { + } + + public Locale getLocale() { + return null; + } + } +} Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/test/java/org/apache/jackrabbit/webdav/io/OutputContextImplTest.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-webdav-project/jackrabbit-webdav/src/test/java/org/apache/jackrabbit/webdav/io/TestAll.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/test/java/org/apache/jackrabbit/webdav/io/TestAll.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/test/java/org/apache/jackrabbit/webdav/io/TestAll.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.webdav.io; + +import junit.framework.Test; +import junit.framework.TestCase; +import junit.framework.TestSuite; + +public class TestAll extends TestCase { + + public static Test suite() { + TestSuite suite = new TestSuite("WebDAV IO tests"); + + suite.addTestSuite(OutputContextImplTest.class); + + return suite; + } +} \ No newline at end of file Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/test/java/org/apache/jackrabbit/webdav/io/TestAll.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-webdav-project/jackrabbit-webdav/src/test/java/org/apache/jackrabbit/webdav/lock/ActiveLockTest.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/test/java/org/apache/jackrabbit/webdav/lock/ActiveLockTest.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/test/java/org/apache/jackrabbit/webdav/lock/ActiveLockTest.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.webdav.lock; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.w3c.dom.Document; +import org.apache.jackrabbit.webdav.xml.DomUtil; +import junit.framework.TestCase; + +import javax.xml.parsers.ParserConfigurationException; +import java.util.List; + +/** + * ActiveLockTest... + */ +public class ActiveLockTest extends TestCase { + + /** + * logger instance + */ + private static final Logger log = LoggerFactory.getLogger(ActiveLockTest.class); + + public void testGetLockRoot() { + ActiveLock lock = new DefaultActiveLock(); + lock.setLockroot("lockroot"); + + assertEquals("lockroot", lock.getLockroot()); + } + + public void testParsing() throws ParserConfigurationException { + Document doc = DomUtil.createDocument(); + + ActiveLock lock = new DefaultActiveLock(); + lock.setLockroot("lockroot"); + lock.setOwner("owner"); + lock.setIsDeep(true); + + LockDiscovery disc = LockDiscovery.createFromXml(new LockDiscovery(lock).toXml(doc)); + List l = disc.getValue(); + + assertFalse(l.isEmpty()); + assertEquals(1, l.size()); + ActiveLock al = l.get(0); + + assertEquals("lockroot", al.getLockroot()); + assertEquals("owner", al.getOwner()); + assertTrue(al.isDeep()); + } +} Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/test/java/org/apache/jackrabbit/webdav/lock/ActiveLockTest.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-webdav-project/jackrabbit-webdav/src/test/java/org/apache/jackrabbit/webdav/lock/TestAll.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/test/java/org/apache/jackrabbit/webdav/lock/TestAll.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/test/java/org/apache/jackrabbit/webdav/lock/TestAll.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.webdav.lock; + +import junit.framework.Test; +import junit.framework.TestCase; +import junit.framework.TestSuite; + +public class TestAll extends TestCase { + + public static Test suite() { + TestSuite suite = new TestSuite("WebDAV lock tests"); + + suite.addTestSuite(ActiveLockTest.class); + + return suite; + } +} \ No newline at end of file Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/test/java/org/apache/jackrabbit/webdav/lock/TestAll.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-webdav-project/jackrabbit-webdav/src/test/java/org/apache/jackrabbit/webdav/util/CSRFUtilTest.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/test/java/org/apache/jackrabbit/webdav/util/CSRFUtilTest.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/test/java/org/apache/jackrabbit/webdav/util/CSRFUtilTest.java (working copy) @@ -0,0 +1,412 @@ +/* + * 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.webdav.util; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.UnsupportedEncodingException; +import java.security.Principal; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Enumeration; +import java.util.HashSet; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.Set; +import java.util.Vector; + +import javax.servlet.AsyncContext; +import javax.servlet.DispatcherType; +import javax.servlet.RequestDispatcher; +import javax.servlet.ServletContext; +import javax.servlet.ServletException; +import javax.servlet.ServletInputStream; +import javax.servlet.ServletRequest; +import javax.servlet.ServletResponse; +import javax.servlet.http.Cookie; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.servlet.http.HttpSession; +import javax.servlet.http.HttpUpgradeHandler; +import javax.servlet.http.Part; + +import junit.framework.TestCase; + +/** + * CSRFUtilTest... + */ +public class CSRFUtilTest extends TestCase { + + private static final String SERVER_NAME = "localhost"; + + private static final String GET = "GET"; + private static final String POST = "POST"; + + private static final List validURLs = new ArrayList(); + private static final List invalidURLs = new ArrayList(); + + static { + validURLs.add("http://localhost:4503/jackrabbit/server"); + validURLs.add("https://localhost:4503/jackrabbit/server"); + validURLs.add("https://localhost/jackrabbit/server"); + validURLs.add("//localhost/jackrabbit/server"); + validURLs.add("/jackrabbit/server"); + + invalidURLs.add("http://invalidHost/test"); + invalidURLs.add("http://host1:8080/test"); + invalidURLs.add("http://user:pw@host2/test"); + } + + static String[] noContentType = new String[0]; + + private static void testValid(CSRFUtil util, Collection validURLs, String method, Set contentTypes) { + if (null == contentTypes) { + for (String url : validURLs) { + assertTrue(url, util.isValidRequest(createRequest(url, method, noContentType))); + } + } else { + for (String contentType : contentTypes) { + for (String url : validURLs) { + assertTrue(url, util.isValidRequest(createRequest(url, method, contentType))); + } + } + } + } + + private static void testInvalid(CSRFUtil util, Collection invalidURLs, String method, Set contentTypes) { + if (null == contentTypes) { + for (String url : validURLs) { + assertFalse(url, util.isValidRequest(createRequest(url, method, noContentType))); + } + } else { + for (String contentType : contentTypes) { + for (String url : invalidURLs) { + assertFalse(url, util.isValidRequest(createRequest(url, method, contentType))); + } + } + } + } + + private static HttpServletRequest createRequest(String url, String method, String[] contentTypes) { + return new DummyRequest(url, SERVER_NAME, method, contentTypes); + } + + private static HttpServletRequest createRequest(String url, String method, String contentType) { + return new DummyRequest(url, SERVER_NAME, method, new String[] { contentType }); + } + + public void testNullConfig() throws Exception { + CSRFUtil util = new CSRFUtil(null); + testValid(util, validURLs, POST, CSRFUtil.CONTENT_TYPES); + testInvalid(util, invalidURLs, POST, CSRFUtil.CONTENT_TYPES); + } + + public void testEmptyConfig() throws Exception { + CSRFUtil util = new CSRFUtil(""); + testValid(util, validURLs, POST, CSRFUtil.CONTENT_TYPES); + testInvalid(util, invalidURLs, POST, CSRFUtil.CONTENT_TYPES); + } + + public void testNoReferrer() throws Exception { + CSRFUtil util = new CSRFUtil(""); + testValid(util, validURLs, POST, CSRFUtil.CONTENT_TYPES); + assertFalse("no referrer", util.isValidRequest(createRequest(null, POST, "text/plain"))); + assertFalse("no referrer", util.isValidRequest(createRequest(null, POST, noContentType))); + assertFalse("no referrer", util.isValidRequest(createRequest(null, POST, "TEXT/PLAIN; foo=bar"))); + assertTrue("no referrer", util.isValidRequest(createRequest(null, POST, "application/json"))); + assertFalse("no referrer", util.isValidRequest(createRequest(null, POST, new String[] { "application/json", "foo/bar" }))); + } + + public void testDisabledConfig() throws Exception { + CSRFUtil util = new CSRFUtil(CSRFUtil.DISABLED); + testValid(util, validURLs, POST, CSRFUtil.CONTENT_TYPES); + // since test is disabled any other referer host must be allowed + testValid(util, invalidURLs, POST, CSRFUtil.CONTENT_TYPES); + } + + public void testConfig() throws Exception { + List configs = new ArrayList(); + configs.add("host1,host2"); + configs.add(" host1 , host2 "); + configs.add("\rhost1,\rhost2\r"); + + // hosts listed in the config must be valid + List otherHosts = new ArrayList(); + otherHosts.add("http://host1:80/test"); + otherHosts.add("http://host1/test"); + otherHosts.add("https://user:pw@host2/test"); + + List invalidURLs = new ArrayList(); + invalidURLs.add("http://invalidHost/test"); + invalidURLs.add("http://host3:8080/test"); + invalidURLs.add("https://user:pw@host4/test"); + + for (String config : configs) { + CSRFUtil util = new CSRFUtil(config); + testValid(util, validURLs, POST, CSRFUtil.CONTENT_TYPES); + testValid(util, otherHosts, POST, CSRFUtil.CONTENT_TYPES); + testInvalid(util, invalidURLs, POST, CSRFUtil.CONTENT_TYPES); + } + } + + public void testMethodsAndMediaType() throws Exception { + CSRFUtil util = new CSRFUtil(""); + testValid(util, invalidURLs, GET, CSRFUtil.CONTENT_TYPES); + testValid(util, invalidURLs, POST, new HashSet(Arrays.asList(new String[] {"application/json"}))); + testInvalid(util, invalidURLs, POST, CSRFUtil.CONTENT_TYPES); + } + + private static final class DummyRequest implements HttpServletRequest { + + private final String referer; + private final String serverName; + private final String method; + private final String[] contentTypes; + + private DummyRequest(String referer, String serverName, String method, String[] contentTypes) { + this.referer = referer; + this.serverName = serverName; + this.method = method; + this.contentTypes = contentTypes; + } + + //---------------------------------------------< HttpServletRequest >--- + + public String getHeader(String name) { + if ("Referer".equalsIgnoreCase(name)) { + return referer; + } else { + return null; + } + } + + public String getServerName() { + return serverName; + } + + public String getContentType() { + return contentTypes.length == 0 ? null : contentTypes[0]; + } + + @SuppressWarnings({ "rawtypes", "unchecked" }) + public Enumeration getHeaders(String name) { + if (name != null && contentTypes.length > 0 && name.toLowerCase(Locale.ENGLISH).equals("content-type")) { + return new Vector(Arrays.asList(contentTypes)).elements(); + } else { + return null; + } + } + + //---------------------------------------------------------< unused >--- + public String getAuthType() { + return null; + } + public Cookie[] getCookies() { + return new Cookie[0]; + } + public long getDateHeader(String name) { + return 0; + } + public Enumeration getHeaderNames() { + return null; + } + public int getIntHeader(String name) { + return 0; + } + public String getMethod() { + return method; + } + public String getPathInfo() { + return null; + } + public String getPathTranslated() { + return null; + } + public String getContextPath() { + return null; + } + public String getQueryString() { + return null; + } + public String getRemoteUser() { + return null; + } + public boolean isUserInRole(String role) { + return false; + } + public Principal getUserPrincipal() { + return null; + } + public String getRequestedSessionId() { + return null; + } + public String getRequestURI() { + return null; + } + public StringBuffer getRequestURL() { + return null; + } + public String getServletPath() { + return null; + } + public HttpSession getSession(boolean create) { + return null; + } + public HttpSession getSession() { + return null; + } + public boolean isRequestedSessionIdValid() { + return false; + } + public boolean isRequestedSessionIdFromCookie() { + return false; + } + public boolean isRequestedSessionIdFromURL() { + return false; + } + public boolean isRequestedSessionIdFromUrl() { + return false; + } + public Object getAttribute(String name) { + return null; + } + public Enumeration getAttributeNames() { + return null; + } + public String getCharacterEncoding() { + return null; + } + public void setCharacterEncoding(String s) throws UnsupportedEncodingException { + + } + public int getContentLength() { + return 0; + } + public ServletInputStream getInputStream() throws IOException { + return null; + } + public String getParameter(String name) { + return null; + } + public Enumeration getParameterNames() { + return null; + } + public String[] getParameterValues(String name) { + return new String[0]; + } + public Map getParameterMap() { + return null; + } + public String getProtocol() { + return null; + } + public String getScheme() { + return null; + } + public int getServerPort() { + return 0; + } + public BufferedReader getReader() throws IOException { + return null; + } + public String getRemoteAddr() { + return null; + } + public String getRemoteHost() { + return null; + } + public void setAttribute(String name, Object o) { + + } + public void removeAttribute(String name) { + + } + public Locale getLocale() { + return null; + } + public Enumeration getLocales() { + return null; + } + public boolean isSecure() { + return false; + } + public RequestDispatcher getRequestDispatcher(String path) { + return null; + } + public String getRealPath(String path) { + return null; + } + public int getRemotePort() { + return 0; + } + public String getLocalName() { + return null; + } + public String getLocalAddr() { + return null; + } + public int getLocalPort() { + return 0; + } + public long getContentLengthLong() { + return 0; + } + public ServletContext getServletContext() { + return null; + } + public AsyncContext startAsync() throws IllegalStateException { + return null; + } + public AsyncContext startAsync(ServletRequest servletRequest, ServletResponse servletResponse) + throws IllegalStateException { + return null; + } + public boolean isAsyncStarted() { + return false; + } + public boolean isAsyncSupported() { + return false; + } + public AsyncContext getAsyncContext() { + return null; + } + public DispatcherType getDispatcherType() { + return null; + } + public String changeSessionId() { + return null; + } + public boolean authenticate(HttpServletResponse response) throws IOException, ServletException { + return false; + } + public void login(String username, String password) throws ServletException { + } + public void logout() throws ServletException { + } + public Collection getParts() throws IOException, ServletException { + return null; + } + public Part getPart(String name) throws IOException, ServletException { + return null; + } + public T upgrade(Class handlerClass) throws IOException, ServletException { + return null; + } + } +} \ No newline at end of file Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/test/java/org/apache/jackrabbit/webdav/util/CSRFUtilTest.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-webdav-project/jackrabbit-webdav/src/test/java/org/apache/jackrabbit/webdav/util/HttpDateTimeFormatterTest.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/test/java/org/apache/jackrabbit/webdav/util/HttpDateTimeFormatterTest.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/test/java/org/apache/jackrabbit/webdav/util/HttpDateTimeFormatterTest.java (working copy) @@ -0,0 +1,65 @@ +/* + * 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.webdav.util; + +import java.time.format.DateTimeParseException; + +import junit.framework.TestCase; + +public class HttpDateTimeFormatterTest extends TestCase { + + public void testImfDate() { + long t = HttpDateTimeFormatter.parseImfFixedDate("Sun, 06 Nov 1994 08:49:37 GMT"); + assertEquals(784111777000l, t); + assertEquals("Sun, 06 Nov 1994 08:49:37 GMT", HttpDateTimeFormatter.formatImfFixed(t)); + } + + public void testImfDateWrongTZ() { + try { + HttpDateTimeFormatter.parseImfFixedDate("Sun, 06 Nov 1994 08:49:37 CET"); + fail("should fail for incorrec tz"); + } catch (DateTimeParseException expected) { + } + } + + public void testImfDateWrongWeekday() { + try { + HttpDateTimeFormatter.parseImfFixedDate("Mon, 06 Nov 1994 08:49:37 GMT"); + fail("should fail for incorrec tz"); + } catch (DateTimeParseException expected) { + } + } + + // will fail after 2044 + public void testRFC850Date() { + long t = HttpDateTimeFormatter.parseRfc850Date("Sunday, 06-Nov-94 08:49:37 GMT"); + assertEquals(784111777000l, t); + assertEquals("Sunday, 06-Nov-94 08:49:37 GMT", HttpDateTimeFormatter.formatRfc850(t)); + } + + public void testAscTimeDate() { + long t = HttpDateTimeFormatter.parseAscTimeDate("Sun Nov 6 08:49:37 1994"); + assertEquals(784111777000l, t); + assertEquals("Sun Nov 6 08:49:37 1994", HttpDateTimeFormatter.formatAscTime(t)); + } + + public void testAscTimeDateZeroPad() { + long t = HttpDateTimeFormatter.parseAscTimeDate("Sun Nov 06 08:49:37 1994"); + assertEquals(784111777000l, t); + assertEquals("Sun Nov 6 08:49:37 1994", HttpDateTimeFormatter.formatAscTime(t)); + } +} Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/test/java/org/apache/jackrabbit/webdav/util/HttpDateTimeFormatterTest.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/test/java/org/apache/jackrabbit/webdav/util/LinkHeaderFieldParserTest.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/test/java/org/apache/jackrabbit/webdav/util/LinkHeaderFieldParserTest.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/test/java/org/apache/jackrabbit/webdav/util/LinkHeaderFieldParserTest.java (working copy) @@ -0,0 +1,65 @@ +/* + * 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.webdav.util; + +import java.util.Collections; + +import junit.framework.TestCase; + +/** + * LinkHeaderFieldParserTest... + */ +public class LinkHeaderFieldParserTest extends TestCase { + + public void testSimple() { + LinkHeaderFieldParser lhfp = new LinkHeaderFieldParser( + Collections.singletonList("; rel=foo")); + assertEquals("a", lhfp.getFirstTargetForRelation("foo")); + } + + public void testMulti() { + LinkHeaderFieldParser lhfp = new LinkHeaderFieldParser( + Collections.singletonList("; rel=foo, ; rel=bar")); + assertEquals("b", lhfp.getFirstTargetForRelation("bar")); + } + + public void testMultiQs() { + LinkHeaderFieldParser lhfp = new LinkHeaderFieldParser( + Collections + .singletonList("; rel=\"fo\\\"o,\", ; rel=bar")); + assertEquals("b,", lhfp.getFirstTargetForRelation("bar")); + } + + // broken by change to httpclient 4 +// public void testTruncated() { +// LinkHeaderFieldParser lhfp = new LinkHeaderFieldParser( +// Collections.singletonList("; rel=\"x\\\"")); +// assertEquals("a,", lhfp.getFirstTargetForRelation("x\\")); +// } + + public void testCommas() { + LinkHeaderFieldParser lhfp = new LinkHeaderFieldParser( + Collections.singletonList(",; rel=\"xy,z\",")); + assertEquals("a", lhfp.getFirstTargetForRelation("xy,z")); + } + + public void testMultiRel() { + LinkHeaderFieldParser lhfp = new LinkHeaderFieldParser( + Collections.singletonList(",; rel=\"a b\"")); + assertEquals("a", lhfp.getFirstTargetForRelation("a")); + } +} Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/test/java/org/apache/jackrabbit/webdav/util/LinkHeaderFieldParserTest.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/test/java/org/apache/jackrabbit/webdav/util/TestAll.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/test/java/org/apache/jackrabbit/webdav/util/TestAll.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/test/java/org/apache/jackrabbit/webdav/util/TestAll.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.webdav.util; + +import junit.framework.Test; +import junit.framework.TestCase; +import junit.framework.TestSuite; + +/** + * Test suite that includes all testcases for package org.apache.jackrabbit.webdav.util. + */ +public class TestAll extends TestCase { + + /** + * Returns a Test suite that executes all tests inside this + * package. + */ + public static Test suite() { + TestSuite suite = new TestSuite("org.apache.jackrabbit.webdav.util tests"); + + suite.addTestSuite(CSRFUtilTest.class); + suite.addTestSuite(LinkHeaderFieldParserTest.class); + + return suite; + } +} Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/test/java/org/apache/jackrabbit/webdav/util/TestAll.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-webdav-project/jackrabbit-webdav/src/test/java/org/apache/jackrabbit/webdav/xml/NamespaceTest.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/test/java/org/apache/jackrabbit/webdav/xml/NamespaceTest.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/test/java/org/apache/jackrabbit/webdav/xml/NamespaceTest.java (working copy) @@ -0,0 +1,94 @@ +/* + * 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.webdav.xml; + +import junit.framework.TestCase; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.HashMap; +import java.util.Map; + +/** + * NamespaceTest... + */ +public class NamespaceTest extends TestCase { + + /** + * logger instance + */ + private static final Logger log = LoggerFactory.getLogger(NamespaceTest.class); + + public void testGetNamespace() { + assertEquals(Namespace.EMPTY_NAMESPACE, Namespace.getNamespace("", "")); + assertEquals(Namespace.EMPTY_NAMESPACE, Namespace.getNamespace(null, null)); + assertEquals(Namespace.XML_NAMESPACE, Namespace.getNamespace(Namespace.XML_NAMESPACE.getPrefix(), Namespace.XML_NAMESPACE.getURI())); + assertEquals(Namespace.XMLNS_NAMESPACE, Namespace.getNamespace(Namespace.XMLNS_NAMESPACE.getPrefix(), Namespace.XMLNS_NAMESPACE.getURI())); + + Map m = new HashMap(); + m.put("foo", "http://foo.org/ns/foo"); + m.put("", "http://foo.org/ns/foo"); + m.put("off", "http://foo.org/ns/foo"); + m.put("off", ""); + + for (String prefix: m.keySet()) { + String uri = m.get(prefix); + Namespace ns = Namespace.getNamespace(prefix, uri); + assertEquals(prefix, ns.getPrefix()); + assertEquals(uri, ns.getURI()); + assertEquals(ns, Namespace.getNamespace(prefix, uri)); + } + } + + public void testIsSame() { + Map same = new HashMap(); + same.put("http://foo.org/ns/foo", Namespace.getNamespace("foo", "http://foo.org/ns/foo")); + same.put("http://foo.org/ns/foo", Namespace.getNamespace("abc", "http://foo.org/ns/foo")); + same.put("http://foo.org/ns/foo", Namespace.getNamespace("", "http://foo.org/ns/foo")); + same.put("http://foo.org/ns/foo", Namespace.getNamespace(null, "http://foo.org/ns/foo")); + same.put("", Namespace.EMPTY_NAMESPACE); + same.put(null, Namespace.EMPTY_NAMESPACE); + same.put(Namespace.XML_NAMESPACE.getURI(), Namespace.XML_NAMESPACE); + same.put(Namespace.XMLNS_NAMESPACE.getURI(), Namespace.XMLNS_NAMESPACE); + + for (String nsURI : same.keySet()) { + assertTrue(nsURI, same.get(nsURI).isSame(nsURI)); + } + + Map notSame = new HashMap(); + notSame.put("http://foo.org/ns/abc", Namespace.getNamespace("foo", "http://foo.org/ns/foo")); + notSame.put("", Namespace.getNamespace("abc", "http://foo.org/ns/foo")); + notSame.put(null, Namespace.getNamespace("", "http://foo.org/ns/foo")); + notSame.put("http://foo.org/ns/abc", Namespace.EMPTY_NAMESPACE); + notSame.put(Namespace.XML_NAMESPACE.getURI(), Namespace.EMPTY_NAMESPACE); + notSame.put(Namespace.EMPTY_NAMESPACE.getURI(), Namespace.XML_NAMESPACE); + notSame.put(Namespace.XMLNS_NAMESPACE.getURI(), Namespace.XML_NAMESPACE); + notSame.put(Namespace.XML_NAMESPACE.getURI(), Namespace.XMLNS_NAMESPACE); + + for (String nsURI : notSame.keySet()) { + assertFalse(notSame.get(nsURI).isSame(nsURI)); + } + } + + public void testEquals() { + assertEquals(Namespace.EMPTY_NAMESPACE, Namespace.getNamespace("prefix", "")); + assertEquals(Namespace.EMPTY_NAMESPACE, Namespace.getNamespace("prefix", null)); + + assertFalse(Namespace.EMPTY_NAMESPACE.equals(Namespace.getNamespace("", "something"))); + assertFalse(Namespace.EMPTY_NAMESPACE.equals(Namespace.getNamespace(null, "something"))); + } +} \ No newline at end of file Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/test/java/org/apache/jackrabbit/webdav/xml/NamespaceTest.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-webdav-project/jackrabbit-webdav/src/test/java/org/apache/jackrabbit/webdav/xml/ParserTest.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/test/java/org/apache/jackrabbit/webdav/xml/ParserTest.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/test/java/org/apache/jackrabbit/webdav/xml/ParserTest.java (working copy) @@ -0,0 +1,143 @@ +/* + * 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.webdav.xml; + +import java.io.ByteArrayInputStream; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.UnsupportedEncodingException; + +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; + +import junit.framework.TestCase; + +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.xml.sax.EntityResolver; +import org.xml.sax.InputSource; +import org.xml.sax.SAXException; + +public class ParserTest extends TestCase { + + // see + public void testBillionLaughs() throws UnsupportedEncodingException { + + String testBody = "" + "" + " " + + " " + + " " + + " " + + " " + + " " + + " " + + " " + + " " + + " " + "]>" + "&lol9;"; + InputStream is = new ByteArrayInputStream(testBody.getBytes("UTF-8")); + + try { + DomUtil.parseDocument(is); + fail("parsing this document should cause an exception"); + } catch (Exception expected) { + } + } + + public void testExternalEntities() throws IOException { + + String dname = "target"; + String fname = "test.xml"; + + File f = new File(dname, fname); + OutputStream os = new FileOutputStream(f); + os.write("testdata".getBytes()); + os.close(); + + String testBody = "\n" + + "]>\n&test;"; + InputStream is = new ByteArrayInputStream(testBody.getBytes("UTF-8")); + + try { + Document d = DomUtil.parseDocument(is); + Element root = d.getDocumentElement(); + String text = DomUtil.getText(root); + fail("parsing this document should cause an exception, but the following external content was included: " + text); + } catch (Exception expected) { + } + } + + public void testCustomEntityResolver() throws ParserConfigurationException, SAXException, IOException { + + try { + DocumentBuilderFactory dbf = new DocumentBuilderFactory() { + + DocumentBuilderFactory def = DocumentBuilderFactory.newInstance(); + + @Override + public void setFeature(String name, boolean value) throws ParserConfigurationException { + def.setFeature(name, value); + } + + @Override + public void setAttribute(String name, Object value) throws IllegalArgumentException { + def.setAttribute(name, value); + } + + @Override + public DocumentBuilder newDocumentBuilder() throws ParserConfigurationException { + DocumentBuilder db = def.newDocumentBuilder(); + db.setEntityResolver(new EntityResolver() { + @Override + public InputSource resolveEntity(String publicId, String systemId) throws SAXException, IOException { + if ("foo:test".equals(systemId)) { + return new InputSource(new ByteArrayInputStream("foo&bar".getBytes("UTF-8"))); + } else { + return null; + } + } + }); + return db; + } + + @Override + public boolean getFeature(String name) throws ParserConfigurationException { + return def.getFeature(name); + } + + @Override + public Object getAttribute(String name) throws IllegalArgumentException { + return def.getAttribute(name); + } + }; + + DomUtil.setBuilderFactory(dbf); + String testBody = "\n" + + "]>\n&test;"; + InputStream is = new ByteArrayInputStream(testBody.getBytes("UTF-8")); + + Document d = DomUtil.parseDocument(is); + Element root = d.getDocumentElement(); + String text = DomUtil.getText(root); + assertEquals("custom entity resolver apparently not called", "foo&bar", text); + } finally { + DomUtil.setBuilderFactory(null); + } + } +} \ No newline at end of file Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/test/java/org/apache/jackrabbit/webdav/xml/ParserTest.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav/src/test/java/org/apache/jackrabbit/webdav/xml/TestAll.java =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/test/java/org/apache/jackrabbit/webdav/xml/TestAll.java (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/test/java/org/apache/jackrabbit/webdav/xml/TestAll.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.webdav.xml; + +import junit.framework.Test; +import junit.framework.TestCase; +import junit.framework.TestSuite; + +/** + * Test suite that includes all testcases for package org.apache.jackrabbit.webdav.xml. + */ +public class TestAll extends TestCase { + + /** + * Returns a Test suite that executes all tests inside this + * package. + */ + public static Test suite() { + TestSuite suite = new TestSuite("org.apache.jackrabbit.webdav.xml tests"); + + suite.addTestSuite(NamespaceTest.class); + suite.addTestSuite(ParserTest.class); + + return suite; + } +} Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/test/java/org/apache/jackrabbit/webdav/xml/TestAll.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-webdav-project/jackrabbit-webdav/src/test/resources/logback-test.xml =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav/src/test/resources/logback-test.xml (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav/src/test/resources/logback-test.xml (working copy) @@ -0,0 +1,31 @@ + + + + + + target/jcr.log + + %date{HH:mm:ss.SSS} %-5level %-40([%thread] %F:%L) %msg%n + + + + + + + + Property changes on: jackrabbit-webdav-project/jackrabbit-webdav/src/test/resources/logback-test.xml ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav (working copy) Property changes on: jackrabbit-webdav-project/jackrabbit-webdav ___________________________________________________________________ Added: svn:ignore ## -0,0 +1,5 ## +target +.* +*.iws +*.ipr +*.iml Index: jackrabbit-webdav-project/jackrabbit-webdav-jakarta/.classpath =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav-jakarta/.classpath (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav-jakarta/.classpath (working copy) @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Index: jackrabbit-webdav-project/jackrabbit-webdav-jakarta/.project =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav-jakarta/.project (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav-jakarta/.project (working copy) @@ -0,0 +1,23 @@ + + + jackrabbit-webdav-jakarta + + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.m2e.core.maven2Builder + + + + + + org.eclipse.jdt.core.javanature + org.eclipse.m2e.core.maven2Nature + + Index: jackrabbit-webdav-project/jackrabbit-webdav-jakarta/.settings/org.eclipse.core.resources.prefs =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav-jakarta/.settings/org.eclipse.core.resources.prefs (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav-jakarta/.settings/org.eclipse.core.resources.prefs (working copy) @@ -0,0 +1,6 @@ +eclipse.preferences.version=1 +encoding//src/main/java=UTF-8 +encoding//src/main/resources=UTF-8 +encoding//src/test/java=UTF-8 +encoding//src/test/resources=UTF-8 +encoding/=UTF-8 Index: jackrabbit-webdav-project/jackrabbit-webdav-jakarta/.settings/org.eclipse.jdt.core.prefs =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav-jakarta/.settings/org.eclipse.jdt.core.prefs (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav-jakarta/.settings/org.eclipse.jdt.core.prefs (working copy) @@ -0,0 +1,8 @@ +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 +org.eclipse.jdt.core.compiler.compliance=1.8 +org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled +org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning +org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=ignore +org.eclipse.jdt.core.compiler.release=disabled +org.eclipse.jdt.core.compiler.source=1.8 Index: jackrabbit-webdav-project/jackrabbit-webdav-jakarta/.settings/org.eclipse.m2e.core.prefs =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav-jakarta/.settings/org.eclipse.m2e.core.prefs (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav-jakarta/.settings/org.eclipse.m2e.core.prefs (working copy) @@ -0,0 +1,4 @@ +activeProfiles= +eclipse.preferences.version=1 +resolveWorkspaceProjects=true +version=1 Index: jackrabbit-webdav-project/jackrabbit-webdav-jakarta/pom.xml =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav-jakarta/pom.xml (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav-jakarta/pom.xml (working copy) @@ -0,0 +1,83 @@ + + 4.0.0 + + org.apache.jackrabbit + jackrabbit-webdav-project + 2.21.16-SNAPSHOT + + jackrabbit-webdav-jakarta + + + + org.eclipse.transformer + transformer-maven-plugin + 0.5.0 + true + + + true + + + + + default-jar + + jar + + + + org.apache.jackrabbit + jackrabbit-webdav + ${project.version} + + + + + + + + + + apache-release + + + + org.eclipse.transformer + transformer-maven-plugin + 0.5.0 + true + + + true + + + + + source-jar + + jar + + + + org.apache.jackrabbit + jackrabbit-webdav + ${project.version} + sources + + + + + + + + + + + + jakarta.servlet + jakarta.servlet-api + 5.0.0 + provided + + + \ No newline at end of file Index: jackrabbit-webdav-project/jackrabbit-webdav-jakarta/target/.plxarc =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav-jakarta/target/.plxarc (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav-jakarta/target/.plxarc (working copy) @@ -0,0 +1 @@ +maven-shared-archive-resources \ No newline at end of file Index: jackrabbit-webdav-project/jackrabbit-webdav-jakarta/target/classes/META-INF/DEPENDENCIES =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav-jakarta/target/classes/META-INF/DEPENDENCIES (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav-jakarta/target/classes/META-INF/DEPENDENCIES (working copy) @@ -0,0 +1,29 @@ +// ------------------------------------------------------------------ +// Transitive dependencies of this project determined from the +// maven pom organized by organization. +// ------------------------------------------------------------------ + +jackrabbit-webdav-jakarta + + +From: 'QOS.ch' (http://www.qos.ch) + - JCL 1.2 implemented over SLF4J (http://www.slf4j.org) org.slf4j:jcl-over-slf4j:jar:1.7.36 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - SLF4J API Module (http://www.slf4j.org) org.slf4j:slf4j-api:jar:1.7.36 + License: MIT License (http://www.opensource.org/licenses/mit-license.php) + +From: 'The Apache Software Foundation' (http://www.apache.org/) + - Apache Commons Logging (http://commons.apache.org/proper/commons-logging/) commons-logging:commons-logging:jar:1.2 + License: The Apache Software License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache HttpClient (http://hc.apache.org/httpcomponents-client-ga) org.apache.httpcomponents:httpclient:jar:4.5.14 + License: Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache HttpCore (http://hc.apache.org/httpcomponents-core-ga) org.apache.httpcomponents:httpcore:jar:4.4.16 + License: Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt) + +From: 'The Apache Software Foundation' (https://www.apache.org/) + - Apache Commons Codec (http://commons.apache.org/proper/commons-codec/) commons-codec:commons-codec:jar:1.11 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + + + + Index: jackrabbit-webdav-project/jackrabbit-webdav-jakarta/target/classes/META-INF/LICENSE =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav-jakarta/target/classes/META-INF/LICENSE (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav-jakarta/target/classes/META-INF/LICENSE (working copy) @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed 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. Index: jackrabbit-webdav-project/jackrabbit-webdav-jakarta/target/classes/META-INF/NOTICE =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav-jakarta/target/classes/META-INF/NOTICE (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav-jakarta/target/classes/META-INF/NOTICE (working copy) @@ -0,0 +1,8 @@ + +jackrabbit-webdav-jakarta +Copyright 2004-1970 The Apache Software Foundation + +This product includes software developed at +The Apache Software Foundation (http://www.apache.org/). + + Index: jackrabbit-webdav-project/jackrabbit-webdav-jakarta/target/classes/META-INF/maven/org.apache.jackrabbit/jackrabbit-webdav-jakarta/pom.properties =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav-jakarta/target/classes/META-INF/maven/org.apache.jackrabbit/jackrabbit-webdav-jakarta/pom.properties (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav-jakarta/target/classes/META-INF/maven/org.apache.jackrabbit/jackrabbit-webdav-jakarta/pom.properties (working copy) @@ -0,0 +1,7 @@ +#Generated by Maven Integration for Eclipse +#Wed Mar 01 12:33:47 CET 2023 +m2e.projectLocation=C\:\\Development\\JackRabbit\\trunk\\jackrabbit-webdav-project\\jackrabbit-webdav-jakarta +m2e.projectName=jackrabbit-webdav-jakarta +groupId=org.apache.jackrabbit +artifactId=jackrabbit-webdav-jakarta +version=2.21.16-SNAPSHOT Index: jackrabbit-webdav-project/jackrabbit-webdav-jakarta/target/classes/META-INF/maven/org.apache.jackrabbit/jackrabbit-webdav-jakarta/pom.xml =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav-jakarta/target/classes/META-INF/maven/org.apache.jackrabbit/jackrabbit-webdav-jakarta/pom.xml (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav-jakarta/target/classes/META-INF/maven/org.apache.jackrabbit/jackrabbit-webdav-jakarta/pom.xml (working copy) @@ -0,0 +1,83 @@ + + 4.0.0 + + org.apache.jackrabbit + jackrabbit-webdav-project + 2.21.16-SNAPSHOT + + jackrabbit-webdav-jakarta + + + + org.eclipse.transformer + transformer-maven-plugin + 0.5.0 + true + + + true + + + + + default-jar + + jar + + + + org.apache.jackrabbit + jackrabbit-webdav + ${project.version} + + + + + + + + + + apache-release + + + + org.eclipse.transformer + transformer-maven-plugin + 0.5.0 + true + + + true + + + + + source-jar + + jar + + + + org.apache.jackrabbit + jackrabbit-webdav + ${project.version} + sources + + + + + + + + + + + + jakarta.servlet + jakarta.servlet-api + 5.0.0 + provided + + + \ No newline at end of file Index: jackrabbit-webdav-project/jackrabbit-webdav-jakarta/target/jackrabbit-webdav-jakarta-2.21.16-SNAPSHOT.jar =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Property changes on: jackrabbit-webdav-project/jackrabbit-webdav-jakarta/target/jackrabbit-webdav-jakarta-2.21.16-SNAPSHOT.jar ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: jackrabbit-webdav-project/jackrabbit-webdav-jakarta/target/maven-shared-archive-resources/META-INF/DEPENDENCIES =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav-jakarta/target/maven-shared-archive-resources/META-INF/DEPENDENCIES (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav-jakarta/target/maven-shared-archive-resources/META-INF/DEPENDENCIES (working copy) @@ -0,0 +1,29 @@ +// ------------------------------------------------------------------ +// Transitive dependencies of this project determined from the +// maven pom organized by organization. +// ------------------------------------------------------------------ + +jackrabbit-webdav-jakarta + + +From: 'QOS.ch' (http://www.qos.ch) + - JCL 1.2 implemented over SLF4J (http://www.slf4j.org) org.slf4j:jcl-over-slf4j:jar:1.7.36 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - SLF4J API Module (http://www.slf4j.org) org.slf4j:slf4j-api:jar:1.7.36 + License: MIT License (http://www.opensource.org/licenses/mit-license.php) + +From: 'The Apache Software Foundation' (http://www.apache.org/) + - Apache Commons Logging (http://commons.apache.org/proper/commons-logging/) commons-logging:commons-logging:jar:1.2 + License: The Apache Software License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache HttpClient (http://hc.apache.org/httpcomponents-client-ga) org.apache.httpcomponents:httpclient:jar:4.5.14 + License: Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache HttpCore (http://hc.apache.org/httpcomponents-core-ga) org.apache.httpcomponents:httpcore:jar:4.4.16 + License: Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt) + +From: 'The Apache Software Foundation' (https://www.apache.org/) + - Apache Commons Codec (http://commons.apache.org/proper/commons-codec/) commons-codec:commons-codec:jar:1.11 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + + + + Index: jackrabbit-webdav-project/jackrabbit-webdav-jakarta/target/maven-shared-archive-resources/META-INF/LICENSE =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav-jakarta/target/maven-shared-archive-resources/META-INF/LICENSE (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav-jakarta/target/maven-shared-archive-resources/META-INF/LICENSE (working copy) @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed 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. Index: jackrabbit-webdav-project/jackrabbit-webdav-jakarta/target/maven-shared-archive-resources/META-INF/NOTICE =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav-jakarta/target/maven-shared-archive-resources/META-INF/NOTICE (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav-jakarta/target/maven-shared-archive-resources/META-INF/NOTICE (working copy) @@ -0,0 +1,8 @@ + +jackrabbit-webdav-jakarta +Copyright 2004-1970 The Apache Software Foundation + +This product includes software developed at +The Apache Software Foundation (http://www.apache.org/). + + Index: jackrabbit-webdav-project/jackrabbit-webdav-jakarta/target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst =================================================================== Index: jackrabbit-webdav-project/jackrabbit-webdav-jakarta/target/maven-status/maven-compiler-plugin/testCompile/default-testCompile/inputFiles.lst =================================================================== Index: jackrabbit-webdav-project/jackrabbit-webdav-jakarta/target/test-classes/META-INF/DEPENDENCIES =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav-jakarta/target/test-classes/META-INF/DEPENDENCIES (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav-jakarta/target/test-classes/META-INF/DEPENDENCIES (working copy) @@ -0,0 +1,29 @@ +// ------------------------------------------------------------------ +// Transitive dependencies of this project determined from the +// maven pom organized by organization. +// ------------------------------------------------------------------ + +jackrabbit-webdav-jakarta + + +From: 'QOS.ch' (http://www.qos.ch) + - JCL 1.2 implemented over SLF4J (http://www.slf4j.org) org.slf4j:jcl-over-slf4j:jar:1.7.36 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - SLF4J API Module (http://www.slf4j.org) org.slf4j:slf4j-api:jar:1.7.36 + License: MIT License (http://www.opensource.org/licenses/mit-license.php) + +From: 'The Apache Software Foundation' (http://www.apache.org/) + - Apache Commons Logging (http://commons.apache.org/proper/commons-logging/) commons-logging:commons-logging:jar:1.2 + License: The Apache Software License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache HttpClient (http://hc.apache.org/httpcomponents-client-ga) org.apache.httpcomponents:httpclient:jar:4.5.14 + License: Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache HttpCore (http://hc.apache.org/httpcomponents-core-ga) org.apache.httpcomponents:httpcore:jar:4.4.16 + License: Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt) + +From: 'The Apache Software Foundation' (https://www.apache.org/) + - Apache Commons Codec (http://commons.apache.org/proper/commons-codec/) commons-codec:commons-codec:jar:1.11 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + + + + Index: jackrabbit-webdav-project/jackrabbit-webdav-jakarta/target/test-classes/META-INF/LICENSE =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav-jakarta/target/test-classes/META-INF/LICENSE (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav-jakarta/target/test-classes/META-INF/LICENSE (working copy) @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed 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. Index: jackrabbit-webdav-project/jackrabbit-webdav-jakarta/target/test-classes/META-INF/NOTICE =================================================================== --- jackrabbit-webdav-project/jackrabbit-webdav-jakarta/target/test-classes/META-INF/NOTICE (nonexistent) +++ jackrabbit-webdav-project/jackrabbit-webdav-jakarta/target/test-classes/META-INF/NOTICE (working copy) @@ -0,0 +1,8 @@ + +jackrabbit-webdav-jakarta +Copyright 2004-1970 The Apache Software Foundation + +This product includes software developed at +The Apache Software Foundation (http://www.apache.org/). + + Index: jackrabbit-webdav-project/pom.xml =================================================================== --- jackrabbit-webdav-project/pom.xml (nonexistent) +++ jackrabbit-webdav-project/pom.xml (working copy) @@ -0,0 +1,56 @@ + + 4.0.0 + + org.apache.jackrabbit + jackrabbit-parent + 2.21.16-SNAPSHOT + ../jackrabbit-parent/pom.xml + + jackrabbit-webdav-project + pom + Jackrabbit JCR Servlet Project + + jackrabbit-webdav + jackrabbit-webdav-jakarta + + + + org.osgi + org.osgi.annotation + provided + + + org.slf4j + slf4j-api + + + javax.servlet + javax.servlet-api + provided + + + org.apache.httpcomponents + httpcore + 4.4.16 + + + org.apache.httpcomponents + httpclient + 4.5.14 + + + org.slf4j + jcl-over-slf4j + + + junit + junit + test + + + ch.qos.logback + logback-classic + test + + + \ No newline at end of file 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-jakarta/.classpath =================================================================== --- jackrabbit-jcr-servlet-project/jackrabbit-jcr-servlet-jakarta/.classpath (nonexistent) +++ jackrabbit-jcr-servlet-project/jackrabbit-jcr-servlet-jakarta/.classpath (working copy) @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Index: jackrabbit-jcr-servlet-project/jackrabbit-jcr-servlet-jakarta/.project =================================================================== --- jackrabbit-jcr-servlet-project/jackrabbit-jcr-servlet-jakarta/.project (nonexistent) +++ jackrabbit-jcr-servlet-project/jackrabbit-jcr-servlet-jakarta/.project (working copy) @@ -0,0 +1,23 @@ + + + jackrabbit-jcr-servlet-jakarta + + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.m2e.core.maven2Builder + + + + + + org.eclipse.jdt.core.javanature + org.eclipse.m2e.core.maven2Nature + + Index: jackrabbit-jcr-servlet-project/jackrabbit-jcr-servlet-jakarta/.settings/org.eclipse.core.resources.prefs =================================================================== --- jackrabbit-jcr-servlet-project/jackrabbit-jcr-servlet-jakarta/.settings/org.eclipse.core.resources.prefs (nonexistent) +++ jackrabbit-jcr-servlet-project/jackrabbit-jcr-servlet-jakarta/.settings/org.eclipse.core.resources.prefs (working copy) @@ -0,0 +1,6 @@ +eclipse.preferences.version=1 +encoding//src/main/java=UTF-8 +encoding//src/main/resources=UTF-8 +encoding//src/test/java=UTF-8 +encoding//src/test/resources=UTF-8 +encoding/=UTF-8 Index: jackrabbit-jcr-servlet-project/jackrabbit-jcr-servlet-jakarta/.settings/org.eclipse.jdt.core.prefs =================================================================== --- jackrabbit-jcr-servlet-project/jackrabbit-jcr-servlet-jakarta/.settings/org.eclipse.jdt.core.prefs (nonexistent) +++ jackrabbit-jcr-servlet-project/jackrabbit-jcr-servlet-jakarta/.settings/org.eclipse.jdt.core.prefs (working copy) @@ -0,0 +1,8 @@ +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 +org.eclipse.jdt.core.compiler.compliance=1.8 +org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled +org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning +org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=ignore +org.eclipse.jdt.core.compiler.release=disabled +org.eclipse.jdt.core.compiler.source=1.8 Index: jackrabbit-jcr-servlet-project/jackrabbit-jcr-servlet-jakarta/.settings/org.eclipse.m2e.core.prefs =================================================================== --- jackrabbit-jcr-servlet-project/jackrabbit-jcr-servlet-jakarta/.settings/org.eclipse.m2e.core.prefs (nonexistent) +++ jackrabbit-jcr-servlet-project/jackrabbit-jcr-servlet-jakarta/.settings/org.eclipse.m2e.core.prefs (working copy) @@ -0,0 +1,4 @@ +activeProfiles= +eclipse.preferences.version=1 +resolveWorkspaceProjects=true +version=1 Index: jackrabbit-jcr-servlet-project/jackrabbit-jcr-servlet-jakarta/pom.xml =================================================================== --- jackrabbit-jcr-servlet-project/jackrabbit-jcr-servlet-jakarta/pom.xml (nonexistent) +++ jackrabbit-jcr-servlet-project/jackrabbit-jcr-servlet-jakarta/pom.xml (working copy) @@ -0,0 +1,83 @@ + + 4.0.0 + + org.apache.jackrabbit + jackrabbit-jcr-servlet-project + 2.21.16-SNAPSHOT + + jackrabbit-jcr-servlet-jakarta + + + + org.eclipse.transformer + transformer-maven-plugin + 0.5.0 + true + + + true + + + + + default-jar + + jar + + + + org.apache.jackrabbit + jackrabbit-jcr-servlet + ${project.version} + + + + + + + + + + apache-release + + + + org.eclipse.transformer + transformer-maven-plugin + 0.5.0 + true + + + true + + + + + source-jar + + jar + + + + org.apache.jackrabbit + jackrabbit-jcr-servlet + ${project.version} + sources + + + + + + + + + + + + jakarta.servlet + jakarta.servlet-api + 5.0.0 + provided + + + \ No newline at end of file Index: jackrabbit-jcr-servlet-project/jackrabbit-jcr-servlet-jakarta/target/.plxarc =================================================================== --- jackrabbit-jcr-servlet-project/jackrabbit-jcr-servlet-jakarta/target/.plxarc (nonexistent) +++ jackrabbit-jcr-servlet-project/jackrabbit-jcr-servlet-jakarta/target/.plxarc (working copy) @@ -0,0 +1 @@ +maven-shared-archive-resources \ No newline at end of file Index: jackrabbit-jcr-servlet-project/jackrabbit-jcr-servlet-jakarta/target/classes/META-INF/DEPENDENCIES =================================================================== --- jackrabbit-jcr-servlet-project/jackrabbit-jcr-servlet-jakarta/target/classes/META-INF/DEPENDENCIES (nonexistent) +++ jackrabbit-jcr-servlet-project/jackrabbit-jcr-servlet-jakarta/target/classes/META-INF/DEPENDENCIES (working copy) @@ -0,0 +1,53 @@ +// ------------------------------------------------------------------ +// Transitive dependencies of this project determined from the +// maven pom organized by organization. +// ------------------------------------------------------------------ + +jackrabbit-jcr-servlet-jakarta + + +From: 'Dough Lea' (http://gee.cs.oswego.edu/dl/classes/EDU/oswego/cs/dl/util/concurrent/intro.html) + - Dough Lea's util.concurrent package concurrent:concurrent:jar:1.3.4 + License: Public domain, Sun Microsoystems (>http://gee.cs.oswego.edu/dl/classes/EDU/oswego/cs/dl/util/concurrent/intro.html) + +From: 'QOS.ch' (http://www.qos.ch) + - JCL 1.2 implemented over SLF4J (http://www.slf4j.org) org.slf4j:jcl-over-slf4j:jar:1.7.36 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - SLF4J API Module (http://www.slf4j.org) org.slf4j:slf4j-api:jar:1.7.36 + License: MIT License (http://www.opensource.org/licenses/mit-license.php) + +From: 'The Apache Software Foundation' (http://www.apache.org) + - Apache Tika core (https://tika.apache.org/) org.apache.tika:tika-core:bundle:2.4.1 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + +From: 'The Apache Software Foundation' (http://www.apache.org/) + - Commons DBCP (http://commons.apache.org/dbcp/) commons-dbcp:commons-dbcp:jar:1.4 + License: The Apache Software License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt) + - Commons Pool (http://commons.apache.org/pool/) commons-pool:commons-pool:jar:1.5.4 + License: The Apache Software License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt) + - Lucene Core (http://lucene.apache.org/java/lucene-parent/lucene-core) org.apache.lucene:lucene-core:jar:3.6.0 + License: Apache 2 (http://www.apache.org/licenses/LICENSE-2.0.txt) + +From: 'The Apache Software Foundation' (https://www.apache.org/) + - Apache Commons IO (https://commons.apache.org/proper/commons-io/) commons-io:commons-io:jar:2.11.0 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Commons Collections (https://commons.apache.org/proper/commons-collections/) org.apache.commons:commons-collections4:jar:4.4 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Jackrabbit Core (http://jackrabbit.apache.org/jackrabbit-core/) org.apache.jackrabbit:jackrabbit-core:jar:2.21.16-SNAPSHOT + License: Apache-2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Jackrabbit Data (http://jackrabbit.apache.org/jackrabbit-data/) org.apache.jackrabbit:jackrabbit-data:bundle:2.21.16-SNAPSHOT + License: Apache-2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Jackrabbit JCR Commons (http://jackrabbit.apache.org/jackrabbit-jcr-commons/) org.apache.jackrabbit:jackrabbit-jcr-commons:bundle:2.21.16-SNAPSHOT + License: Apache-2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Jackrabbit JCR-RMI (http://jackrabbit.apache.org/jackrabbit-jcr-rmi/) org.apache.jackrabbit:jackrabbit-jcr-rmi:bundle:2.21.16-SNAPSHOT + License: Apache-2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Jackrabbit SPI (http://jackrabbit.apache.org/jackrabbit-spi/) org.apache.jackrabbit:jackrabbit-spi:bundle:2.21.16-SNAPSHOT + License: Apache-2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Jackrabbit SPI Commons (http://jackrabbit.apache.org/jackrabbit-spi-commons/) org.apache.jackrabbit:jackrabbit-spi-commons:bundle:2.21.16-SNAPSHOT + License: Apache-2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Jackrabbit API (http://jackrabbit.apache.org/oak-jackrabbit-api/) org.apache.jackrabbit:oak-jackrabbit-api:bundle:1.48.0 + License: Apache-2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + + + + Index: jackrabbit-jcr-servlet-project/jackrabbit-jcr-servlet-jakarta/target/classes/META-INF/LICENSE =================================================================== --- jackrabbit-jcr-servlet-project/jackrabbit-jcr-servlet-jakarta/target/classes/META-INF/LICENSE (nonexistent) +++ jackrabbit-jcr-servlet-project/jackrabbit-jcr-servlet-jakarta/target/classes/META-INF/LICENSE (working copy) @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed 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. Index: jackrabbit-jcr-servlet-project/jackrabbit-jcr-servlet-jakarta/target/classes/META-INF/NOTICE =================================================================== --- jackrabbit-jcr-servlet-project/jackrabbit-jcr-servlet-jakarta/target/classes/META-INF/NOTICE (nonexistent) +++ jackrabbit-jcr-servlet-project/jackrabbit-jcr-servlet-jakarta/target/classes/META-INF/NOTICE (working copy) @@ -0,0 +1,8 @@ + +jackrabbit-jcr-servlet-jakarta +Copyright 2004-1970 The Apache Software Foundation + +This product includes software developed at +The Apache Software Foundation (http://www.apache.org/). + + Index: jackrabbit-jcr-servlet-project/jackrabbit-jcr-servlet-jakarta/target/classes/META-INF/maven/org.apache.jackrabbit/jackrabbit-jcr-servlet-jakarta/pom.properties =================================================================== --- jackrabbit-jcr-servlet-project/jackrabbit-jcr-servlet-jakarta/target/classes/META-INF/maven/org.apache.jackrabbit/jackrabbit-jcr-servlet-jakarta/pom.properties (nonexistent) +++ jackrabbit-jcr-servlet-project/jackrabbit-jcr-servlet-jakarta/target/classes/META-INF/maven/org.apache.jackrabbit/jackrabbit-jcr-servlet-jakarta/pom.properties (working copy) @@ -0,0 +1,7 @@ +#Generated by Maven Integration for Eclipse +#Wed Mar 01 12:32:52 CET 2023 +m2e.projectLocation=C\:\\Development\\JackRabbit\\trunk\\jackrabbit-jcr-servlet-project\\jackrabbit-jcr-servlet-jakarta +m2e.projectName=jackrabbit-jcr-servlet-jakarta +groupId=org.apache.jackrabbit +artifactId=jackrabbit-jcr-servlet-jakarta +version=2.21.16-SNAPSHOT Index: jackrabbit-jcr-servlet-project/jackrabbit-jcr-servlet-jakarta/target/classes/META-INF/maven/org.apache.jackrabbit/jackrabbit-jcr-servlet-jakarta/pom.xml =================================================================== --- jackrabbit-jcr-servlet-project/jackrabbit-jcr-servlet-jakarta/target/classes/META-INF/maven/org.apache.jackrabbit/jackrabbit-jcr-servlet-jakarta/pom.xml (nonexistent) +++ jackrabbit-jcr-servlet-project/jackrabbit-jcr-servlet-jakarta/target/classes/META-INF/maven/org.apache.jackrabbit/jackrabbit-jcr-servlet-jakarta/pom.xml (working copy) @@ -0,0 +1,83 @@ + + 4.0.0 + + org.apache.jackrabbit + jackrabbit-jcr-servlet-project + 2.21.16-SNAPSHOT + + jackrabbit-jcr-servlet-jakarta + + + + org.eclipse.transformer + transformer-maven-plugin + 0.5.0 + true + + + true + + + + + default-jar + + jar + + + + org.apache.jackrabbit + jackrabbit-jcr-servlet + ${project.version} + + + + + + + + + + apache-release + + + + org.eclipse.transformer + transformer-maven-plugin + 0.5.0 + true + + + true + + + + + source-jar + + jar + + + + org.apache.jackrabbit + jackrabbit-jcr-servlet + ${project.version} + sources + + + + + + + + + + + + jakarta.servlet + jakarta.servlet-api + 5.0.0 + provided + + + \ No newline at end of file Index: jackrabbit-jcr-servlet-project/jackrabbit-jcr-servlet-jakarta/target/jackrabbit-jcr-servlet-jakarta-2.21.16-SNAPSHOT.jar =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Property changes on: jackrabbit-jcr-servlet-project/jackrabbit-jcr-servlet-jakarta/target/jackrabbit-jcr-servlet-jakarta-2.21.16-SNAPSHOT.jar ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: jackrabbit-jcr-servlet-project/jackrabbit-jcr-servlet-jakarta/target/maven-shared-archive-resources/META-INF/DEPENDENCIES =================================================================== --- jackrabbit-jcr-servlet-project/jackrabbit-jcr-servlet-jakarta/target/maven-shared-archive-resources/META-INF/DEPENDENCIES (nonexistent) +++ jackrabbit-jcr-servlet-project/jackrabbit-jcr-servlet-jakarta/target/maven-shared-archive-resources/META-INF/DEPENDENCIES (working copy) @@ -0,0 +1,53 @@ +// ------------------------------------------------------------------ +// Transitive dependencies of this project determined from the +// maven pom organized by organization. +// ------------------------------------------------------------------ + +jackrabbit-jcr-servlet-jakarta + + +From: 'Dough Lea' (http://gee.cs.oswego.edu/dl/classes/EDU/oswego/cs/dl/util/concurrent/intro.html) + - Dough Lea's util.concurrent package concurrent:concurrent:jar:1.3.4 + License: Public domain, Sun Microsoystems (>http://gee.cs.oswego.edu/dl/classes/EDU/oswego/cs/dl/util/concurrent/intro.html) + +From: 'QOS.ch' (http://www.qos.ch) + - JCL 1.2 implemented over SLF4J (http://www.slf4j.org) org.slf4j:jcl-over-slf4j:jar:1.7.36 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - SLF4J API Module (http://www.slf4j.org) org.slf4j:slf4j-api:jar:1.7.36 + License: MIT License (http://www.opensource.org/licenses/mit-license.php) + +From: 'The Apache Software Foundation' (http://www.apache.org) + - Apache Tika core (https://tika.apache.org/) org.apache.tika:tika-core:bundle:2.4.1 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + +From: 'The Apache Software Foundation' (http://www.apache.org/) + - Commons DBCP (http://commons.apache.org/dbcp/) commons-dbcp:commons-dbcp:jar:1.4 + License: The Apache Software License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt) + - Commons Pool (http://commons.apache.org/pool/) commons-pool:commons-pool:jar:1.5.4 + License: The Apache Software License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt) + - Lucene Core (http://lucene.apache.org/java/lucene-parent/lucene-core) org.apache.lucene:lucene-core:jar:3.6.0 + License: Apache 2 (http://www.apache.org/licenses/LICENSE-2.0.txt) + +From: 'The Apache Software Foundation' (https://www.apache.org/) + - Apache Commons IO (https://commons.apache.org/proper/commons-io/) commons-io:commons-io:jar:2.11.0 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Commons Collections (https://commons.apache.org/proper/commons-collections/) org.apache.commons:commons-collections4:jar:4.4 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Jackrabbit Core (http://jackrabbit.apache.org/jackrabbit-core/) org.apache.jackrabbit:jackrabbit-core:jar:2.21.16-SNAPSHOT + License: Apache-2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Jackrabbit Data (http://jackrabbit.apache.org/jackrabbit-data/) org.apache.jackrabbit:jackrabbit-data:bundle:2.21.16-SNAPSHOT + License: Apache-2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Jackrabbit JCR Commons (http://jackrabbit.apache.org/jackrabbit-jcr-commons/) org.apache.jackrabbit:jackrabbit-jcr-commons:bundle:2.21.16-SNAPSHOT + License: Apache-2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Jackrabbit JCR-RMI (http://jackrabbit.apache.org/jackrabbit-jcr-rmi/) org.apache.jackrabbit:jackrabbit-jcr-rmi:bundle:2.21.16-SNAPSHOT + License: Apache-2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Jackrabbit SPI (http://jackrabbit.apache.org/jackrabbit-spi/) org.apache.jackrabbit:jackrabbit-spi:bundle:2.21.16-SNAPSHOT + License: Apache-2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Jackrabbit SPI Commons (http://jackrabbit.apache.org/jackrabbit-spi-commons/) org.apache.jackrabbit:jackrabbit-spi-commons:bundle:2.21.16-SNAPSHOT + License: Apache-2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Jackrabbit API (http://jackrabbit.apache.org/oak-jackrabbit-api/) org.apache.jackrabbit:oak-jackrabbit-api:bundle:1.48.0 + License: Apache-2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + + + + Index: jackrabbit-jcr-servlet-project/jackrabbit-jcr-servlet-jakarta/target/maven-shared-archive-resources/META-INF/LICENSE =================================================================== --- jackrabbit-jcr-servlet-project/jackrabbit-jcr-servlet-jakarta/target/maven-shared-archive-resources/META-INF/LICENSE (nonexistent) +++ jackrabbit-jcr-servlet-project/jackrabbit-jcr-servlet-jakarta/target/maven-shared-archive-resources/META-INF/LICENSE (working copy) @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed 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. Index: jackrabbit-jcr-servlet-project/jackrabbit-jcr-servlet-jakarta/target/maven-shared-archive-resources/META-INF/NOTICE =================================================================== --- jackrabbit-jcr-servlet-project/jackrabbit-jcr-servlet-jakarta/target/maven-shared-archive-resources/META-INF/NOTICE (nonexistent) +++ jackrabbit-jcr-servlet-project/jackrabbit-jcr-servlet-jakarta/target/maven-shared-archive-resources/META-INF/NOTICE (working copy) @@ -0,0 +1,8 @@ + +jackrabbit-jcr-servlet-jakarta +Copyright 2004-1970 The Apache Software Foundation + +This product includes software developed at +The Apache Software Foundation (http://www.apache.org/). + + Index: jackrabbit-jcr-servlet-project/jackrabbit-jcr-servlet-jakarta/target/maven-status/maven-compiler-plugin/compile/default-compile/createdFiles.lst =================================================================== Index: jackrabbit-jcr-servlet-project/jackrabbit-jcr-servlet-jakarta/target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst =================================================================== Index: jackrabbit-jcr-servlet-project/jackrabbit-jcr-servlet-jakarta/target/maven-status/maven-compiler-plugin/testCompile/default-testCompile/createdFiles.lst =================================================================== Index: jackrabbit-jcr-servlet-project/jackrabbit-jcr-servlet-jakarta/target/maven-status/maven-compiler-plugin/testCompile/default-testCompile/inputFiles.lst =================================================================== Index: jackrabbit-jcr-servlet-project/jackrabbit-jcr-servlet-jakarta/target/test-classes/META-INF/DEPENDENCIES =================================================================== --- jackrabbit-jcr-servlet-project/jackrabbit-jcr-servlet-jakarta/target/test-classes/META-INF/DEPENDENCIES (nonexistent) +++ jackrabbit-jcr-servlet-project/jackrabbit-jcr-servlet-jakarta/target/test-classes/META-INF/DEPENDENCIES (working copy) @@ -0,0 +1,53 @@ +// ------------------------------------------------------------------ +// Transitive dependencies of this project determined from the +// maven pom organized by organization. +// ------------------------------------------------------------------ + +jackrabbit-jcr-servlet-jakarta + + +From: 'Dough Lea' (http://gee.cs.oswego.edu/dl/classes/EDU/oswego/cs/dl/util/concurrent/intro.html) + - Dough Lea's util.concurrent package concurrent:concurrent:jar:1.3.4 + License: Public domain, Sun Microsoystems (>http://gee.cs.oswego.edu/dl/classes/EDU/oswego/cs/dl/util/concurrent/intro.html) + +From: 'QOS.ch' (http://www.qos.ch) + - JCL 1.2 implemented over SLF4J (http://www.slf4j.org) org.slf4j:jcl-over-slf4j:jar:1.7.36 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - SLF4J API Module (http://www.slf4j.org) org.slf4j:slf4j-api:jar:1.7.36 + License: MIT License (http://www.opensource.org/licenses/mit-license.php) + +From: 'The Apache Software Foundation' (http://www.apache.org) + - Apache Tika core (https://tika.apache.org/) org.apache.tika:tika-core:bundle:2.4.1 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + +From: 'The Apache Software Foundation' (http://www.apache.org/) + - Commons DBCP (http://commons.apache.org/dbcp/) commons-dbcp:commons-dbcp:jar:1.4 + License: The Apache Software License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt) + - Commons Pool (http://commons.apache.org/pool/) commons-pool:commons-pool:jar:1.5.4 + License: The Apache Software License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt) + - Lucene Core (http://lucene.apache.org/java/lucene-parent/lucene-core) org.apache.lucene:lucene-core:jar:3.6.0 + License: Apache 2 (http://www.apache.org/licenses/LICENSE-2.0.txt) + +From: 'The Apache Software Foundation' (https://www.apache.org/) + - Apache Commons IO (https://commons.apache.org/proper/commons-io/) commons-io:commons-io:jar:2.11.0 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Apache Commons Collections (https://commons.apache.org/proper/commons-collections/) org.apache.commons:commons-collections4:jar:4.4 + License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Jackrabbit Core (http://jackrabbit.apache.org/jackrabbit-core/) org.apache.jackrabbit:jackrabbit-core:jar:2.21.16-SNAPSHOT + License: Apache-2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Jackrabbit Data (http://jackrabbit.apache.org/jackrabbit-data/) org.apache.jackrabbit:jackrabbit-data:bundle:2.21.16-SNAPSHOT + License: Apache-2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Jackrabbit JCR Commons (http://jackrabbit.apache.org/jackrabbit-jcr-commons/) org.apache.jackrabbit:jackrabbit-jcr-commons:bundle:2.21.16-SNAPSHOT + License: Apache-2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Jackrabbit JCR-RMI (http://jackrabbit.apache.org/jackrabbit-jcr-rmi/) org.apache.jackrabbit:jackrabbit-jcr-rmi:bundle:2.21.16-SNAPSHOT + License: Apache-2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Jackrabbit SPI (http://jackrabbit.apache.org/jackrabbit-spi/) org.apache.jackrabbit:jackrabbit-spi:bundle:2.21.16-SNAPSHOT + License: Apache-2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Jackrabbit SPI Commons (http://jackrabbit.apache.org/jackrabbit-spi-commons/) org.apache.jackrabbit:jackrabbit-spi-commons:bundle:2.21.16-SNAPSHOT + License: Apache-2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + - Jackrabbit API (http://jackrabbit.apache.org/oak-jackrabbit-api/) org.apache.jackrabbit:oak-jackrabbit-api:bundle:1.48.0 + License: Apache-2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + + + + Index: jackrabbit-jcr-servlet-project/jackrabbit-jcr-servlet-jakarta/target/test-classes/META-INF/LICENSE =================================================================== --- jackrabbit-jcr-servlet-project/jackrabbit-jcr-servlet-jakarta/target/test-classes/META-INF/LICENSE (nonexistent) +++ jackrabbit-jcr-servlet-project/jackrabbit-jcr-servlet-jakarta/target/test-classes/META-INF/LICENSE (working copy) @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed 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. Index: jackrabbit-jcr-servlet-project/jackrabbit-jcr-servlet-jakarta/target/test-classes/META-INF/NOTICE =================================================================== --- jackrabbit-jcr-servlet-project/jackrabbit-jcr-servlet-jakarta/target/test-classes/META-INF/NOTICE (nonexistent) +++ jackrabbit-jcr-servlet-project/jackrabbit-jcr-servlet-jakarta/target/test-classes/META-INF/NOTICE (working copy) @@ -0,0 +1,8 @@ + +jackrabbit-jcr-servlet-jakarta +Copyright 2004-1970 The Apache Software Foundation + +This product includes software developed at +The Apache Software Foundation (http://www.apache.org/). + +