001 package railo.runtime.search; 002 003 import java.net.MalformedURLException; 004 import java.net.URL; 005 import java.util.Iterator; 006 import java.util.Map; 007 import java.util.Map.Entry; 008 009 import org.w3c.dom.Element; 010 011 import railo.commons.collections.HashTable; 012 import railo.commons.io.FileUtil; 013 import railo.commons.io.log.Log; 014 import railo.commons.io.res.Resource; 015 import railo.commons.io.res.util.ResourceUtil; 016 import railo.commons.lang.StringUtil; 017 import railo.commons.lock.KeyLock; 018 import railo.commons.lock.Lock; 019 import railo.commons.net.HTTPUtil; 020 import railo.runtime.PageContext; 021 import railo.runtime.exp.DatabaseException; 022 import railo.runtime.exp.PageException; 023 import railo.runtime.op.Caster; 024 import railo.runtime.type.ArrayImpl; 025 import railo.runtime.type.Collection.Key; 026 import railo.runtime.type.KeyImpl; 027 import railo.runtime.type.List; 028 import railo.runtime.type.Query; 029 import railo.runtime.type.QueryColumn; 030 import railo.runtime.type.QueryImpl; 031 import railo.runtime.type.dt.DateTime; 032 import railo.runtime.type.dt.DateTimeImpl; 033 import railo.runtime.type.util.ArrayUtil; 034 035 /** 036 * represent a single Collection 037 */ 038 public abstract class SearchCollectionSupport implements SearchCollectionPlus { 039 040 private static final long serialVersionUID = 8089312879341384114L; 041 042 private static final int LOCK_TIMEOUT = 10*60*1000; // ten minutes 043 private final String name; 044 private final Resource path; 045 private String language; 046 private DateTime lastUpdate; 047 private SearchEngineSupport searchEngine; 048 //TODO change visibility to private 049 protected Map<String,SearchIndex> indexes=new HashTable(); 050 051 private DateTime created; 052 053 private Log log; 054 //private static LockManager manager=Lock Manager Impl.getInstance(); 055 private KeyLock<String> lock=new KeyLock<String>(); 056 057 058 /** 059 * constructor of the class 060 * @param searchEngine 061 * @param name name of the Collection 062 * @param path 063 * @param language 064 * @param count total count of documents in the collection 065 * @param lastUpdate 066 * @param created 067 */ 068 public SearchCollectionSupport(SearchEngineSupport searchEngine, String name,Resource path, String language, DateTime lastUpdate, DateTime created) { 069 this.searchEngine=searchEngine; 070 this.name=name; 071 this.path=path; 072 this.language=SearchUtil.translateLanguage(language); 073 this.lastUpdate=lastUpdate; 074 this.created=created; 075 this.log = searchEngine.getLogger(); 076 } 077 078 /** 079 * @see railo.runtime.search.SearchCollection#create() 080 */ 081 public final void create() throws SearchException { 082 Lock l = lock(); 083 try { 084 _create(); 085 } 086 finally { 087 unlock(l); 088 } 089 } 090 091 /** 092 * create a collection 093 * @throws SearchException 094 */ 095 protected abstract void _create() throws SearchException; 096 097 /** 098 * @see railo.runtime.search.SearchCollection#optimize() 099 */ 100 public final void optimize() throws SearchException { 101 Lock l = lock(); 102 try { 103 _optimize(); 104 changeLastUpdate(); 105 } 106 finally { 107 unlock(l); 108 } 109 } 110 111 /** 112 * optimize a Collection 113 * @throws SearchException 114 */ 115 protected abstract void _optimize() throws SearchException ; 116 117 /** 118 * @see railo.runtime.search.SearchCollection#map(railo.commons.io.res.Resource) 119 */ 120 public final void map(Resource path) throws SearchException { 121 Lock l = lock(); 122 try { 123 _map(path); 124 changeLastUpdate(); 125 } 126 finally { 127 unlock(l); 128 } 129 } 130 131 /** 132 * map a Collection 133 * @param path 134 * @throws SearchException 135 */ 136 protected abstract void _map(Resource path) throws SearchException ; 137 138 /** 139 * @see railo.runtime.search.SearchCollection#repair() 140 */ 141 public final void repair() throws SearchException { 142 Lock l = lock(); 143 try { 144 _repair(); 145 changeLastUpdate(); 146 } 147 finally { 148 unlock(l); 149 } 150 } 151 152 /** 153 * repair a Collection 154 * @throws SearchException 155 */ 156 protected abstract void _repair() throws SearchException ; 157 158 /** 159 * @return 160 * @see railo.runtime.search.SearchCollection#index(railo.runtime.PageContext, java.lang.String, short, java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String[], java.lang.String, boolean, java.lang.String, java.lang.String[], java.lang.String, java.lang.String, java.lang.String, java.lang.String) 161 */ 162 public IndexResult index(PageContext pc, String key, short type, String urlpath, String title, String body, String language, 163 String[] extensions, String query, boolean recurse,String categoryTree, String[] categories, 164 String custom1, String custom2, String custom3, String custom4) throws PageException, MalformedURLException, SearchException { 165 return index(pc, key, type, urlpath, title, body, language, extensions, query, recurse, categoryTree, categories, 10000, custom1, custom2, custom3, custom4); 166 } 167 168 // FUTURE add this to interface 169 public IndexResult index(PageContext pc, String key, short type, String urlpath, String title, String body, String language, 170 String[] extensions, String query, boolean recurse,String categoryTree, String[] categories, long timeout, 171 String custom1, String custom2, String custom3, String custom4) throws PageException, MalformedURLException, SearchException { 172 language=SearchUtil.translateLanguage(language); 173 Lock l = lock(); 174 try { 175 SearchIndex si = new SearchIndex(title,key,type,query,extensions,language,urlpath,categoryTree,categories,custom1,custom2,custom3,custom4); 176 String id=si.getId(); 177 IndexResult ir=IndexResultImpl.EMPTY; 178 if(type==SearchIndex.TYPE_FILE){ 179 Resource file=ResourceUtil.toResourceNotExisting(pc,key); 180 if(!file.isFile())throw new SearchException("value of attribute key must specify a existing file, ["+key+"] is invalid"); 181 ir=indexFile(id,title,file,language); 182 } 183 else if(type==SearchIndex.TYPE_PATH){ 184 Resource dir=ResourceUtil.toResourceNotExisting(pc,key); 185 if(!dir.isDirectory())throw new SearchException("value of attribute key must specify a existing directory, ["+key+"] is invalid"); 186 ir=indexPath(id,title,dir,extensions,recurse,language); 187 } 188 else if(type==SearchIndex.TYPE_URL) { 189 ir=indexURL(id,title,new URL(key),extensions,recurse,language,timeout); 190 } 191 else if(type==SearchIndex.TYPE_CUSTOM) { 192 Query qv; 193 if(StringUtil.isEmpty(query)){ 194 195 // set columns 196 railo.runtime.type.Array columns=new ArrayImpl(); 197 columns.append("key"); 198 columns.append("body"); 199 if(!StringUtil.isEmpty(title))columns.append("title"); 200 if(!StringUtil.isEmpty(urlpath))columns.append("urlpath"); 201 if(!StringUtil.isEmpty(custom1))columns.append("custom1"); 202 if(!StringUtil.isEmpty(custom2))columns.append("custom2"); 203 if(!StringUtil.isEmpty(custom3))columns.append("custom3"); 204 if(!StringUtil.isEmpty(custom4))columns.append("custom4"); 205 206 // populate query with a single row 207 qv=new QueryImpl(columns,1,"query"); 208 // body 209 qv.setAt(KeyImpl.KEY, 1, key); 210 key="key"; 211 212 // body 213 qv.setAt(KeyImpl.BODY, 1, body); 214 body="body"; 215 216 // title 217 if(!StringUtil.isEmpty(title)){ 218 qv.setAt(KeyImpl.TITLE, 1, title); 219 title="title"; 220 } 221 222 // urlpath 223 if(!StringUtil.isEmpty(urlpath)){ 224 qv.setAt("urlpath", 1, urlpath); 225 urlpath="urlpath"; 226 } 227 228 // custom1 229 if(!StringUtil.isEmpty(custom1)){ 230 qv.setAt("custom1", 1, custom1); 231 custom1="custom1"; 232 } 233 // custom2 234 if(!StringUtil.isEmpty(custom2)){ 235 qv.setAt("custom2", 1, custom2); 236 custom2="custom2"; 237 } 238 // custom3 239 if(!StringUtil.isEmpty(custom3)){ 240 qv.setAt("custom3", 1, custom3); 241 custom3="custom3"; 242 } 243 // custom4 244 if(!StringUtil.isEmpty(custom4)){ 245 qv.setAt("custom4", 1, custom4); 246 custom4="custom4"; 247 } 248 } 249 else qv = Caster.toQuery(pc.getVariable(query)); 250 251 QueryColumn keyColumn=qv.getColumn(key); 252 253 String[] strBodies=List.toStringArrayTrim(List.listToArrayRemoveEmpty(body,',')); 254 QueryColumn[] bodyColumns=new QueryColumn[strBodies.length]; 255 for(int i=0;i<bodyColumns.length;i++) { 256 bodyColumns[i]=qv.getColumn(strBodies[i]); 257 } 258 259 ir= indexCustom(id, 260 getValue(qv,title), 261 keyColumn, 262 bodyColumns, 263 language, 264 getValue(qv,urlpath), 265 getValue(qv,custom1), 266 getValue(qv,custom2), 267 getValue(qv,custom3), 268 getValue(qv,custom4)); 269 } 270 createIndex(si); 271 return ir; 272 } 273 finally { 274 unlock(l); 275 } 276 } 277 278 private QueryColumn getColumnEL(Query query, String column) { 279 if(StringUtil.isEmpty(column)) return null; 280 QueryColumn c = query.getColumn(column,null); 281 282 return c; 283 } 284 285 private Object getValue(Query query, String column) { 286 if(StringUtil.isEmpty(column)) return null; 287 QueryColumn c = query.getColumn(column,null); 288 if(c==null) return column; 289 return c; 290 } 291 292 /** 293 * @see railo.runtime.search.SearchCollection#indexFile(java.lang.String, java.lang.String, railo.commons.io.res.Resource, java.lang.String) 294 */ 295 public final IndexResult indexFile(String id,String title, Resource res, String language) throws SearchException { 296 IndexResult ir=_indexFile(id,title,res,language); 297 changeLastUpdate(); 298 return ir; 299 } 300 301 /** 302 * updates a collection with a file 303 * @param id 304 * @param title 305 * @param file 306 * @param language 307 * @throws SearchException 308 */ 309 protected abstract IndexResult _indexFile(String id, String title, Resource file, String language) throws SearchException; 310 311 /** 312 * @see railo.runtime.search.SearchCollection#indexPath(java.lang.String, java.lang.String, railo.commons.io.res.Resource, java.lang.String[], boolean, java.lang.String) 313 */ 314 public final IndexResult indexPath(String id, String title, Resource dir, String[] extensions, boolean recurse, String language) throws SearchException { 315 IndexResult ir=_indexPath(id,title,dir,extensions,recurse,language); 316 changeLastUpdate(); 317 return ir; 318 } 319 320 321 /** 322 * updates a collection with a path 323 * @param id 324 * @param title 325 * @param dir 326 * @param recurse 327 * @param extensions 328 * @param language 329 * @throws SearchException 330 */ 331 protected abstract IndexResult _indexPath(String id,String title, Resource dir, String[] extensions, boolean recurse, String language) throws SearchException; 332 333 /** 334 * @see railo.runtime.search.SearchCollection#indexURL(java.lang.String, java.lang.String, java.net.URL, java.lang.String[], boolean, java.lang.String) 335 */ 336 public final IndexResult indexURL(String id,String title, URL url, String[] extensions, boolean recurse, String language) throws SearchException { 337 return indexURL(id, title, url, extensions, recurse, language, 10000); 338 } 339 // FUTURE replace this in interface with method above 340 public final IndexResult indexURL(String id,String title, URL url, String[] extensions, boolean recurse, String language,long timeout) throws SearchException { 341 IndexResult ir=_indexURL(id,title,url,extensions,recurse,language,timeout); 342 changeLastUpdate(); 343 return ir; 344 } 345 346 /** 347 * updates a collection with a url 348 * @param id 349 * @param title 350 * @param recurse 351 * @param extensions 352 * @param url 353 * @param language 354 * @throws SearchException 355 */ 356 protected abstract IndexResult _indexURL(String id,String title, URL url, String[] extensions, boolean recurse, String language,long timeout) throws SearchException ; 357 358 protected abstract IndexResult _indexURL(String id,String title, URL url, String[] extensions, boolean recurse, String language) throws SearchException ; 359 360 /** 361 * @see railo.runtime.search.SearchCollection#indexCustom(java.lang.String, railo.runtime.type.QueryColumn, railo.runtime.type.QueryColumn, railo.runtime.type.QueryColumn[], java.lang.String, railo.runtime.type.QueryColumn, railo.runtime.type.QueryColumn, railo.runtime.type.QueryColumn, railo.runtime.type.QueryColumn) 362 */ 363 public final IndexResult indexCustom(String id, QueryColumn title, QueryColumn keyColumn, QueryColumn[] bodyColumns, String language, 364 QueryColumn custom1, QueryColumn custom2, QueryColumn custom3, QueryColumn custom4) throws SearchException { 365 IndexResult ir=_indexCustom(id,title,keyColumn,bodyColumns,language,null,custom1,custom2,custom3,custom4); 366 changeLastUpdate(); 367 return ir; 368 } 369 /*public final IndexResult indexCustom(String id, QueryColumn title, QueryColumn keyColumn, QueryColumn[] bodyColumns, String language, 370 QueryColumn urlpath,QueryColumn custom1, QueryColumn custom2, QueryColumn custom3, QueryColumn custom4) throws SearchException { 371 IndexResult ir=_indexCustom(id,title,keyColumn,bodyColumns,language,urlpath,custom1,custom2,custom3,custom4); 372 changeLastUpdate(); 373 return ir; 374 }*/ 375 public final IndexResult indexCustom(String id, Object title, QueryColumn keyColumn, QueryColumn[] bodyColumns, String language, 376 Object urlpath,Object custom1, Object custom2, Object custom3, Object custom4) throws SearchException { 377 IndexResult ir=_indexCustom(id,title,keyColumn,bodyColumns,language,urlpath,custom1,custom2,custom3,custom4); 378 changeLastUpdate(); 379 return ir; 380 } 381 382 383 public final IndexResult deleteCustom(String id, QueryColumn keyColumn) throws SearchException { 384 IndexResult ir = _deleteCustom(id,keyColumn); 385 changeLastUpdate(); 386 return ir; 387 } 388 389 protected abstract IndexResult _deleteCustom(String id, QueryColumn keyColumn) throws SearchException; 390 391 /** 392 * updates a collection with a custom 393 * @param id 394 * @param title Title for the Index 395 * @param keyColumn Key Column 396 * @param bodyColumns Body Column Array 397 * @param language Language for index 398 * @param custom1 399 * @param custom2 400 * @param custom3 401 * @param custom4 402 * @throws SearchException 403 */ 404 //protected abstract IndexResult _indexCustom(String id,QueryColumn title, QueryColumn keyColumn, QueryColumn[] bodyColumns, String language, QueryColumn custom1, QueryColumn custom2, QueryColumn custom3, QueryColumn custom4) throws SearchException; 405 protected abstract IndexResult _indexCustom( 406 String id,Object title, QueryColumn keyColumn, QueryColumn[] bodyColumns, String language, Object urlpath 407 , Object custom1, Object custom2, Object custom3, Object custom4) throws SearchException; 408 409 /** 410 * @param index 411 * @throws SearchException 412 */ 413 private void createIndex(SearchIndex index) throws SearchException { 414 Iterator<String> it = indexes.keySet().iterator(); 415 SearchIndex otherIndex=null; 416 417 while(it.hasNext()) { 418 Object key=it.next(); 419 if(key.equals(index.getId())) { 420 otherIndex=indexes.get(key); 421 break; 422 } 423 } 424 425 Element collElement=searchEngine.getCollectionElement(name); 426 427 // Insert 428 if(otherIndex==null) { 429 addIndex(index); 430 collElement.appendChild(searchEngine.toElement(index)); 431 } 432 // Update 433 else { 434 addIndex(index); 435 Element el=searchEngine.getIndexElement(collElement,index.getId()); 436 searchEngine.setAttributes(el,index); 437 } 438 changeLastUpdate(); 439 } 440 441 /** 442 * @param index 443 */ 444 public void addIndex(SearchIndex index) { 445 indexes.put(index.getId(),index); 446 } 447 448 /** 449 * @see railo.runtime.search.SearchCollection#getLanguage() 450 */ 451 public final String getLanguage() { 452 return language; 453 } 454 455 /** 456 * @see railo.runtime.search.SearchCollection#purge() 457 */ 458 public final IndexResult purge() throws SearchException { 459 Lock l = lock(); 460 try { 461 indexes.clear(); 462 IndexResult ir=_purge(); 463 searchEngine.purgeCollection(this); 464 changeLastUpdate(); 465 return ir; 466 } 467 finally { 468 unlock(l); 469 } 470 } 471 472 /** 473 * purge a collection 474 * @throws SearchException 475 */ 476 protected abstract IndexResult _purge() throws SearchException; 477 478 /** 479 * @see railo.runtime.search.SearchCollection#delete() 480 */ 481 public final IndexResult delete() throws SearchException { 482 Lock l = lock(); 483 try { 484 IndexResult ir=_delete(); 485 searchEngine.removeCollection(this); 486 return ir; 487 } 488 finally { 489 unlock(l); 490 } 491 } 492 493 /** 494 * delete the collection from a file 495 * @throws SearchException 496 */ 497 protected abstract IndexResult _delete() throws SearchException; 498 499 /** 500 * @see railo.runtime.search.SearchCollection#deleteIndex(railo.runtime.PageContext, java.lang.String, short, java.lang.String) 501 */ 502 public final IndexResult deleteIndex(PageContext pc,String key,short type,String queryName) throws SearchException { 503 //if(queryName==null) queryName=""; 504 Key k; 505 506 if(type==SearchIndex.TYPE_CUSTOM) { 507 // delete all when no key is defined 508 if(StringUtil.isEmpty(key,true)) 509 return deleteIndexNotCustom(pc, key, type, queryName); 510 511 try{ 512 Query qv; 513 if(!StringUtil.isEmpty(queryName)) { 514 k=KeyImpl.init(key); 515 qv = Caster.toQuery(pc.getVariable(queryName)); 516 } 517 else { 518 k=KeyImpl.ID; 519 Key[] cols = new Key[]{k}; 520 String[] types = new String[]{"VARCHAR"}; 521 qv=new QueryImpl(cols,types, 1,"query"); 522 qv.setAtEL(k, 1, key); 523 } 524 525 526 527 QueryColumn keyColumn=qv.getColumn(k); 528 return deleteCustom("custom", keyColumn); 529 } 530 catch(PageException pe){ 531 throw new SearchException(pe); 532 } 533 } 534 return deleteIndexNotCustom(pc, key, type, queryName); 535 536 537 } 538 539 540 public final IndexResult deleteIndexNotCustom(PageContext pc,String key,short type,String queryName) throws SearchException { 541 Iterator<String> it = indexes.keySet().iterator(); 542 while(it.hasNext()) { 543 String id = it.next(); 544 if(id.equals(SearchIndex.toId(type,key,queryName))) { 545 SearchIndex index=indexes.get(id); 546 547 IndexResult ir=_deleteIndex(index.getId()); 548 Element indexEl=searchEngine.getIndexElement(searchEngine.getCollectionElement(name),index.getId()); 549 if(indexEl!=null)indexEl.getParentNode().removeChild(indexEl); 550 changeLastUpdate(); 551 return ir; 552 } 553 } 554 return new IndexResultImpl(0,0,0); 555 } 556 557 /** 558 * delete a Index from collection 559 * @param id id ofthe Index to delete 560 * @throws SearchException 561 */ 562 protected abstract IndexResult _deleteIndex(String id) throws SearchException; 563 564 /** 565 * @see railo.runtime.search.SearchCollection#getPath() 566 */ 567 public final Resource getPath() { 568 return path; 569 } 570 571 /** 572 * @see railo.runtime.search.SearchCollection#getCreated() 573 */ 574 public DateTime getCreated() { 575 return created; 576 } 577 578 /** 579 * @see railo.runtime.search.SearchCollection#getLastUpdate() 580 */ 581 public final DateTime getLastUpdate() { 582 return lastUpdate; 583 } 584 585 /** 586 * @see railo.runtime.search.SearchCollection#getName() 587 */ 588 public final String getName() { 589 return name; 590 } 591 592 /** 593 * @see railo.runtime.search.SearchCollection#getLogger() 594 */ 595 public final Log getLogger() { 596 return log; 597 } 598 599 /** 600 * @see railo.runtime.search.SearchCollection#getSearchEngine() 601 */ 602 public final SearchEngine getSearchEngine() { 603 return searchEngine; 604 } 605 606 /** 607 * change the last update attribute and store it 608 * @throws SearchException 609 */ 610 private void changeLastUpdate() throws SearchException { 611 lastUpdate=new DateTimeImpl(); 612 searchEngine.store(); 613 } 614 615 /** 616 * @see railo.runtime.search.SearchCollection#created() 617 */ 618 public Object created() { 619 return created; 620 } 621 622 /** 623 * @see railo.runtime.search.SearchCollection#search(railo.runtime.search.SearchData, railo.runtime.type.Query, java.lang.String, java.lang.String, short, int, int, java.lang.String, java.lang.String[]) 624 */ 625 public final int search(SearchData data, Query qry,String criteria, String language, short type,int startrow,int maxrow,String categoryTree, String[] categories) throws SearchException, PageException { 626 int len=qry.getRecordcount(); 627 SearchResulItem[] records; 628 629 AddionalAttrs aa = AddionalAttrs.getAddionlAttrs(); 630 boolean hasRowHandling=false; 631 aa.setStartrow(startrow); 632 if(maxrow!=-1)aa.setMaxrows(maxrow-len); 633 634 Lock l = lock(); 635 try { 636 records = _search(data, criteria,language,type,categoryTree,categories); 637 } 638 finally { 639 unlock(l); 640 if(hasRowHandling=aa.hasRowHandling()) 641 startrow = aa.getStartrow(); 642 643 } 644 645 646 647 // Startrow 648 if(!hasRowHandling && startrow>1) { 649 650 if(startrow>records.length) { 651 return startrow-records.length; 652 } 653 int start=startrow-1; 654 655 SearchResulItem[] tmpRecords=new SearchResulItem[records.length-start]; 656 for(int i=start;i<records.length;i++) { 657 tmpRecords[i-start]=records[i]; 658 } 659 records=tmpRecords; 660 startrow=1; 661 } 662 663 664 if(!ArrayUtil.isEmpty(records)) { 665 666 int to=(!hasRowHandling && maxrow>-1 && len+records.length>maxrow)?maxrow-len:records.length; 667 qry.addRow(to); 668 669 String title; 670 String custom1; 671 String custom2; 672 String custom3; 673 String custom4; 674 String url; 675 SearchResultItemPro record; 676 SearchIndex si; 677 boolean hasContextSummary=false; 678 for(int y=0;y<to;y++) { 679 680 int row=len+y+1; 681 record = SearchResulItemImpl.toSearchResultItemPro(records[y]); 682 if(y==0)hasContextSummary=record instanceof SearchResultItemPro; 683 si=(SearchIndex)indexes.get(record.getId()); 684 685 title=record.getTitle(); 686 custom1=record.getCustom1(); 687 custom2=record.getCustom2(); 688 custom3=record.getCustom3(); 689 custom4=record.getCustom4(); 690 url=record.getUrl(); 691 692 qry.setAt(KeyImpl.TITLE,row,title); 693 qry.setAt("custom1",row,custom1); 694 qry.setAt("custom2",row,custom2); 695 qry.setAt("custom3",row,custom3); 696 qry.setAt("custom4",row,custom4); 697 qry.setAt("categoryTree",row,record.getCategoryTree()); 698 qry.setAt("category",row,record.getCategory()); 699 qry.setAt(KeyImpl.TYPE,row,record.getMimeType()); 700 qry.setAt("author",row,record.getAuthor()); 701 qry.setAt(KeyImpl.SIZE,row,record.getSize()); 702 703 qry.setAt("summary",row,record.getSummary()); 704 if(hasContextSummary)qry.setAt("context",row,((SearchResultItemPro)record).getContextSummary()); 705 qry.setAt("score",row,new Float(record.getScore())); 706 qry.setAt(KeyImpl.KEY,row,record.getKey()); 707 qry.setAt(KeyImpl.URL,row,url); 708 qry.setAt("collection",row,getName()); 709 qry.setAt("rank",row,new Double(row)); 710 String rootPath,file; 711 String urlPath; 712 if(si!=null) { 713 switch(si.getType()){ 714 case SearchIndex.TYPE_PATH: 715 rootPath = si.getKey(); 716 rootPath=rootPath.replace(FileUtil.FILE_ANTI_SEPERATOR,FileUtil.FILE_SEPERATOR); 717 file=record.getKey(); 718 file=file.replace(FileUtil.FILE_ANTI_SEPERATOR,FileUtil.FILE_SEPERATOR); 719 qry.setAt(KeyImpl.URL,row,toURL(si.getUrlpath(),StringUtil.replace(file, rootPath, "", true))); 720 721 722 break; 723 case SearchIndex.TYPE_URL: 724 rootPath = si.getKey(); 725 urlPath = si.getUrlpath(); 726 try { 727 rootPath = getDirectory(si.getKey()); 728 } 729 catch (MalformedURLException e) {} 730 if(StringUtil.isEmpty(urlPath))urlPath=rootPath; 731 file=record.getKey(); 732 qry.setAt(KeyImpl.URL,row,toURL(urlPath,StringUtil.replace(file, rootPath, "", true))); 733 734 735 break; 736 case SearchIndex.TYPE_CUSTOM: 737 qry.setAt(KeyImpl.URL,row,url); 738 break; 739 default: 740 qry.setAt(KeyImpl.URL,row,toURL(si.getUrlpath(),url)); 741 break; 742 } 743 744 745 if(StringUtil.isEmpty(title)) qry.setAt(KeyImpl.TITLE,row,si.getTitle()); 746 if(StringUtil.isEmpty(custom1)) qry.setAt("custom1",row,si.getCustom1()); 747 if(StringUtil.isEmpty(custom2)) qry.setAt("custom2",row,si.getCustom2()); 748 if(StringUtil.isEmpty(custom3)) qry.setAt("custom3",row,si.getCustom3()); 749 if(StringUtil.isEmpty(custom4)) qry.setAt("custom4",row,si.getCustom4()); 750 751 } 752 } 753 } 754 return startrow; 755 } 756 757 public static String getDirectory(String strUrl) throws MalformedURLException { 758 URL url = new URL(strUrl); 759 String path=url.getPath(); 760 int slashIndex = path.lastIndexOf('/'); 761 int dotIndex = path.lastIndexOf('.'); 762 // no dot 763 if(dotIndex==-1){ 764 if(path.endsWith("/"))return HTTPUtil.removeRef(url).toExternalForm(); 765 return HTTPUtil.removeRef(new URL( 766 url.getProtocol(), 767 url.getHost(), 768 url.getPort(),path+"/")).toExternalForm(); 769 } 770 if(slashIndex>dotIndex){ 771 path=path.substring(0,dotIndex); 772 slashIndex = path.lastIndexOf('/'); 773 } 774 775 return HTTPUtil.removeRef(new URL( 776 url.getProtocol(), 777 url.getHost(), 778 url.getPort(),path.substring(0,slashIndex+1))).toExternalForm(); 779 } 780 781 private static String toURL(String url, String path) { 782 if(StringUtil.isEmpty(url)) return path; 783 if(StringUtil.isEmpty(path)) return url; 784 785 url=url.replace('\\','/'); 786 path=path.replace('\\','/'); 787 if(StringUtil.startsWith(path, '/'))path=path.substring(1); 788 if(StringUtil.endsWith(url, '/'))url=url.substring(0,url.length()-1); 789 790 if(StringUtil.startsWithIgnoreCase(path, url)) 791 return path; 792 return url+"/"+path; 793 } 794 795 796 797 798 799 protected SearchIndex[] getIndexes() { 800 Iterator<Entry<String, SearchIndex>> it = indexes.entrySet().iterator(); 801 int len=indexes.size(); 802 SearchIndex[] rtn=new SearchIndex[len]; 803 int count=0; 804 while(it.hasNext()) { 805 rtn[count++]=it.next().getValue(); 806 } 807 return rtn; 808 } 809 810 811 private Lock lock() throws SearchException { 812 try { 813 return lock.lock(getId(),LOCK_TIMEOUT); 814 //manager.lock(LockManager.TYPE_EXCLUSIVE,getId(),LOCK_TIMEOUT,ThreadLocalPageContext.get().getId()); 815 } 816 catch (Exception e) { 817 throw new SearchException(e); 818 } 819 820 } 821 822 private void unlock(Lock l) { 823 lock.unlock(l); 824 //manager.unlock(ThreadLocalPageContext.get().getId()); 825 } 826 827 828 private String getId() { 829 return path.getRealResource(name).getAbsolutePath(); 830 } 831 832 // FUTURE 833 public Object getIndexesAsQuery() { 834 Iterator<Entry<String, SearchIndex>> it = indexes.entrySet().iterator(); 835 836 final String v="VARCHAR"; 837 Query query=null; 838 String[] cols = new String[]{ 839 "categories","categoryTree","custom1","custom2","custom3","custom4","extensions", 840 "key","language","query","title","urlpath","type"}; 841 String[] types = new String[]{ 842 v,v,v,v,v,v,v, 843 v,v,v,v,v,v}; 844 try { 845 query=new QueryImpl(cols,types, 0,"query"); 846 } catch (DatabaseException e) { 847 query=new QueryImpl(cols, 0,"query"); 848 } 849 850 Entry<String, SearchIndex> entry; 851 SearchIndex index; 852 int row=0; 853 while(it.hasNext()) { 854 query.addRow(); 855 row++; 856 entry = it.next(); 857 index= entry.getValue(); 858 if(index==null)continue; 859 try { 860 861 query.setAt("categories",row,List.arrayToList(index.getCategories(),"")); 862 query.setAt("categoryTree",row,index.getCategoryTree()); 863 864 query.setAt("custom1",row,index.getCustom1()); 865 query.setAt("custom2",row,index.getCustom2()); 866 query.setAt("custom3",row,index.getCustom3()); 867 query.setAt("custom4",row,index.getCustom4()); 868 869 query.setAt("extensions",row,List.arrayToList(index.getExtensions(),",")); 870 query.setAt(KeyImpl.KEY,row,index.getKey()); 871 query.setAt("language",row,index.getLanguage()); 872 query.setAt("query",row,index.getQuery()); 873 query.setAt(KeyImpl.TITLE,row,index.getTitle()); 874 query.setAt("urlpath",row,index.getUrlpath()); 875 query.setAt(KeyImpl.TYPE,row,SearchIndex.toStringTypeEL(index.getType())); 876 877 } 878 catch(PageException pe) {} 879 } 880 return query; 881 } 882 883 }