001package com.killcoding.datasource; 002 003import java.util.Calendar; 004import java.util.TimeZone; 005import java.util.Date; 006import java.sql.Timestamp; 007import java.io.File; 008import com.killcoding.tool.CommonTools; 009import com.killcoding.tool.ConfigProperties; 010import java.io.InputStream; 011import java.io.IOException; 012import java.io.FileInputStream; 013import com.killcoding.datasource.DriverDataSource; 014import java.sql.Time; 015import com.killcoding.datasource.CacheDriverExecutor; 016import java.sql.Connection; 017import java.sql.SQLException; 018import com.killcoding.log.Logger; 019import com.killcoding.log.LoggerFactory; 020import java.util.Map; 021import java.time.LocalDate; 022import java.time.Instant; 023import java.time.ZoneId; 024import java.time.LocalDateTime; 025 026public final class Clock { 027 028 private Calendar calendar = null; 029 030 public static File APP_CLOCK = null; 031 private static boolean enable = false; 032 private static ConfigProperties configProperties = null; 033 private static DriverDataSource dataSource = null; 034 private static String dataSourcePath = null; 035 private Long gap = 0L; 036 037 private Logger log = LoggerFactory.getLogger(Clock.class); 038 039 public Clock() { 040 super(); 041 init(); 042 } 043 044 private synchronized void init() { 045 if (dataSource == null) { 046 try { 047 if (APP_CLOCK == null) { 048 APP_CLOCK = CommonTools.getSystemProperties(Clock.class, "APP_CLOCK", "Clock.properties"); 049 } 050 if (APP_CLOCK != null && APP_CLOCK.exists() && configProperties == null) { 051 configProperties = new ConfigProperties(); 052 Runnable updatedRun = new Runnable(){ 053 @Override 054 public void run(){ 055 try { 056 reload(); 057 Logger.systemMark(Clock.class, "Clock Reloaded"); 058 } catch (Exception e) { 059 log.error(e.getMessage(), e); 060 } 061 } 062 }; 063 configProperties.load(APP_CLOCK,updatedRun); 064 enable = configProperties.getBoolean("Enable", false); 065 if (enable) { 066 dataSourcePath = configProperties.getString("DataSource"); 067 if (!CommonTools.isBlank(dataSourcePath)) { 068 dataSource = new DriverDataSource(new File(dataSourcePath)); 069 } 070 } 071 } 072 } catch (Exception e) { 073 log.error(e.getMessage(), e); 074 } 075 } 076 } 077 078 private void reload() { 079 if (configProperties != null) { 080 enable = configProperties.getBoolean("Enable", false); 081 String reloadDataSourcePath = configProperties.getString("DataSource"); 082 083 boolean isReload = false; 084 if(!CommonTools.isBlank(reloadDataSourcePath)){ 085 isReload = !dataSourcePath.equals(reloadDataSourcePath); 086 } 087 if(dataSource != null && isReload){ 088 // May be referenced when expansion is needed 089 // dataSource.closeAll(); 090 dataSourcePath = reloadDataSourcePath; 091 } 092 // May be referenced when expansion is needed 093 // if(!enable && dataSource != null){ 094 // dataSource.closeAll(); 095 // } 096 if (enable && isReload) { 097 if (!CommonTools.isBlank(dataSourcePath)) { 098 dataSource = new DriverDataSource(new File(dataSourcePath)); 099 } 100 } 101 } 102 } 103 104 private Calendar getRemoteCalendar() { 105 if (enable && dataSource != null) { 106 Connection conn = null; 107 CacheDriverExecutor executor = null; 108 try { 109 String getAppClockSql = configProperties.getString("GetAppClockSql"); 110 111 if (CommonTools.isBlank(getAppClockSql)) 112 getAppClockSql = dataSource.getConfigProperties().getString("GetAppClockSql"); 113 114 if (CommonTools.isBlank(getAppClockSql)) 115 return null; 116 117 conn = dataSource.getConnection(); 118 119 if (conn == null) 120 return null; 121 122 executor = new CacheDriverExecutor(conn); 123 Map<String, Object> result = executor.first(getAppClockSql); 124 125 if (result == null) 126 return null; 127 128 Object appSystemDateObj = result.get("app_systime_date"); 129 Object appTimeZoneObj = result.get("app_time_zone"); 130 Long appSystemDateTime = null; 131 if (appSystemDateObj instanceof Timestamp) { 132 appSystemDateTime = ((Timestamp) appSystemDateObj).getTime(); 133 } 134 if (appSystemDateTime == null && appSystemDateObj instanceof java.sql.Date) { 135 appSystemDateTime = ((java.sql.Date) appSystemDateObj).getTime(); 136 } 137 if (appSystemDateTime == null && appSystemDateObj instanceof java.util.Date) { 138 appSystemDateTime = ((java.util.Date) appSystemDateObj).getTime(); 139 } 140 if (appSystemDateTime == null && appSystemDateObj instanceof Long) { 141 appSystemDateTime = (Long) appSystemDateObj; 142 } 143 if (appSystemDateTime == null) 144 return null; 145 146 gap = Calendar.getInstance().getTimeInMillis() - appSystemDateTime; 147 148 String timeZone = CommonTools.isBlank(appTimeZoneObj) 149 ? configProperties.getString("DefaultTimeZone", "GMT") : (String) appTimeZoneObj; 150 151 Calendar remoteCalendar = Calendar.getInstance(); 152 TimeZone calTimeZone = TimeZone.getTimeZone(timeZone); 153 remoteCalendar.setTimeZone(calTimeZone); 154 remoteCalendar.setTimeInMillis(appSystemDateTime); 155 return remoteCalendar; 156 } catch (Exception e) { 157 log.error(e.getMessage(), e); 158 return null; 159 } finally { 160 try { 161 if (executor != null) 162 executor.close(); 163 } catch (SQLException e) { 164 log.error(e.getMessage(), e); 165 } 166 } 167 } 168 return null; 169 } 170 171 public Calendar getCalendar() { 172 173 if (calendar != null) 174 return calendar; 175 176 calendar = getRemoteCalendar(); 177 if (calendar == null && !enable) { 178 calendar = Calendar.getInstance(); 179 } 180 if(calendar == null && enable){ 181 calendar = getDefaultCalendear(); 182 } 183 return calendar; 184 } 185 186 private Calendar getDefaultCalendear(){ 187 String timeZone = configProperties.getString("DefaultTimeZone", "GMT"); 188 long msGap = Calendar.getInstance().getTimeInMillis() + gap; 189 Calendar defaultCalendar = Calendar.getInstance(); 190 TimeZone calTimeZone = TimeZone.getTimeZone(timeZone); 191 defaultCalendar.setTimeZone(calTimeZone); 192 defaultCalendar.setTimeInMillis(msGap); 193 return defaultCalendar; 194 } 195 196 public java.util.Date getDate() { 197 return new java.util.Date(getCalendar().getTimeInMillis()); 198 } 199 200 public long getTime() { 201 return getCalendar().getTimeInMillis(); 202 } 203 204 public java.sql.Date getSqlDate() { 205 return new java.sql.Date(getTime()); 206 } 207 208 public java.sql.Time getSqlTime() { 209 return new java.sql.Time(getTime()); 210 } 211 212 public Timestamp getSqlTimestamp() { 213 return new Timestamp(getTime()); 214 } 215 216 public LocalDate getLocalDate() { 217 ZoneId zoneId = getCalendar().getTimeZone().toZoneId(); 218 return Instant.ofEpochMilli(getTime()).atZone(zoneId).toLocalDate(); 219 } 220 221 public LocalDateTime getLocalDateTime() { 222 ZoneId zoneId = getCalendar().getTimeZone().toZoneId(); 223 return LocalDateTime.ofInstant(Instant.ofEpochMilli(getTime()), zoneId); 224 } 225 226 public static DriverDataSource getDataSource(){ 227 return dataSource; 228 } 229 230 public static ConfigProperties getConfigProperties(){ 231 return configProperties; 232 } 233 234}