e3da5e9429201289c3e33ad3d3e8ad140371e9d5
[oam/tr069-adapter.git] / acs / cpe / src / main / java / org / commscope / tr069adapter / acs / cpe / TR069RPC.java
1 /*\r
2  * ============LICENSE_START========================================================================\r
3  * ONAP : tr-069-adapter\r
4  * =================================================================================================\r
5  * Copyright (C) 2020 CommScope Inc Intellectual Property.\r
6  * =================================================================================================\r
7  * This tr-069-adapter software file is distributed by CommScope Inc under the Apache License,\r
8  * Version 2.0 (the "License"); you may not use this file except in compliance with the License. You\r
9  * may obtain a copy of the License at\r
10  *\r
11  * http://www.apache.org/licenses/LICENSE-2.0\r
12  *\r
13  * This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,\r
14  * either express or implied. See the License for the specific language governing permissions and\r
15  * limitations under the License.\r
16  * ===============LICENSE_END=======================================================================\r
17  */\r
18 \r
19 \r
20 package org.commscope.tr069adapter.acs.cpe;\r
21 \r
22 import java.io.IOException;\r
23 import java.io.OutputStream;\r
24 import java.io.Serializable;\r
25 import java.util.HashMap;\r
26 import java.util.Iterator;\r
27 import java.util.Random;\r
28 \r
29 import javax.xml.soap.MessageFactory;\r
30 import javax.xml.soap.Name;\r
31 import javax.xml.soap.Node;\r
32 import javax.xml.soap.SOAPBody;\r
33 import javax.xml.soap.SOAPBodyElement;\r
34 import javax.xml.soap.SOAPElement;\r
35 import javax.xml.soap.SOAPEnvelope;\r
36 import javax.xml.soap.SOAPException;\r
37 import javax.xml.soap.SOAPFactory;\r
38 import javax.xml.soap.SOAPHeader;\r
39 import javax.xml.soap.SOAPHeaderElement;\r
40 import javax.xml.soap.SOAPMessage;\r
41 import javax.xml.soap.SOAPPart;\r
42 \r
43 import org.commscope.tr069adapter.acs.cpe.rpc.Fault;\r
44 import org.slf4j.Logger;\r
45 import org.slf4j.LoggerFactory;\r
46 \r
47 public abstract class TR069RPC implements Serializable {\r
48 \r
49   private static final String HTTP_SCHEMA_ENCODING = "http://schemas.xmlsoap.org/soap/encoding/";\r
50 \r
51   private static final long serialVersionUID = 7270475819053880884L;\r
52 \r
53   protected static final Logger logger = LoggerFactory.getLogger(TR069RPC.class);\r
54 \r
55   private Random mrandom = new Random();\r
56 \r
57   /** Creates a new instance of Message */\r
58   public TR069RPC() {}\r
59 \r
60   public static final String ENVELOPE_NAMESPACE = "http://schemas.xmlsoap.org/soap/envelope/";\r
61 \r
62   protected abstract void createBody(SOAPBodyElement body, SOAPFactory spf) throws SOAPException;\r
63 \r
64   protected abstract void parseBody(SOAPBodyElement body, SOAPFactory f) throws SOAPException;\r
65 \r
66   protected class ArrayType {\r
67 \r
68     public ArrayType() {\r
69       super();\r
70     }\r
71 \r
72     private String type;\r
73 \r
74     public String getType() {\r
75       return type;\r
76     }\r
77 \r
78     public Name getType(SOAPBodyElement body, SOAPFactory spf) throws SOAPException {\r
79       int i = type.indexOf(':');\r
80       if (i == -1) {\r
81         return spf.createName(type);\r
82       } else {\r
83         String prefix = type.substring(0, i);\r
84         SOAPBody b = (SOAPBody) body.getParentElement();\r
85         SOAPEnvelope e = (SOAPEnvelope) b.getParentElement();\r
86         SOAPHeader h = e.getHeader();\r
87         String uri = null;\r
88         try {\r
89           uri = h.lookupNamespaceURI(prefix);\r
90         } catch (Exception ee) {\r
91           logger.error("While geting namespace URI 1 {}", ee.toString());\r
92         }\r
93         if (uri == null) {\r
94           try {\r
95             uri = e.lookupNamespaceURI(prefix);\r
96           } catch (Exception ee) {\r
97             logger.error("While geting namespace URI 2 {}", ee.toString());\r
98           }\r
99         }\r
100         if (uri == null) {\r
101           try {\r
102             uri = b.lookupNamespaceURI(prefix);\r
103           } catch (Exception ee) {\r
104             logger.error("While geting namespace URI {} ", ee.toString());\r
105           }\r
106         }\r
107         return spf.createName(type.substring(i + 1), prefix, uri);\r
108       }\r
109     }\r
110 \r
111     public void setType(String type) {\r
112       this.type = type;\r
113     }\r
114   }\r
115 \r
116   public static SOAPBodyElement getRequest(SOAPMessage msg) throws SOAPException {\r
117     SOAPBodyElement request = null;\r
118     Iterator<Node> i1 = msg.getSOAPBody().getChildElements();\r
119     while (i1.hasNext()) {\r
120       Node n = i1.next();\r
121       if (n.getNodeType() == org.w3c.dom.Node.ELEMENT_NODE) {\r
122         request = (SOAPBodyElement) n;\r
123       }\r
124     }\r
125     return request;\r
126   }\r
127 \r
128   private static String getRequestName(SOAPMessage msg) throws SOAPException {\r
129     if (msg.getSOAPBody().hasFault()) {\r
130       return "Fault";\r
131     }\r
132     String name = "";\r
133     SOAPBodyElement element = getRequest(msg);\r
134     if (element != null) {\r
135       name = element.getNodeName();\r
136     }\r
137     if (name.startsWith("cwmp:")) {\r
138       name = name.substring(5);\r
139     } else if (name.startsWith("cwmp_x:")) {\r
140       name = name.substring(7);\r
141     } else if (name.indexOf(':') != -1) {\r
142       name = name.substring(name.indexOf(':') + 1, name.length());\r
143     }\r
144     return name;\r
145   }\r
146 \r
147   public static TR069RPC parse(SOAPMessage soapMsg)\r
148       throws SOAPException, InstantiationException, IllegalAccessException, ClassNotFoundException {\r
149     String reqname = TR069RPC.getRequestName(soapMsg);\r
150 \r
151     TR069RPC msg = null;\r
152     try {\r
153       msg = (TR069RPC) Class.forName("org.commscope.tr069adapter.acs.cpe.rpc." + reqname)\r
154           .newInstance();\r
155     } catch (Exception e) {\r
156       msg = (TR069RPC) Class.forName("org.commscope.tr069adapter.acs.cpe.rpc." + reqname)\r
157           .newInstance();\r
158     }\r
159     msg = msg.parseSoapMessage(soapMsg);\r
160     return msg;\r
161   }\r
162 \r
163   @SuppressWarnings("unchecked")\r
164   private TR069RPC parseSoapMessage(SOAPMessage soapMsg) throws SOAPException {\r
165     SOAPEnvelope env = soapMsg.getSOAPPart().getEnvelope();\r
166 \r
167     Iterator<String> pfxs = env.getNamespacePrefixes();\r
168     while (pfxs.hasNext()) {\r
169       String pfx = pfxs.next();\r
170       String uri = env.getNamespaceURI(pfx);\r
171       if (uri.startsWith("urn:dslforum-org:cwmp-")) {\r
172         urnCWMP = uri;\r
173       }\r
174     }\r
175     SOAPFactory spf = SOAPFactory.newInstance();\r
176     SOAPBodyElement soaprequest = getRequest(soapMsg);\r
177     SOAPHeader hdr = soapMsg.getSOAPHeader();\r
178     id = "device_did_not_send_id"; // or make it null?...\r
179     if (hdr != null) {\r
180       try {\r
181         id = getHeaderElement(spf, hdr, "ID");\r
182       } catch (Exception e) {\r
183         logger.error("While parsing the soap message {}", e.toString());\r
184       }\r
185     }\r
186     name = getRequestName(soapMsg);\r
187     if (soaprequest != null) {\r
188       Fault fault = parseSOAPRequest(soaprequest, spf);\r
189       if (fault != null)\r
190         return fault;\r
191     }\r
192     return this;\r
193   }\r
194 \r
195   private Fault parseSOAPRequest(SOAPBodyElement soaprequest, SOAPFactory spf)\r
196       throws SOAPException {\r
197     if (soaprequest != null) {\r
198       try {\r
199         parseBody(soaprequest, spf);\r
200       } catch (Exception e) {\r
201         SOAPElement se = getRequestChildElement(spf, soaprequest, FAULT_CODE);\r
202         String fc = (se != null) ? se.getValue() : "0";\r
203         SOAPElement se2 = getRequestChildElement(spf, soaprequest, FAULT_STRING);\r
204         String fs = (se2 != null) ? se2.getValue() : "0";\r
205 \r
206         if (se != null || se2 != null) {\r
207           return new Fault(fc, fs, id);\r
208         }\r
209         throw e;\r
210       }\r
211     }\r
212     return null;\r
213   }\r
214 \r
215   public void writeTo(OutputStream out) {\r
216     try {\r
217       SOAPFactory spf = SOAPFactory.newInstance();\r
218       MessageFactory factory = MessageFactory.newInstance();\r
219       SOAPMessage soapMsg = factory.createMessage();\r
220       SOAPPart part = soapMsg.getSOAPPart();\r
221 \r
222       SOAPEnvelope envelope = part.getEnvelope();\r
223       SOAPHeader header = envelope.getHeader();\r
224       SOAPBody body = envelope.getBody();\r
225 \r
226       String responseId = getId();\r
227 \r
228       envelope.addNamespaceDeclaration("xsd", "http://www.w3.org/2001/XMLSchema");\r
229       envelope.addNamespaceDeclaration("cwmp", urnCWMP);\r
230       envelope.addNamespaceDeclaration("SOAP-ENC", HTTP_SCHEMA_ENCODING);\r
231       envelope.addNamespaceDeclaration("SOAP-ENV", ENVELOPE_NAMESPACE);\r
232       envelope.addNamespaceDeclaration("xsi", "http://www.w3.org/2001/XMLSchema-instance");\r
233 \r
234       SOAPElement element = header.addChildElement(spf.createName("ID", "cwmp", urnCWMP));\r
235       element.addAttribute(spf.createName("mustUnderstand", "SOAP-ENV", ENVELOPE_NAMESPACE),\r
236           responseId);\r
237       element.addTextNode("1");\r
238 \r
239       body.setEncodingStyle(HTTP_SCHEMA_ENCODING);\r
240       SOAPBodyElement bd = body.addBodyElement(spf.createName(name, CWMP, urnCWMP));\r
241 \r
242       if (name == null || name.equals("")) {\r
243         name = this.getClass().getSimpleName();\r
244       }\r
245       createBody(bd, spf, id);\r
246 \r
247       soapMsg.writeTo(out);\r
248     } catch (SOAPException ex) {\r
249       logger.error("Exception occurred while constructing SOAP message: {}", ex.getMessage());\r
250     } catch (IOException e) {\r
251       logger.error("Exception occurred while constructing SOAP message: {}", e.getMessage());\r
252     }\r
253   }\r
254 \r
255   protected void createBody(SOAPBodyElement body, SOAPFactory spf, String key)\r
256       throws SOAPException {\r
257     logger.debug("Key element is: {}", key);\r
258     createBody(body, spf);\r
259   }\r
260 \r
261   protected SOAPElement getRequestChildElement(SOAPFactory f, SOAPElement req, String name) {\r
262     @SuppressWarnings("unchecked")\r
263     Iterator<Object> i = req.getChildElements();\r
264     f.getClass();\r
265     while (i.hasNext()) {\r
266       Object o = i.next();\r
267       try {\r
268         Node nn = (Node) o;\r
269         String n = nn.getLocalName();\r
270         if (n != null && n.equals(name)) {\r
271           return (SOAPElement) o;\r
272         }\r
273       } catch (Exception e) {\r
274         logger.debug("Exception: {}, {}", e.getMessage(), e.getClass().getName());\r
275       }\r
276     }\r
277     return null;\r
278   }\r
279 \r
280   protected SOAPElement getRequestChildElement2(SOAPFactory f, SOAPElement req, String name)\r
281       throws SOAPException {\r
282     return (SOAPElement) req.getChildElements(f.createName(name, CWMP, urnCWMP)).next();\r
283   }\r
284 \r
285   protected String getRequestElement(SOAPFactory f, SOAPElement req, String name) {\r
286     return getRequestChildElement(f, req, name).getValue();\r
287   }\r
288 \r
289   protected String getRequestElement(SOAPFactory f, SOAPElement req, String name, String def) {\r
290     String v = getRequestChildElement(f, req, name).getValue();\r
291     return (v != null) ? v : def;\r
292   }\r
293 \r
294   protected SOAPElement getRequestChildElement(SOAPElement req, Name name) {\r
295     return (SOAPElement) req.getChildElements(name).next();\r
296   }\r
297 \r
298   protected String getRequestElement(SOAPElement req, Name name) {\r
299     return getRequestChildElement(req, name).getValue();\r
300   }\r
301 \r
302   protected String getHeaderElement(SOAPFactory f, SOAPHeader hdr, String name)\r
303       throws SOAPException {\r
304     return ((SOAPHeaderElement) hdr.getChildElements(f.createName(name, CWMP, urnCWMP)).next())\r
305         .getValue();\r
306   }\r
307 \r
308   protected HashMap<String, String> parseParamList(SOAPElement body, SOAPFactory spf)\r
309       throws SOAPException {\r
310     return parseParamList(body, spf, "ParameterValueStruct", "Value");\r
311   }\r
312 \r
313   protected HashMap<String, String> parseParamList(SOAPElement body, SOAPFactory spf, String sn,\r
314       String vn) throws SOAPException {\r
315     Iterator<SOAPElement> pi =\r
316         getRequestChildElement(spf, body, "ParameterList").getChildElements(spf.createName(sn));\r
317     Name nameKey = spf.createName("Name");\r
318     Name nameValue = spf.createName(vn);\r
319     HashMap<String, String> pl = new HashMap<>();\r
320     while (pi.hasNext()) {\r
321       SOAPElement param = pi.next();\r
322       String key = getRequestElement(param, nameKey);\r
323       String value = getRequestElement(param, nameValue);\r
324       if (value == null) {\r
325         value = "";\r
326       }\r
327       pl.put(key, value);\r
328     }\r
329     return pl;\r
330   }\r
331 \r
332   protected int getArrayCount(SOAPFactory spf, SOAPElement e) throws SOAPException {\r
333     return getArrayCount(spf, e, null);\r
334   }\r
335 \r
336   protected int getArrayCount(SOAPFactory spf, SOAPElement e, ArrayType type) throws SOAPException {\r
337     Name nameArray = spf.createName("arrayType", "soap-enc", HTTP_SCHEMA_ENCODING);\r
338     String attr = e.getAttributeValue(nameArray);\r
339     if (attr == null) {\r
340       return 0;\r
341     }\r
342     attr = attr.replace(" ", "");\r
343     int i = attr.indexOf('[');\r
344     String c = attr.substring(i + 1, attr.length() - 1);\r
345     if (type != null) {\r
346       type.setType(attr.substring(0, i));\r
347     }\r
348     return Integer.parseInt(c);\r
349   }\r
350 \r
351   public boolean isFault() {\r
352     return name.equals("Fault");\r
353   }\r
354 \r
355   protected String b2s(boolean b) {\r
356     return (b) ? "1" : "0";\r
357   }\r
358 \r
359   protected String name;\r
360 \r
361   public String getName() {\r
362     return name;\r
363   }\r
364 \r
365   protected String id;\r
366 \r
367   public String getId() {\r
368     if (id == null) {\r
369       id = "" + mrandom.nextInt(99999);\r
370     }\r
371     return id;\r
372   }\r
373 \r
374   protected void println(StringBuilder b, String n, String v) {\r
375     b.append(n);\r
376     b.append(": ");\r
377     b.append(v);\r
378     b.append("\n");\r
379   }\r
380 \r
381   protected void println(StringBuilder b, String n, String n2, String v) {\r
382     b.append(n);\r
383     println(b, n2, v);\r
384   }\r
385 \r
386   public String getCWMPVersion() {\r
387     return urnCWMP;\r
388   }\r
389 \r
390   public void setCWMPVersion(String cwmpVersion) {\r
391     urnCWMP = cwmpVersion;\r
392   }\r
393 \r
394   protected String urnCWMP = "urn:dslforum-org:cwmp-1-0";\r
395   protected static final String CWMP = "cwmp";\r
396   protected static final String PARAMETER_KEY = "ParameterKey";\r
397   protected static final String COMMAND_KEY = "CommandKey";\r
398   protected static final String XSI_TYPE = "xsi:type";\r
399   protected static final String XSD_STRING = "xsd:string";\r
400   protected static final String XSD_UNSIGNEDINT = "xsd:unsignedInt";\r
401   protected static final String XSD_INT = "xsd:int";\r
402   protected static final String XSD_BOOLEAN = "xsd:boolean";\r
403   protected static final String XSD_DATETIME = "xsd:dateTime";\r
404   protected static final String XSD_BASE64 = "xsd:base64";\r
405   protected static final String SOAP_ARRAY_TYPE = "SOAP-ENC:arrayType";\r
406   public static final String FAULT_CODE = "FaultCode";\r
407   public static final String FAULT_STRING = "FaultString";\r
408   public static final String TYPE_OBJECT = "object";\r
409   public static final String TYPE_STRING = "string";\r
410   public static final String TYPE_BOOLEAN = "boolean";\r
411   public static final String TYPE_DATETIME = "dateTime";\r
412   public static final String TYPE_UNSIGNEDINT = "unsignedInt";\r
413   public static final String TYPE_INT = "int";\r
414   public static final String TYPE_BASE64 = "base64";\r
415 \r
416   public String getXmlType(String type) {\r
417     if (type.equals(TYPE_BASE64)) {\r
418       return TR069RPC.XSD_BASE64;\r
419     } else if (type.equals(TYPE_BOOLEAN)) {\r
420       return TR069RPC.XSD_BOOLEAN;\r
421     } else if (type.equals(TYPE_DATETIME)) {\r
422       return TR069RPC.XSD_DATETIME;\r
423     } else if (type.equals(TYPE_INT)) {\r
424       return TR069RPC.XSD_INT;\r
425     } else if (type.equals(TYPE_OBJECT)) {\r
426       return "";\r
427     } else if (type.equals(TYPE_STRING)) {\r
428       return TR069RPC.XSD_STRING;\r
429     } else if (type.equals(TYPE_UNSIGNEDINT)) {\r
430       return TR069RPC.XSD_UNSIGNEDINT;\r
431     }\r
432     return type;\r
433   }\r
434 }\r