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.config;
020
021import java.io.IOException;
022import java.net.URL;
023import java.util.Enumeration;
024import java.util.Map;
025
026import javax.servlet.ServletConfig;
027import javax.servlet.ServletContext;
028import javax.servlet.http.HttpServletRequest;
029import javax.servlet.http.HttpServletResponse;
030
031import lucee.commons.digest.HashUtil;
032import lucee.commons.io.SystemUtil;
033import lucee.commons.io.res.Resource;
034import lucee.commons.io.res.ResourceProvider;
035import lucee.commons.io.res.ResourcesImpl;
036import lucee.commons.lang.StringUtil;
037import lucee.commons.lock.KeyLock;
038import lucee.runtime.CFMLFactoryImpl;
039import lucee.runtime.Mapping;
040import lucee.runtime.MappingImpl;
041import lucee.runtime.Page;
042import lucee.runtime.PageContext;
043import lucee.runtime.PageSourceImpl;
044import lucee.runtime.cache.tag.CacheHandlerFactoryCollection;
045import lucee.runtime.cfx.CFXTagPool;
046import lucee.runtime.compiler.CFMLCompilerImpl;
047import lucee.runtime.debug.DebuggerPool;
048import lucee.runtime.engine.ThreadQueue;
049import lucee.runtime.exp.ExpressionException;
050import lucee.runtime.exp.PageException;
051import lucee.runtime.exp.SecurityException;
052import lucee.runtime.gateway.GatewayEngineImpl;
053import lucee.runtime.gateway.GatewayEntry;
054import lucee.runtime.lock.LockManager;
055import lucee.runtime.lock.LockManagerImpl;
056import lucee.runtime.monitor.ActionMonitorCollector;
057import lucee.runtime.monitor.IntervallMonitor;
058import lucee.runtime.monitor.RequestMonitor;
059import lucee.runtime.net.http.ReqRspUtil;
060import lucee.runtime.security.SecurityManager;
061import lucee.runtime.security.SecurityManagerImpl;
062import lucee.runtime.tag.TagHandlerPool;
063import lucee.runtime.type.scope.Cluster;
064import lucee.runtime.writer.CFMLWriter;
065import lucee.runtime.writer.CFMLWriterImpl;
066import lucee.runtime.writer.CFMLWriterWS;
067import lucee.runtime.writer.CFMLWriterWSPref;
068
069import org.apache.commons.collections.map.ReferenceMap;
070import org.xml.sax.SAXException;
071
072/**
073 * Web Context
074 */
075public final class ConfigWebImpl extends ConfigImpl implements ServletConfig, ConfigWeb {
076    
077    private ServletConfig config;
078    private ConfigServerImpl configServer;
079    private SecurityManager securityManager;
080    private static final LockManager lockManager= LockManagerImpl.getInstance(false);
081        private Resource rootDir;
082    private CFMLCompilerImpl compiler=new CFMLCompilerImpl();
083    private Page baseComponentPage;
084        private MappingImpl serverTagMapping;
085        private MappingImpl serverFunctionMapping;
086        private KeyLock<String> contextLock;
087        private GatewayEngineImpl gatewayEngine;
088    private DebuggerPool debuggerPool;
089    private CacheHandlerFactoryCollection cacheHandlerFactoryCollection;
090    
091    
092
093    //private File deployDirectory;
094
095    /**
096     * constructor of the class
097     * @param configServer
098     * @param config
099     * @param configDir
100     * @param configFile
101     * @param cloneServer 
102     */
103    protected ConfigWebImpl(CFMLFactoryImpl factory,ConfigServerImpl configServer, ServletConfig config, Resource configDir, Resource configFile) {
104        super(factory,configDir, configFile,configServer.getTLDs(),configServer.getFLDs());
105        this.configServer=configServer;
106        this.config=config;
107        factory.setConfig(this);
108        ResourceProvider frp = ResourcesImpl.getFileResourceProvider();
109        
110        this.rootDir=frp.getResource(ReqRspUtil.getRootPath(config.getServletContext()));
111        
112        
113        // Fix for tomcat
114        if(this.rootDir.getName().equals(".") || this.rootDir.getName().equals(".."))
115                this.rootDir=this.rootDir.getParentResource();
116    }
117    
118    public void reset() {
119        super.reset();
120        tagHandlerPool.reset();
121        contextLock=null;
122        baseComponentPage=null;
123    }
124    
125    /* *
126     * Constructor of the class, used for configserver dummy instance
127     * @param factory
128     * @param configServer
129     * @param configx
130     * @param configDir
131     * @param configFile
132     * /
133    protected ConfigWebImpl(CFMLFactoryImpl factory,ConfigServerImpl configServer, Resource configDir, Resource configFile,Resource rootDir) {
134        super(factory,configDir, configFile,configServer.getTLDs(),configServer.getFLDs());
135        this.configServer=configServer;
136        factory.setConfig(this);
137        
138        this.rootDir=rootDir;
139        
140        // Fix for tomcat
141        if(this.rootDir.getName().equals(".") || this.rootDir.getName().equals(".."))
142                this.rootDir=this.rootDir.getParentResource();
143    }*/
144    
145    
146
147    @Override
148    public String getServletName() {
149        return config.getServletName();
150    }
151
152    @Override
153    public ServletContext getServletContext() {
154        return config.getServletContext();
155    }
156
157    @Override
158    public String getInitParameter(String name) {
159        return config.getInitParameter(name);
160    }
161
162    @Override
163    public Enumeration getInitParameterNames() {
164        return config.getInitParameterNames();
165    }
166
167    protected ConfigServerImpl getConfigServerImpl() {
168        return configServer;
169    }
170    
171    @Override
172    public ConfigServer getConfigServer(String password) throws ExpressionException {
173        configServer.checkAccess(password);
174        return configServer;
175    }
176    
177    // FUTURE add to public interface
178    public ConfigServer getConfigServer(String key, long timeNonce) throws PageException {
179        configServer.checkAccess(key,timeNonce);
180        return configServer;
181    }
182    
183    public String getServerId() {
184        return configServer.getId();
185    }
186    
187    public String getServerIdPro() {
188        return configServer.getIdPro();
189    }
190
191    public String getServerSecurityKey() {
192        return configServer.getSecurityKey();
193    }
194    
195    public Resource getServerConfigDir() {
196        return configServer.getConfigDir();
197    }
198    
199
200    /**
201     * @return Returns the accessor.
202     */
203    public SecurityManager getSecurityManager() {
204        return securityManager;
205    }
206
207    /**
208     * @param securityManager The accessor to set.
209     */
210    protected void setSecurityManager(SecurityManager securityManager) {
211        ((SecurityManagerImpl)securityManager).setRootDirectory(getRootDirectory());
212        this.securityManager = securityManager;
213    }
214    
215    @Override
216    public CFXTagPool getCFXTagPool() throws SecurityException {
217        if(securityManager.getAccess(SecurityManager.TYPE_CFX_USAGE)==SecurityManager.VALUE_YES) return super.getCFXTagPool();
218        throw new SecurityException("no access to cfx functionality", "disabled by security settings");
219    }
220
221    /**
222     * @return Returns the rootDir.
223     */
224    public Resource getRootDirectory() {
225        return rootDir;
226    }
227
228    @Override
229    public String getUpdateType() {
230        return configServer.getUpdateType();
231    }
232
233    @Override
234    public URL getUpdateLocation() {
235        return configServer.getUpdateLocation();
236    }
237
238    @Override
239    public LockManager getLockManager() {
240        return lockManager;
241    }
242
243        /**
244         * @return the compiler
245         */
246        public CFMLCompilerImpl getCompiler() {
247                return compiler;
248        }
249        
250         public Page getBaseComponentPage(PageContext pc) throws PageException {
251                if(baseComponentPage==null) {
252                    baseComponentPage=((PageSourceImpl)getBaseComponentPageSource(pc)).loadPage(pc);
253                                
254                }
255                return baseComponentPage;
256            }
257            public void resetBaseComponentPage() {
258                baseComponentPage=null;
259            }
260            
261
262
263                
264
265            public Mapping getServerTagMapping() {
266                if(serverTagMapping==null){
267                        serverTagMapping=getConfigServerImpl().tagMapping.cloneReadOnly(this);
268                }
269                        return serverTagMapping;
270                }
271            public Mapping getServerFunctionMapping() {
272                if(serverFunctionMapping==null){
273                        serverFunctionMapping=getConfigServerImpl().functionMapping.cloneReadOnly(this);
274                }
275                        return serverFunctionMapping;
276                }
277            private Map<String,Mapping> applicationMappings=new ReferenceMap(ReferenceMap.SOFT,ReferenceMap.SOFT);
278
279            
280            
281                private TagHandlerPool tagHandlerPool=new TagHandlerPool(this);
282                
283                // FYI used by Extensions, do not remove
284                public Mapping getApplicationMapping(String virtual, String physical) {
285                        return getApplicationMapping("application",virtual, physical,null,true,false);
286                }
287
288                public Mapping getApplicationMapping(String type,String virtual, String physical,String archive,boolean physicalFirst, boolean ignoreVirtual) {
289                        String key=type+":"+
290                                virtual.toLowerCase()
291                                +":"+(physical==null?"":physical.toLowerCase())
292                                +":"+(archive==null?"":archive.toLowerCase())
293                                +":"+physicalFirst;
294                        key=Long.toString(HashUtil.create64BitHash(key),Character.MAX_RADIX);
295                        
296                        
297                        Mapping m=applicationMappings.get(key);
298                        
299                        if(m==null){
300                                m=new MappingImpl(
301                                        this,virtual,
302                                        physical,
303                                        archive,ConfigImpl.INSPECT_UNDEFINED,physicalFirst,false,false,false,true,ignoreVirtual,null
304                                        );
305                                applicationMappings.put(key,m);
306                        }
307                        
308                        return m;
309                }
310
311                public String getLabel() {
312                        String hash=getHash();
313                        String label=hash;
314                        Map<String, String> labels = configServer.getLabels();
315                        if(labels!=null) {
316                                String l = labels.get(hash);
317                                if(!StringUtil.isEmpty(l)) {
318                                        label=l;
319                                }
320                        }
321                        return label;
322                }
323                
324                public String getHash() {
325                        return SystemUtil.hash(getServletContext());
326                }
327
328                public KeyLock<String> getContextLock() {
329                        if(contextLock==null) {
330                                contextLock=new KeyLock<String>();
331                        }
332                        return contextLock;
333                }
334
335
336                protected void setGatewayEntries(Map<String, GatewayEntry> gatewayEntries) {
337                        try {
338                                getGatewayEngine().addEntries(this,gatewayEntries);
339                        } catch (Exception e) {
340                                e.printStackTrace();
341                        }       
342                }
343                public GatewayEngineImpl getGatewayEngine() {
344                        if(gatewayEngine==null){
345                                gatewayEngine=new GatewayEngineImpl(this);
346                        }
347                        return gatewayEngine;
348                }
349                public void setGatewayEngine(GatewayEngineImpl gatewayEngine) {
350                        this.gatewayEngine=gatewayEngine;
351                }
352
353                public TagHandlerPool getTagHandlerPool() {
354                        return tagHandlerPool;
355                }
356
357                public DebuggerPool getDebuggerPool() {
358                        if(debuggerPool==null){
359                                Resource dir = getConfigDir().getRealResource("debugger");
360                                dir.mkdirs();
361                                debuggerPool=new DebuggerPool(dir);
362                        }
363                        return debuggerPool;
364                }
365                
366
367                public ThreadQueue getThreadQueue() {
368                        return configServer.getThreadQueue();
369                }
370
371                @Override
372                public int getLoginDelay() {
373                        return configServer.getLoginDelay();
374                }
375
376                @Override
377                public boolean getLoginCaptcha() {
378                        return configServer.getLoginCaptcha();
379                }
380
381                @Override
382                public boolean getRememberMe() {
383                        return configServer.getRememberMe();
384                }
385                
386                @Override
387                public Resource getSecurityDirectory(){
388                        return configServer.getSecurityDirectory();
389                }
390                
391                @Override
392                public boolean isMonitoringEnabled(){
393                        return configServer.isMonitoringEnabled();
394                }
395                
396
397                
398                public RequestMonitor[] getRequestMonitors(){
399                        return configServer.getRequestMonitors();
400                }
401                
402                public RequestMonitor getRequestMonitor(String name) throws PageException{
403                        return configServer.getRequestMonitor(name);
404                }
405                
406                public IntervallMonitor[] getIntervallMonitors(){
407                        return configServer.getIntervallMonitors();
408                }
409
410                public IntervallMonitor getIntervallMonitor(String name) throws PageException{
411                        return configServer.getIntervallMonitor(name);
412                }
413                
414                @Override
415                public void checkPermGenSpace(boolean check) {
416                        configServer.checkPermGenSpace(check);
417                }
418
419                @Override
420                public Cluster createClusterScope() throws PageException {
421                        return configServer.createClusterScope();
422                }
423
424                @Override
425                public boolean hasServerPassword() {
426                        return configServer.hasPassword();
427                }
428                
429                public void updatePassword(boolean server, String passwordOld, String passwordNew) throws PageException, IOException, SAXException {
430                        Password.updatePassword(server?configServer:this,passwordOld,passwordNew);
431                }
432                
433                public void updatePassword(boolean server, Password passwordOld, Password passwordNew) throws PageException, IOException, SAXException {
434                        Password.updatePassword(server?configServer:this,passwordOld,passwordNew);
435                }
436                
437                public Password updatePasswordIfNecessary(boolean server,String passwordRaw) {
438                        ConfigImpl config=server?configServer:this;
439                        return Password.updatePasswordIfNecessary(config,config.password,passwordRaw);
440                }
441
442                @Override
443                public Resource getConfigServerDir() {
444                        return configServer.getConfigDir();
445                }
446
447                public Map<String, String> getAllLabels() {
448                        return configServer.getLabels();
449                }
450
451                @Override
452                public boolean allowRequestTimeout() {
453                        return configServer.allowRequestTimeout();
454                }
455                
456                public CFMLWriter getCFMLWriter(PageContext pc, HttpServletRequest req, HttpServletResponse rsp) {
457                        // FUTURE  move interface CFMLWriter to Loader and load dynaicly from lucee-web.xml
458                if(writerType==CFML_WRITER_WS)
459                    return new CFMLWriterWS             (pc,req,rsp,-1,false,closeConnection(),isShowVersion(),contentLength());
460                else if(writerType==CFML_WRITER_REFULAR) 
461                    return new CFMLWriterImpl                   (pc,req,rsp,-1,false,closeConnection(),isShowVersion(),contentLength());
462                else
463                    return new CFMLWriterWSPref (pc,req,rsp,-1,false,closeConnection(),isShowVersion(),contentLength());
464            }
465
466                
467                public ActionMonitorCollector getActionMonitorCollector() {
468                        return configServer.getActionMonitorCollector();
469                }
470
471                @Override
472                public boolean getFullNullSupport() {
473                        return configServer.getFullNullSupport();
474                }
475                public boolean hasIndividualSecurityManager() {
476                        return configServer.hasIndividualSecurityManager(getId());
477            }
478                public String getServerApiKey() {
479                        return configServer.getApiKey();
480            }
481                
482                public CacheHandlerFactoryCollection getCacheHandlerFactories(){
483                        if(cacheHandlerFactoryCollection==null)
484                                cacheHandlerFactoryCollection=new CacheHandlerFactoryCollection(this);
485                        return cacheHandlerFactoryCollection;
486                }
487                
488
489                public int getServerPasswordType() {
490                        return configServer.getPasswordType();
491                }
492                public String getServerPasswordSalt() {
493                        return configServer.getPasswordSalt();
494                }
495                public int getServerPasswordOrigin() {
496                        return configServer.getPasswordOrigin();
497                }
498                
499                public String getServerSalt() {
500                        return configServer.getSalt();
501                }
502
503                public Password isServerPasswordEqual(String password, boolean hashIfNecessary) {
504                        return configServer.isPasswordEqual(password, hashIfNecessary);
505                }
506
507                public boolean isDefaultPassword() {
508                        if(password==null) return false;
509                        return password==configServer.defaultPassword;
510                }
511}