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