Search in sources :

Example 1 with CalendarRuntime

use of org.openhab.io.caldav.internal.EventStorage.CalendarRuntime in project openhab1-addons by openhab.

the class CalDavLoaderImpl method updated.

@Override
public void updated(Dictionary<String, ?> config) throws ConfigurationException {
    if (config == null) {
        log.debug("Update was called with a null configuration for CalDAV IO.");
        return;
    }
    log.debug("Update was called for CalDAV IO.");
    CompatibilityHints.setHintEnabled(CompatibilityHints.KEY_RELAXED_PARSING, true);
    Map<String, CalDavConfig> configMap = new HashMap<String, CalDavConfig>();
    Enumeration<String> iter = config.keys();
    while (iter.hasMoreElements()) {
        String key = iter.nextElement();
        if (key.equals("service.pid")) {
            continue;
        }
        log.trace("processing configuration parameter: {}", key);
        if (key.equals(PROP_TIMEZONE)) {
            String newTimeZoneStr = Objects.toString(config.get(key), null);
            if (StringUtils.isBlank(newTimeZoneStr)) {
                log.info("The {} setting was configured with an empty value. Default value '{}' will be used instead.", PROP_TIMEZONE, defaultTimeZone);
                continue;
            }
            DateTimeZone newTimeZone = DateTimeZone.forID(newTimeZoneStr);
            if (newTimeZone == null) {
                log.warn("Invalid timezone value: {}", newTimeZoneStr);
                throw new ConfigurationException(PROP_TIMEZONE, "Invalid timezone value: " + newTimeZoneStr);
            }
            log.debug("Overriding default timezone {} with {}", defaultTimeZone, newTimeZone);
            defaultTimeZone = newTimeZone;
            continue;
        }
        String[] keys = key.split(":");
        if (keys.length != 2) {
            log.warn("Unable to parse configuration parameter: {}", key);
            throw new ConfigurationException("CalDAV IO", "Unable to parse configuration parameter: " + key);
        }
        String id = keys[0];
        String paramKey = keys[1];
        CalDavConfig calDavConfig = configMap.get(id);
        if (calDavConfig == null) {
            calDavConfig = new CalDavConfig();
            configMap.put(id, calDavConfig);
        }
        String value = Objects.toString(config.get(key), null);
        calDavConfig.setKey(id);
        if (paramKey.equals(PROP_USERNAME)) {
            calDavConfig.setUsername(value);
        } else if (paramKey.equals(PROP_PASSWORD)) {
            calDavConfig.setPassword(value);
        } else if (paramKey.equals(PROP_URL)) {
            calDavConfig.setUrl(value);
        } else if (paramKey.equals(PROP_RELOAD_INTERVAL)) {
            calDavConfig.setReloadMinutes(Integer.parseInt(value));
        } else if (paramKey.equals(PROP_PRELOAD_TIME)) {
            calDavConfig.setPreloadMinutes(Integer.parseInt(value));
        } else if (paramKey.equals(PROP_HISTORIC_LOAD_TIME)) {
            calDavConfig.setHistoricLoadMinutes(Integer.parseInt(value));
        } else if (paramKey.equals(PROP_LAST_MODIFIED_TIMESTAMP_VALID)) {
            calDavConfig.setLastModifiedFileTimeStampValid(BooleanUtils.toBoolean(value));
        } else if (paramKey.equals(PROP_DISABLE_CERTIFICATE_VERIFICATION)) {
            calDavConfig.setDisableCertificateVerification(BooleanUtils.toBoolean(value));
        } else if (paramKey.equals(PROP_CHARSET)) {
            try {
                Charset.forName(value);
                calDavConfig.setCharset(value);
            } catch (UnsupportedCharsetException e) {
                log.warn("Character set not valid: {}", value);
            }
        }
    }
    // verify if all required parameters are set
    for (String id : configMap.keySet()) {
        if (StringUtils.isEmpty(configMap.get(id).getUrl())) {
            log.warn("A URL must be configured for calendar '{}'", id);
            throw new ConfigurationException("CalDAV IO", "A URL must be configured for calendar '" + id + "'");
        }
        log.trace("config for calendar '{}': {}", id, configMap.get(id));
    }
    // initialize event cache
    for (CalDavConfig calDavConfig : configMap.values()) {
        final CalendarRuntime eventRuntime = new CalendarRuntime();
        eventRuntime.setConfig(calDavConfig);
        File cachePath = Util.getCachePath(calDavConfig.getKey());
        if (!cachePath.exists() && !cachePath.mkdirs()) {
            log.warn("cannot create directory ({}) for calendar caching (missing rights?)", cachePath.getAbsoluteFile());
            continue;
        }
        EventStorage.getInstance().getEventCache().put(calDavConfig.getKey(), eventRuntime);
    }
    log.info("CalDAV IO is properly configured.");
    setProperlyConfigured(true);
}
Also used : ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap) HashMap(java.util.HashMap) ConfigurationException(org.osgi.service.cm.ConfigurationException) UnsupportedCharsetException(java.nio.charset.UnsupportedCharsetException) CalendarRuntime(org.openhab.io.caldav.internal.EventStorage.CalendarRuntime) File(java.io.File) DateTimeZone(org.joda.time.DateTimeZone)

Example 2 with CalendarRuntime

use of org.openhab.io.caldav.internal.EventStorage.CalendarRuntime in project openhab1-addons by openhab.

the class CalDavLoaderImpl method addEvent.

@Override
public void addEvent(CalDavEvent calDavEvent) {
    final CalendarRuntime calendarRuntime = EventStorage.getInstance().getEventCache().get(calDavEvent.getCalendarId());
    CalDavConfig config = calendarRuntime.getConfig();
    if (config == null) {
        log.error("cannot find config for calendar id: {}", calDavEvent.getCalendarId());
    }
    Sardine sardine = Util.getConnection(config);
    Calendar calendar = Util.createCalendar(calDavEvent, defaultTimeZone);
    try {
        final String fullIcsFile = config.getUrl() + "/" + calDavEvent.getFilename() + ".ics";
        if (calendarRuntime.getEventContainerByFilename(calDavEvent.getFilename()) != null) {
            log.debug("event will be updated: {}", fullIcsFile);
            try {
                sardine.delete(fullIcsFile);
            } catch (IOException e) {
                log.error("cannot remove old ics file: {}", fullIcsFile);
            }
        } else {
            log.debug("event is new: {}", fullIcsFile);
        }
        sardine.put(fullIcsFile, calendar.toString().getBytes("UTF-8"));
        EventContainer eventContainer = new EventContainer(calDavEvent.getCalendarId());
        eventContainer.setEventId(calDavEvent.getId());
        eventContainer.setFilename(Util.getFilename(calDavEvent.getFilename()));
        eventContainer.getEventList().add(calDavEvent);
        eventContainer.setLastChanged(calDavEvent.getLastChanged());
        this.addEventToMap(eventContainer, false);
    } catch (UnsupportedEncodingException e) {
        log.error("cannot write event", e);
    } catch (IOException e) {
        log.error("cannot write event", e);
    }
}
Also used : Sardine(com.github.sardine.Sardine) EventContainer(org.openhab.io.caldav.internal.EventStorage.EventContainer) Calendar(net.fortuna.ical4j.model.Calendar) UnsupportedEncodingException(java.io.UnsupportedEncodingException) IOException(java.io.IOException) CalendarRuntime(org.openhab.io.caldav.internal.EventStorage.CalendarRuntime)

Example 3 with CalendarRuntime

use of org.openhab.io.caldav.internal.EventStorage.CalendarRuntime in project openhab1-addons by openhab.

the class CalDavLoaderImpl method addEventToMap.

public synchronized void addEventToMap(EventContainer eventContainer, boolean createTimer) {
    CalendarRuntime calendarRuntime = EventStorage.getInstance().getEventCache().get(eventContainer.getCalendarId());
    ConcurrentHashMap<String, EventContainer> eventContainerMap = calendarRuntime.getEventMap();
    if (eventContainerMap.containsKey(eventContainer.getEventId())) {
        EventContainer eventContainerOld = eventContainerMap.get(eventContainer.getEventId());
        // event is already in map
        if (eventContainer.getLastChanged().isAfter(eventContainerOld.getLastChanged())) {
            log.debug("event is already in event map and newer -> delete the old one, reschedule timer");
            // cancel old jobs
            for (String timerKey : eventContainerOld.getTimerMap()) {
                try {
                    this.scheduler.deleteJob(JobKey.jobKey(timerKey));
                } catch (SchedulerException e) {
                    log.error("cannot cancel event with job-id: " + timerKey, e);
                }
            }
            eventContainerOld.getTimerMap().clear();
            // override event
            eventContainerMap.put(eventContainer.getEventId(), eventContainer);
            for (EventNotifier notifier : eventListenerList) {
                for (CalDavEvent event : eventContainerOld.getEventList()) {
                    log.trace("notify listener... {}", notifier);
                    try {
                        notifier.eventRemoved(event);
                    } catch (Exception e) {
                        log.error("error while invoking listener", e);
                    }
                }
            }
            for (EventNotifier notifier : eventListenerList) {
                for (CalDavEvent event : eventContainer.getEventList()) {
                    log.trace("notify listener... {}", notifier);
                    try {
                        notifier.eventLoaded(event);
                    } catch (Exception e) {
                        log.error("error while invoking listener", e);
                    }
                }
            }
            if (createTimer) {
                int index = 0;
                for (CalDavEvent event : eventContainer.getEventList()) {
                    if (event.getEnd().isAfterNow()) {
                        try {
                            createJob(eventContainer, event, index);
                        } catch (SchedulerException e) {
                            log.error("cannot create jobs for event '{}': ", event.getShortName(), e.getMessage());
                        }
                    }
                    index++;
                }
            }
        } else {
            // event is already in map and not updated (eventContainerold and eventContainer have the same
            // "lastchanged" date) : we need to reschedule possible new events from recurrent events
            log.debug("event is already in map and not updated, we NEED to update eventlist and schedule new events jobs");
            ArrayList<CalDavEvent> eventsToAdd = new ArrayList<>();
            for (CalDavEvent event : eventContainer.getEventList()) {
                boolean eventAlreadyKnown = false;
                for (CalDavEvent oldevent : eventContainerOld.getEventList()) {
                    if (event.equals(oldevent)) {
                        eventAlreadyKnown = true;
                        log.trace("events match");
                    } else {
                        log.trace("eventsarenotequal : {} - {} - {} - {} - {}", event.getId(), event.getName(), event.getStart(), event.getEnd(), event.getLastChanged());
                        log.trace("eventsarenotequal : {} - {} - {} - {} - {}", oldevent.getId(), oldevent.getName(), oldevent.getStart(), oldevent.getEnd(), oldevent.getLastChanged());
                    }
                }
                if (!eventAlreadyKnown) {
                    eventsToAdd.add(event);
                }
            }
            // add only new events
            for (CalDavEvent event : eventsToAdd) {
                if (event.getEnd().isAfterNow()) {
                    eventContainerOld.getEventList().add(event);
                    for (EventNotifier notifier : eventListenerList) {
                        log.trace("notify listener... {}", notifier);
                        try {
                            notifier.eventLoaded(event);
                        } catch (Exception e) {
                            log.error("error while invoking listener", e);
                        }
                    }
                    if (createTimer) {
                        try {
                            log.trace("creating job for event {} ", event.getShortName());
                            createJob(eventContainerOld, event, eventContainerOld.getEventList().size() - 1);
                        // -1 because we already added the event to eventContainerOld
                        } catch (SchedulerException e) {
                            log.error("cannot create jobs for event '{}': ", event.getShortName(), e.getMessage());
                        }
                    }
                }
            }
            // update eventcontainer's calculateduntil
            eventContainerOld.setCalculatedUntil(eventContainer.getCalculatedUntil());
        }
    } else {
        // event is new
        eventContainerMap.put(eventContainer.getEventId(), eventContainer);
        log.trace("listeners for events: {}", eventListenerList.size());
        for (EventNotifier notifier : eventListenerList) {
            for (CalDavEvent event : eventContainer.getEventList()) {
                log.trace("notify listener... {}", notifier);
                try {
                    notifier.eventLoaded(event);
                } catch (Exception e) {
                    log.error("error while invoking listener", e);
                }
            }
        }
        if (createTimer) {
            int index = 0;
            for (CalDavEvent event : eventContainer.getEventList()) {
                if (event.getEnd().isAfterNow()) {
                    try {
                        createJob(eventContainer, event, index);
                    } catch (SchedulerException e) {
                        log.error("cannot create jobs for event: " + event.getShortName());
                    }
                }
                index++;
            }
        }
    }
}
Also used : SchedulerException(org.quartz.SchedulerException) EventContainer(org.openhab.io.caldav.internal.EventStorage.EventContainer) CalDavEvent(org.openhab.io.caldav.CalDavEvent) EventNotifier(org.openhab.io.caldav.EventNotifier) ArrayList(java.util.ArrayList) CalendarRuntime(org.openhab.io.caldav.internal.EventStorage.CalendarRuntime) ConfigurationException(org.osgi.service.cm.ConfigurationException) UnsupportedCharsetException(java.nio.charset.UnsupportedCharsetException) UnsupportedEncodingException(java.io.UnsupportedEncodingException) SchedulerException(org.quartz.SchedulerException) IOException(java.io.IOException)

Example 4 with CalendarRuntime

use of org.openhab.io.caldav.internal.EventStorage.CalendarRuntime in project openhab1-addons by openhab.

the class EventReloaderJob method removeDeletedEvents.

private synchronized void removeDeletedEvents(String calendarKey, List<String> oldMap) {
    final CalendarRuntime eventRuntime = EventStorage.getInstance().getEventCache().get(calendarKey);
    for (String filename : oldMap) {
        EventContainer eventContainer = eventRuntime.getEventContainerByFilename(filename);
        if (eventContainer == null) {
            log.error("cannot find event container for filename: {}", filename);
            continue;
        }
        // cancel old jobs
        for (String jobId : eventContainer.getTimerMap()) {
            try {
                String group;
                if (jobId.startsWith(CalDavLoaderImpl.JOB_NAME_EVENT_START)) {
                    group = CalDavLoaderImpl.JOB_NAME_EVENT_START;
                } else if (jobId.startsWith(CalDavLoaderImpl.JOB_NAME_EVENT_END)) {
                    group = CalDavLoaderImpl.JOB_NAME_EVENT_END;
                } else {
                    throw new SchedulerException("unknown job id: " + jobId);
                }
                boolean deleteJob = CalDavLoaderImpl.instance.getScheduler().deleteJob(JobKey.jobKey(jobId, group));
                log.debug("old job ({}) deleted? {}", jobId, deleteJob);
            } catch (SchedulerException e) {
                log.error("cannot delete job '{}'", jobId);
            }
        }
        eventContainer.getTimerMap().clear();
        for (EventNotifier notifier : CalDavLoaderImpl.instance.getEventListenerList()) {
            for (CalDavEvent event : eventContainer.getEventList()) {
                try {
                    notifier.eventRemoved(event);
                } catch (Exception e) {
                    log.error("error while invoking listener", e);
                }
            }
        }
        ConcurrentHashMap<String, EventContainer> eventContainerMap = eventRuntime.getEventMap();
        if (eventContainer != null) {
            this.removeFromDisk(eventContainer);
            log.debug("remove deleted event: {}", eventContainer.getEventId());
            eventContainerMap.remove(eventContainer.getEventId());
        }
    }
}
Also used : SchedulerException(org.quartz.SchedulerException) EventContainer(org.openhab.io.caldav.internal.EventStorage.EventContainer) CalDavEvent(org.openhab.io.caldav.CalDavEvent) EventNotifier(org.openhab.io.caldav.EventNotifier) CalendarRuntime(org.openhab.io.caldav.internal.EventStorage.CalendarRuntime) ParserException(net.fortuna.ical4j.data.ParserException) JobExecutionException(org.quartz.JobExecutionException) SchedulerException(org.quartz.SchedulerException) IOException(java.io.IOException) SardineException(com.github.sardine.impl.SardineException)

Example 5 with CalendarRuntime

use of org.openhab.io.caldav.internal.EventStorage.CalendarRuntime in project openhab1-addons by openhab.

the class EventReloaderJob method execute.

@Override
public void execute(JobExecutionContext context) throws JobExecutionException {
    final String config = context.getJobDetail().getJobDataMap().getString(KEY_CONFIG);
    CalendarRuntime eventRuntime = EventStorage.getInstance().getEventCache().get(config);
    log.debug("running EventReloaderJob for config : {}", config);
    // reload cached events (if necessary)
    if (!cachedEventsLoaded.containsKey(config)) {
        try {
            log.debug("reload cached events for config: {}", eventRuntime.getConfig().getKey());
            for (File fileCalendarKeys : new File(CalDavLoaderImpl.CACHE_PATH).listFiles()) {
                if (!eventRuntime.getConfig().getKey().equals(Util.getFilename(fileCalendarKeys.getName()))) {
                    log.trace("not our config : {}", Util.getFilename(fileCalendarKeys.getName()));
                    continue;
                }
                log.trace("found our config : {}", Util.getFilename(fileCalendarKeys.getName()));
                final Collection<File> icsFiles = FileUtils.listFiles(fileCalendarKeys, new String[] { "ics" }, false);
                for (File icsFile : icsFiles) {
                    try {
                        FileInputStream fis = new FileInputStream(icsFile);
                        log.debug("loading events from file : {}", icsFile);
                        loadEvents(Util.getFilename(icsFile.getAbsolutePath()), new org.joda.time.DateTime(icsFile.lastModified()), fis, eventRuntime.getConfig(), new ArrayList<String>(), true);
                    } catch (IOException e) {
                        log.error("cannot load events for file: " + icsFile, e);
                    } catch (ParserException e) {
                        log.error("cannot load events for file: " + icsFile, e);
                    }
                }
                break;
            }
        } catch (Throwable e) {
            log.error("cannot load events", e);
        } finally {
            cachedEventsLoaded.put(config, true);
        }
    }
    try {
        log.debug("loading events for config: " + config);
        List<String> oldEventIds = new ArrayList<String>();
        for (EventContainer eventContainer : eventRuntime.getEventMap().values()) {
            oldEventIds.add(eventContainer.getFilename());
            log.debug("old eventcontainer -- id : {} -- filename : {} -- calcuntil : {} -- lastchanged : {} -- ishistoric : {}", eventContainer.getEventId(), eventContainer.getFilename(), eventContainer.getCalculatedUntil(), eventContainer.getLastChanged(), eventContainer.isHistoricEvent());
            if (log.isDebugEnabled()) {
                for (int i = 0; i < eventContainer.getEventList().size(); i++) {
                    CalDavEvent elem = eventContainer.getEventList().get(i);
                    log.debug("old eventlist contient l'evenement : {} -- deb : {} -- fin : {} -- lastchang {}", elem.getName(), elem.getStart(), elem.getEnd(), elem.getLastChanged());
                }
            }
        }
        loadEvents(eventRuntime, oldEventIds);
        // stop all events in oldMap
        removeDeletedEvents(config, oldEventIds);
        for (EventNotifier notifier : CalDavLoaderImpl.instance.getEventListenerList()) {
            try {
                notifier.calendarReloaded(config);
            } catch (Exception e) {
                log.error("error while invoking listener", e);
            }
        }
        // print All scheduled jobs :
        if (log.isDebugEnabled()) {
            log.debug("jobs scheduled : ");
            Scheduler scheduler = CalDavLoaderImpl.instance.getScheduler();
            for (String groupName : CalDavLoaderImpl.instance.getScheduler().getJobGroupNames()) {
                for (JobKey jobKey : scheduler.getJobKeys(GroupMatcher.jobGroupEquals(groupName))) {
                    String jobName = jobKey.getName();
                    String jobGroup = jobKey.getGroup();
                    // get job's trigger
                    List<Trigger> triggers = (List<Trigger>) scheduler.getTriggersOfJob(jobKey);
                    Date nextFireTime = triggers.get(0).getNextFireTime();
                    log.debug("[job] : {} - [groupName] : {} - {}", jobName, jobGroup, nextFireTime);
                }
            }
        }
    } catch (SardineException e) {
        log.error("error while loading calendar entries: {} ({} - {} )", e.getMessage(), e.getStatusCode(), e.getResponsePhrase(), e);
        throw new JobExecutionException("error while loading calendar entries", e, false);
    } catch (Exception e) {
        log.error("error while loading calendar entries: {}", e.getMessage(), e);
        throw new JobExecutionException("error while loading calendar entries", e, false);
    }
}
Also used : Scheduler(org.quartz.Scheduler) ArrayList(java.util.ArrayList) JobKey(org.quartz.JobKey) SardineException(com.github.sardine.impl.SardineException) Trigger(org.quartz.Trigger) JobExecutionException(org.quartz.JobExecutionException) EventNotifier(org.openhab.io.caldav.EventNotifier) PropertyList(net.fortuna.ical4j.model.PropertyList) List(java.util.List) ArrayList(java.util.ArrayList) ComponentList(net.fortuna.ical4j.model.ComponentList) PeriodList(net.fortuna.ical4j.model.PeriodList) ParserException(net.fortuna.ical4j.data.ParserException) EventContainer(org.openhab.io.caldav.internal.EventStorage.EventContainer) IOException(java.io.IOException) FileInputStream(java.io.FileInputStream) ParserException(net.fortuna.ical4j.data.ParserException) JobExecutionException(org.quartz.JobExecutionException) SchedulerException(org.quartz.SchedulerException) IOException(java.io.IOException) SardineException(com.github.sardine.impl.SardineException) Date(java.util.Date) CalDavEvent(org.openhab.io.caldav.CalDavEvent) CalendarRuntime(org.openhab.io.caldav.internal.EventStorage.CalendarRuntime) CalendarRuntime(org.openhab.io.caldav.internal.EventStorage.CalendarRuntime) File(java.io.File)

Aggregations

CalendarRuntime (org.openhab.io.caldav.internal.EventStorage.CalendarRuntime)9 EventContainer (org.openhab.io.caldav.internal.EventStorage.EventContainer)7 CalDavEvent (org.openhab.io.caldav.CalDavEvent)5 IOException (java.io.IOException)4 EventNotifier (org.openhab.io.caldav.EventNotifier)4 SchedulerException (org.quartz.SchedulerException)4 SardineException (com.github.sardine.impl.SardineException)3 File (java.io.File)3 ArrayList (java.util.ArrayList)3 ParserException (net.fortuna.ical4j.data.ParserException)3 JobExecutionException (org.quartz.JobExecutionException)3 Sardine (com.github.sardine.Sardine)2 FileInputStream (java.io.FileInputStream)2 UnsupportedEncodingException (java.io.UnsupportedEncodingException)2 UnsupportedCharsetException (java.nio.charset.UnsupportedCharsetException)2 ConfigurationException (org.osgi.service.cm.ConfigurationException)2 DavResource (com.github.sardine.DavResource)1 InputStream (java.io.InputStream)1 URL (java.net.URL)1 Date (java.util.Date)1