VirtualBox

source: vbox/trunk/src/VBox/Main/VirtualBoxImplExtra.cpp@ 17467

Last change on this file since 17467 was 16560, checked in by vboxsync, 16 years ago

Main: do not include include/VBox/settings.h from other header files but only from implementations that need it (save compile time)

  • Property svn:eol-style set to native
  • Property svn:keywords set to Date Revision Author Id
File size: 9.0 KB
Line 
1/** @file
2 *
3 * VirtualBox COM class implementation extra definitions
4 *
5 * This file pulls in generated entities that may be rather big but rarely
6 * changed. Separating them from VirtualBoxImpl.cpp should speed up
7 * compilation a bit.
8 */
9
10/*
11 * Copyright (C) 2006-2007 Sun Microsystems, Inc.
12 *
13 * This file is part of VirtualBox Open Source Edition (OSE), as
14 * available from http://www.virtualbox.org. This file is free software;
15 * you can redistribute it and/or modify it under the terms of the GNU
16 * General Public License (GPL) as published by the Free Software
17 * Foundation, in version 2 as it comes in the "COPYING" file of the
18 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
19 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
20 *
21 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
22 * Clara, CA 95054 USA or visit http://www.sun.com if you need
23 * additional information or have any questions.
24 */
25
26#include <VBox/settings.h>
27
28#include "VirtualBoxImpl.h"
29#include "VirtualBoxImplExtra.h"
30
31#include "VirtualBoxXMLUtil.h"
32
33/* embedded XML Schema documents for validating XML settings files */
34#include "xml_VirtualBox_settings_xsd.h"
35#include "xml_VirtualBox_settings_common_xsd.h"
36
37/* embedded settings converter template for updating settings files */
38#include "xml_SettingsConverter_xsl.h"
39
40/* embedded VirtualBox element definition that contains a proper 'version'
41 * attribute constraint */
42static const unsigned char g_ab_xml_VirtualBox_settings_root_xsd[] =
43"<xsd:schema"
44" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\""
45" xmlns=\"http://www.innotek.de/VirtualBox-settings\""
46" xmlns:vb=\"http://www.innotek.de/VirtualBox-settings\""
47" targetNamespace=\"http://www.innotek.de/VirtualBox-settings\""
48" elementFormDefault=\"qualified\""
49">"
50"<xsd:element name=\"VirtualBox\">"
51" <xsd:complexType>"
52" <xsd:complexContent>"
53" <xsd:extension base=\"TVirtualBox\">"
54" <xsd:attribute name=\"version\" type=\"xsd:token\" fixed=\"" VBOX_XML_VERSION_FULL "\" use=\"required\"/>"
55" </xsd:extension>"
56" </xsd:complexContent>"
57" </xsd:complexType>"
58"</xsd:element>"
59"</xsd:schema>";
60
61static const unsigned g_cb_xml_VirtualBox_settings_root_xsd =
62 sizeof (g_ab_xml_VirtualBox_settings_root_xsd);
63
64/**
65 * Resolves external entities while parting and validating XML settings files.
66 *
67 * @param aURI URI of the external entity.
68 * @param aID ID of the external entity (may be NULL).
69 *
70 * @return Input stream created using @c new or NULL to indicate
71 * a wrong URI/ID pair.
72 */
73xml::Input *
74SettingsTreeHelper::resolveEntity (const char *aURI, const char *aID)
75{
76 if (strcmp (aURI, VBOX_XML_SCHEMA_COMMON) == 0)
77 {
78 return new xml::
79 MemoryBuf ((const char *) g_ab_xml_VirtualBox_settings_common_xsd,
80 g_cb_xml_VirtualBox_settings_common_xsd, aURI);
81 }
82
83 if (strcmp (aURI, VBOX_XML_SCHEMA_ROOT) == 0)
84 {
85 return new xml::
86 MemoryBuf ((const char *) g_ab_xml_VirtualBox_settings_root_xsd,
87 g_cb_xml_VirtualBox_settings_root_xsd, aURI);
88 }
89
90 if (strcmp (aURI, VBOX_XML_SCHEMA) == 0)
91 {
92 return new xml::
93 MemoryBuf ((const char *) g_ab_xml_VirtualBox_settings_xsd,
94 g_cb_xml_VirtualBox_settings_xsd, aURI);
95 }
96
97 if (strcmp (aURI, VBOX_XML_SETTINGS_CONVERTER) == 0)
98 {
99 return new xml::
100 MemoryBuf ((const char *) g_ab_xml_SettingsConverter_xsl,
101 g_cb_xml_SettingsConverter_xsl, aURI);
102 }
103
104 AssertMsgFailed (("Unexpected entity: '%s' - knows: '%s' and '%s'\n", aURI,
105 VBOX_XML_SCHEMA_COMMON, VBOX_XML_SCHEMA));
106 return NULL;
107}
108
109/**
110 * Returns @true if the given tree needs to be converted using the XSLT
111 * template identified by #templateUri(), or @false if no conversion is
112 * required.
113 *
114 * The implementation normally checks for the "version" value of the
115 * root key to determine if the conversion is necessary. When the
116 * @a aOldVersion argument is not NULL, the implementation must return a
117 * non-NULL non-empty string representing the old version (before
118 * conversion) in it this string is used by XmlTreeBackend::oldVersion()
119 * and must be non-NULL to indicate that the conversion has been
120 * performed on the tree. The returned string must be allocated using
121 * RTStrDup() or such.
122 *
123 * This method is called again after the successful transformation to
124 * let the implementation retry the version check and request another
125 * transformation if necessary. This may be used to perform multi-step
126 * conversion like this: 1.1 => 1.2, 1.2 => 1.3 (instead of 1.1 => 1.3)
127 * which saves from the need to update all previous conversion
128 * templates to make each of them convert directly to the recent
129 * version.
130 *
131 * @note Multi-step transformations are performed in a loop that exits
132 * only when this method returns @false. It's up to the
133 * implementation to detect cycling (repeated requests to convert
134 * from the same version) wrong version order, etc. and throw an
135 * EConversionCycle exception to break the loop without returning
136 * @false (which means the transformation succeeded).
137 *
138 * @param aRoot Root settings key.
139 * @param aOldVersionString Where to store old version string
140 * pointer. May be NULL. Allocated memory is
141 * freed by the caller using RTStrFree().
142 */
143bool SettingsTreeHelper::
144needsConversion (const settings::Key &aRoot, char **aOldVersion) const
145{
146 if (strcmp (aRoot.name(), "VirtualBox") == 0)
147 {
148 const char *version = aRoot.stringValue ("version");
149 const char *dash = strchr (version, '-');
150 if (dash != NULL && strcmp (dash + 1, VBOX_XML_PLATFORM) == 0)
151 {
152 if (strcmp (version, VBOX_XML_VERSION_FULL) != 0)
153 {
154 /* version mismatch */
155 if (aOldVersion != NULL)
156 *aOldVersion = RTStrDup (version);
157
158 return true;
159 }
160 }
161 }
162
163 /* either the tree is invalid, or it's the other platform, or it's the same
164 * version */
165 return false;
166}
167
168/**
169 * Returns the URI of the XSLT template to perform the conversion.
170 * This template will be applied to the tree if #needsConversion()
171 * returns @c true for this tree.
172 */
173const char* SettingsTreeHelper::templateUri() const
174{
175 return VBOX_XML_SETTINGS_CONVERTER;
176}
177
178#if defined VBOX_MAIN_SETTINGS_ADDONS
179
180// Settings API additions
181////////////////////////////////////////////////////////////////////////////////
182
183namespace settings
184{
185
186template<> stdx::char_auto_ptr
187ToString <com::Bstr> (const com::Bstr &aValue, unsigned int aExtra)
188{
189 stdx::char_auto_ptr result;
190
191 if (aValue.raw() == NULL)
192 throw ENoValue();
193
194 /* The only way to cause RTUtf16ToUtf8Ex return a number of bytes needed
195 * w/o allocating the result buffer itself is to provide that both cch
196 * and *ppsz are not NULL. */
197 char dummy [1];
198 char *dummy2 = dummy;
199 size_t strLen = 1;
200
201 int vrc = RTUtf16ToUtf8Ex (aValue.raw(), RTSTR_MAX,
202 &dummy2, strLen, &strLen);
203 if (RT_SUCCESS (vrc))
204 {
205 /* the string only contains '\0' :) */
206 result.reset (new char [1]);
207 result.get() [0] = '\0';
208 return result;
209 }
210
211 if (vrc == VERR_BUFFER_OVERFLOW)
212 {
213 result.reset (new char [strLen + 1]);
214 char *buf = result.get();
215 vrc = RTUtf16ToUtf8Ex (aValue.raw(), RTSTR_MAX, &buf, strLen + 1, NULL);
216 }
217
218 if (RT_FAILURE (vrc))
219 throw xml::LogicError (RT_SRC_POS);
220
221 return result;
222}
223
224template<> com::Guid FromString <com::Guid> (const char *aValue)
225{
226 if (aValue == NULL)
227 throw ENoValue();
228
229 /* For settings, the format is always {XXX...XXX} */
230 char buf [RTUUID_STR_LENGTH];
231 if (aValue == NULL || *aValue != '{' ||
232 strlen (aValue) != RTUUID_STR_LENGTH + 1 ||
233 aValue [RTUUID_STR_LENGTH] != '}')
234 throw ENoConversion(com::Utf8StrFmt("'%s' is not Guid", aValue));
235
236 /* strip { and } */
237 memcpy (buf, aValue + 1, RTUUID_STR_LENGTH - 1);
238 buf [RTUUID_STR_LENGTH - 1] = '\0';
239 /* we don't use Guid (const char *) because we want to throw
240 * ENoConversion on format error */
241 RTUUID uuid;
242 int vrc = RTUuidFromStr (&uuid, buf);
243 if (RT_FAILURE (vrc))
244 throw ENoConversion(com::Utf8StrFmt("'%s' is not Guid (%Rrc)", aValue, vrc));
245
246 return com::Guid (uuid);
247}
248
249template<> stdx::char_auto_ptr
250ToString <com::Guid> (const com::Guid &aValue, unsigned int aExtra)
251{
252 /* For settings, the format is always {XXX...XXX} */
253 stdx::char_auto_ptr result (new char [RTUUID_STR_LENGTH + 2]);
254
255 int vrc = RTUuidToStr (aValue.raw(), result.get() + 1, RTUUID_STR_LENGTH);
256 if (RT_FAILURE (vrc))
257 throw xml::LogicError (RT_SRC_POS);
258
259 result.get() [0] = '{';
260 result.get() [RTUUID_STR_LENGTH] = '}';
261 result.get() [RTUUID_STR_LENGTH + 1] = '\0';
262
263 return result;
264}
265
266#endif // VBOX_MAIN_SETTINGS_ADDONS
267
268} /* namespace settings */
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette