001/**
002 *
003 * Copyright © 2017 Grigory Fedorov, 2017-2019 Florian Schmaus
004 *
005 * Licensed under the Apache License, Version 2.0 (the "License");
006 * you may not use this file except in compliance with the License.
007 * You may obtain a copy of the License at
008 *
009 *     http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017package org.jivesoftware.smackx.httpfileupload.provider;
018
019import java.io.IOException;
020import java.net.URL;
021import java.util.HashMap;
022import java.util.Map;
023
024import org.jivesoftware.smack.packet.IqData;
025import org.jivesoftware.smack.packet.XmlEnvironment;
026import org.jivesoftware.smack.provider.IqProvider;
027import org.jivesoftware.smack.util.ParserUtils;
028import org.jivesoftware.smack.xml.XmlPullParser;
029import org.jivesoftware.smack.xml.XmlPullParserException;
030
031import org.jivesoftware.smackx.httpfileupload.HttpFileUploadManager;
032import org.jivesoftware.smackx.httpfileupload.UploadService;
033import org.jivesoftware.smackx.httpfileupload.element.Slot;
034import org.jivesoftware.smackx.httpfileupload.element.Slot_V0_2;
035
036/**
037 * Provider for Slot.
038 *
039 * @author Grigory Fedorov
040 * @see <a href="http://xmpp.org/extensions/xep-0363.html">XEP-0363: HTTP File Upload</a>
041 */
042public class SlotProvider extends IqProvider<Slot> {
043
044    @Override
045    public Slot parse(XmlPullParser parser, int initialDepth, IqData iqData, XmlEnvironment xmlEnvironment) throws XmlPullParserException, IOException {
046        final String namespace = parser.getNamespace();
047
048        final UploadService.Version version = HttpFileUploadManager.namespaceToVersion(namespace);
049        assert version != null;
050
051        URL putUrl = null;
052        URL getUrl = null;
053        PutElement_V0_4_Content putElementV04Content = null;
054
055        outerloop: while (true) {
056            XmlPullParser.Event event = parser.next();
057
058            switch (event) {
059                case START_ELEMENT:
060                    String name = parser.getName();
061                    switch (name) {
062                        case "put": {
063                            switch (version) {
064                            case v0_2:
065                                String putUrlString = parser.nextText();
066                                putUrl = new URL(putUrlString);
067                                break;
068                            case v0_3:
069                                putElementV04Content = parsePutElement_V0_4(parser);
070                                break;
071                            default:
072                                throw new AssertionError();
073                            }
074                            break;
075                        }
076                        case "get":
077                            String getUrlString;
078                            switch (version) {
079                            case v0_2:
080                                getUrlString = parser.nextText();
081                                break;
082                            case v0_3:
083                                getUrlString = parser.getAttributeValue(null, "url");
084                                break;
085                            default:
086                                throw new AssertionError();
087                            }
088                            getUrl = new URL(getUrlString);
089                            break;
090                    }
091                    break;
092                case END_ELEMENT:
093                    if (parser.getDepth() == initialDepth) {
094                        break outerloop;
095                    }
096                    break;
097                default:
098                    // Catch all for incomplete switch (MissingCasesInEnumSwitch) statement.
099                    break;
100            }
101        }
102
103        switch (version) {
104        case v0_3:
105            return new Slot(putElementV04Content.putUrl, getUrl, putElementV04Content.headers);
106        case v0_2:
107            return new Slot_V0_2(putUrl, getUrl);
108        default:
109            throw new AssertionError();
110        }
111    }
112
113    public static PutElement_V0_4_Content parsePutElement_V0_4(XmlPullParser parser) throws XmlPullParserException, IOException {
114        final int initialDepth = parser.getDepth();
115
116        String putUrlString = parser.getAttributeValue(null, "url");
117        URL putUrl = new URL(putUrlString);
118
119        Map<String, String> headers = null;
120        outerloop: while (true) {
121            XmlPullParser.Event next = parser.next();
122            switch (next) {
123            case START_ELEMENT:
124                String name = parser.getName();
125                switch (name) {
126                case "header":
127                    String headerName = ParserUtils.getRequiredAttribute(parser, "name");
128                    String headerValue = ParserUtils.getRequiredNextText(parser);
129                    if (headers == null) {
130                        headers = new HashMap<>();
131                    }
132                    headers.put(headerName, headerValue);
133                    break;
134                default:
135                    break;
136                }
137                break;
138            case END_ELEMENT:
139                if (parser.getDepth() == initialDepth) {
140                    break outerloop;
141                }
142                break;
143            default:
144                // Catch all for incomplete switch (MissingCasesInEnumSwitch) statement.
145                break;
146            }
147        }
148
149        return new PutElement_V0_4_Content(putUrl, headers);
150    }
151
152    public static final class PutElement_V0_4_Content {
153        private final URL putUrl;
154        private final Map<String, String> headers;
155
156        private PutElement_V0_4_Content(URL putUrl, Map<String, String> headers) {
157            this.putUrl = putUrl;
158            this.headers = headers;
159        }
160
161        public URL getPutUrl() {
162            return putUrl;
163        }
164
165        public Map<String, String> getHeaders() {
166            return headers;
167        }
168    }
169}