001 package railo.runtime.tag; 002 003 import java.net.URL; 004 005 import org.apache.commons.httpclient.Credentials; 006 import org.apache.commons.httpclient.UsernamePasswordCredentials; 007 008 import railo.commons.io.res.Resource; 009 import railo.commons.io.res.util.ResourceUtil; 010 import railo.commons.lang.StringUtil; 011 import railo.commons.net.HTTPUtil; 012 import railo.runtime.exp.ApplicationException; 013 import railo.runtime.exp.DatabaseException; 014 import railo.runtime.exp.PageException; 015 import railo.runtime.ext.tag.TagImpl; 016 import railo.runtime.op.Caster; 017 import railo.runtime.op.date.DateCaster; 018 import railo.runtime.schedule.ScheduleTask; 019 import railo.runtime.schedule.ScheduleTaskImpl; 020 import railo.runtime.schedule.Scheduler; 021 import railo.runtime.schedule.SchedulerImpl; 022 import railo.runtime.type.QueryImpl; 023 import railo.runtime.type.dt.Date; 024 import railo.runtime.type.dt.DateImpl; 025 import railo.runtime.type.dt.Time; 026 import railo.runtime.type.util.KeyConstants; 027 /** 028 * Provides a programmatic interface to the Railo scheduling engine. You can run a specified 029 * page at scheduled intervals with the option to write out static HTML pages. This lets you offer users 030 * access to pages that publish data, such as reports, without forcing users to wait while a database transaction 031 * is performed in order to populate the data on the page. 032 **/ 033 public final class Schedule extends TagImpl { 034 035 private static final short ACTION_RUN=1; 036 private static final short ACTION_UPDATE=2; 037 private static final short ACTION_DELETE=3; 038 private static final short ACTION_LIST=4; 039 private static final short ACTION_PAUSE=5; 040 private static final short ACTION_RESUME=6; 041 042 043 /** Password if URL is protected. */ 044 private String password=""; 045 046 /** Required when action ='update'. The date when scheduling of the task should start. */ 047 private Date startdate; 048 049 /** Specifies whether to resolve links in the result page to absolute references. */ 050 private boolean resolveurl; 051 052 /** */ 053 private short action; 054 055 /** Host name or IP address of a proxy server. */ 056 private String proxyserver; 057 058 /** The date when the scheduled task ends. */ 059 private Date enddate; 060 061 /** Required with publish ='Yes' A valid filename for the published file. */ 062 private String strFile; 063 064 /** Required when creating tasks with action = 'update'. Enter a value in seconds. The time when 065 ** scheduling of the task starts. */ 066 private Time starttime; 067 068 /** The port number on the proxy server from which the task is being requested. Default is 80. When 069 ** used with resolveURL, the URLs of retrieved documents that specify a port number are automatically 070 ** resolved to preserve links in the retrieved document. */ 071 private int proxyport=80; 072 073 /** The port number on the server from which the task is being scheduled. Default is 80. When used 074 ** with resolveURL, the URLs of retrieved documents that specify a port number are automatically resolved 075 ** to preserve links in the retrieved document. */ 076 private int port=-1; 077 078 /** The time when the scheduled task ends. Enter a value in seconds. */ 079 private Time endtime; 080 081 082 /** Required when creating tasks with action = 'update'. Interval at which task should be scheduled. 083 ** Can be set in seconds or as Once, Daily, Weekly, and Monthly. The default interval is one hour. The 084 ** minimum interval is one minute. */ 085 private String interval; 086 087 /** Specifies whether the result should be saved to a file. */ 088 private boolean publish; 089 090 /** Customizes the requestTimeOut for the task operation. Can be used to extend the default timeout 091 ** for operations that require more time to execute. */ 092 private long requesttimeout=-1; 093 094 /** Username if URL is protected. */ 095 private String username; 096 097 /** Required when action = 'update'. The URL to be executed. */ 098 private String url; 099 100 /** Required with publish ='Yes' The path location for the published file. */ 101 private String strPath; 102 103 /** The name of the task to delete, update, or run. */ 104 private String task; 105 private Scheduler scheduler; 106 107 private String proxyuser; 108 private String proxypassword=""; 109 110 private String returnvariable="cfschedule"; 111 private boolean hidden; 112 private boolean readonly; 113 private String serverPassword=null; 114 private boolean paused; 115 private boolean autoDelete; 116 117 public void setAutodelete(boolean autoDelete) { 118 this.autoDelete=autoDelete; 119 } 120 121 /** 122 * @param readonly the readonly to set 123 */ 124 public void setReadonly(boolean readonly) { 125 this.readonly = readonly; 126 } 127 128 /** 129 * @param hidden the hidden to set 130 */ 131 public void setHidden(boolean hidden) { 132 this.hidden = hidden; 133 } 134 135 /** 136 * @param returnvariable The returnvariable to set. 137 */ 138 public void setReturnvariable(String returnvariable) { 139 this.returnvariable = returnvariable; 140 } 141 142 /** 143 * @param proxypassword The proxypassword to set. 144 */ 145 public void setProxypassword(String proxypassword) { 146 this.proxypassword = proxypassword; 147 } 148 /** 149 * @param proxyuser The proxyuser to set. 150 */ 151 public void setProxyuser(String proxyuser) { 152 this.proxyuser = proxyuser; 153 } 154 155 public void setPaused(boolean paused) { 156 this.paused = paused; 157 } 158 159 /** set the value password 160 * Password if URL is protected. 161 * @param password value to set 162 **/ 163 public void setPassword(String password) { 164 this.password=password; 165 } 166 167 /** set the value startdate 168 * Required when action ='update'. The date when scheduling of the task should start. 169 * @param objStartDate value to set 170 * @throws PageException 171 **/ 172 public void setStartdate(Object objStartDate) throws PageException { 173 if(StringUtil.isEmpty(objStartDate)) return; 174 this.startdate=new DateImpl(DateCaster.toDateAdvanced(objStartDate,pageContext.getTimeZone())); 175 } 176 177 /** set the value resolveurl 178 * Specifies whether to resolve links in the result page to absolute references. 179 * @param resolveurl value to set 180 **/ 181 public void setResolveurl(boolean resolveurl) { 182 this.resolveurl=resolveurl; 183 } 184 185 public void setServerpassword(String serverPassword) { 186 this.serverPassword=serverPassword; 187 } 188 189 /** set the value action 190 * 191 * @param action value to set 192 * @throws ApplicationException 193 **/ 194 public void setAction(String action) throws ApplicationException { 195 if(StringUtil.isEmpty(action)) return; 196 action=action.toLowerCase().trim(); 197 if(action.equals("run"))this.action=ACTION_RUN; 198 else if(action.equals("delete"))this.action=ACTION_DELETE; 199 else if(action.equals("update"))this.action=ACTION_UPDATE; 200 else if(action.equals("list"))this.action=ACTION_LIST; 201 else if(action.equals("lists"))this.action=ACTION_LIST; 202 else if(action.equals("pause"))this.action=ACTION_PAUSE; 203 else if(action.equals("resume"))this.action=ACTION_RESUME; 204 else throw new ApplicationException("attribute action with value ["+action+"] of tag schedule is invalid","valid attributes are [delete,run,update,list,resume,pause]"); 205 } 206 207 /** set the value proxyserver 208 * Host name or IP address of a proxy server. 209 * @param proxyserver value to set 210 **/ 211 public void setProxyserver(String proxyserver) { 212 this.proxyserver=proxyserver; 213 } 214 215 /** set the value enddate 216 * The date when the scheduled task ends. 217 * @param enddate value to set 218 * @throws PageException 219 **/ 220 public void setEnddate(Object enddate) throws PageException { 221 if(StringUtil.isEmpty(enddate)) return; 222 this.enddate=new DateImpl(DateCaster.toDateAdvanced(enddate,pageContext.getTimeZone())); 223 } 224 225 /** set the value file 226 * Required with publish ='Yes' A valid filename for the published file. 227 * @param file value to set 228 **/ 229 public void setFile(String file) { 230 this.strFile=file; 231 } 232 233 /** set the value starttime 234 * Required when creating tasks with action = 'update'. Enter a value in seconds. The time when 235 * scheduling of the task starts. 236 * @param starttime value to set 237 * @throws PageException 238 **/ 239 public void setStarttime(Object starttime) throws PageException { 240 if(StringUtil.isEmpty(starttime)) return; 241 this.starttime=DateCaster.toTime(pageContext.getTimeZone(),starttime); 242 } 243 244 /** set the value proxyport 245 * The port number on the proxy server from which the task is being requested. Default is 80. When 246 * used with resolveURL, the URLs of retrieved documents that specify a port number are automatically 247 * resolved to preserve links in the retrieved document. 248 * @param proxyport value to set 249 * @throws PageException 250 **/ 251 public void setProxyport(Object oProxyport) throws PageException { 252 if(StringUtil.isEmpty(oProxyport)) return; 253 this.proxyport=Caster.toIntValue(oProxyport); 254 } 255 256 /** set the value port 257 * The port number on the server from which the task is being scheduled. Default is 80. When used 258 * with resolveURL, the URLs of retrieved documents that specify a port number are automatically resolved 259 * to preserve links in the retrieved document. 260 * @param port value to set 261 * @throws PageException 262 **/ 263 public void setPort(Object oPort) throws PageException { 264 if(StringUtil.isEmpty(oPort)) return; 265 this.port=Caster.toIntValue(oPort); 266 } 267 268 /** set the value endtime 269 * The time when the scheduled task ends. Enter a value in seconds. 270 * @param endtime value to set 271 * @throws PageException 272 **/ 273 public void setEndtime(Object endtime) throws PageException { 274 if(StringUtil.isEmpty(endtime)) return; 275 this.endtime=DateCaster.toTime(pageContext.getTimeZone(),endtime); 276 } 277 278 /** set the value operation 279 * The type of operation the scheduler performs when executing this task. 280 * @param operation value to set 281 * @throws ApplicationException 282 **/ 283 public void setOperation(String operation) throws ApplicationException { 284 if(StringUtil.isEmpty(operation)) return; 285 operation=operation.toLowerCase().trim(); 286 if(!operation.equals("httprequest")) 287 throw new ApplicationException("attribute operation must have the value [HTTPRequest]"); 288 } 289 290 /** set the value interval 291 * Required when creating tasks with action = 'update'. Interval at which task should be scheduled. 292 * Can be set in seconds or as Once, Daily, Weekly, and Monthly. The default interval is one hour. The 293 * minimum interval is one minute. 294 * @param interval value to set 295 **/ 296 public void setInterval(String interval) { 297 if(StringUtil.isEmpty(interval)) return; 298 interval=interval.trim().toLowerCase(); 299 if(interval.equals("week")) this.interval="weekly"; 300 else if(interval.equals("day")) this.interval="daily"; 301 else if(interval.equals("month")) this.interval="monthly"; 302 else if(interval.equals("year")) this.interval="yearly"; 303 this.interval=interval; 304 } 305 306 /** set the value publish 307 * Specifies whether the result should be saved to a file. 308 * @param publish value to set 309 **/ 310 public void setPublish(boolean publish) { 311 this.publish=publish; 312 } 313 314 /** set the value requesttimeout 315 * Customizes the requestTimeOut for the task operation. Can be used to extend the default timeout 316 * for operations that require more time to execute. 317 * @param requesttimeout value to set 318 **/ 319 public void setRequesttimeout(Object oRequesttimeout) throws PageException { 320 if(StringUtil.isEmpty(oRequesttimeout)) return; 321 this.requesttimeout=Caster.toLongValue(oRequesttimeout)*1000L; 322 } 323 324 /** set the value username 325 * Username if URL is protected. 326 * @param username value to set 327 **/ 328 public void setUsername(String username) { 329 this.username=username; 330 } 331 332 /** set the value url 333 * Required when action = 'update'. The URL to be executed. 334 * @param url value to set 335 **/ 336 public void setUrl(String url) { 337 this.url=url; 338 } 339 340 /** set the value path 341 * Required with publish ='Yes' The path location for the published file. 342 * @param path value to set 343 **/ 344 public void setPath(String path) { 345 this.strPath=path; 346 } 347 348 /** set the value task 349 * The name of the task to delete, update, or run. 350 * @param task value to set 351 **/ 352 public void setTask(String task) { 353 this.task=task; 354 } 355 356 357 /** 358 * @throws ApplicationException 359 * @see javax.servlet.jsp.tagext.Tag#doStartTag() 360 */ 361 public int doStartTag() throws PageException { 362 scheduler=pageContext.getConfig().getScheduler(); 363 364 if(action!=ACTION_LIST && task==null) { 365 throw new ApplicationException("attribute task is required for tag schedule when action is not list"); 366 } 367 368 369 switch(action) { 370 case ACTION_DELETE: doDelete(); break; 371 case ACTION_RUN: doRun(); break; 372 case ACTION_UPDATE: doUpdate(); break; 373 case ACTION_LIST: doList(); break; 374 case ACTION_PAUSE: doPause(true); break; 375 case ACTION_RESUME: doPause(false); break; 376 } 377 return SKIP_BODY; 378 } 379 380 /** 381 * @throws PageException 382 */ 383 private void doUpdate() throws PageException { 384 String message="missing attribute for tag schedule with action update"; 385 String detail="required attributes are [startDate, startTime, URL, interval, operation]"; 386 387 Resource file=null; 388 //if(publish) { 389 if(!StringUtil.isEmpty(strFile) && !StringUtil.isEmpty(strPath)) { 390 file=ResourceUtil.toResourceNotExisting(pageContext, strPath); 391 file=file.getRealResource(strFile); 392 } 393 else if(!StringUtil.isEmpty(strFile)) { 394 file=ResourceUtil.toResourceNotExisting(pageContext, strFile); 395 } 396 else if(!StringUtil.isEmpty(strPath)) { 397 file=ResourceUtil.toResourceNotExisting(pageContext, strPath); 398 } 399 if(file!=null)pageContext.getConfig().getSecurityManager().checkFileLocation(pageContext.getConfig(),file,serverPassword); 400 401 // missing attributes 402 if(startdate==null || starttime==null || url==null || interval==null) 403 throw new ApplicationException(message,detail); 404 405 // timeout 406 if(requesttimeout<0)requesttimeout=pageContext.getRequestTimeout(); 407 408 // username/password 409 Credentials cr=null; 410 if(username!=null) cr=new UsernamePasswordCredentials(username,password); 411 412 // Proxy 413 Credentials pcr=null; 414 if(proxyserver!=null) { 415 if(proxyuser!=null) pcr=new UsernamePasswordCredentials(proxyuser,proxypassword); 416 } 417 418 try { 419 420 ScheduleTask st=new ScheduleTaskImpl( 421 task, 422 file, 423 startdate, 424 starttime, 425 enddate, 426 endtime, 427 url, 428 port, 429 interval, 430 requesttimeout, 431 cr, 432 proxyserver, 433 proxyport, 434 pcr, 435 resolveurl, 436 publish, 437 hidden, 438 readonly, 439 paused, 440 autoDelete); 441 scheduler.addScheduleTask(st,true); 442 } catch (Exception e) { 443 throw Caster.toPageException(e); 444 } 445 446 447 448 449 450 // 451 } 452 453 /** 454 * @throws PageException 455 */ 456 private void doRun() throws PageException { 457 try { 458 scheduler.runScheduleTask(task,true); 459 } catch (Exception e) { 460 throw Caster.toPageException(e); 461 } 462 } 463 464 /** 465 * @throws PageException 466 */ 467 private void doDelete() throws PageException { 468 try { 469 scheduler.removeScheduleTask(task,false); 470 } catch (Exception e) { 471 throw Caster.toPageException(e); 472 } 473 } 474 475 /** 476 * @throws PageException 477 * 478 */ 479 private void doList() throws PageException { 480 //if(tr ue) throw new PageRuntimeException("qqq"); 481 ScheduleTask[] tasks = scheduler.getAllScheduleTasks(); 482 final String v="VARCHAR"; 483 String[] cols = new String[]{"task","path","file","startdate","starttime","enddate","endtime", 484 "url","port","interval","timeout","username","password","proxyserver", 485 "proxyport","proxyuser","proxypassword","resolveurl","publish","valid","paused","autoDelete"}; 486 String[] types = new String[]{v,v,v,"DATE","OTHER","DATE","OTHER", 487 v,v,v,v,v,v,v, 488 v,v,v,v,"BOOLEAN",v,"BOOLEAN","BOOLEAN"}; 489 railo.runtime.type.Query query=new QueryImpl(cols,types,tasks.length,"query" 490 ); 491 try { 492 for(int i=0;i<tasks.length;i++) { 493 int row=i+1; 494 ScheduleTask task=tasks[i]; 495 query.setAt(KeyConstants._task,row,task.getTask()); 496 if(task.getResource()!=null) { 497 query.setAt(KeyConstants._path,row,task.getResource().getParent()); 498 query.setAt(KeyConstants._file,row,task.getResource().getName()); 499 } 500 query.setAt("publish",row,Caster.toBoolean(task.isPublish())); 501 query.setAt("startdate",row,task.getStartDate()); 502 query.setAt("starttime",row,task.getStartTime()); 503 query.setAt("enddate",row,task.getEndDate()); 504 query.setAt("endtime",row,task.getEndTime()); 505 query.setAt(KeyConstants._url,row,printUrl(task.getUrl())); 506 query.setAt(KeyConstants._port,row,Caster.toString(HTTPUtil.getPort(task.getUrl()))); 507 query.setAt("interval",row,task.getStringInterval()); 508 query.setAt("timeout",row,Caster.toString(task.getTimeout()/1000)); 509 query.setAt("valid",row,Caster.toString(task.isValid())); 510 if(task.hasCredentials()) { 511 query.setAt("username",row,task.getUPCredentials().getUserName()); 512 query.setAt("password",row,task.getUPCredentials().getPassword()); 513 } 514 query.setAt("proxyserver",row,task.getProxyHost()); 515 if(task.getProxyPort()>0)query.setAt("proxyport",row,Caster.toString(task.getProxyPort())); 516 if(task.hasProxyCredentials()) { 517 query.setAt("proxyuser",row,task.getUPProxyCredentials().getUserName()); 518 query.setAt("proxypassword",row,task.getUPProxyCredentials().getPassword()); 519 } 520 query.setAt("resolveurl",row,Caster.toString(task.isResolveURL())); 521 522 query.setAt("paused",row,Caster.toBoolean(task.isPaused())); 523 query.setAt("autoDelete",row,Caster.toBoolean(((ScheduleTaskImpl)task).isAutoDelete())); 524 525 526 527 } 528 pageContext.setVariable(returnvariable,query); 529 } 530 catch (DatabaseException e) {} 531 532 533 } 534 535 private void doPause(boolean pause) throws PageException { 536 try { 537 ((SchedulerImpl)scheduler).pauseScheduleTask(task,pause,true); 538 } catch (Exception e) { 539 throw Caster.toPageException(e); 540 } 541 542 } 543 544 private String printUrl(URL url) { 545 546 String qs=url.getQuery(); 547 if(qs==null) qs=""; 548 else if(qs.length()>0)qs="?"+qs; 549 550 String str=url.getProtocol()+"://"+url.getHost()+url.getPath()+qs; 551 return str; 552 } 553 /** 554 * @see javax.servlet.jsp.tagext.Tag#doEndTag() 555 */ 556 public int doEndTag() { 557 return EVAL_PAGE; 558 } 559 560 /** 561 * @see javax.servlet.jsp.tagext.Tag#release() 562 */ 563 public void release() { 564 super.release(); 565 readonly=false; 566 strPath=null; 567 strFile=null; 568 starttime=null; 569 startdate=null; 570 endtime=null; 571 enddate=null; 572 url=null; 573 port=-1; 574 interval=null; 575 requesttimeout=-1; 576 username=null; 577 password=""; 578 proxyserver=null; 579 proxyport=80; 580 proxyuser=null; 581 proxypassword=""; 582 resolveurl=false; 583 publish=false; 584 returnvariable="cfschedule"; 585 task=null; 586 hidden=false; 587 serverPassword=null; 588 paused=false; 589 autoDelete=false; 590 } 591 592 }