001/**
002 *
003 * Copyright © 2017 Grigory Fedorov, 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.SmackException;
025import org.jivesoftware.smack.provider.IQProvider;
026import org.jivesoftware.smack.util.ParserUtils;
027
028import org.jivesoftware.smackx.httpfileupload.HttpFileUploadManager;
029import org.jivesoftware.smackx.httpfileupload.UploadService;
030import org.jivesoftware.smackx.httpfileupload.element.Slot;
031import org.jivesoftware.smackx.httpfileupload.element.Slot_V0_2;
032
033import org.xmlpull.v1.XmlPullParser;
034import org.xmlpull.v1.XmlPullParserException;
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) throws XmlPullParserException, IOException, SmackException {
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            int event = parser.next();
057
058            switch (event) {
059                case XmlPullParser.START_TAG:
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 XmlPullParser.END_TAG:
093                    if (parser.getDepth() == initialDepth) {
094                        break outerloop;
095                    }
096                    break;
097            }
098        }
099
100        switch (version) {
101        case v0_3:
102            return new Slot(putElementV04Content.putUrl, getUrl, putElementV04Content.headers);
103        case v0_2:
104            return new Slot_V0_2(putUrl, getUrl);
105        default:
106            throw new AssertionError();
107        }
108    }
109
110    public static PutElement_V0_4_Content parsePutElement_V0_4(XmlPullParser parser) throws XmlPullParserException, IOException {
111        final int initialDepth = parser.getDepth();
112
113        String putUrlString = parser.getAttributeValue(null, "url");
114        URL putUrl = new URL(putUrlString);
115
116        Map<String, String> headers = null;
117        outerloop: while (true) {
118            int next = parser.next();
119            switch (next) {
120            case XmlPullParser.START_TAG:
121                String name = parser.getName();
122                switch (name) {
123                case "header":
124                    String headerName = ParserUtils.getRequiredAttribute(parser, "name");
125                    String headerValue = ParserUtils.getRequiredNextText(parser);
126                    if (headers == null) {
127                        headers = new HashMap<>();
128                    }
129                    headers.put(headerName, headerValue);
130                    break;
131                default:
132                    break;
133                }
134                break;
135            case XmlPullParser.END_TAG:
136                if (parser.getDepth() == initialDepth) {
137                    break outerloop;
138                }
139                break;
140            }
141        }
142
143        return new PutElement_V0_4_Content(putUrl, headers);
144    }
145
146    public static final class PutElement_V0_4_Content {
147        private final URL putUrl;
148        private final Map<String, String> headers;
149
150        private PutElement_V0_4_Content(URL putUrl, Map<String, String> headers) {
151            this.putUrl = putUrl;
152            this.headers = headers;
153        }
154
155        public URL getPutUrl() {
156            return putUrl;
157        }
158
159        public Map<String, String> getHeaders() {
160            return headers;
161        }
162    }
163}