001    package railo.runtime.config;
002    
003    import java.io.IOException;
004    import java.io.PrintWriter;
005    import java.net.URL;
006    import java.util.ArrayList;
007    import java.util.Arrays;
008    import java.util.Collections;
009    import java.util.Comparator;
010    import java.util.HashMap;
011    import java.util.Iterator;
012    import java.util.List;
013    import java.util.Locale;
014    import java.util.Map;
015    import java.util.Map.Entry;
016    import java.util.TimeZone;
017    
018    import org.apache.commons.collections.map.ReferenceMap;
019    
020    import railo.commons.io.SystemUtil;
021    import railo.commons.io.log.Log;
022    import railo.commons.io.log.LogAndSource;
023    import railo.commons.io.log.LogAndSourceImpl;
024    import railo.commons.io.log.LogConsole;
025    import railo.commons.io.res.Resource;
026    import railo.commons.io.res.ResourceProvider;
027    import railo.commons.io.res.Resources;
028    import railo.commons.io.res.ResourcesImpl;
029    import railo.commons.io.res.filter.ExtensionResourceFilter;
030    import railo.commons.io.res.type.compress.Compress;
031    import railo.commons.io.res.type.compress.CompressResource;
032    import railo.commons.io.res.type.compress.CompressResourceProvider;
033    import railo.commons.io.res.util.ResourceClassLoader;
034    import railo.commons.io.res.util.ResourceUtil;
035    import railo.commons.lang.ClassException;
036    import railo.commons.lang.ClassUtil;
037    import railo.commons.lang.ExceptionUtil;
038    import railo.commons.lang.Md5;
039    import railo.commons.lang.PhysicalClassLoader;
040    import railo.commons.lang.StringUtil;
041    import railo.commons.lang.SystemOut;
042    import railo.commons.net.IPRange;
043    import railo.commons.net.JarLoader;
044    import railo.loader.engine.CFMLEngine;
045    import railo.runtime.CFMLFactory;
046    import railo.runtime.Component;
047    import railo.runtime.Mapping;
048    import railo.runtime.MappingImpl;
049    import railo.runtime.Page;
050    import railo.runtime.PageContext;
051    import railo.runtime.PageContextImpl;
052    import railo.runtime.PageSource;
053    import railo.runtime.PageSourceImpl;
054    import railo.runtime.cache.CacheConnection;
055    import railo.runtime.cfx.CFXTagPool;
056    import railo.runtime.cfx.customtag.CFXTagPoolImpl;
057    import railo.runtime.component.ImportDefintion;
058    import railo.runtime.component.ImportDefintionImpl;
059    import railo.runtime.customtag.InitFile;
060    import railo.runtime.db.DataSource;
061    import railo.runtime.db.DatasourceConnectionPool;
062    import railo.runtime.dump.DumpWriter;
063    import railo.runtime.dump.DumpWriterEntry;
064    import railo.runtime.dump.HTMLDumpWriter;
065    import railo.runtime.engine.ExecutionLogFactory;
066    import railo.runtime.engine.ThreadLocalPageContext;
067    import railo.runtime.exp.DatabaseException;
068    import railo.runtime.exp.DeprecatedException;
069    import railo.runtime.exp.ExpressionException;
070    import railo.runtime.exp.PageException;
071    import railo.runtime.exp.PageRuntimeException;
072    import railo.runtime.exp.SecurityException;
073    import railo.runtime.extension.Extension;
074    import railo.runtime.extension.ExtensionProvider;
075    import railo.runtime.extension.ExtensionProviderImpl;
076    import railo.runtime.listener.AppListenerUtil;
077    import railo.runtime.listener.ApplicationContext;
078    import railo.runtime.listener.ApplicationListener;
079    import railo.runtime.listener.JavaSettingsImpl;
080    import railo.runtime.net.amf.AMFCaster;
081    import railo.runtime.net.amf.ClassicAMFCaster;
082    import railo.runtime.net.amf.ModernAMFCaster;
083    import railo.runtime.net.mail.Server;
084    import railo.runtime.net.ntp.NtpClient;
085    import railo.runtime.net.proxy.ProxyData;
086    import railo.runtime.op.Caster;
087    import railo.runtime.orm.ORMConfiguration;
088    import railo.runtime.orm.ORMEngine;
089    import railo.runtime.orm.ORMException;
090    import railo.runtime.rest.RestSettingImpl;
091    import railo.runtime.rest.RestSettings;
092    import railo.runtime.schedule.Scheduler;
093    import railo.runtime.schedule.SchedulerImpl;
094    import railo.runtime.search.SearchEngine;
095    import railo.runtime.security.SecurityManager;
096    import railo.runtime.spooler.SpoolerEngine;
097    import railo.runtime.tag.Admin;
098    import railo.runtime.tag.util.DeprecatedUtil;
099    import railo.runtime.type.Struct;
100    import railo.runtime.type.StructImpl;
101    import railo.runtime.type.UDF;
102    import railo.runtime.type.dt.TimeSpan;
103    import railo.runtime.type.dt.TimeSpanImpl;
104    import railo.runtime.type.scope.Cluster;
105    import railo.runtime.type.scope.ClusterNotSupported;
106    import railo.runtime.type.scope.Undefined;
107    import railo.runtime.type.util.ArrayUtil;
108    import railo.runtime.type.util.KeyConstants;
109    import railo.runtime.video.VideoExecuterNotSupported;
110    import railo.transformer.library.function.FunctionLib;
111    import railo.transformer.library.function.FunctionLibException;
112    import railo.transformer.library.function.FunctionLibFactory;
113    import railo.transformer.library.function.FunctionLibFunction;
114    import railo.transformer.library.function.FunctionLibFunctionArg;
115    import railo.transformer.library.tag.TagLib;
116    import railo.transformer.library.tag.TagLibException;
117    import railo.transformer.library.tag.TagLibFactory;
118    import railo.transformer.library.tag.TagLibTag;
119    import railo.transformer.library.tag.TagLibTagAttr;
120    import flex.messaging.config.ConfigMap;
121    
122    
123    /**
124     * Hold the definitions of the railo configuration.
125     */
126    public abstract class ConfigImpl implements Config {
127    
128            public static final short INSPECT_UNDEFINED = 4;// FUTURE move to Config
129    
130    
131            public static final int CLIENT_BOOLEAN_TRUE = 0;
132            public static final int CLIENT_BOOLEAN_FALSE = 1;
133            public static final int SERVER_BOOLEAN_TRUE = 2;
134            public static final int SERVER_BOOLEAN_FALSE = 3;
135    
136            public static final int DEBUG_DATABASE = 1;
137            public static final int DEBUG_EXCEPTION = 2;
138            public static final int DEBUG_TRACING = 4;
139            public static final int DEBUG_TIMER = 8;
140            public static final int DEBUG_IMPLICIT_ACCESS = 16;
141            public static final int DEBUG_QUERY_USAGE = 32;
142            
143            
144            
145            
146            public static final ExtensionProvider[] RAILO_EXTENSION_PROVIDERS = new ExtensionProviderImpl[]{
147                    new ExtensionProviderImpl("http://www.getrailo.com/ExtensionProvider.cfc",true),
148                    new ExtensionProviderImpl("http://www.getrailo.org/ExtensionProvider.cfc",true)
149            };
150            private static final Extension[] EXTENSIONS_EMPTY = new Extension[0];
151            
152            public static final int AMF_CONFIG_TYPE_XML = 1;
153            public static final int AMF_CONFIG_TYPE_MANUAL = 2;
154    
155            public static final int MODE_CUSTOM = 1;
156            public static final int MODE_STRICT = 2;
157            
158    
159            public static final int CFML_WRITER_REFULAR=1;
160            public static final int CFML_WRITER_WS=2;
161            public static final int CFML_WRITER_WS_PREF=3;
162            
163            
164            private int mode=MODE_CUSTOM;
165    
166            private PhysicalClassLoader rpcClassLoader;
167            private Map<String,DataSource> datasources=new HashMap<String,DataSource>();
168            private Map<String,CacheConnection> caches=new HashMap<String, CacheConnection>();
169    
170            private CacheConnection defaultCacheFunction=null;
171            private CacheConnection defaultCacheObject=null;
172            private CacheConnection defaultCacheTemplate=null;
173            private CacheConnection defaultCacheQuery=null;
174            private CacheConnection defaultCacheResource=null;
175    
176            private String cacheDefaultConnectionNameFunction=null;
177            private String cacheDefaultConnectionNameObject=null;
178            private String cacheDefaultConnectionNameTemplate=null;
179            private String cacheDefaultConnectionNameQuery=null;
180            private String cacheDefaultConnectionNameResource=null;
181            
182        private TagLib[] tlds=new TagLib[1];
183        private FunctionLib[] flds=new FunctionLib[1];
184        private FunctionLib combinedFLDs;
185    
186        private short type=SCOPE_STANDARD;
187        //private File deployDirectory;
188        private boolean _allowImplicidQueryCall=true;
189        private boolean _mergeFormAndURL=false;
190    
191        private int _debug;
192        private int debugLogOutput;
193        private int debugOptions=0;
194    
195        private boolean suppresswhitespace = false;
196        private boolean suppressContent = false;
197        private boolean showVersion = false;
198        
199            private Resource tempDirectory;
200        private TimeSpan clientTimeout=new TimeSpanImpl(90,0,0,0);
201        private TimeSpan sessionTimeout=new TimeSpanImpl(0,0,30,0);
202        private TimeSpan applicationTimeout=new TimeSpanImpl(1,0,0,0);
203        private TimeSpan requestTimeout=new TimeSpanImpl(0,0,0,30);
204        
205        private boolean sessionManagement=true;  
206        private boolean clientManagement=false;
207        private boolean clientCookies=true; 
208        private boolean domainCookies=false;
209    
210        private Resource configFile;
211        private Resource configDir;
212    
213        private long loadTime;
214    
215        private int spoolInterval=30;
216        private boolean spoolEnable=true;
217    
218        private Server[] mailServers;
219    
220        private int mailTimeout=30;
221    
222        private TimeZone timeZone;
223    
224        private String timeServer="";
225        private boolean useTimeServer=true;
226    
227        private long timeOffset;
228        
229        //private ConnectionPool conns;
230    
231        private SearchEngine searchEngine;
232    
233        private Locale locale;
234    
235        private boolean psq=false;
236        private boolean debugShowUsage;
237    
238        private Map<String,String> errorTemplates=new HashMap<String,String>();
239    
240        private String password;
241    
242        private Mapping[] mappings=new Mapping[0];
243        private Mapping[] customTagMappings=new Mapping[0];
244        private Mapping[] componentMappings=new Mapping[0];
245        
246        
247            private Map<String,Mapping> customTagAppMappings=new ReferenceMap(ReferenceMap.SOFT,ReferenceMap.SOFT);
248    
249        private SchedulerImpl scheduler;
250        
251        private CFXTagPool cfxTagPool;
252    
253        private PageSource baseComponentPageSource;
254        //private Page baseComponentPage;
255        private String baseComponentTemplate;
256        private boolean restList=false;
257        //private boolean restAllowChanges=false;
258        
259        private LogAndSource mailLogger=null;//new LogAndSourceImpl(LogConsole.getInstance(Log.LEVEL_ERROR),"");
260        private LogAndSource restLogger=null;//new LogAndSourceImpl(LogConsole.getInstance(Log.LEVEL_ERROR),"");
261        private LogAndSource threadLogger=null;//new LogAndSourceImpl(LogConsole.getInstance(Log.LEVEL_INFO),"");
262        
263        private LogAndSource requestTimeoutLogger=null;
264        private LogAndSource applicationLogger=null;
265        private LogAndSource deployLogger=null;
266        private LogAndSource exceptionLogger=null;
267            private LogAndSource traceLogger=null;
268    
269        
270        private short clientType=CLIENT_SCOPE_TYPE_COOKIE;
271        
272        private String componentDumpTemplate;
273        private int componentDataMemberDefaultAccess=Component.ACCESS_PRIVATE;
274        private boolean triggerComponentDataMember=false;
275        
276        
277        private short sessionType=SESSION_TYPE_CFML;
278    
279        //private EmailSpooler emailSpooler;
280    
281        
282        private Resource deployDirectory;
283    
284        private short compileType=RECOMPILE_NEVER;
285        
286        private String resourceCharset=SystemUtil.getCharset();
287        private String templateCharset=SystemUtil.getCharset();
288        private String webCharset="UTF-8";
289    
290            private String mailDefaultEncoding = "UTF-8";
291            
292            private Resource tldFile;
293            private Resource fldFile;
294    
295            private Resources resources=new ResourcesImpl();
296    
297            private ApplicationListener applicationListener;
298            
299            private int scriptProtect=ApplicationContext.SCRIPT_PROTECT_ALL;
300    
301            //private boolean proxyEnable=false;
302            private ProxyData proxy =null;
303    
304    
305            private Resource clientScopeDir;
306            private Resource sessionScopeDir;
307            private long clientScopeDirSize=1024*1024*10;
308            private long sessionScopeDirSize=1024*1024*10;
309    
310            private Resource cacheDir;
311            private long cacheDirSize=1024*1024*10;
312    
313    
314            private boolean useComponentShadow=true;
315    
316            
317            private PrintWriter out=SystemUtil.getPrintWriter(SystemUtil.OUT);
318            private PrintWriter err=SystemUtil.getPrintWriter(SystemUtil.ERR);
319    
320            private DatasourceConnectionPool pool=new DatasourceConnectionPool();
321    
322            private boolean doCustomTagDeepSearch=false;
323            private boolean doComponentTagDeepSearch=false;
324    
325            private double version=1.0D;
326    
327            private boolean closeConnection=false;
328            private boolean contentLength=true;
329            private boolean allowCompression=false;
330            
331    
332            private boolean doLocalCustomTag=true; 
333    
334            private Struct constants=null;
335    
336            private RemoteClient[] remoteClients;
337    
338            private SpoolerEngine remoteClientSpoolerEngine;
339    
340            private Resource remoteClientDirectory;
341    
342            private LogAndSource remoteClientLog;
343        
344            private boolean allowURLRequestTimeout=false;
345            private CFMLFactory factory;
346            private boolean errorStatusCode=true;
347            private int localMode=Undefined.MODE_LOCAL_OR_ARGUMENTS_ONLY_WHEN_EXISTS;
348            
349            private String id;
350            private String securityToken;
351            private String securityKey;
352            private ExtensionProvider[] extensionProviders=RAILO_EXTENSION_PROVIDERS;
353            private Extension[] extensions=EXTENSIONS_EMPTY;
354            private boolean extensionEnabled;
355            private boolean allowRealPath=true;
356            //private ClassLoader classLoader;
357    
358            private DumpWriterEntry[] dmpWriterEntries;
359            private Class clusterClass=ClusterNotSupported.class;//ClusterRemoteNotSupported.class;//
360            private Struct remoteClientUsage;
361            private Class adminSyncClass=AdminSyncNotSupported.class;
362            private AdminSync adminSync;
363            private String[] customTagExtensions=new String[]{"cfm","cfc"};
364            private Class videoExecuterClass=VideoExecuterNotSupported.class;
365            
366            protected MappingImpl tagMapping;
367            private Resource tagDirectory;
368            //private Resource functionDirectory;
369            protected MappingImpl functionMapping;
370            private Map amfCasterArguments;
371            private Class amfCasterClass=ClassicAMFCaster.class;
372            private AMFCaster amfCaster;
373            //private String defaultDataSource;
374            private short inspectTemplate=INSPECT_ONCE;
375            private String serial="";
376            private String cacheMD5;
377            private boolean executionLogEnabled;
378            private ExecutionLogFactory executionLogFactory;
379            //private int clientScopeMaxAge=90;
380            private Map<String, ORMEngine> ormengines=new HashMap<String, ORMEngine>();
381            private Class<ORMEngine> ormEngineClass;
382            private ORMConfiguration ormConfig;
383            //private ResourceClassLoaderFactory classLoaderFactory;
384            private ResourceClassLoader resourceCL;
385            
386            private ImportDefintion componentDefaultImport=new ImportDefintionImpl("org.railo.cfml","*");
387            private boolean componentLocalSearch=true;
388            private boolean componentRootSearch=true;
389            private LogAndSource mappingLogger;
390            private LogAndSource ormLogger;
391            private boolean useComponentPathCache=true;
392            private boolean useCTPathCache=true;
393            private int amfConfigType=AMF_CONFIG_TYPE_XML;
394            private LogAndSource scopeLogger;
395            private railo.runtime.rest.Mapping[] restMappings;
396            
397            protected int writerType=CFML_WRITER_REFULAR;
398            private long configFileLastModified;
399            private boolean checkForChangesInConfigFile;
400            
401            
402            
403            /**
404             * @return the allowURLRequestTimeout
405             */
406            public boolean isAllowURLRequestTimeout() {
407                    return allowURLRequestTimeout;
408            }
409    
410            /**
411             * @param allowURLRequestTimeout the allowURLRequestTimeout to set
412             */
413            public void setAllowURLRequestTimeout(boolean allowURLRequestTimeout) {
414                    this.allowURLRequestTimeout = allowURLRequestTimeout;
415            }
416    
417    
418        @Override
419        public short getCompileType() {
420            return compileType;
421        }
422    
423        @Override
424        public void reset() {
425            timeServer="";
426            componentDumpTemplate="";
427            factory.resetPageContext();
428            //resources.reset();
429            ormengines.clear();
430            compressResources.clear();
431            clearFunctionCache();
432            clearCTCache();
433            clearComponentCache();
434            //clearComponentMetadata();
435        }
436        
437        @Override
438        public void reloadTimeServerOffset() {
439            timeOffset=0;
440            if(useTimeServer && !StringUtil.isEmpty(timeServer,true)) {
441                NtpClient ntp=new NtpClient(timeServer);
442                try {
443                    timeOffset=ntp.getOffset();
444                } catch (IOException e) {
445                    timeOffset=0;
446                }
447            }
448        }
449    
450        
451        /**
452         * private constructor called by factory method
453         * @param configDir config directory
454         * @param configFile config file
455         * @param id 
456         * @throws FunctionLibException 
457         * @throws TagLibException 
458         */
459        protected ConfigImpl(CFMLFactory factory,Resource configDir, Resource configFile) {
460            this(factory,configDir,configFile,
461                            loadTLDs() , 
462                            loadFLDs());
463        }
464    
465    
466        private static FunctionLib[] loadFLDs() {
467                    try {
468                            return new FunctionLib[]{FunctionLibFactory.loadFromSystem()};
469                    } catch (FunctionLibException e) {
470                            return new FunctionLib[]{};
471                    }
472            }
473    
474            private static TagLib[] loadTLDs() {
475                    try {
476                            return new TagLib[]{TagLibFactory.loadFromSystem()};
477                    } catch (TagLibException e) {
478                            return new TagLib[]{};
479                    }
480            }
481    
482            public ConfigImpl(CFMLFactory factory,Resource configDir, Resource configFile, TagLib[] tlds, FunctionLib[] flds) {
483                    
484                    this.configDir=configDir;
485            this.configFile=configFile;
486            this.factory=factory;
487            
488            this.tlds=duplicate(tlds,false);
489            this.flds=duplicate(flds,false);
490            }
491    
492    
493            private static TagLib[] duplicate(TagLib[] tlds, boolean deepCopy) {
494                    TagLib[] rst = new TagLib[tlds.length];
495                    for(int i=0;i<tlds.length;i++){
496                            rst[i]=tlds[i].duplicate(deepCopy);
497                    }
498                    return rst;
499            }
500            private static FunctionLib[] duplicate(FunctionLib[] flds, boolean deepCopy) {
501                    FunctionLib[] rst = new FunctionLib[flds.length];
502                    for(int i=0;i<flds.length;i++){
503                            rst[i]=flds[i].duplicate(deepCopy);
504                    }
505                    return rst;
506            }
507            
508            public long lastModified() {
509            return configFileLastModified;
510        }
511            
512            protected void setLastModified() {
513                    this.configFileLastModified=configFile.lastModified();
514        }
515            
516    
517        
518    
519            @Override
520        public short getScopeCascadingType() {
521            return type;
522        }
523        
524        @Override
525        public String[] getCFMLExtensions() {
526            return Constants.CFML_EXTENSION;
527        }
528        @Override
529        public String getCFCExtension() {
530            return Constants.CFC_EXTENSION;
531        }
532    
533        
534        /**
535         * return all Function Library Deskriptors
536         * @return Array of Function Library Deskriptors
537         */
538        public FunctionLib[] getFLDs() {
539            return flds;
540        }
541        
542        public FunctionLib getCombinedFLDs() {
543            if(combinedFLDs==null)combinedFLDs=FunctionLibFactory.combineFLDs(flds);
544            return combinedFLDs;
545        }
546        
547        /**
548         * return all Tag Library Deskriptors
549         * @return Array of Tag Library Deskriptors
550         */
551        public TagLib[] getTLDs()  {
552            return tlds;
553        }
554        
555        @Override
556        public boolean allowImplicidQueryCall() {
557            return _allowImplicidQueryCall;
558        }
559    
560        @Override
561        public boolean mergeFormAndURL() {
562            return _mergeFormAndURL;
563        }
564        
565        @Override
566        public TimeSpan getApplicationTimeout() {
567            return applicationTimeout;
568        }
569    
570        @Override
571        public TimeSpan getSessionTimeout() {
572            return sessionTimeout;
573        }
574    
575        @Override
576        public TimeSpan getClientTimeout() {
577            return clientTimeout;
578        }
579        
580        @Override
581        public TimeSpan getRequestTimeout() {
582            return requestTimeout;
583        }   
584        
585        @Override
586        public boolean isClientCookies() {
587            return clientCookies;
588        }
589        
590        @Override
591        public boolean isClientManagement() {
592            return clientManagement;
593        }
594        
595        @Override
596        public boolean isDomainCookies() {
597            return domainCookies;
598        }
599        
600        @Override
601        public boolean isSessionManagement() {
602            return sessionManagement;
603        }
604        
605        @Override
606        public boolean isMailSpoolEnable() {
607            //print.ln("isMailSpoolEnable:"+spoolEnable);
608            return spoolEnable;
609        }
610        
611        @Override
612        public Server[] getMailServers() {
613            if(mailServers==null) mailServers=new Server[0];
614            return mailServers;
615        }
616        
617        @Override
618        public int getMailTimeout() {
619            return mailTimeout;
620        }   
621        
622        @Override
623        public boolean getPSQL() {
624            return psq;   
625        }
626    
627        @Override
628        public ClassLoader getClassLoader() {
629            return getResourceClassLoader();   
630        }
631        public ResourceClassLoader getResourceClassLoader() {
632            if(resourceCL==null) throw new RuntimeException("no RCL defined yet!");
633            return resourceCL;   
634        }
635    
636        @Override
637        public ClassLoader getClassLoader(Resource[] reses) throws IOException {
638            // FUTURE @deprected use instead PageContext.getClassLoader(Resource[] reses);
639            //PageContextImpl pci=(PageContextImpl) ThreadLocalPageContext.get();
640            //if(pci==null) 
641                    throw new RuntimeException("this method is no longer suported");
642            //return pci.getClassLoader(reses);
643            ////return getResourceClassLoader().getCustomResourceClassLoader(reses);   
644        }
645        
646            /* *
647             * @return the classLoaderFactory
648            
649            public ResourceClassLoaderFactory getClassLoaderFactory() {
650                    return classLoaderFactory;
651            } */
652    
653            /* *
654             * @param classLoaderFactory the classLoaderFactory to set
655            /
656        protected void setClassLoaderFactory(ResourceClassLoaderFactory classLoaderFactory) {
657                    if(this.classLoaderFactory!=null){
658                            classLoaderFactory.reset();
659                    }
660                    this.classLoaderFactory = classLoaderFactory;
661            } */
662        
663        protected void setResourceClassLoader(ResourceClassLoader resourceCL) {
664            this.resourceCL=resourceCL;
665            }
666    
667        @Override
668        public Locale getLocale() {
669            return locale;
670        }
671    
672        @Override
673        public boolean debug() {
674            return _debug==CLIENT_BOOLEAN_TRUE || _debug==SERVER_BOOLEAN_TRUE;
675        }
676        
677        public boolean debugLogOutput() {
678            return debug() && debugLogOutput==CLIENT_BOOLEAN_TRUE || debugLogOutput==SERVER_BOOLEAN_TRUE;
679        }
680    
681        public int intDebug() {
682            return _debug;
683        }
684    
685        public int intDebugLogOutput() {
686            return debugLogOutput;
687        }
688        
689        @Override
690        public Resource getTempDirectory() {
691            if(tempDirectory==null) return SystemUtil.getTempDirectory();
692            return tempDirectory;
693        }
694        
695        @Override
696        public int getMailSpoolInterval() {
697            return spoolInterval;
698        }
699    
700        @Override
701        public LogAndSource getMailLogger() {
702            if(mailLogger==null)mailLogger=new LogAndSourceImpl(LogConsole.getInstance(this,Log.LEVEL_ERROR),"");
703                    return mailLogger;
704        }
705        
706    
707        public LogAndSource getRestLogger() {
708            if(restLogger==null)restLogger=new LogAndSourceImpl(LogConsole.getInstance(this,Log.LEVEL_ERROR),"");
709                    return restLogger;
710        }
711    
712        public LogAndSource getThreadLogger() {
713            if(threadLogger==null)threadLogger=new LogAndSourceImpl(LogConsole.getInstance(this,Log.LEVEL_ERROR),"");
714                    return threadLogger;
715        }
716    
717    
718        public void setThreadLogger(LogAndSource threadLogger) {
719            this.threadLogger=threadLogger;
720        }
721        
722        @Override
723        public LogAndSource getRequestTimeoutLogger() {
724            if(requestTimeoutLogger==null)requestTimeoutLogger=new LogAndSourceImpl(LogConsole.getInstance(this,Log.LEVEL_ERROR),"");
725                    return requestTimeoutLogger;
726        }
727    
728        @Override
729        public TimeZone getTimeZone() {
730            return timeZone;
731        }
732        
733        @Override
734        public long getTimeServerOffset() {
735            return timeOffset;
736        }
737        
738        @Override
739        public SearchEngine getSearchEngine() {
740            return searchEngine;
741        }
742        
743        /**
744         * @return return the Scheduler
745         */
746        public Scheduler getScheduler() {
747            return scheduler;
748        }
749    
750        /**
751         * @return gets the password
752         */
753        protected String getPassword() {
754            return password;
755        }
756        
757        @Override
758        public boolean hasPassword() {
759            return password!=null && password.length()>0;
760        }
761        
762        @Override
763        public boolean passwordEqual(String password) {
764            return this.password.equals(password);
765        }
766    
767        @Override
768        public Mapping[] getMappings() {
769            return mappings;
770        }
771        
772        public railo.runtime.rest.Mapping[] getRestMappings() {
773            if(restMappings==null) restMappings=new railo.runtime.rest.Mapping[0];
774            return restMappings;
775        }
776      
777        protected void setRestMappings(railo.runtime.rest.Mapping[] restMappings) {
778            
779            // make sure only one is default
780            boolean hasDefault=false;
781            railo.runtime.rest.Mapping m;
782            for(int i=0;i<restMappings.length;i++){
783                    m=restMappings[i];
784                    if(m.isDefault()) {
785                            if(hasDefault) m.setDefault(false);
786                            hasDefault=true;
787                    }
788            }
789            
790            this.restMappings= restMappings;
791        }
792    
793    
794        public PageSource getPageSource(Mapping[] mappings, String realPath,boolean onlyTopLevel) {
795            throw new PageRuntimeException(new DeprecatedException("method not supported"));
796        }
797        
798        public PageSource getPageSourceExisting(PageContext pc,Mapping[] mappings, String realPath,boolean onlyTopLevel,boolean useSpecialMappings, boolean useDefaultMapping, boolean onlyPhysicalExisting) {
799            realPath=realPath.replace('\\','/');
800            String lcRealPath = StringUtil.toLowerCase(realPath)+'/';
801            Mapping mapping;
802            PageSource ps;
803    
804            if(mappings!=null){
805                    for(int i=0;i<mappings.length;i++) {
806                        mapping = mappings[i];
807                        //print.err(lcRealPath+".startsWith"+(mapping.getStrPhysical()));
808                        if(lcRealPath.startsWith(mapping.getVirtualLowerCaseWithSlash(),0)) {
809                            ps= mapping.getPageSource(realPath.substring(mapping.getVirtual().length()));
810                            if(onlyPhysicalExisting) {
811                                    if(ps.physcalExists())return ps;
812                            }
813                            else if(ps.exists()) return ps;
814                        }
815                    }
816            }
817            
818            /// special mappings
819            if(useSpecialMappings && lcRealPath.startsWith("/mapping-",0)){
820                    String virtual="/mapping-tag";
821                    // tag mappings
822                    Mapping[] tagMappings=(this instanceof ConfigWebImpl)?new Mapping[]{((ConfigWebImpl)this).getServerTagMapping(),getTagMapping()}:new Mapping[]{getTagMapping()};
823                    if(lcRealPath.startsWith(virtual,0)){
824                            for(int i=0;i<tagMappings.length;i++) {
825                                mapping = tagMappings[i];
826                                //if(lcRealPath.startsWith(mapping.getVirtualLowerCaseWithSlash(),0)) {
827                                    ps = mapping.getPageSource(realPath.substring(virtual.length()));
828                                    if(onlyPhysicalExisting) {
829                                            if(ps.physcalExists())return ps;
830                                    }
831                                    else if(ps.exists()) return ps;
832                                //}
833                            }
834                    }
835                    
836                    // customtag mappings
837                    tagMappings=getCustomTagMappings();
838                    virtual="/mapping-customtag";
839                    if(lcRealPath.startsWith(virtual,0)){
840                            for(int i=0;i<tagMappings.length;i++) {
841                                mapping = tagMappings[i];
842                                //if(lcRealPath.startsWith(mapping.getVirtualLowerCaseWithSlash(),0)) {
843                                    ps = mapping.getPageSource(realPath.substring(virtual.length()));
844                                    if(onlyPhysicalExisting) {
845                                            if(ps.physcalExists())return ps;
846                                    }
847                                    else if(ps.exists()) return ps;
848                                //}
849                            }
850                    }
851            }
852            
853            // component mappings (only used for gateway)
854            if(pc!=null && ((PageContextImpl)pc).isGatewayContext()) {
855                    boolean isCFC=getCFCExtension().equalsIgnoreCase(ResourceUtil.getExtension(realPath, null));
856                if(isCFC) {
857                            Mapping[] cmappings = getComponentMappings();
858                            for(int i=0;i<cmappings.length;i++) {
859                                    ps = cmappings[i].getPageSource(realPath);
860                            if(onlyPhysicalExisting) {
861                                    if(ps.physcalExists())return ps;
862                            }
863                            else if(ps.exists()) return ps;
864                        }
865                    }
866            }
867            
868            // config mappings
869            for(int i=0;i<this.mappings.length-1;i++) {
870                mapping = this.mappings[i];
871                if((!onlyTopLevel || mapping.isTopLevel()) && lcRealPath.startsWith(mapping.getVirtualLowerCaseWithSlash(),0)) {
872                    ps= mapping.getPageSource(realPath.substring(mapping.getVirtual().length()));
873                    if(onlyPhysicalExisting) {
874                            if(ps.physcalExists())return ps;
875                    }
876                    else if(ps.exists()) return ps;
877                }
878            }
879            
880            if(useDefaultMapping){
881                    ps= this.mappings[this.mappings.length-1].getPageSource(realPath);
882                    if(onlyPhysicalExisting) {
883                            if(ps.physcalExists())return ps;
884                    }
885                    else if(ps.exists()) return ps;
886            }
887            return null;
888        }
889        
890    
891        
892        public PageSource[] getPageSources(PageContext pc,Mapping[] mappings, String realPath,boolean onlyTopLevel,boolean useSpecialMappings, boolean useDefaultMapping) {
893            realPath=realPath.replace('\\','/');
894            String lcRealPath = StringUtil.toLowerCase(realPath)+'/';
895            Mapping mapping;
896    
897            PageSource ps;
898            List<PageSource> list=new ArrayList<PageSource>();
899            
900            if(mappings!=null){
901                    for(int i=0;i<mappings.length;i++) {
902                        mapping = mappings[i];
903                        //print.err(lcRealPath+".startsWith"+(mapping.getStrPhysical()));
904                        if(lcRealPath.startsWith(mapping.getVirtualLowerCaseWithSlash(),0)) {
905                            list.add(mapping.getPageSource(realPath.substring(mapping.getVirtual().length())));
906                        }
907                    }
908            }
909            
910            /// special mappings
911            if(useSpecialMappings && lcRealPath.startsWith("/mapping-",0)){
912                    String virtual="/mapping-tag";
913                    // tag mappings
914                    Mapping[] tagMappings=(this instanceof ConfigWebImpl)?new Mapping[]{((ConfigWebImpl)this).getServerTagMapping(),getTagMapping()}:new Mapping[]{getTagMapping()};
915                    if(lcRealPath.startsWith(virtual,0)){
916                            for(int i=0;i<tagMappings.length;i++) {
917                                ps=tagMappings[i].getPageSource(realPath.substring(virtual.length()));
918                                if(ps.exists()) list.add(ps);
919                            }
920                    }
921                    
922                    // customtag mappings
923                    tagMappings=getCustomTagMappings();
924                    virtual="/mapping-customtag";
925                    if(lcRealPath.startsWith(virtual,0)){
926                            for(int i=0;i<tagMappings.length;i++) {
927                                ps=tagMappings[i].getPageSource(realPath.substring(virtual.length()));
928                                if(ps.exists()) list.add(ps);
929                            }
930                    }
931            }
932            
933            // component mappings (only used for gateway)
934            if(pc!=null && ((PageContextImpl)pc).isGatewayContext()) {
935                    boolean isCFC=getCFCExtension().equalsIgnoreCase(ResourceUtil.getExtension(realPath, null));
936                if(isCFC) {
937                            Mapping[] cmappings = getComponentMappings();
938                            for(int i=0;i<cmappings.length;i++) {
939                                    ps=cmappings[i].getPageSource(realPath);
940                                    if(ps.exists()) list.add(ps);
941                        }
942                    }
943            }
944            
945            // config mappings
946            for(int i=0;i<this.mappings.length-1;i++) {
947                mapping = this.mappings[i];
948                if((!onlyTopLevel || mapping.isTopLevel()) && lcRealPath.startsWith(mapping.getVirtualLowerCaseWithSlash(),0)) {
949                    list.add(mapping.getPageSource(realPath.substring(mapping.getVirtual().length())));
950                }
951            }
952            
953            if(useDefaultMapping){
954                    list.add(this.mappings[this.mappings.length-1].getPageSource(realPath));
955            }
956            return list.toArray(new PageSource[list.size()]); 
957        }
958        
959        /**
960         * @param mappings2 
961         * @param realPath
962         * @param alsoDefaultMapping ignore default mapping (/) or not
963         * @return physical path from mapping
964         */
965        public Resource getPhysical(Mapping[] mappings, String realPath, boolean alsoDefaultMapping) {
966            throw new PageRuntimeException(new DeprecatedException("method not supported"));
967        }
968    
969        public Resource[] getPhysicalResources(PageContext pc,Mapping[] mappings, String realPath,boolean onlyTopLevel,boolean useSpecialMappings, boolean useDefaultMapping) {
970            // now that archives can be used the same way as physical resources, there is no need anymore to limit to that
971            throw new PageRuntimeException(new DeprecatedException("method not supported"));
972            /*PageSource[] pages = getPageSources(pc, mappings, realPath, onlyTopLevel, useSpecialMappings, useDefaultMapping);
973            List<Resource> list=new ArrayList<Resource>();
974            Resource res;
975            for(int i=0;i<pages.length;i++) {
976                    if(!pages[i].getMapping().hasPhysical()) continue;
977                    res=pages[i].getPhyscalFile();
978                    if(res!=null) list.add(res);
979            }
980            return list.toArray(new Resource[list.size()]);*/
981        }
982        
983    
984        public Resource getPhysicalResourceExisting(PageContext pc,Mapping[] mappings, String realPath,boolean onlyTopLevel,boolean useSpecialMappings, boolean useDefaultMapping) {
985            // now that archives can be used the same way as physical resources, there is no need anymore to limit to that
986            throw new PageRuntimeException(new DeprecatedException("method not supported"));
987            /*PageSource ps = getPageSourceExisting(pc, mappings, realPath, onlyTopLevel, useSpecialMappings, useDefaultMapping,true);
988            if(ps==null) return null;
989            return ps.getPhyscalFile();*/
990        }
991    
992        public PageSource toPageSource(Mapping[] mappings, Resource res,PageSource defaultValue) {
993            Mapping mapping;
994            String path;
995            
996            // app-cfc mappings
997            if(mappings!=null){
998                for(int i=0;i<mappings.length;i++) {
999                    mapping = mappings[i];
1000                    
1001                // Physical
1002                   if(mapping.hasPhysical()) {
1003                    path=ResourceUtil.getPathToChild(res, mapping.getPhysical());
1004                       if(path!=null) {
1005                            return mapping.getPageSource(path);
1006                       }
1007                   }
1008               // Archive
1009                   if(mapping.hasArchive() && res.getResourceProvider() instanceof CompressResourceProvider) {
1010                       Resource archive = mapping.getArchive();
1011                       CompressResource cr = ((CompressResource) res);
1012                       if(archive.equals(cr.getCompressResource())) {
1013                               return mapping.getPageSource(cr.getCompressPath());
1014                       }
1015                   }
1016                }
1017            }
1018            
1019            // config mappings
1020            for(int i=0;i<this.mappings.length;i++) {
1021                mapping = this.mappings[i];
1022                    
1023             // Physical
1024                if(mapping.hasPhysical()) {
1025                    path=ResourceUtil.getPathToChild(res, mapping.getPhysical());
1026                    if(path!=null) {
1027                            return mapping.getPageSource(path);
1028                    }
1029                }
1030            // Archive
1031                if(mapping.hasArchive() && res.getResourceProvider() instanceof CompressResourceProvider) {
1032                            Resource archive = mapping.getArchive();
1033                            CompressResource cr = ((CompressResource) res);
1034                            if(archive.equals(cr.getCompressResource())) {
1035                                    return mapping.getPageSource(cr.getCompressPath());
1036                            }
1037                }
1038            }
1039            
1040        // map resource to root mapping when same filesystem
1041            Mapping rootMapping = this.mappings[this.mappings.length-1];
1042            Resource root;
1043            if(rootMapping.hasPhysical() && 
1044                            res.getResourceProvider().getScheme().equals((root=rootMapping.getPhysical()).getResourceProvider().getScheme())) {
1045                    
1046                    String realpath="";
1047                    while(root!=null && !ResourceUtil.isChildOf(res, root)){
1048                            root=root.getParentResource();
1049                            realpath+="../";
1050                    }
1051                    String p2c=ResourceUtil.getPathToChild(res,root);
1052                    if(StringUtil.startsWith(p2c, '/') || StringUtil.startsWith(p2c, '\\') )
1053                            p2c=p2c.substring(1);
1054                    realpath+=p2c;
1055                    
1056                    return rootMapping.getPageSource(realpath);
1057                    
1058            }
1059            // MUST better impl than this
1060            if(this instanceof ConfigWebImpl) {
1061                    Resource parent = res.getParentResource();
1062                    if(parent!=null && !parent.equals(res)) {
1063                            Mapping m = ((ConfigWebImpl)this).getApplicationMapping("/", parent.getAbsolutePath());
1064                            return m.getPageSource(res.getName());
1065                    }
1066            }
1067            
1068                    
1069         // Archive
1070            // MUST check archive
1071            return defaultValue;
1072        }
1073        
1074        @Override
1075        public Resource getConfigDir() {
1076            return configDir;
1077        }
1078        
1079        @Override
1080        public Resource getConfigFile() {
1081            return configFile;
1082        }
1083    
1084        @Override
1085        public LogAndSource getScheduleLogger() {
1086            return scheduler.getLogger();
1087        }
1088        
1089        @Override
1090        public LogAndSource getApplicationLogger() {
1091            if(applicationLogger==null)applicationLogger=new LogAndSourceImpl(LogConsole.getInstance(this,Log.LEVEL_ERROR),"");
1092                    return applicationLogger;
1093        }
1094        
1095        public LogAndSource getDeployLogger() {
1096            if(deployLogger==null){
1097                    deployLogger=new LogAndSourceImpl(LogConsole.getInstance(this,Log.LEVEL_INFO),"");
1098            }
1099                    return deployLogger;
1100        }
1101        
1102        public LogAndSource getScopeLogger() {
1103            if(scopeLogger==null)scopeLogger=new LogAndSourceImpl(LogConsole.getInstance(this,Log.LEVEL_ERROR),"");
1104                    return scopeLogger;
1105        }
1106    
1107        /**
1108         * sets the password
1109         * @param password
1110         */
1111        protected void setPassword(String password) {
1112            this.password=password;
1113        }
1114        
1115        
1116        /**
1117         * set how railo cascade scopes
1118         * @param type cascading type
1119         */
1120        protected void setScopeCascadingType(String type) {
1121            
1122            if(type.equalsIgnoreCase("strict")) setScopeCascadingType(SCOPE_STRICT);
1123            else if(type.equalsIgnoreCase("small")) setScopeCascadingType(SCOPE_SMALL);
1124            else if(type.equalsIgnoreCase("standard"))setScopeCascadingType(SCOPE_STANDARD);
1125            else if(type.equalsIgnoreCase("standart"))setScopeCascadingType(SCOPE_STANDARD);
1126            else setScopeCascadingType(SCOPE_STANDARD);
1127        }
1128    
1129        /**
1130         * set how railo cascade scopes
1131         * @param type cascading type
1132         */
1133        protected void setScopeCascadingType(short type) {
1134            this.type=type;
1135        }
1136    
1137        protected void addTag(String nameSpace, String nameSpaceSeperator,String name, String clazz){
1138            for(int i=0;i<tlds.length;i++) {
1139                    if(tlds[i].getNameSpaceAndSeparator().equalsIgnoreCase(nameSpace+nameSpaceSeperator)){
1140                            TagLibTag tlt = new TagLibTag(tlds[i]);
1141                            tlt.setAttributeType(TagLibTag.ATTRIBUTE_TYPE_DYNAMIC);
1142                            tlt.setBodyContent("free");
1143                            tlt.setTagClass(clazz);
1144                            tlt.setName(name);
1145                            tlds[i].setTag(tlt              );
1146                    }
1147            }
1148        }
1149        
1150        /**
1151         * set the optional directory of the tag library deskriptors
1152         * @param fileTld directory of the tag libray deskriptors
1153         * @throws TagLibException
1154         */
1155        protected void setTldFile(Resource fileTld) throws TagLibException {
1156            if(fileTld==null) return;
1157            this.tldFile=fileTld;
1158            String key;
1159            Map<String,TagLib> map=new HashMap<String,TagLib>();
1160            // First fill existing to set
1161            for(int i=0;i<tlds.length;i++) {
1162                    key=getKey(tlds[i]);
1163                    map.put(key,tlds[i]);
1164            }
1165            
1166            TagLib tl;
1167            
1168            // now overwrite with new data
1169            if(fileTld.isDirectory()) {
1170                    Resource[] files=fileTld.listResources(new ExtensionResourceFilter("tld"));
1171                for(int i=0;i<files.length;i++) {
1172                    try {
1173                            tl = TagLibFactory.loadFromFile(files[i]);
1174                            key=getKey(tl);
1175                            if(!map.containsKey(key))
1176                                    map.put(key,tl);
1177                            else 
1178                                    overwrite(map.get(key),tl);
1179                    }
1180                    catch(TagLibException tle) {
1181                        SystemOut.printDate(out,"can't load tld "+files[i]);
1182                        tle.printStackTrace(getErrWriter());
1183                    }
1184                    
1185                }
1186            }
1187            else if(fileTld.isFile()){
1188                    tl = TagLibFactory.loadFromFile(fileTld);
1189                    key=getKey(tl);
1190                    if(!map.containsKey(key))
1191                            map.put(key,tl);
1192                    else overwrite(map.get(key),tl);
1193            }
1194    
1195            // now fill back to array
1196            tlds=new TagLib[map.size()];
1197            int index=0;
1198            Iterator<TagLib> it = map.values().iterator();
1199            while(it.hasNext()) {
1200                    tlds[index++]=it.next();
1201            }
1202        }
1203        
1204        public TagLib getCoreTagLib(){
1205            for(int i=0;i<tlds.length;i++) {
1206                    if(tlds[i].getNameSpaceAndSeparator().equals("cf"))return tlds[i];      
1207            }
1208            throw new RuntimeException("no core taglib found"); // this should never happen
1209        }
1210        
1211        protected void setTagDirectory(Resource tagDirectory) {
1212            this.tagDirectory=tagDirectory;
1213            
1214            this.tagMapping= new MappingImpl(this,"/mapping-tag/",tagDirectory.getAbsolutePath(),null,ConfigImpl.INSPECT_NEVER,true,true,true,true,false,true,null);
1215            
1216            TagLib tl=getCoreTagLib();
1217            
1218            // now overwrite with new data
1219            if(tagDirectory.isDirectory()) {
1220                    String[] files=tagDirectory.list(new ExtensionResourceFilter(new String[]{"cfm","cfc"}));
1221                for(int i=0;i<files.length;i++) {
1222                    if(tl!=null)createTag(tl, files[i]);
1223                        
1224                }
1225            }
1226            
1227        }
1228        
1229        public void createTag(TagLib tl,String filename) {// Jira 1298
1230            String name=toName(filename);//filename.substring(0,filename.length()-(getCFCExtension().length()+1));
1231            
1232            TagLibTag tlt = new TagLibTag(tl);
1233            tlt.setName(name);
1234            tlt.setTagClass("railo.runtime.tag.CFTagCore");
1235            tlt.setHandleExceptions(true);
1236            tlt.setBodyContent("free");
1237            tlt.setParseBody(false);
1238            tlt.setDescription("");
1239            tlt.setAttributeType(TagLibTag.ATTRIBUTE_TYPE_MIXED);
1240    
1241    
1242            TagLibTagAttr tlta = new TagLibTagAttr(tlt);
1243            tlta.setName("__filename");
1244            tlta.setRequired(true);
1245            tlta.setRtexpr(true);
1246            tlta.setType("string");
1247            tlta.setHidden(true);
1248            tlta.setDefaultValue(filename);
1249            tlt.setAttribute(tlta);
1250            
1251            tlta = new TagLibTagAttr(tlt);
1252            tlta.setName("__name");
1253            tlta.setRequired(true);
1254            tlta.setRtexpr(true);
1255            tlta.setHidden(true);
1256            tlta.setType("string");
1257            tlta.setDefaultValue(name);
1258            tlt.setAttribute(tlta);
1259            
1260            tlta = new TagLibTagAttr(tlt);
1261            tlta.setName("__isweb");
1262            tlta.setRequired(true);
1263            tlta.setRtexpr(true);
1264            tlta.setHidden(true);
1265            tlta.setType("boolean");
1266            tlta.setDefaultValue(this instanceof ConfigWeb?"true":"false");
1267            tlt.setAttribute(tlta);
1268            
1269            tl.setTag(tlt);
1270        }
1271        
1272        protected void setFunctionDirectory(Resource functionDirectory) {
1273            //this.functionDirectory=functionDirectory;
1274            this.functionMapping= new MappingImpl(this,"/mapping-function/",functionDirectory.getAbsolutePath(),null,ConfigImpl.INSPECT_NEVER,true,true,true,true,false,true,null);
1275            FunctionLib fl=flds[flds.length-1];
1276            
1277            // now overwrite with new data
1278            if(functionDirectory.isDirectory()) {
1279                    String[] files=functionDirectory.list(new ExtensionResourceFilter(getCFMLExtensions()));
1280                    
1281                for(int i=0;i<files.length;i++) {
1282                    if(fl!=null)createFunction(fl, files[i]);
1283                        
1284                }
1285            }
1286            
1287        }
1288        
1289        public void createFunction(FunctionLib fl,String filename) {
1290            //PageSource ps = functionMapping.getPageSource(filename);
1291            
1292            String name=toName(filename);//filename.substring(0,filename.length()-(getCFMLExtensions().length()+1));
1293            FunctionLibFunction flf = new FunctionLibFunction(fl);
1294            flf.setArgType(FunctionLibFunction.ARG_DYNAMIC);
1295            flf.setCls("railo.runtime.functions.system.CFFunction");
1296            flf.setName(name);
1297            flf.setReturn("object");
1298            FunctionLibFunctionArg arg = new FunctionLibFunctionArg(flf);
1299            arg.setName("__filename");
1300            arg.setRequired(true);
1301            arg.setType("string");
1302            arg.setHidden(true);
1303            arg.setDefaultValue(filename);
1304            flf.setArg(arg);
1305            
1306            arg = new FunctionLibFunctionArg(flf);
1307            arg.setName("__name");
1308            arg.setRequired(true);
1309            arg.setHidden(true);
1310            arg.setType("string");
1311            arg.setDefaultValue(name);
1312            flf.setArg(arg);
1313            
1314            arg = new FunctionLibFunctionArg(flf);
1315            arg.setName("__isweb");
1316            arg.setRequired(true);
1317            arg.setHidden(true);
1318            arg.setType("boolean");
1319            arg.setDefaultValue(this instanceof ConfigWeb?"true":"false");
1320            flf.setArg(arg);
1321            
1322            
1323            
1324            fl.setFunction(flf);
1325        }
1326        
1327        
1328        
1329        
1330        
1331        private static String toName(String filename) {
1332            int pos=filename.lastIndexOf('.');
1333            if(pos==-1)return filename;
1334            return filename.substring(0,pos);
1335            }
1336        
1337    
1338            private void overwrite(TagLib existingTL, TagLib newTL) {
1339                    Iterator<TagLibTag> it = newTL.getTags().values().iterator();
1340                    while(it.hasNext()){
1341                            existingTL.setTag(it.next());
1342                    }
1343            }
1344    
1345            private String getKey(TagLib tl) {
1346                    return tl.getNameSpaceAndSeparator().toLowerCase();
1347            }
1348            
1349            protected void setFldFile(Resource fileFld) throws FunctionLibException {
1350                    // merge all together (backward compatibility)
1351            if(flds.length>1)for(int i=1;i<flds.length;i++) {
1352                    overwrite(flds[0], flds[i]);
1353            }
1354            flds=new FunctionLib[]{flds[0]};
1355            
1356                    
1357                    if(fileFld==null) return;
1358            this.fldFile=fileFld;
1359    
1360            
1361            // overwrite with addional functions
1362            FunctionLib fl;
1363            if(fileFld.isDirectory()) {
1364                Resource[] files=fileFld.listResources(new ExtensionResourceFilter("fld"));
1365                for(int i=0;i<files.length;i++) {
1366                    try {
1367                            fl = FunctionLibFactory.loadFromFile(files[i]);
1368                            overwrite(flds[0],fl);
1369                            
1370                    }
1371                    catch(FunctionLibException fle) {
1372                        SystemOut.printDate(out,"can't load fld "+files[i]);
1373                        fle.printStackTrace(getErrWriter());
1374                    }   
1375                }
1376            }
1377            else {
1378                    fl = FunctionLibFactory.loadFromFile(fileFld);
1379                    overwrite(flds[0],fl);
1380            }
1381        }
1382    
1383            /*
1384        protected void setFldFileOld(Resource fileFld) throws FunctionLibException {
1385            if(fileFld==null) return;
1386            this.fldFile=fileFld;
1387    
1388            Map<String,FunctionLib> map=new LinkedHashMap<String,FunctionLib>();
1389            String key;
1390            // First fill existing to set
1391            for(int i=0;i<flds.length;i++) {
1392                    key=getKey(flds[i]);
1393                    map.put(key,flds[i]);
1394            }
1395            
1396            // now overwrite with new data
1397            FunctionLib fl;
1398            if(fileFld.isDirectory()) {
1399                Resource[] files=fileFld.listResources(new ExtensionResourceFilter("fld"));
1400                for(int i=0;i<files.length;i++) {
1401                    try {
1402                            fl = FunctionLibFactory.loadFromFile(files[i]);
1403                            key=getKey(fl);
1404                            // for the moment we only need one fld, so it is always overwrite, when you remove this make sure you get no conflicts with duplicates
1405                            if(map.containsKey(key)) 
1406                                    overwrite(map.get(key),fl);
1407                            else 
1408                                    map.put(key,fl);
1409                                    
1410                            
1411                    }
1412                    catch(FunctionLibException fle) {
1413                        SystemOut.printDate(out,"can't load tld "+files[i]);
1414                        fle.printStackTrace(getErrWriter());
1415                    }   
1416                }
1417            }
1418            else {
1419                    fl = FunctionLibFactory.loadFromFile(fileFld);
1420                    key=getKey(fl);
1421    
1422                    // for the moment we only need one fld, so it is always overwrite, when you remove this make sure you get no conflicts with duplicates
1423                    if(map.containsKey(key))
1424                            overwrite(map.get(key),fl);
1425                    else 
1426                            map.put(key,fl);
1427            }
1428            
1429            // now fill back to array
1430            flds=new FunctionLib[map.size()];
1431            int index=0;
1432            Iterator<FunctionLib> it = map.values().iterator();
1433            while(it.hasNext()) {
1434                    flds[index++]= it.next();
1435            }
1436        }*/
1437        
1438    
1439        
1440    
1441        private void overwrite(FunctionLib existingFL, FunctionLib newFL) {
1442                    Iterator<FunctionLibFunction> it = newFL.getFunctions().values().iterator();
1443                    while(it.hasNext()){
1444                            existingFL.setFunction(it.next());
1445                    }
1446            }
1447    
1448        private String getKey(FunctionLib functionLib) {
1449                    return functionLib.getDisplayName().toLowerCase();
1450            }
1451    
1452            /**
1453         * sets if it is allowed to implizit query call, call a query member witot define name of the query. 
1454         * @param _allowImplicidQueryCall is allowed
1455         */
1456        protected void setAllowImplicidQueryCall(boolean _allowImplicidQueryCall) {
1457            this._allowImplicidQueryCall=_allowImplicidQueryCall;
1458        }
1459    
1460        /**
1461         * sets if url and form scope will be merged
1462         * @param _mergeFormAndURL merge yes or no
1463         */
1464        protected void setMergeFormAndURL(boolean _mergeFormAndURL) {
1465            this._mergeFormAndURL=_mergeFormAndURL;
1466        }
1467        
1468        /**
1469         * @param strApplicationTimeout The applicationTimeout to set.
1470         * @throws PageException
1471         */
1472        void setApplicationTimeout(String strApplicationTimeout) throws PageException {
1473            setApplicationTimeout(Caster.toTimespan(strApplicationTimeout));
1474        }
1475        
1476        /**
1477         * @param applicationTimeout The applicationTimeout to set.
1478         */
1479        protected void setApplicationTimeout(TimeSpan applicationTimeout) {
1480            this.applicationTimeout = applicationTimeout;
1481        }
1482        
1483        /**
1484         * @param strSessionTimeout The sessionTimeout to set.
1485         * @throws PageException
1486         */
1487        protected void setSessionTimeout(String strSessionTimeout) throws PageException {
1488            setSessionTimeout(Caster.toTimespan(strSessionTimeout));
1489        }
1490        
1491        /**
1492         * @param sessionTimeout The sessionTimeout to set.
1493         */
1494        protected void setSessionTimeout(TimeSpan sessionTimeout) {
1495            this.sessionTimeout = sessionTimeout;
1496        }
1497        
1498        protected void setClientTimeout(String strClientTimeout) throws PageException {
1499            setClientTimeout(Caster.toTimespan(strClientTimeout));
1500        }
1501        
1502        /**
1503         * @param sessionTimeout The sessionTimeout to set.
1504         */
1505        protected void setClientTimeout(TimeSpan clientTimeout) {
1506            this.clientTimeout = clientTimeout;
1507        }
1508        
1509        /**
1510         * @param strRequestTimeout The requestTimeout to set.
1511         * @throws PageException
1512         */
1513        protected void setRequestTimeout(String strRequestTimeout) throws PageException {
1514            setRequestTimeout(Caster.toTimespan(strRequestTimeout));
1515        }
1516        
1517        /**
1518         * @param requestTimeout The requestTimeout to set.
1519         */
1520        protected void setRequestTimeout(TimeSpan requestTimeout) {
1521            this.requestTimeout = requestTimeout;
1522        }
1523        
1524        /**
1525         * @param clientCookies The clientCookies to set.
1526         */
1527        protected void setClientCookies(boolean clientCookies) {
1528            this.clientCookies = clientCookies;
1529        }
1530        
1531        /**
1532         * @param clientManagement The clientManagement to set.
1533         */
1534        protected void setClientManagement(boolean clientManagement) {
1535            this.clientManagement = clientManagement;
1536        }
1537        
1538        /**
1539         * @param domainCookies The domainCookies to set.
1540         */
1541        protected void setDomainCookies(boolean domainCookies) {
1542            this.domainCookies = domainCookies;
1543        }
1544        
1545        /**
1546         * @param sessionManagement The sessionManagement to set.
1547         */
1548        protected void setSessionManagement(boolean sessionManagement) {
1549            this.sessionManagement = sessionManagement;
1550        }
1551        
1552        /**
1553         * @param spoolEnable The spoolEnable to set.
1554         */
1555        protected void setMailSpoolEnable(boolean spoolEnable) {
1556            //print.ln("setMailSpoolEnable:"+spoolEnable);
1557            this.spoolEnable = spoolEnable;
1558        }
1559        
1560        /**
1561         * @param mailTimeout The mailTimeout to set.
1562         */
1563        protected void setMailTimeout(int mailTimeout) {
1564            this.mailTimeout = mailTimeout;
1565        }
1566    
1567        /**
1568         * sets the mail logger
1569         * @param mailLogger
1570         */
1571        protected void setMailLogger(LogAndSource mailLogger) {
1572            this.mailLogger = mailLogger;
1573        }
1574        
1575    
1576        protected void setORMLogger(LogAndSource ormLogger) {
1577            this.ormLogger = ormLogger;
1578        }
1579        public LogAndSource getORMLogger() {
1580            if(ormLogger==null)ormLogger=new LogAndSourceImpl(LogConsole.getInstance(this,Log.LEVEL_ERROR),"");
1581                    
1582            return ormLogger;
1583        }
1584    
1585        /**
1586         * sets the request timeout logger
1587         * @param requestTimeoutLogger
1588         */
1589        protected void setRequestTimeoutLogger(LogAndSource requestTimeoutLogger) {
1590            this.requestTimeoutLogger=requestTimeoutLogger;
1591        }
1592        
1593        /**
1594         * @param psq (preserve single quote) 
1595         * sets if sql string inside a cfquery will be prederved for Single Quotes
1596         */
1597        protected void setPSQL(boolean psq) {
1598            this.psq=psq;
1599        }
1600        
1601        /**
1602         * set if railo make debug output or not
1603         * @param _debug debug or not
1604         */
1605        protected void setDebug(int _debug) {
1606            this._debug=_debug;
1607        }  
1608        
1609        protected void setDebugLogOutput(int debugLogOutput) {
1610            this.debugLogOutput=debugLogOutput;
1611        }   
1612        
1613        /**
1614         * sets the temp directory
1615         * @param strTempDirectory temp directory
1616         * @throws ExpressionException
1617         */
1618        protected void setTempDirectory(String strTempDirectory, boolean flush) throws ExpressionException {
1619            setTempDirectory(resources.getResource(strTempDirectory),flush);
1620        }   
1621        
1622        /**
1623         * sets the temp directory
1624         * @param tempDirectory temp directory
1625         * @throws ExpressionException
1626         */
1627        protected void setTempDirectory(Resource tempDirectory, boolean flush) throws ExpressionException {
1628            if(!isDirectory(tempDirectory) || !tempDirectory.isWriteable()) {
1629                    SystemOut.printDate(getErrWriter(), "temp directory ["+tempDirectory+"] is not writable or can not be created, using directory ["+SystemUtil.getTempDirectory()+"] instead");
1630                    tempDirectory=SystemUtil.getTempDirectory();
1631                    if(!tempDirectory.isWriteable()){
1632                            SystemOut.printDate(getErrWriter(), "temp directory ["+tempDirectory+"] is not writable");
1633                    }
1634            }
1635            if(flush)ResourceUtil.removeChildrenEL(tempDirectory);// start with a empty temp directory
1636            this.tempDirectory=tempDirectory;
1637        }
1638    
1639        /**
1640         * sets the Schedule Directory
1641         * @param scheduleDirectory sets the schedule Directory 
1642         * @param logger
1643         * @throws PageException
1644         */
1645        protected void setScheduler(CFMLEngine engine,Resource scheduleDirectory, LogAndSource logger) throws PageException {
1646            if(scheduleDirectory==null) {
1647                    if(this.scheduler==null) this.scheduler=new SchedulerImpl(engine,"<?xml version=\"1.0\"?>\n<schedule></schedule>",this,logger);
1648                    return;
1649            }
1650            
1651            
1652            if(!isDirectory(scheduleDirectory)) throw new ExpressionException("schedule task directory "+scheduleDirectory+" doesn't exist or is not a directory");
1653            try {
1654                    if(this.scheduler==null)
1655                            this.scheduler=new SchedulerImpl(engine,this,scheduleDirectory,logger,SystemUtil.getCharset());
1656                    //else
1657                            //this.scheduler.reinit(scheduleDirectory,logger);
1658            } 
1659            catch (Exception e) {
1660                throw Caster.toPageException(e);
1661            }
1662        }
1663        
1664        /**
1665         * @param spoolInterval The spoolInterval to set.
1666         */
1667        protected void setMailSpoolInterval(int spoolInterval) {
1668            this.spoolInterval = spoolInterval;
1669        }
1670        
1671        /**
1672         * sets the timezone
1673         * @param timeZone
1674         */
1675        protected void setTimeZone(TimeZone timeZone) {
1676            this.timeZone=timeZone;
1677        }
1678        
1679        /**
1680         * sets the time server
1681         * @param timeServer
1682         */
1683        protected void setTimeServer(String timeServer) {
1684            this.timeServer=timeServer;
1685        }
1686    
1687        /**
1688         * sets the locale
1689         * @param strLocale
1690         */
1691        protected void setLocale(String strLocale) {
1692            if(strLocale==null) {
1693                this.locale=Locale.US;
1694            }
1695            else {
1696                try {
1697                    this.locale=Caster.toLocale(strLocale);
1698                    if(this.locale==null)this.locale=Locale.US;
1699                } catch (ExpressionException e) {
1700                    this.locale=Locale.US;
1701                }
1702            }
1703        }
1704        
1705        /**
1706         * sets the locale
1707         * @param locale
1708         */
1709        protected void setLocale(Locale locale) {
1710            this.locale=locale;
1711        }
1712    
1713        /**
1714         * @param mappings The mappings to set.
1715         */
1716        protected void setMappings(Mapping[] mappings) {
1717            Arrays.sort(mappings,new Comparator(){ 
1718                public int compare(Object left, Object right) { 
1719                    Mapping r = ((Mapping)right);
1720                    Mapping l = ((Mapping)left);
1721                    int rtn=r.getVirtualLowerCaseWithSlash().length()-l.getVirtualLowerCaseWithSlash().length();
1722                    if(rtn==0) return slashCount(r)-slashCount(l);
1723                    return rtn; 
1724                }
1725    
1726                            private int slashCount(Mapping l) {
1727                                    String str=l.getVirtualLowerCaseWithSlash();
1728                                    int count=0,lastIndex=-1;
1729                                    while((lastIndex=str.indexOf('/', lastIndex))!=-1) {
1730                                            count++;
1731                                            lastIndex++;
1732                                    }
1733                                    return count;
1734                            } 
1735            }); 
1736            this.mappings = mappings;
1737        }
1738        
1739        /**
1740         * @param datasources The datasources to set
1741         */
1742        protected void setDataSources(Map<String,DataSource> datasources) {
1743            this.datasources=datasources;
1744        }
1745        /**
1746         * @param customTagMapping The customTagMapping to set.
1747         */
1748        protected void setCustomTagMappings(Mapping[] customTagMappings) {
1749            this.customTagMappings = customTagMappings;
1750        }
1751        
1752    
1753        @Override
1754        public Mapping[] getCustomTagMappings() {
1755            return customTagMappings;
1756        }
1757        
1758        /**
1759         * @param mailServers The mailsServers to set.
1760         */
1761        protected void setMailServers(Server[] mailServers) {
1762            this.mailServers = mailServers;
1763        }
1764        
1765        /**
1766         * is file a directory or not, touch if not exist
1767         * @param directory
1768         * @return true if existing directory or has created new one
1769         */
1770        protected boolean isDirectory(Resource directory) {
1771            if(directory.exists()) return directory.isDirectory();
1772            try {
1773                            directory.createDirectory(true);
1774                            return true;
1775                    } catch (IOException e) {
1776                            e.printStackTrace(getErrWriter());
1777                    }
1778            return false;
1779        }
1780    
1781        @Override
1782        public long getLoadTime() {
1783            return loadTime;
1784        }
1785        /**
1786         * @param loadTime The loadTime to set.
1787         */
1788        protected void setLoadTime(long loadTime) {
1789            this.loadTime = loadTime;
1790        }
1791        /**
1792         * @return Returns the configLogger.
1793         * /
1794        public Log getConfigLogger() {
1795            return configLogger;
1796        }*/
1797    
1798        @Override
1799        public CFXTagPool getCFXTagPool() throws SecurityException {
1800            return cfxTagPool;
1801        }
1802    
1803        /**
1804         * @param cfxTagPool The customTagPool to set.
1805         */
1806        protected void setCFXTagPool(CFXTagPool cfxTagPool) {
1807            this.cfxTagPool = cfxTagPool;
1808        }
1809        /**
1810         * @param cfxTagPool The customTagPool to set.
1811         */
1812        protected void setCFXTagPool(Map cfxTagPool) {
1813            this.cfxTagPool = new CFXTagPoolImpl(cfxTagPool);
1814        }
1815    
1816        @Override
1817        public String getBaseComponentTemplate() {
1818            return baseComponentTemplate;
1819        }
1820    
1821        /**
1822         * @return pagesource of the base component
1823         */
1824        public PageSource getBaseComponentPageSource() {
1825            return getBaseComponentPageSource(ThreadLocalPageContext.get());
1826        }
1827        public PageSource getBaseComponentPageSource(PageContext pc) {
1828            if(baseComponentPageSource==null) {
1829                    baseComponentPageSource=PageSourceImpl.best(getPageSources(pc,null,getBaseComponentTemplate(),false,false,true));
1830            }
1831            return baseComponentPageSource;
1832        }
1833        
1834        /**
1835         * @param template The baseComponent template to set.
1836         */
1837        protected void setBaseComponentTemplate(String template) {
1838            this.baseComponentPageSource=null;
1839            this.baseComponentTemplate = template;
1840        }
1841        
1842        /**
1843         * sets the application logger
1844         * @param applicationLogger
1845         */
1846        protected void setApplicationLogger(LogAndSource applicationLogger) {
1847            this.applicationLogger=applicationLogger;
1848        }
1849        protected void setDeployLogger(LogAndSource deployLogger) {
1850            this.deployLogger=deployLogger;
1851        }
1852    
1853        protected void setScopeLogger(LogAndSource scopeLogger) {
1854            this.scopeLogger=scopeLogger;
1855        }
1856    
1857    
1858        protected void setMappingLogger(LogAndSource mappingLogger) {
1859            this.mappingLogger=mappingLogger;
1860        }
1861        
1862        protected void setRestLogger(LogAndSource restLogger) {
1863            this.restLogger=restLogger;
1864        }
1865    
1866    
1867        protected void setRestList(boolean restList) {
1868            this.restList=restList;
1869        }
1870    
1871        public boolean getRestList() {
1872            return restList;
1873        }
1874    
1875        /*protected void setRestAllowChanges(boolean restAllowChanges) {
1876            this.restAllowChanges=restAllowChanges;
1877        }
1878    
1879        public boolean getRestAllowChanges() {
1880            return restAllowChanges;
1881        }*/
1882        
1883        
1884    
1885        public LogAndSource getMappingLogger() {
1886            if(mappingLogger==null)
1887                    mappingLogger=new LogAndSourceImpl(LogConsole.getInstance(this,Log.LEVEL_ERROR),"");
1888                    return mappingLogger;
1889        }
1890        
1891        /**
1892         * @param clientType
1893         */
1894        protected void setClientType(short clientType) {
1895            this.clientType=clientType;
1896        }
1897        
1898        /**
1899         * @param strClientType
1900         */
1901        protected void setClientType(String strClientType) {
1902            strClientType=strClientType.trim().toLowerCase();
1903            if(strClientType.equals("file"))clientType=Config.CLIENT_SCOPE_TYPE_FILE;
1904            else if(strClientType.equals("db"))clientType=Config.CLIENT_SCOPE_TYPE_DB;
1905            else if(strClientType.equals("database"))clientType=Config.CLIENT_SCOPE_TYPE_DB;
1906            else clientType=Config.CLIENT_SCOPE_TYPE_COOKIE;
1907        }
1908        
1909        @Override
1910        public short getClientType() {
1911            return this.clientType;
1912        }
1913        
1914        /**
1915         * @param searchEngine The searchEngine to set.
1916         */
1917        protected void setSearchEngine(SearchEngine searchEngine) {
1918            this.searchEngine = searchEngine;
1919        }
1920    
1921        @Override
1922        public int getComponentDataMemberDefaultAccess() {
1923            return componentDataMemberDefaultAccess;
1924        }
1925        /**
1926         * @param componentDataMemberDefaultAccess The componentDataMemberDefaultAccess to set.
1927         */
1928        protected void setComponentDataMemberDefaultAccess(
1929                int componentDataMemberDefaultAccess) {
1930            this.componentDataMemberDefaultAccess = componentDataMemberDefaultAccess;
1931        }
1932    
1933        
1934        @Override
1935        public String getTimeServer() {
1936            return timeServer;
1937        }
1938    
1939        @Override
1940        public String getComponentDumpTemplate() {
1941            return componentDumpTemplate;
1942        }
1943        
1944        /**
1945         * @param template The componentDump template to set.
1946         */
1947        protected void setComponentDumpTemplate(String template) {
1948            this.componentDumpTemplate = template;
1949        }
1950    
1951        public String getSecurityToken() {
1952            if(securityToken==null){
1953                    try {
1954                            securityToken = Md5.getDigestAsString(getConfigDir().getAbsolutePath());
1955                            } 
1956                    catch (IOException e) {
1957                                    return null;
1958                            }
1959            }
1960            return securityToken;
1961            }
1962    
1963        @Override
1964        public String getId() {
1965            if(id==null){
1966                    id = getId(getSecurityKey(),getSecurityToken(),securityKey);
1967            }
1968            return id;
1969            }
1970    
1971        public static String getId(String key, String token,String defaultValue) {
1972            
1973                    try {
1974                            return Md5.getDigestAsString(key+token);
1975                    } 
1976            catch (IOException e) {
1977                            return defaultValue;
1978                    }
1979            }
1980        
1981        
1982        public String getSecurityKey() {
1983            return securityKey;
1984        }
1985    
1986        @Override
1987        public String getDebugTemplate() {
1988            throw new PageRuntimeException(new DeprecatedException("no longer supported, use instead getDebugEntry(ip, defaultValue)"));
1989        }
1990    
1991            @Override
1992            public String getErrorTemplate(int statusCode) {
1993                    return errorTemplates.get(Caster.toString(statusCode));
1994            }
1995    
1996            /**
1997             * @param errorTemplate the errorTemplate to set
1998             */
1999            protected void setErrorTemplate(int statusCode,String errorTemplate) {
2000                    this.errorTemplates.put(Caster.toString(statusCode), errorTemplate);
2001            }
2002    
2003        @Override
2004        public short getSessionType() {
2005            return sessionType;
2006        }
2007        /**
2008         * @param sessionType The sessionType to set.
2009         */
2010        protected void setSessionType(short sessionType) {
2011            this.sessionType = sessionType;
2012        }
2013        /**
2014         * @param type The sessionType to set.
2015         */
2016        protected void setSessionType(String type) {
2017            type=type.toLowerCase().trim();
2018            if(type.startsWith("cfm")) setSessionType(SESSION_TYPE_CFML);
2019            else if(type.startsWith("j")) setSessionType(SESSION_TYPE_J2EE);
2020            else setSessionType(SESSION_TYPE_CFML);
2021        }
2022    
2023        @Override
2024        public abstract String getUpdateType() ;
2025    
2026        @Override
2027        public abstract URL getUpdateLocation();
2028    
2029        @Override
2030        public Resource getDeployDirectory() {
2031            return deployDirectory;
2032        }
2033    
2034        /**
2035         * set the deploy directory, directory where railo deploy transalted cfml classes (java and class files)
2036         * @param strDeployDirectory deploy directory
2037         * @throws ExpressionException
2038         */
2039        protected void setDeployDirectory(String strDeployDirectory) throws ExpressionException {
2040            setDeployDirectory(resources.getResource(strDeployDirectory));
2041        }
2042        
2043        /**
2044         * set the deploy directory, directory where railo deploy transalted cfml classes (java and class files)
2045         * @param deployDirectory deploy directory
2046         * @throws ExpressionException
2047         * @throws ExpressionException
2048         */
2049        protected void setDeployDirectory(Resource deployDirectory) throws ExpressionException {
2050            if(!isDirectory(deployDirectory)) {
2051                throw new ExpressionException("deploy directory "+deployDirectory+" doesn't exist or is not a directory");
2052            }
2053            this.deployDirectory=deployDirectory;
2054        }
2055        
2056    
2057        @Override
2058        public abstract Resource getRootDirectory();
2059    
2060        /**
2061         * sets the compileType value.
2062         * @param compileType The compileType to set.
2063         */
2064        protected void setCompileType(short compileType) {
2065            this.compileType = compileType;
2066        }
2067    
2068        /** FUTHER
2069         * Returns the value of suppresswhitespace.
2070         * @return value suppresswhitespace
2071         */
2072        public boolean isSuppressWhitespace() {
2073            return suppresswhitespace;
2074        }
2075    
2076        /** FUTHER
2077         * sets the suppresswhitespace value.
2078         * @param suppresswhitespace The suppresswhitespace to set.
2079         */
2080        protected void setSuppressWhitespace(boolean suppresswhitespace) {
2081            this.suppresswhitespace = suppresswhitespace;
2082        }
2083        
2084    
2085        public boolean isSuppressContent() {
2086            return suppressContent;
2087        }
2088        
2089        protected void setSuppressContent(boolean suppressContent) {
2090            this.suppressContent = suppressContent;
2091        }
2092        
2093    
2094            @Override
2095            public String getDefaultEncoding() {
2096                    return webCharset;
2097            }
2098            
2099            @Override
2100            public String getTemplateCharset() {
2101                    return templateCharset;
2102            }
2103            
2104            /**
2105             * sets the charset to read the files
2106             * @param templateCharset
2107             */
2108            protected void setTemplateCharset(String templateCharset) {
2109                    this.templateCharset = templateCharset;
2110            }
2111    
2112            @Override
2113            public String getWebCharset() {
2114                    return webCharset;
2115            }
2116            
2117            /**
2118             * sets the charset to read and write resources
2119             * @param resourceCharset
2120             */
2121            protected void setResourceCharset(String resourceCharset) {
2122                    this.resourceCharset = resourceCharset;
2123            }
2124    
2125            @Override
2126            public String getResourceCharset() {
2127                    return resourceCharset;
2128            }
2129            
2130            /**
2131             * sets the charset for the response stream
2132             * @param outputEncoding
2133             */
2134            protected void setWebCharset(String webCharset) {
2135                    this.webCharset = webCharset;
2136            }
2137    
2138            public SecurityManager getSecurityManager() {
2139                    return null;
2140            }
2141    
2142            /**
2143             * @return the fldFile
2144             */
2145            public Resource getFldFile() {
2146                    return fldFile;
2147            }
2148    
2149            /**
2150             * @return the tldFile
2151             */
2152            public Resource getTldFile() {
2153                    return tldFile;
2154            }
2155        
2156        @Override
2157            public DataSource[] getDataSources() {
2158                    Map<String, DataSource> map = getDataSourcesAsMap();
2159                    Iterator<DataSource> it = map.values().iterator();
2160                    DataSource[] ds = new DataSource[map.size()];
2161                    int count=0;
2162                    
2163                    while(it.hasNext()) {
2164                            ds[count++]=it.next();
2165                    }
2166                    return ds;
2167            }
2168            
2169            public Map<String,DataSource> getDataSourcesAsMap() {
2170            Map<String,DataSource> map=new HashMap<String, DataSource>();
2171            Iterator<Entry<String, DataSource>> it = datasources.entrySet().iterator();
2172            Entry<String, DataSource> entry;
2173            while(it.hasNext()) {
2174                entry = it.next();
2175                if(!entry.getKey().equals("_queryofquerydb"))
2176                    map.put(entry.getKey(),entry.getValue());
2177            }        
2178            return map;
2179        }
2180    
2181            /**
2182             * @return the mailDefaultCharset
2183             */
2184            public String getMailDefaultEncoding() {
2185                    return mailDefaultEncoding;
2186            }
2187    
2188            /**
2189             * @param mailDefaultCharset the mailDefaultCharset to set
2190             */
2191            protected void setMailDefaultEncoding(String mailDefaultEncoding) {
2192                    this.mailDefaultEncoding = mailDefaultEncoding;
2193            }
2194    
2195            protected void setDefaultResourceProvider(String strDefaultProviderClass, Map arguments) throws ClassException {
2196                    Object o=ClassUtil.loadInstance(strDefaultProviderClass);
2197                    if(o instanceof ResourceProvider) {
2198                            ResourceProvider rp=(ResourceProvider) o;
2199                            rp.init(null,arguments);
2200                            setDefaultResourceProvider(rp);
2201                    }
2202                    else 
2203                            throw new ClassException("object ["+Caster.toClassName(o)+"] must implement the interface "+ResourceProvider.class.getName());
2204            }
2205    
2206            protected void setDefaultResourceProvider(Class defaultProviderClass, Map arguments) throws ClassException {
2207                    Object o=ClassUtil.loadInstance(defaultProviderClass);
2208                    if(o instanceof ResourceProvider) {
2209                            ResourceProvider rp=(ResourceProvider) o;
2210                            rp.init(null,arguments);
2211                            setDefaultResourceProvider(rp);
2212                    }
2213                    else 
2214                            throw new ClassException("object ["+Caster.toClassName(o)+"] must implement the interface "+ResourceProvider.class.getName());
2215            }
2216    
2217            /**
2218             * @param defaultResourceProvider the defaultResourceProvider to set
2219             */
2220            protected void setDefaultResourceProvider(ResourceProvider defaultResourceProvider) {
2221                    resources.registerDefaultResourceProvider(defaultResourceProvider);
2222            }
2223    
2224            /**
2225             * @return the defaultResourceProvider
2226             */
2227            public ResourceProvider getDefaultResourceProvider() {
2228                    return resources.getDefaultResourceProvider();
2229            }
2230    
2231            protected void addResourceProvider(String strProviderScheme, String strProviderClass, Map arguments) throws ClassException {
2232                    // old buld in S3
2233                    
2234                    
2235                    Object o=null;
2236                    
2237                    o=ClassUtil.loadInstance(strProviderClass);
2238                    
2239                    if(o instanceof ResourceProvider) {
2240                            ResourceProvider rp=(ResourceProvider) o;
2241                            rp.init(strProviderScheme,arguments);
2242                            addResourceProvider(rp);
2243                    }
2244                    else 
2245                            throw new ClassException("object ["+Caster.toClassName(o)+"] must implement the interface "+ResourceProvider.class.getName());
2246            }
2247            protected void addResourceProvider(String strProviderScheme, Class providerClass, Map arguments) throws ClassException {
2248                    Object o=ClassUtil.loadInstance(providerClass);
2249                    
2250                    if(o instanceof ResourceProvider) {
2251                            ResourceProvider rp=(ResourceProvider) o;
2252                            rp.init(strProviderScheme,arguments);
2253                            addResourceProvider(rp);
2254                    }
2255                    else 
2256                            throw new ClassException("object ["+Caster.toClassName(o)+"] must implement the interface "+ResourceProvider.class.getName());
2257            }
2258    
2259            protected void addResourceProvider(ResourceProvider provider) {
2260                    resources.registerResourceProvider(provider);
2261            }
2262            
2263    
2264            public void clearResourceProviders() {
2265                    resources.reset();
2266            }
2267            
2268    
2269            /**
2270             * @return return the resource providers
2271             */
2272            public ResourceProvider[] getResourceProviders() {
2273                    return resources.getResourceProviders();
2274            }
2275    
2276            protected void setResourceProviders(ResourceProvider[] resourceProviders) {
2277                    for(int i=0;i<resourceProviders.length;i++) {
2278                            resources.registerResourceProvider(resourceProviders[i]);
2279                    }
2280            }
2281    
2282    
2283            @Override
2284            public Resource getResource(String path) {
2285                    return resources.getResource(path);
2286            }
2287    
2288            @Override
2289            public ApplicationListener getApplicationListener() {
2290                    return applicationListener;
2291            }
2292    
2293            /**
2294             * @param applicationListener the applicationListener to set
2295             */
2296            protected void setApplicationListener(ApplicationListener applicationListener) {
2297                    this.applicationListener = applicationListener;
2298            }
2299    
2300            /**
2301             * @return the exceptionLogger
2302             */
2303            public LogAndSource getExceptionLogger() {
2304                    if(exceptionLogger==null)exceptionLogger=new LogAndSourceImpl(LogConsole.getInstance(this,Log.LEVEL_ERROR),"");
2305                    return exceptionLogger;
2306            }
2307    
2308            /**
2309             * @return the exceptionLogger
2310             */
2311            public LogAndSource getTraceLogger() {
2312                    if(traceLogger==null)traceLogger=new LogAndSourceImpl(LogConsole.getInstance(this,Log.LEVEL_ERROR),"");
2313                    return traceLogger;
2314            }
2315    
2316            /**
2317             * @param exceptionLogger the exceptionLogger to set
2318             */
2319            protected void setExceptionLogger(LogAndSource exceptionLogger) {
2320                    this.exceptionLogger = exceptionLogger;
2321            }
2322    
2323            /**
2324             * @param traceLogger the traceLogger to set
2325             */
2326            protected void setTraceLogger(LogAndSource traceLogger) {
2327                    this.traceLogger = traceLogger;
2328            }
2329    
2330            /**
2331             * @return the scriptProtect
2332             */
2333            public int getScriptProtect() {
2334                    return scriptProtect;
2335            }
2336    
2337            /**
2338             * @param scriptProtect the scriptProtect to set
2339             */
2340            protected void setScriptProtect(int scriptProtect) {
2341                    this.scriptProtect = scriptProtect;
2342            }
2343    
2344            /**
2345             * @return the proxyPassword
2346             */
2347            public ProxyData getProxyData() {
2348                    return proxy;
2349            }
2350    
2351            /**
2352             * @param proxyPassword the proxyPassword to set
2353             */
2354            protected void setProxyData(ProxyData proxy) {
2355                    this.proxy = proxy;
2356            }
2357    
2358            @Override
2359            public boolean isProxyEnableFor(String host) {
2360                    return false;// TODO proxyEnable;
2361            }
2362    
2363            /**
2364             * @return the triggerComponentDataMember
2365             */
2366            public boolean getTriggerComponentDataMember() {
2367                    return triggerComponentDataMember;
2368            }
2369    
2370            /**
2371             * @param triggerComponentDataMember the triggerComponentDataMember to set
2372             */
2373            protected void setTriggerComponentDataMember(boolean triggerComponentDataMember) {
2374                    this.triggerComponentDataMember = triggerComponentDataMember;
2375            }
2376    
2377            @Override
2378            public Resource getClientScopeDir() {
2379                    if(clientScopeDir==null) clientScopeDir=getConfigDir().getRealResource("client-scope");
2380                    return clientScopeDir;
2381            }
2382    
2383            public Resource getSessionScopeDir() {
2384                    if(sessionScopeDir==null) sessionScopeDir=getConfigDir().getRealResource("session-scope");
2385                    return sessionScopeDir;
2386            }
2387            
2388            
2389    
2390            /*public int getClientScopeMaxAge() {
2391                    return clientScopeMaxAge;
2392            }
2393            
2394            public void setClientScopeMaxAge(int age) {
2395                    this. clientScopeMaxAge=age;
2396            }*/
2397            
2398            
2399    
2400            @Override
2401            public long getClientScopeDirSize() {
2402                    return clientScopeDirSize;
2403            }
2404            public long getSessionScopeDirSize() {
2405                    return sessionScopeDirSize;
2406            }
2407    
2408            /**
2409             * @param clientScopeDir the clientScopeDir to set
2410             */
2411            protected void setClientScopeDir(Resource clientScopeDir) {
2412                    this.clientScopeDir = clientScopeDir;
2413            }
2414            
2415            protected void setSessionScopeDir(Resource sessionScopeDir) {
2416                    this.sessionScopeDir = sessionScopeDir;
2417            }
2418    
2419            /**
2420             * @param clientScopeDirSize the clientScopeDirSize to set
2421             */
2422            protected void setClientScopeDirSize(long clientScopeDirSize) {
2423                    this.clientScopeDirSize = clientScopeDirSize;
2424            }
2425    
2426            @Override
2427            public ClassLoader getRPCClassLoader(boolean reload) throws IOException {
2428                    
2429                    if(rpcClassLoader!=null && !reload) return rpcClassLoader;
2430            
2431                    Resource dir = getDeployDirectory().getRealResource("RPC");
2432                    if(!dir.exists())dir.createDirectory(true);
2433                    //rpcClassLoader = new PhysicalClassLoader(dir,getFactory().getServlet().getClass().getClassLoader());
2434                    rpcClassLoader = new PhysicalClassLoader(dir,getClassLoader());
2435                    return rpcClassLoader;
2436            }
2437            
2438            public void resetRPCClassLoader() {
2439                    rpcClassLoader=null;
2440            }
2441    
2442            protected void setCacheDir(Resource cacheDir) {
2443                    this.cacheDir=cacheDir;
2444            }
2445            
2446            public Resource getCacheDir() {
2447                    return this.cacheDir;
2448            }
2449    
2450            public long getCacheDirSize() {
2451                    return cacheDirSize;
2452            }
2453    
2454            protected void setCacheDirSize(long cacheDirSize) {
2455                    this.cacheDirSize=cacheDirSize;
2456            }
2457            
2458    
2459    
2460            protected void setDumpWritersEntries(DumpWriterEntry[] dmpWriterEntries) {
2461                    this.dmpWriterEntries=dmpWriterEntries;
2462            }
2463            
2464            public DumpWriterEntry[] getDumpWritersEntries() {
2465                    return dmpWriterEntries;
2466            }
2467            
2468            @Override
2469            public DumpWriter getDefaultDumpWriter(int defaultType) {
2470                    DumpWriterEntry[] entries = getDumpWritersEntries();
2471                    if(entries!=null)for(int i=0;i<entries.length;i++){
2472                            if(entries[i].getDefaultType()==defaultType) {
2473                                    return entries[i].getWriter();
2474                            }
2475                    }
2476                    return new HTMLDumpWriter();
2477            }
2478    
2479            @Override
2480            public DumpWriter getDumpWriter(String name) throws DeprecatedException {
2481                    throw new DeprecatedException("this method is no longer supported");
2482            }
2483            
2484            public DumpWriter getDumpWriter(String name,int defaultType) throws ExpressionException {
2485                    if(StringUtil.isEmpty(name)) return getDefaultDumpWriter(defaultType);
2486                    
2487                    DumpWriterEntry[] entries = getDumpWritersEntries();
2488                    for(int i=0;i<entries.length;i++){
2489                            if(entries[i].getName().equals(name)) {
2490                                    return entries[i].getWriter();
2491                            }
2492                    }
2493                    
2494                    // error
2495                    StringBuffer sb=new StringBuffer(); 
2496                    for(int i=0;i<entries.length;i++){
2497                            if(i>0)sb.append(", ");
2498                            sb.append(entries[i].getName());
2499                    }
2500                    throw new ExpressionException("invalid format definition ["+name+"], valid definitions are ["+sb+"]");
2501            }
2502            
2503            @Override
2504            public boolean useComponentShadow() {
2505                    return useComponentShadow;
2506            }
2507    
2508            public boolean useComponentPathCache() {
2509                    return useComponentPathCache;
2510            }
2511            
2512            public boolean useCTPathCache() {
2513                    return useCTPathCache;
2514            }
2515            
2516            public void flushComponentPathCache() {
2517                    if(componentPathCache!=null)componentPathCache.clear();
2518            }
2519            
2520            public void flushCTPathCache() {
2521                    if(ctPatchCache!=null)ctPatchCache.clear();
2522            }
2523            
2524    
2525            protected void setUseCTPathCache(boolean useCTPathCache) {
2526                    this.useCTPathCache = useCTPathCache;
2527            }
2528            protected void setUseComponentPathCache(boolean useComponentPathCache) {
2529                    this.useComponentPathCache = useComponentPathCache;
2530            }
2531    
2532            /**
2533             * @param useComponentShadow the useComponentShadow to set
2534             */
2535            protected void setUseComponentShadow(boolean useComponentShadow) {
2536                    this.useComponentShadow = useComponentShadow;
2537            }
2538            
2539            @Override
2540            public DataSource getDataSource(String datasource) throws DatabaseException {
2541                    DataSource ds=(datasource==null)?null:(DataSource) datasources.get(datasource.toLowerCase());
2542                    if(ds!=null) return ds;
2543                    
2544                    
2545                    // create error detail
2546                    DatabaseException de = new DatabaseException("datasource ["+datasource+"] doesn't exist",null,null,null);
2547                    de.setDetail(ExceptionUtil.createSoundexDetail(datasource,datasources.keySet().iterator(),"datasource names"));
2548                    de.setAdditional(KeyConstants._Datasource,datasource);
2549                    throw de;
2550            }
2551            
2552            @Override
2553            public DataSource getDataSource(String datasource, DataSource defaultValue) {
2554                    DataSource ds=(datasource==null)?null:(DataSource) datasources.get(datasource.toLowerCase());
2555                    if(ds!=null) return ds;
2556                    return defaultValue;
2557            }
2558    
2559            @Override
2560            public PrintWriter getErrWriter() {
2561                    return err;
2562            }
2563    
2564            /**
2565             * @param err the err to set
2566             */
2567            protected void setErr(PrintWriter err) {
2568                    this.err = err;
2569            }
2570    
2571            @Override
2572            public PrintWriter getOutWriter() {
2573                    return out;
2574            }
2575    
2576            /**
2577             * @param out the out to set
2578             */
2579            protected void setOut(PrintWriter out) {
2580                    this.out = out;
2581            }
2582    
2583            public DatasourceConnectionPool getDatasourceConnectionPool() {
2584                    return pool;
2585            }
2586    
2587    
2588    
2589            public boolean doLocalCustomTag() {
2590                    return doLocalCustomTag;
2591            }       
2592            
2593            @Override
2594            public String[] getCustomTagExtensions() {
2595                    return customTagExtensions;
2596            }
2597            
2598            protected void setCustomTagExtensions(String[] customTagExtensions) {
2599                    this.customTagExtensions = customTagExtensions;
2600            }
2601            
2602            protected void setDoLocalCustomTag(boolean doLocalCustomTag) {
2603                    this.doLocalCustomTag= doLocalCustomTag;
2604            }
2605            
2606    
2607            public boolean doComponentDeepSearch() {
2608                    return doComponentTagDeepSearch;
2609            }
2610            
2611            protected void setDoComponentDeepSearch(boolean doComponentTagDeepSearch) {
2612                    this.doComponentTagDeepSearch = doComponentTagDeepSearch;
2613            }
2614            
2615            @Override
2616            public boolean doCustomTagDeepSearch() {
2617                    return doCustomTagDeepSearch;
2618            }
2619            
2620    
2621            /**
2622             * @param doCustomTagDeepSearch the doCustomTagDeepSearch to set
2623             */
2624            protected void setDoCustomTagDeepSearch(boolean doCustomTagDeepSearch) {
2625                    this.doCustomTagDeepSearch = doCustomTagDeepSearch;
2626            }
2627    
2628            protected void setVersion(double version) {
2629                    this.version=version;
2630            }
2631    
2632            /**
2633             * @return the version
2634             */
2635            public double getVersion() {
2636                    return version;
2637            }
2638            
2639    
2640    
2641            public boolean closeConnection() {
2642                    return closeConnection;
2643            }
2644    
2645            protected void setCloseConnection(boolean closeConnection) {
2646                    this.closeConnection=closeConnection;
2647            }
2648    
2649            public boolean contentLength() {
2650                    return contentLength;
2651            }
2652            
2653    
2654            public boolean allowCompression() {
2655                    return allowCompression;
2656            }
2657            protected void setAllowCompression(boolean allowCompression) {
2658                    this.allowCompression= allowCompression;
2659            }
2660    
2661    
2662            protected void setContentLength(boolean contentLength) {
2663                    this.contentLength=contentLength;
2664            }
2665    
2666            /**
2667             * @return the constants
2668             */
2669            public Struct getConstants() {
2670                    return constants;
2671            }
2672    
2673            /**
2674             * @param constants the constants to set
2675             */
2676            protected void setConstants(Struct constants) {
2677                    this.constants = constants;
2678            }
2679    
2680            /**
2681             * @return the showVersion
2682             */
2683            public boolean isShowVersion() {
2684                    return showVersion;
2685            }
2686    
2687            /**
2688             * @param showVersion the showVersion to set
2689             */
2690            protected void setShowVersion(boolean showVersion) {
2691                    this.showVersion = showVersion;
2692            }
2693    
2694            protected void setRemoteClients(RemoteClient[] remoteClients) {
2695                    this.remoteClients=remoteClients;
2696            }
2697            
2698            public RemoteClient[] getRemoteClients() {
2699                    if(remoteClients==null) return new RemoteClient[0];
2700                    return remoteClients;
2701            }
2702    
2703            protected void setSecurityKey(String securityKey) {
2704                    this.securityKey=securityKey;
2705                    this.id=null;
2706            }
2707    
2708            public SpoolerEngine getSpoolerEngine() {
2709                    return remoteClientSpoolerEngine;
2710            }
2711    
2712            protected void setRemoteClientLog(LogAndSource remoteClientLog) {
2713                    this.remoteClientLog=remoteClientLog;
2714            }
2715    
2716            protected void setRemoteClientDirectory(Resource remoteClientDirectory) {
2717                    this.remoteClientDirectory=remoteClientDirectory;
2718            }
2719    
2720            /**
2721             * @return the remoteClientDirectory
2722             */
2723            public Resource getRemoteClientDirectory() {
2724                    return remoteClientDirectory;
2725            }
2726    
2727            /**
2728             * @return the remoteClientLog
2729             */
2730            public LogAndSource getRemoteClientLog() {
2731                    return remoteClientLog;
2732            }
2733    
2734            protected void setSpoolerEngine(SpoolerEngine spoolerEngine) {
2735                    this.remoteClientSpoolerEngine=spoolerEngine;
2736            }
2737    
2738            /**
2739             * @return the factory
2740             */
2741            public CFMLFactory getFactory() {
2742                    return factory;
2743            }
2744    
2745            
2746            
2747            /* *
2748             * @return the structCase
2749             * /
2750            public int getStructCase() {
2751                    return structCase;
2752            }*/
2753    
2754            /* *
2755             * @param structCase the structCase to set
2756             * /
2757            protected void setStructCase(int structCase) {
2758                    this.structCase = structCase;
2759            }*/
2760            
2761    
2762            /**
2763             * @return if error status code will be returned or not
2764             */
2765            public boolean getErrorStatusCode() {
2766                    return errorStatusCode;
2767            }
2768    
2769            /**
2770             * @param errorStatusCode the errorStatusCode to set
2771             */
2772            protected void setErrorStatusCode(boolean errorStatusCode) {
2773                    this.errorStatusCode = errorStatusCode;
2774            }
2775    
2776            @Override
2777            public int getLocalMode() {
2778                    return localMode;
2779            }
2780    
2781            /**
2782             * @param localMode the localMode to set
2783             */
2784            protected void setLocalMode(int localMode) {
2785                    this.localMode = localMode;
2786            }
2787    
2788            /**
2789             * @param localMode the localMode to set
2790             */
2791            protected void setLocalMode(String strLocalMode) {
2792                    this.localMode=AppListenerUtil.toLocalMode(strLocalMode,this.localMode);
2793            }
2794    
2795            public Resource getVideoDirectory() {
2796                    // TODO take from tag <video>
2797                    Resource dir = getConfigDir().getRealResource("video");
2798                if(!dir.exists())dir.mkdirs();
2799                return dir;
2800            }
2801    
2802    
2803            public Resource getExtensionDirectory() {
2804                    // TODO take from tag <extensions>
2805                    Resource dir = getConfigDir().getRealResource("extensions");
2806                if(!dir.exists())dir.mkdirs();
2807                return dir;
2808            }
2809            
2810            protected void setExtensionProviders(ExtensionProvider[] extensionProviders) {
2811                    this.extensionProviders=extensionProviders;
2812            }
2813    
2814            public ExtensionProvider[] getExtensionProviders() {
2815                    return extensionProviders;
2816            }
2817    
2818            public Extension[] getExtensions() {
2819                    return extensions;
2820            }
2821    
2822            protected void setExtensions(Extension[] extensions) {
2823                    
2824                    this.extensions=extensions;
2825            }
2826    
2827            protected void setExtensionEnabled(boolean extensionEnabled) {
2828                    this.extensionEnabled=extensionEnabled;
2829            }
2830            public boolean isExtensionEnabled() {
2831                    return extensionEnabled;
2832            }
2833    
2834            public boolean allowRealPath() {
2835                    return allowRealPath;
2836            }
2837    
2838            protected void setAllowRealPath(boolean allowRealPath) {
2839                    this.allowRealPath=allowRealPath;
2840            }
2841    
2842            /**
2843             * @return the classClusterScope
2844             */
2845            public Class getClusterClass() {
2846                    return clusterClass;
2847            }
2848    
2849            /**
2850             * @param classClusterScope the classClusterScope to set
2851             */
2852            protected void setClusterClass(Class clusterClass) {
2853                    this.clusterClass = clusterClass;
2854            }
2855    
2856            @Override
2857            public Struct getRemoteClientUsage() {
2858                    if(remoteClientUsage==null)remoteClientUsage=new StructImpl();
2859                    return remoteClientUsage;
2860            }
2861            
2862            protected void setRemoteClientUsage(Struct remoteClientUsage) {
2863                    this.remoteClientUsage=remoteClientUsage;
2864            }
2865    
2866            @Override
2867            public Class getAdminSyncClass() {
2868                    return adminSyncClass;
2869            }
2870    
2871            protected void setAdminSyncClass(Class adminSyncClass) {
2872                    this.adminSyncClass=adminSyncClass;
2873                    this.adminSync=null;
2874            }
2875    
2876            public AdminSync getAdminSync() throws ClassException {
2877                    if(adminSync==null){
2878                            adminSync=(AdminSync) ClassUtil.loadInstance(getAdminSyncClass());
2879                            
2880                    }
2881                    return this.adminSync;
2882            }
2883            
2884            @Override
2885            public Class getVideoExecuterClass() {
2886                    return videoExecuterClass;
2887            }
2888            
2889            protected void setVideoExecuterClass(Class videoExecuterClass) {
2890                    this.videoExecuterClass=videoExecuterClass;
2891            }
2892    
2893            protected void setUseTimeServer(boolean useTimeServer) {
2894                    this.useTimeServer=useTimeServer;
2895            }
2896            
2897            public boolean getUseTimeServer() {
2898                    return useTimeServer; 
2899            }
2900            
2901    
2902            /**
2903             * @return the tagMappings
2904             */
2905            public Mapping getTagMapping() {
2906                    return tagMapping;
2907            }
2908            
2909            public Mapping getFunctionMapping() {
2910                    return functionMapping;
2911            }
2912    
2913            /**
2914             * @return the tagDirectory
2915             */
2916            public Resource getTagDirectory() {
2917                    return tagDirectory;
2918            }
2919    
2920            public void setAMFCaster(String strCaster, Map args) {
2921    
2922                    amfCasterArguments=args;
2923            try{
2924                            if(StringUtil.isEmpty(strCaster) || "classic".equalsIgnoreCase(strCaster)) 
2925                            amfCasterClass=ClassicAMFCaster.class;
2926                    else if("modern".equalsIgnoreCase(strCaster))
2927                            amfCasterClass=ModernAMFCaster.class;
2928                    else {
2929                            Class caster = ClassUtil.loadClass(strCaster);
2930                            if((caster.newInstance() instanceof AMFCaster)) {
2931                                    amfCasterClass=caster;
2932                            }
2933                            else {
2934                                    amfCasterClass=ClassicAMFCaster.class;
2935                                    throw new ClassException("object ["+Caster.toClassName(caster)+"] must implement the interface "+ResourceProvider.class.getName());
2936                            }
2937                    }
2938            }
2939            catch(Exception e){
2940                    e.printStackTrace();
2941            }
2942            }
2943            
2944            public void setAMFCaster(Class clazz, Map args) {
2945                    amfCasterArguments=args;
2946            amfCasterClass=clazz;
2947            }
2948            
2949            public void setAMFConfigType(String strDeploy) {
2950                    if(!StringUtil.isEmpty(strDeploy)){
2951                            if("xml".equalsIgnoreCase(strDeploy))amfConfigType=AMF_CONFIG_TYPE_XML;
2952                            else if("manual".equalsIgnoreCase(strDeploy))amfConfigType=AMF_CONFIG_TYPE_MANUAL;
2953                    }
2954            }
2955            public void setAMFConfigType(int amfDeploy) {
2956                    this.amfConfigType=amfDeploy;
2957            }
2958            public int getAMFConfigType() {
2959                    return amfConfigType;
2960            }
2961    
2962            public AMFCaster getAMFCaster(ConfigMap properties) throws ClassException {
2963                    if(amfCaster==null){
2964                            if(properties!=null){
2965                                    ConfigMap cases = properties.getPropertyAsMap("property-case", null);
2966                            if(cases!=null){
2967                                    if(!amfCasterArguments.containsKey("force-cfc-lowercase"))
2968                                            amfCasterArguments.put("force-cfc-lowercase",Caster.toBoolean(cases.getPropertyAsBoolean("force-cfc-lowercase", false)));
2969                                    if(!amfCasterArguments.containsKey("force-query-lowercase"))
2970                                            amfCasterArguments.put("force-query-lowercase",Caster.toBoolean(cases.getPropertyAsBoolean("force-query-lowercase", false)));
2971                                    if(!amfCasterArguments.containsKey("force-struct-lowercase"))
2972                                            amfCasterArguments.put("force-struct-lowercase",Caster.toBoolean(cases.getPropertyAsBoolean("force-struct-lowercase", false)));
2973                                    
2974                            }
2975                            ConfigMap access = properties.getPropertyAsMap("access", null);
2976                            if(access!=null){
2977                                    if(!amfCasterArguments.containsKey("use-mappings"))
2978                                            amfCasterArguments.put("use-mappings",Caster.toBoolean(access.getPropertyAsBoolean("use-mappings", false)));
2979                                    if(!amfCasterArguments.containsKey("method-access-level"))
2980                                            amfCasterArguments.put("method-access-level",access.getPropertyAsString("method-access-level","remote"));
2981                            }
2982                            }
2983                            
2984                            amfCaster=(AMFCaster)ClassUtil.loadInstance(amfCasterClass);
2985                            amfCaster.init(amfCasterArguments);
2986                    }
2987                    return amfCaster;
2988            }
2989            public Class getAMFCasterClass() {
2990                    return amfCasterClass;
2991            }
2992            public Map getAMFCasterArguments() {
2993                    if(amfCasterArguments==null) amfCasterArguments=new HashMap();
2994                    return amfCasterArguments;
2995            }
2996    
2997            public String getDefaultDataSource() {
2998                    // TODO Auto-generated method stub
2999                    return null;
3000            }
3001            protected void setDefaultDataSource(String defaultDataSource) {
3002                    //this.defaultDataSource=defaultDataSource;
3003            }
3004    
3005            /**
3006             * @return the inspectTemplate 
3007             */
3008            public short getInspectTemplate() {
3009                    return inspectTemplate;
3010            }
3011    
3012            /**
3013             * @param inspectTemplate the inspectTemplate to set
3014             */
3015            protected void setInspectTemplate(short inspectTemplate) {
3016                    this.inspectTemplate = inspectTemplate;
3017            }
3018    
3019            protected void setSerialNumber(String serial) {
3020                    this.serial=serial;
3021            }
3022    
3023            public String getSerialNumber() {
3024                    return serial;
3025            }
3026    
3027            protected void setCaches(Map<String,CacheConnection> caches) {
3028                    this.caches=caches;
3029                    Iterator<Entry<String, CacheConnection>> it = caches.entrySet().iterator();
3030                    Entry<String, CacheConnection> entry;
3031                    CacheConnection cc;
3032                    while(it.hasNext()){
3033                            entry = it.next();
3034                            cc=entry.getValue();
3035                            if(cc.getName().equalsIgnoreCase(cacheDefaultConnectionNameTemplate)){
3036                                    defaultCacheTemplate=cc;
3037                            }
3038                            else if(cc.getName().equalsIgnoreCase(cacheDefaultConnectionNameFunction)){
3039                                    defaultCacheFunction=cc;
3040                            }
3041                            else if(cc.getName().equalsIgnoreCase(cacheDefaultConnectionNameQuery)){
3042                                    defaultCacheQuery=cc;
3043                            }
3044                            else if(cc.getName().equalsIgnoreCase(cacheDefaultConnectionNameResource)){
3045                                    defaultCacheResource=cc;
3046                            }
3047                            else if(cc.getName().equalsIgnoreCase(cacheDefaultConnectionNameObject)){
3048                                    defaultCacheObject=cc;
3049                            }
3050                    }
3051            }
3052            
3053            @Override
3054            public Map<String,CacheConnection> getCacheConnections() {
3055                    return caches;
3056            }
3057    
3058            @Override
3059            public CacheConnection getCacheDefaultConnection(int type) {
3060                    if(type==CACHE_DEFAULT_FUNCTION)        return defaultCacheFunction;
3061                    if(type==CACHE_DEFAULT_OBJECT)          return defaultCacheObject;
3062                    if(type==CACHE_DEFAULT_TEMPLATE)        return defaultCacheTemplate;
3063                    if(type==CACHE_DEFAULT_QUERY)           return defaultCacheQuery;
3064                    if(type==CACHE_DEFAULT_RESOURCE)        return defaultCacheResource;
3065                    return null;
3066            }
3067    
3068            protected void setCacheDefaultConnectionName(int type,String cacheDefaultConnectionName) {
3069                    if(type==CACHE_DEFAULT_FUNCTION)                cacheDefaultConnectionNameFunction=cacheDefaultConnectionName;
3070                    else if(type==CACHE_DEFAULT_OBJECT)             cacheDefaultConnectionNameObject=cacheDefaultConnectionName;
3071                    else if(type==CACHE_DEFAULT_TEMPLATE)   cacheDefaultConnectionNameTemplate=cacheDefaultConnectionName;
3072                    else if(type==CACHE_DEFAULT_QUERY)              cacheDefaultConnectionNameQuery=cacheDefaultConnectionName;
3073                    else if(type==CACHE_DEFAULT_RESOURCE)   cacheDefaultConnectionNameResource=cacheDefaultConnectionName;
3074            }
3075            
3076            @Override
3077            public String getCacheDefaultConnectionName(int type) {
3078                    if(type==CACHE_DEFAULT_FUNCTION)        return cacheDefaultConnectionNameFunction;
3079                    if(type==CACHE_DEFAULT_OBJECT)          return cacheDefaultConnectionNameObject;
3080                    if(type==CACHE_DEFAULT_TEMPLATE)        return cacheDefaultConnectionNameTemplate;
3081                    if(type==CACHE_DEFAULT_QUERY)           return cacheDefaultConnectionNameQuery;
3082                    if(type==CACHE_DEFAULT_RESOURCE)        return cacheDefaultConnectionNameResource;
3083                    return null;
3084            }
3085    
3086            public String getCacheMD5() { 
3087                    return cacheMD5;
3088            }
3089    
3090            public void setCacheMD5(String cacheMD5) { 
3091                    this.cacheMD5 = cacheMD5;
3092            }
3093    
3094            public boolean getExecutionLogEnabled() {
3095                    return executionLogEnabled;
3096            }
3097            protected void setExecutionLogEnabled(boolean executionLogEnabled) {
3098                    this.executionLogEnabled= executionLogEnabled;
3099            }
3100    
3101            public ExecutionLogFactory getExecutionLogFactory() {
3102                    return executionLogFactory;
3103            }
3104            protected void setExecutionLogFactory(ExecutionLogFactory executionLogFactory) {
3105                    this.executionLogFactory= executionLogFactory;
3106            }
3107            
3108            public ORMEngine resetORMEngine(PageContext pc, boolean force) throws PageException {
3109                    //String name = pc.getApplicationContext().getName();
3110                    //ormengines.remove(name);
3111                    ORMEngine e = getORMEngine(pc);
3112                    e.reload(pc,force);
3113                    return e;
3114            }
3115            
3116            public ORMEngine getORMEngine(PageContext pc) throws PageException {
3117                    String name = pc.getApplicationContext().getName();
3118                    
3119                    ORMEngine engine = ormengines.get(name);
3120                    if(engine==null){
3121                            //try {
3122                            boolean hasError=false; 
3123                            try {
3124                                    engine=(ORMEngine)ClassUtil.loadInstance(ormEngineClass);
3125                                    engine.init(pc);
3126                            }
3127                            catch (ClassException t) {
3128                                    hasError=true;  
3129                            }
3130                            catch (NoClassDefFoundError t) {
3131                                    hasError=true;  
3132                            }
3133                            
3134                            if(hasError) {
3135                                    // try to load hibernate jars
3136                                    if(JarLoader.changed(pc.getConfig(), Admin.ORM_JARS))
3137                                            throw new ORMException(
3138                                                    "cannot initialize ORM Engine ["+ormEngineClass.getName()+"], make sure you have added all the required jar files",
3139                                                    "GO to the Railo Server Administrator and on the page Services/Update, click on \"Update JARs\"");
3140                                    throw new ORMException(
3141                                                            "cannot initialize ORM Engine ["+ormEngineClass.getName()+"], make sure you have added all the required jar files",
3142                                                            "if you have updated the JARs in the Railo Administrator, please restart your Servlet Engine");
3143                            
3144                            }
3145                                    ormengines.put(name,engine);
3146                            /*}
3147                            catch (PageException pe) {
3148                                    throw pe;
3149                            }*/
3150                    }
3151                    
3152                    return engine; 
3153            }
3154            
3155            public Class<ORMEngine> getORMEngineClass() {
3156                    return ormEngineClass; 
3157            }
3158            
3159            @Override
3160            public Mapping[] getComponentMappings() {
3161                    return componentMappings;
3162            }
3163    
3164            /**
3165             * @param componentMappings the componentMappings to set
3166             */
3167            protected void setComponentMappings(Mapping[] componentMappings) {
3168                    this.componentMappings = componentMappings;
3169            }
3170            
3171            protected void setORMEngineClass(Class<ORMEngine> ormEngineClass) {
3172                    this.ormEngineClass=ormEngineClass;
3173            }
3174    
3175            protected void setORMConfig(ORMConfiguration ormConfig) {
3176                    this.ormConfig=ormConfig;
3177            }
3178    
3179            public ORMConfiguration getORMConfig() {
3180                    return ormConfig;
3181            }
3182    
3183            public Mapping createCustomTagAppMappings(String virtual, String physical) {
3184                    Mapping m=customTagAppMappings.get(physical.toLowerCase());
3185                    
3186                    if(m==null){
3187                            m=new MappingImpl(
3188                                    this,virtual,
3189                                    physical,
3190                                    null,ConfigImpl.INSPECT_UNDEFINED,true,false,false,false,true,true,null
3191                                    );
3192                            customTagAppMappings.put(physical.toLowerCase(),m);
3193                    }
3194                    
3195                    return m;
3196            }
3197    
3198            
3199    
3200            private Map<String,PageSource> componentPathCache=null;//new ArrayList<Page>();
3201            private Map<String,InitFile> ctPatchCache=null;//new ArrayList<Page>();
3202            
3203            private Map<String,UDF> udfCache=new ReferenceMap();
3204            
3205            
3206            
3207            
3208            
3209            public Page getCachedPage(PageContext pc,String pathWithCFC) throws PageException {
3210                    if(componentPathCache==null) return null; 
3211                    
3212                    PageSource ps = componentPathCache.get(pathWithCFC.toLowerCase());
3213                    if(ps==null) return null;
3214                    return ((PageSourceImpl)ps).loadPage(pc,(Page)null);
3215            }
3216            
3217            public void putCachedPageSource(String pathWithCFC,PageSource ps) {
3218                    if(componentPathCache==null) componentPathCache=Collections.synchronizedMap(new HashMap<String, PageSource>());//MUSTMUST new ReferenceMap(ReferenceMap.SOFT,ReferenceMap.SOFT); 
3219                    componentPathCache.put(pathWithCFC.toLowerCase(),ps);
3220            }
3221            
3222            public InitFile getCTInitFile(PageContext pc,String key) {
3223                    if(ctPatchCache==null) return null; 
3224                    
3225                    InitFile initFile = ctPatchCache.get(key.toLowerCase());
3226                    if(initFile!=null){
3227                            if(MappingImpl.isOK(initFile.getPageSource()))return initFile;
3228                            ctPatchCache.remove(key.toLowerCase());
3229                    }
3230                    return null;
3231            }
3232            
3233            public void putCTInitFile(String key,InitFile initFile) {
3234                    if(ctPatchCache==null) ctPatchCache=Collections.synchronizedMap(new HashMap<String, InitFile>());//MUSTMUST new ReferenceMap(ReferenceMap.SOFT,ReferenceMap.SOFT); 
3235                    ctPatchCache.put(key.toLowerCase(),initFile);
3236            }
3237            
3238            
3239    
3240            public Struct listCTCache() {
3241                    Struct sct=new StructImpl();
3242                    if(ctPatchCache==null) return sct; 
3243                    Iterator<Entry<String, InitFile>> it = ctPatchCache.entrySet().iterator();
3244                    
3245                    Entry<String, InitFile> entry;
3246                    while(it.hasNext()){
3247                            entry = it.next();
3248                            sct.setEL(entry.getKey(),entry.getValue().getPageSource().getDisplayPath());
3249                    }
3250                    return sct;
3251            }
3252            
3253            public void clearCTCache() {
3254                    if(ctPatchCache==null) return; 
3255                    ctPatchCache.clear();
3256            }
3257            
3258    
3259            public void clearFunctionCache() {
3260                    udfCache.clear();
3261            }
3262            public UDF getFromFunctionCache(String key) {
3263                    return udfCache.get(key);
3264            }
3265            public void putToFunctionCache(String key,UDF udf) {
3266                    udfCache.put(key, udf);
3267            }
3268            
3269            
3270            public Struct listComponentCache() {
3271                    Struct sct=new StructImpl();
3272                    if(componentPathCache==null) return sct; 
3273                    Iterator<Entry<String, PageSource>> it = componentPathCache.entrySet().iterator();
3274                    
3275                    Entry<String, PageSource> entry;
3276                    while(it.hasNext()){
3277                            entry = it.next();
3278                            sct.setEL(entry.getKey(),entry.getValue().getDisplayPath());
3279                    }
3280                    return sct;
3281            }
3282            
3283            public void clearComponentCache() {
3284                    if(componentPathCache==null) return; 
3285                    componentPathCache.clear();
3286            }
3287            
3288            
3289    
3290            public ImportDefintion getComponentDefaultImport() {
3291                    return componentDefaultImport;
3292            }
3293            protected void setComponentDefaultImport(String str) {
3294                    ImportDefintion cdi = ImportDefintionImpl.getInstance(str, null);
3295                    if(cdi!=null)this.componentDefaultImport= cdi;
3296            }
3297    
3298        /**
3299             * @return the componentLocalSearch
3300             */
3301            public boolean getComponentLocalSearch() {
3302                    return componentLocalSearch;
3303            }
3304    
3305            /**
3306             * @param componentLocalSearch the componentLocalSearch to set
3307             */
3308            protected void setComponentLocalSearch(boolean componentLocalSearch) {
3309                    this.componentLocalSearch = componentLocalSearch;
3310            }
3311    
3312        /**
3313             * @return the componentLocalSearch
3314             */
3315            public boolean getComponentRootSearch() {
3316                    return componentRootSearch;
3317            }
3318    
3319            /**
3320             * @param componentLocalSearch the componentLocalSearch to set
3321             */
3322            protected void setComponentRootSearch(boolean componentRootSearch) {
3323                    this.componentRootSearch = componentRootSearch;
3324            }
3325    
3326            private final Map compressResources= new ReferenceMap(ReferenceMap.SOFT,ReferenceMap.SOFT);
3327            public Compress getCompressInstance(Resource zipFile, int format, boolean caseSensitive) {
3328                    Compress compress=(Compress) compressResources.get(zipFile.getPath());
3329                    if(compress==null) {
3330                            compress=new Compress(zipFile,format,caseSensitive);
3331                            compressResources.put(zipFile.getPath(), compress);
3332                    }
3333                    return compress;
3334            }
3335    
3336            public boolean getSessionCluster() {
3337                    return false;
3338            }
3339    
3340            public boolean getClientCluster() {
3341                    return false;
3342            }
3343            
3344            private Map<String,ComponentMetaData> componentMetaData=null;
3345            public ComponentMetaData getComponentMetadata(String key) {
3346                    if(componentMetaData==null) return null;
3347                    return componentMetaData.get(key.toLowerCase());
3348            }
3349            public void putComponentMetadata(String key,ComponentMetaData data) {
3350                    if(componentMetaData==null) componentMetaData=new HashMap<String, ComponentMetaData>();
3351                    componentMetaData.put(key.toLowerCase(),data);
3352            }
3353            
3354            public void clearComponentMetadata() {
3355                    if(componentMetaData==null) return; 
3356                    componentMetaData.clear();
3357            }
3358            
3359            public static class ComponentMetaData {
3360    
3361                    public final Struct meta;
3362                    public final long lastMod;
3363    
3364                    public ComponentMetaData(Struct meta, long lastMod) {
3365                            this.meta=meta;
3366                            this.lastMod=lastMod;
3367                    }
3368                    
3369            }
3370     
3371            private DebugEntry[] debugEntries;
3372            protected void setDebugEntries(DebugEntry[] debugEntries) {
3373                    this.debugEntries=debugEntries;
3374            }
3375    
3376            public DebugEntry[] getDebugEntries() {
3377                    if(debugEntries==null)debugEntries=new DebugEntry[0];
3378                    return debugEntries;
3379            }
3380            
3381            public DebugEntry getDebugEntry(String ip, DebugEntry defaultValue) {
3382                    if(debugEntries.length==0) return defaultValue;
3383                    short[] sarr;
3384                    try {
3385                            sarr = IPRange.toShortArray(ip);
3386                    } catch (IOException e) {
3387                            return defaultValue;
3388                    }
3389                    for(int i=0;i<debugEntries.length;i++){
3390                            if(debugEntries[i].getIpRange().inRange(sarr)) return debugEntries[i];
3391                    }
3392                    
3393                    
3394                    
3395                    return defaultValue;
3396            }
3397    
3398            private int debugMaxRecordsLogged=10;
3399            protected void setDebugMaxRecordsLogged(int debugMaxRecordsLogged) {
3400                    this.debugMaxRecordsLogged=debugMaxRecordsLogged;
3401            }
3402            public int getDebugMaxRecordsLogged() {
3403                    return debugMaxRecordsLogged;
3404            }
3405            
3406            public abstract int getLoginDelay();
3407            
3408            public abstract boolean getLoginCaptcha();
3409    
3410            private boolean dotNotationUpperCase=true;
3411            protected void setDotNotationUpperCase(boolean dotNotationUpperCase) {
3412                    this.dotNotationUpperCase=dotNotationUpperCase;
3413            }
3414    
3415            public boolean getDotNotationUpperCase() {
3416                    return dotNotationUpperCase;
3417            }
3418    
3419            private boolean getSupressWSBeforeArg=true;
3420            protected void setSupressWSBeforeArg(boolean getSupressWSBeforeArg) {
3421                    this.getSupressWSBeforeArg=getSupressWSBeforeArg;
3422            }
3423    
3424            public boolean getSupressWSBeforeArg() {
3425                    return getSupressWSBeforeArg;
3426            }
3427    
3428            public abstract boolean getFullNullSupport();
3429            
3430            
3431    
3432            public abstract Cluster createClusterScope() throws PageException;
3433    
3434    
3435            private RestSettings restSetting=new RestSettingImpl(false,UDF.RETURN_FORMAT_JSON);
3436            protected void setRestSetting(RestSettings restSetting){
3437                    this.restSetting= restSetting;
3438            }
3439            
3440            @Override
3441            public RestSettings getRestSetting(){
3442                    return restSetting; 
3443            }
3444    
3445            protected void setMode(int mode) {
3446                    this.mode=mode;
3447            }
3448    
3449            public int getMode() {
3450                    return mode;
3451            }
3452    
3453            // do not move to Config interface, do instead getCFMLWriterClass
3454            protected void setCFMLWriterType(int writerType) {
3455                    this.writerType=writerType;
3456            }
3457    
3458            // do not move to Config interface, do instead setCFMLWriterClass
3459            public int getCFMLWriterType() {
3460                    return writerType;
3461            }
3462    
3463            private boolean bufferOutput=true;
3464            public boolean getBufferOutput() {
3465                    return bufferOutput;
3466            }
3467    
3468            protected void setBufferOutput(boolean bufferOutput) {
3469                    this.bufferOutput= bufferOutput;
3470            }
3471    
3472            public int getDebugOptions() {
3473                    return debugOptions;
3474            }
3475            
3476            public boolean hasDebugOptions(int debugOption) {
3477                    return (debugOptions&debugOption)>0  ;
3478            }
3479            
3480            protected void setDebugOptions(int debugOptions) {
3481                    this.debugOptions = debugOptions;
3482            }
3483    
3484            public static Mapping[] getAllMappings(PageContext pc) {
3485                    List<Mapping> list=new ArrayList<Mapping>();
3486                    getAllMappings(list,pc.getConfig().getMappings());
3487                    getAllMappings(list,pc.getConfig().getCustomTagMappings());
3488                    getAllMappings(list,pc.getConfig().getComponentMappings());
3489                    getAllMappings(list,pc.getApplicationContext().getMappings());
3490                    return list.toArray(new Mapping[list.size()]);
3491            }
3492            
3493            public static Mapping[] getAllMappings(ConfigWeb cw) {
3494                    List<Mapping> list=new ArrayList<Mapping>();
3495                    getAllMappings(list,cw.getMappings());
3496                    getAllMappings(list,cw.getCustomTagMappings());
3497                    getAllMappings(list,cw.getComponentMappings());
3498                    return list.toArray(new Mapping[list.size()]);
3499            }
3500    
3501            private static void getAllMappings(List<Mapping> list, Mapping[] mappings) {
3502                    if(!ArrayUtil.isEmpty(mappings))for(int i=0;i<mappings.length;i++)   {
3503                            list.add(mappings[i]);
3504                    }
3505            }
3506    
3507            protected void setCheckForChangesInConfigFile(boolean checkForChangesInConfigFile) {
3508                    this.checkForChangesInConfigFile=checkForChangesInConfigFile;
3509            }
3510            public boolean checkForChangesInConfigFile() {
3511                    return checkForChangesInConfigFile;
3512            }
3513            
3514    }