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