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