/** * OLAT - Online Learning and Training<br> * http://www.olat.org * <p> * Licensed under the Apache License, Version 2.0 (the "License"); <br> * you may not use this file except in compliance with the License.<br> * You may obtain a copy of the License at * <p> * http://www.apache.org/licenses/LICENSE-2.0 * <p> * Unless required by applicable law or agreed to in writing,<br> * software distributed under the License is distributed on an "AS IS" BASIS, <br> * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br> * See the License for the specific language governing permissions and <br> * limitations under the License. * <p> * Copyright (c) since 2004 at Multimedia- & E-Learning Services (MELS),<br> * University of Zurich, Switzerland. * <hr> * <a href="http://www.openolat.org"> * OpenOLAT - Online Learning and Training</a><br> * This file has been modified by the OpenOLAT community. Changes are licensed * under the Apache 2.0 license as the original file. * <p> */ package org.olat.commons.calendar.manager; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.net.URL; import java.nio.file.Files; import java.util.ArrayList; import java.util.Collections; import java.util.Date; import java.util.List; import java.util.UUID; import java.util.regex.Pattern; import org.olat.commons.calendar.CalendarManager; import org.olat.commons.calendar.CalendarModule; import org.olat.commons.calendar.model.CalendarFileInfos; import org.olat.commons.calendar.model.CalendarUserConfiguration; import org.olat.commons.calendar.model.ImportedCalendar; import org.olat.commons.calendar.model.Kalendar; import org.olat.commons.calendar.model.KalendarComparator; import org.olat.commons.calendar.ui.components.KalendarRenderWrapper; import org.olat.core.commons.persistence.DB; import org.olat.core.id.Identity; import org.olat.core.logging.OLog; import org.olat.core.logging.Tracing; import org.olat.core.util.WebappHelper; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import net.fortuna.ical4j.model.Calendar; /** * Description:<BR> * Constants and helper methods for the OLAT iCal feeds * * <P> * Initial Date: July 22, 2008 * * @author Udit Sajjanhar */ @Service public class ImportCalendarManager { private static final OLog log = Tracing.createLoggerFor(ImportCalendarManager.class); private static final int RELOAD_INTERVAL = 3600000; @Autowired private DB dbInstance; @Autowired private CalendarModule calendarModule; @Autowired private CalendarManager calendarManager; @Autowired private ImportedCalendarDAO importedCalendarDao; public KalendarRenderWrapper importCalendar(Identity identity, String calendarName, String type, String url) throws IOException { File tmpFile = new File(WebappHelper.getTmpDir(), UUID.randomUUID() + ".ics"); try(InputStream in = new URL(url).openStream()) { Files.copy(in, tmpFile.toPath()); } catch(IOException e) { throw e; } KalendarRenderWrapper calendarWrapper = null; Calendar calendar = calendarManager.readCalendar(tmpFile); if(calendar != null) { String calendarID = getImportedCalendarID(identity, calendarName); File calendarFile = calendarManager.getCalendarFile(type, calendarID); if(!tmpFile.renameTo(calendarFile)) { Files.copy(tmpFile.toPath(), calendarFile.toPath()); } importedCalendarDao.createImportedCalendar(identity, calendarName, calendarID, type, url, new Date()); calendarWrapper = calendarManager.getImportedCalendar(identity, calendarID); calendarWrapper.setDisplayName(calendarName); calendarWrapper.setPrivateEventsVisible(true); } return calendarWrapper; } public KalendarRenderWrapper importCalendar(Identity identity, String calendarName, String type, File file) throws IOException { KalendarRenderWrapper calendarWrapper = null; Calendar calendar = calendarManager.readCalendar(file); if(calendar != null) { String calendarID = getImportedCalendarID(identity, calendarName); File calendarFile = calendarManager.getCalendarFile(type, calendarID); if(!file.renameTo(calendarFile)) { Files.copy(file.toPath(), calendarFile.toPath()); } importedCalendarDao.createImportedCalendar(identity, calendarName, calendarID, type, null, new Date()); calendarWrapper = calendarManager.getImportedCalendar(identity, calendarID); calendarWrapper.setDisplayName(calendarName); calendarWrapper.setPrivateEventsVisible(true); } return calendarWrapper; } /** * Delete an imported calendar * 1. remove the entry from the database * 2. delete the calendar file * @param calendarID * @param ureq * @return */ public void deleteCalendar(Identity identity, Kalendar calendar) { importedCalendarDao.deleteImportedCalendar(identity, calendar.getCalendarID(), calendar.getType()); calendarManager.deleteCalendar(calendar.getType(), calendar.getCalendarID()); } /** * Get imported calendars for a user. * @param ureq * @return */ public List<KalendarRenderWrapper> getImportedCalendarsForIdentity(Identity identity, boolean reload) { // initialize the calendars list List<KalendarRenderWrapper> calendars = new ArrayList<KalendarRenderWrapper>(); if(calendarModule.isEnabled() && calendarModule.isEnablePersonalCalendar()) { long timestamp = System.currentTimeMillis(); List<ImportedCalendar> importedCalendars = importedCalendarDao.getImportedCalendars(identity); for (ImportedCalendar importedCalendar: importedCalendars) { if(reload) { reloadImportCalendar(importedCalendar, timestamp); } String calendarId = importedCalendar.getCalendarId(); KalendarRenderWrapper calendarWrapper = calendarManager.getImportedCalendar(identity, calendarId); calendarWrapper.setDisplayName(importedCalendar.getDisplayName()); calendarWrapper.setAccess(KalendarRenderWrapper.ACCESS_READ_ONLY); calendarWrapper.setImported(true); CalendarUserConfiguration config = calendarManager.findCalendarConfigForIdentity(calendarWrapper.getKalendar(), identity); if (config != null) { calendarWrapper.setConfiguration(config); } calendars.add(calendarWrapper); } Collections.sort(calendars, KalendarComparator.getInstance()); } return calendars; } public List<CalendarFileInfos> getImportedCalendarInfosForIdentity(Identity identity, boolean reload) { List<CalendarFileInfos> calendars = new ArrayList<CalendarFileInfos>(); if(calendarModule.isEnabled() && calendarModule.isEnablePersonalCalendar()) { long timestamp = System.currentTimeMillis(); List<ImportedCalendar> importedCalendars = importedCalendarDao.getImportedCalendars(identity); for (ImportedCalendar importedCalendar: importedCalendars) { if(reload) { reloadImportCalendar(importedCalendar, timestamp); } String calendarId = importedCalendar.getCalendarId(); File calendarFile = calendarManager.getCalendarFile(CalendarManager.TYPE_USER, calendarId); CalendarFileInfos calendarInfos = new CalendarFileInfos(calendarId, CalendarManager.TYPE_USER, calendarFile); calendars.add(calendarInfos); } } return calendars; } private void reloadImportCalendar(ImportedCalendar importedCalendar, long timestamp) { String url = importedCalendar.getUrl(); Date lastUpdate = importedCalendar.getLastUpdate(); if (url != null && (timestamp - lastUpdate.getTime() > RELOAD_INTERVAL)) { log.info("Calendar reload started from url=" + url); importedCalendar.setLastUpdate(new Date()); importedCalendar = importedCalendarDao.update(importedCalendar); dbInstance.commit(); String calendarId = importedCalendar.getCalendarId(); reloadCalendarFromUrl(url, CalendarManager.TYPE_USER, calendarId); log.info("Calendar reloaded from url=" + url); } } /** * Reload calendar from url and store calendar file locally. * @param importUrl * @param calType * @param calId */ private void reloadCalendarFromUrl(String importUrl, String calType, String calId) { try (InputStream in = new URL(importUrl).openStream()){ Kalendar kalendar = calendarManager.buildKalendarFrom(in, calType, calId); calendarManager.persistCalendar(kalendar); } catch (Exception e) { log.error("Could not reload calendar from url=" + importUrl, e); } } /** * Get ID of a imported calendar * @param identity * @param calendarName * @return */ public static String getImportedCalendarID(Identity identity, String calendarName) { return identity.getName() + "_" + sanitize(calendarName); } private static String sanitize(String name) { // delete the preceding and trailing whitespaces name = name.trim(); // replace every other character other than alphabets and numbers by underscore Pattern specialChars = Pattern.compile("([^a-zA-z0-9])"); return specialChars.matcher(name).replaceAll("_").toLowerCase(); } }