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 : Alexander Wolf-Reber, IBM, a.wolf-reber@de.ibm.com
12   * 
13   * Change History
14   * Flag       Date        Prog         Description
15   *------------------------------------------------------------------------------- 
16   * 1565892    2006-12-06  lupusalex    Make SBLIM client JSR48 compliant
17   * 2003590    2008-06-30  blaschke-oss Change licensing from CPL to EPL
18   * 2524131    2009-01-21  raman_arora  Upgrade client to JDK 1.5 (Phase 1)
19   * 2964463    2010-03-08  blaschke-oss WBEMClient.initialize() throws wrong exception
20   * 2942520    2010-03-08  blaschke-oss IPv6 link local address with scope_id including a dot not supported
21   * 3513353    2012-03-30  blaschke-oss TCK: CIMDataType arrays must have length >= 1
22   * 3513349    2012-03-31  blaschke-oss TCK: CIMDataType must not accept null string
23   * 3598613    2013-01-11  blaschke-oss different data type in cim instance and cim object path
24   */
25  
26  package org.metricshub.wbem.sblim.cimclient.internal.cim;
27  
28  /*-
29   * ╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲
30   * WBEM Java Client
31   * ჻჻჻჻჻჻
32   * Copyright 2023 - 2025 MetricsHub
33   * ჻჻჻჻჻჻
34   * Licensed under the Apache License, Version 2.0 (the "License");
35   * you may not use this file except in compliance with the License.
36   * You may obtain a copy of the License at
37   *
38   *      http://www.apache.org/licenses/LICENSE-2.0
39   *
40   * Unless required by applicable law or agreed to in writing, software
41   * distributed under the License is distributed on an "AS IS" BASIS,
42   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
43   * See the License for the specific language governing permissions and
44   * limitations under the License.
45   * ╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱
46   */
47  
48  import java.math.BigInteger;
49  import java.net.URI;
50  import java.net.URISyntaxException;
51  import org.metricshub.wbem.javax.cim.CIMDataType;
52  import org.metricshub.wbem.javax.cim.CIMInstance;
53  import org.metricshub.wbem.javax.cim.CIMObjectPath;
54  import org.metricshub.wbem.javax.cim.CIMProperty;
55  import org.metricshub.wbem.javax.cim.UnsignedInteger16;
56  import org.metricshub.wbem.javax.cim.UnsignedInteger32;
57  import org.metricshub.wbem.javax.cim.UnsignedInteger64;
58  import org.metricshub.wbem.javax.cim.UnsignedInteger8;
59  import org.metricshub.wbem.sblim.cimclient.internal.util.WBEMConstants;
60  
61  /**
62   * Class CIMHelper provides convenience methods that are missing from the
63   * official JSR48 API
64   *
65   */
66  public abstract class CIMHelper {
67  
68  	private CIMHelper() {
69  		// no instances
70  	}
71  
72  	/**
73  	 * Creates a URI of a CIMOM from a given CIM object path, adding default
74  	 * port if port not parsable.
75  	 *
76  	 * @param pPath
77  	 *            The CIM object path.
78  	 * @return The URI.
79  	 * @throws URISyntaxException
80  	 */
81  	public static URI createCimomUri(CIMObjectPath pPath) throws URISyntaxException {
82  		String scheme = pPath.getScheme();
83  		String host = pPath.getHost();
84  		int port = WBEMConstants.DEFAULT_WBEM_PORT;
85  		try {
86  			port = Integer.parseInt(pPath.getPort());
87  		} catch (NumberFormatException e) {
88  			// stuck with default port
89  		}
90  		return new URI(scheme, null, host, port, WBEMConstants.CIMOM_PATH, null, null);
91  	}
92  
93  	/**
94  	 * Creates a URI of a CIMOM from a given URI, adding default port if port
95  	 * not specified.
96  	 *
97  	 * @param pUri
98  	 *            The URI.
99  	 * @return The URI.
100 	 * @throws URISyntaxException
101 	 */
102 	public static URI createCimomUri(URI pUri) throws URISyntaxException {
103 		String scheme = pUri.getScheme();
104 		String host = pUri.getHost();
105 		int port = pUri.getPort();
106 		if (port == -1) {
107 			// stuck with default port
108 			port = WBEMConstants.DEFAULT_WBEM_PORT;
109 		}
110 		return new URI(scheme, null, host, port, WBEMConstants.CIMOM_PATH, null, null);
111 	}
112 
113 	private static CIMDataType CIMScalarDataTypes[] = {
114 		/* 00 */CIMDataType.UINT8_T,
115 		/* 01 */CIMDataType.SINT8_T,
116 		/* 02 */CIMDataType.UINT16_T,
117 		/* 03 */CIMDataType.SINT16_T,
118 		/* 04 */CIMDataType.UINT32_T,
119 		/* 05 */CIMDataType.SINT32_T,
120 		/* 06 */CIMDataType.UINT64_T,
121 		/* 07 */CIMDataType.SINT64_T,
122 		/* 08 */CIMDataType.STRING_T,
123 		/* 09 */CIMDataType.BOOLEAN_T,
124 		/* 10 */CIMDataType.REAL32_T,
125 		/* 11 */CIMDataType.REAL64_T,
126 		/* 12 */CIMDataType.DATETIME_T,
127 		/* 13 */CIMDataType.CHAR16_T,
128 		/* 14 */new CIMDataType(""),
129 		/* 15 */CIMDataType.OBJECT_T,
130 		/* 16 */null,
131 		/* 17 */CIMDataType.CLASS_T
132 	};
133 
134 	/**
135 	 * Returns the CIMDataType of a scalar of the specified data type. This
136 	 * should be used in lieu of "new CIMDataType(pType)" which is not supported
137 	 * by the JSR48 standard.
138 	 *
139 	 * @param pType
140 	 *            Data type.
141 	 * @return CIMDataType corresponding to data type.
142 	 */
143 	public static CIMDataType ScalarDataType(int pType) {
144 		if (pType < 0 || pType >= CIMScalarDataTypes.length) return null;
145 		return CIMScalarDataTypes[pType];
146 	}
147 
148 	private static CIMDataType CIMArrayDataTypes[] = {
149 		/* 00 */CIMDataType.UINT8_ARRAY_T,
150 		/* 01 */CIMDataType.SINT8_ARRAY_T,
151 		/* 02 */CIMDataType.UINT16_ARRAY_T,
152 		/* 03 */CIMDataType.SINT16_ARRAY_T,
153 		/* 04 */CIMDataType.UINT32_ARRAY_T,
154 		/* 05 */CIMDataType.SINT32_ARRAY_T,
155 		/* 06 */CIMDataType.UINT64_ARRAY_T,
156 		/* 07 */CIMDataType.SINT64_ARRAY_T,
157 		/* 08 */CIMDataType.STRING_ARRAY_T,
158 		/* 09 */CIMDataType.BOOLEAN_ARRAY_T,
159 		/* 10 */CIMDataType.REAL32_ARRAY_T,
160 		/* 11 */CIMDataType.REAL64_ARRAY_T,
161 		/* 12 */CIMDataType.DATETIME_ARRAY_T,
162 		/* 13 */CIMDataType.CHAR16_ARRAY_T,
163 		/* 14 */new CIMDataType("", 0),
164 		/* 15 */CIMDataType.OBJECT_ARRAY_T,
165 		/* 16 */null,
166 		/* 17 */CIMDataType.CLASS_ARRAY_T
167 	};
168 
169 	/**
170 	 * Returns the CIMDataType of an unbounded array of the specified data type.
171 	 * This should be used in lieu of "new CIMDataType(pType,0)" which is not
172 	 * supported by the JSR48 standard.
173 	 *
174 	 * @param pType
175 	 *            Data type.
176 	 * @return CIMDataType corresponding to data type.
177 	 */
178 	public static CIMDataType UnboundedArrayDataType(int pType) {
179 		if (pType < 0 || pType >= CIMArrayDataTypes.length) return null;
180 		return CIMArrayDataTypes[pType];
181 	}
182 
183 	/**
184 	 * CIMInstanceWithSynchonizedNumericKeyDataTypes returns a
185 	 * <code>CIMInstance</code> where the data types of all numeric keys in the
186 	 * <code>CIMObjectPath</code> match those of the corresponding keys within
187 	 * the <code>CIMProperty[]</code>.
188 	 *
189 	 * The need for this conversion mechanism arises from a deficiency in the
190 	 * CIM-XML specs, where the TYPE (sint8, uint8, etc.) is required for
191 	 * PROPERTY but not for KEYVALUE. If a CIMOM sends a KEYVALUE of
192 	 * VALUETYPE="numeric" without TYPE, the Java CIM Client assumes a type of
193 	 * sint64, uint64 or real64. This can cause problems (i.e.
194 	 * ClassCastException) down the line if the TYPE of the corresponding
195 	 * PROPERTY is different.
196 	 *
197 	 * @param pObjectPath
198 	 *            Instance object path.
199 	 * @param pProps
200 	 *            Instance properties.
201 	 * @return CIMInstance with numeric key data types synchronized.
202 	 */
203 	public static CIMInstance CIMInstanceWithSynchonizedNumericKeyDataTypes(
204 		CIMObjectPath pObjectPath,
205 		CIMProperty<?>[] pProps
206 	) {
207 		CIMInstance inst = new CIMInstance(pObjectPath, pProps);
208 		CIMProperty<?>[] oldKeys = inst.getKeys();
209 		CIMProperty<?>[] newKeys = new CIMProperty<?>[oldKeys.length];
210 		boolean update = false;
211 
212 		for (int i = 0; i < oldKeys.length; i++) {
213 			CIMDataType oldType = oldKeys[i].getDataType();
214 			CIMProperty<?> prop = inst.getProperty(oldKeys[i].getName());
215 			if (
216 				oldType != null &&
217 				prop != null &&
218 				prop.getDataType() != null &&
219 				!prop.getDataType().equals(oldType) &&
220 				isNumericObject(oldType) &&
221 				isNumericObject(prop.getDataType())
222 			) {
223 				update = true;
224 				newKeys[i] =
225 					new CIMProperty<Object>(
226 						oldKeys[i].getName(),
227 						prop.getDataType(),
228 						translateNumericObject(oldKeys[i].getValue(), oldType, prop.getDataType()),
229 						oldKeys[i].isKey(),
230 						oldKeys[i].isPropagated(),
231 						oldKeys[i].getOriginClass()
232 					);
233 			} else {
234 				newKeys[i] = oldKeys[i];
235 			}
236 		}
237 
238 		return (
239 			update
240 				? inst.deriveInstance(
241 					new CIMObjectPath(
242 						pObjectPath.getScheme(),
243 						pObjectPath.getHost(),
244 						pObjectPath.getPort(),
245 						pObjectPath.getNamespace(),
246 						pObjectPath.getObjectName(),
247 						newKeys
248 					)
249 				)
250 				: inst
251 		);
252 	}
253 
254 	private static boolean isNumericObject(CIMDataType type) {
255 		switch (type.getType()) {
256 			case CIMDataType.SINT8:
257 			case CIMDataType.SINT16:
258 			case CIMDataType.SINT32:
259 			case CIMDataType.SINT64:
260 			case CIMDataType.UINT8:
261 			case CIMDataType.UINT16:
262 			case CIMDataType.UINT32:
263 			case CIMDataType.UINT64:
264 			case CIMDataType.REAL32:
265 			case CIMDataType.REAL64:
266 				return true;
267 		}
268 		return false;
269 	}
270 
271 	private static Object translateNumericObject(Object oldValue, CIMDataType oldType, CIMDataType newType) {
272 		if (oldValue == null) return null;
273 
274 		int from = oldType.getType(), to = newType.getType();
275 		long newInt = 0;
276 		double newDec = 0;
277 		Object o = null;
278 		boolean useInt = true;
279 
280 		switch (from) {
281 			case CIMDataType.SINT8:
282 				Byte b = (Byte) oldValue;
283 				newInt = b.longValue();
284 				break;
285 			case CIMDataType.SINT16:
286 				Short s = (Short) oldValue;
287 				newInt = s.longValue();
288 				break;
289 			case CIMDataType.SINT32:
290 				Integer i = (Integer) oldValue;
291 				newInt = i.longValue();
292 				break;
293 			case CIMDataType.SINT64:
294 				Long l = (Long) oldValue;
295 				newInt = l.longValue();
296 				break;
297 			case CIMDataType.UINT8:
298 				UnsignedInteger8 u8 = (UnsignedInteger8) oldValue;
299 				newInt = u8.longValue();
300 				break;
301 			case CIMDataType.UINT16:
302 				UnsignedInteger16 u16 = (UnsignedInteger16) oldValue;
303 				newInt = u16.longValue();
304 				break;
305 			case CIMDataType.UINT32:
306 				UnsignedInteger32 u32 = (UnsignedInteger32) oldValue;
307 				newInt = u32.longValue();
308 				break;
309 			case CIMDataType.UINT64:
310 				UnsignedInteger64 u64 = (UnsignedInteger64) oldValue;
311 				newInt = u64.longValue();
312 				break;
313 			case CIMDataType.REAL32:
314 				Float f = (Float) oldValue;
315 				newDec = f.doubleValue();
316 				useInt = false;
317 				break;
318 			case CIMDataType.REAL64:
319 				Double d = (Double) oldValue;
320 				newDec = d.doubleValue();
321 				useInt = false;
322 				break;
323 		}
324 
325 		switch (to) {
326 			case CIMDataType.SINT8:
327 				byte b = (byte) (useInt ? newInt : newDec);
328 				o = new Byte(b);
329 				break;
330 			case CIMDataType.SINT16:
331 				short s = (short) (useInt ? newInt : newDec);
332 				o = new Short(s);
333 				break;
334 			case CIMDataType.SINT32:
335 				int i = (int) (useInt ? newInt : newDec);
336 				o = new Integer(i);
337 				break;
338 			case CIMDataType.SINT64:
339 				long l = (long) (useInt ? newInt : newDec);
340 				o = new Long(l);
341 				break;
342 			case CIMDataType.UINT8:
343 				byte u8 = (byte) (useInt ? newInt : newDec);
344 				o = new UnsignedInteger8(u8);
345 				break;
346 			case CIMDataType.UINT16:
347 				short u16 = (short) (useInt ? newInt : newDec);
348 				o = new UnsignedInteger16(u16);
349 				break;
350 			case CIMDataType.UINT32:
351 				int u32 = (int) (useInt ? newInt : newDec);
352 				o = new UnsignedInteger32(u32);
353 				break;
354 			case CIMDataType.UINT64:
355 				long u64 = (long) (useInt ? newInt : newDec);
356 				o = new UnsignedInteger64(BigInteger.valueOf(u64));
357 				break;
358 			case CIMDataType.REAL32:
359 				float f = (float) (useInt ? newInt : newDec);
360 				o = new Float(f);
361 				break;
362 			case CIMDataType.REAL64:
363 				double d = useInt ? (double) newInt : newDec;
364 				o = new Double(d);
365 				break;
366 		}
367 
368 		return o;
369 	}
370 }