• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 package com.android.server.wifi.hotspot2.omadm;
2 
3 import android.util.Log;
4 
5 import org.xml.sax.SAXException;
6 
7 import java.io.IOException;
8 import java.io.InputStream;
9 import java.io.OutputStream;
10 import java.nio.charset.StandardCharsets;
11 import java.util.*;
12 
13 public class MOTree {
14     public static final String MgmtTreeTag = "MgmtTree";
15 
16     private static final String NodeTag = "Node";
17     private static final String NodeNameTag = "NodeName";
18     private static final String PathTag = "Path";
19     private static final String ValueTag = "Value";
20     private static final String RTPropTag = "RTProperties";
21     private static final String TypeTag = "Type";
22     private static final String DDFNameTag = "DDFName";
23 
24     private final String mUrn;
25     private final String mDtdRev;
26     private final OMAConstructed mRoot;
27 
MOTree(XMLNode node, String urn)28     public MOTree(XMLNode node, String urn) throws IOException, SAXException {
29         Iterator<XMLNode> children = node.getChildren().iterator();
30 
31         String dtdRev = null;
32 
33         while (children.hasNext()) {
34             XMLNode child = children.next();
35             if (child.getTag().equals(OMAConstants.SyncMLVersionTag)) {
36                 dtdRev = child.getText();
37                 children.remove();
38                 break;
39             }
40         }
41 
42         mUrn = urn;
43         mDtdRev = dtdRev;
44 
45         mRoot = new OMAConstructed(null, MgmtTreeTag, null);
46 
47         for (XMLNode child : node.getChildren()) {
48             buildNode(mRoot, child);
49         }
50     }
51 
MOTree(String urn, String rev, OMAConstructed root)52     public MOTree(String urn, String rev, OMAConstructed root) {
53         mUrn = urn;
54         mDtdRev = rev;
55         mRoot = root;
56     }
57 
58     private static class NodeData {
59         private final String mName;
60         private String mPath;
61         private String mValue;
62 
NodeData(String name)63         private NodeData(String name) {
64             mName = name;
65         }
66 
setPath(String path)67         private void setPath(String path) {
68             mPath = path;
69         }
70 
setValue(String value)71         private void setValue(String value) {
72             mValue = value;
73         }
74 
getName()75         public String getName() {
76             return mName;
77         }
78 
getPath()79         public String getPath() {
80             return mPath;
81         }
82 
getValue()83         public String getValue() {
84             return mValue;
85         }
86     }
87 
buildNode(OMANode parent, XMLNode node)88     private static void buildNode(OMANode parent, XMLNode node) throws IOException {
89         if (!node.getTag().equals(NodeTag))
90             throw new IOException("Node is a '" + node.getTag() + "' instead of a 'Node'");
91 
92         Map<String, XMLNode> checkMap = new HashMap<String, XMLNode>(3);
93         String context = null;
94         List<NodeData> values = new ArrayList<NodeData>();
95         List<XMLNode> children = new ArrayList<XMLNode>();
96 
97         NodeData curValue = null;
98 
99         for (XMLNode child : node.getChildren()) {
100             XMLNode old = checkMap.put(child.getTag(), child);
101 
102             if (child.getTag().equals(NodeNameTag)) {
103                 if (curValue != null)
104                     throw new IOException(NodeNameTag + " not expected");
105                 curValue = new NodeData(child.getText());
106 
107             } else if (child.getTag().equals(PathTag)) {
108                 if (curValue == null || curValue.getPath() != null)
109                     throw new IOException(PathTag + " not expected");
110                 curValue.setPath(child.getText());
111 
112             } else if (child.getTag().equals(ValueTag)) {
113                 if (!children.isEmpty())
114                     throw new IOException(ValueTag + " in constructed node");
115                 if (curValue == null || curValue.getValue() != null)
116                     throw new IOException(ValueTag + " not expected");
117                 curValue.setValue(child.getText());
118                 values.add(curValue);
119                 curValue = null;
120 
121             } else if (child.getTag().equals(RTPropTag)) {
122                 if (old != null)
123                     throw new IOException("Duplicate " + RTPropTag);
124                 XMLNode typeNode = getNextNode(child, TypeTag);
125                 XMLNode ddfName = getNextNode(typeNode, DDFNameTag);
126                 context = ddfName.getText();
127                 if (context == null)
128                     throw new IOException("No text in " + DDFNameTag);
129 
130             } else if (child.getTag().equals(NodeTag)) {
131                 if (!values.isEmpty())
132                     throw new IOException("Scalar node " + node.getText() + " has Node child");
133                 children.add(child);
134 
135             }
136         }
137 
138         if (values.isEmpty()) {
139             if (curValue == null)
140                 throw new IOException("Missing name");
141 
142             OMANode subNode = parent.addChild(curValue.getName(),
143                     context, null, curValue.getPath());
144 
145             for (XMLNode child : children) {
146                 buildNode(subNode, child);
147             }
148         } else {
149             if (!children.isEmpty())
150                 throw new IOException("Got both sub nodes and value(s)");
151 
152             for (NodeData nodeData : values) {
153                 parent.addChild(nodeData.getName(), context,
154                         nodeData.getValue(), nodeData.getPath());
155             }
156         }
157     }
158 
getNextNode(XMLNode node, String tag)159     private static XMLNode getNextNode(XMLNode node, String tag) throws IOException {
160         if (node == null)
161             throw new IOException("No node for " + tag);
162         if (node.getChildren().size() != 1)
163             throw new IOException("Expected " + node.getTag() + " to have exactly one child");
164         XMLNode child = node.getChildren().iterator().next();
165         if (!child.getTag().equals(tag))
166             throw new IOException("Expected " + node.getTag() + " to have child '" + tag +
167                     "' instead of '" + child.getTag() + "'");
168         return child;
169     }
170 
getUrn()171     public String getUrn() {
172         return mUrn;
173     }
174 
getDtdRev()175     public String getDtdRev() {
176         return mDtdRev;
177     }
178 
getRoot()179     public OMAConstructed getRoot() {
180         return mRoot;
181     }
182 
183     @Override
toString()184     public String toString() {
185         StringBuilder sb = new StringBuilder();
186         sb.append("MO Tree v").append(mDtdRev).append(", urn ").append(mUrn).append(")\n");
187         sb.append(mRoot);
188 
189         return sb.toString();
190     }
191 
marshal(OutputStream out)192     public void marshal(OutputStream out) throws IOException {
193         out.write("tree ".getBytes(StandardCharsets.UTF_8));
194         OMAConstants.serializeString(mDtdRev, out);
195         out.write(String.format("(%s)\n", mUrn).getBytes(StandardCharsets.UTF_8));
196         mRoot.marshal(out, 0);
197     }
198 
unmarshal(InputStream in)199     public static MOTree unmarshal(InputStream in) throws IOException {
200         boolean strip = true;
201         StringBuilder tree = new StringBuilder();
202         for (; ; ) {
203             int octet = in.read();
204             if (octet < 0) {
205                 return null;
206             } else if (octet > ' ') {
207                 tree.append((char) octet);
208                 strip = false;
209             } else if (!strip) {
210                 break;
211             }
212         }
213         if (!tree.toString().equals("tree")) {
214             throw new IOException("Not a tree: " + tree);
215         }
216 
217         String version = OMAConstants.deserializeString(in);
218         String urn = OMAConstants.readURN(in);
219 
220         OMAConstructed root = OMANode.unmarshal(in);
221 
222         return new MOTree(urn, version, root);
223     }
224 }
225