1 /************************************************************** 2 * 3 * Licensed to the Apache Software Foundation (ASF) under one 4 * or more contributor license agreements. See the NOTICE file 5 * distributed with this work for additional information 6 * regarding copyright ownership. The ASF licenses this file 7 * to you under the Apache License, Version 2.0 (the 8 * "License"); you may not use this file except in compliance 9 * with the License. You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, 14 * software distributed under the License is distributed on an 15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 * KIND, either express or implied. See the License for the 17 * specific language governing permissions and limitations 18 * under the License. 19 * 20 *************************************************************/ 21 22 23 24 // MARKER(update_precomp.py): autogen include statement, do not remove 25 #include "precompiled_lingucomponent.hxx" 26 27 #include <iostream> 28 29 #include <tools/debug.hxx> 30 31 #include <sal/config.h> 32 #include <cppuhelper/factory.hxx> 33 #include <cppuhelper/implementationentry.hxx> 34 #include <cppuhelper/implbase2.hxx> 35 #include <tools/string.hxx> 36 37 #include <simpleguesser.hxx> 38 #include <guess.hxx> 39 40 //#include <cppuhelper/queryinterface.hxx> // helper for queryInterface() impl 41 42 //#include <com/sun/star/lang/XMultiServiceFactory.hpp> 43 #include <com/sun/star/registry/XRegistryKey.hpp> 44 #include <com/sun/star/lang/XServiceInfo.hpp> 45 #include <com/sun/star/linguistic2/XLanguageGuessing.hpp> 46 #include <unotools/pathoptions.hxx> 47 #include <unotools/localfilehelper.hxx> 48 #include <osl/thread.h> 49 50 using namespace ::rtl; 51 using namespace ::osl; 52 using namespace ::cppu; 53 using namespace ::com::sun::star; 54 using namespace ::com::sun::star::uno; 55 using namespace ::com::sun::star::lang; 56 using namespace ::com::sun::star::linguistic2; 57 58 namespace css = ::com::sun::star; 59 60 //================================================================================================== 61 62 #define A2OU(x) ::rtl::OUString::createFromAscii( x ) 63 64 #define SERVICENAME "com.sun.star.linguistic2.LanguageGuessing" 65 66 #define IMPLNAME "com.sun.star.lingu2.LanguageGuessing" 67 68 static Sequence< OUString > getSupportedServiceNames_LangGuess_Impl() 69 { 70 Sequence<OUString> names(1); 71 names[0] = A2OU( SERVICENAME ); 72 return names; 73 } 74 75 static OUString getImplementationName_LangGuess_Impl() 76 { 77 return A2OU( IMPLNAME ); 78 } 79 80 static osl::Mutex & GetLangGuessMutex() 81 { 82 static osl::Mutex aMutex; 83 return aMutex; 84 } 85 86 87 class LangGuess_Impl : 88 public ::cppu::WeakImplHelper2< 89 XLanguageGuessing, 90 XServiceInfo > 91 { 92 SimpleGuesser m_aGuesser; 93 bool m_bInitialized; 94 css::uno::Reference< css::uno::XComponentContext > m_xContext; 95 96 LangGuess_Impl( const LangGuess_Impl & ); // not defined 97 LangGuess_Impl & operator =( const LangGuess_Impl & ); // not defined 98 99 virtual ~LangGuess_Impl() {} 100 void EnsureInitialized(); 101 102 public: 103 explicit LangGuess_Impl(css::uno::Reference< css::uno::XComponentContext > const & rxContext); 104 105 // XServiceInfo implementation 106 virtual OUString SAL_CALL getImplementationName( ) throw(RuntimeException); 107 virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) throw(RuntimeException); 108 virtual Sequence< OUString > SAL_CALL getSupportedServiceNames( ) throw(RuntimeException); 109 static Sequence< OUString > SAL_CALL getSupportedServiceNames_Static( ); 110 111 // XLanguageGuessing implementation 112 virtual ::com::sun::star::lang::Locale SAL_CALL guessPrimaryLanguage( const ::rtl::OUString& aText, ::sal_Int32 nStartPos, ::sal_Int32 nLen ) throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException); 113 virtual void SAL_CALL disableLanguages( const ::com::sun::star::uno::Sequence< ::com::sun::star::lang::Locale >& aLanguages ) throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException); 114 virtual void SAL_CALL enableLanguages( const ::com::sun::star::uno::Sequence< ::com::sun::star::lang::Locale >& aLanguages ) throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException); 115 virtual ::com::sun::star::uno::Sequence< ::com::sun::star::lang::Locale > SAL_CALL getAvailableLanguages( ) throw (::com::sun::star::uno::RuntimeException); 116 virtual ::com::sun::star::uno::Sequence< ::com::sun::star::lang::Locale > SAL_CALL getEnabledLanguages( ) throw (::com::sun::star::uno::RuntimeException); 117 virtual ::com::sun::star::uno::Sequence< ::com::sun::star::lang::Locale > SAL_CALL getDisabledLanguages( ) throw (::com::sun::star::uno::RuntimeException); 118 119 // implementation specific 120 void SetFingerPrintsDB( const rtl::OUString &fileName ) throw (RuntimeException); 121 122 static const OUString & SAL_CALL getImplementationName_Static() throw(); 123 124 }; 125 126 //************************************************************************* 127 128 LangGuess_Impl::LangGuess_Impl(css::uno::Reference< css::uno::XComponentContext > const & rxContext) : 129 m_bInitialized( false ), 130 m_xContext( rxContext ) 131 { 132 } 133 134 //************************************************************************* 135 136 void LangGuess_Impl::EnsureInitialized() 137 { 138 if (!m_bInitialized) 139 { 140 // set this to true at the very start to prevent loops because of 141 // implicitly called functions below 142 m_bInitialized = true; 143 144 // set default fingerprint path to where those get installed 145 String aPhysPath; 146 String aURL( SvtPathOptions().GetFingerprintPath() ); 147 utl::LocalFileHelper::ConvertURLToPhysicalName( aURL, aPhysPath ); 148 #ifdef WNT 149 aPhysPath += '\\'; 150 #else 151 aPhysPath += '/'; 152 #endif 153 154 SetFingerPrintsDB( aPhysPath ); 155 156 // 157 // disable currently not functional languages... 158 // 159 struct LangCountry 160 { 161 const char *pLang; 162 const char *pCountry; 163 }; 164 LangCountry aDisable[] = 165 { 166 {"gv", ""}, {"sco", ""}, // no lang-id available yet... 167 // {"hy", ""}, {"drt", ""}, // 0 bytes fingerprints... 168 {"zh", "CN"}, {"zh", "TW"}, {"ja", ""}, {"ko", ""}, // not yet correct functional... 169 {"ka", ""}, {"hi", ""}, {"mr", ""}, {"ne", ""}, 170 {"sa", ""}, {"ta", ""}, {"th", ""}, 171 {"qu", ""}, {"yi", ""} 172 }; 173 sal_Int32 nNum = sizeof(aDisable) / sizeof(aDisable[0]); 174 Sequence< Locale > aDisableSeq( nNum ); 175 Locale *pDisableSeq = aDisableSeq.getArray(); 176 for (sal_Int32 i = 0; i < nNum; ++i) 177 { 178 Locale aLocale; 179 aLocale.Language = OUString::createFromAscii( aDisable[i].pLang ); 180 aLocale.Country = OUString::createFromAscii( aDisable[i].pCountry ); 181 pDisableSeq[i] = aLocale; 182 } 183 disableLanguages( aDisableSeq ); 184 DBG_ASSERT( nNum == getDisabledLanguages().getLength(), "size mismatch" ); 185 } 186 } 187 188 //************************************************************************* 189 190 /* TL: currently not part of the API 191 Sequence< com::sun::star::lang::Locale > SAL_CALL LangGuess_Impl::guessLanguages( 192 const rtl::OUString &rText, 193 sal_Int32 nStartPos, 194 sal_Int32 nLen ) 195 throw (RuntimeException) 196 { 197 Sequence< com::sun::star::lang::Locale > aRes; 198 199 OString o = OUStringToOString( rText, RTL_TEXTENCODING_UTF8 ); 200 vector<Guess> gs = m_aGuesser.GuessLanguage(o.pData->buffer); 201 202 aRes.realloc(gs.size()); 203 204 com::sun::star::lang::Locale *pRes = aRes.getArray(); 205 206 #ifdef DEBUG 207 std::cout << " We have " << gs.size() << " candidates" << std::endl; 208 #endif 209 210 for(int i = 0; i < gs.size() ; i++ ){ 211 com::sun::star::lang::Locale current_aRes; 212 213 current_aRes.Language = A2OU( gs[i].getLanguage().c_str() ); 214 current_aRes.Country = A2OU( gs[i].getCountry().c_str() ); 215 216 pRes[i] = current_aRes; 217 } 218 219 return aRes; 220 } 221 */ 222 //************************************************************************* 223 224 Locale SAL_CALL LangGuess_Impl::guessPrimaryLanguage( 225 const ::rtl::OUString& rText, 226 ::sal_Int32 nStartPos, 227 ::sal_Int32 nLen ) 228 throw (lang::IllegalArgumentException, uno::RuntimeException) 229 { 230 osl::MutexGuard aGuard( GetLangGuessMutex() ); 231 232 EnsureInitialized(); 233 234 lang::Locale aRes; 235 if (nStartPos >=0 && nLen >= 0 && nStartPos + nLen <= rText.getLength()) 236 { 237 OString o( OUStringToOString( rText.copy(nStartPos, nLen), RTL_TEXTENCODING_UTF8 ) ); 238 Guess g = m_aGuesser.GuessPrimaryLanguage((char*)o.getStr()); 239 aRes.Language = OUString::createFromAscii(g.GetLanguage().c_str()); 240 aRes.Country = OUString::createFromAscii(g.GetCountry().c_str()); 241 } 242 else 243 throw lang::IllegalArgumentException(); 244 245 return aRes; 246 } 247 248 //************************************************************************* 249 #define DEFAULT_CONF_FILE_NAME "fpdb.conf" 250 251 void LangGuess_Impl::SetFingerPrintsDB( 252 const rtl::OUString &filePath ) 253 throw (RuntimeException) 254 { 255 //! text encoding for file name / path needs to be in the same encoding the OS uses 256 OString path = OUStringToOString( filePath, osl_getThreadTextEncoding() ); 257 OString conf_file_name( DEFAULT_CONF_FILE_NAME ); 258 OString conf_file_path(path); 259 conf_file_path += conf_file_name; 260 261 //cout << "Conf file : " << conf_file_path.getStr() << " directory : " << path.getStr() << endl; 262 263 m_aGuesser.SetDBPath((const char*)conf_file_path.getStr(), (const char*)path.getStr()); 264 } 265 266 //************************************************************************* 267 uno::Sequence< Locale > SAL_CALL LangGuess_Impl::getAvailableLanguages( ) 268 throw (uno::RuntimeException) 269 { 270 osl::MutexGuard aGuard( GetLangGuessMutex() ); 271 272 EnsureInitialized(); 273 274 Sequence< com::sun::star::lang::Locale > aRes; 275 vector<Guess> gs = m_aGuesser.GetAllManagedLanguages(); 276 aRes.realloc(gs.size()); 277 278 com::sun::star::lang::Locale *pRes = aRes.getArray(); 279 280 for(size_t i = 0; i < gs.size() ; i++ ){ 281 com::sun::star::lang::Locale current_aRes; 282 current_aRes.Language = A2OU( gs[i].GetLanguage().c_str() ); 283 current_aRes.Country = A2OU( gs[i].GetCountry().c_str() ); 284 pRes[i] = current_aRes; 285 } 286 287 return aRes; 288 } 289 290 //************************************************************************* 291 uno::Sequence< Locale > SAL_CALL LangGuess_Impl::getEnabledLanguages( ) 292 throw (uno::RuntimeException) 293 { 294 osl::MutexGuard aGuard( GetLangGuessMutex() ); 295 296 EnsureInitialized(); 297 298 Sequence< com::sun::star::lang::Locale > aRes; 299 vector<Guess> gs = m_aGuesser.GetAvailableLanguages(); 300 aRes.realloc(gs.size()); 301 302 com::sun::star::lang::Locale *pRes = aRes.getArray(); 303 304 for(size_t i = 0; i < gs.size() ; i++ ){ 305 com::sun::star::lang::Locale current_aRes; 306 current_aRes.Language = A2OU( gs[i].GetLanguage().c_str() ); 307 current_aRes.Country = A2OU( gs[i].GetCountry().c_str() ); 308 pRes[i] = current_aRes; 309 } 310 311 return aRes; 312 } 313 314 //************************************************************************* 315 uno::Sequence< Locale > SAL_CALL LangGuess_Impl::getDisabledLanguages( ) 316 throw (uno::RuntimeException) 317 { 318 osl::MutexGuard aGuard( GetLangGuessMutex() ); 319 320 EnsureInitialized(); 321 322 Sequence< com::sun::star::lang::Locale > aRes; 323 vector<Guess> gs = m_aGuesser.GetUnavailableLanguages(); 324 aRes.realloc(gs.size()); 325 326 com::sun::star::lang::Locale *pRes = aRes.getArray(); 327 328 for(size_t i = 0; i < gs.size() ; i++ ){ 329 com::sun::star::lang::Locale current_aRes; 330 current_aRes.Language = A2OU( gs[i].GetLanguage().c_str() ); 331 current_aRes.Country = A2OU( gs[i].GetCountry().c_str() ); 332 pRes[i] = current_aRes; 333 } 334 335 return aRes; 336 } 337 338 //************************************************************************* 339 void SAL_CALL LangGuess_Impl::disableLanguages( 340 const uno::Sequence< Locale >& rLanguages ) 341 throw (lang::IllegalArgumentException, uno::RuntimeException) 342 { 343 osl::MutexGuard aGuard( GetLangGuessMutex() ); 344 345 EnsureInitialized(); 346 347 sal_Int32 nLanguages = rLanguages.getLength(); 348 const Locale *pLanguages = rLanguages.getConstArray(); 349 350 for (sal_Int32 i = 0; i < nLanguages; ++i) 351 { 352 string language; 353 354 OString l = OUStringToOString( pLanguages[i].Language, RTL_TEXTENCODING_ASCII_US ); 355 OString c = OUStringToOString( pLanguages[i].Country, RTL_TEXTENCODING_ASCII_US ); 356 357 language += l.getStr(); 358 language += "-"; 359 language += c.getStr(); 360 m_aGuesser.DisableLanguage(language); 361 } 362 } 363 364 //************************************************************************* 365 void SAL_CALL LangGuess_Impl::enableLanguages( 366 const uno::Sequence< Locale >& rLanguages ) 367 throw (lang::IllegalArgumentException, uno::RuntimeException) 368 { 369 osl::MutexGuard aGuard( GetLangGuessMutex() ); 370 371 EnsureInitialized(); 372 373 sal_Int32 nLanguages = rLanguages.getLength(); 374 const Locale *pLanguages = rLanguages.getConstArray(); 375 376 for (sal_Int32 i = 0; i < nLanguages; ++i) 377 { 378 string language; 379 380 OString l = OUStringToOString( pLanguages[i].Language, RTL_TEXTENCODING_ASCII_US ); 381 OString c = OUStringToOString( pLanguages[i].Country, RTL_TEXTENCODING_ASCII_US ); 382 383 language += l.getStr(); 384 language += "-"; 385 language += c.getStr(); 386 m_aGuesser.EnableLanguage(language); 387 } 388 } 389 390 //************************************************************************* 391 OUString SAL_CALL LangGuess_Impl::getImplementationName( ) 392 throw(RuntimeException) 393 { 394 osl::MutexGuard aGuard( GetLangGuessMutex() ); 395 return A2OU( IMPLNAME ); 396 } 397 398 //************************************************************************* 399 sal_Bool SAL_CALL LangGuess_Impl::supportsService( const OUString& ServiceName ) 400 throw(RuntimeException) 401 { 402 osl::MutexGuard aGuard( GetLangGuessMutex() ); 403 Sequence< OUString > aSNL = getSupportedServiceNames(); 404 const OUString * pArray = aSNL.getArray(); 405 for( sal_Int32 i = 0; i < aSNL.getLength(); i++ ) 406 if( pArray[i] == ServiceName ) 407 return sal_True; 408 return sal_False; 409 } 410 411 //************************************************************************* 412 Sequence<OUString> SAL_CALL LangGuess_Impl::getSupportedServiceNames( ) 413 throw(RuntimeException) 414 { 415 osl::MutexGuard aGuard( GetLangGuessMutex() ); 416 return getSupportedServiceNames_Static(); 417 } 418 419 //************************************************************************* 420 Sequence<OUString> SAL_CALL LangGuess_Impl::getSupportedServiceNames_Static( ) 421 { 422 OUString aName( A2OU( SERVICENAME ) ); 423 return Sequence< OUString >( &aName, 1 ); 424 } 425 426 //************************************************************************* 427 428 429 /** 430 * Function to create a new component instance; is needed by factory helper implementation. 431 * @param xMgr service manager to if the components needs other component instances 432 */ 433 Reference< XInterface > SAL_CALL LangGuess_Impl_create( 434 Reference< XComponentContext > const & xContext ) 435 SAL_THROW( () ) 436 { 437 return static_cast< ::cppu::OWeakObject * >( new LangGuess_Impl(xContext) ); 438 } 439 440 //################################################################################################## 441 //#### EXPORTED ### functions to allow for registration and creation of the UNO component 442 //################################################################################################## 443 444 static struct ::cppu::ImplementationEntry s_component_entries [] = 445 { 446 { 447 LangGuess_Impl_create, getImplementationName_LangGuess_Impl, 448 getSupportedServiceNames_LangGuess_Impl, 449 ::cppu::createSingleComponentFactory, 450 0, 0 451 }, 452 { 0, 0, 0, 0, 0, 0 } 453 }; 454 455 extern "C" 456 { 457 458 void SAL_CALL component_getImplementationEnvironment( 459 sal_Char const ** ppEnvTypeName, uno_Environment ** /*ppEnv*/ ) 460 { 461 *ppEnvTypeName = CPPU_CURRENT_LANGUAGE_BINDING_NAME; 462 } 463 464 void * SAL_CALL component_getFactory( 465 sal_Char const * implName, lang::XMultiServiceFactory * xMgr, 466 registry::XRegistryKey * xRegistry ) 467 { 468 return ::cppu::component_getFactoryHelper( 469 implName, xMgr, xRegistry, s_component_entries ); 470 } 471 472 } 473 474