1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_connectivity.hxx"
30 
31 #include <stdio.h>
32 #include "connectivity/CommonTools.hxx"
33 #include "connectivity/dbtools.hxx"
34 #include <com/sun/star/util/Date.hpp>
35 #include <com/sun/star/util/Time.hpp>
36 #include <com/sun/star/util/DateTime.hpp>
37 #include <com/sun/star/beans/XPropertySet.hpp>
38 #include <com/sun/star/lang/XComponent.hpp>
39 #include <comphelper/extract.hxx>
40 #include <cppuhelper/interfacecontainer.h>
41 #include "TConnection.hxx"
42 #include <comphelper/types.hxx>
43 #include <com/sun/star/java/XJavaVM.hpp>
44 #include <rtl/process.h>
45 
46 using namespace ::comphelper;
47 inline sal_Unicode rtl_ascii_toUpperCase( sal_Unicode ch )
48 {
49     return ch >= 0x0061 && ch <= 0x007a ? ch + 0x20 : ch;
50 }
51 
52 namespace connectivity
53 {
54 	using namespace ::com::sun::star::uno;
55 	using namespace ::com::sun::star::lang;
56 	using namespace ::com::sun::star::beans;
57 	using namespace dbtools;
58 	namespace starjava	= com::sun::star::java;
59 	//------------------------------------------------------------------------------
60 	const sal_Unicode CHAR_PLACE = '_';
61 	const sal_Unicode CHAR_WILD  = '%';
62 	// -------------------------------------------------------------------------
63 	sal_Bool match(const sal_Unicode* pWild, const sal_Unicode* pStr, const sal_Unicode cEscape)
64 	{
65 		int    pos=0;
66 		int    flag=0;
67 
68 		while ( *pWild || flag )
69 		{
70 			switch (*pWild)
71 			{
72 				case CHAR_PLACE:
73 					if ( *pStr == 0 )
74 						return sal_False;
75 					break;
76 				default:
77 					if (*pWild && (*pWild == cEscape) && ((*(pWild+1)== CHAR_PLACE) || (*(pWild+1) == CHAR_WILD)) )
78 						pWild++;
79 					if ( rtl_ascii_toUpperCase(*pWild) != rtl_ascii_toUpperCase(*pStr) )
80 						if ( !pos )
81 							return sal_False;
82 						else
83 							pWild += pos;
84 					else
85 						break;          // ACHTUNG laeuft unter bestimmten
86 										// Umstaenden in den nachsten case rein!!
87 				case CHAR_WILD:
88 					while ( *pWild == CHAR_WILD )
89 						pWild++;
90 					if ( *pWild == 0 )
91 						return sal_True;
92 					flag = 1;
93 					pos  = 0;
94 					if ( *pStr == 0 )
95 						return ( *pWild == 0 );
96 					while ( *pStr && *pStr != *pWild )
97 					{
98 						if ( *pWild == CHAR_PLACE ) {
99 							pWild++;
100 							while ( *pWild == CHAR_WILD )
101 								pWild++;
102 						}
103 						pStr++;
104 						if ( *pStr == 0 )
105 							return ( *pWild == 0 );
106 					}
107 					break;
108 			}
109 			if ( *pWild != 0 )
110 				pWild++;
111 			if ( *pStr != 0 )
112 				pStr++;
113 			else
114 				flag = 0;
115 			if ( flag )
116 				pos--;
117 		}
118 		return ( *pStr == 0 ) && ( *pWild == 0 );
119 	}
120 	//------------------------------------------------------------------
121 	rtl::OUString toDateString(const ::com::sun::star::util::Date& rDate)
122 	{
123 		sal_Char s[11];
124 		snprintf(s,
125 				sizeof(s),
126 				"%04d-%02d-%02d",
127 				(int)rDate.Year,
128 				(int)rDate.Month,
129 				(int)rDate.Day);
130 		s[10] = 0;
131 		return rtl::OUString::createFromAscii(s);
132 	}
133 
134 	//------------------------------------------------------------------
135 	rtl::OUString toTimeString(const ::com::sun::star::util::Time& rTime)
136 	{
137 		sal_Char s[9];
138 		snprintf(s,
139 				sizeof(s),
140 				"%02d:%02d:%02d",
141 				(int)rTime.Hours,
142 				(int)rTime.Minutes,
143 				(int)rTime.Seconds);
144 		s[8] = 0;
145 		return rtl::OUString::createFromAscii(s);
146 	}
147 
148 	//------------------------------------------------------------------
149 	rtl::OUString toDateTimeString(const ::com::sun::star::util::DateTime& rDateTime)
150 	{
151 		sal_Char s[21];
152 		snprintf(s,
153 				sizeof(s),
154 				"%04d-%02d-%02d %02d:%02d:%02d",
155 				(int)rDateTime.Year,
156 				(int)rDateTime.Month,
157 				(int)rDateTime.Day,
158 				(int)rDateTime.Hours,
159 				(int)rDateTime.Minutes,
160 				(int)rDateTime.Seconds);
161 		s[20] = 0;
162 		return rtl::OUString::createFromAscii(s);
163 	}
164 
165 
166 	//--------------------------------------------------------------------------------------------------
167 	rtl::OUString toString(const Any& rValue)
168 	{
169 		rtl::OUString aRes;
170 		TypeClass aDestinationClass = rValue.getValueType().getTypeClass();
171 
172 		switch (aDestinationClass)
173 		{
174 			case TypeClass_CHAR:
175 				aRes = ::rtl::OUString::valueOf(*(sal_Unicode*)rValue.getValue());
176 				break;
177 			case TypeClass_FLOAT:
178 				aRes = ::rtl::OUString::valueOf(*(float*)rValue.getValue());
179 				break;
180 			case TypeClass_DOUBLE:
181 				aRes = ::rtl::OUString::valueOf(*(double*)rValue.getValue());
182 				break;
183 			case TypeClass_BOOLEAN:
184 				aRes = ::rtl::OUString::valueOf((sal_Int32)*(sal_Bool*)rValue.getValue());
185 				break;
186 			case TypeClass_BYTE:
187 			case TypeClass_SHORT:
188 			case TypeClass_LONG:
189 				aRes = ::rtl::OUString::valueOf(*(sal_Int32*)rValue.getValue());
190 				break;
191             case TypeClass_HYPER:
192 		    {
193 			    sal_Int64 nValue = 0;
194 			    OSL_VERIFY( rValue >>= nValue );
195                 aRes = ::rtl::OUString::valueOf(nValue);
196 		    }
197 			case TypeClass_STRING:
198 				rValue >>= aRes;
199 				break;
200 			case TypeClass_STRUCT:
201 				if (rValue.getValueType() == ::getCppuType((const ::com::sun::star::util::Date*)0))
202 				{
203 					::com::sun::star::util::Date aDate;
204 					rValue >>= aDate;
205 					aRes = toDateString(aDate);
206 				}
207 				else if (rValue.getValueType() == ::getCppuType((const ::com::sun::star::util::DateTime*)0))
208 				{
209 					::com::sun::star::util::DateTime aDT;
210 					rValue >>= aDT;
211 					aRes = toDateTimeString(aDT);
212 				}
213 				else if (rValue.getValueType() == ::getCppuType((const ::com::sun::star::util::Time*)0))
214 				{
215 					::com::sun::star::util::Time aTime;
216 					rValue >>= aTime;
217 					aRes = toTimeString(aTime);
218 				}
219 
220 				break;
221 			default:
222 				;
223 		}
224 		return aRes;
225 	}
226 
227 	// -----------------------------------------------------------------------------
228 	::rtl::Reference< jvmaccess::VirtualMachine > getJavaVM(const Reference<XMultiServiceFactory >& _rxFactory)
229 	{
230 		::rtl::Reference< jvmaccess::VirtualMachine > aRet;
231 		OSL_ENSURE(_rxFactory.is(),"No XMultiServiceFactory a.v.!");
232 		if(!_rxFactory.is())
233 			return aRet;
234 
235 		try
236 		{
237 			Reference< starjava::XJavaVM > xVM(_rxFactory->createInstance(
238 				rtl::OUString::createFromAscii("com.sun.star.java.JavaVirtualMachine")), UNO_QUERY);
239 
240 			OSL_ENSURE(_rxFactory.is(),"InitJava: I have no factory!");
241 			if (!xVM.is() || !_rxFactory.is())
242 				throw Exception(); // -2;
243 
244 			Sequence<sal_Int8> processID(16);
245 			rtl_getGlobalProcessId( (sal_uInt8*) processID.getArray() );
246 			processID.realloc(17);
247 			processID[16] = 0;
248 
249 			Any uaJVM = xVM->getJavaVM( processID );
250 
251 			if (!uaJVM.hasValue())
252 				throw Exception(); // -5
253 			else
254 			{
255 				sal_Int32 nValue = 0;
256 				jvmaccess::VirtualMachine* pJVM = NULL;
257 				if ( uaJVM >>= nValue )
258 					pJVM = reinterpret_cast< jvmaccess::VirtualMachine* > (nValue);
259 				else
260 				{
261 					sal_Int64 nTemp = 0;
262 					uaJVM >>= nTemp;
263 					pJVM = reinterpret_cast< jvmaccess::VirtualMachine* > (nTemp);
264 				}
265 				aRet = pJVM;
266 			}
267 		}
268 		catch (Exception&)
269 		{
270 		}
271 
272 		return aRet;
273 	}
274 	//------------------------------------------------------------------------------
275 	sal_Bool existsJavaClassByName( const ::rtl::Reference< jvmaccess::VirtualMachine >& _pJVM,const ::rtl::OUString& _sClassName )
276 	{
277 		sal_Bool bRet = sal_False;
278 #ifdef SOLAR_JAVA
279 		if ( _pJVM.is() )
280 		{
281 			jvmaccess::VirtualMachine::AttachGuard aGuard(_pJVM);
282 			JNIEnv*	pEnv = aGuard.getEnvironment();
283 			if( pEnv )
284 			{
285 				::rtl::OString sClassName = ::rtl::OUStringToOString(_sClassName, RTL_TEXTENCODING_ASCII_US);
286 				sClassName = sClassName.replace('.','/');
287 				jobject out = pEnv->FindClass(sClassName);
288 				bRet = out != NULL;
289 				pEnv->DeleteLocalRef( out );
290 			}
291 		}
292 #endif
293 		return bRet;
294 	}
295 
296 }
297 
298 #include <ctype.h>		//isdigit
299 namespace dbtools
300 {
301 //------------------------------------------------------------------
302 sal_Bool isCharOk(sal_Unicode c,const ::rtl::OUString& _rSpecials)
303 {
304 
305     return ( ((c >= 97) && (c <= 122)) || ((c >= 65) && (c <=  90)) || ((c >= 48) && (c <=  57)) ||
306           c == '_' || _rSpecials.indexOf(c) != -1);
307 }
308 
309 //------------------------------------------------------------------------------
310 sal_Bool isValidSQLName(const ::rtl::OUString& rName,const ::rtl::OUString& _rSpecials)
311 {
312     // Ueberpruefung auf korrekte Namensgebung im SQL Sinne
313     // Dieses ist wichtig fuer Tabellennamen beispielsweise
314 	const sal_Unicode* pStr = rName.getStr();
315 	if (*pStr > 127 || isdigit(*pStr))
316 		return sal_False;
317 
318 	for (; *pStr; ++pStr )
319 		if(!isCharOk(*pStr,_rSpecials))
320 			return sal_False;
321 
322 	if	(	rName.getLength()
323 		&&	(	(rName.toChar() == '_')
324 			||	(	(rName.toChar() >= '0')
325 				&&	(rName.toChar() <= '9')
326 				)
327 			)
328 		)
329 		return sal_False;
330 	// the SQL-Standard requires the first character to be an alphabetic character, which
331 	// isn't easy to decide in UniCode ...
332 	// So we just prohibit the characters which already lead to problems ....
333 	// 11.04.00 - 74902 - FS
334 
335 	return sal_True;
336 }
337 //------------------------------------------------------------------
338 // Erzeugt einen neuen Namen falls noetig
339 ::rtl::OUString convertName2SQLName(const ::rtl::OUString& rName,const ::rtl::OUString& _rSpecials)
340 {
341 	if(isValidSQLName(rName,_rSpecials))
342 		return rName;
343 	::rtl::OUString aNewName(rName);
344 	const sal_Unicode* pStr = rName.getStr();
345 	sal_Int32 nLength = rName.getLength();
346 	sal_Bool bValid(*pStr < 128 && !isdigit(*pStr));
347 	for (sal_Int32 i=0; bValid && i < nLength; ++pStr,++i )
348 		if(!isCharOk(*pStr,_rSpecials))
349 		{
350 			aNewName = aNewName.replace(*pStr,'_');
351 			pStr = aNewName.getStr() + i;
352 		}
353 
354 	if ( !bValid )
355 		aNewName = ::rtl::OUString();
356 
357 	return aNewName;
358 }
359 //------------------------------------------------------------------------------
360 ::rtl::OUString quoteName(const ::rtl::OUString& _rQuote, const ::rtl::OUString& _rName)
361 {
362 	::rtl::OUString sName = _rName;
363 	if(_rQuote.getLength() && _rQuote.toChar() != ' ')
364 		sName = _rQuote + _rName + _rQuote;
365 	return sName;
366 }
367 
368 
369 }
370