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

com.elopteryx.paint.upload.UploadParser Maven / Gradle / Ivy

/*
 * Copyright (C) 2015- Adam Forgacs
 *
 * 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.
 */
package com.elopteryx.paint.upload;

import com.elopteryx.paint.upload.impl.AsyncUploadParser;
import com.elopteryx.paint.upload.impl.BlockingUploadParser;

import javax.annotation.Nonnegative;
import javax.annotation.Nonnull;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Locale;

import static java.util.Objects.requireNonNull;

/**
 * Builder class. Provides a fluent API for the users to
 * customize the parsing process.
 */
public abstract class UploadParser {
    /**
     * The type of the HTTP request.
     */
    private static final String POST_METHOD = "POST";

    /**
     * Part of HTTP content type header.
     */
    private static final String MULTIPART = "multipart/";

    /**
     * The request object.
     */
    protected final HttpServletRequest request;

    /**
     * The response object.
     */
    protected final HttpServletResponse response;

    /**
     * The part begin callback, called at the beginning of each part parsing. Mandatory.
     */
    protected OnPartBegin partBeginCallback;

    /**
     * The part end callback, called at the end of each part parsing. Mandatory.
     */
    protected OnPartEnd partEndCallback;

    /**
     * The request callback, called after every part has been processed. Optional.
     */
    protected OnRequestComplete requestCallback;

    /**
     * The error callback, called when an error occurred. Optional.
     */
    protected OnError errorCallback;

    /**
     * The number of bytes that should be buffered before calling the part begin callback.
     */
    protected int sizeThreshold;

    /**
     * The maximum size permitted for the parts. By default it is unlimited.
     */
    protected long maxPartSize = -1;

    /**
     * The maximum size permitted for the complete request. By default it is unlimited.
     */
    protected long maxRequestSize = -1;

    /**
     * Protected constructor, to prevent invalid usages.
     * @param request The servlet request
     * @param response The servlet response
     */
    protected UploadParser(@Nonnull HttpServletRequest request, @Nonnull HttpServletResponse response) {
        this.request = requireNonNull(request);
        this.response = requireNonNull(response);
    }

    /**
     * Utility method which can be used to check whether the request
     * should be processed by this parser or not.
     * @param request The servlet request
     * @return Whether the request is a proper multipart request
     */
    public static boolean isMultipart(@Nonnull HttpServletRequest request) {
        return POST_METHOD.equalsIgnoreCase(request.getMethod()) && request.getContentType() != null &&
                request.getContentType().toLowerCase(Locale.ENGLISH).startsWith(MULTIPART);
    }

    /**
     * Returns a parser implementation, allowing the caller to set configuration.
     * @param request The servlet request
     * @param response The servlet response
     * @return A parser object
     * @throws ServletException If the parameters are invalid
     */
    public static UploadParser newParser(@Nonnull HttpServletRequest request, @Nonnull HttpServletResponse response)
            throws ServletException {
        if (!isMultipart(request))
            throw new ServletException("Not a multipart request!");
        return request.isAsyncSupported() ? new AsyncUploadParser(request, response) : new BlockingUploadParser(request, response);
    }

    /**
     * Sets a callback for each part, called at the beginning.
     * @param partBeginCallback An object or lambda expression
     * @return The parser will return itself
     */
    public UploadParser onPartBegin(@Nonnull OnPartBegin partBeginCallback) {
        this.partBeginCallback = requireNonNull(partBeginCallback);
        return this;
    }

    /**
     * Sets a callback for each part, called at the end.
     * @param partEndCallback An object or lambda expression
     * @return The parser will return itself
     */
    public UploadParser onPartEnd(@Nonnull OnPartEnd partEndCallback) {
        this.partEndCallback = requireNonNull(partEndCallback);
        return this;
    }

    /**
     * Sets a callback for the request, called after each part is processed.
     * @param requestCallback An object or lambda expression
     * @return The parser will return itself
     */
    public UploadParser onRequestComplete(@Nonnull OnRequestComplete requestCallback) {
        this.requestCallback = requireNonNull(requestCallback);
        return this;
    }

    /**
     * Sets a callback for the errors, called if any error occurs.
     * @param errorCallback An object or lambda expression
     * @return The parser will return itself
     */
    public UploadParser onError(@Nonnull OnError errorCallback) {
        this.errorCallback = requireNonNull(errorCallback);
        return this;
    }

    /**
     * Sets the amount of bytes to buffer in the memory, before
     * calling the part end callback.
     * @param sizeThreshold The amount to use
     * @return The parser will return itself
     */
    public UploadParser sizeThreshold(@Nonnegative int sizeThreshold) {
        this.sizeThreshold = Math.max(sizeThreshold, 0);
        return this;
    }

    /**
     * Sets the maximum allowed size for each part. Exceeding this
     * will result in a {@link com.elopteryx.paint.upload.errors.PartSizeException} exception.
     * @param maxPartSize The amount to use
     * @return The parser will return itself
     */
    public UploadParser maxPartSize(@Nonnegative long maxPartSize) {
        this.maxPartSize = Math.max(maxPartSize, -1);
        return this;
    }

    /**
     * Sets the maximum allowed size for the request. Exceeding this
     * will result in a {@link com.elopteryx.paint.upload.errors.RequestSizeException} exception.
     * @param maxRequestSize The amount to use
     * @return The parser will return itself
     */
    public UploadParser maxRequestSize(@Nonnegative long maxRequestSize) {
        this.maxRequestSize = Math.max(maxRequestSize, -1);
        return this;
    }

    /**
     * Sets up the necessary objects to start the parsing. Depending upon
     * the environment the concrete implementations can be very different.
     * @throws IOException If an error occurs with the IO
     */
    public abstract void setup() throws IOException;
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy