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.XmlEnvironment;
025import org.jivesoftware.smack.provider.IQProvider;
026import org.jivesoftware.smack.util.ParserUtils;
027import org.jivesoftware.smack.xml.XmlPullParser;
028import org.jivesoftware.smack.xml.XmlPullParserException;
029
030import org.jivesoftware.smackx.httpfileupload.HttpFileUploadManager;
031import org.jivesoftware.smackx.httpfileupload.UploadService;
032import org.jivesoftware.smackx.httpfileupload.element.Slot;
033import org.jivesoftware.smackx.httpfileupload.element.Slot_V0_2;
034
035/**
036 * Provider for Slot.
037 *
038 * @author Grigory Fedorov
039 * @see <a href="http://xmpp.org/extensions/xep-0363.html">XEP-0363: HTTP File Upload</a>
040 */
041public class SlotProvider extends IQProvider<Slot> {
042
043    @Override
044    public Slot parse(XmlPullParser parser, int initialDepth, XmlEnvironment xmlEnvironment) throws XmlPullParserException, IOException {
045        final String namespace = parser.getNamespace();
046
047        final UploadService.Version version = HttpFileUploadManager.namespaceToVersion(namespace);
048        assert version != null;
049
050        URL putUrl = null;
051        URL getUrl = null;
052        PutElement_V0_4_Content putElementV04Content = null;
053
054        outerloop: while (true) {
055            XmlPullParser.Event event = parser.next();
056
057            switch (event) {
058                case START_ELEMENT:
059                    String name = parser.getName();
060                    switch (name) {
061                        case "put": {
062                            switch (version) {
063                            case v0_2:
064                                String putUrlString = parser.nextText();
065                                putUrl = new URL(putUrlString);
066                                break;
067                            case v0_3:
068                                putElementV04Content = parsePutElement_V0_4(parser);
069                                break;
070                            default:
071                                throw new AssertionError();
072                            }
073                            break;
074                        }
075                        case "get":
076                            String getUrlString;
077                            switch (version) {
078                            case v0_2:
079                                getUrlString = parser.nextText();
080                                break;
081                            case v0_3:
082                                getUrlString = parser.getAttributeValue(null, "url");
083                                break;
084                            default:
085                                throw new AssertionError();
086                            }
087                            getUrl = new URL(getUrlString);
088                            break;
089                    }
090                    break;
091                case END_ELEMENT:
092                    if (parser.getDepth() == initialDepth) {
093                        break outerloop;
094                    }
095                    break;
096                default:
097                    // Catch all for incomplete switch (MissingCasesInEnumSwitch) statement.
098                    break;
099            }
100        }
101
102        switch (version) {
103        case v0_3:
104            return new Slot(putElementV04Content.putUrl, getUrl, putElementV04Content.headers);
105        case v0_2:
106            return new Slot_V0_2(putUrl, getUrl);
107        default:
108            throw new AssertionError();
109        }
110    }
111
112    public static PutElement_V0_4_Content parsePutElement_V0_4(XmlPullParser parser) throws XmlPullParserException, IOException {
113        final int initialDepth = parser.getDepth();
114
115        String putUrlString = parser.getAttributeValue(null, "url");
116        URL putUrl = new URL(putUrlString);
117
118        Map<String, String> headers = null;
119        outerloop: while (true) {
120            XmlPullParser.Event next = parser.next();
121            switch (next) {
122            case START_ELEMENT:
123                String name = parser.getName();
124                switch (name) {
125                case "header":
126                    String headerName = ParserUtils.getRequiredAttribute(parser, "name");
127                    String headerValue = ParserUtils.getRequiredNextText(parser);
128                    if (headers == null) {
129                        headers = new HashMap<>();
130                    }
131                    headers.put(headerName, headerValue);
132                    break;
133                default:
134                    break;
135                }
136                break;
137            case END_ELEMENT:
138                if (parser.getDepth() == initialDepth) {
139                    break outerloop;
140                }
141                break;
142            default:
143                // Catch all for incomplete switch (MissingCasesInEnumSwitch) statement.
144                break;
145            }
146        }
147
148        return new PutElement_V0_4_Content(putUrl, headers);
149    }
150
151    public static final class PutElement_V0_4_Content {
152        private final URL putUrl;
153        private final Map<String, String> headers;
154
155        private PutElement_V0_4_Content(URL putUrl, Map<String, String> headers) {
156            this.putUrl = putUrl;
157            this.headers = headers;
158        }
159
160        public URL getPutUrl() {
161            return putUrl;
162        }
163
164        public Map<String, String> getHeaders() {
165            return headers;
166        }
167    }
168}