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