1 | /* |
2 | * $Id: VARIANT.java,v 1.16 2005/12/16 22:32:46 hastings Exp $ |
3 | * |
4 | * (c) Copyright, Moebius Solutions, Inc., 2004 |
5 | * |
6 | * All Rights Reserved |
7 | * |
8 | * This material may be reproduced by or for the U. S. Government |
9 | * pursuant to the copyright license under the clause at |
10 | * DFARS 252.227-7014 (OCT 2001). |
11 | */ |
12 | |
13 | package com.moesol.bindings.platform_sdk.component_services; |
14 | |
15 | import java.io.PrintWriter; |
16 | import java.io.StringWriter; |
17 | import java.lang.reflect.Array; |
18 | import java.nio.Buffer; |
19 | import java.nio.ByteBuffer; |
20 | import com.moesol.bindings.NativeStructure; |
21 | import com.moesol.nio.BufferMarker; |
22 | import com.moesol.util.DumpBytes; |
23 | |
24 | public class VARIANT extends NativeStructure implements VARENUM { |
25 | public VARIANT() { |
26 | super( new byte[sizeof()] ); |
27 | } |
28 | public VARIANT(ByteBuffer bb) { |
29 | super( bb ); |
30 | } |
31 | public static int sizeof() { |
32 | return 16; |
33 | } |
34 | |
35 | /** |
36 | * Get the reference for this VARIANT. |
37 | * |
38 | * @return reference array of size one (1) or null. |
39 | */ |
40 | public Object getReference() { |
41 | return m_ref; |
42 | } |
43 | /** |
44 | * Set the reference for this VARIANT. When the VT_BYREF bit flag |
45 | * is set in the vt field, the native bindings will use the |
46 | * reference set here. The reference should be an array of size |
47 | * one (1). The type of the array should match the VARTYPE set in |
48 | * the other bits of the vt field. Element zero will contain the |
49 | * referred to value. |
50 | * |
51 | * @param ref |
52 | * @throws COMException if ref is null, not an array, or not length 1 |
53 | */ |
54 | public void setReference(Object ref) { |
55 | if (ref == null) { |
56 | throw new COMException("Requires non-null array.", HRESULT.E_INVALIDARG); |
57 | } |
58 | if (isBadArray(ref)) { |
59 | throw new COMException("Requires an array.", HRESULT.E_INVALIDARG); |
60 | } |
61 | if (Array.getLength(ref) != 1) { |
62 | throw new COMException("Requires length of one.", HRESULT.E_INVALIDARG); |
63 | } |
64 | m_ref = ref; |
65 | } |
66 | private Object m_ref = null; |
67 | |
68 | /** |
69 | * Get the array for this VARIANT. |
70 | * |
71 | * @return the array. |
72 | */ |
73 | public Object getArray() { |
74 | return m_array; |
75 | } |
76 | /** |
77 | * Set the array for this VARIANT. When the VT_ARRAY bit flag is |
78 | * set in the vt field, the native bindings will use the array set |
79 | * here. The array element type should match the VARTYPE set in |
80 | * the other bits of the vt field. |
81 | * |
82 | * @param array |
83 | * @throws COMException if <code>array</code> is not an array. |
84 | */ |
85 | public void setArray(Object array) { |
86 | if (array == null) { |
87 | m_array = null; |
88 | return; |
89 | } |
90 | if (isBadArray(array)) { |
91 | throw new COMException("Requires an array.", HRESULT.E_INVALIDARG); |
92 | } |
93 | m_array = array; |
94 | } |
95 | /** |
96 | * @param array |
97 | * @return |
98 | */ |
99 | private boolean isBadArray(Object array) { |
100 | if (array.getClass().isArray()) { |
101 | return false; |
102 | } |
103 | if (array instanceof BufferMarker) { |
104 | return false; |
105 | } |
106 | if (array instanceof Buffer) { |
107 | return false; |
108 | } |
109 | return true; |
110 | } |
111 | |
112 | private Object m_array; |
113 | |
114 | /** |
115 | * Get the record for this VARIANT. |
116 | * |
117 | * @return the record |
118 | */ |
119 | public NativeStructure getRecord() { |
120 | return m_record; |
121 | } |
122 | /** |
123 | * Set the record for this VARIANT. Note that the variant type is not |
124 | * automatically set when this method is called. You may want to call |
125 | * makeRecord instead of this method. |
126 | * |
127 | * @param record |
128 | */ |
129 | public void setRecord(NativeStructure record) { |
130 | m_record = record; |
131 | } |
132 | private NativeStructure m_record; |
133 | |
134 | /** |
135 | * Set the string for this VARIANT. When the VARIANT is of type |
136 | * VT_BSTR, VT_LPSTR, or VT_LPWSTR the converion to a native type |
137 | * uses this property. Normally, you do not need to use this for |
138 | * VT_BSTR since a java.lang.String will convert to VT_BSTR automatically. |
139 | * |
140 | * @param s |
141 | */ |
142 | public void setString(String s) { |
143 | m_string = s; |
144 | } |
145 | /** @return String property */ |
146 | public String getString() { |
147 | return m_string; |
148 | } |
149 | private String m_string; |
150 | |
151 | public void set_vt(short v) { |
152 | putShort(0, v); |
153 | } |
154 | public short get_vt() { |
155 | return getShort(0); |
156 | } |
157 | public void set_lVal(int v) { |
158 | putInt(8, v); |
159 | } |
160 | public int get_lVal() { |
161 | return getInt(8); |
162 | } |
163 | public void set_iVal(short v) { |
164 | putShort(8, v); |
165 | } |
166 | public short get_iVal() { |
167 | return getShort(8); |
168 | } |
169 | public void set_fltVal(float v) { |
170 | putFloat(8, v); |
171 | } |
172 | public float get_fltVal() { |
173 | return getFloat(8); |
174 | } |
175 | public void set_dblVal(double v) { |
176 | putDouble(8, v); |
177 | } |
178 | public double get_dblVal() { |
179 | return getDouble(8); |
180 | } |
181 | public void set_boolVal(short v) { |
182 | putShort(8, v); |
183 | } |
184 | public short get_boolVal() { |
185 | return getShort(8); |
186 | } |
187 | public void set_scode(int v) { |
188 | putInt(8, v); |
189 | } |
190 | public int get_scode() { |
191 | return getInt(8); |
192 | } |
193 | public void set_cyVal(long v) { |
194 | putLong(8, v); |
195 | } |
196 | public long get_cyVal() { |
197 | return getLong(8); |
198 | } |
199 | public void set_cVal(byte v) { |
200 | putByte(8, v); |
201 | } |
202 | public byte get_cVal() { |
203 | return getByte(8); |
204 | } |
205 | public void set_date(double v) { |
206 | putDouble(8, v); |
207 | } |
208 | public double get_date() { |
209 | return getDouble(8); |
210 | } |
211 | public void set_bVal(short v) { |
212 | putByte(8, (byte)v); |
213 | } |
214 | public short get_bVal() { |
215 | return getByte(8); |
216 | } |
217 | public void set_uiVal(int v) { |
218 | putShort(8, (short)v); |
219 | } |
220 | public int get_uiVal() { |
221 | return getShort(8); |
222 | } |
223 | public void set_ulVal(long v) { |
224 | putInt(8, (int)v); |
225 | } |
226 | public long get_ulVal() { |
227 | return getInt(8); |
228 | } |
229 | public void set_llVal(long v) { |
230 | putLong(8, v); |
231 | } |
232 | public long get_llVal() { |
233 | return getLong(8); |
234 | } |
235 | public void set_intVal(int v) { |
236 | putInt(8, v); |
237 | } |
238 | public int get_intVal() { |
239 | return getInt(8); |
240 | } |
241 | public void set_uintVal(long v) { |
242 | putInt(8, (int)v); |
243 | } |
244 | public long get_uintVal() { |
245 | return getInt(8); |
246 | } |
247 | |
248 | public final static VARIANT EMPTY = makeEmpty(); |
249 | public final static VARIANT NULL = makeNull(); |
250 | public final static VARIANT PARAMNOTFOUND = makeERROR(HRESULT.DISP_E_PARAMNOTFOUND); |
251 | public static final short VARIANT_FALSE = 0; |
252 | public static final short VARIANT_TRUE = (short)0xFFFF; |
253 | |
254 | public static VARIANT makeI2(short iVal) { |
255 | VARIANT v = new VARIANT(); |
256 | v.set_vt(VT_I2); |
257 | v.set_iVal(iVal); |
258 | return v; |
259 | } |
260 | public static VARIANT makeI4(int lVal) { |
261 | VARIANT v = new VARIANT(); |
262 | v.set_vt(VT_I4); |
263 | v.set_lVal(lVal); |
264 | return v; |
265 | } |
266 | public static VARIANT makeR4(float fltVal) { |
267 | VARIANT v = new VARIANT(); |
268 | v.set_vt(VT_R4); |
269 | v.set_fltVal(fltVal); |
270 | return v; |
271 | } |
272 | public static VARIANT makeR8(double dblVal) { |
273 | VARIANT v = new VARIANT(); |
274 | v.set_vt(VT_R8); |
275 | v.set_dblVal(dblVal); |
276 | return v; |
277 | } |
278 | public static VARIANT makeBOOL(boolean bool) { |
279 | VARIANT v = new VARIANT(); |
280 | v.set_vt(VT_BOOL); |
281 | v.set_boolVal(bool ? VARIANT_TRUE : VARIANT_FALSE); |
282 | return v; |
283 | } |
284 | public static VARIANT makeI1(byte cVal) { |
285 | VARIANT v = new VARIANT(); |
286 | v.set_vt(VT_I1); |
287 | v.set_cVal(cVal); |
288 | return v; |
289 | } |
290 | public static VARIANT makeUI1(short bVal) { |
291 | VARIANT v = new VARIANT(); |
292 | v.set_vt(VT_UI1); |
293 | v.set_bVal(bVal); |
294 | return v; |
295 | } |
296 | public static VARIANT makeUI2(int uiVal) { |
297 | VARIANT v = new VARIANT(); |
298 | v.set_vt(VT_UI2); |
299 | v.set_uiVal(uiVal); |
300 | return v; |
301 | } |
302 | public static VARIANT makeUI4(long ulVal) { |
303 | VARIANT v = new VARIANT(); |
304 | v.set_vt(VT_UI4); |
305 | v.set_ulVal(ulVal); |
306 | return v; |
307 | } |
308 | public static VARIANT makeI8(long lVal) { |
309 | VARIANT v = new VARIANT(); |
310 | v.set_vt(VT_I8); |
311 | v.set_llVal(lVal); |
312 | return v; |
313 | } |
314 | /* TODO |
315 | public static VARIANT makeUI8(long lVal) { |
316 | VARIANT v = new VARIANT(); |
317 | v.set_vt(VT_UI8); |
318 | v.set_ulVal(lVal); |
319 | return v; |
320 | } |
321 | */ |
322 | public static VARIANT makeINT(int intVal) { |
323 | VARIANT v = new VARIANT(); |
324 | v.set_vt(VT_INT); |
325 | v.set_intVal(intVal); |
326 | return v; |
327 | } |
328 | public static VARIANT makeUINT(long uintVal) { |
329 | VARIANT v = new VARIANT(); |
330 | v.set_vt(VT_UINT); |
331 | v.set_uintVal(uintVal); |
332 | return v; |
333 | } |
334 | public static VARIANT makeERROR(int scode) { |
335 | VARIANT v = new VARIANT(); |
336 | v.set_vt(VT_ERROR); |
337 | v.set_scode(scode); |
338 | return v; |
339 | } |
340 | public static VARIANT makeCY(long cy) { |
341 | VARIANT v = new VARIANT(); |
342 | v.set_vt(VT_CY); |
343 | v.set_cyVal(cy); |
344 | return v; |
345 | } |
346 | /** |
347 | * Wrap disp in a VARIANT if it is null, otherwise just return disp. |
348 | * COM cannot convert a VT_NULL to a VT_DISPATCH so if we want to pass |
349 | * NULL for any VT_DISPATCH argument we must first wrap it in a VARIANT |
350 | * of type VT_DISPATCH |
351 | * |
352 | * @return disp or a VARIANT of type VT_DISPATCH and value NULL. |
353 | */ |
354 | public static Object wrapDISPATCH(IDispatch disp) { |
355 | if (disp != null) { |
356 | return disp; |
357 | } |
358 | return wrapWithVt(VT_DISPATCH); |
359 | } |
360 | /** @see #wrapDISPATCH */ |
361 | public static Object wrapUNKNOWN(IUnknown i) { |
362 | if (i != null) { |
363 | return i; |
364 | } |
365 | return wrapWithVt(VT_UNKNOWN); |
366 | } |
367 | /** |
368 | * Wrap s in a VARIANT if it is null, otherwise just return s. |
369 | * COM cannot convert a VT_NULL to a VT_BSTR so if we want to pass |
370 | * NULL for any VT_BSTR argument we must first wrap it in a VARIANT |
371 | * of type VT_BSTR |
372 | * |
373 | * @return s or a VARIANT of type VT_BSTR and value NULL. |
374 | */ |
375 | public static Object wrapBSTR(String s) { |
376 | if (s != null) { |
377 | return s; |
378 | } |
379 | // return wrapWithVt(VT_BSTR); |
380 | // |
381 | // I cannot seem to pass a VARIANT with |
382 | // vt = VT_BSTR |
383 | // bstrVal = NULL, ITypeInfo::Invoke returns an error |
384 | // Using VT_EMPTY has the same effect as |
385 | // vt = VT_BSTR |
386 | // String = "" |
387 | return EMPTY; |
388 | } |
389 | /** @see #wrapBSTR */ |
390 | public static Object wrapLPSTR(String s) { |
391 | if (s != null) { |
392 | return s; |
393 | } |
394 | return wrapWithVt(VT_LPSTR); |
395 | } |
396 | |
397 | /** |
398 | * Creates a VARIANT that passes VARTYPE vt by reference. |
399 | * First a new VARIANT is created and its set_vt is called with |
400 | * (vt | VT_BYREF), then setReference(ref) is called. |
401 | * |
402 | * @param vt |
403 | * @param ref |
404 | * @return VT_BYREF variant |
405 | * |
406 | * @throws COMException if ref is null, not an array, or not length 1 |
407 | * @see #setReference . |
408 | */ |
409 | public static VARIANT makeReference(int vt, Object ref) { |
410 | VARIANT v = new VARIANT(); |
411 | vt |= VT_BYREF; |
412 | assert((vt & 0xFFFF0000) == 0); |
413 | v.set_vt((short)vt); |
414 | v.setReference(ref); |
415 | return v; |
416 | } |
417 | /** |
418 | * Creates a VARIANT that passes VARTYPE vt by reference. |
419 | * First a new VARIANT is created and its set_vt is called with |
420 | * (vt | VT_BYREF), then setReference(ref) is called. |
421 | * |
422 | * @param vt |
423 | * @param array |
424 | * @return a new VARIANT |
425 | * |
426 | * @throws COMException if <code>array</code> is not an array. |
427 | * @see #setArray . |
428 | */ |
429 | public static VARIANT makeArray(short vt, Object array) { |
430 | VARIANT v = new VARIANT(); |
431 | vt |= VT_ARRAY; |
432 | v.set_vt(vt); |
433 | v.setArray(array); |
434 | return v; |
435 | } |
436 | /** |
437 | * |
438 | * @return variant for record |
439 | */ |
440 | public static VARIANT makeRecord(NativeStructure record) { |
441 | VARIANT v = new VARIANT(); |
442 | v.set_vt(VT_RECORD); |
443 | v.setRecord(record); |
444 | return v; |
445 | } |
446 | |
447 | private static VARIANT makeEmpty() { |
448 | VARIANT v = new VARIANT(); |
449 | |
450 | v.set_vt(VT_EMPTY); |
451 | return v; |
452 | } |
453 | private static VARIANT makeNull() { |
454 | VARIANT v = new VARIANT(); |
455 | |
456 | v.set_vt(VT_NULL); |
457 | return v; |
458 | } |
459 | private static Object wrapWithVt(short vt) { |
460 | VARIANT v = new VARIANT(); |
461 | v.set_vt(vt); |
462 | v.set_lVal(0); |
463 | return v; |
464 | } |
465 | |
466 | /* (non-Javadoc) |
467 | * @see java.lang.Object#toString() |
468 | */ |
469 | public String toString() { |
470 | StringBuffer sb = new StringBuffer(); |
471 | sb.append(computeVtName()); |
472 | sb.append('['); |
473 | sb.append(computeValueString()); |
474 | sb.append(']'); |
475 | return sb.toString(); |
476 | } |
477 | |
478 | private String computeVtName() { |
479 | StringBuffer sb = new StringBuffer(); |
480 | |
481 | if (flagPresent(VARIANT.VT_VECTOR)) { |
482 | sb.append("VT_VECTOR | "); |
483 | } |
484 | if (flagPresent(VARIANT.VT_ARRAY)) { |
485 | sb.append("VT_ARRAY | "); |
486 | } |
487 | if (flagPresent(VARIANT.VT_BYREF)) { |
488 | sb.append("VT_BYREF | "); |
489 | } |
490 | if (flagPresent(VT_RESERVED)) { |
491 | sb.append("VT_RESERVED"); |
492 | } |
493 | |
494 | for (int i = 0; i < s_type_names.length; i++) { |
495 | if (get_vt() == s_type_names[i].getVt()) { |
496 | sb.append(s_type_names[i].getName()); |
497 | break; |
498 | } |
499 | } |
500 | |
501 | return sb.toString(); |
502 | } |
503 | |
504 | private String computeValueString() { |
505 | StringWriter sw = new StringWriter(); |
506 | PrintWriter pw = new PrintWriter(sw); |
507 | try { |
508 | DumpBytes.dumpBytes(pw, getByteBuffer()); |
509 | pw.print("m_array="); pw.print(m_array); pw.print(" "); |
510 | pw.print("m_ref="); pw.print(m_ref); pw.print(" "); |
511 | pw.print("m_record="); pw.print(m_record); pw.print(" "); |
512 | pw.print("m_string="); pw.print(m_string); |
513 | } finally { |
514 | pw.close(); |
515 | } |
516 | return sw.toString(); |
517 | } |
518 | |
519 | private boolean flagPresent(short flag) { |
520 | return flag == (get_vt() & flag); |
521 | } |
522 | |
523 | private static class ValueToName { |
524 | private short m_vt; |
525 | private String m_name; |
526 | |
527 | public ValueToName(short vt, String name) { |
528 | m_vt = vt; |
529 | m_name = name; |
530 | } |
531 | public short getVt() { |
532 | return m_vt; |
533 | } |
534 | public String getName() { |
535 | return m_name; |
536 | } |
537 | } |
538 | private static final ValueToName[] s_type_names = { |
539 | new ValueToName(VT_EMPTY, "VT_EMPTY"), |
540 | new ValueToName(VT_NULL, "VT_NULL"), |
541 | new ValueToName(VT_I2, "VT_I2"), |
542 | new ValueToName(VT_I4, "VT_I4"), |
543 | new ValueToName(VT_R4, "VT_R4"), |
544 | new ValueToName(VT_R8, "VT_R8"), |
545 | new ValueToName(VT_CY, "VT_CY"), |
546 | new ValueToName(VT_DATE, "VT_DATE"), |
547 | new ValueToName(VT_BSTR, "VT_BSTR"), |
548 | new ValueToName(VT_DISPATCH, "VT_DISPATCH"), |
549 | new ValueToName(VT_ERROR, "VT_ERROR"), |
550 | new ValueToName(VT_BOOL, "VT_BOOL"), |
551 | new ValueToName(VT_VARIANT, "VT_VARIANT"), |
552 | new ValueToName(VT_UNKNOWN, "VT_UNKNOWN"), |
553 | new ValueToName(VT_DECIMAL, "VT_DECIMAL"), |
554 | new ValueToName(VT_I1, "VT_I1"), |
555 | new ValueToName(VT_UI1, "VT_UI1"), |
556 | new ValueToName(VT_UI2, "VT_UI2"), |
557 | new ValueToName(VT_UI4, "VT_UI4"), |
558 | new ValueToName(VT_I8, "VT_I8"), |
559 | new ValueToName(VT_UI8, "VT_UI8"), |
560 | new ValueToName(VT_INT, "VT_INT"), |
561 | new ValueToName(VT_UINT, "VT_UINT"), |
562 | new ValueToName(VT_VOID, "VT_VOID"), |
563 | new ValueToName(VT_HRESULT, "VT_HRESULT"), |
564 | new ValueToName(VT_PTR, "VT_PTR"), |
565 | new ValueToName(VT_SAFEARRAY, "VT_SAFEARRAY"), |
566 | new ValueToName(VT_CARRAY, "VT_CARRAY"), |
567 | new ValueToName(VT_USERDEFINED, "VT_USERDEFINED"), |
568 | new ValueToName(VT_LPSTR, "VT_LPSTR"), |
569 | new ValueToName(VT_LPWSTR, "VT_LPWSTR"), |
570 | new ValueToName(VT_RECORD, "VT_RECORD"), |
571 | new ValueToName(VT_FILETIME, "VT_FILETIME"), |
572 | new ValueToName(VT_BLOB, "VT_BLOB"), |
573 | new ValueToName(VT_STREAM, "VT_STREAM"), |
574 | new ValueToName(VT_STORAGE, "VT_STORAGE"), |
575 | new ValueToName(VT_STREAMED_OBJECT, "VT_STREAMED_OBJECT"), |
576 | new ValueToName(VT_STORED_OBJECT, "VT_STORED_OBJECT"), |
577 | new ValueToName(VT_BLOB_OBJECT, "VT_BLOB_OBJECT"), |
578 | new ValueToName(VT_CF, "VT_CF"), |
579 | new ValueToName(VT_CLSID, "VT_CLSID"), |
580 | new ValueToName(VT_BSTR_BLOB, "VT_BSTR_BLOB"), |
581 | new ValueToName(VT_VECTOR, "VT_VECTOR"), |
582 | new ValueToName(VT_ARRAY, "VT_ARRAY"), |
583 | new ValueToName(VT_BYREF, "VT_BYREF"), |
584 | new ValueToName(VT_RESERVED, "VT_RESERVED"), |
585 | new ValueToName(VT_ILLEGAL, "VT_ILLEGAL"), |
586 | new ValueToName(VT_ILLEGALMASKED, "VT_ILLEGALMASKED"), |
587 | new ValueToName(VT_TYPEMASK, "VT_TYPEMASK"), |
588 | }; |
589 | |
590 | } |