001/*
002 *  Copyright 2017 Anyware Services
003 *
004 *  Licensed under the Apache License, Version 2.0 (the "License");
005 *  you may not use this file except in compliance with the License.
006 *  You may obtain a copy of the License at
007 *
008 *      http://www.apache.org/licenses/LICENSE-2.0
009 *
010 *  Unless required by applicable law or agreed to in writing, software
011 *  distributed under the License is distributed on an "AS IS" BASIS,
012 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 *  See the License for the specific language governing permissions and
014 *  limitations under the License.
015 */
016package org.ametys.plugins.bluemind;
017
018import java.util.ArrayList;
019import java.util.Collections;
020import java.util.Date;
021import java.util.HashMap;
022import java.util.List;
023import java.util.Map;
024
025import org.apache.avalon.framework.service.ServiceException;
026import org.apache.avalon.framework.service.ServiceManager;
027import org.joda.time.DateTime;
028
029import org.ametys.core.user.CurrentUserProvider;
030import org.ametys.core.user.UserIdentity;
031import org.ametys.core.util.DateUtils;
032import org.ametys.plugins.messagingconnector.AbstractMessagingConnector;
033import org.ametys.plugins.messagingconnector.CalendarEvent;
034import org.ametys.plugins.messagingconnector.EmailMessage;
035import org.ametys.plugins.messagingconnector.MessagingConnectorException;
036import org.ametys.runtime.config.Config;
037
038import net.bluemind.authentication.api.IAuthentication;
039import net.bluemind.authentication.api.LoginResponse;
040import net.bluemind.calendar.api.CalendarContainerType;
041import net.bluemind.calendar.api.ICalendar;
042import net.bluemind.calendar.api.VEvent;
043import net.bluemind.core.api.date.BmDateTime;
044import net.bluemind.core.api.date.BmDateTimeWrapper;
045import net.bluemind.core.api.fault.ServerFault;
046import net.bluemind.core.container.model.ItemValue;
047import net.bluemind.core.rest.http.ClientSideServiceProvider;
048import net.bluemind.mailbox.api.IMailboxes;
049import net.bluemind.user.api.IUser;
050
051/**
052 * 
053 * The connector used by the messaging connector plugin when the bluemind mail server is used.
054 * Implements the methods of the MessagingConnector interface in order to get the  informations from the mail server
055 *
056 */
057public class BluemindConnector extends AbstractMessagingConnector
058{
059    /** The current user provider */
060    protected CurrentUserProvider _currentUserProvider;
061
062    /**
063     * The bluemind server core URL (for instance
064     * http://bluemind.myserver.com/services)
065     */
066    protected String _bmCoreUrl;
067
068    /** The administrator login. */
069    protected String _adminLogin;
070
071    /** An API key generated by the above administrator account. */
072    protected String _apiKey;
073    
074    /** The BlueMind domain (for instance myserver.com) */
075    protected String _domain;
076
077    /** The serviceProvider to establish the connection*/
078    protected ClientSideServiceProvider _serviceProvider;
079
080    @Override
081    public void service(ServiceManager manager) throws ServiceException
082    {
083        super.service(manager);
084        _currentUserProvider = (CurrentUserProvider) manager.lookup(CurrentUserProvider.ROLE);
085    }
086
087    @Override
088    public void initialize()
089    {
090        super.initialize();
091        _bmCoreUrl = Config.getInstance().getValueAsString("bluemind.server.url");
092        _adminLogin = Config.getInstance().getValueAsString("bluemind.admin.login");
093        _apiKey = Config.getInstance().getValueAsString("bluemind.api.key");
094        _domain = Config.getInstance().getValueAsString("bluemind.domain");
095
096        LoginResponse resp = ClientSideServiceProvider.getProvider(_bmCoreUrl, null).instance(IAuthentication.class).login(_adminLogin, _apiKey, BluemindConnector.class.getName());
097        _serviceProvider = ClientSideServiceProvider.getProvider(_bmCoreUrl, resp.authKey);
098    }
099    
100    private String _getUserAuthKey(UserIdentity userIdentity)
101    {
102        return _serviceProvider.instance(IAuthentication.class).su(userIdentity.getLogin() + "@" + _domain).authKey;
103    }
104    
105    private ClientSideServiceProvider _getServiceUserProvider(UserIdentity userIdentity)
106    {
107        String authKey = _getUserAuthKey(userIdentity);
108        return ClientSideServiceProvider.getProvider(_bmCoreUrl, authKey);
109    }
110    
111    /**
112     * Get the events information from the bluemind server.
113     * @param userIdentity the user identity.
114     * @param maxDays The maximum number of days from now to search the events
115     * @return the events information as a Map.
116     * @throws MessagingConnectorException if an error occurs.
117     */
118    protected Map<String, Object> getEventsInfo(UserIdentity userIdentity, int maxDays) throws MessagingConnectorException
119    {
120        ClientSideServiceProvider userProvider = null;
121        
122        try
123        {
124            userProvider = _getServiceUserProvider(userIdentity);
125            
126            if (userProvider == null)
127            {
128                throw new MessagingConnectorException("Bluemind authentification failed for user " + userIdentity);
129            }
130            
131            Map<String, Object> userInfo = new HashMap<>();
132            
133            Date now = new Date();
134
135            DateTime end = new DateTime().plusDays(maxDays);
136
137            IUser userClient = _serviceProvider.instance(IUser.class, _domain);
138            String userCalendar = CalendarContainerType.defaultUserCalendar(userClient.byEmail(userIdentity.getLogin() + "@" + _domain).uid);
139            List<VEvent> listEvents = new ArrayList<>();
140            ICalendar calendar = userProvider.instance(ICalendar.class, userCalendar);
141            List<String> listUid = calendar.all();
142            for (String uid : listUid)
143            {
144                ItemValue<VEvent> itemEvent = calendar.getComplete(uid);
145                VEvent event = new VEvent();
146                event = itemEvent.value;
147                BmDateTimeWrapper bmdTimeWrapper = new BmDateTimeWrapper(event.dtstart);
148                if (bmdTimeWrapper.toDate().getTime() >= now.getTime() && bmdTimeWrapper.toDate().getTime() <= end.getMillis())
149                {
150                    listEvents.add(event);
151                }
152            }
153
154            userInfo.put("events", listEvents);
155
156            return userInfo;
157        }
158        catch (ServerFault e)
159        {
160            throw new MessagingConnectorException("Failed to get Bluemind informations for user " + userIdentity, e);
161        }
162        finally
163        {
164            if (userProvider != null)
165            {
166                userProvider.instance(IAuthentication.class).logout();
167            }
168        }
169    }
170    
171    @SuppressWarnings("unchecked")
172    @Override
173    protected List<CalendarEvent> internalGetEvents(UserIdentity userIdentity, Date fromDate, Date untilDate, int maxEvents) throws MessagingConnectorException
174    {
175        List<CalendarEvent> calendar = new ArrayList<>();
176        
177        int maxDays = (int) DateUtils.asLocalDate(untilDate).toEpochDay() - (int) DateUtils.asLocalDate(fromDate).toEpochDay();
178        Map<String, Object> userInfo = getEventsInfo(userIdentity, maxDays);
179        List<VEvent> listEvents = (List<VEvent>) userInfo.get("events");
180        for (VEvent event : listEvents)
181        {
182            if (calendar.size() < maxEvents)
183            {
184                //Changing from BmDateTime to Date
185                BmDateTime begin = event.dtstart;
186                BmDateTime end = event.dtend;
187                Long dateBegin = BmDateTimeWrapper.toTimeZonedTimeStamp(begin.iso8601, begin.timezone);
188                Long dateEnd = BmDateTimeWrapper.toTimeZonedTimeStamp(end.iso8601, end.timezone);
189                
190                //Creating the event
191                CalendarEvent newEvent = new CalendarEvent();
192                newEvent.setEndDate(new Date(dateEnd));
193                newEvent.setStartDate(new Date(dateBegin));
194                if (event.summary != null)
195                {
196                    newEvent.setSubject(event.summary);
197                }
198                if (event.location != null)
199                {
200                    newEvent.setLocation(event.location);
201                }
202                calendar.add(newEvent);
203            }
204        }
205        return calendar;
206
207    }
208
209    @SuppressWarnings("unchecked")
210    @Override
211    protected int internalGetEventsCount(UserIdentity userIdentity, Date fromDate, Date untilDate) throws MessagingConnectorException
212    {
213        int maxDays = (int) DateUtils.asLocalDate(untilDate).toEpochDay() - (int) DateUtils.asLocalDate(fromDate).toEpochDay();
214        Map<String, Object> userInfo = getEventsInfo(userIdentity, maxDays);
215        return ((List<VEvent>) userInfo.get("events")).size();
216    }
217
218    @Override
219    protected List<EmailMessage> internalGetEmails(UserIdentity userIdentity, int maxEmails) throws MessagingConnectorException
220    {
221        // Not implement for bluemind
222        return Collections.EMPTY_LIST;
223    }
224
225    @Override
226    protected int internalGetEmailsCount(UserIdentity userIdentity) throws MessagingConnectorException
227    {
228        ClientSideServiceProvider userProvider = null;
229
230        try
231        {
232            userProvider = _getServiceUserProvider(userIdentity);
233            
234            if (userProvider == null)
235            {
236                throw new MessagingConnectorException("Bluemind authentification failed for user " + userIdentity);
237            }
238            
239            IMailboxes mailboxes = userProvider.instance(IMailboxes.class, _domain);
240            return mailboxes.getUnreadMessagesCount();
241        }
242        catch (ServerFault e)
243        {
244            throw new MessagingConnectorException("Fail to get email count for user " + userIdentity, e);
245        }
246        finally
247        {
248            if (userProvider != null)
249            {
250                userProvider.instance(IAuthentication.class).logout();
251            }
252        }
253    }
254}