/*
 * Copyright (c) 2008-2013, Hazelcast, Inc. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.hazelcast.util;

/**
 *  Utility class to be able to simulate different time zones.
 *  Time offset can be configured with following property
 *  "com.hazelcast.clock.offset"
 */
public final class Clock {
    private static final ClockImpl CLOCK;

    private Clock() {
    }

    public static long currentTimeMillis() {
        return CLOCK.currentTimeMillis();
    }

    static {
        final String clockOffset = System.getProperty("com.hazelcast.clock.offset");
        long offset = 0L;
        if (clockOffset != null) {
            try {
                offset = Long.parseLong(clockOffset);
            } catch (NumberFormatException ignored) {
                EmptyStatement.ignore(ignored);
            }
        }
        if (offset == 0L) {
            CLOCK = new SystemClock();
        } else {
            CLOCK = new SystemOffsetClock(offset);
        }
    }

    private abstract static class ClockImpl {

        protected abstract long currentTimeMillis();
    }

    private static final class SystemClock extends ClockImpl {

        @Override
        protected long currentTimeMillis() {
            return System.currentTimeMillis();
        }

        @Override
        public String toString() {
            return "SystemClock";
        }
    }

    private static final class SystemOffsetClock extends ClockImpl {

        private final long offset;

        private SystemOffsetClock(final long offset) {
            this.offset = offset;
        }

        @Override
        protected long currentTimeMillis() {
            return System.currentTimeMillis() + offset;
        }

        @Override
        public String toString() {
            final StringBuilder sb = new StringBuilder();
            sb.append("SystemOffsetClock");
            sb.append("{offset=").append(offset);
            sb.append('}');
            return sb.toString();
        }
    }


}

@@ -649,16 +649,59 @@
 .util;%0A%0A
+import com.hazelcast.nio.ClassLoaderUtil;%0A%0A
 /**%0A *  
@@ -881,16 +881,672 @@
 Clock %7B%0A
+%0A    /**%0A     * Clock offset property in milliseconds. When it's set to a non-zero value,%0A     * %7B@link Clock#currentTimeMillis()%7D will return a shifted %7B@link System#currentTimeMillis()%7D%0A     * time by given offset value.%0A     */%0A    public static final String HAZELCAST_CLOCK_OFFSET = %22com.hazelcast.clock.offset%22;%0A%0A    /**%0A     * Classname of a %7B@link com.hazelcast.util.Clock.ClockImpl%7D implementation.%0A     * When this property is set, %7B@link Clock#currentTimeMillis()%7D%0A     * will call %3Ccode%3EcurrentTimeMillis()%3C/code%3E method of given %3Ccode%3EClockImpl%3C/code%3E.%0A     */%0A    public static final String HAZELCAST_CLOCK_IMPL = %22com.hazelcast.clock.impl%22;%0A%0A
     priv
@@ -1699,24 +1699,25 @@
 s();%0A    %7D%0A%0A
+%0A
     static %7B
@@ -1729,82 +1729,474 @@
     
-final String clockOffset = System.getProperty(%22com.hazelcast.clock.offset%22
+CLOCK = initClock();%0A    %7D%0A%0A    private static ClockImpl initClock() %7B%0A        String clockImplClassName = System.getProperty(HAZELCAST_CLOCK_IMPL);%0A        if (clockImplClassName != null) %7B%0A            try %7B%0A                return ClassLoaderUtil.newInstance(null, clockImplClassName);%0A            %7D catch (Exception e) %7B%0A                throw ExceptionUtil.rethrow(e);%0A            %7D%0A        %7D%0A%0A        String clockOffset = System.getProperty(HAZELCAST_CLOCK_OFFSET
 );%0A 
@@ -2370,23 +2370,17 @@
 ception 
-ignored
+e
 ) %7B%0A    
@@ -2395,37 +2395,37 @@
     
-EmptyStatement.ignore(ignored
+throw ExceptionUtil.rethrow(e
 );%0A 
@@ -2466,17 +2466,17 @@
 (offset 
-=
+!
 = 0L) %7B%0A
@@ -2479,39 +2479,38 @@
 ) %7B%0A            
-CLOCK =
+return
  new SystemClock
@@ -2508,113 +2508,216 @@
 stem
-Clock();%0A        %7D else %7B
+OffsetClock(offset);%0A        %7D%0A%0A        return new SystemClock();
 %0A    
+%7D%0A%0A
     
-    CLOCK = new SystemOffsetClock(offset);%0A        %7D
+/**%0A     * Clock abstraction to be able to simulate different clocks%0A     * without changing actual system time.
 %0A    
-%7D%0A
+ */
 %0A    p
-rivate
+ublic
  abs

Make ClockImpl abstraction public to allow external Clock implementations to be used. Introduced new com.hazelcast.clock.impl system property.