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