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}