1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
4 *
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 */
19
20 #include <sal/config.h>
21 #include <sal/log.hxx>
22
23 #include <cassert>
24 #include <memory>
25
26 #include <elements.hxx>
27 #include <osl/mutex.hxx>
28 #include <osl/file.hxx>
29 #include <fwkutil.hxx>
30 #include <fwkbase.hxx>
31 #include "framework.hxx"
32 #include <libxmlutil.hxx>
33 #include <algorithm>
34 #include <libxml/parser.h>
35 #include <libxml/xpath.h>
36 #include <libxml/xpathInternals.h>
37 #include <boost/optional.hpp>
38 #include <string.h>
39
40 // For backwards compatibility, the nFeatures and nRequirements flag words are
41 // read/written as potentially signed hexadecimal numbers (though that has no
42 // practical relevance given that each has only one flag with value 0x01
43 // defined).
44
45 using namespace osl;
46 namespace jfw
47 {
48
getElement(OString const & docPath,xmlChar const * pathExpression)49 static OString getElement(OString const & docPath,
50 xmlChar const * pathExpression)
51 {
52 //Prepare the xml document and context
53 OSL_ASSERT(!docPath.isEmpty());
54 jfw::CXmlDocPtr doc(xmlParseFile(docPath.getStr()));
55 if (doc == nullptr)
56 throw FrameworkException(
57 JFW_E_ERROR,
58 "[Java framework] Error in function getElement (elements.cxx)");
59
60 jfw::CXPathContextPtr context(xmlXPathNewContext(doc));
61 if (xmlXPathRegisterNs(context, reinterpret_cast<xmlChar const *>("jf"),
62 reinterpret_cast<xmlChar const *>(NS_JAVA_FRAMEWORK)) == -1)
63 throw FrameworkException(
64 JFW_E_ERROR,
65 "[Java framework] Error in function getElement (elements.cxx)");
66
67 CXPathObjectPtr pathObj = xmlXPathEvalExpression(pathExpression, context);
68 OString sValue;
69 if (xmlXPathNodeSetIsEmpty(pathObj->nodesetval))
70 {
71 throw FrameworkException(
72 JFW_E_ERROR,
73 "[Java framework] Error in function getElement (elements.cxx)");
74 }
75 sValue = reinterpret_cast<sal_Char*>(pathObj->nodesetval->nodeTab[0]->content);
76 return sValue;
77 }
78
getElementUpdated()79 OString getElementUpdated()
80 {
81 return getElement(jfw::getVendorSettingsPath(),
82 reinterpret_cast<xmlChar const *>("/jf:javaSelection/jf:updated/text()"));
83 }
84
createSettingsStructure(xmlDoc * document,bool * bNeedsSave)85 void createSettingsStructure(xmlDoc * document, bool * bNeedsSave)
86 {
87 OString sExcMsg("[Java framework] Error in function createSettingsStructure "
88 "(elements.cxx).");
89 xmlNode * root = xmlDocGetRootElement(document);
90 if (root == nullptr)
91 throw FrameworkException(JFW_E_ERROR, sExcMsg);
92 bool bFound = false;
93 xmlNode * cur = root->children;
94 while (cur != nullptr)
95 {
96 if (xmlStrcmp(cur->name, reinterpret_cast<xmlChar const *>("enabled")) == 0)
97 {
98 bFound = true;
99 break;
100 }
101 cur = cur->next;
102 }
103 if (bFound)
104 {
105 *bNeedsSave = false;
106 return;
107 }
108 //We will modify this document
109 *bNeedsSave = true;
110 // Now we create the child elements ------------------
111 //Get xsi:nil namespace
112 xmlNs* nsXsi = xmlSearchNsByHref(
113 document, root, reinterpret_cast<xmlChar const *>(NS_SCHEMA_INSTANCE));
114
115 //<enabled xsi:nil="true"
116 xmlNode * nodeEn = xmlNewTextChild(
117 root, nullptr, reinterpret_cast<xmlChar const *>("enabled"), reinterpret_cast<xmlChar const *>(""));
118 if (nodeEn == nullptr)
119 throw FrameworkException(JFW_E_ERROR, sExcMsg);
120 xmlSetNsProp(nodeEn, nsXsi, reinterpret_cast<xmlChar const *>("nil"), reinterpret_cast<xmlChar const *>("true"));
121 //add a new line
122 xmlNode * nodeCrLf = xmlNewText(reinterpret_cast<xmlChar const *>("\n"));
123 xmlAddChild(root, nodeCrLf);
124
125 //<userClassPath xsi:nil="true">
126 xmlNode * nodeUs = xmlNewTextChild(
127 root, nullptr, reinterpret_cast<xmlChar const *>("userClassPath"), reinterpret_cast<xmlChar const *>(""));
128 if (nodeUs == nullptr)
129 throw FrameworkException(JFW_E_ERROR, sExcMsg);
130 xmlSetNsProp(nodeUs, nsXsi, reinterpret_cast<xmlChar const *>("nil"), reinterpret_cast<xmlChar const *>("true"));
131 //add a new line
132 nodeCrLf = xmlNewText(reinterpret_cast<xmlChar const *>("\n"));
133 xmlAddChild(root, nodeCrLf);
134
135 //<vmParameters xsi:nil="true">
136 xmlNode * nodeVm = xmlNewTextChild(
137 root, nullptr, reinterpret_cast<xmlChar const *>("vmParameters"), reinterpret_cast<xmlChar const *>(""));
138 if (nodeVm == nullptr)
139 throw FrameworkException(JFW_E_ERROR, sExcMsg);
140 xmlSetNsProp(nodeVm, nsXsi, reinterpret_cast<xmlChar const *>("nil"), reinterpret_cast<xmlChar const *>("true"));
141 //add a new line
142 nodeCrLf = xmlNewText(reinterpret_cast<xmlChar const *>("\n"));
143 xmlAddChild(root, nodeCrLf);
144
145 //<jreLocations xsi:nil="true">
146 xmlNode * nodeJre = xmlNewTextChild(
147 root, nullptr, reinterpret_cast<xmlChar const *>("jreLocations"), reinterpret_cast<xmlChar const *>(""));
148 if (nodeJre == nullptr)
149 throw FrameworkException(JFW_E_ERROR, sExcMsg);
150 xmlSetNsProp(nodeJre, nsXsi, reinterpret_cast<xmlChar const *>("nil"), reinterpret_cast<xmlChar const *>("true"));
151 //add a new line
152 nodeCrLf = xmlNewText(reinterpret_cast<xmlChar const *>("\n"));
153 xmlAddChild(root, nodeCrLf);
154
155 //<javaInfo xsi:nil="true">
156 xmlNode * nodeJava = xmlNewTextChild(
157 root, nullptr, reinterpret_cast<xmlChar const *>("javaInfo"), reinterpret_cast<xmlChar const *>(""));
158 if (nodeJava == nullptr)
159 throw FrameworkException(JFW_E_ERROR, sExcMsg);
160 xmlSetNsProp(nodeJava, nsXsi, reinterpret_cast<xmlChar const *>("nil"), reinterpret_cast<xmlChar const *>("true"));
161 //add a new line
162 nodeCrLf = xmlNewText(reinterpret_cast<xmlChar const *>("\n"));
163 xmlAddChild(root, nodeCrLf);
164 }
165
NodeJava(Layer layer)166 NodeJava::NodeJava(Layer layer):
167 m_layer(layer)
168 {
169 //This class reads and write to files which should only be done in
170 //application mode
171 if (getMode() == JFW_MODE_DIRECT)
172 throw FrameworkException(
173 JFW_E_DIRECT_MODE,
174 "[Java framework] Trying to access settings files in direct mode.");
175 }
176
177
load()178 void NodeJava::load()
179 {
180 const OString sExcMsg("[Java framework] Error in function NodeJava::load"
181 "(elements.cxx).");
182 if (SHARED == m_layer)
183 {
184 //we do not support yet to write into the shared installation
185
186 //check if shared settings exist at all.
187 OUString sURL(BootParams::getSharedData());
188 jfw::FileStatus s = sURL.isEmpty()
189 ? FILE_DOES_NOT_EXIST : checkFileURL(sURL);
190 if (s == FILE_INVALID)
191 throw FrameworkException(
192 JFW_E_ERROR,
193 "[Java framework] Invalid file for shared Java settings.");
194 else if (s == FILE_DOES_NOT_EXIST)
195 //Writing shared data is not supported yet.
196 return;
197 }
198 else if (USER == m_layer)
199 {
200 if (!prepareSettingsDocument())
201 {
202 SAL_INFO("jfw.level1", "no path to load user settings document from");
203 return;
204 }
205 }
206 else
207 {
208 OSL_FAIL("[Java framework] Unknown enum used.");
209 }
210
211
212 //Read the user elements
213 OString sSettingsPath = getSettingsPath();
214 //There must not be a share settings file
215 CXmlDocPtr docUser(xmlParseFile(sSettingsPath.getStr()));
216 if (docUser == nullptr)
217 throw FrameworkException(JFW_E_ERROR, sExcMsg);
218
219 xmlNode * cur = xmlDocGetRootElement(docUser);
220 if (cur == nullptr || cur->children == nullptr)
221 throw FrameworkException(JFW_E_ERROR, sExcMsg);
222
223 CXmlCharPtr sNil;
224 cur = cur->children;
225 while (cur != nullptr)
226 {
227 if (xmlStrcmp(cur->name, reinterpret_cast<xmlChar const *>("enabled")) == 0)
228 {
229 //only overwrite share settings if xsi:nil="false"
230 sNil = xmlGetNsProp(
231 cur, reinterpret_cast<xmlChar const *>("nil"), reinterpret_cast<xmlChar const *>(NS_SCHEMA_INSTANCE));
232 if (sNil == nullptr)
233 throw FrameworkException(JFW_E_ERROR, sExcMsg);
234 if (xmlStrcmp(sNil, reinterpret_cast<xmlChar const *>("false")) == 0)
235 {
236 CXmlCharPtr sEnabled( xmlNodeListGetString(
237 docUser, cur->children, 1));
238 if (xmlStrcmp(sEnabled, reinterpret_cast<xmlChar const *>("true")) == 0)
239 m_enabled = boost::optional<sal_Bool>(true);
240 else if (xmlStrcmp(sEnabled, reinterpret_cast<xmlChar const *>("false")) == 0)
241 m_enabled = boost::optional<sal_Bool>(false);
242 }
243 }
244 else if (xmlStrcmp(cur->name, reinterpret_cast<xmlChar const *>("userClassPath")) == 0)
245 {
246 sNil = xmlGetNsProp(
247 cur, reinterpret_cast<xmlChar const *>("nil"), reinterpret_cast<xmlChar const *>(NS_SCHEMA_INSTANCE));
248 if (sNil == nullptr)
249 throw FrameworkException(JFW_E_ERROR, sExcMsg);
250 if (xmlStrcmp(sNil, reinterpret_cast<xmlChar const *>("false")) == 0)
251 {
252 CXmlCharPtr sUser(xmlNodeListGetString(
253 docUser, cur->children, 1));
254 m_userClassPath = boost::optional<OUString>(OUString(sUser));
255 }
256 }
257 else if (xmlStrcmp(cur->name, reinterpret_cast<xmlChar const *>("javaInfo")) == 0)
258 {
259 sNil = xmlGetNsProp(
260 cur, reinterpret_cast<xmlChar const *>("nil"), reinterpret_cast<xmlChar const *>(NS_SCHEMA_INSTANCE));
261 if (sNil == nullptr)
262 throw FrameworkException(JFW_E_ERROR, sExcMsg);
263
264 if (xmlStrcmp(sNil, reinterpret_cast<xmlChar const *>("false")) == 0)
265 {
266 if (! m_javaInfo)
267 m_javaInfo = boost::optional<CNodeJavaInfo>(CNodeJavaInfo());
268 m_javaInfo->loadFromNode(docUser, cur);
269 }
270 }
271 else if (xmlStrcmp(cur->name, reinterpret_cast<xmlChar const *>("vmParameters")) == 0)
272 {
273 sNil = xmlGetNsProp(
274 cur, reinterpret_cast<xmlChar const *>("nil"), reinterpret_cast<xmlChar const *>(NS_SCHEMA_INSTANCE));
275 if (sNil == nullptr)
276 throw FrameworkException(JFW_E_ERROR, sExcMsg);
277 if (xmlStrcmp(sNil, reinterpret_cast<xmlChar const *>("false")) == 0)
278 {
279 if ( ! m_vmParameters)
280 m_vmParameters = boost::optional<std::vector<OUString> >(
281 std::vector<OUString> ());
282
283 xmlNode * pOpt = cur->children;
284 while (pOpt != nullptr)
285 {
286 if (xmlStrcmp(pOpt->name, reinterpret_cast<xmlChar const *>("param")) == 0)
287 {
288 CXmlCharPtr sOpt = xmlNodeListGetString(
289 docUser, pOpt->children, 1);
290 m_vmParameters->push_back(sOpt);
291 }
292 pOpt = pOpt->next;
293 }
294 }
295 }
296 else if (xmlStrcmp(cur->name, reinterpret_cast<xmlChar const *>("jreLocations")) == 0)
297 {
298 sNil = xmlGetNsProp(
299 cur, reinterpret_cast<xmlChar const *>("nil"), reinterpret_cast<xmlChar const *>(NS_SCHEMA_INSTANCE));
300 if (sNil == nullptr)
301 throw FrameworkException(JFW_E_ERROR, sExcMsg);
302 if (xmlStrcmp(sNil, reinterpret_cast<xmlChar const *>("false")) == 0)
303 {
304 if (! m_JRELocations)
305 m_JRELocations = boost::optional<std::vector<OUString> >(
306 std::vector<OUString>());
307
308 xmlNode * pLoc = cur->children;
309 while (pLoc != nullptr)
310 {
311 if (xmlStrcmp(pLoc->name, reinterpret_cast<xmlChar const *>("location")) == 0)
312 {
313 CXmlCharPtr sLoc = xmlNodeListGetString(
314 docUser, pLoc->children, 1);
315 m_JRELocations->push_back(sLoc);
316 }
317 pLoc = pLoc->next;
318 }
319 }
320 }
321 cur = cur->next;
322 }
323 }
324
getSettingsPath() const325 OString NodeJava::getSettingsPath() const
326 {
327 OString ret;
328 switch (m_layer)
329 {
330 case USER: ret = getUserSettingsPath(); break;
331 case SHARED: ret = getSharedSettingsPath(); break;
332 default:
333 OSL_FAIL("[Java framework] NodeJava::getSettingsPath()");
334 }
335 return ret;
336 }
337
getSettingsURL() const338 OUString NodeJava::getSettingsURL() const
339 {
340 OUString ret;
341 switch (m_layer)
342 {
343 case USER: ret = BootParams::getUserData(); break;
344 case SHARED: ret = BootParams::getSharedData(); break;
345 default:
346 OSL_FAIL("[Java framework] NodeJava::getSettingsURL()");
347 }
348 return ret;
349 }
350
prepareSettingsDocument() const351 bool NodeJava::prepareSettingsDocument() const
352 {
353 OString sExcMsg(
354 "[Java framework] Error in function prepareSettingsDocument"
355 " (elements.cxx).");
356 if (!createSettingsDocument())
357 {
358 return false;
359 }
360 OString sSettings = getSettingsPath();
361 CXmlDocPtr doc(xmlParseFile(sSettings.getStr()));
362 if (!doc)
363 throw FrameworkException(JFW_E_ERROR, sExcMsg);
364
365 bool bNeedsSave = false;
366 createSettingsStructure(doc, & bNeedsSave);
367 if (bNeedsSave)
368 {
369 if (xmlSaveFormatFileEnc(
370 sSettings.getStr(), doc,"UTF-8", 1) == -1)
371 throw FrameworkException(JFW_E_ERROR, sExcMsg);
372 }
373 return true;
374 }
375
write() const376 void NodeJava::write() const
377 {
378 OString sExcMsg("[Java framework] Error in function NodeJava::writeSettings "
379 "(elements.cxx).");
380 CXmlDocPtr docUser;
381 CXPathContextPtr contextUser;
382 CXPathObjectPtr pathObj;
383
384 if (!prepareSettingsDocument())
385 {
386 SAL_INFO("jfw.level1", "no path to write settings document to");
387 return;
388 }
389
390 //Read the user elements
391 OString sSettingsPath = getSettingsPath();
392 docUser = xmlParseFile(sSettingsPath.getStr());
393 if (docUser == nullptr)
394 throw FrameworkException(JFW_E_ERROR, sExcMsg);
395 contextUser = xmlXPathNewContext(docUser);
396 if (xmlXPathRegisterNs(contextUser, reinterpret_cast<xmlChar const *>("jf"),
397 reinterpret_cast<xmlChar const *>(NS_JAVA_FRAMEWORK)) == -1)
398 throw FrameworkException(JFW_E_ERROR, sExcMsg);
399
400 xmlNode * root = xmlDocGetRootElement(docUser);
401 //Get xsi:nil namespace
402 xmlNs* nsXsi = xmlSearchNsByHref(docUser,
403 root,
404 reinterpret_cast<xmlChar const *>(NS_SCHEMA_INSTANCE));
405
406 //set the <enabled> element
407 //The element must exist
408 if (m_enabled)
409 {
410 pathObj = xmlXPathEvalExpression(reinterpret_cast<xmlChar const *>("/jf:java/jf:enabled"),
411 contextUser);
412 if ( ! pathObj || xmlXPathNodeSetIsEmpty(pathObj->nodesetval))
413 throw FrameworkException(JFW_E_ERROR, sExcMsg);
414
415 xmlNode * nodeEnabled = pathObj->nodesetval->nodeTab[0];
416 xmlSetNsProp(nodeEnabled,
417 nsXsi,
418 reinterpret_cast<xmlChar const *>("nil"),
419 reinterpret_cast<xmlChar const *>("false"));
420
421 if (m_enabled == boost::optional<sal_Bool>(true))
422 xmlNodeSetContent(nodeEnabled,reinterpret_cast<xmlChar const *>("true"));
423 else
424 xmlNodeSetContent(nodeEnabled,reinterpret_cast<xmlChar const *>("false"));
425 }
426
427 //set the <userClassPath> element
428 //The element must exist
429 if (m_userClassPath)
430 {
431 pathObj = xmlXPathEvalExpression(reinterpret_cast<xmlChar const *>("/jf:java/jf:userClassPath"),
432 contextUser);
433 if ( ! pathObj || xmlXPathNodeSetIsEmpty(pathObj->nodesetval))
434 throw FrameworkException(JFW_E_ERROR, sExcMsg);
435
436 xmlNode * nodeEnabled = pathObj->nodesetval->nodeTab[0];
437 xmlSetNsProp(nodeEnabled, nsXsi, reinterpret_cast<xmlChar const *>("nil"),reinterpret_cast<xmlChar const *>("false"));
438 xmlNodeSetContent(nodeEnabled,static_cast<xmlChar*>(CXmlCharPtr(*m_userClassPath)));
439 }
440
441 //set <javaInfo> element
442 if (m_javaInfo)
443 {
444 pathObj = xmlXPathEvalExpression(reinterpret_cast<xmlChar const *>("/jf:java/jf:javaInfo"),
445 contextUser);
446 if ( ! pathObj || xmlXPathNodeSetIsEmpty(pathObj->nodesetval))
447 throw FrameworkException(JFW_E_ERROR, sExcMsg);
448 m_javaInfo->writeToNode(
449 docUser, pathObj->nodesetval->nodeTab[0]);
450 }
451
452 //set <vmParameters> element
453 if (m_vmParameters)
454 {
455 pathObj = xmlXPathEvalExpression(reinterpret_cast<xmlChar const *>("/jf:java/jf:vmParameters"),
456 contextUser);
457 if ( ! pathObj || xmlXPathNodeSetIsEmpty(pathObj->nodesetval))
458 throw FrameworkException(JFW_E_ERROR, sExcMsg);
459 xmlNode* vmParameters = pathObj->nodesetval->nodeTab[0];
460 //set xsi:nil = false;
461 xmlSetNsProp(vmParameters, nsXsi,reinterpret_cast<xmlChar const *>("nil"),
462 reinterpret_cast<xmlChar const *>("false"));
463
464 //remove option elements
465 xmlNode* cur = vmParameters->children;
466 while (cur != nullptr)
467 {
468 xmlNode* lastNode = cur;
469 cur = cur->next;
470 xmlUnlinkNode(lastNode);
471 xmlFreeNode(lastNode);
472 }
473 //add a new line after <vmParameters>
474 if (!m_vmParameters->empty())
475 {
476 xmlNode * nodeCrLf = xmlNewText(reinterpret_cast<xmlChar const *>("\n"));
477 xmlAddChild(vmParameters, nodeCrLf);
478 }
479
480 for (auto const & vmParameter : *m_vmParameters)
481 {
482 xmlNewTextChild(vmParameters, nullptr, reinterpret_cast<xmlChar const *>("param"),
483 CXmlCharPtr(vmParameter));
484 //add a new line
485 xmlNode * nodeCrLf = xmlNewText(reinterpret_cast<xmlChar const *>("\n"));
486 xmlAddChild(vmParameters, nodeCrLf);
487 }
488 }
489
490 //set <jreLocations> element
491 if (m_JRELocations)
492 {
493 pathObj = xmlXPathEvalExpression(reinterpret_cast<xmlChar const *>("/jf:java/jf:jreLocations"),
494 contextUser);
495 if ( ! pathObj || xmlXPathNodeSetIsEmpty(pathObj->nodesetval))
496 throw FrameworkException(JFW_E_ERROR, sExcMsg);
497 xmlNode* jreLocationsNode = pathObj->nodesetval->nodeTab[0];
498 //set xsi:nil = false;
499 xmlSetNsProp(jreLocationsNode, nsXsi,reinterpret_cast<xmlChar const *>("nil"),
500 reinterpret_cast<xmlChar const *>("false"));
501
502 //remove option elements
503 xmlNode* cur = jreLocationsNode->children;
504 while (cur != nullptr)
505 {
506 xmlNode* lastNode = cur;
507 cur = cur->next;
508 xmlUnlinkNode(lastNode);
509 xmlFreeNode(lastNode);
510 }
511 //add a new line after <vmParameters>
512 if (!m_JRELocations->empty())
513 {
514 xmlNode * nodeCrLf = xmlNewText(reinterpret_cast<xmlChar const *>("\n"));
515 xmlAddChild(jreLocationsNode, nodeCrLf);
516 }
517
518 for (auto const & JRELocation : *m_JRELocations)
519 {
520 xmlNewTextChild(jreLocationsNode, nullptr, reinterpret_cast<xmlChar const *>("location"),
521 CXmlCharPtr(JRELocation));
522 //add a new line
523 xmlNode * nodeCrLf = xmlNewText(reinterpret_cast<xmlChar const *>("\n"));
524 xmlAddChild(jreLocationsNode, nodeCrLf);
525 }
526 }
527
528 if (xmlSaveFormatFile(sSettingsPath.getStr(), docUser, 1) == -1)
529 throw FrameworkException(JFW_E_ERROR, sExcMsg);
530 }
531
setEnabled(bool bEnabled)532 void NodeJava::setEnabled(bool bEnabled)
533 {
534 m_enabled = boost::optional<sal_Bool>(bEnabled);
535 }
536
537
setUserClassPath(const OUString & sClassPath)538 void NodeJava::setUserClassPath(const OUString & sClassPath)
539 {
540 m_userClassPath = boost::optional<OUString>(sClassPath);
541 }
542
setJavaInfo(const JavaInfo * pInfo,bool bAutoSelect)543 void NodeJava::setJavaInfo(const JavaInfo * pInfo, bool bAutoSelect)
544 {
545 if (!m_javaInfo)
546 m_javaInfo = boost::optional<CNodeJavaInfo>(CNodeJavaInfo());
547 m_javaInfo->bAutoSelect = bAutoSelect;
548 m_javaInfo->bNil = false;
549
550 if (pInfo != nullptr)
551 {
552 m_javaInfo->m_bEmptyNode = false;
553 m_javaInfo->sVendor = pInfo->sVendor;
554 m_javaInfo->sLocation = pInfo->sLocation;
555 m_javaInfo->sVersion = pInfo->sVersion;
556 m_javaInfo->nFeatures = pInfo->nFeatures;
557 m_javaInfo->nRequirements = pInfo->nRequirements;
558 m_javaInfo->arVendorData = pInfo->arVendorData;
559 }
560 else
561 {
562 m_javaInfo->m_bEmptyNode = true;
563 m_javaInfo->sVendor.clear();
564 m_javaInfo->sLocation.clear();
565 m_javaInfo->sVersion.clear();
566 m_javaInfo->nFeatures = 0;
567 m_javaInfo->nRequirements = 0;
568 m_javaInfo->arVendorData = rtl::ByteSequence();
569 }
570 }
571
setVmParameters(std::vector<OUString> const & arOptions)572 void NodeJava::setVmParameters(std::vector<OUString> const & arOptions)
573 {
574 m_vmParameters = boost::optional<std::vector<OUString> >(arOptions);
575 }
576
addJRELocation(OUString const & sLocation)577 void NodeJava::addJRELocation(OUString const & sLocation)
578 {
579 if (!m_JRELocations)
580 m_JRELocations = boost::optional<std::vector<OUString> >(
581 std::vector<OUString> ());
582 //only add the path if not already present
583 std::vector<OUString>::const_iterator it =
584 std::find(m_JRELocations->begin(), m_JRELocations->end(), sLocation);
585 if (it == m_JRELocations->end())
586 m_JRELocations->push_back(sLocation);
587 }
588
checkSettingsFileStatus(OUString const & sURL)589 jfw::FileStatus NodeJava::checkSettingsFileStatus(OUString const & sURL)
590 {
591 jfw::FileStatus ret = FILE_DOES_NOT_EXIST;
592
593 //check the file time
594 ::osl::DirectoryItem item;
595 File::RC rc = ::osl::DirectoryItem::get(sURL, item);
596 if (File::E_None == rc)
597 {
598 ::osl::FileStatus stat(osl_FileStatus_Mask_Validate);
599 File::RC rc_stat = item.getFileStatus(stat);
600 if (File::E_None == rc_stat)
601 {
602 ret = FILE_OK;
603 }
604 else if (File::E_NOENT == rc_stat)
605 {
606 ret = FILE_DOES_NOT_EXIST;
607 }
608 else
609 {
610 ret = FILE_INVALID;
611 }
612 }
613 else if(File::E_NOENT == rc)
614 {
615 ret = FILE_DOES_NOT_EXIST;
616 }
617 else
618 {
619 ret = FILE_INVALID;
620 }
621 return ret;
622 }
623
createSettingsDocument() const624 bool NodeJava::createSettingsDocument() const
625 {
626 const OUString sURL = getSettingsURL();
627 if (sURL.isEmpty())
628 {
629 return false;
630 }
631 //make sure there is a user directory
632 OString sExcMsg("[Java framework] Error in function createSettingsDocument "
633 "(elements.cxx).");
634 // check if javasettings.xml already exist
635 if (FILE_OK == checkSettingsFileStatus(sURL))
636 return true;
637
638 //make sure that the directories are created in case they do not exist
639 FileBase::RC rcFile = Directory::createPath(getDirFromFile(sURL));
640 if (rcFile != FileBase::E_EXIST && rcFile != FileBase::E_None)
641 throw FrameworkException(JFW_E_ERROR, sExcMsg);
642
643 //javasettings.xml does not exist yet
644 CXmlDocPtr doc(xmlNewDoc(reinterpret_cast<xmlChar const *>("1.0")));
645 if (! doc)
646 throw FrameworkException(JFW_E_ERROR, sExcMsg);
647
648 //Create the root element and name spaces
649 xmlNodePtr root = xmlNewDocNode(
650 doc, nullptr, reinterpret_cast<xmlChar const *>("java"), reinterpret_cast<xmlChar const *>("\n"));
651
652 if (root == nullptr)
653 throw FrameworkException(JFW_E_ERROR, sExcMsg);
654
655 if (xmlNewNs(root, reinterpret_cast<xmlChar const *>(NS_JAVA_FRAMEWORK),nullptr) == nullptr)
656 throw FrameworkException(JFW_E_ERROR, sExcMsg);
657 if (xmlNewNs(root,reinterpret_cast<xmlChar const *>(NS_SCHEMA_INSTANCE),reinterpret_cast<xmlChar const *>("xsi")) == nullptr)
658 throw FrameworkException(JFW_E_ERROR, sExcMsg);
659 xmlDocSetRootElement(doc, root);
660
661 //Create a comment
662 xmlNodePtr com = xmlNewComment(
663 reinterpret_cast<xmlChar const *>("This is a generated file. Do not alter this file!"));
664 if (com == nullptr)
665 throw FrameworkException(JFW_E_ERROR, sExcMsg);
666
667 if (xmlAddPrevSibling(root, com) == nullptr)
668 throw FrameworkException(JFW_E_ERROR, sExcMsg);
669
670 const OString path = getSettingsPath();
671 if (xmlSaveFormatFileEnc(path.getStr(), doc,"UTF-8", 1) == -1)
672 throw FrameworkException(JFW_E_ERROR, sExcMsg);
673 return true;
674 }
675
676
CNodeJavaInfo()677 CNodeJavaInfo::CNodeJavaInfo() :
678 m_bEmptyNode(false), bNil(true), bAutoSelect(true),
679 nFeatures(0), nRequirements(0)
680 {
681 }
682
loadFromNode(xmlDoc * pDoc,xmlNode * pJavaInfo)683 void CNodeJavaInfo::loadFromNode(xmlDoc * pDoc, xmlNode * pJavaInfo)
684 {
685 OString sExcMsg("[Java framework] Error in function NodeJavaInfo::loadFromNode "
686 "(elements.cxx).");
687
688 OSL_ASSERT(pJavaInfo && pDoc);
689 if (pJavaInfo->children == nullptr)
690 return;
691 //Get the xsi:nil attribute;
692 CXmlCharPtr sNil = xmlGetNsProp(
693 pJavaInfo, reinterpret_cast<xmlChar const *>("nil"), reinterpret_cast<xmlChar const *>(NS_SCHEMA_INSTANCE));
694 if ( ! sNil)
695 throw FrameworkException(JFW_E_ERROR, sExcMsg);
696
697 if (xmlStrcmp(sNil, reinterpret_cast<xmlChar const *>("true")) == 0)
698 bNil = true;
699 else if (xmlStrcmp(sNil, reinterpret_cast<xmlChar const *>("false")) == 0)
700 bNil = false;
701 else
702 throw FrameworkException(JFW_E_ERROR, sExcMsg);
703 if (bNil)
704 return;
705
706 //Get javaInfo@manuallySelected attribute
707 CXmlCharPtr sAutoSelect = xmlGetProp(
708 pJavaInfo, reinterpret_cast<xmlChar const *>("autoSelect"));
709 if ( ! sAutoSelect)
710 throw FrameworkException(JFW_E_ERROR, sExcMsg);
711
712 if (xmlStrcmp(sAutoSelect, reinterpret_cast<xmlChar const *>("true")) == 0)
713 bAutoSelect = true;
714 else if (xmlStrcmp(sAutoSelect, reinterpret_cast<xmlChar const *>("false")) == 0)
715 bAutoSelect = false;
716 else
717 throw FrameworkException(JFW_E_ERROR, sExcMsg);
718
719 xmlNode * cur = pJavaInfo->children;
720
721 while (cur != nullptr)
722 {
723 if (xmlStrcmp(cur->name, reinterpret_cast<xmlChar const *>("vendor")) == 0)
724 {
725 CXmlCharPtr xmlVendor = xmlNodeListGetString(
726 pDoc, cur->children, 1);
727 if (! xmlVendor)
728 return;
729 sVendor = xmlVendor;
730 }
731 else if (xmlStrcmp(cur->name, reinterpret_cast<xmlChar const *>("location")) == 0)
732 {
733 CXmlCharPtr xmlLocation = xmlNodeListGetString(
734 pDoc, cur->children, 1);
735 sLocation = xmlLocation;
736 }
737 else if (xmlStrcmp(cur->name, reinterpret_cast<xmlChar const *>("version")) == 0)
738 {
739 CXmlCharPtr xmlVersion = xmlNodeListGetString(
740 pDoc, cur->children, 1);
741 sVersion = xmlVersion;
742 }
743 else if (xmlStrcmp(cur->name, reinterpret_cast<xmlChar const *>("features"))== 0)
744 {
745 CXmlCharPtr xmlFeatures = xmlNodeListGetString(
746 pDoc, cur->children, 1);
747 OUString sFeatures = xmlFeatures;
748 nFeatures = sFeatures.toInt64(16);
749 }
750 else if (xmlStrcmp(cur->name, reinterpret_cast<xmlChar const *>("requirements")) == 0)
751 {
752 CXmlCharPtr xmlRequire = xmlNodeListGetString(
753 pDoc, cur->children, 1);
754 OUString sRequire = xmlRequire;
755 nRequirements = sRequire.toInt64(16);
756 #ifdef MACOSX
757 //javaldx is not used anymore in the mac build. In case the Java
758 //corresponding to the saved settings does not exist anymore the
759 //javavm services will look for an existing Java after creation of
760 //the JVM failed. See stoc/source/javavm/javavm.cxx. Only if
761 //nRequirements does not have the flag JFW_REQUIRE_NEEDRESTART the
762 //jvm of the new selected JRE will be started. Old settings (before
763 //OOo 3.3) still contain the flag which can be safely ignored.
764 nRequirements &= ~JFW_REQUIRE_NEEDRESTART;
765 #endif
766 }
767 else if (xmlStrcmp(cur->name, reinterpret_cast<xmlChar const *>("vendorData")) == 0)
768 {
769 CXmlCharPtr xmlData = xmlNodeListGetString(
770 pDoc, cur->children, 1);
771 xmlChar* _data = static_cast<xmlChar*>(xmlData);
772 if (_data)
773 {
774 rtl::ByteSequence seq(reinterpret_cast<sal_Int8*>(_data), strlen(reinterpret_cast<char*>(_data)));
775 arVendorData = decodeBase16(seq);
776 }
777 }
778 cur = cur->next;
779 }
780
781 if (sVendor.isEmpty())
782 m_bEmptyNode = true;
783 //Get the javainfo attributes
784 CXmlCharPtr sVendorUpdate = xmlGetProp(pJavaInfo,
785 reinterpret_cast<xmlChar const *>("vendorUpdate"));
786 if ( ! sVendorUpdate)
787 throw FrameworkException(JFW_E_ERROR, sExcMsg);
788 sAttrVendorUpdate = sVendorUpdate;
789 }
790
791
writeToNode(xmlDoc * pDoc,xmlNode * pJavaInfoNode) const792 void CNodeJavaInfo::writeToNode(xmlDoc* pDoc,
793 xmlNode* pJavaInfoNode) const
794
795 {
796 OSL_ASSERT(pJavaInfoNode && pDoc);
797 //write the attribute vendorSettings
798
799 //javaInfo@vendorUpdate
800 //creates the attribute if necessary
801 OString sUpdated = getElementUpdated();
802
803 xmlSetProp(pJavaInfoNode, reinterpret_cast<xmlChar const *>("vendorUpdate"),
804 reinterpret_cast<xmlChar const *>(sUpdated.getStr()));
805
806 //javaInfo@autoSelect
807 xmlSetProp(pJavaInfoNode, reinterpret_cast<xmlChar const *>("autoSelect"),
808 reinterpret_cast<xmlChar const *>(bAutoSelect ? "true" : "false"));
809
810 //Set xsi:nil in javaInfo element to false
811 //the xmlNs pointer must not be destroyed
812 xmlNs* nsXsi = xmlSearchNsByHref(pDoc,
813 pJavaInfoNode,
814 reinterpret_cast<xmlChar const *>(NS_SCHEMA_INSTANCE));
815
816 xmlSetNsProp(pJavaInfoNode,
817 nsXsi,
818 reinterpret_cast<xmlChar const *>("nil"),
819 reinterpret_cast<xmlChar const *>("false"));
820
821 //Delete the children of JavaInfo
822 xmlNode* cur = pJavaInfoNode->children;
823 while (cur != nullptr)
824 {
825 xmlNode* lastNode = cur;
826 cur = cur->next;
827 xmlUnlinkNode(lastNode);
828 xmlFreeNode(lastNode);
829 }
830
831 //If the JavaInfo was set with an empty value,
832 //then we are done.
833 if (m_bEmptyNode)
834 return;
835
836 //add a new line after <javaInfo>
837 xmlNode * nodeCrLf = xmlNewText(reinterpret_cast<xmlChar const *>("\n"));
838 xmlAddChild(pJavaInfoNode, nodeCrLf);
839
840 //Create the vendor element
841 xmlNewTextChild(pJavaInfoNode, nullptr, reinterpret_cast<xmlChar const *>("vendor"),
842 CXmlCharPtr(sVendor));
843 //add a new line for better readability
844 nodeCrLf = xmlNewText(reinterpret_cast<xmlChar const *>("\n"));
845 xmlAddChild(pJavaInfoNode, nodeCrLf);
846
847 //Create the location element
848 xmlNewTextChild(pJavaInfoNode, nullptr, reinterpret_cast<xmlChar const *>("location"),
849 CXmlCharPtr(sLocation));
850 //add a new line for better readability
851 nodeCrLf = xmlNewText(reinterpret_cast<xmlChar const *>("\n"));
852 xmlAddChild(pJavaInfoNode, nodeCrLf);
853
854 //Create the version element
855 xmlNewTextChild(pJavaInfoNode, nullptr, reinterpret_cast<xmlChar const *>("version"),
856 CXmlCharPtr(sVersion));
857 //add a new line for better readability
858 nodeCrLf = xmlNewText(reinterpret_cast<xmlChar const *>("\n"));
859 xmlAddChild(pJavaInfoNode, nodeCrLf);
860
861 //Create the features element
862 OUString sFeatures = OUString::number(
863 nFeatures, 16);
864 xmlNewTextChild(pJavaInfoNode, nullptr, reinterpret_cast<xmlChar const *>("features"),
865 CXmlCharPtr(sFeatures));
866 //add a new line for better readability
867 nodeCrLf = xmlNewText(reinterpret_cast<xmlChar const *>("\n"));
868 xmlAddChild(pJavaInfoNode, nodeCrLf);
869
870
871 //Create the requirements element
872 OUString sRequirements = OUString::number(
873 nRequirements, 16);
874 xmlNewTextChild(pJavaInfoNode, nullptr, reinterpret_cast<xmlChar const *>("requirements"),
875 CXmlCharPtr(sRequirements));
876 //add a new line for better readability
877 nodeCrLf = xmlNewText(reinterpret_cast<xmlChar const *>("\n"));
878 xmlAddChild(pJavaInfoNode, nodeCrLf);
879
880
881 //Create the features element
882 rtl::ByteSequence data = encodeBase16(arVendorData);
883 xmlNode* dataNode = xmlNewChild(pJavaInfoNode, nullptr,
884 reinterpret_cast<xmlChar const *>("vendorData"),
885 reinterpret_cast<xmlChar const *>(""));
886 xmlNodeSetContentLen(dataNode,
887 reinterpret_cast<xmlChar*>(data.getArray()), data.getLength());
888 //add a new line for better readability
889 nodeCrLf = xmlNewText(reinterpret_cast<xmlChar const *>("\n"));
890 xmlAddChild(pJavaInfoNode, nodeCrLf);
891 }
892
makeJavaInfo() const893 std::unique_ptr<JavaInfo> CNodeJavaInfo::makeJavaInfo() const
894 {
895 if (bNil || m_bEmptyNode)
896 return std::unique_ptr<JavaInfo>();
897 return std::unique_ptr<JavaInfo>(
898 new JavaInfo{
899 sVendor, sLocation, sVersion, nFeatures, nRequirements,
900 arVendorData});
901 }
902
903
MergedSettings()904 MergedSettings::MergedSettings():
905 m_bEnabled(false),
906 m_sClassPath(),
907 m_vmParams(),
908 m_JRELocations(),
909 m_javaInfo()
910 {
911 NodeJava settings(NodeJava::USER);
912 settings.load();
913 NodeJava sharedSettings(NodeJava::SHARED);
914 sharedSettings.load();
915 merge(sharedSettings, settings);
916 }
917
~MergedSettings()918 MergedSettings::~MergedSettings()
919 {
920 }
921
merge(const NodeJava & share,const NodeJava & user)922 void MergedSettings::merge(const NodeJava & share, const NodeJava & user)
923 {
924 if (user.getEnabled())
925 m_bEnabled = * user.getEnabled();
926 else if (share.getEnabled())
927 m_bEnabled = * share.getEnabled();
928 else
929 m_bEnabled = true;
930
931 if (user.getUserClassPath())
932 m_sClassPath = * user.getUserClassPath();
933 else if (share.getUserClassPath())
934 m_sClassPath = * share.getUserClassPath();
935
936 if (user.getJavaInfo())
937 m_javaInfo = * user.getJavaInfo();
938 else if (share.getJavaInfo())
939 m_javaInfo = * share.getJavaInfo();
940
941 if (user.getVmParameters())
942 m_vmParams = * user.getVmParameters();
943 else if (share.getVmParameters())
944 m_vmParams = * share.getVmParameters();
945
946 if (user.getJRELocations())
947 m_JRELocations = * user.getJRELocations();
948 else if (share.getJRELocations())
949 m_JRELocations = * share.getJRELocations();
950 }
951
952
getVmParametersUtf8() const953 ::std::vector< OString> MergedSettings::getVmParametersUtf8() const
954 {
955 ::std::vector< OString> ret;
956 for (auto const & vmParam : m_vmParams)
957 {
958 ret.push_back( OUStringToOString(vmParam, RTL_TEXTENCODING_UTF8));
959 }
960 return ret;
961 }
962
963
createJavaInfo() const964 std::unique_ptr<JavaInfo> MergedSettings::createJavaInfo() const
965 {
966 return m_javaInfo.makeJavaInfo();
967 }
968 #ifdef _WIN32
getJavaInfoAttrAutoSelect() const969 bool MergedSettings::getJavaInfoAttrAutoSelect() const
970 {
971 return m_javaInfo.bAutoSelect;
972 }
973 #endif
getVmParametersArray(std::vector<OUString> * parParams) const974 void MergedSettings::getVmParametersArray(std::vector<OUString> * parParams)
975 const
976 {
977 assert(parParams != nullptr);
978 osl::MutexGuard guard(FwkMutex::get());
979
980 *parParams = m_vmParams;
981 }
982
983 }
984
985 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
986