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

org.apache.abdera.protocol.server.multipart.AbstractMultipartCollectionAdapter Maven / Gradle / Ivy

Go to download

Atom Publishing Protocol Specification Server-Side Implementation

The newest version!
/*
 * 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.  For additional information regarding
 * copyright in this work, please see the NOTICE file in the top level
 * directory of this distribution.
 */
package org.apache.abdera.protocol.server.multipart;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PushbackInputStream;
import java.util.Collection;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;

import javax.mail.Header;
import javax.mail.MessagingException;
import javax.mail.internet.InternetHeaders;

import org.apache.abdera.model.Document;
import org.apache.abdera.model.Element;
import org.apache.abdera.model.Entry;
import org.apache.abdera.parser.ParseException;
import org.apache.abdera.parser.Parser;
import org.apache.abdera.protocol.server.RequestContext;
import org.apache.abdera.protocol.server.impl.AbstractCollectionAdapter;
import org.apache.abdera.util.Constants;
import org.apache.abdera.util.MimeTypeHelper;
import org.apache.commons.codec.binary.Base64;

@SuppressWarnings("unchecked")
public abstract class AbstractMultipartCollectionAdapter extends AbstractCollectionAdapter implements
    MultipartRelatedCollectionInfo {

    private static final String CONTENT_TYPE_HEADER = "content-type";
    private static final String CONTENT_ID_HEADER = "content-id";
    private static final String START_PARAM = "start";
    private static final String TYPE_PARAM = "type";
    private static final String BOUNDARY_PARAM = "boundary";

    protected Map accepts;

    public String[] getAccepts(RequestContext request) {
        Collection acceptKeys = getAlternateAccepts(request).keySet();
        return acceptKeys.toArray(new String[acceptKeys.size()]);
    }

    protected MultipartRelatedPost getMultipartRelatedData(RequestContext request) throws IOException, ParseException,
        MessagingException {

        MultipartInputStream multipart = getMultipartStream(request);
        multipart.skipBoundary();

        String start = request.getContentType().getParameter(START_PARAM);

        Document entry = null;
        Map entryHeaders = new HashMap();
        InputStream data = null;
        Map dataHeaders = new HashMap();

        Map headers = getHeaders(multipart);

        // check if the first boundary is the media link entry
        if (start == null || start.length() == 0
            || (headers.containsKey(CONTENT_ID_HEADER) && start.equals(headers.get(CONTENT_ID_HEADER)))
            || (headers.containsKey(CONTENT_TYPE_HEADER) && MimeTypeHelper.isAtom(headers.get(CONTENT_TYPE_HEADER)))) {
            entry = getEntry(multipart, request);
            entryHeaders.putAll(headers);
        } else {
            data = getDataInputStream(multipart);
            dataHeaders.putAll(headers);
        }

        multipart.skipBoundary();

        headers = getHeaders(multipart);

        if (start != null && (headers.containsKey(CONTENT_ID_HEADER) && start.equals(headers.get(CONTENT_ID_HEADER)))
            && (headers.containsKey(CONTENT_TYPE_HEADER) && MimeTypeHelper.isAtom(headers.get(CONTENT_TYPE_HEADER)))) {
            entry = getEntry(multipart, request);
            entryHeaders.putAll(headers);
        } else {
            data = getDataInputStream(multipart);
            dataHeaders.putAll(headers);
        }

        checkMultipartContent(entry, dataHeaders, request);

        return new MultipartRelatedPost(entry, data, entryHeaders, dataHeaders);
    }

    private MultipartInputStream getMultipartStream(RequestContext request) throws IOException, ParseException,
        IllegalArgumentException {
        String boundary = request.getContentType().getParameter(BOUNDARY_PARAM);

        if (boundary == null) {
            throw new IllegalArgumentException("multipart/related stream invalid, boundary parameter is missing.");
        }

        boundary = "--" + boundary;

        String type = request.getContentType().getParameter(TYPE_PARAM);
        if (!(type != null && MimeTypeHelper.isAtom(type))) {
            throw new ParseException(
                                     "multipart/related stream invalid, type parameter should be " + Constants.ATOM_MEDIA_TYPE);
        }

        PushbackInputStream pushBackInput = new PushbackInputStream(request.getInputStream(), 2);
        pushBackInput.unread("\r\n".getBytes());

        return new MultipartInputStream(pushBackInput, boundary.getBytes());
    }

    private void checkMultipartContent(Document entry, Map dataHeaders, RequestContext request)
        throws ParseException {
        if (entry == null) {
            throw new ParseException("multipart/related stream invalid, media link entry is missing");
        }
        if (!dataHeaders.containsKey(CONTENT_TYPE_HEADER)) {
            throw new ParseException("multipart/related stream invalid, data content-type is missing");
        }
        if (!isContentTypeAccepted(dataHeaders.get(CONTENT_TYPE_HEADER), request)) {
            throw new ParseException("multipart/related stream invalid, content-type " + dataHeaders
                .get(CONTENT_TYPE_HEADER)
                + " not accepted into this multipart file");
        }
    }

    private Map getHeaders(MultipartInputStream multipart) throws IOException, MessagingException {
        Map mapHeaders = new HashMap();
        moveToHeaders(multipart);
        InternetHeaders headers = new InternetHeaders(multipart);

        Enumeration
allHeaders = headers.getAllHeaders(); if (allHeaders != null) { while (allHeaders.hasMoreElements()) { Header header = allHeaders.nextElement(); mapHeaders.put(header.getName().toLowerCase(), header.getValue()); } } return mapHeaders; } private boolean moveToHeaders(InputStream stream) throws IOException { boolean dash = false; boolean cr = false; int byteReaded; while ((byteReaded = stream.read()) != -1) { switch (byteReaded) { case '\r': cr = true; dash = false; break; case '\n': if (cr == true) return true; dash = false; break; case '-': if (dash == true) { // two dashes stream.close(); return false; } dash = true; cr = false; break; default: dash = false; cr = false; } } return false; } private InputStream getDataInputStream(InputStream stream) throws IOException { Base64 base64 = new Base64(); ByteArrayOutputStream bo = new ByteArrayOutputStream(); byte[] buffer = new byte[1024]; while (stream.read(buffer) != -1) { bo.write(buffer); } return new ByteArrayInputStream(base64.decode(bo.toByteArray())); } private Document getEntry(InputStream stream, RequestContext request) throws ParseException, IOException { Parser parser = request.getAbdera().getParser(); if (parser == null) throw new IllegalArgumentException("No Parser implementation was provided"); Document document = parser.parse(stream, request.getResolvedUri().toString(), parser.getDefaultParserOptions()); return (Document)document; } private boolean isContentTypeAccepted(String contentType, RequestContext request) { if (getAlternateAccepts(request) == null) { return false; } for (Map.Entry accept : getAlternateAccepts(request).entrySet()) { if (accept.getKey().equalsIgnoreCase(contentType) && accept.getValue() != null && accept.getValue().equalsIgnoreCase(Constants.LN_ALTERNATE_MULTIPART_RELATED)) { return true; } } return false; } protected class MultipartRelatedPost { private final Document entry; private final InputStream data; private final Map entryHeaders; private final Map dataHeaders; public MultipartRelatedPost(Document entry, InputStream data, Map entryHeaders, Map dataHeaders) { this.entry = entry; this.data = data; this.entryHeaders = entryHeaders; this.dataHeaders = dataHeaders; } public Document getEntry() { return entry; } public InputStream getData() { return data; } public Map getEntryHeaders() { return entryHeaders; } public Map getDataHeaders() { return dataHeaders; } } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy