001    package railo.runtime.config;
002    
003    import java.net.MalformedURLException;
004    import java.net.URL;
005    import java.util.HashMap;
006    import java.util.Iterator;
007    import java.util.Map;
008    
009    import railo.commons.collections.HashTable;
010    import railo.commons.io.SystemUtil;
011    import railo.commons.io.res.Resource;
012    import railo.commons.lang.ClassUtil;
013    import railo.commons.lang.PCLCollection;
014    import railo.commons.lang.StringUtil;
015    import railo.commons.lang.SystemOut;
016    import railo.loader.engine.CFMLEngine;
017    import railo.runtime.CFMLFactoryImpl;
018    import railo.runtime.Mapping;
019    import railo.runtime.MappingImpl;
020    import railo.runtime.engine.CFMLEngineImpl;
021    import railo.runtime.exp.ApplicationException;
022    import railo.runtime.exp.PageException;
023    import railo.runtime.monitor.IntervallMonitor;
024    import railo.runtime.monitor.RequestMonitor;
025    import railo.runtime.op.Caster;
026    import railo.runtime.reflection.Reflector;
027    import railo.runtime.security.SecurityManager;
028    import railo.runtime.security.SecurityManagerImpl;
029    import railo.runtime.type.scope.Cluster;
030    import railo.runtime.type.scope.ClusterRemote;
031    import railo.runtime.type.scope.ClusterWrap;
032    import railo.runtime.type.util.ArrayUtil;
033    
034    /**
035     * config server impl
036     */
037    public final class ConfigServerImpl extends ConfigImpl implements ConfigServer {
038        
039    
040            private final CFMLEngineImpl engine;
041        private Map initContextes;
042        private Map contextes;
043        private SecurityManager defaultSecurityManager;
044        private Map managers=new HashTable();
045        private String defaultPassword;
046        private Resource rootDir;
047        private URL updateLocation;
048        private String updateType="";
049            private ConfigListener configListener;
050            private Map<String, String> labels;
051            private RequestMonitor[] requestMonitors;
052            private IntervallMonitor[] intervallMonitors;
053            private boolean monitoringEnabled=false;
054            private int delay=0;
055            private boolean captcha=false;
056            private static ConfigServerImpl instance;
057            
058            /**
059         * @param engine 
060         * @param initContextes
061         * @param contextes
062         * @param configDir
063         * @param configFile
064         */
065        protected ConfigServerImpl(CFMLEngineImpl engine,Map initContextes, Map contextes, Resource configDir, Resource configFile) {
066            super(null,configDir, configFile);
067            this.engine=engine;
068            this.initContextes=initContextes;
069            this.contextes=contextes;
070            this.rootDir=configDir;
071            instance=this;
072        }
073            
074        /**
075             * @return the configListener
076             */
077            public ConfigListener getConfigListener() {
078                    return configListener;
079            }
080    
081            /**
082             * @param configListener the configListener to set
083             */
084            public void setConfigListener(ConfigListener configListener) {
085                    this.configListener = configListener;
086            }
087    
088            
089    
090        /**
091         * @see railo.runtime.config.ConfigImpl#getConfigServerImpl()
092         */
093        protected ConfigServerImpl getConfigServerImpl() {
094            return this;
095        }
096    
097        /**
098         * @see railo.runtime.config.ConfigImpl#getConfigServer(java.lang.String)
099         */
100        public ConfigServer getConfigServer(String password) {
101            return this;
102        }
103        
104    
105        public ConfigServer getConfigServer() {
106            return this;
107        }
108    
109        /**
110         * @see railo.runtime.config.ConfigServer#getConfigWebs()
111         */
112        public ConfigWeb[] getConfigWebs() {
113        
114             Iterator it = initContextes.keySet().iterator();
115            ConfigWeb[] webs=new ConfigWeb[initContextes.size()];
116            int index=0;        
117            while(it.hasNext()) {
118                webs[index++]=((CFMLFactoryImpl)initContextes.get(it.next())).getConfig();
119            }
120            return webs;
121        }
122        
123        /**
124         * @see railo.runtime.config.ConfigServer#getConfigWeb(java.lang.String)
125         */
126        public ConfigWeb getConfigWeb(String realpath) {
127            return getConfigWebImpl(realpath);
128        }
129        
130        /**
131         * returns CongigWeb Implementtion
132         * @param realpath
133         * @return ConfigWebImpl
134         */
135        protected ConfigWebImpl getConfigWebImpl(String realpath) {
136            Iterator it = initContextes.keySet().iterator();
137            while(it.hasNext()) {
138                ConfigWebImpl cw=((CFMLFactoryImpl)initContextes.get(it.next())).getConfigWebImpl();
139                if(cw.getServletContext().getRealPath("/").equals(realpath))
140                    return cw;
141            }
142            return null;
143        }
144        
145        public ConfigWebImpl getConfigWebById(String id) {
146            Iterator it = initContextes.keySet().iterator();
147              
148            while(it.hasNext()) {
149                ConfigWebImpl cw=((CFMLFactoryImpl)initContextes.get(it.next())).getConfigWebImpl();
150                if(cw.getId().equals(id))
151                    return cw;
152            }
153            return null;
154        }
155        
156        /**
157         * @return JspFactoryImpl array
158         */
159        public CFMLFactoryImpl[] getJSPFactories() {
160            Iterator it = initContextes.keySet().iterator();
161            CFMLFactoryImpl[] factories=new CFMLFactoryImpl[initContextes.size()];
162            int index=0;        
163            while(it.hasNext()) {
164                factories[index++]=(CFMLFactoryImpl)initContextes.get(it.next());
165            }
166            return factories;
167        }
168        /**
169         * @see railo.runtime.config.ConfigServer#getJSPFactoriesAsMap()
170         */
171        public Map getJSPFactoriesAsMap() {
172            return initContextes;
173        }
174    
175        /**
176         * @see railo.runtime.config.ConfigServer#getSecurityManager(java.lang.String)
177         */
178        public SecurityManager getSecurityManager(String id) {
179            Object o=managers.get(id);
180            if(o!=null) return (SecurityManager) o;
181            return defaultSecurityManager.cloneSecurityManager();
182        }
183        
184        /**
185         * @see railo.runtime.config.ConfigServer#hasIndividualSecurityManager(java.lang.String)
186         */
187        public boolean hasIndividualSecurityManager(String id) {
188            return managers.containsKey(id);
189        }
190    
191        /**
192         * @param defaultSecurityManager
193         */
194        protected void setDefaultSecurityManager(SecurityManager defaultSecurityManager) {
195            this.defaultSecurityManager=defaultSecurityManager;
196        }
197    
198        /**
199         * @param id
200         * @param securityManager
201         */
202        protected void setSecurityManager(String id, SecurityManager securityManager) {
203            managers.put(id,securityManager);
204        }
205    
206        /**
207         * @param id
208         */
209        protected void removeSecurityManager(String id) {
210            managers.remove(id);
211        }
212        
213        /**
214         * @see railo.runtime.config.ConfigServer#getDefaultSecurityManager()
215         */
216        public SecurityManager getDefaultSecurityManager() {
217            return defaultSecurityManager;
218        }
219        /**
220         * @return Returns the defaultPassword.
221         */
222        protected String getDefaultPassword() {
223            return defaultPassword;
224        }
225        /**
226         * @param defaultPassword The defaultPassword to set.
227         */
228        protected void setDefaultPassword(String defaultPassword) {
229            this.defaultPassword = defaultPassword;
230        }
231    
232        /**
233         * @see railo.runtime.config.ConfigServer#getCFMLEngine()
234         */
235        public CFMLEngine getCFMLEngine() {
236            return engine;
237        }
238        public CFMLEngineImpl getCFMLEngineImpl() {
239            return engine;
240        }
241    
242    
243        /**
244         * @return Returns the rootDir.
245         */
246        public Resource getRootDirectory() {
247            return rootDir;
248        }
249    
250        /**
251         * @see railo.runtime.config.Config#getUpdateType()
252         */
253        public String getUpdateType() {
254            return updateType;
255        }
256    
257        /**
258         * @see railo.runtime.config.ConfigServer#setUpdateType(java.lang.String)
259         */
260        public void setUpdateType(String updateType) {
261            if(!StringUtil.isEmpty(updateType))
262                this.updateType = updateType;
263        }
264    
265        /**
266         * @see railo.runtime.config.Config#getUpdateLocation()
267         */
268        public URL getUpdateLocation() {
269            return updateLocation;
270        }
271    
272        /**
273         * @see railo.runtime.config.ConfigServer#setUpdateLocation(java.net.URL)
274         */
275        public void setUpdateLocation(URL updateLocation) {
276            this.updateLocation = updateLocation;
277        }
278    
279        /**
280         * @see railo.runtime.config.ConfigServer#setUpdateLocation(java.lang.String)
281         */
282        public void setUpdateLocation(String strUpdateLocation) throws MalformedURLException {
283            setUpdateLocation(new URL(strUpdateLocation));
284        }
285    
286        /**
287         * @see railo.runtime.config.ConfigServer#setUpdateLocation(java.lang.String, java.net.URL)
288         */
289        public void setUpdateLocation(String strUpdateLocation, URL defaultValue) {
290            try {
291                setUpdateLocation(strUpdateLocation);
292            } catch (MalformedURLException e) {
293                setUpdateLocation(defaultValue);
294            }
295        }
296    
297        /**
298         * @see railo.runtime.config.Config#getSecurityManager()
299         */
300        public SecurityManager getSecurityManager() {
301            SecurityManagerImpl sm = (SecurityManagerImpl) getDefaultSecurityManager();//.cloneSecurityManager();
302            //sm.setAccess(SecurityManager.TYPE_ACCESS_READ,SecurityManager.ACCESS_PROTECTED);
303            //sm.setAccess(SecurityManager.TYPE_ACCESS_WRITE,SecurityManager.ACCESS_PROTECTED);
304            return sm;
305        }
306    
307            /**
308             * @return the instance
309             */
310            public static ConfigServerImpl getInstance() {
311                    return instance;
312            }
313    
314            public void setLabels(Map<String, String> labels) {
315                    this.labels=labels;
316            }
317            public Map<String, String> getLabels() {
318                    if(labels==null) labels=new HashMap<String, String>();
319                    return labels;
320            }
321    
322            public RequestMonitor[] getRequestMonitors() {
323                    return requestMonitors;
324            }
325            
326            public RequestMonitor getRequestMonitor(String name) throws ApplicationException {
327                    for(int i=0;i<requestMonitors.length;i++){
328                            if(requestMonitors[i].getName().equalsIgnoreCase(name))
329                                    return requestMonitors[i];
330                    }
331                    throw new ApplicationException("there is no request monitor registered with name ["+name+"]");
332            }
333    
334            protected void setRequestMonitors(RequestMonitor[] monitors) {
335                    this.requestMonitors=monitors;;
336            }
337            public IntervallMonitor[] getIntervallMonitors() {
338                    return intervallMonitors;
339            }
340            public IntervallMonitor getIntervallMonitor(String name) throws ApplicationException {
341                    for(int i=0;i<intervallMonitors.length;i++){
342                            if(intervallMonitors[i].getName().equalsIgnoreCase(name))
343                                    return intervallMonitors[i];
344                    }
345                    throw new ApplicationException("there is no intervall monitor registered with name ["+name+"]");
346            }
347    
348            protected void setIntervallMonitors(IntervallMonitor[] monitors) {
349                    this.intervallMonitors=monitors;;
350            }
351            public boolean isMonitoringEnabled() {
352                    return monitoringEnabled;
353            }
354    
355            protected void setMonitoringEnabled(boolean monitoringEnabled) {
356                    this.monitoringEnabled=monitoringEnabled;;
357            }
358    
359    
360            protected void setLoginDelay(int delay) {
361                    this.delay=delay;
362            }
363    
364            protected void setLoginCaptcha(boolean captcha) {
365                    this.captcha=captcha;
366            }
367    
368            @Override
369            public int getLoginDelay() {
370                    return delay;
371            }
372    
373            @Override
374            public boolean getLoginCaptcha() {
375                    return captcha;
376            }
377    
378            @Override
379            public Resource getConfigServerDir() {
380                    return getConfigDir();
381            }
382    
383            public static Cluster createClusterScope(Config config) throws PageException {
384                    ConfigServer cs=config instanceof ConfigWebImpl?((ConfigWebImpl)config).getConfigServerImpl():(ConfigServer)config;
385                    Cluster cluster=null;
386                    
387            try {
388                    if(Reflector.isInstaneOf(cs.getClusterClass(), Cluster.class)){
389                            cluster=(Cluster) ClassUtil.loadInstance(
390                                                    cs.getClusterClass(),
391                                                    ArrayUtil.OBJECT_EMPTY
392                                                    );
393                            cluster.init(cs);
394                    }
395                    else if(Reflector.isInstaneOf(cs.getClusterClass(), ClusterRemote.class)){
396                            ClusterRemote cb=(ClusterRemote) ClassUtil.loadInstance(
397                                                    cs.getClusterClass(),
398                                                    ArrayUtil.OBJECT_EMPTY
399                                                    );
400                            
401                            cluster=new ClusterWrap(cs,cb);
402                            //cluster.init(cs);
403                    }
404                    } 
405            catch (Exception e) {
406                            throw Caster.toPageException(e);
407                    } 
408            return cluster;
409            }
410            
411            
412    
413            /**
414             * if free permspace gen is lower than 10000000 bytes, railo shrinks all classloaders 
415             * @param cs
416             */
417        public static void checkPermGenSpace(Config config, boolean check) {
418            ConfigServer cs=config instanceof ConfigWebImpl?((ConfigWebImpl)config).getConfigServerImpl():(ConfigServer)config;
419                    //print.e(Runtime.getRuntime().freeMemory());
420                    // Runtime.getRuntime().freeMemory()<200000 || 
421            // long pgs=SystemUtil.getFreePermGenSpaceSize();
422            int promille=SystemUtil.getFreePermGenSpacePromille();
423            
424            // Pen Gen Space info not available 
425            if(promille==-1) {//if(pgs==-1) {
426                    if(countLoadedPages(cs)>500)
427                            shrink(cs);
428            }
429            else if(!check || promille<50){//else if(!check || pgs<1024*1024){
430                            SystemOut.printDate(cs.getErrWriter(),"+Free Perm Gen Space is less than 1mb (free:"+((SystemUtil.getFreePermGenSpaceSize())/1024)+"kb), shrink all template classloaders");
431                            // first just call GC and check if it help
432                            System.gc();
433                            //if(SystemUtil.getFreePermGenSpaceSize()>1024*1024) 
434                            if(SystemUtil.getFreePermGenSpacePromille()>50) 
435                                    return;
436                            
437                            shrink(cs);
438                    }
439            }
440        
441        private static void shrink(ConfigServer cs) {
442            ConfigWeb[] webs = cs.getConfigWebs();
443                    int count=0;
444                    for(int i=0;i<webs.length;i++){
445                            count+=shrink((ConfigWebImpl) webs[i],false);
446                    }
447                    if(count==0) {
448                            for(int i=0;i<webs.length;i++){
449                                    shrink((ConfigWebImpl) webs[i],true);
450                            }
451                    }
452            }
453    
454            private static int shrink(ConfigWebImpl config, boolean force) {
455                    int count=0;
456                    count+=shrink(config.getMappings(),force);
457                    count+=shrink(config.getCustomTagMappings(),force);
458                    count+=shrink(config.getComponentMappings(),force);
459                    count+=shrink(config.getFunctionMapping(),force);
460                    count+=shrink(config.getServerFunctionMapping(),force);
461                    count+=shrink(config.getTagMapping(),force);
462                    count+=shrink(config.getServerTagMapping(),force);
463                    count+=shrink(((ConfigWebImpl)config).getServerTagMapping(),force);
464                    return count;
465            }
466    
467            private static int shrink(Mapping[] mappings, boolean force) {
468                    int count=0;
469                    for(int i=0;i<mappings.length;i++){
470                            count+=shrink(mappings[i],force);
471                    }
472                    return count;
473            }
474    
475            private static int shrink(Mapping mapping, boolean force) {
476                    try {
477                            PCLCollection pcl = ((MappingImpl)mapping).getPCLCollection();
478                            if(pcl!=null)return pcl.shrink(force);
479                    } 
480                    catch (Throwable t) {
481                            t.printStackTrace();
482                    }
483                    return 0;
484            }
485            
486             public static long countLoadedPages(ConfigServer cs) {
487                     long count=0;
488                     ConfigWeb[] webs = cs.getConfigWebs();
489                            for(int i=0;i<webs.length;i++){
490                    count+=_count((ConfigWebImpl) webs[i]);
491                    }       
492                    return count;
493             }
494             private static long _count(ConfigWebImpl config) {
495                     long count=0;
496                    count+=_count(config.getMappings());
497                    count+=_count(config.getCustomTagMappings());
498                    count+=_count(config.getComponentMappings());
499                    count+=_count(config.getFunctionMapping());
500                    count+=_count(config.getServerFunctionMapping());
501                    count+=_count(config.getTagMapping());
502                    count+=_count(config.getServerTagMapping());
503                    count+=_count(((ConfigWebImpl)config).getServerTagMapping());
504                    return count;
505            }
506    
507             private static long _count(Mapping[] mappings) {
508                     long count=0;
509                    for(int i=0;i<mappings.length;i++){
510                            count+=_count(mappings[i]);
511                    }
512                    return count;
513            }
514    
515            private static long _count(Mapping mapping) {
516                    PCLCollection pcl = ((MappingImpl)mapping).getPCLCollection();
517                    return pcl==null?0:pcl.count();
518            }
519    
520    }