blob: 29e6a2f9fd64940bf866a9e42b7113d6f38bf92f [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2011 Tasktop Technologies.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Tasktop Technologies - initial API and implementation
*******************************************************************************/
#include "stdafx.h"
#include "Windows7Search.h"
#include "Windows7SearchProvider.h"
#include <sstream>
#include <list>
#import "C:/Program Files/Common Files/System/ado/msado15.dll" rename("EOF", "ADOEOF")
void InvokeCallback(JNIEnv *env, jobject obj, jobject callback, std::wstring filename)
{
jstring j_filename = env->NewString((const jchar *)filename.c_str(), filename.length());
jclass fileClass = env->FindClass("java/io/File");
jmethodID fileConstructor = env->GetMethodID(fileClass, "<init>", "(Ljava/lang/String;)V");
jobject fileObj = env->NewObject(fileClass, fileConstructor, j_filename);
jclass resultClass = env->FindClass("org/eclipse/mylyn/sandbox/search/ui/SearchResult");
jmethodID resultConstructor = env->GetMethodID(resultClass, "<init>", "(Ljava/io/File;)V");
jobject resultObj = env->NewObject(resultClass, resultConstructor, fileObj);
jclass jc = env->GetObjectClass(callback);
jmethodID mid = env->GetMethodID(jc, "searchResult","(Lorg/eclipse/mylyn/sandbox/search/ui/SearchResult;)V");
env->CallObjectMethod(callback, mid, resultObj);
}
bool IsProgressMonitorCancelled(JNIEnv *env,jobject monitor) {
jclass monitorClass = env->FindClass("org/eclipse/core/runtime/IProgressMonitor");
jmethodID isCanceledMethod = env->GetMethodID(monitorClass,"isCanceled","()Z");
jboolean result = env->CallBooleanMethod(monitor,isCanceledMethod);
return result == JNI_TRUE;
}
std::wstring ReplaceCharWithString(std::wstring source, const wchar_t replaceChar, std::wstring replaceString)
{
size_t posn = source.find(&replaceChar);
while (posn != std::wstring::npos)
{
source.replace(posn, 1, replaceString);
posn = source.find(&replaceChar, posn + replaceString.length());
}
return source;
}
std::wstring IntToString(int value) {
std::wstringstream sstream;
sstream << value;
return sstream.str();
}
void PerformSearch(JNIEnv *env, jobject obj, jobject callback, std::wstring searchText, std::list<std::wstring>& patterns,int maximumResults, jobject monitor)
{
ADODB::_ConnectionPtr connection = NULL;
ADODB::_RecordsetPtr recordset = NULL;
try {
HRESULT hr = ::CoInitialize(NULL);
if (!SUCCEEDED(hr))
return;
hr = connection.CreateInstance(__uuidof(ADODB::Connection));
if (!SUCCEEDED(hr))
return;
hr = recordset.CreateInstance(__uuidof(ADODB::Recordset));
if (!SUCCEEDED(hr))
return;
connection->CursorLocation = ADODB::adUseClient;
hr = connection->Open(L"Provider=Search.CollatorDSO;Extended Properties='Application=Windows';", L"", L"", ADODB::adConnectUnspecified);
if (!SUCCEEDED(hr))
return;
searchText = ReplaceCharWithString(searchText, '\'', L"''");
std::wstring filenameMatcher = searchText;
filenameMatcher = ReplaceCharWithString(filenameMatcher, '%', L"\\%");
filenameMatcher = ReplaceCharWithString(filenameMatcher, '*', L"%");
// see FREETEXT http://msdn.microsoft.com/en-us/library/bb231268(v=vs.85).aspx
// see CONTAINS http://msdn.microsoft.com/en-us/library/bb231270(v=vs.85).aspx
std::wstring query = L"SELECT TOP ";
query += IntToString(maximumResults);
query += L" System.ItemPathDisplay from SystemIndex WHERE ";
// limit to documents, pictures and video
query += L"(System.Kind = 'document' or System.Kind = 'picture' or System.Kind = 'video' or System.Kind is null) AND ";
// content search
query += L"(FREETEXT('\"";
query += searchText;
query += L"\"') OR ";
// filename search
query += L"(System.ItemName LIKE '%";
query += filenameMatcher;
query += L"%'))";
if (patterns.size() > 0) {
bool hasFilenameSearch = true;
std::wstring anyFile(L"*");
for(std::list<std::wstring>::iterator iterator = patterns.begin(); iterator != patterns.end(); iterator++) {
std::wstring pattern = *iterator;
if (pattern == anyFile) {
hasFilenameSearch = false;
break;
}
}
if (hasFilenameSearch) {
query += L" AND (";
for(std::list<std::wstring>::iterator iterator = patterns.begin(); iterator != patterns.end(); iterator++) {
std::wstring pattern = *iterator;
if (pattern.size() == 0) {
continue;
}
pattern = ReplaceCharWithString(pattern, '*', L"%");
if (iterator != patterns.begin()) {
query += L" OR ";
}
query += L"(System.ItemName LIKE '";
if (pattern[0] != '%') {
query += L"%";
}
query += pattern;
query += L"')";
}
query += L")";
}
}
//std::cout << "Query:\n";
//std::cout << query;
//std::cout << "\n";
//std::cout << std::flush;
hr = recordset->Open(query.c_str(), connection.GetInterfacePtr(), ADODB::adOpenForwardOnly, ADODB::adLockReadOnly, ADODB::adCmdText);
if (!SUCCEEDED(hr)) {
std::cout << "Open Failed\n" << std::flush;
return;
}
int count = maximumResults;
while(!recordset->ADOEOF)
{
_variant_t var = recordset->Fields->GetItem(L"System.ItemPathDisplay")->GetValue();
std::wstring filename = (const wchar_t*)_bstr_t(var.bstrVal);
InvokeCallback(env, obj, callback, filename);
if (IsProgressMonitorCancelled(env,monitor)) {
break;
}
if (--count < 0) {
break;
}
hr = recordset->MoveNext();
if (!SUCCEEDED(hr)) {
std::cout << "Move Next Failed\n" << std::flush;
break;
}
}
} catch (_com_error &e) {
_tprintf(_T("\tCOM Error code = %08lx\n"), e.Error());
}
if (recordset != NULL && recordset->State == ADODB::adStateOpen)
recordset->Close();
if (connection != NULL && connection->State == ADODB::adStateOpen)
connection->Close();
::CoUninitialize();
}
std::wstring JStringToWString (JNIEnv *env, jstring javaString)
{
const jchar *javaChars = env->GetStringChars(javaString, NULL);
jsize length = env->GetStringLength(javaString);
std::wstring wideString((wchar_t *)javaChars, length);
env->ReleaseStringChars(javaString, javaChars);
return wideString;
}
JNIEXPORT void JNICALL Java_org_eclipse_mylyn_internal_sandbox_search_ui_windows_WindowsSearchProvider_performNativeSearch (JNIEnv *env, jobject obj, jobject criteria, jobject callback, jobject monitor)
{
jclass jc = env->GetObjectClass(criteria);
jmethodID mid = env->GetMethodID(jc, "getText","()Ljava/lang/String;");
jstring jSearchText = (jstring)env->CallObjectMethod(criteria, mid);
std::wstring searchText = JStringToWString(env, jSearchText);
jmethodID getPatternId = env->GetMethodID(jc, "getFilenamePatterns","()[Ljava/lang/String;");
jobjectArray patternArray = (jobjectArray)env->CallObjectMethod(criteria, getPatternId);
unsigned int patternCount = env->GetArrayLength(patternArray);
// FIXME FIXME FIXME
jmethodID getMaximumResultsId = env->GetMethodID(jc,"getMaximumResults","()I");
jint maximumResults = (jint) env->CallIntMethod(criteria,getMaximumResultsId);
std::list<std::wstring> patterns;
for (unsigned int i=0; i<patternCount; i++) {
jstring jPattern = (jstring)env->GetObjectArrayElement(patternArray, i);
std::wstring pattern = JStringToWString(env, jPattern);
patterns.push_back(pattern);
}
PerformSearch(env, obj, callback, searchText, patterns,(int) maximumResults, monitor);
}