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 package com.sun.star.help; 29 30 import com.sun.star.lib.uno.helper.Factory; 31 import com.sun.star.lang.XMultiComponentFactory; 32 import com.sun.star.lang.XSingleComponentFactory; 33 import com.sun.star.lib.uno.helper.WeakBase; 34 import com.sun.star.uno.XComponentContext; 35 import com.sun.star.registry.XRegistryKey; 36 import com.sun.star.lang.XServiceInfo; 37 import com.sun.star.uno.Type; 38 import com.sun.star.uno.Any; 39 import com.sun.star.uno.AnyConverter; 40 41 import org.apache.lucene.analysis.Analyzer; 42 import org.apache.lucene.analysis.standard.StandardAnalyzer; 43 import org.apache.lucene.analysis.cjk.CJKAnalyzer; 44 import org.apache.lucene.document.Document; 45 import org.apache.lucene.index.IndexReader; 46 import org.apache.lucene.index.Term; 47 import org.apache.lucene.search.Hits; 48 import org.apache.lucene.search.IndexSearcher; 49 import org.apache.lucene.search.Query; 50 import org.apache.lucene.search.Searcher; 51 import org.apache.lucene.search.TermQuery; 52 import org.apache.lucene.search.WildcardQuery; 53 54 import com.sun.star.script.XInvocation; 55 import com.sun.star.beans.XIntrospectionAccess; 56 57 /** This class capsulates the class, that implements the minimal component and a 58 * factory for creating the service (<CODE>__getComponentFactory</CODE>). 59 */ 60 public class HelpSearch 61 { 62 /** This class implements the component. At least the interfaces XServiceInfo, 63 * XTypeProvider, and XInitialization should be provided by the service. 64 */ 65 public static class _HelpSearch extends WeakBase 66 implements XServiceInfo, XInvocation 67 { 68 /** The service name, that must be used to get an instance of this service. 69 */ 70 static private final String __serviceName = 71 "com.sun.star.help.HelpSearch"; 72 static private final String aSearchMethodName = "search"; 73 74 /** The initial component contextr, that gives access to 75 * the service manager, supported singletons, ... 76 * It's often later used 77 */ 78 private XComponentContext m_cmpCtx; 79 80 /** The service manager, that gives access to all registered services. 81 * It's often later used 82 */ 83 private XMultiComponentFactory m_xMCF; 84 85 /** The constructor of the inner class has a XMultiServiceFactory parameter. 86 * @param xmultiservicefactoryInitialization A special service factory 87 * could be introduced while initializing. 88 */ 89 public _HelpSearch(XComponentContext xCompContext) 90 { 91 try { 92 m_cmpCtx = xCompContext; 93 m_xMCF = m_cmpCtx.getServiceManager(); 94 } 95 catch( Exception e ) { 96 e.printStackTrace(); 97 } 98 } 99 100 /** This method returns an array of all supported service names. 101 * @return Array of supported service names. 102 */ 103 public String[] getSupportedServiceNames() 104 { 105 return getServiceNames(); 106 } 107 108 /** This method is a simple helper function to used in the 109 * static component initialisation functions as well as in 110 * getSupportedServiceNames. 111 */ 112 public static String[] getServiceNames() 113 { 114 String[] sSupportedServiceNames = { __serviceName }; 115 return sSupportedServiceNames; 116 } 117 118 /** This method returns true, if the given service will be 119 * supported by the component. 120 * @param sServiceName Service name. 121 * @return True, if the given service name will be supported. 122 */ 123 public boolean supportsService( String sServiceName ) 124 { 125 return sServiceName.equals( __serviceName ); 126 } 127 128 /** Return the class name of the component. 129 * @return Class name of the component. 130 */ 131 public String getImplementationName() 132 { 133 return _HelpSearch.class.getName(); 134 } 135 136 //=================================================== 137 // XInvocation 138 public XIntrospectionAccess getIntrospection() 139 { 140 return null; 141 } 142 143 public Object invoke( String aFunctionName, java.lang.Object[] aParams, 144 short[][] aOutParamIndex, java.lang.Object[][] aOutParam ) 145 throws com.sun.star.lang.IllegalArgumentException, 146 com.sun.star.script.CannotConvertException, 147 com.sun.star.reflection.InvocationTargetException 148 { 149 String[] aRet = null; 150 if( !aFunctionName.equals( aSearchMethodName ) ) 151 throw new com.sun.star.lang.IllegalArgumentException(); 152 153 Object[] aScoreOutArray = new Object[1]; 154 aScoreOutArray[0] = null; 155 try 156 { 157 aRet = doQuery( aParams, aScoreOutArray ); 158 } 159 catch( Exception e ) 160 { 161 aRet = null; 162 } 163 164 Object aScoreArray = aScoreOutArray[0]; 165 if( aScoreArray == null ) 166 { 167 aOutParamIndex[0] = new short[0]; 168 aOutParam[0] = new Object[0]; 169 } 170 else 171 { 172 short nInParamCount = (short)aParams.length; 173 aOutParamIndex[0] = new short[1]; 174 aOutParamIndex[0][0] = nInParamCount; 175 aOutParam[0] = new Object[1]; 176 aOutParam[0][0] = aScoreArray; 177 } 178 179 Any aRetAny = new Any( new Type( String[].class ), aRet ); 180 return aRetAny; 181 } 182 183 public void setValue( String aPropertyName, java.lang.Object aValue ) 184 throws com.sun.star.beans.UnknownPropertyException, 185 com.sun.star.script.CannotConvertException, 186 com.sun.star.reflection.InvocationTargetException { 187 throw new com.sun.star.beans.UnknownPropertyException(); 188 } 189 190 public Object getValue( String aPropertyName ) 191 throws com.sun.star.beans.UnknownPropertyException { 192 throw new com.sun.star.beans.UnknownPropertyException(); 193 } 194 195 public boolean hasMethod( String aMethodName ) { 196 boolean bRet = (aMethodName.equals( aSearchMethodName ) ); 197 return bRet; 198 } 199 public boolean hasProperty( String aName ) { 200 return false; 201 } 202 203 // Command line interface for testing 204 private static String[] doQuery( Object[] args, Object[] aScoreOutArray ) throws Exception 205 { 206 String aLanguageStr = ""; 207 String aIndexStr = ""; 208 String aQueryStr = ""; 209 boolean bCaptionOnly = false; 210 211 int nParamCount = args.length; 212 String aStrs[] = new String[nParamCount]; 213 for( int i = 0 ; i < nParamCount ; i++ ) 214 { 215 try 216 { 217 aStrs[i] = AnyConverter.toString( args[i] ); 218 } 219 catch( IllegalArgumentException e ) 220 { 221 aStrs[i] = ""; 222 } 223 } 224 225 // TODO: Error handling 226 for( int i = 0 ; i < nParamCount ; i++ ) 227 { 228 if ("-lang".equals(aStrs[i]) ) 229 { 230 aLanguageStr = aStrs[i + 1]; 231 i++; 232 } 233 else if( "-index".equals(aStrs[i]) ) 234 { 235 aIndexStr = aStrs[i+1]; 236 i++; 237 } 238 else if( "-query".equals(aStrs[i]) ) 239 { 240 aQueryStr = aStrs[i+1]; 241 i++; 242 } 243 else if( "-caption".equals(aStrs[i]) ) 244 { 245 bCaptionOnly = true; 246 } 247 } 248 String[] aDocs = queryImpl( aLanguageStr, aIndexStr, aQueryStr, bCaptionOnly, aScoreOutArray ); 249 250 return aDocs; 251 } 252 253 private static String[] queryImpl( String aLanguageStr, String aIndexStr, String aQueryStr, 254 boolean bCaptionOnly, Object[] aScoreOutArray ) throws Exception 255 { 256 IndexReader reader = IndexReader.open( aIndexStr ); 257 Searcher searcher = new IndexSearcher( reader ); 258 Analyzer analyzer = aLanguageStr.equals("ja") ? (Analyzer)new CJKAnalyzer() : (Analyzer)new StandardAnalyzer(); 259 260 String aField; 261 if( bCaptionOnly ) 262 aField = "caption"; 263 else 264 aField = "content"; 265 266 Query aQuery; 267 if( aQueryStr.endsWith( "*" ) ) 268 aQuery = new WildcardQuery( new Term( aField, aQueryStr ) ); 269 else 270 aQuery = new TermQuery( new Term( aField, aQueryStr ) ); 271 272 // Perform search 273 Hits aHits = searcher.search( aQuery ); 274 int nHitCount = aHits.length(); 275 276 String aDocs[] = new String[nHitCount]; 277 float aScores[] = null; 278 aScores = new float[nHitCount]; 279 for( int iHit = 0 ; iHit < nHitCount ; iHit++ ) 280 { 281 Document aDoc = aHits.doc( iHit ); 282 String aPath = aDoc.get( "path" ); 283 aDocs[iHit] = ( aPath != null ) ? aPath : ""; 284 aScores[iHit] = aHits.score( iHit ); 285 } 286 aScoreOutArray[0] = aScores; 287 288 reader.close(); 289 290 return aDocs; 291 } 292 } 293 294 /** 295 * Gives a factory for creating the service. 296 * This method is called by the <code>JavaLoader</code> 297 * <p> 298 * @return returns a <code>XSingleComponentFactory</code> for creating 299 * the component 300 * @param sImplName the name of the implementation for which a 301 * service is desired 302 * @see com.sun.star.comp.loader.JavaLoader 303 */ 304 public static XSingleComponentFactory __getComponentFactory(String sImplName) 305 { 306 XSingleComponentFactory xFactory = null; 307 308 if ( sImplName.equals( _HelpSearch.class.getName() ) ) 309 xFactory = Factory.createComponentFactory(_HelpSearch.class, 310 _HelpSearch.getServiceNames()); 311 312 return xFactory; 313 } 314 315 /** This method is a member of the interface for initializing an object 316 * directly after its creation. 317 * @param object This array of arbitrary objects will be passed to the 318 * component after its creation. 319 * @throws Exception Every exception will not be handled, but will be 320 * passed to the caller. 321 */ 322 public void initialize( Object[] object ) 323 throws com.sun.star.uno.Exception { 324 /* The component describes what arguments its expected and in which 325 * order!At this point you can read the objects and can intialize 326 * your component using these objects. 327 */ 328 } 329 } 330