/* * Copyright (C) 2010-2023 Oracle and/or its affiliates. * * This file is part of a free software library; you can redistribute * it and/or modify it under the terms of the GNU Lesser General * Public License version 2.1 as published by the Free Software * Foundation and shipped in the \"COPYING.LIB\" file with this library. * The library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY of any kind. * * Oracle LGPL Disclaimer: For the avoidance of doubt, except that if * any license choice other than GPL or LGPL is available it will * apply instead, Oracle elects to use only the Lesser General Public * License version 2.1 (LGPLv2) at this time for any software where * a choice of LGPL license versions is made available with the * language indicating that LGPLv2 or any later version may be used, * or where a choice of which version of the LGPL is applied is * otherwise unspecified. * http://www.virtualbox.org. This library is free software; you can * redistribute it and/or modify it under the terms of the GNU Lesser General * Public License as published by the Free Software Foundation, in version 2.1 * as it comes in the "COPYING.LIB" file of the VirtualBox SDK distribution. * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * License for more details. * * SPDX-License-Identifier: LGPL-2.1-only */ /* * * DO NOT EDIT! This is a generated file. * Generated from: src/VBox/Main/idl/VirtualBox.xidl (VirtualBox's interface definitions in XML) * Generator: src/VBox/Main/glue/glue-java.xsl */ import org.mozilla.interfaces.*; import com.jacob.com.*; import com.jacob.activeX.ActiveXComponent; import javax.xml.ws.*; <code> <h2> </code> </h2> ( , Holder ) () {@link } # NOTE: @see <p></p><dl><dt><b>Expected result codes:</b></dt> <dd><code> </code> - </dd> </dl> Interface ID: <code>{ }</code> */ @return yes */ @param value yes */ */ @return @param Interface ID: <code>{ }</code> */ */ { , ; private final int value; { value = v; } public int value() { return value; } { { if (c.value == (int)v) { return c; } } throw new IllegalArgumentException(Long.toString(v)); } { } } this.getObjMgr().preventObjRelease(); try { } catch (org.mozilla.xpcom.XPCOMException e) { throw new VBoxException(e.getMessage(), e); } } catch (com.jacob.com.ComException e) { throw new VBoxException(e.getMessage(), e); } } catch (InvalidObjectFaultMsg e) { throw new VBoxException(e.getMessage(), e, this.getObjMgr(), this.port); } catch (RuntimeFaultMsg e) { throw new VBoxException(e.getMessage(), e, this.getObjMgr(), this.port); } finally { getObjMgr().allowObjRelease(); } com.jacob.com.Dispatch String List &lt; < IUnknown &gt; > [] long long int int short byte boolean nsISupports String String long [] Variant List< String String /*base64*/String Long Long Integer Integer Short Boolean String String > null null, , ); , ); obj , , , ); null ); private VboxPortType port; private ObjectRefManager objMgr; { this.real = real; this.port = port; this.objMgr = objMgr; } { } void retVal.value retVal , ) { } void , ); { nsISupports nsobj = obj != null ? (nsISupports)obj.getWrapped() : null; if (nsobj == null) return null; } void , ) { Variant _args[]) { , ); } { super(wrapped, objMgr, port); } { super(wrapped); } { } { } { } import java.util.List; { { { } import java.util.List; { } import java.util.List; { { { this.sink = sink; } } { public T value; public Holder() { } public Holder(T value) { this.value = value; } } ]]> wrap(byte[] values) { if (values == null) return null; List ret = new ArrayList(values.length); for (short v : values) { ret.add(v); } return ret; } public static List wrap(short[] values) { if (values == null) return null; List ret = new ArrayList(values.length); for (short v : values) { ret.add(v); } return ret; } public static List wrap(int[] values) { if (values == null) return null; List ret = new ArrayList(values.length); for (int v : values) { ret.add(v); } return ret; } public static List wrap(long[] values) { if (values == null) return null; List ret = new ArrayList(values.length); for (long v : values) { ret.add(v); } return ret; } public static List wrap(boolean[] values) { if (values == null) return null; List ret = new ArrayList(values.length); for (boolean v: values) { ret.add(v); } return ret; } public static List wrap(String[] values) { if (values == null) return null; List ret = new ArrayList(values.length); for (String v : values) { ret.add(v); } return ret; } public static List wrap(Class wrapperClass, T[] values) { if (values == null) return null; List ret = new ArrayList(values.length); for (T v : values) { ret.add(v); } return ret; } @SuppressWarnings( "unchecked") public static List wrapEnum(Class wrapperClass, long values[]) { try { if (values == null) return null; //// This code is questionable, as it invokes a private constructor //// (all enums only have default constructors), and we don't really //// know what to pass as the name, and the ordinal may or may not //// be sensible, especially if the long was abused as a bitset. //Constructor c = wrapperClass.getDeclaredConstructor(String.class, int.class, int.class); //c.setAccessible(true); // make it callable //List ret = new ArrayList(values.length); //for (long v : values) //{ // T convEnum = c.newInstance("unknown", (int)v, (int)v); // ret.add(convEnum); //} // Alternative implementation: use the fromValue method, which is // what the code handling single enums will do. I see no reason to // use the above very ugly hack if there are better alternatives, // which as a bonus complain about unknown values. This variant is // slower, but also orders of magnitude safer. java.lang.reflect.Method fromValue = wrapperClass.getMethod("fromValue", long.class); List ret = new ArrayList(values.length); for (long v : values) { T convEnum = (T)fromValue.invoke(null, v); ret.add(convEnum); } return ret; } catch (NoSuchMethodException e) { throw new AssertionError(e); } //catch (InstantiationException e) //{ // throw new AssertionError(e); //} catch (IllegalAccessException e) { throw new AssertionError(e); } catch (InvocationTargetException e) { throw new AssertionError(e); } } public static short[] unwrapUShort(List values) { if (values == null) return null; short[] ret = new short[values.size()]; int i = 0; for (short l : values) { ret[i++] = l; } return ret; } public static int[] unwrapInteger(List values) { if (values == null) return null; int[] ret = new int[values.size()]; int i = 0; for (int l : values) { ret[i++] = l; } return ret; } public static long[] unwrapULong(List values) { if (values == null) return null; long[] ret = new long[values.size()]; int i = 0; for (long l : values) { ret[i++] = l; } return ret; } public static boolean[] unwrapBoolean(List values) { if (values == null) return null; boolean[] ret = new boolean[values.size()]; int i = 0; for (boolean l : values) { ret[i++] = l; } return ret; } public static String[] unwrapStr(List values) { if (values == null) return null; String[] ret = new String[values.size()]; int i = 0; for (String l : values) { ret[i++] = l; } return ret; } public static > long[] unwrapEnum(Class enumClass, List values) { if (values == null) return null; long result[] = new long[values.size()]; try { java.lang.reflect.Method valueM = enumClass.getMethod("value"); int i = 0; for (T v : values) { result[i++] = (Integer)valueM.invoke(v); } return result; } catch (NoSuchMethodException e) { throw new AssertionError(e); } catch(SecurityException e) { throw new AssertionError(e); } catch (IllegalAccessException e) { throw new AssertionError(e); } catch (IllegalArgumentException e) { throw new AssertionError(e); } catch (InvocationTargetException e) { throw new AssertionError(e); } } public static List wrap2(Class wrapperClass1, Class wrapperClass2, T2[] values) { try { if (values == null) return null; Constructor c = wrapperClass1.getConstructor(wrapperClass2); List ret = new ArrayList(values.length); for (T2 v : values) { ret.add(c.newInstance(v)); } return ret; } catch (NoSuchMethodException e) { throw new AssertionError(e); } catch (InstantiationException e) { throw new AssertionError(e); } catch (IllegalAccessException e) { throw new AssertionError(e); } catch (InvocationTargetException e) { throw new AssertionError(e); } } @SuppressWarnings( "unchecked") public static T[] unwrap(Class wrapperClass, List values) { if (values == null) return null; if (values.size() == 0) return null; return (T[])values.toArray((T[])Array.newInstance(wrapperClass, values.size())); } @SuppressWarnings( "unchecked" ) public static T queryInterface(Object obj, String uuid, Class iface) { return (T)queryInterface(obj, uuid); } public static Object queryInterface(Object obj, String uuid) { try { /* Kind of ugly, but does the job of casting */ org.mozilla.xpcom.Mozilla moz = org.mozilla.xpcom.Mozilla.getInstance(); long xpobj = moz.wrapJavaObject(obj, uuid); return moz.wrapXPCOMObject(xpobj, uuid); } catch (Exception e) { return null; } } @SuppressWarnings("unchecked") public static T2[] unwrap2(Class wrapperClass1, Class wrapperClass2, List values) { if (values == null) return null; T2 ret[] = (T2[])Array.newInstance(wrapperClass2, values.size()); int i = 0; for (T1 obj : values) { ret[i++] = (T2)obj.getWrapped(); } return ret; } } ]]> import org.mozilla.xpcom.*; public class VBoxException extends RuntimeException { private int resultCode; private IVirtualBoxErrorInfo errorInfo; public VBoxException(String message) { super(message); resultCode = -1; errorInfo = null; } public VBoxException(String message, Throwable cause) { super(message, cause); if (cause instanceof org.mozilla.xpcom.XPCOMException) { resultCode = (int)((org.mozilla.xpcom.XPCOMException)cause).errorcode; try { Mozilla mozilla = Mozilla.getInstance(); nsIServiceManager sm = mozilla.getServiceManager(); nsIExceptionService es = (nsIExceptionService)sm.getServiceByContractID("@mozilla.org/exceptionservice;1", nsIExceptionService.NS_IEXCEPTIONSERVICE_IID); nsIExceptionManager em = es.getCurrentExceptionManager(); nsIException ex = em.getCurrentException(); errorInfo = new IVirtualBoxErrorInfo((org.mozilla.interfaces.IVirtualBoxErrorInfo)ex.queryInterface(org.mozilla.interfaces.IVirtualBoxErrorInfo.IVIRTUALBOXERRORINFO_IID)); } catch (NullPointerException e) { e.printStackTrace(); // nothing we can do errorInfo = null; } } else resultCode = -1; } public int getResultCode() { return resultCode; } public IVirtualBoxErrorInfo getVirtualBoxErrorInfo() { return errorInfo; } } wrap(short[] values) { if (values == null) return null; List ret = new ArrayList(values.length); for (short v : values) { ret.add(v); } return ret; } public static List wrap(int[] values) { if (values == null) return null; List ret = new ArrayList(values.length); for (int v : values) { ret.add(v); } return ret; } public static List wrap(long[] values) { if (values == null) return null; List ret = new ArrayList(values.length); for (long v : values) { ret.add(v); } return ret; } public static List wrap(String[] values) { if (values == null) return null; List ret = new ArrayList(values.length); for (String v : values) { ret.add(v); } return ret; } public static T wrapDispatch(Class wrapperClass, Dispatch d) { try { if (d == null || d.m_pDispatch == 0) return null; Constructor c = wrapperClass.getConstructor(Dispatch.class); return (T)c.newInstance(d); } catch (NoSuchMethodException e) { throw new AssertionError(e); } catch (InstantiationException e) { throw new AssertionError(e); } catch (IllegalAccessException e) { throw new AssertionError(e); } catch (InvocationTargetException e) { throw new AssertionError(e); } } @SuppressWarnings("unchecked") public static Object wrapVariant(Class wrapperClass, Variant v) { if (v == null) return null; short vt = v.getvt(); switch (vt) { case Variant.VariantNull: return null; case Variant.VariantBoolean: return v.getBoolean(); case Variant.VariantByte: return v.getByte(); case Variant.VariantShort: return v.getShort(); case Variant.VariantInt: return v.getInt(); case Variant.VariantLongInt: return v.getLong(); case Variant.VariantString: return v.getString(); case Variant.VariantDispatch: return wrapDispatch(wrapperClass, v.getDispatch()); default: throw new IllegalArgumentException("unhandled variant type " + vt); } } public static byte[] wrapBytes(SafeArray sa) { if (sa == null) return null; int saLen = sa.getUBound() - sa.getLBound() + 1; byte[] ret = new byte[saLen]; int j = 0; for (int i = sa.getLBound(); i <= sa.getUBound(); i++) { Variant v = sa.getVariant(i); // come up with more effective approach!!! ret[j++] = v.getByte(); } return ret; } @SuppressWarnings("unchecked") public static List wrap(Class wrapperClass, SafeArray sa) { if (sa == null) return null; int saLen = sa.getUBound() - sa.getLBound() + 1; if (saLen == 0) return Collections.emptyList(); List ret = new ArrayList(saLen); for (int i = sa.getLBound(); i <= sa.getUBound(); i++) { Variant v = sa.getVariant(i); ret.add((T)wrapVariant(wrapperClass, v)); } return ret; } public static List wrapEnum(Class wrapperClass, SafeArray sa) { try { if (sa == null) return null; int saLen = sa.getUBound() - sa.getLBound() + 1; if (saLen == 0) return Collections.emptyList(); List ret = new ArrayList(saLen); Constructor c = wrapperClass.getConstructor(int.class); for (int i = sa.getLBound(); i <= sa.getUBound(); i++) { Variant v = sa.getVariant(i); ret.add(c.newInstance(v.getInt())); } return ret; } catch (NoSuchMethodException e) { throw new AssertionError(e); } catch (InstantiationException e) { throw new AssertionError(e); } catch (IllegalAccessException e) { throw new AssertionError(e); } catch (InvocationTargetException e) { throw new AssertionError(e); } } public static SafeArray unwrapInt(List values) { if (values == null) return null; SafeArray ret = new SafeArray(Variant.VariantInt, values.size()); int i = 0; for (int l : values) { ret.setInt(i++, l); } return ret; } public static SafeArray unwrapLong(List values) { if (values == null) return null; SafeArray ret = new SafeArray(Variant.VariantLongInt, values.size()); int i = 0; for (long l : values) { ret.setLong(i++, l); } return ret; } public static SafeArray unwrapBool(List values) { if (values == null) return null; SafeArray result = new SafeArray(Variant.VariantBoolean, values.size()); int i = 0; for (boolean l : values) { result.setBoolean(i++, l); } return result; } public static SafeArray unwrapBytes(byte[] values) { if (values == null) return null; SafeArray result = new SafeArray(Variant.VariantByte, values.length); int i = 0; for (byte l : values) { result.setByte(i++, l); } return result; } public static > SafeArray unwrapEnum(Class enumClass, List values) { if (values == null) return null; SafeArray result = new SafeArray(Variant.VariantInt, values.size()); try { java.lang.reflect.Method valueM = enumClass.getMethod("value"); int i = 0; for (T v : values) { result.setInt(i++, (Integer)valueM.invoke(v)); } return result; } catch (NoSuchMethodException e) { throw new AssertionError(e); } catch(SecurityException e) { throw new AssertionError(e); } catch (IllegalAccessException e) { throw new AssertionError(e); } catch (IllegalArgumentException e) { throw new AssertionError(e); } catch (InvocationTargetException e) { throw new AssertionError(e); } } public static SafeArray unwrapString(List values) { if (values == null) return null; SafeArray result = new SafeArray(Variant.VariantString, values.size()); int i = 0; for (String l : values) { result.setString(i++, l); } return result; } public static List wrap2(Class wrapperClass1, Class wrapperClass2, T2[] values) { try { if (values == null) return null; if (values.length == 0) return Collections.emptyList(); Constructor c = wrapperClass1.getConstructor(wrapperClass2); List ret = new ArrayList(values.length); for (T2 v : values) { ret.add(c.newInstance(v)); } return ret; } catch (NoSuchMethodException e) { throw new AssertionError(e); } catch (InstantiationException e) { throw new AssertionError(e); } catch (IllegalAccessException e) { throw new AssertionError(e); } catch (InvocationTargetException e) { throw new AssertionError(e); } } @SuppressWarnings("unchecked") public static T[] unwrap(Class wrapperClass, List values) { if (values == null) return null; return (T[])values.toArray((T[])Array.newInstance(wrapperClass, values.size())); } @SuppressWarnings("unchecked") public static T2[] unwrap2(Class wrapperClass1, Class wrapperClass2, List values) { if (values == null) return null; T2 ret[] = (T2[])Array.newInstance(wrapperClass2, values.size()); int i = 0; for (T1 obj : values) { ret[i++] = (T2)obj.getWrapped(); } return ret; } /* We have very long invoke lists sometimes */ public static Variant invoke(Dispatch d, String method, Object ... args) { return Dispatch.callN(d, method, args); } } ]]> public class VBoxException extends RuntimeException { private int resultCode; private IVirtualBoxErrorInfo errorInfo; public VBoxException(String message) { super(message); resultCode = -1; errorInfo = null; } public VBoxException(String message, Throwable cause) { super(message, cause); if (cause instanceof com.jacob.com.ComException) { resultCode = ((com.jacob.com.ComException)cause).getHResult(); // JACOB doesn't support calling GetErrorInfo, which // means there is no way of getting an IErrorInfo reference, // and that means no way of getting to IVirtualBoxErrorInfo. errorInfo = null; } else resultCode = -1; } public int getResultCode() { return resultCode; } public IVirtualBoxErrorInfo getVirtualBoxErrorInfo() { return errorInfo; } } List wrap(Class wrapperClass, ObjectRefManager objMgr, VboxPortType pt, List values) { try { if (values == null) return null; Constructor c = wrapperClass.getConstructor(String.class, ObjectRefManager.class, VboxPortType.class); List ret = new ArrayList(values.size()); for (String v : values) { ret.add(c.newInstance(v, objMgr, pt)); } return ret; } catch (NoSuchMethodException e) { throw new AssertionError(e); } catch (InstantiationException e) { throw new AssertionError(e); } catch (IllegalAccessException e) { throw new AssertionError(e); } catch (InvocationTargetException e) { throw new AssertionError(e); } } public static List wrap2(Class wrapperClass1, Class wrapperClass2, ObjectRefManager objMgr, VboxPortType pt, List values) { try { if (values == null) return null; Constructor c = wrapperClass1.getConstructor(wrapperClass2, ObjectRefManager.class, VboxPortType.class); List ret = new ArrayList(values.size()); for (T2 v : values) { ret.add(c.newInstance(v, objMgr, pt)); } return ret; } catch (NoSuchMethodException e) { throw new AssertionError(e); } catch (InstantiationException e) { throw new AssertionError(e); } catch (IllegalAccessException e) { throw new AssertionError(e); } catch (InvocationTargetException e) { throw new AssertionError(e); } } public static List unwrap(List values) { if (values == null) return null; List ret = new ArrayList(values.size()); for (T obj : values) { ret.add(obj.getWrapped()); } return ret; } @SuppressWarnings("unchecked" ) public static , T2 extends Enum > List convertEnums(Class fromClass, Class toClass, List values) { try { if (values == null) return null; List ret = new ArrayList(values.size()); for (T1 v : values) { // Ordinal based enum conversion, as JAX-WS "invents" its own // enum names and has string values with the expected content. int enumOrdinal = v.ordinal(); T2 convEnum = toClass.getEnumConstants()[enumOrdinal]; ret.add(convEnum); } return ret; } catch (ArrayIndexOutOfBoundsException e) { throw new AssertionError(e); } } /* Pretty naive Base64 encoder/decoder. */ private static final char[] valToChar = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".toCharArray(); private static final int[] charToVal = new int[256]; /* Initialize recoding alphabet. */ static { for (int i = 0; i < charToVal.length; i++) charToVal[i] = -1; for (int i = 0; i < valToChar.length; i++) charToVal[valToChar[i]] = i; charToVal['='] = 0; } public static String encodeBase64(byte[] data) { if (data == null) return null; if (data.length == 0) return ""; int fullTriplets = data.length / 3; int resultLen = ((data.length - 1) / 3 + 1) * 4; char[] result = new char[resultLen]; int dataIndex = 0, stringIndex = 0; for (int i = 0; i < fullTriplets; i++) { int ch1 = data[dataIndex++] & 0xff; result[stringIndex++] = valToChar[ch1 >> 2]; int ch2 = data[dataIndex++] & 0xff; result[stringIndex++] = valToChar[((ch1 << 4) & 0x3f) | (ch2 >> 4)]; int ch3 = data[dataIndex++] & 0xff; result[stringIndex++] = valToChar[((ch2 << 2) & 0x3f) | (ch3 >> 6)]; result[stringIndex++] = valToChar[ch3 & 0x3f]; } switch (data.length - dataIndex) { case 0: // do nothing break; case 1: { int ch1 = data[dataIndex++] & 0xff; result[stringIndex++] = valToChar[ch1 >> 2]; result[stringIndex++] = valToChar[(ch1 << 4) & 0x3f]; result[stringIndex++] = '='; result[stringIndex++] = '='; break; } case 2: { int ch1 = data[dataIndex++] & 0xff; result[stringIndex++] = valToChar[ch1 >> 2]; int ch2 = data[dataIndex++] & 0xff; result[stringIndex++] = valToChar[((ch1 << 4) & 0x3f) | (ch2 >> 4)]; result[stringIndex++] = valToChar[(ch2 << 2) & 0x3f]; result[stringIndex++] = '='; break; } default: throw new VBoxException("bug!"); } return new String(result); } private static int skipInvalid(String str, int stringIndex) { while (charToVal[str.charAt(stringIndex)] < 0) stringIndex++; return stringIndex; } public static byte[] decodeBase64(String str) { if (str == null) return null; int stringLength = str.length(); if (stringLength == 0) return new byte[0]; int validChars = 0, padChars = 0; for (int i = 0; i < str.length(); i++) { char ch = str.charAt(i); if (charToVal[ch] >= 0) validChars++; if (ch == '=') padChars++; } if ((validChars * 3 % 4) != 0) throw new VBoxException("invalid base64 encoded string " + str); int resultLength = validChars * 3 / 4 - padChars; byte[] result = new byte[resultLength]; int dataIndex = 0, stringIndex = 0; int quadraplets = validChars / 4; for (int i = 0; i < quadraplets; i++) { stringIndex = skipInvalid(str, stringIndex); int ch1 = str.charAt(stringIndex++); stringIndex = skipInvalid(str, stringIndex); int ch2 = str.charAt(stringIndex++); stringIndex = skipInvalid(str, stringIndex); int ch3 = str.charAt(stringIndex++); stringIndex = skipInvalid(str, stringIndex); int ch4 = str.charAt(stringIndex++); result[dataIndex++] = (byte)(((charToVal[ch1] << 2) | charToVal[ch2] >> 4) & 0xff); /* we check this to ensure that we don't override data with '=' padding. */ if (dataIndex < result.length) result[dataIndex++] = (byte)(((charToVal[ch2] << 4) | charToVal[ch3] >> 2) & 0xff); if (dataIndex < result.length) result[dataIndex++] = (byte)(((charToVal[ch3] << 6) | charToVal[ch4]) & 0xff); } return result; } } ]]> public class VBoxException extends RuntimeException { private int resultCode; private IVirtualBoxErrorInfo errorInfo; public VBoxException(String message) { super(message); resultCode = -1; errorInfo = null; } public VBoxException(String message, Throwable cause) { super(message, cause); resultCode = -1; errorInfo = null; } public VBoxException(String message, Throwable cause, ObjectRefManager objMgr, VboxPortType port) { super(message, cause); if (cause instanceof RuntimeFaultMsg) { RuntimeFaultMsg m = (RuntimeFaultMsg)cause; RuntimeFault f = m.getFaultInfo(); resultCode = f.getResultCode(); String retVal = f.getReturnval(); errorInfo = (retVal.length() > 0) ? new IVirtualBoxErrorInfo(retVal, objMgr, port) : null; } else resultCode = -1; } public int getResultCode() { return resultCode; } public IVirtualBoxErrorInfo getVirtualBoxErrorInfo() { return errorInfo; } } import java.net.URL; import java.math.BigInteger; import java.util.Iterator; import java.util.List; import java.util.LinkedList; import java.util.Map; import java.util.HashMap; import java.util.ArrayList; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.ConcurrentMap; import java.util.concurrent.locks.ReentrantReadWriteLock; import java.lang.Integer; import java.lang.ref.WeakReference; import java.lang.ref.ReferenceQueue; import javax.xml.namespace.QName; import javax.xml.ws.BindingProvider; import javax.xml.ws.Holder; import javax.xml.ws.WebServiceException; import java.io.IOException; import java.net.UnknownHostException; import java.net.Socket; import java.net.InetAddress; import javax.net.SocketFactory; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLSocketFactory; import javax.net.ssl.SSLSocket; class PortPool { private final static String wsdlFile = known; private boolean initStarted; private VboxService svc; PortPool(boolean usePreinit) { known = new HashMap(); if (usePreinit) { new Thread(new Runnable() { public void run() { // need to sync on something else but 'this' synchronized (known) { initStarted = true; known.notify(); } preinit(); } }).start(); synchronized (known) { while (!initStarted) { try { known.wait(); } catch (InterruptedException e) { break; } } } } } private synchronized void preinit() { VboxPortType port = getPort(); releasePort(port); } synchronized VboxPortType getPort() { VboxPortType port = null; int ttl = 0; for (VboxPortType cur: known.keySet()) { int value = known.get(cur); if ((value & 0x10000) == 0) { port = cur; ttl = value & 0xffff; break; } } if (port == null) { if (svc == null) { URL wsdl = PortPool.class.getClassLoader().getResource(wsdlFile); if (wsdl == null) throw new LinkageError(wsdlFile + " not found, but it should have been in the jar"); svc = new VboxService(wsdl, new QName("http://www.virtualbox.org/Service", "vboxService")); } port = svc.getVboxServicePort(); // reuse this object 0x10 times ttl = 0x10; } // mark as used known.put(port, new Integer(0x10000 | ttl)); return port; } synchronized void releasePort(VboxPortType port) { Integer val = known.get(port); if (val == null || val == 0) { // know you not return; } int v = val; int ttl = v & 0xffff; // decrement TTL, and throw away port if used too much times if (--ttl <= 0) { known.remove(port); } else { v = ttl; // set new TTL and clear busy bit known.put(port, v); } } } /** * This class manages the object references between us and the webservice server. * It makes sure that the object on the server side is destroyed when all */ class ObjectRefManager { private final static ReferenceQueue refQ = new ReferenceQueue(); private final ConcurrentMap map = new ConcurrentHashMap(); private final ReentrantReadWriteLock lock = new ReentrantReadWriteLock(); private final ObjRefMgrCleanupThread objRefMgrCleanup; public ObjectRefManager() { this.objRefMgrCleanup = new ObjRefMgrCleanupThread(this, 100); this.objRefMgrCleanup.start(); } /** * Prevents the object reference manager cleanup thread from releasing any * server side objects to avoid a fundamental race in the multi threaded * java environment where it is possible that a wrapper got the object ID * from the server but couldn't create the local stub protecting the object * before the cleanup thread released it. */ public void preventObjRelease() { lock.readLock().lock(); } /** * Allows releasing server side objects from the cleanup thread again. */ public void allowObjRelease() { lock.readLock().unlock(); } /** * Marks the start of a run to release server side objects which don't hold * a reference locally anymore. */ public void startObjRelease() { lock.writeLock().lock(); } /** * Marks the end of a cleanup run. */ public void endObjRelease() { lock.writeLock().unlock(); } /** * Registers a new stub object for automatic reference managing. */ public void registerObj(IUnknown obj) { assert lock.getReadLockCount() > 0; ManagedObjRef ref = new ManagedObjRef(obj); ManagedObj mgrobj = map.get(obj.getWrapped()); if (mgrobj != null) { mgrobj.addObject(ref); } else { /* Create new. */ mgrobj = new ManagedObj(obj.getWrapped(), obj.getRemoteWSPort()); mgrobj.addObject(ref); map.put(obj.getWrapped(), mgrobj); } } /** * Removes a garbage collected object reference from our reference manager. * * Returns the server side object wrapper if there is no stub referencing it * anymore otherwise null is returned. */ public ManagedObj unregisterObj(ManagedObjRef objRef) { ManagedObj obj = this.map.get(objRef.objId); assert obj != null; obj.removeObject(objRef); if (!obj.isReferenced()) return obj; return null; } public void releaseRemoteObj(ManagedObj obj) { assert lock.isWriteLockedByCurrentThread(); if (!obj.isReferenced()) { try { obj.port.iManagedObjectRefRelease(obj.objId); } catch (InvalidObjectFaultMsg e) { throw new WebServiceException(e); } catch (RuntimeFaultMsg e) { throw new WebServiceException(e); } finally { this.map.remove(obj.objId); } } } /** * An object which is living on the server side. This can be referenced * by multiple stub objects here. */ static class ManagedObj { private final String objId; private final VboxPortType port; private final ConcurrentLinkedQueue refQ; ManagedObj(String objId, VboxPortType port) { this.objId = objId; this.port = port; this.refQ = new ConcurrentLinkedQueue(); } public void addObject(ManagedObjRef obj) { this.refQ.add(obj); } public void removeObject(ManagedObjRef obj) { this.refQ.remove(obj); } public boolean isReferenced() { return !this.refQ.isEmpty(); } } /** * A private class extending WeakReference to get notified about garbage * collected stub objects. */ static class ManagedObjRef extends WeakReference { final String objId; ManagedObjRef(IUnknown obj) { super(obj, refQ); this.objId = obj.getWrapped(); } } /** * A private class implementing a thread getting notified * about garbage collected objects so it can release the object on the * server side if it is not used anymore. */ static class ObjRefMgrCleanupThread extends Thread { ObjectRefManager objRefMgr; int cStubsReleased; int cStubsReleaseThreshold; HashMap mapToRelease = new HashMap(); ObjRefMgrCleanupThread(ObjectRefManager objRefMgr) { init(objRefMgr, 500); } ObjRefMgrCleanupThread(ObjectRefManager objRefMgr, int cStubsReleaseThreshold) { init(objRefMgr, cStubsReleaseThreshold); } private void init(ObjectRefManager objRefMgr, int cStubsReleaseThreshold) { this.objRefMgr = objRefMgr; this.cStubsReleased = 0; this.cStubsReleaseThreshold = cStubsReleaseThreshold; setName("ObjectRefManager-VBoxWSObjRefGcThrd"); /* * setDaemon() makes sure the jvm exits and is not blocked * if the thread is still running so we don't have to care about * tearing it down. */ setDaemon(true); } public void run() { while (true) { while (cStubsReleased < cStubsReleaseThreshold) { try { /* Accumulate a few objects before we start. */ while (cStubsReleased < cStubsReleaseThreshold) { ManagedObjRef ref = (ManagedObjRef)refQ.remove(); ManagedObj obj = this.objRefMgr.unregisterObj(ref); /* * If the server side object is not referenced anymore * promote to map for releasing later. */ if (obj != null && !mapToRelease.containsKey(ref.objId)) mapToRelease.put(ref.objId, obj); cStubsReleased++; } } catch (InterruptedException e) { /* ignore */ } catch (javax.xml.ws.WebServiceException e) { /* ignore */ } } /* * After we released enough stubs we go over all non referenced * server side objects and release them if they were not * referenced again in between. */ cStubsReleased = 0; if (!mapToRelease.isEmpty()) { this.objRefMgr.startObjRelease(); try { Iterator it = mapToRelease.values().iterator(); while (it.hasNext()) { ManagedObj obj = it.next(); this.objRefMgr.releaseRemoteObj(obj); } mapToRelease.clear(); } catch (javax.xml.ws.WebServiceException e) { /* ignore */ } finally { this.objRefMgr.endObjRelease(); } } } } } } class VBoxTLSSocketFactory extends SSLSocketFactory { private final SSLSocketFactory sf; private void setupSocket(SSLSocket s) { String[] oldproto = s.getEnabledProtocols(); List protolist = new ArrayList(); for (int i = 0; i < oldproto.length; i++) if (oldproto[i].toUpperCase().startsWith("TLS")) protolist.add(oldproto[i]); String[] newproto = protolist.toArray(new String[protolist.size()]); s.setEnabledProtocols(newproto); } public VBoxTLSSocketFactory() { SSLSocketFactory tmp = null; try { SSLContext sc = SSLContext.getInstance("TLS"); sc.init(null, null, null); tmp = sc.getSocketFactory(); } catch (Exception e) { e.printStackTrace(); } sf = tmp; } public static SocketFactory getDefault() { return new VBoxTLSSocketFactory(); } public Socket createSocket(Socket socket, String host, int port, boolean autoClose) throws IOException, UnknownHostException { SSLSocket s = (SSLSocket)sf.createSocket(socket, host, port, autoClose); setupSocket(s); return s; } public Socket createSocket() throws IOException { SSLSocket s = (SSLSocket)sf.createSocket(); setupSocket(s); return s; } public Socket createSocket(InetAddress host, int port) throws IOException { SSLSocket s = (SSLSocket)sf.createSocket(host, port); setupSocket(s); return s; } public Socket createSocket(InetAddress address, int port, InetAddress localAddress, int localPort) throws IOException { SSLSocket s = (SSLSocket)sf.createSocket(address, port, localAddress, localPort); setupSocket(s); return s; } public Socket createSocket(String host, int port) throws IOException, UnknownHostException { SSLSocket s = (SSLSocket)sf.createSocket(host, port); setupSocket(s); return s; } public Socket createSocket(String host, int port, InetAddress localHost, int localPort) throws IOException, UnknownHostException { SSLSocket s = (SSLSocket)sf.createSocket(host, port, localHost, localPort); setupSocket(s); return s; } public String[] getDefaultCipherSuites() { return sf.getDefaultCipherSuites(); } public String[] getSupportedCipherSuites() { return sf.getSupportedCipherSuites(); } } public class VirtualBoxManager { private static PortPool pool = new PortPool(true); private static final ObjectRefManager objMgr = new ObjectRefManager(); protected VboxPortType port; private IVirtualBox vbox; private VirtualBoxManager() { } public static void initPerThread() { } public static void deinitPerThread() { } public void connect(String url, String username, String passwd) { this.port = pool.getPort(); try { ((BindingProvider)port).getRequestContext(). put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY, url); // Unfortunately there is no official way to make JAX-WS use // TLS only, which means that a rather tedious approach is // unavoidable (implementing a TLS only SSLSocketFactory, // because the default one associated with a TLS SSLContext // happily uses SSLv2/3 handshakes, which make TLS servers // drop the connection), and additionally a not standardized, // shotgun approach is needed to make the relevant JAX-WS // implementations use this factory. VBoxTLSSocketFactory sf = new VBoxTLSSocketFactory(); ((BindingProvider)port).getRequestContext(). put("com.sun.xml.internal.ws.transport.https.client.SSLSocketFactory", sf); ((BindingProvider)port).getRequestContext(). put("com.sun.xml.ws.transport.https.client.SSLSocketFactory", sf); String handle = port.iWebsessionManagerLogon(username, passwd); this.objMgr.preventObjRelease(); try { this.vbox = new IVirtualBox(handle, this.objMgr, port); } finally { this.objMgr.allowObjRelease(); } } catch (Throwable t) { if (this.port != null && pool != null) { pool.releasePort(this.port); this.port = null; } // we have to throw smth derived from RuntimeException throw new VBoxException(t.getMessage(), t, this.objMgr, this.port); } } public void connect(String url, String username, String passwd, Map requestContext, Map responseContext) { this.port = pool.getPort(); try { ((BindingProvider)port).getRequestContext(); if (requestContext != null) ((BindingProvider)port).getRequestContext().putAll(requestContext); if (responseContext != null) ((BindingProvider)port).getResponseContext().putAll(responseContext); ((BindingProvider)port).getRequestContext(). put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY, url); String handle = port.iWebsessionManagerLogon(username, passwd); this.objMgr.preventObjRelease(); try { this.vbox = new IVirtualBox(handle, this.objMgr, port); } finally { this.objMgr.allowObjRelease(); } } catch (Throwable t) { if (this.port != null && pool != null) { pool.releasePort(this.port); this.port = null; } // we have to throw smth derived from RuntimeException throw new VBoxException(t.getMessage(), t, this.objMgr, this.port); } } public void disconnect() { if (this.port == null) return; try { if (this.vbox != null && port != null) port.iWebsessionManagerLogoff(this.vbox.getWrapped()); } catch (InvalidObjectFaultMsg e) { throw new VBoxException(e.getMessage(), e, this.objMgr, this.port); } catch (RuntimeFaultMsg e) { throw new VBoxException(e.getMessage(), e, this.objMgr, this.port); } finally { if (this.port != null) { pool.releasePort(this.port); this.port = null; } } } public String getClientAPIVersion() { return "]]>