View Javadoc
1   /*
2     (C) Copyright IBM Corp. 2006, 2013
3   
4     THIS FILE IS PROVIDED UNDER THE TERMS OF THE ECLIPSE PUBLIC LICENSE
5     ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THIS FILE
6     CONSTITUTES RECIPIENTS ACCEPTANCE OF THE AGREEMENT.
7   
8     You can obtain a current copy of the Eclipse Public License from
9     http://www.opensource.org/licenses/eclipse-1.0.php
10  
11    @author : Endre Bak, ebak@de.ibm.com
12   * 
13   * Flag       Date        Prog         Description
14   * -------------------------------------------------------------------------------
15   * 1565892    2006-12-04  ebak         Make SBLIM client JSR48 compliant
16   * 1663270    2007-02-19  ebak         Minor performance problems
17   * 1660756    2007-02-22  ebak         Embedded object support
18   * 1714878    2007-05-08  ebak         Empty string property values are parsed as nulls
19   * 1720707    2007-05-17  ebak         Conventional Node factory for CIM-XML SAX parser
20   * 1769504	  2007-08-08  ebak         Type identification for VALUETYPE="numeric"
21   * 2003590    2008-06-30  blaschke-oss Change licensing from CPL to EPL
22   * 2524131    2009-01-21  raman_arora  Upgrade client to JDK 1.5 (Phase 1)
23   * 2763216    2009-04-14  blaschke-oss Code cleanup: visible spelling/grammar errors
24   * 2823494    2009-08-03  rgummada     Change Boolean constructor to static
25   * 3572993    2012-10-01  blaschke-oss parseDouble("2.2250738585072012e-308") DoS vulnerability
26   * 3602604    2013-01-29  blaschke-oss Clean up SAXException messages
27   *    2604    2013-07-01  blaschke-oss SAXException messages should contain node name
28   *    2683    2013-10-07  blaschke-oss KEYVALUE VALUETYPE optional, "string" default
29   */
30  
31  package org.metricshub.wbem.sblim.cimclient.internal.cimxml.sax.node;
32  
33  /*-
34   * ╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲
35   * WBEM Java Client
36   * ჻჻჻჻჻჻
37   * Copyright 2023 - 2025 MetricsHub
38   * ჻჻჻჻჻჻
39   * Licensed under the Apache License, Version 2.0 (the "License");
40   * you may not use this file except in compliance with the License.
41   * You may obtain a copy of the License at
42   *
43   *      http://www.apache.org/licenses/LICENSE-2.0
44   *
45   * Unless required by applicable law or agreed to in writing, software
46   * distributed under the License is distributed on an "AS IS" BASIS,
47   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
48   * See the License for the specific language governing permissions and
49   * limitations under the License.
50   * ╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱
51   */
52  
53  import org.metricshub.wbem.javax.cim.CIMDataType;
54  import org.metricshub.wbem.javax.cim.CIMDateTimeAbsolute;
55  import org.metricshub.wbem.javax.cim.CIMDateTimeInterval;
56  import org.metricshub.wbem.javax.cim.UnsignedInteger64;
57  import org.metricshub.wbem.sblim.cimclient.internal.cimxml.sax.CIMObjectFactory;
58  import org.metricshub.wbem.sblim.cimclient.internal.cimxml.sax.SAXSession;
59  import org.metricshub.wbem.sblim.cimclient.internal.util.MOF;
60  import org.metricshub.wbem.sblim.cimclient.internal.util.Util;
61  import org.metricshub.wbem.sblim.cimclient.internal.util.WBEMConfiguration;
62  import org.xml.sax.Attributes;
63  import org.xml.sax.SAXException;
64  
65  /**
66   * ELEMENT KEYVALUE (#PCDATA) ATTLIST KEYVALUE VALUETYPE (string | boolean |
67   * numeric) "string" %CIMType; #IMPLIED
68   */
69  public class KeyValueNode extends AbstractScalarValueNode {
70  	private CIMDataType iType;
71  
72  	private String iValueTypeStr;
73  
74  	private Object iValue;
75  
76  	/**
77  	 * Ctor.
78  	 */
79  	public KeyValueNode() {
80  		super(KEYVALUE);
81  	}
82  
83  	/**
84  	 * @param pSession
85  	 */
86  	@Override
87  	public void init(Attributes pAttribs, SAXSession pSession) throws SAXException {
88  		this.iType = getCIMType(pAttribs, true);
89  		this.iValue = null;
90  		if (this.iType != null) {
91  			if (this.iType.isArray()) throw new SAXException("KEYVALUE node cannot be array typed!");
92  			return;
93  		}
94  		// let's see the VALUETYPE attribute
95  		this.iValueTypeStr = pAttribs.getValue("VALUETYPE");
96  		if (this.iValueTypeStr == null) this.iValueTypeStr = "string";
97  	}
98  
99  	@Override
100 	public void parseData(String pData) throws SAXException {
101 		if (this.iType == null) {
102 			setTypeAndValue(pData);
103 		} else {
104 			this.iValue = CIMObjectFactory.getObject(this.iType, pData);
105 		}
106 	}
107 
108 	/**
109 	 * @param pNodeNameEnum
110 	 */
111 	@Override
112 	public void testChild(String pNodeNameEnum) throws SAXException {
113 		throw new SAXException("KEYVALUE node cannot have any child nodes!");
114 	}
115 
116 	/**
117 	 * @param pChild
118 	 */
119 	@Override
120 	public void childParsed(Node pChild) {
121 		// no child
122 	}
123 
124 	@Override
125 	public void testCompletness() {
126 		// nothing to do
127 	}
128 
129 	public Object getValue() {
130 		/*
131 		 * null key values are not allowed, empty #PCDATA means empty String
132 		 */
133 		return this.iValue == null ? "" : this.iValue;
134 	}
135 
136 	public CIMDataType getType() {
137 		return this.iType;
138 	}
139 
140 	private void setTypeAndValue(String pValue) throws SAXException {
141 		// determine iType from iValueTypeStr if required
142 		if (this.iType != null) return;
143 
144 		if (this.iValueTypeStr.equals("numeric")) {
145 			if (!setUInt64(pValue) && !setSInt64(pValue) && !setReal64(pValue)) throw new SAXException(
146 				"Unparseable \"number\" value in " + getNodeName() + " node: " + pValue + "!"
147 			);
148 		} else if (this.iValueTypeStr.equals(MOF.DT_STR)) {
149 			if (!setDTAbsolute(pValue) && !setDTInterval(pValue)) {
150 				this.iValue = pValue;
151 				this.iType = CIMDataType.STRING_T;
152 			}
153 		} else if (this.iValueTypeStr.equals(MOF.DT_BOOL)) {
154 			if (!setBoolean(pValue)) throw new SAXException(
155 				"Unparseable \"boolean\" value in " + getNodeName() + " node: " + pValue + "!"
156 			);
157 		} else {
158 			throw new SAXException(
159 				"KEYVALUE node's VALUETYPE attribute must be " +
160 				MOF.DT_STR +
161 				", " +
162 				MOF.DT_BOOL +
163 				" or numeric! " +
164 				pValue +
165 				" is not allowed!"
166 			);
167 		}
168 	}
169 
170 	private boolean setUInt64(String pValue) {
171 		try {
172 			this.iValue = new UnsignedInteger64(pValue);
173 		} catch (NumberFormatException e) {
174 			return false;
175 		}
176 		this.iType = CIMDataType.UINT64_T;
177 		return true;
178 	}
179 
180 	private boolean setSInt64(String pValue) {
181 		try {
182 			this.iValue = new Long(pValue);
183 		} catch (NumberFormatException e) {
184 			return false;
185 		}
186 		this.iType = CIMDataType.SINT64_T;
187 		return true;
188 	}
189 
190 	private boolean setReal64(String pValue) {
191 		try {
192 			if (WBEMConfiguration.getGlobalConfiguration().verifyJavaLangDoubleStrings()) {
193 				if (Util.isBadDoubleString(pValue)) return false;
194 			}
195 			this.iValue = new Double(pValue);
196 		} catch (NumberFormatException e) {
197 			return false;
198 		}
199 		this.iType = CIMDataType.REAL64_T;
200 		return true;
201 	}
202 
203 	private boolean setBoolean(String pValue) {
204 		this.iValue = Boolean.valueOf(pValue);
205 		this.iType = CIMDataType.BOOLEAN_T;
206 		return true;
207 	}
208 
209 	private boolean setDTAbsolute(String pValue) {
210 		try {
211 			this.iValue = new CIMDateTimeAbsolute(pValue);
212 		} catch (IllegalArgumentException e) {
213 			return false;
214 		}
215 		this.iType = CIMDataType.DATETIME_T;
216 		return true;
217 	}
218 
219 	private boolean setDTInterval(String pValue) {
220 		try {
221 			this.iValue = new CIMDateTimeInterval(pValue);
222 		} catch (IllegalArgumentException e) {
223 			return false;
224 		}
225 		this.iType = CIMDataType.DATETIME_T;
226 		return true;
227 	}
228 }