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