/* * Copyright 2011 Future Systems * * 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 org.krakenapps.ntp.impl; import java.net.InetAddress; import java.net.UnknownHostException; import java.util.Date; import java.util.Map; import java.util.concurrent.CopyOnWriteArraySet; import org.apache.felix.ipojo.annotations.Component; import org.apache.felix.ipojo.annotations.Provides; import org.apache.felix.ipojo.annotations.Requires; import org.apache.felix.ipojo.annotations.ServiceProperty; import org.apache.felix.ipojo.annotations.Validate; import org.krakenapps.cron.CronService; import org.krakenapps.cron.Schedule; import org.krakenapps.ntp.NtpClient; import org.krakenapps.ntp.NtpSyncListener; import org.krakenapps.ntp.NtpSyncService; import org.osgi.service.prefs.BackingStoreException; import org.osgi.service.prefs.Preferences; import org.osgi.service.prefs.PreferencesService; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @Component(name = "ntp-sync-service") @Provides public class NtpSyncServiceImpl implements NtpSyncService { private Logger logger = LoggerFactory.getLogger(NtpSyncServiceImpl.class); @Requires private PreferencesService prefsvc; @Requires private CronService cronService; @ServiceProperty(name = "instance.name") private String instanceName; private NtpClient client; private String cronExp = "*/10 * * * *"; private CopyOnWriteArraySet<NtpSyncListener> listeners; public NtpSyncServiceImpl() { listeners = new CopyOnWriteArraySet<NtpSyncListener>(); } private void ensureClient() { if (client != null) return; try { Preferences p = getPreference(); String host = p.get("server", null); int timeout = p.getInt("timeout", 5000); this.client = new NtpClient(host, timeout); } catch (UnknownHostException e) { logger.error("kraken ntp: failed to create ntp client", e); } } @Override public NtpClient getNtpClient() { return client; } @Override public void setNtpClient(NtpClient client) { this.client = client; } @Override public InetAddress getTimeServer() { ensureClient(); return this.client.getTimeServer(); } @Override public void setTimeServer(InetAddress timeServer) { ensureClient(); this.client.setTimeServer(timeServer); Preferences p = getPreference(); p.put("server", timeServer.getHostName()); syncPreferences(p); } @Override public int getTimeout() { return this.client.getTimeout(); } @Override public void setTimeout(int timeout) { ensureClient(); this.client.setTimeout(timeout); Preferences p = getPreference(); p.putInt("timeout", timeout); syncPreferences(p); } private Preferences getPreference() { return prefsvc.getSystemPreferences().node("ntp"); } private void syncPreferences(Preferences p) { try { p.flush(); p.sync(); } catch (BackingStoreException e) { throw new IllegalStateException(e.getMessage()); } } @Override public String getSchedule() { return cronExp; } @Override public void setSchedule(String exp) { this.cronExp = exp; } @Override public void run() { try { if (client != null) { Date newTime = client.sync(); triggerListeners(newTime); } } catch (Throwable t) { logger.error("kraken ntp: cannot sync time", t); } } private void triggerListeners(Date newTime) { for (NtpSyncListener listener : listeners) { try { listener.onSetTime(newTime); } catch (Throwable t) { logger.warn("kraken ntp: ntp sync listener should not throw any exception", t); } } } @Override @Validate public void start() { Integer cronJobId = getCronJobId(); if (cronJobId == null) { try { Schedule schedule = new Schedule.Builder(instanceName).build(cronExp); cronService.registerSchedule(schedule); } catch (Exception e) { logger.error("kraken ntp: cron register failed"); } } } @Override public void stop() { Integer cronJobId = getCronJobId(); if (cronJobId != null) cronService.unregisterSchedule(cronJobId); } @Override public boolean isRunning() { return getCronJobId() != null; } @Override public void addListener(NtpSyncListener listener) { listeners.add(listener); } @Override public void removeListener(NtpSyncListener listener) { listeners.remove(listener); } private Integer getCronJobId() { Map<Integer, Schedule> schedules = cronService.getSchedules(); for (Integer id : schedules.keySet()) { Schedule schedule = schedules.get(id); if (schedule.getTaskName().equals(instanceName)) return id; } return null; } }