GME
13
|
00001 /* 00002 * Licensed to the Apache Software Foundation (ASF) under one or more 00003 * contributor license agreements. See the NOTICE file distributed with 00004 * this work for additional information regarding copyright ownership. 00005 * The ASF licenses this file to You under the Apache License, Version 2.0 00006 * (the "License"); you may not use this file except in compliance with 00007 * the License. You may obtain a copy of the License at 00008 * 00009 * http://www.apache.org/licenses/LICENSE-2.0 00010 * 00011 * Unless required by applicable law or agreed to in writing, software 00012 * distributed under the License is distributed on an "AS IS" BASIS, 00013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00014 * See the License for the specific language governing permissions and 00015 * limitations under the License. 00016 */ 00017 00018 /* 00019 * $Id: PlatformUtils.cpp 932877 2010-04-11 12:17:34Z borisk $ 00020 * 00021 */ 00022 00023 00024 // --------------------------------------------------------------------------- 00025 // Includes 00026 // --------------------------------------------------------------------------- 00027 #if HAVE_CONFIG_H 00028 # include <config.h> 00029 #endif 00030 00031 #if HAVE_LIMITS_H 00032 # include <limits.h> 00033 #endif 00034 #if HAVE_SYS_TIME_H 00035 # include <sys/time.h> 00036 #endif 00037 #if HAVE_SYS_TIMEB_H 00038 # include <sys/timeb.h> 00039 #endif 00040 #if HAVE_CPUID_H && !XERCES_HAVE_INTRIN_H 00041 # include <cpuid.h> 00042 #endif 00043 00044 #include <xercesc/util/Mutexes.hpp> 00045 #include <xercesc/util/PlatformUtils.hpp> 00046 #include <xercesc/util/RefVectorOf.hpp> 00047 #include <xercesc/util/XMLString.hpp> 00048 #include <xercesc/util/XMLUni.hpp> 00049 #include <xercesc/internal/XMLReader.hpp> 00050 #include <xercesc/util/RuntimeException.hpp> 00051 #include <xercesc/util/OutOfMemoryException.hpp> 00052 #include <xercesc/util/DefaultPanicHandler.hpp> 00053 #include <xercesc/util/XMLInitializer.hpp> 00054 #include <xercesc/internal/MemoryManagerImpl.hpp> 00055 00056 #if XERCES_HAVE_INTRIN_H 00057 # include <intrin.h> 00058 #endif 00059 00060 #include <xercesc/util/XMLFileMgr.hpp> 00061 #if XERCES_USE_FILEMGR_POSIX 00062 # include <xercesc/util/FileManagers/PosixFileMgr.hpp> 00063 #endif 00064 #if XERCES_USE_FILEMGR_WINDOWS 00065 # include <xercesc/util/FileManagers/WindowsFileMgr.hpp> 00066 #endif 00067 00068 #include <xercesc/util/XMLMutexMgr.hpp> 00069 #if XERCES_USE_MUTEXMGR_NOTHREAD 00070 # include <xercesc/util/MutexManagers/NoThreadMutexMgr.hpp> 00071 #endif 00072 #if XERCES_USE_MUTEXMGR_POSIX 00073 # include <xercesc/util/MutexManagers/PosixMutexMgr.hpp> 00074 #endif 00075 #if XERCES_USE_MUTEXMGR_WINDOWS 00076 # include <xercesc/util/MutexManagers/WindowsMutexMgr.hpp> 00077 #endif 00078 00079 #include <xercesc/util/XMLNetAccessor.hpp> 00080 #if XERCES_USE_NETACCESSOR_CURL 00081 # include <xercesc/util/NetAccessors/Curl/CurlNetAccessor.hpp> 00082 #endif 00083 #if XERCES_USE_NETACCESSOR_SOCKET 00084 # include <xercesc/util/NetAccessors/Socket/SocketNetAccessor.hpp> 00085 #endif 00086 #if XERCES_USE_NETACCESSOR_CFURL 00087 # include <xercesc/util/NetAccessors/MacOSURLAccessCF/MacOSURLAccessCF.hpp> 00088 #endif 00089 #if XERCES_USE_NETACCESSOR_WINSOCK 00090 # include <xercesc/util/NetAccessors/WinSock/WinSockNetAccessor.hpp> 00091 #endif 00092 00093 00094 #include <xercesc/util/XMLMsgLoader.hpp> 00095 #if XERCES_USE_MSGLOADER_ICU 00096 # include <xercesc/util/MsgLoaders/ICU/ICUMsgLoader.hpp> 00097 #endif 00098 #if XERCES_USE_MSGLOADER_ICONV 00099 # include <xercesc/util/MsgLoaders/MsgCatalog/MsgCatalogLoader.hpp> 00100 #endif 00101 #if XERCES_USE_MSGLOADER_INMEMORY 00102 # include <xercesc/util/MsgLoaders/InMemory/InMemMsgLoader.hpp> 00103 #endif 00104 #if XERCES_USE_WIN32_MSGLOADER 00105 # include <xercesc/util/MsgLoaders/Win32/Win32MsgLoader.hpp> 00106 #endif 00107 00108 #include <xercesc/util/TransService.hpp> 00109 #if XERCES_USE_TRANSCODER_ICU 00110 # include <xercesc/util/Transcoders/ICU/ICUTransService.hpp> 00111 #endif 00112 #if XERCES_USE_TRANSCODER_GNUICONV 00113 # include <xercesc/util/Transcoders/IconvGNU/IconvGNUTransService.hpp> 00114 #endif 00115 #if XERCES_USE_TRANSCODER_ICONV 00116 # include <xercesc/util/Transcoders/Iconv/IconvTransService.hpp> 00117 #endif 00118 #if XERCES_USE_TRANSCODER_MACOSUNICODECONVERTER 00119 # include <xercesc/util/Transcoders/MacOSUnicodeConverter/MacOSUnicodeConverter.hpp> 00120 #endif 00121 #if XERCES_USE_TRANSCODER_WINDOWS 00122 # include <xercesc/util/Transcoders/Win32/Win32TransService.hpp> 00123 #endif 00124 00125 XERCES_CPP_NAMESPACE_BEGIN 00126 00127 // --------------------------------------------------------------------------- 00128 // Local data members 00129 // 00130 // gSyncMutex 00131 // This is a mutex that will be used to synchronize access to some of 00132 // the static data of the platform utilities class and here locally. 00133 // --------------------------------------------------------------------------- 00134 static XMLMutex* gSyncMutex = 0; 00135 static long gInitFlag = 0; 00136 00137 00138 // --------------------------------------------------------------------------- 00139 // XMLPlatformUtils: Static Data Members 00140 // --------------------------------------------------------------------------- 00141 XMLNetAccessor* XMLPlatformUtils::fgNetAccessor = 0; 00142 XMLTransService* XMLPlatformUtils::fgTransService = 0; 00143 #ifdef OS390 00144 XMLTransService* XMLPlatformUtils::fgTransService2 = 0; 00145 #endif 00146 PanicHandler* XMLPlatformUtils::fgUserPanicHandler = 0; 00147 PanicHandler* XMLPlatformUtils::fgDefaultPanicHandler = 0; 00148 MemoryManager* XMLPlatformUtils::fgMemoryManager = 0; 00149 bool XMLPlatformUtils::fgMemMgrAdopted = true; 00150 00151 XMLFileMgr* XMLPlatformUtils::fgFileMgr = 0; 00152 XMLMutexMgr* XMLPlatformUtils::fgMutexMgr = 0; 00153 00154 XMLMutex* XMLPlatformUtils::fgAtomicMutex = 0; 00155 00156 bool XMLPlatformUtils::fgXMLChBigEndian = true; 00157 bool XMLPlatformUtils::fgSSE2ok = false; 00158 00159 // --------------------------------------------------------------------------- 00160 // XMLPlatformUtils: Init/term methods 00161 // --------------------------------------------------------------------------- 00162 void XMLPlatformUtils::Initialize(const char* const locale 00163 , const char* const nlsHome 00164 , PanicHandler* const panicHandler 00165 , MemoryManager* const memoryManager) 00166 { 00167 // 00168 // Effects of overflow: 00169 // . resouce re-allocations 00170 // . consequently resource leaks 00171 // . potentially terminate() may never get executed 00172 // 00173 // We got to prevent overflow from happening. 00174 // no error or exception 00175 // 00176 if (gInitFlag == LONG_MAX) 00177 return; 00178 00179 // 00180 // Make sure we haven't already been initialized. Note that this is not 00181 // thread safe and is not intended for that. Its more for those COM 00182 // like processes that cannot keep up with whether they have initialized 00183 // us yet or not. 00184 // 00185 gInitFlag++; 00186 00187 if (gInitFlag > 1) 00188 return; 00189 00190 // Set pluggable memory manager 00191 if (!fgMemoryManager) 00192 { 00193 if (memoryManager) 00194 { 00195 fgMemoryManager = memoryManager; 00196 fgMemMgrAdopted = false; 00197 } 00198 else 00199 { 00200 fgMemoryManager = new MemoryManagerImpl(); 00201 } 00202 } 00203 00204 /*** 00205 * Panic Handler: 00206 * 00207 ***/ 00208 if (!panicHandler) 00209 { 00210 fgDefaultPanicHandler = new DefaultPanicHandler(); 00211 } 00212 else 00213 { 00214 fgUserPanicHandler = panicHandler; 00215 } 00216 00217 00218 // Determine our endianness (with regard to a XMLCh 16-bit word) 00219 union { 00220 XMLCh ch; 00221 unsigned char ar[sizeof(XMLCh)]; 00222 } endianTest; 00223 endianTest.ch = 1; 00224 fgXMLChBigEndian = (endianTest.ar[sizeof(XMLCh)-1] == 1); 00225 00226 // Determine if we can use SSE2 functions 00227 #if defined(XERCES_HAVE_CPUID_INTRINSIC) 00228 int CPUInfo[4]={0}; 00229 __cpuid(CPUInfo, 1); 00230 if(CPUInfo[3] & (1UL << 26)) 00231 fgSSE2ok = true; 00232 else 00233 fgSSE2ok = false; 00234 #elif defined(XERCES_HAVE_GETCPUID) 00235 unsigned int eax, ebx, ecx, edx; 00236 if(!__get_cpuid (1, &eax, &ebx, &ecx, &edx) || (edx & (1UL << 26))==0) 00237 fgSSE2ok = false; 00238 else 00239 fgSSE2ok = true; 00240 #elif defined(XERCES_HAVE_SSE2_INTRINSIC) 00241 // if we cannot find out at runtime, assume the define has it right 00242 fgSSE2ok = true; 00243 #else 00244 fgSSE2ok = false; 00245 #endif 00246 00247 // Initialize the platform-specific mutex and file mgrs 00248 fgMutexMgr = makeMutexMgr(fgMemoryManager); 00249 fgFileMgr = makeFileMgr(fgMemoryManager); 00250 00251 00252 // Create the local sync mutex 00253 gSyncMutex = new XMLMutex(fgMemoryManager); 00254 00255 // Create the global "atomic operations" mutex. 00256 fgAtomicMutex = new XMLMutex(fgMemoryManager); 00257 00258 // 00259 // Ask the per-platform code to make the desired transcoding service for 00260 // us to use. This call cannot throw any exceptions or do anything that 00261 // cause any transcoding to happen. It should create the service and 00262 // return it or zero if it cannot. 00263 // 00264 // This one also cannot use any utility services. It can only create a 00265 // transcoding service object and return it. 00266 // 00267 // If we cannot make one, then we call panic to end the process. 00268 // 00269 XMLInitializer::initializeTransService(); // TransService static data. 00270 00271 fgTransService = makeTransService(); 00272 00273 if (!fgTransService) 00274 panic(PanicHandler::Panic_NoTransService); 00275 00276 // Initialize the transcoder service 00277 fgTransService->initTransService(); 00278 00279 // 00280 // Try to create a default local code page transcoder. This is the one 00281 // that will be used internally by the XMLString class. If we cannot 00282 // create one, then call the panic method. 00283 // 00284 XMLLCPTranscoder* defXCode = XMLPlatformUtils::fgTransService->makeNewLCPTranscoder(fgMemoryManager); 00285 if (!defXCode) 00286 panic(PanicHandler::Panic_NoDefTranscoder); 00287 XMLString::initString(defXCode, fgMemoryManager); 00288 00289 // 00290 // Now lets ask the per-platform code to give us an instance of the type 00291 // of network access implementation he wants to use. This can return 00292 // a zero pointer if this platform doesn't want to support this. 00293 // 00294 fgNetAccessor = makeNetAccessor(); 00295 00296 /*** 00297 * Message Loader: 00298 * 00299 * Locale setting 00300 * nlsHome setting 00301 ***/ 00302 XMLMsgLoader::setLocale(locale); 00303 XMLMsgLoader::setNLSHome(nlsHome); 00304 00305 // Initialize static data. 00306 // 00307 XMLInitializer::initializeStaticData(); 00308 } 00309 00310 void XMLPlatformUtils::Initialize(XMLSize_t initialDOMHeapAllocSize 00311 , XMLSize_t maxDOMHeapAllocSize 00312 , XMLSize_t maxDOMSubAllocationSize 00313 , const char* const locale 00314 , const char* const nlsHome 00315 , PanicHandler* const panicHandler 00316 , MemoryManager* const memoryManager) 00317 { 00318 Initialize (locale, nlsHome, panicHandler, memoryManager); 00319 00320 // Don't change the parameters unless it is the first time. 00321 // 00322 if (gInitFlag == 1) 00323 XMLInitializer::initializeDOMHeap(initialDOMHeapAllocSize, 00324 maxDOMHeapAllocSize, 00325 maxDOMSubAllocationSize); 00326 } 00327 00328 void XMLPlatformUtils::Terminate() 00329 { 00330 // 00331 // To prevent it from running underflow. 00332 // otherwise we come to delete non-existing resources. 00333 // 00334 // no error or exception 00335 // 00336 if (gInitFlag == 0) 00337 return; 00338 00339 gInitFlag--; 00340 00341 if (gInitFlag > 0) 00342 return; 00343 00344 // Terminate static data. 00345 // 00346 XMLInitializer::terminateStaticData(); 00347 00348 // Delete any net accessor that got installed 00349 delete fgNetAccessor; 00350 fgNetAccessor = 0; 00351 00352 // 00353 // Call some other internal modules to give them a chance to clean up. 00354 // Do the string class last in case something tries to use it during 00355 // cleanup. 00356 // 00357 XMLString::termString(); 00358 00359 // Clean up the the transcoding service 00360 delete fgTransService; 00361 fgTransService = 0; 00362 00363 XMLInitializer::terminateTransService(); // TransService static data. 00364 00365 // Clean up mutexes 00366 delete gSyncMutex; gSyncMutex = 0; 00367 delete fgAtomicMutex; fgAtomicMutex = 0; 00368 00369 // Clean up our mgrs 00370 delete fgFileMgr; fgFileMgr = 0; 00371 delete fgMutexMgr; fgMutexMgr = 0; 00372 00373 /*** 00374 * de-allocate resource 00375 * 00376 * refer to discussion in the Initialize() 00377 ***/ 00378 XMLMsgLoader::setLocale(0); 00379 XMLMsgLoader::setNLSHome(0); 00380 00381 delete fgDefaultPanicHandler; 00382 fgDefaultPanicHandler = 0; 00383 fgUserPanicHandler = 0; 00384 00385 // de-allocate default memory manager 00386 if (fgMemMgrAdopted) 00387 delete fgMemoryManager; 00388 else 00389 fgMemMgrAdopted = true; 00390 00391 // set memory manager to 0 00392 fgMemoryManager = 0; 00393 00394 // And say we are no longer initialized 00395 gInitFlag = 0; 00396 } 00397 00398 00399 00400 00401 // --------------------------------------------------------------------------- 00402 // XMLPlatformUtils: The panic method 00403 // --------------------------------------------------------------------------- 00404 void XMLPlatformUtils::panic(const PanicHandler::PanicReasons reason) 00405 { 00406 fgUserPanicHandler? fgUserPanicHandler->panic(reason) : fgDefaultPanicHandler->panic(reason); 00407 } 00408 00409 00410 00411 // --------------------------------------------------------------------------- 00412 // XMLPlatformUtils: Private Static Methods 00413 // --------------------------------------------------------------------------- 00414 00415 XMLNetAccessor* XMLPlatformUtils::makeNetAccessor() 00416 { 00417 XMLNetAccessor* na = 0; 00418 00419 #if defined (XERCES_USE_NETACCESSOR_CURL) 00420 na = new CurlNetAccessor(); 00421 #elif defined (XERCES_USE_NETACCESSOR_SOCKET) 00422 na = new SocketNetAccessor(); 00423 #elif defined (XERCES_USE_NETACCESSOR_CFURL) 00424 na = new MacOSURLAccessCF(); 00425 #elif defined (XERCES_USE_NETACCESSOR_WINSOCK) 00426 na = new WinSockNetAccessor(); 00427 #endif 00428 00429 return na; 00430 } 00431 00432 00433 // 00434 // This method is called by the platform independent part of this class 00435 // when client code asks to have one of the supported message sets loaded. 00436 // 00437 00438 XMLMsgLoader* XMLPlatformUtils::loadAMsgSet(const XMLCh* const msgDomain) 00439 { 00440 XMLMsgLoader* ms=0; 00441 00442 try 00443 { 00444 #if defined (XERCES_USE_MSGLOADER_ICU) 00445 ms = new ICUMsgLoader(msgDomain); 00446 #elif defined (XERCES_USE_MSGLOADER_ICONV) 00447 ms = new MsgCatalogLoader(msgDomain); 00448 #elif defined (XERCES_USE_WIN32_MSGLOADER) 00449 ms = new Win32MsgLoader(msgDomain); 00450 #elif defined (XERCES_USE_MSGLOADER_INMEMORY) 00451 ms = new InMemMsgLoader(msgDomain); 00452 #else 00453 #error No MsgLoader configured for platform! You must configure it. 00454 #endif 00455 } 00456 catch(const OutOfMemoryException&) 00457 { 00458 throw; 00459 } 00460 catch(...) 00461 { 00462 panic(PanicHandler::Panic_CantLoadMsgDomain); 00463 } 00464 00465 return ms; 00466 } 00467 00468 00469 // 00470 // This method is called very early in the bootstrapping process. This guy 00471 // must create a transcoding service and return it. It cannot use any string 00472 // methods, any transcoding services, throw any exceptions, etc... It just 00473 // makes a transcoding service and returns it, or returns zero on failure. 00474 // 00475 00476 XMLTransService* XMLPlatformUtils::makeTransService() 00477 { 00478 XMLTransService* tc = 0; 00479 00480 #if defined (XERCES_USE_TRANSCODER_ICU) 00481 tc = new ICUTransService(fgMemoryManager); 00482 #elif defined (XERCES_USE_TRANSCODER_GNUICONV) 00483 tc = new IconvGNUTransService(fgMemoryManager); 00484 #elif defined (XERCES_USE_TRANSCODER_ICONV) 00485 tc = new IconvTransService(fgMemoryManager); 00486 #elif defined (XERCES_USE_TRANSCODER_MACOSUNICODECONVERTER) 00487 tc = new MacOSUnicodeConverter(fgMemoryManager); 00488 #elif defined (XERCES_USE_TRANSCODER_WINDOWS) 00489 tc = new Win32TransService(fgMemoryManager); 00490 #else 00491 #error No Transcoder configured for platform! You must configure it. 00492 #endif 00493 00494 return tc; 00495 } 00496 00497 00498 // --------------------------------------------------------------------------- 00499 // XMLPlatformUtils: File Methods 00500 // --------------------------------------------------------------------------- 00501 XMLFileMgr* 00502 XMLPlatformUtils::makeFileMgr(MemoryManager* const memmgr) 00503 { 00504 XMLFileMgr* mgr = NULL; 00505 00506 #if XERCES_USE_FILEMGR_POSIX 00507 mgr = new (memmgr) PosixFileMgr; 00508 #elif XERCES_USE_FILEMGR_WINDOWS 00509 mgr = new (memmgr) WindowsFileMgr; 00510 #else 00511 #error No File Manager configured for platform! You must configure it. 00512 #endif 00513 00514 return mgr; 00515 } 00516 00517 00518 FileHandle 00519 XMLPlatformUtils::openFile(const char* const fileName 00520 , MemoryManager* const memmgr) 00521 { 00522 if (!fgFileMgr) 00523 ThrowXMLwithMemMgr(XMLPlatformUtilsException, XMLExcepts::CPtr_PointerIsZero, memmgr); 00524 00525 return fgFileMgr->fileOpen(fileName, false, memmgr); 00526 } 00527 00528 00529 FileHandle 00530 XMLPlatformUtils::openFile(const XMLCh* const fileName, MemoryManager* const memmgr) 00531 { 00532 if (!fgFileMgr) 00533 ThrowXMLwithMemMgr(XMLPlatformUtilsException, XMLExcepts::CPtr_PointerIsZero, memmgr); 00534 00535 return fgFileMgr->fileOpen(fileName, false, memmgr); 00536 } 00537 00538 00539 FileHandle 00540 XMLPlatformUtils::openFileToWrite(const char* const fileName 00541 , MemoryManager* const memmgr) 00542 { 00543 if (!fgFileMgr) 00544 ThrowXMLwithMemMgr(XMLPlatformUtilsException, XMLExcepts::CPtr_PointerIsZero, memmgr); 00545 00546 return fgFileMgr->fileOpen(fileName, true, memmgr); 00547 } 00548 00549 00550 FileHandle 00551 XMLPlatformUtils::openFileToWrite(const XMLCh* const fileName 00552 , MemoryManager* const memmgr) 00553 { 00554 if (!fgFileMgr) 00555 ThrowXMLwithMemMgr(XMLPlatformUtilsException, XMLExcepts::CPtr_PointerIsZero, memmgr); 00556 00557 return fgFileMgr->fileOpen(fileName, true, memmgr); 00558 } 00559 00560 00561 FileHandle 00562 XMLPlatformUtils::openStdInHandle(MemoryManager* const memmgr) 00563 { 00564 if (!fgFileMgr) 00565 ThrowXMLwithMemMgr(XMLPlatformUtilsException, XMLExcepts::CPtr_PointerIsZero, memmgr); 00566 00567 return fgFileMgr->openStdIn(memmgr); 00568 } 00569 00570 00571 void 00572 XMLPlatformUtils::closeFile(FileHandle theFile 00573 , MemoryManager* const memmgr) 00574 { 00575 if (!fgFileMgr) 00576 ThrowXMLwithMemMgr(XMLPlatformUtilsException, XMLExcepts::CPtr_PointerIsZero, memmgr); 00577 00578 fgFileMgr->fileClose(theFile, memmgr); 00579 } 00580 00581 void 00582 XMLPlatformUtils::resetFile(FileHandle theFile 00583 , MemoryManager* const memmgr) 00584 { 00585 if (!fgFileMgr) 00586 ThrowXMLwithMemMgr(XMLPlatformUtilsException, XMLExcepts::CPtr_PointerIsZero, memmgr); 00587 00588 fgFileMgr->fileReset(theFile, memmgr); 00589 } 00590 00591 00592 XMLFilePos 00593 XMLPlatformUtils::curFilePos(FileHandle theFile 00594 , MemoryManager* const memmgr) 00595 { 00596 if (!fgFileMgr) 00597 ThrowXMLwithMemMgr(XMLPlatformUtilsException, XMLExcepts::CPtr_PointerIsZero, memmgr); 00598 00599 return fgFileMgr->curPos(theFile, memmgr); 00600 } 00601 00602 XMLFilePos 00603 XMLPlatformUtils::fileSize(FileHandle theFile 00604 , MemoryManager* const memmgr) 00605 { 00606 if (!fgFileMgr) 00607 ThrowXMLwithMemMgr(XMLPlatformUtilsException, XMLExcepts::CPtr_PointerIsZero, memmgr); 00608 00609 return fgFileMgr->fileSize(theFile, memmgr); 00610 } 00611 00612 00613 XMLSize_t 00614 XMLPlatformUtils::readFileBuffer( FileHandle theFile 00615 , const XMLSize_t toRead 00616 , XMLByte* const toFill 00617 , MemoryManager* const memmgr) 00618 { 00619 if (!fgFileMgr) 00620 ThrowXMLwithMemMgr(XMLPlatformUtilsException, XMLExcepts::CPtr_PointerIsZero, memmgr); 00621 00622 return fgFileMgr->fileRead(theFile, toRead, toFill, memmgr); 00623 } 00624 00625 00626 void 00627 XMLPlatformUtils::writeBufferToFile( const FileHandle theFile 00628 , XMLSize_t toWrite 00629 , const XMLByte* const toFlush 00630 , MemoryManager* const memmgr) 00631 { 00632 if (!fgFileMgr) 00633 ThrowXMLwithMemMgr(XMLPlatformUtilsException, XMLExcepts::CPtr_PointerIsZero, memmgr); 00634 00635 fgFileMgr->fileWrite(theFile, toWrite, toFlush, memmgr); 00636 } 00637 00638 00639 // --------------------------------------------------------------------------- 00640 // XMLPlatformUtils: File system methods 00641 // --------------------------------------------------------------------------- 00642 XMLCh* XMLPlatformUtils::getFullPath(const XMLCh* const srcPath, 00643 MemoryManager* const memmgr) 00644 { 00645 if (!fgFileMgr) 00646 ThrowXMLwithMemMgr(XMLPlatformUtilsException, XMLExcepts::CPtr_PointerIsZero, memmgr); 00647 00648 return fgFileMgr->getFullPath(srcPath, memmgr); 00649 } 00650 00651 00652 XMLCh* XMLPlatformUtils::getCurrentDirectory(MemoryManager* const memmgr) 00653 { 00654 if (!fgFileMgr) 00655 ThrowXMLwithMemMgr(XMLPlatformUtilsException, XMLExcepts::CPtr_PointerIsZero, memmgr); 00656 00657 return fgFileMgr->getCurrentDirectory(memmgr); 00658 } 00659 00660 00661 bool XMLPlatformUtils::isRelative(const XMLCh* const toCheck 00662 , MemoryManager* const memmgr) 00663 { 00664 if (!fgFileMgr) 00665 ThrowXMLwithMemMgr(XMLPlatformUtilsException, XMLExcepts::CPtr_PointerIsZero, memmgr); 00666 00667 return fgFileMgr->isRelative(toCheck, memmgr); 00668 } 00669 00670 00671 inline bool 00672 XMLPlatformUtils::isAnySlash(XMLCh c) 00673 { 00674 // As far as we know, all supported Xerces 00675 // platforms use at least a forward slash 00676 // as a path delimiter. So we always check for 00677 // that. 00678 // 00679 // If XERCES_PATH_DELIMITER_BACKSLASH evaluates to true, 00680 // we also consider that as a slash. 00681 // 00682 // XERCES_PATH_DELIMITER_BACKSLASH may be set in config.h 00683 // by configure, or elsewhere by platform-specific 00684 // code. 00685 return ( 00686 false 00687 || chForwardSlash == c 00688 #if XERCES_PATH_DELIMITER_BACKSLASH 00689 || chBackSlash == c 00690 #endif 00691 ); 00692 } 00693 00694 00695 // --------------------------------------------------------------------------- 00696 // XMLPlatformUtils: Timing Methods 00697 // --------------------------------------------------------------------------- 00698 unsigned long XMLPlatformUtils::getCurrentMillis() 00699 { 00700 unsigned long ms = 0; 00701 00702 // *** TODO: additional platform support? 00703 #if HAVE_GETTIMEOFDAY 00704 struct timeval aTime; 00705 gettimeofday(&aTime, NULL); 00706 ms = (unsigned long) (aTime.tv_sec * 1000 + aTime.tv_usec / 1000); 00707 #elif HAVE_FTIME 00708 timeb aTime; 00709 ftime(&aTime); 00710 ms = (unsigned long)(aTime.time*1000 + aTime.millitm); 00711 #else 00712 // Make this a warning instead? 00713 #error No timing support is configured for this platform. You must configure it. 00714 #endif 00715 00716 return ms; 00717 } 00718 00719 00720 // ----------------------------------------------------------------------- 00721 // Mutex methods 00722 // ----------------------------------------------------------------------- 00723 XMLMutexMgr* XMLPlatformUtils::makeMutexMgr(MemoryManager* const memmgr) 00724 { 00725 XMLMutexMgr* mgr = NULL; 00726 00727 #if XERCES_USE_MUTEXMGR_NOTHREAD 00728 mgr = new (memmgr) NoThreadMutexMgr; 00729 #elif XERCES_USE_MUTEXMGR_POSIX 00730 mgr = new (memmgr) PosixMutexMgr; 00731 #elif XERCES_USE_MUTEXMGR_WINDOWS 00732 mgr = new (memmgr) WindowsMutexMgr; 00733 #else 00734 #error No Mutex Manager configured for platform! You must configure it. 00735 #endif 00736 00737 return mgr; 00738 } 00739 00740 00741 XMLMutexHandle XMLPlatformUtils::makeMutex(MemoryManager* const memmgr) 00742 { 00743 if (!fgMutexMgr) 00744 XMLPlatformUtils::panic(PanicHandler::Panic_MutexErr); 00745 00746 return fgMutexMgr->create(memmgr); 00747 } 00748 00749 00750 void XMLPlatformUtils::closeMutex(XMLMutexHandle const mtx, MemoryManager* const memmgr) 00751 { 00752 if (!fgMutexMgr) 00753 XMLPlatformUtils::panic(PanicHandler::Panic_MutexErr); 00754 00755 fgMutexMgr->destroy(mtx, memmgr); 00756 } 00757 00758 00759 void XMLPlatformUtils::lockMutex(XMLMutexHandle const mtx) 00760 { 00761 if (!fgMutexMgr) 00762 XMLPlatformUtils::panic(PanicHandler::Panic_MutexErr); 00763 00764 fgMutexMgr->lock(mtx); 00765 } 00766 00767 00768 void XMLPlatformUtils::unlockMutex(XMLMutexHandle const mtx) 00769 { 00770 if (!fgMutexMgr) 00771 XMLPlatformUtils::panic(PanicHandler::Panic_MutexErr); 00772 00773 fgMutexMgr->unlock(mtx); 00774 } 00775 00776 // --------------------------------------------------------------------------- 00777 // XMLPlatformUtils: Msg support methods 00778 // --------------------------------------------------------------------------- 00779 XMLMsgLoader* XMLPlatformUtils::loadMsgSet(const XMLCh* const msgDomain) 00780 { 00781 // 00782 // Ask the platform support to load up the correct type of message 00783 // loader for the indicated message set. We don't check here whether it 00784 // works or not. That's their decision. 00785 // 00786 return loadAMsgSet(msgDomain); 00787 } 00788 00789 // --------------------------------------------------------------------------- 00790 // XMLPlatformUtils: NEL Character Handling 00791 // --------------------------------------------------------------------------- 00792 void XMLPlatformUtils::recognizeNEL(bool state, MemoryManager* const manager) { 00793 00794 //Make sure initialize has been called 00795 if (gInitFlag == 0) { 00796 return; 00797 } 00798 00799 if (state) { 00800 00801 if (!XMLChar1_0::isNELRecognized()) { 00802 XMLChar1_0::enableNELWS(); 00803 } 00804 } 00805 else { 00806 00807 if (XMLChar1_0::isNELRecognized()) { 00808 ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::NEL_RepeatedCalls, manager); 00809 } 00810 } 00811 } 00812 00813 00814 bool XMLPlatformUtils::isNELRecognized() { 00815 00816 return XMLChar1_0::isNELRecognized(); 00817 } 00818 00819 // --------------------------------------------------------------------------- 00820 // XMLPlatformUtils: IANA Encoding checking setting 00821 // --------------------------------------------------------------------------- 00822 void XMLPlatformUtils::strictIANAEncoding(const bool state) { 00823 00824 //Make sure initialize has been called 00825 if (gInitFlag == 0) { 00826 return; 00827 } 00828 00829 fgTransService->strictIANAEncoding(state); 00830 } 00831 00832 00833 bool XMLPlatformUtils::isStrictIANAEncoding() { 00834 00835 if (gInitFlag) 00836 return fgTransService->isStrictIANAEncoding(); 00837 00838 return false; 00839 } 00840 00841 /*** 00842 * 00843 * Previously, each <OS>PlatformUtils.cpp has its onw copy of the 00844 * method weavePaths(), and almost of them implemented the same logic, 00845 * with few platform specific difference, and unfortunately that 00846 * implementation was wrong. 00847 * 00848 * The only platform specific issue is slash character. 00849 * On all platforms other than Windows, chForwardSlash and chBackSlash 00850 * are considered slash, while on Windows, two additional characters, 00851 * chYenSign and chWonSign are slash as well. 00852 * 00853 * The idea is to maintain a SINGLE copy of this method rather than 00854 * each <OS>PlatformUtils.cpp has its own copy, we introduce a new 00855 * method, XMLPlatformUtils::isAnySlash(), to replace the direct checking 00856 * code ( if ( c == chForwardSlash || c == chBackSlash). 00857 * 00858 * With this approach, we might have a performance hit since isAnySlash() 00859 * is so frequently used in this implementation, so we intend to make it 00860 * inline. Then we face a complier issue. 00861 * 00862 * There are two compilation units involved, one is PlatformUtils.cpp and 00863 * the other <OS>PlatformUtils.cpp. When PlatformUtils.cp get compiled, 00864 * the weavePath(), remove**Slash() have dependency upon isAnySlash() which 00865 * is in <OS>PlatformUtils.cpp (and what is worse, it is inlined), so we have 00866 * undefined/unresolved symbol: isAnySlash() on AIX/xlc_r, Solaris/cc and 00867 * Linux/gcc, while MSVC and HP/aCC are fine with this. 00868 * 00869 * That means we can not place these new methods in PlatformUtils.cpp with 00870 * inlined XMLPlatformUtils::isAnySlash() in <OS>PlatformUtils.cpp. 00871 * 00872 * The solution to this is <os>PlatformUtils.cpp will include this file so that 00873 * we have only one copy of these methods while get compiled in <os>PlatformUtils 00874 * inlined isAnySlash(). 00875 * 00876 ***/ 00877 XMLCh* XMLPlatformUtils::weavePaths(const XMLCh* const basePath 00878 , const XMLCh* const relativePath 00879 , MemoryManager* const manager) 00880 00881 { 00882 // Create a buffer as large as both parts and empty it 00883 XMLCh* tmpBuf = (XMLCh*) manager->allocate 00884 ( 00885 (XMLString::stringLen(basePath) 00886 + XMLString::stringLen(relativePath) + 2) * sizeof(XMLCh) 00887 );//new XMLCh[XMLString::stringLen(basePath) + XMLString::stringLen(relativePath) + 2]; 00888 *tmpBuf = 0; 00889 00890 // 00891 // If we have no base path, then just take the relative path as is. 00892 // 00893 if ((!basePath) || (!*basePath)) 00894 { 00895 XMLString::copyString(tmpBuf, relativePath); 00896 return tmpBuf; 00897 } 00898 00899 // 00900 // Remove anything after the last slash 00901 // 00902 const XMLCh* basePtr = basePath + (XMLString::stringLen(basePath) - 1); 00903 while ((basePtr >= basePath) && ((isAnySlash(*basePtr) == false))) 00904 { 00905 basePtr--; 00906 } 00907 00908 // There is no relevant base path, so just take the relative part 00909 if (basePtr < basePath) 00910 { 00911 XMLString::copyString(tmpBuf, relativePath); 00912 return tmpBuf; 00913 } 00914 00915 // 00916 // 1. concatenate the base and relative 00917 // 2. remove all occurences of "/./" 00918 // 3. remove all occurences of segment/../ where segment is not ../ 00919 // 00920 00921 XMLString::subString(tmpBuf, basePath, 0, (basePtr - basePath + 1), manager); 00922 tmpBuf[basePtr - basePath + 1] = 0; 00923 XMLString::catString(tmpBuf, relativePath); 00924 00925 removeDotSlash(tmpBuf, manager); 00926 00927 removeDotDotSlash(tmpBuf, manager); 00928 00929 return tmpBuf; 00930 00931 } 00932 00933 // 00934 // Remove all occurences of './' when it is part of '/./' 00935 // 00936 // Since it could be '.\' or other combination on windows ( eg, '.'+chYanSign) 00937 // we can't make use of patterMatch(). 00938 // 00939 // 00940 void XMLPlatformUtils::removeDotSlash(XMLCh* const path 00941 , MemoryManager* const manager) 00942 { 00943 if ((!path) || (!*path)) 00944 return; 00945 00946 XMLCh* srcPtr = XMLString::replicate(path, manager); 00947 XMLSize_t srcLen = XMLString::stringLen(srcPtr); 00948 ArrayJanitor<XMLCh> janName(srcPtr, manager); 00949 XMLCh* tarPtr = path; 00950 00951 while (*srcPtr) 00952 { 00953 if ( 3 <= srcLen ) 00954 { 00955 if ( (isAnySlash(*srcPtr)) && 00956 (chPeriod == *(srcPtr+1)) && 00957 (isAnySlash(*(srcPtr+2))) ) 00958 { 00959 // "\.\x" seen 00960 // skip the first two, and start from the 3rd, 00961 // since "\x" could be another "\." 00962 srcPtr+=2; 00963 srcLen-=2; 00964 } 00965 else 00966 { 00967 *tarPtr++ = *srcPtr++; // eat the current char 00968 srcLen--; 00969 } 00970 } 00971 else if ( 1 == srcLen ) 00972 { 00973 *tarPtr++ = *srcPtr++; 00974 } 00975 else if ( 2 == srcLen) 00976 { 00977 *tarPtr++ = *srcPtr++; 00978 *tarPtr++ = *srcPtr++; 00979 } 00980 00981 } 00982 00983 *tarPtr = 0; 00984 00985 return; 00986 } 00987 00988 // 00989 // Remove all occurences of '/segment/../' when segment is not '..' 00990 // 00991 // Cases with extra /../ is left to the underlying file system. 00992 // 00993 void XMLPlatformUtils::removeDotDotSlash(XMLCh* const path 00994 , MemoryManager* const manager) 00995 { 00996 XMLSize_t pathLen = XMLString::stringLen(path); 00997 XMLCh* tmp1 = (XMLCh*) manager->allocate 00998 ( 00999 (pathLen+1) * sizeof(XMLCh) 01000 );//new XMLCh [pathLen+1]; 01001 ArrayJanitor<XMLCh> tmp1Name(tmp1, manager); 01002 01003 XMLCh* tmp2 = (XMLCh*) manager->allocate 01004 ( 01005 (pathLen+1) * sizeof(XMLCh) 01006 );//new XMLCh [pathLen+1]; 01007 ArrayJanitor<XMLCh> tmp2Name(tmp2, manager); 01008 01009 // remove all "<segment>/../" where "<segment>" is a complete 01010 // path segment not equal to ".." 01011 int index = -1; 01012 int segIndex = -1; 01013 int offset = 1; 01014 01015 while ((index = searchSlashDotDotSlash(&(path[offset]))) != -1) 01016 { 01017 // Undo offset 01018 index += offset; 01019 01020 // Find start of <segment> within substring ending at found point. 01021 XMLString::subString(tmp1, path, 0, index-1, manager); 01022 segIndex = index - 1; 01023 while ((segIndex >= 0) && (!isAnySlash(tmp1[segIndex]))) 01024 { 01025 segIndex--; 01026 } 01027 01028 // Ensure <segment> exists and != ".." 01029 if (segIndex >= 0 && 01030 (path[segIndex+1] != chPeriod || 01031 path[segIndex+2] != chPeriod || 01032 segIndex + 3 != index)) 01033 { 01034 01035 XMLString::subString(tmp1, path, 0, segIndex, manager); 01036 XMLString::subString(tmp2, path, index+3, XMLString::stringLen(path), manager); 01037 01038 path[0] = 0; 01039 XMLString::catString(path, tmp1); 01040 XMLString::catString(path, tmp2); 01041 01042 offset = (segIndex == 0 ? 1 : segIndex); 01043 } 01044 else 01045 { 01046 offset += 4; 01047 } 01048 01049 }// while 01050 01051 } 01052 01053 int XMLPlatformUtils::searchSlashDotDotSlash(XMLCh* const srcPath) 01054 { 01055 if ((!srcPath) || (!*srcPath)) 01056 return -1; 01057 01058 XMLCh* srcPtr = srcPath; 01059 XMLSize_t srcLen = XMLString::stringLen(srcPath); 01060 int retVal = -1; 01061 01062 while (*srcPtr) 01063 { 01064 if ( 4 <= srcLen ) 01065 { 01066 if ( (isAnySlash(*srcPtr)) && 01067 (chPeriod == *(srcPtr+1)) && 01068 (chPeriod == *(srcPtr+2)) && 01069 (isAnySlash(*(srcPtr+3))) ) 01070 { 01071 retVal = (int)(srcPtr - srcPath); 01072 break; 01073 } 01074 else 01075 { 01076 srcPtr++; 01077 srcLen--; 01078 } 01079 } 01080 else 01081 { 01082 break; 01083 } 01084 01085 } // while 01086 01087 return retVal; 01088 01089 } 01090 01091 01092 XERCES_CPP_NAMESPACE_END