001/** 002 * 003 * Copyright the original author or authors 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.privacy.provider; 018 019import java.io.IOException; 020import java.util.ArrayList; 021 022import org.jivesoftware.smack.datatypes.UInt32; 023import org.jivesoftware.smack.packet.IqData; 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.privacy.packet.Privacy; 031import org.jivesoftware.smackx.privacy.packet.PrivacyItem; 032 033/** 034 * The PrivacyProvider parses {@link Privacy} packets. {@link Privacy} 035 * Parses the <code>query</code> sub-document and creates an instance of {@link Privacy}. 036 * For each <code>item</code> in the <code>list</code> element, it creates an instance 037 * of {@link PrivacyItem}. 038 * 039 * @author Francisco Vives 040 */ 041public class PrivacyProvider extends IqProvider<Privacy> { 042 043 @Override 044 public Privacy parse(XmlPullParser parser, int initialDepth, IqData iqData, XmlEnvironment xmlEnvironment) 045 throws XmlPullParserException, IOException { 046 Privacy privacy = new Privacy(); 047 boolean done = false; 048 while (!done) { 049 XmlPullParser.Event eventType = parser.next(); 050 if (eventType == XmlPullParser.Event.START_ELEMENT) { 051 // CHECKSTYLE:OFF 052 if (parser.getName().equals("active")) { 053 String activeName = parser.getAttributeValue("", "name"); 054 if (activeName == null) { 055 privacy.setDeclineActiveList(true); 056 } else { 057 privacy.setActiveName(activeName); 058 } 059 } 060 else if (parser.getName().equals("default")) { 061 String defaultName = parser.getAttributeValue("", "name"); 062 if (defaultName == null) { 063 privacy.setDeclineDefaultList(true); 064 } else { 065 privacy.setDefaultName(defaultName); 066 } 067 } 068 // CHECKSTYLE:ON 069 else if (parser.getName().equals("list")) { 070 parseList(parser, privacy); 071 } 072 } 073 else if (eventType == XmlPullParser.Event.END_ELEMENT) { 074 if (parser.getName().equals("query")) { 075 done = true; 076 } 077 } 078 } 079 080 return privacy; 081 } 082 083 // Parse the list complex type 084 private static void parseList(XmlPullParser parser, Privacy privacy) throws XmlPullParserException, IOException { 085 boolean done = false; 086 String listName = parser.getAttributeValue("", "name"); 087 ArrayList<PrivacyItem> items = new ArrayList<>(); 088 while (!done) { 089 XmlPullParser.Event eventType = parser.next(); 090 if (eventType == XmlPullParser.Event.START_ELEMENT) { 091 if (parser.getName().equals("item")) { 092 // CHECKSTYLE:OFF 093 items.add(parseItem(parser)); 094 // CHECKSTYLE:ON 095 } 096 } 097 else if (eventType == XmlPullParser.Event.END_ELEMENT) { 098 if (parser.getName().equals("list")) { 099 done = true; 100 } 101 } 102 } 103 104 privacy.setPrivacyList(listName, items); 105 // CHECKSTYLE:OFF 106 } 107 108 // Parse the list complex type 109 private static PrivacyItem parseItem(XmlPullParser parser) throws XmlPullParserException, IOException { 110 // CHECKSTYLE:ON 111 // Retrieves the required attributes 112 String actionValue = parser.getAttributeValue("", "action"); 113 // Set the order number, this attribute is required 114 UInt32 order = ParserUtils.getUInt32Attribute(parser, "order"); 115 116 // If type is not set, then it's the fall-through case 117 String type = parser.getAttributeValue("", "type"); 118 119 /* 120 * According the action value it sets the allow status. The fall-through action is assumed 121 * to be "allow" 122 */ 123 boolean allow; 124 switch (actionValue) { 125 case "allow": 126 allow = true; 127 break; 128 case "deny": 129 allow = false; 130 break; 131 default: 132 // TODO: Should be SmackParsingException. 133 throw new IOException("Unknown action value '" + actionValue + "'"); 134 } 135 136 PrivacyItem item; 137 if (type != null) { 138 // If the type is not null, then we are dealing with a standard privacy item 139 String value = parser.getAttributeValue("", "value"); 140 item = new PrivacyItem(PrivacyItem.Type.valueOf(type), value, allow, order); 141 } 142 else { 143 // If the type is null, then we are dealing with the fall-through privacy item. 144 item = new PrivacyItem(allow, order); 145 } 146 parseItemChildElements(parser, item); 147 return item; 148 // CHECKSTYLE:OFF 149 } 150 // CHECKSTYLE:ON 151 152 private static void parseItemChildElements(XmlPullParser parser, PrivacyItem privacyItem) throws XmlPullParserException, IOException { 153 final int initialDepth = parser.getDepth(); 154 155 outerloop: while (true) { 156 XmlPullParser.Event eventType = parser.next(); 157 switch (eventType) { 158 case START_ELEMENT: 159 String name = parser.getName(); 160 switch (name) { 161 case "iq": 162 privacyItem.setFilterIQ(true); 163 break; 164 case "message": 165 privacyItem.setFilterMessage(true); 166 break; 167 case "presence-in": 168 privacyItem.setFilterPresenceIn(true); 169 break; 170 case "presence-out": 171 privacyItem.setFilterPresenceOut(true); 172 break; 173 } 174 break; 175 case END_ELEMENT: 176 if (parser.getDepth() == initialDepth) { 177 break outerloop; 178 } 179 break; 180 default: 181 // Catch all for incomplete switch (MissingCasesInEnumSwitch) statement. 182 break; 183 } 184 } 185 } 186}