merge the formfield patch from ooo-build
[ooovba.git] / connectivity / source / drivers / evoab / LDriver.cxx
blobbc11ee5395df1b0fbf6f4164fd84f039941ba2ce
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: LDriver.cxx,v $
10 * $Revision: 1.10.42.1 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_connectivity.hxx"
33 #include "LDriver.hxx"
34 #include "LConnection.hxx"
35 #include <com/sun/star/lang/DisposedException.hpp>
36 #include "connectivity/dbexception.hxx"
37 #include "LConfigAccess.hxx"
38 #include <osl/file.hxx>
39 #include "osl/security.hxx"
40 #include <comphelper/processfactory.hxx>
41 #include <com/sun/star/ucb/XCommandEnvironment.hpp>
42 #include <ucbhelper/content.hxx>
43 #include <tools/debug.hxx>
44 #include "resource/common_res.hrc"
45 #include "resource/sharedresources.hxx"
46 #include "LDebug.hxx"
48 using namespace osl;
49 using namespace connectivity::evoab;
50 using namespace connectivity::file;
51 using namespace ::com::sun::star::uno;
52 using namespace ::com::sun::star::beans;
53 using namespace ::com::sun::star::sdbcx;
54 using namespace ::com::sun::star::sdbc;
55 using namespace ::com::sun::star::lang;
56 using namespace ::com::sun::star::ucb;
58 // --------------------------------------------------------------------------------
59 OEvoabDriver::OEvoabDriver(const Reference< XMultiServiceFactory >& _rxFactory) : OFileDriver(_rxFactory)
60 ,m_aTempDir(NULL, sal_True)
61 ,m_aFolderListName(::rtl::OUString::createFromAscii(getEVOAB_FOLDERLIST_FILE_NAME()))
62 ,m_aVersionName(::rtl::OUString::createFromAscii(getEVOAB_VERSION_FILE_NAME()))
63 ,m_aFileExt(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(getEVOAB_META_FILE_EXT())))
64 ,m_bWorkingDirCreated(sal_False)
65 ,m_eSupportedEvoVersion( eUnknown )
67 m_aEvoab_CLI_FullPathCommand = getFullPathExportingCommand(_rxFactory);
69 if ( m_aEvoab_CLI_FullPathCommand.getLength() == 0 )
70 m_aEvoab_CLI_FullPathCommand = ::rtl::OUString::createFromAscii(getEVOAB_CLI_FULLPATHCOMMAND());
71 if ( m_aEvoab_CLI_FullPathCommand.copy(0,7) != ::rtl::OUString::createFromAscii("file://") && m_aEvoab_CLI_FullPathCommand.copy(0,1) == ::rtl::OUString::createFromAscii("/"))
72 m_aEvoab_CLI_FullPathCommand = ::rtl::OUString::createFromAscii("file://") + m_aEvoab_CLI_FullPathCommand;
73 m_aEvoab_CLI_EffectiveCommand = m_aEvoab_CLI_FullPathCommand;
74 m_aTempDir.EnableKillingFile();
76 EVO_TRACE_STRING("OEvoabDriver::OEvoabDriver()::m_aEvoab_CLI_FullPathCommand = %s", m_aEvoab_CLI_FullPathCommand );
78 // static ServiceInfo
79 //------------------------------------------------------------------------------
80 rtl::OUString OEvoabDriver::getImplementationName_Static( ) throw(RuntimeException)
82 return rtl::OUString::createFromAscii(EVOAB_DRIVER_IMPL_NAME);
85 //------------------------------------------------------------------
86 ::rtl::OUString SAL_CALL OEvoabDriver::getImplementationName( ) throw(RuntimeException)
88 return getImplementationName_Static();
91 //------------------------------------------------------------------
92 ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > SAL_CALL connectivity::evoab::OEvoabDriver_CreateInstance(const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& _rxFactory) throw( ::com::sun::star::uno::Exception )
94 return *(new OEvoabDriver(_rxFactory));
96 // --------------------------------------------------------------------------------
97 Reference< XConnection > SAL_CALL OEvoabDriver::connect( const ::rtl::OUString& url, const Sequence< PropertyValue >& info ) throw(SQLException, RuntimeException)
99 ::osl::MutexGuard aGuard( m_aMutex );
100 if (ODriver_BASE::rBHelper.bDisposed)
101 throw DisposedException();
103 if ( ! acceptsURL(url) )
104 return NULL;
106 OEvoabConnection* pCon = new OEvoabConnection(this);
107 pCon->construct(url,info);
108 Reference< XConnection > xCon = pCon;
109 m_xConnections.push_back(WeakReferenceHelper(*pCon));
111 return xCon;
113 // --------------------------------------------------------------------------------
114 namespace
116 ::rtl::OUString lcl_translateProcessErrorMessage( oslProcessError nProcErr)
118 ::rtl::OUString sProcErr = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" not executed!."));
119 switch (nProcErr)
121 case osl_Process_E_None:
122 sProcErr = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" executed sucessful!"));
123 break;
124 case osl_Process_E_NotFound:
125 sProcErr = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" executed failed: not found!"));
126 break;
127 case osl_Process_E_NoPermission:
128 sProcErr = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" executed failed: has no permission!"));
129 break;
130 case osl_Process_E_TimedOut:
131 sProcErr = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" executed failed: time out!"));
132 break;
133 case osl_Process_E_Unknown:
134 sProcErr = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" executed failed: unkown reason!"));
135 break;
136 case osl_Process_E_InvalidError:
137 sProcErr = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" executed failed: invalid error!"));
138 break;
139 default:
140 sProcErr = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" executed failed: other reason!"));
142 return sProcErr;
144 oslProcessError lcl_execute( const ::rtl::OUString& _rCommand, ::rtl::OUString& _rArgument,
145 const ::rtl::OUString& _rWorkingDir, oslProcessOption _nOptions, oslFileHandle& /*[out]*/ _hStdOut )
147 oslProcessError nError = osl_Process_E_None;
149 EVO_TRACE_STRING("LDriver.cxx::lcl_execute: command : %s", _rCommand );
150 EVO_TRACE_STRING("LDriver.cxx::lcl_execute: argument : %s", _rArgument );
151 EVO_TRACE_STRING("LDriver.cxx::lcl_execute: working dir: %s", _rWorkingDir );
153 oslProcess hProcess( 0 );
155 nError = osl_executeProcess_WithRedirectedIO(
156 _rCommand.pData,
157 &_rArgument.pData,
159 _nOptions,
161 _rWorkingDir.pData,
164 &hProcess,
165 NULL,
166 &_hStdOut,
167 NULL
169 ::rtl::OUString sError = _rCommand + lcl_translateProcessErrorMessage( nError);
170 EVO_TRACE_STRING( "%s", sError );
172 if ( nError == osl_Process_E_None )
174 TimeValue aFiveSeconds;
175 aFiveSeconds.Seconds = 5;
176 aFiveSeconds.Nanosec = 0;
177 oslProcessError nWaitForProcessError = osl_joinProcessWithTimeout( hProcess, &aFiveSeconds );
178 if ( osl_Process_E_None != nWaitForProcessError )
180 nError = nWaitForProcessError;
181 // TODO: kill the running process?
183 osl_freeProcessHandle( hProcess );
185 return nError;
189 // --------------------------------------------------------------------------------
190 sal_Bool SAL_CALL OEvoabDriver::acceptsURL( const ::rtl::OUString& url )
191 throw(SQLException, RuntimeException)
193 sal_Bool bRet;
194 bRet = sal_False;
195 // here we have to look if we support this url format
196 if(acceptsURL_Stat(url))
198 if ( m_eSupportedEvoVersion != eUnknown )
199 return m_eSupportedEvoVersion == eTrue ? sal_True : sal_False;
201 if(!m_bWorkingDirCreated)
203 String sTempDirURL = getTempDirURL();
204 //EVO_TRACE_STRING("OEvoabDriver::acceptsURL()::sTempDirURL = %s", sTempDirURL );
206 ::rtl::OUString aTempDirURL(sTempDirURL);
207 m_aWorkingDirURL = aTempDirURL;
208 m_bWorkingDirCreated = sal_True;
211 ::rtl::OUString aCLICommand = getEvoab_CLI_EffectiveCommand();
212 ::rtl::OUString aWorkingDirURL = getWorkingDirURL();
213 ::rtl::OUString aArgVersion = ::rtl::OUString::createFromAscii(getEVOAB_CLI_ARG_VERSION());
215 oslFileHandle hStdout = NULL;
216 oslProcessError nProcErr = lcl_execute( aCLICommand, aArgVersion, aWorkingDirURL, 0, hStdout );
217 if(nProcErr != osl_Process_E_None)
219 if(doesEvoab_CLI_HavePath())
220 aCLICommand = getEvoab_CLI_Command();
221 else
222 aCLICommand = getEvoab_CLI_Path() + getEvoab_CLI_Command();
223 nProcErr = lcl_execute( aCLICommand, aArgVersion, aWorkingDirURL, osl_Process_SEARCHPATH | osl_Process_HIDDEN, hStdout );
224 if ( nProcErr == osl_Process_E_None )
225 m_aEvoab_CLI_EffectiveCommand = aCLICommand;
228 if ( hStdout != NULL )
230 OSL_ASSERT( hStdout );
231 sal_Char pBuffer[256];
232 sal_uInt64 nBytesRead;
233 oslFileError nFileErr = osl_File_E_None;
234 nFileErr = osl_readFile( hStdout, pBuffer, 256, &nBytesRead);
235 if ( nFileErr != osl_File_E_None )
237 ::rtl::OUString sErr = translateFileErrorMessage( nFileErr);
238 OSL_ENSURE(false, ::rtl::OUStringToOString( sErr, RTL_TEXTENCODING_ASCII_US ).getStr());
240 ::rtl::OUString aVersionInfo;
241 if ( nFileErr == osl_File_E_None && nBytesRead > 0 && nBytesRead <= 256)
243 OSL_TRACE("OEvoabDriver::acceptsURL()::osl_readFile(),nBytesRead = %u",nBytesRead);
244 aVersionInfo =
245 ::rtl::OUString( ( const sal_Char * )pBuffer,
246 (sal_Int32)nBytesRead,
247 RTL_TEXTENCODING_UTF8 );
248 EVO_TRACE_STRING("OEvoabDriver::acceptsURL()::aVersionInfo = %s", aVersionInfo );
249 sal_Int32 nIndex = 0;
250 sal_Bool bNumRetrieved = sal_False;
251 ::rtl::OUString aToken;
252 sal_Int32 aVer[4];
253 sal_Int32 i;
254 for ( i = 0; i < 4; i++ )
255 aVer[i] = 0;
258 aToken = aVersionInfo.getToken( 0, ' ', nIndex );
259 //OSL_TRACE("OEvoabDriver::acceptsURL()::Token:%d", nIndex );
260 //EVO_TRACE_STRING("OEvoabDriver::acceptsURL()::aToken = %s", aToken );
261 if( aToken.toChar() >= '0' && aToken.toChar() <= '9' )
263 bNumRetrieved = sal_True;
264 sal_Int32 nIndex1 = 0;
265 ::rtl::OUString aNum;
266 for(i = 0; i < 4 ; i++)
268 if( nIndex1 >= 0 )
270 aNum = aToken.getToken( 0, '.', nIndex1);
271 aVer[i] = aNum.toInt32();
272 OSL_TRACE("OEvoabDriver::acceptsURL()::Ver[%u]=%u", i, aVer[i] );
277 while ( nIndex >= 0 && !bNumRetrieved );
279 if((aVer[0]>1)||(aVer[0]==1 && aVer[1]>3)||(aVer[0]==1 && aVer[1]==3 && aVer[2]>2)||(aVer[0]==1 && aVer[1]==3 && aVer[2]==2 && aVer[3]>=99))
280 bRet = sal_True;
281 else
282 bRet = sal_False;
284 else
285 bRet = sal_False;
287 osl_closeFile( hStdout );
289 m_eSupportedEvoVersion = bRet ? eTrue : eFalse;
291 EVO_TRACE_STRING("OEvoabDriver::acceptsURL()::return, return value = %s", ::rtl::OUString::valueOf(bRet) );
292 return bRet;
296 // --------------------------------------------------------------------------------
297 sal_Bool OEvoabDriver::acceptsURL_Stat( const ::rtl::OUString& url )
300 EVO_TRACE_STRING("OEvoabDriver::acceptsURL_Stat()::Scheme = %s", url );
301 // Skip 'sdbc:address: part of URL
303 sal_Int32 nLen = url.indexOf(':');
304 nLen = url.indexOf(':',nLen+1);
305 ::rtl::OUString aAddrbookURI(url.copy(nLen+1));
307 // Get Scheme
308 nLen = aAddrbookURI.indexOf(':');
309 ::rtl::OUString aAddrbookScheme;
310 if ( nLen == -1 )
312 // There isn't any subschema: - but could be just subschema
313 if ( aAddrbookURI.getLength() > 0 )
314 aAddrbookScheme= aAddrbookURI;
315 else if(url == ::rtl::OUString::createFromAscii("sdbc:address:") )
316 return sal_True; // special case here
317 else
318 return sal_False;
320 else
321 aAddrbookScheme = aAddrbookURI.copy(0, nLen);
324 EVO_TRACE_STRING("OEvoabDriver::acceptsURL_Stat()::URI = %s", aAddrbookURI );
325 EVO_TRACE_STRING("OEvoabDriver::acceptsURL_Stat()::Scheme = %s", aAddrbookScheme );
327 return aAddrbookScheme.compareToAscii( getSDBC_SCHEME_EVOLUTION() ) == 0 ;
329 // -------------------------------------------------------------------------
330 const rtl::OUString OEvoabDriver::getEvoab_CLI_Command() const
332 rtl::OUString aEvoab_CLI_Command;
333 sal_Int32 nLen = m_aEvoab_CLI_FullPathCommand.lastIndexOf('/');
335 if ( nLen == -1 )
336 aEvoab_CLI_Command = m_aEvoab_CLI_FullPathCommand;
337 else
338 aEvoab_CLI_Command = m_aEvoab_CLI_FullPathCommand.copy(nLen+1);
340 EVO_TRACE_STRING( "OEvoabDriver::getEvoab_CLI_Command()::aEvoab_CLI_Command = %s", aEvoab_CLI_Command );
342 return aEvoab_CLI_Command;
344 // -------------------------------------------------------------------------
345 const rtl::OUString OEvoabDriver::getEvoab_CLI_Path() const
347 rtl::OUString aEvoab_CLI_Path;
348 sal_Int32 nLen = m_aEvoab_CLI_FullPathCommand.lastIndexOf('/');
350 if ( nLen == -1 )
352 rtl::OUString aDefault_CLI_FullPathCommand;
353 aDefault_CLI_FullPathCommand = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(OEvoabDriver::getEVOAB_CLI_FULLPATHCOMMAND()));
354 sal_Int32 nLength = aDefault_CLI_FullPathCommand.lastIndexOf('/');
355 aEvoab_CLI_Path = aDefault_CLI_FullPathCommand.copy(0, nLength+1);
357 else
358 aEvoab_CLI_Path = m_aEvoab_CLI_FullPathCommand.copy(0, nLen+1);
359 EVO_TRACE_STRING( "OEvoabDriver::getEvoab_CLI_Path()::aEvoab_CLI_Path = %s", aEvoab_CLI_Path );
361 return aEvoab_CLI_Path;
363 // -------------------------------------------------------------------------
364 const rtl::OUString OEvoabDriver::getWorkingDirPath() const
366 ::rtl::OUString aWorkingDirPath;
367 if(m_bWorkingDirCreated)
368 osl::File::getSystemPathFromFileURL( m_aWorkingDirURL, aWorkingDirPath );
369 return aWorkingDirPath;
371 // -------------------------------------------------------------------------
372 const String OEvoabDriver::getEvoFolderListFileURL() const
375 ::rtl::OUString aEvoFolderListFileURL;
376 aEvoFolderListFileURL = getWorkingDirURL() + getEvoFolderListFileName();
378 EVO_TRACE_STRING("OEvoabDriver::getEvoFolderListFileURL(): aEvoFolderListFileURL = %s", aEvoFolderListFileURL );
379 return aEvoFolderListFileURL.getStr();
382 // -------------------------------------------------------------------------
383 String OEvoabDriver::getTempDirURL() const
385 ::rtl::OUString aTempDirURL;
386 aTempDirURL = m_aTempDir.GetURL();
387 if((aTempDirURL.lastIndexOf( '/')) != (aTempDirURL.getLength( ) - 1))
388 aTempDirURL += ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("/"));
390 EVO_TRACE_STRING("OEvoabDriver::getTempDirURL(): aTempDirURL = %s", aTempDirURL );
391 return aTempDirURL.getStr();
393 //-------------------------------------------------------------------------
394 sal_Bool OEvoabDriver::fileExists(const ::rtl::OUString& _rURL, sal_Bool _bIsDir) const
396 ::ucbhelper::Content aCheckExistence;
397 sal_Bool bExists = sal_False;
400 aCheckExistence = ::ucbhelper::Content(_rURL, Reference< XCommandEnvironment >());
401 if(_bIsDir)
402 bExists = aCheckExistence.isFolder();
403 else
404 bExists = aCheckExistence.isDocument();
406 catch(const Exception&) { }
407 return bExists;
410 // -----------------------------------------------------------------------------
411 const sal_Char* OEvoabDriver::getSDBC_SCHEME_EVOLUTION()
413 static const sal_Char* SDBC_SCHEME_EVOLUTION = EVOAB_EVOLUTION_SCHEMA;
414 return SDBC_SCHEME_EVOLUTION;
416 const sal_Char* OEvoabDriver::getEVOAB_FOLDERLIST_FILE_NAME()
418 static const sal_Char* EVOAB_FOLDERLIST_FILE_NAME = "FolderList";
419 return EVOAB_FOLDERLIST_FILE_NAME;
421 const sal_Char* OEvoabDriver::getEVOAB_VERSION_FILE_NAME()
423 static const sal_Char* EVOAB_VERSION_FILE_NAME = "EvoVersion";
424 return EVOAB_VERSION_FILE_NAME;
426 const sal_Char* OEvoabDriver::getEVOAB_META_FILE_EXT()
428 static const sal_Char* EVOAB_META_FILE_EXT = "csv";
429 return EVOAB_META_FILE_EXT;
431 const sal_Char* OEvoabDriver::getEVOAB_CLI_FULLPATHCOMMAND()
433 static const sal_Char* EVOAB_CLI_FULLPATHCOMMAND = "file:///home/evoab/extra/share/evolution/*/tools/evolution-addressbook-export";
434 return EVOAB_CLI_FULLPATHCOMMAND;
436 const sal_Char* OEvoabDriver::getEVOAB_CLI_ARG_LIST_FOLDERS()
438 static const sal_Char* EVOAB_CLI_ARG_LIST_FOLDERS = "-l";
439 return EVOAB_CLI_ARG_LIST_FOLDERS;
441 const sal_Char* OEvoabDriver::getEVOAB_CLI_ARG_OUTPUT_FILE_PREFIX()
443 static const sal_Char* EVOAB_CLI_ARG_OUTPUT_FILE_PREFIX = "--output=";
444 return EVOAB_CLI_ARG_OUTPUT_FILE_PREFIX;
446 const sal_Char* OEvoabDriver::getEVOAB_CLI_ARG_OUTPUT_FORMAT()
448 static const sal_Char* EVOAB_CLI_ARG_OUTPUT_FORMAT = "--format=csv";
449 return EVOAB_CLI_ARG_OUTPUT_FORMAT;
451 const sal_Char* OEvoabDriver::getEVOAB_CLI_ARG_VERSION()
453 static const sal_Char* EVOAB_CLI_ARG_VERSION = "--version";
454 return EVOAB_CLI_ARG_VERSION;
456 const sal_Char* OEvoabDriver::getEVOAB_CLI_ARG_OUTPUT_REDIRECT()
458 static const sal_Char* EVOAB_CLI_ARG_OUTPUT_REDIRECT = ">";
459 return EVOAB_CLI_ARG_OUTPUT_REDIRECT;
461 rtl::OUString OEvoabDriver::translateFileErrorMessage( oslFileError nFileErr)
463 ::rtl::OUString sFileErr = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" no file operation!."));
464 switch (nFileErr)
466 case osl_File_E_None:
467 sFileErr = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" File operation succeeded!"));
468 break;
469 case osl_File_E_INVAL:
470 sFileErr = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" File operation failed: the format of the parameters was not valid!"));
471 break;
472 case osl_File_E_INTR:
473 sFileErr = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" File operation failed: function call was interrupted!"));
474 break;
475 case osl_File_E_IO:
476 sFileErr = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" File operation failed: I/O errors!"));
477 break;
478 case osl_File_E_ISDIR:
479 sFileErr = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" File operation failed: is a directory!"));
480 break;
481 case osl_File_E_BADF:
482 sFileErr = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" File operation failed: bad file!"));
483 break;
484 case osl_File_E_FAULT:
485 sFileErr = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" File operation failed: bad address!"));
486 break;
487 case osl_File_E_AGAIN:
488 sFileErr = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" File operation failed: operation would block!"));
489 break;
490 case osl_File_E_NOLINK:
491 sFileErr = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" File operation failed: link has been severed!"));
492 break;
493 default:
494 sFileErr = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" File operation failed: other reason!"));
496 return sFileErr;
498 // -----------------------------------------------------------------------------
499 Sequence< DriverPropertyInfo > SAL_CALL OEvoabDriver::getPropertyInfo( const ::rtl::OUString& url, const Sequence< PropertyValue >& /*info*/ ) throw(SQLException, RuntimeException)
501 if ( !acceptsURL(url) )
503 ::connectivity::SharedResources aResources;
504 const ::rtl::OUString sMessage = aResources.getResourceString(STR_URI_SYNTAX_ERROR);
505 ::dbtools::throwGenericSQLException(sMessage ,*this);
506 } // if ( !acceptsURL(url) )
507 return Sequence< DriverPropertyInfo >();