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.tag;
020
021import lucee.commons.io.res.Resource;
022import lucee.commons.io.res.util.ResourceUtil;
023import lucee.commons.lang.StringUtil;
024import lucee.runtime.exp.ApplicationException;
025import lucee.runtime.exp.PageException;
026import lucee.runtime.ext.tag.TagImpl;
027import lucee.runtime.op.Caster;
028import lucee.runtime.search.SearchCollection;
029import lucee.runtime.search.SearchEngine;
030import lucee.runtime.search.SearchException;
031
032/**
033* Allows you to create and administer Collections.
034**/
035public final class Collection extends TagImpl {
036
037        /** Specifies the action to perform. */
038        private String action="list";
039
040        /**  */
041        private Resource path;
042
043        /** Specifies a collection name or an alias if action = "map" */
044        private String collection;
045
046        /** Name of the output variable (action=list) */
047        private String name;
048
049        /** language of the collection (operators,stopwords) */
050        private String language="english";
051        
052        //private boolean categories=false;
053
054
055        @Override
056        public void release()   {
057                super.release();
058                action="list";
059                path=null;
060                collection=null;
061                name=null;
062                language="english";
063                //categories=false;
064        }
065        
066
067        /**
068         * @param categories the categories to set
069         * @throws ApplicationException 
070         */
071        public void setCategories(boolean categories) {
072                // Lucee always support categories
073                //this.categories = categories;
074        }
075        
076        /** set the value action
077        *  Specifies the action to perform.
078        * @param action value to set
079        **/
080        public void setAction(String action)    {
081                if(action==null) return;
082                this.action=action.toLowerCase().trim();
083        }
084        
085
086        public void setEngine(String engine)    {
087                // This setter only exists for compatibility reasions to other CFML engines, the attribute is completely ignored by Lucee.
088        }
089
090        /** set the value path
091        *  
092        * @param path value to set
093         * @throws PageException 
094        **/
095        public void setPath(String strPath) throws PageException        {
096                if(strPath==null) return;
097            this.path=ResourceUtil.toResourceNotExisting(pageContext,strPath.trim() );
098                //this.path=new File(path.toLowerCase().trim());
099
100                pageContext.getConfig().getSecurityManager().checkFileLocation(this.path);
101                
102            if(!this.path.exists()) {
103                Resource parent=this.path.getParentResource();
104                if(parent!=null && parent.exists())this.path.mkdirs();
105                else {
106                    throw new ApplicationException("attribute path of the tag collection must be a existing directory");
107                }
108            }
109                else if(!this.path.isDirectory())
110                    throw new ApplicationException("attribute path of the tag collection must be a existing directory");
111        }
112
113        /** set the value collection
114        *  Specifies a collection name or an alias if action = "map"
115        * @param collection value to set
116        **/
117        public void setCollection(String collection)    {
118                if(collection==null) return;
119                this.collection=collection.toLowerCase().trim();
120        }
121
122        /** set the value name
123        *  
124        * @param name value to set
125        **/
126        public void setName(String name)        {
127                if(name==null) return;
128                this.name=name.toLowerCase().trim();
129        }
130
131        /** set the value language
132        *  
133        * @param language value to set
134        **/
135        public void setLanguage(String language)        {
136                if(language==null) return;
137                this.language=validateLanguage(language);
138        }
139
140        public static String validateLanguage(String language) {
141                if(StringUtil.isEmpty(language,true)) 
142                        return "english"; 
143                language=language.toLowerCase().trim();
144                if("standard".equals(language))
145                        return "english";
146                return language;
147        }
148
149
150        @Override
151        public int doStartTag() throws PageException    {
152            //SerialNumber sn = pageContext.getConfig().getSerialNumber();
153            //if(sn.getVersion()==SerialNumber.VERSION_COMMUNITY)
154            //    throw new SecurityException("no access to this functionality with the "+sn.getStringVersion()+" version of lucee");
155            
156            try {
157                        if(action.equals("create"))                     doCreate();
158                        else if(action.equals("repair"))        doRepair();
159                        else if(action.equals("delete"))        doDelete();
160                        else if(action.equals("optimize"))      doOptimize();
161                        else if(action.equals("list"))          doList();
162                        else if(action.equals("map"))           doMap();
163                        else if(action.equals("categorylist"))doCategoryList();
164                        
165                        else throw new ApplicationException("Invalid value [" + action + "] for attribute action.", "allowed values are [create,repair,map,delete,optimize,list ]");
166                } catch (SearchException e) {
167                        throw Caster.toPageException(e);
168                }
169                return SKIP_BODY;
170        }
171
172        /**
173         * @throws SearchException
174         * @throws PageException 
175     * 
176     */
177    private void doMap() throws SearchException, PageException {
178        required("collection",action,"collection",collection);
179        required("collection",action,"path",path);
180                getCollection().map(path);
181    }
182
183        /**
184         * Creates a query in the PageContext containing all available Collections of the current searchStorage
185         * @throws ApplicationException
186         * @throws PageException
187         * 
188         */
189        private void doList() throws ApplicationException, PageException {
190                required("collection",action,"name",name);
191        //if(StringUtil.isEmpty(name))throw new ApplicationException("for action list attribute name is required");
192        pageContext.setVariable(name,getSearchEngine().getCollectionsAsQuery());
193        }
194        
195
196        private void doCategoryList() throws PageException, SearchException {
197                // check attributes
198                required("collection",action,"collection",collection);
199                required("collection",action,"name",name);
200                pageContext.setVariable(name,getCollection().getCategoryInfo());
201        }
202
203        /**
204         * Optimizes the Collection
205         * @throws SearchException
206         * @throws PageException 
207         * 
208         */
209        private void doOptimize() throws SearchException, PageException {
210            required("collection",action,"collection",collection);
211            getCollection().optimize();
212        }
213
214        /**
215         * Deletes a Collection
216         * @throws SearchException
217         * @throws PageException 
218         * 
219         */
220        private void doDelete() throws SearchException, PageException {
221            required("collection",action,"collection",collection);
222            getCollection().delete();
223        }
224
225        /**
226         * 
227         * @throws SearchException
228         * @throws PageException 
229         * 
230         */
231        private void doRepair() throws SearchException, PageException {
232            required("collection",action,"collection",collection);
233            getCollection().repair();
234        }
235
236        /**
237         * Creates a new collection
238         * @throws SearchException
239         * @throws PageException 
240         * 
241         */
242        private void doCreate() throws SearchException, PageException {
243            required("collection",action,"collection",collection);
244            required("collection",action,"path",path);
245                getSearchEngine().createCollection(collection,path,language,SearchEngine.DENY_OVERWRITE);
246        }
247
248    /**
249         * Returns the Searchstorage defined in the Environment
250         * @return searchStorage
251         */
252        private SearchEngine getSearchEngine() {
253            return pageContext.getConfig().getSearchEngine();
254        }
255
256    /**
257     * the collection matching the collection name
258     * @return collection
259     * @throws SearchException
260     */
261    private SearchCollection getCollection() throws SearchException {
262        return getSearchEngine().getCollectionByName(collection);
263    }
264
265    @Override
266        public int doEndTag()   {
267                return EVAL_PAGE;
268        }
269}