docs: public void run() {
  		//register the current application for this thread
  		// in case a subsystem logs to the environment
  //		Environment.setCurrentApplication(application);
  		currentState = SCHEDULER_WAIT;
  
  		long currentTime = System.currentTimeMillis();
  		//long officialTime = TimeSupport.roundToMinute(currentTime);// + totalOffsetInMillis;
  
  		while (currentState == SCHEDULER_WAIT) {
  			try {
  				long interval2 = SchedulingSupport.getTimeTillIntervalStart(System.currentTimeMillis(), interval);
  				//prevent having two runs in one heartbeat
  				if (interval2 < TimeSupport.SECOND_IN_MS) {
  					interval2 += interval * TimeSupport.MINUTE_IN_MS;
  				}
  				Thread.sleep(interval2);
  			} catch (InterruptedException ie) {
  				System.out.println(new LogEntry(Level.CRITICAL, ("scheduler interrupted...")));
  				currentState = SCHEDULER_HALT;
  			}
  			if (currentState == SCHEDULER_WAIT) {
  				currentState = SCHEDULER_BUSY;
  				//do work (async in future)
  				currentTime = System.currentTimeMillis();
  				final long officialTime = TimeSupport.roundToMinute(currentTime);// + totalOffsetInMillis;
  
  				synchronized (pagedSystems) {
  					Iterator i = pagedSystems.iterator();
  					while (i.hasNext()) {
  						final Pageable pageable = (Pageable) i.next();
  						//check if intervals within limits
  						if (pageable.getPageIntervalInMinutes() <= 0) {
  							//log("scheduler can not page " + StringSupport.trim(pageable.toString() + "'", 50, "...") + ": interval in minutes (" + pageable.getPageIntervalInMinutes() + ") is not valid");
  						} else if (SchedulingSupport.isWithinMinuteOfIntervalStart(officialTime, pageable.getPageIntervalInMinutes(), pageable.getPageOffsetInMinutes()) && pageable.isStarted()) {
  							System.out.println(new LogEntry("scheduler about to page " + StringSupport.trim(pageable.toString() + "'", 80, "...")));
  							//the page method is invoked by a system session
  							//  so a developer may try to use it to outflank the security system
  							//another risk is that the invoked method consumes too much time
  
  							if(runAsync) {
  								new Executable() {
  									public Object execute() {
  										try {
  											pageable.onPageEvent(officialTime);
  										} catch (Exception e) {//pageable is not a trusted component
  											//TODO keep history
  											System.out.println(new LogEntry(Level.CRITICAL, "exception while paging pageable '" + StringSupport.trim(pageable.toString() + "'", 80, "..."), e));
  										}
  										return null;
  									}
  								}.executeAsync();
  							} else {
  								try {
  									pageable.onPageEvent(officialTime);
  								} catch (UndeclaredThrowableException e) {
  									System.out.println(new LogEntry(Level.CRITICAL, "undeclared exception while paging pageable '" + StringSupport.trim(pageable.toString() + "'", 80, "..."), e.getCause()));
  								} catch (Exception e) {//pageable is not a trusted component
  									System.out.println(new LogEntry(Level.CRITICAL, "exception while paging pageable '" + StringSupport.trim(pageable.toString() + "'", 80, "..."), e));
  								}
  							}
  						}
  					}
  					lastCall = officialTime;
  				}
  				currentState = SCHEDULER_WAIT;
  			}
  		}
  		currentState = SCHEDULER_HALT;
  	}