001/*
002 * This library is part of OpenCms -
003 * the Open Source Content Management System
004 *
005 * Copyright (c) Alkacon Software GmbH & Co. KG (http://www.alkacon.com)
006 *
007 * This library is free software; you can redistribute it and/or
008 * modify it under the terms of the GNU Lesser General Public
009 * License as published by the Free Software Foundation; either
010 * version 2.1 of the License, or (at your option) any later version.
011 *
012 * This library is distributed in the hope that it will be useful,
013 * but WITHOUT ANY WARRANTY; without even the implied warranty of
014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
015 * Lesser General Public License for more details.
016 *
017 * For further information about Alkacon Software, please see the
018 * company website: http://www.alkacon.com
019 *
020 * For further information about OpenCms, please see the
021 * project website: http://www.opencms.org
022 *
023 * You should have received a copy of the GNU Lesser General Public
024 * License along with this library; if not, write to the Free Software
025 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
026 */
027
028package org.opencms.gwt.client;
029
030import org.opencms.gwt.client.ui.CmsNotification;
031import org.opencms.gwt.client.ui.CmsNotification.Type;
032import org.opencms.gwt.client.ui.css.I_CmsLayoutBundle;
033import org.opencms.gwt.shared.CmsBroadcastMessage;
034import org.opencms.util.CmsStringUtil;
035
036import java.util.List;
037
038import com.google.gwt.core.client.Scheduler;
039import com.google.gwt.core.client.Scheduler.RepeatingCommand;
040import com.google.gwt.user.client.rpc.AsyncCallback;
041import com.google.gwt.user.client.rpc.StatusCodeException;
042
043/**
044 * A timer which sends an RPC call regularly to keep the session alive and receive workplace broadcasts.<p>
045 *
046 * @since 9.5.0
047 */
048public class CmsBroadcastTimer {
049
050    /**
051     * The interval for the RPC calls.<p>
052     */
053    public static final int PING_INTERVAL = 1000 * 10;
054
055    /**
056     * The static instance.<p>
057     */
058    private static CmsBroadcastTimer INSTANCE;
059
060    /** Flag indicating if the timer should keep running. */
061    private static boolean m_keepRunning;
062
063    /**
064     * Aborts the timer.<p>
065     */
066    public static void abort() {
067
068        m_keepRunning = false;
069    }
070
071    /**
072     * Starts the timer.<p>
073     */
074    public static void start() {
075
076        if (!CmsCoreProvider.get().isKeepAlive()) {
077            return;
078        }
079
080        if (INSTANCE == null) {
081            m_keepRunning = true;
082            CmsBroadcastTimer timer = new CmsBroadcastTimer();
083            timer.getBroadcast();
084            timer.run();
085            INSTANCE = timer;
086        }
087    }
088
089    /**
090     * Returns if the timer should keep running.<p>
091     *
092     * @return <code>true</code>  if the ping timer should keep running
093     */
094    protected static boolean shouldKeepRunning() {
095
096        return m_keepRunning;
097    }
098
099    /**
100     * Generates the HTML for a single broadcast message.<p>
101     *
102     * @param message the message
103     *
104     * @return the HTML string
105     */
106    protected String createMessageHtml(CmsBroadcastMessage message) {
107
108        StringBuffer result = new StringBuffer();
109        result.append("<p class=\"").append(I_CmsLayoutBundle.INSTANCE.notificationCss().messageHead()).append("\">");
110        if (!CmsStringUtil.isEmptyOrWhitespaceOnly(message.getIcon())) {
111            result.append("<img src=\"").append(message.getIcon()).append("\">");
112        }
113        result.append("<em>" + message.getTime() + "</em><br/>");
114        result.append(Messages.get().key(Messages.GUI_BROADCAST_SEND_BY_1, message.getUser()));
115        String contentClass = I_CmsLayoutBundle.INSTANCE.notificationCss().messageText();
116        result.append("</p>").append("<div class='" + contentClass + "'>");
117        result.append(message.getMessage());
118
119        result.append("\n</div>");
120        return result.toString();
121    }
122
123    /**
124     * Installs the timer which fires the RPC calls.<p>
125     */
126    protected void run() {
127
128        Scheduler.get().scheduleFixedDelay(new RepeatingCommand() {
129
130            public boolean execute() {
131
132                if (CmsBroadcastTimer.shouldKeepRunning()) {
133                    getBroadcast();
134                    return true;
135                }
136                return false;
137            }
138        }, PING_INTERVAL);
139    }
140
141    /**
142     * Requests the latest broadcast.<p>
143     */
144    void getBroadcast() {
145
146        CmsCoreProvider.getService().getBroadcast(new AsyncCallback<List<CmsBroadcastMessage>>() {
147
148            public void onFailure(Throwable caught) {
149
150                // in case of a status code exception abort, indicates the session is no longer valid
151                if ((caught instanceof StatusCodeException) && (((StatusCodeException)caught).getStatusCode() == 500)) {
152                    CmsBroadcastTimer.abort();
153                }
154            }
155
156            public void onSuccess(List<CmsBroadcastMessage> result) {
157
158                if (result != null) {
159                    for (CmsBroadcastMessage message : result) {
160                        CmsNotification.get().sendAlert(Type.WARNING, createMessageHtml(message));
161                    }
162                }
163            }
164        });
165    }
166}