NTPDate.java
/*
* GovWay - A customizable API Gateway
* https://govway.org
*
* Copyright (c) 2005-2024 Link.it srl (https://link.it).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 3, as published by
* the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
package org.openspcoop2.utils.date;
import java.net.InetAddress;
import java.sql.Timestamp;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import org.apache.commons.net.ntp.NTPUDPClient;
import org.apache.commons.net.ntp.TimeInfo;
import org.openspcoop2.utils.UtilsException;
/**
* Classe per la produzione di date utilizzando un server NTP
*
* @author Poli Andrea (apoli@link.it)
* @author $Author$
* @version $Rev$, $Date$
*/
public class NTPDate implements IDate {
private static InetAddress server = null;
private static NTPUDPClient udpClient = null;
private static int defaultTimeout = -1;
private static Map<String,Date> time = null;
private static boolean cacheEnabled = true;
private static int cacheRefresh = 100;
private static org.openspcoop2.utils.Semaphore semaphore = new org.openspcoop2.utils.Semaphore("NTPDate");
private static Date getDateCached() throws Exception{
if(NTPDate.cacheEnabled==false){
TimeInfo tInfo = NTPDate.udpClient.getTime(NTPDate.server);
return tInfo.getMessage().getReceiveTimeStamp().getDate();
}
else{
String key = (System.currentTimeMillis() / (NTPDate.cacheRefresh)) + ""; // al massimo vengono eseguite 10 richieste al secondo.
if(NTPDate.time.containsKey(key)){
//System.out.println("NOW ["+key+"] from cache");
return NTPDate.time.get(key);
}else{
//synchronized(NTPDate.time){
semaphore.acquire("getDateCached");
try {
if(NTPDate.time.containsKey(key)){
//System.out.println("NOW ["+key+"] from cache sync");
return NTPDate.time.get(key);
}else{
//System.out.println("NOW ["+key+"] no cache");
TimeInfo tInfo = NTPDate.udpClient.getTime(NTPDate.server);
Date d = tInfo.getMessage().getReceiveTimeStamp().getDate();
NTPDate.time.clear();
NTPDate.time.put(key, d);
return d;
}
}finally {
semaphore.release("getDateCached");
}
}
}
}
/**
* Impostazione delle proprieta' per il DateManager
*/
@Override
public void init(java.util.Properties properties) throws UtilsException{
_init(properties);
}
private static void _init(java.util.Properties properties) throws UtilsException{
if(NTPDate.udpClient==null) {
_initSync(properties);
}
}
private static synchronized void _initSync(java.util.Properties properties) throws UtilsException{
if(NTPDate.udpClient!=null) {
return;
}
try{
NTPDate.udpClient = new NTPUDPClient();
// timeout
String timeoutS = properties.getProperty("ntp.timeout");
if(timeoutS!=null){
try{
NTPDate.defaultTimeout = Integer.parseInt(timeoutS);
}catch(Exception e){
throw new Exception("org.openspcoop.pdd.date.property.ntp.timeout value non valido: "+e.getMessage(),e);
}
}
if(NTPDate.defaultTimeout!=-1)
NTPDate.udpClient.setDefaultTimeout(NTPDate.defaultTimeout);
// ipaddress
String ipaddressS = properties.getProperty("ntp.server");
if(ipaddressS==null)
throw new Exception("org.openspcoop.pdd.date.property.ntp.server value non definito");
if(ipaddressS!=null){
try{
NTPDate.server = InetAddress.getByName(ipaddressS);
}catch(Exception e){
throw new Exception("org.openspcoop.pdd.date.property.ntp.server value non valido: "+e.getMessage(),e);
}
}
// cache
String cacheS = properties.getProperty("ntp.cache.enable");
if(cacheS!=null){
try{
NTPDate.cacheEnabled = Boolean.parseBoolean(cacheS);
}catch(Exception e){
throw new Exception("org.openspcoop.pdd.date.property.ntp.cache.enable non valido: "+e.getMessage(),e);
}
}
// intervallo cache refresh
String cacheRefreshS = properties.getProperty("ntp.cache.refresh");
if(cacheRefreshS!=null){
try{
int value = Integer.parseInt(cacheRefreshS);
if(value>1000)
throw new Exception("Valore deve essere minore di 1000");
NTPDate.cacheRefresh = 1000 / value;
}catch(Exception e){
throw new Exception("org.openspcoop.pdd.date.property.ntp.cache.refresh non valido: "+e.getMessage(),e);
}
}
NTPDate.udpClient.open();
NTPDate.time = new ConcurrentHashMap<String,Date>();
}catch(Exception e){
NTPDate.udpClient=null;
throw new UtilsException("Inizializzazione NTP Client (properties) non riuscita: "+e.getMessage(),e);
}
}
/**
* Close il DataManager
*
* @throws UtilsException
*/
@Override
public void close() throws UtilsException{
try{
if(NTPDate.udpClient!=null)
NTPDate.udpClient.close();
}catch(Exception e){
throw new UtilsException("Chiusura NTP Client non riuscita: "+e.getMessage(),e);
}
}
/**
* Ritorna la data corrente.
*
* @return Data corrente
*/
@Override
public Date getDate() throws UtilsException{
try{
if(NTPDate.udpClient==null)
throw new Exception("Inizializzazione non effettuata, invocare metodo init");
//System.out.println("NTP getDate ("+NTPDate.getDateCached()+")");
return NTPDate.getDateCached();
}catch(Exception e){
throw new UtilsException("getDate error: "+e.getMessage(),e);
}
}
/**
* Ritorna la data corrente in millisecondi da Gennaio 1.4970.
*
* @return Data corrente
*/
@Override
public long getTimeMillis()throws UtilsException {
try{
if(NTPDate.udpClient==null)
throw new Exception("Inizializzazione non effettuata, invocare metodo init");
//System.out.println("NTP getTime ("+NTPDate.getDateCached().getTime()+")");
return NTPDate.getDateCached().getTime();
}catch(Exception e){
throw new UtilsException("getDate error: "+e.getMessage(),e);
}
}
/**
* Ritorna la data corrente come timestamp SQL.
*
* @return Data corrente
*/
@Override
public Timestamp getTimestamp() throws UtilsException{
try{
if(NTPDate.udpClient==null)
throw new Exception("Inizializzazione non effettuata, invocare metodo init");
//System.out.println("NTP getTimestamp ("+new Timestamp(NTPDate.getDateCached().getTime())+")");
return new Timestamp(NTPDate.getDateCached().getTime());
}catch(Exception e){
throw new UtilsException("getDate error: "+e.getMessage(),e);
}
}
/**
* Ritorna la data corrente come Calendar
*
* @return Data corrente
*/
@Override
public Calendar getCalendar() throws UtilsException{
Calendar c = new GregorianCalendar();
c.setTime(this.getDate());
return c;
}
}