All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.milton.http.webdav.MkColHandler Maven / Gradle / Ivy

Go to download

Milton Community Edition: Supports DAV level 1 and is available on Apache2 license

There is a newer version: 4.0.3.2215
Show newest version
/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
package io.milton.http.webdav;

import io.milton.http.Handler;
import io.milton.resource.CollectionResource;
import io.milton.resource.Resource;
import io.milton.http.HandlerHelper;
import io.milton.http.HttpManager;
import io.milton.resource.MakeCollectionableResource;
import io.milton.common.Path;
import io.milton.http.Request.Method;
import io.milton.http.Response.Status;
import io.milton.http.exceptions.BadRequestException;
import io.milton.http.exceptions.ConflictException;
import io.milton.http.exceptions.NotAuthorizedException;
import io.milton.event.NewFolderEvent;
import io.milton.http.Request;
import io.milton.http.Response;
import java.io.IOException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class MkColHandler implements Handler {

	private static final Logger log = LoggerFactory.getLogger(MkColHandler.class);
	private final WebDavResponseHandler responseHandler;
	private final HandlerHelper handlerHelper;
	private CollectionResourceCreator collectionResourceCreator = new DefaultCollectionResourceCreator();

	public MkColHandler(WebDavResponseHandler responseHandler, HandlerHelper handlerHelper) {
		this.responseHandler = responseHandler;
		this.handlerHelper = handlerHelper;
	}

	@Override
	public String[] getMethods() {
		return new String[]{Method.MKCOL.code};
	}

	@Override
	public boolean isCompatible(Resource r) {
		return (r instanceof MakeCollectionableResource);
	}

	@Override
	public void process(HttpManager manager, Request request, Response response) throws ConflictException, NotAuthorizedException, BadRequestException {
		try {
			process(manager, request, response, collectionResourceCreator);
		} catch (IOException ex) {
			throw new RuntimeException(ex);
		}
	}

	public void process(HttpManager manager, Request request, Response response, CollectionResourceCreator creator) throws ConflictException, NotAuthorizedException, BadRequestException, IOException {
		if (!handlerHelper.checkExpects(responseHandler, request, response)) {
			return;
		}
		String host = request.getHostHeader();
		String finalurl = HttpManager.decodeUrl(request.getAbsolutePath());
		String name;
		if (log.isDebugEnabled()) {
			log.debug("process request: host: " + host + " url: " + finalurl);
		}

		Path finalpath = Path.path(finalurl); //this is the parent collection it goes in
		name = finalpath.getName();
		Path parent = finalpath.getParent();
		String parenturl = parent.toString();

		Resource parentcol = manager.getResourceFactory().getResource(host, parenturl);
		if (parentcol != null) {
			log.debug("process: resource: " + parentcol.getClass().getName());

			if (handlerHelper.isNotCompatible(parentcol, request.getMethod())) {
				log.debug("resource not compatible. Resource class: " + parentcol.getClass() + " handler: " + getClass());
				responseHandler.respondMethodNotImplemented(parentcol, response, request);
				return;
			}

			if (handlerHelper.isLockedOut(request, parentcol)) {
				log.warn("isLockedOut");
				response.setStatus(Status.SC_LOCKED);
				return;
			}
			Resource dest = manager.getResourceFactory().getResource(host, finalpath.toString());

			if (dest != null) {
				if (handlerHelper.isLockedOut(request, dest)) {
					log.info("destination exists and is locked");
					responseHandler.respondLocked(request, response, dest);
				} else {
					log.info("destination exists and is not locked");
					responseHandler.respondMethodNotAllowed(dest, response, request);
				}
				return;
			}
			if (handlerHelper.missingLock(request, parentcol)) {
				// ensure the dest is not locked
				if (handlerHelper.isLocked(dest)) {
					log.info("precondition failed");
					//response.setStatus(Status.SC_PRECONDITION_FAILED); //notowner_modify wants this code here
					responseHandler.respondPreconditionFailed(request, response, dest);
					return;
				}
			}

			if (parentcol instanceof CollectionResource) {
				CollectionResource col = (CollectionResource) parentcol;
				if (log.isTraceEnabled()) {
					log.trace("process mkcol on parent: " + parentcol.getClass() + " with creator: " + creator.getClass());
				}
				processMakeCol(manager, request, response, col, name, creator);
			} else {
				log.warn("parent collection is no a CollectionResource: " + parentcol.getName());
				responseHandler.respondConflict(parentcol, response, request, "not a collection");
			}

		} else {
			log.warn("parent does not exist: host=" + host + " path=" + parenturl);
			manager.getResponseHandler().respondConflict(parentcol, response, request, name);
		}
	}

	private void processMakeCol(HttpManager manager, Request request, Response response, CollectionResource resource, String newName, CollectionResourceCreator creator) throws ConflictException, NotAuthorizedException, BadRequestException, IOException {
		if (!handlerHelper.checkAuthorisation(manager, resource, request)) {
			log.info("not authorised");
			responseHandler.respondUnauthorised(resource, response, request);
			return;
		}

		handlerHelper.checkExpects(responseHandler, request, response);

		if (!isCompatible(resource)) {
			log.info("not compatible");
			responseHandler.respondMethodNotImplemented(resource, response, request);
			return;
		}

		MakeCollectionableResource existingCol = (MakeCollectionableResource) resource;
//		try {
//			//For litmus test and RFC support
//			if (request.getInputStream().read() > -1) //This should be empty
//			{
//				log.info("unsupported media type1");
//				response.setStatus(Response.Status.SC_UNSUPPORTED_MEDIA_TYPE);
//				return;
//			}
//		} catch (Exception ex) {
//			//Per RFC2518 MKCOL request-content is undefined and it is therefore MANDATORY to return 415 if it exists.
//			if (request.getContentLengthHeader() > 0) {
//				log.info("unsupported media type2");
//				response.setStatus(Response.Status.SC_UNSUPPORTED_MEDIA_TYPE);
//				return;
//			}
//		}

		Resource existingChild = existingCol.child(newName);
		if (existingChild != null) {
			log.warn("found already existing item: " + newName + " of type: " + existingChild.getClass() + " with actual name: " + existingChild.getName());
			//throw new ConflictException( existingChild );
			// See http://www.ettrema.com:8080/browse/MIL-86
			// 405 (Method Not Allowed) - MKCOL can only be executed on a deleted/non-existent resource.
			responseHandler.respondMethodNotAllowed(existingChild, response, request);
			return;
		}
		CollectionResource made = creator.createResource(existingCol, newName, request);
		if (made == null) {
			log.warn("createCollection returned null. In resource class: " + existingCol.getClass());
			response.setStatus(Response.Status.SC_METHOD_NOT_ALLOWED);
		} else {
			log.info("created item ok: " + made.getClass());
			manager.getEventManager().fireEvent(new NewFolderEvent(resource));
			response.setStatus(Response.Status.SC_CREATED);
		}
	}

	public CollectionResourceCreator getCollectionResourceCreator() {
		return collectionResourceCreator;
	}

	public void setCollectionResourceCreator(CollectionResourceCreator collectionResourceCreator) {
		this.collectionResourceCreator = collectionResourceCreator;
	}

	public interface CollectionResourceCreator {

		CollectionResource createResource(MakeCollectionableResource existingCol, String newName, Request request) throws ConflictException, NotAuthorizedException, BadRequestException, IOException;
	}

	private static class DefaultCollectionResourceCreator implements CollectionResourceCreator {

		@Override
		public CollectionResource createResource(MakeCollectionableResource existingCol, String newName, Request request) throws ConflictException, NotAuthorizedException, BadRequestException, IOException {
			return existingCol.createCollection(newName);
		}
	}

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy