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.ui.apps.cacheadmin;
029
030import org.opencms.cache.CmsLruCache;
031import org.opencms.flex.CmsFlexCache;
032import org.opencms.loader.CmsImageLoader;
033import org.opencms.main.OpenCms;
034import org.opencms.monitor.CmsMemoryStatus;
035import org.opencms.ui.A_CmsUI;
036import org.opencms.ui.CmsVaadinUtils;
037import org.opencms.ui.FontOpenCms;
038import org.opencms.ui.apps.A_CmsWorkplaceApp;
039import org.opencms.ui.apps.CmsFileExplorer;
040import org.opencms.ui.apps.Messages;
041import org.opencms.ui.components.CmsInfoButton;
042import org.opencms.util.CmsFileUtil;
043import org.opencms.util.CmsStringUtil;
044
045import java.io.File;
046import java.util.LinkedHashMap;
047import java.util.List;
048import java.util.Map;
049
050import org.apache.commons.io.FileUtils;
051
052import com.vaadin.server.Sizeable.Unit;
053import com.vaadin.ui.Component;
054import com.vaadin.ui.HorizontalSplitPanel;
055import com.vaadin.ui.UI;
056import com.vaadin.ui.themes.ValoTheme;
057import com.vaadin.v7.event.FieldEvents.TextChangeEvent;
058import com.vaadin.v7.event.FieldEvents.TextChangeListener;
059import com.vaadin.v7.shared.ui.label.ContentMode;
060import com.vaadin.v7.ui.Label;
061import com.vaadin.v7.ui.ProgressBar;
062import com.vaadin.v7.ui.TextField;
063import com.vaadin.v7.ui.VerticalLayout;
064
065/**
066 * Class for the app which shows the content of caches.<p>
067 */
068public class CmsCacheViewApp extends A_CmsWorkplaceApp {
069
070    /**
071     * Modes to run this app.
072     */
073    public static enum Mode {
074        /**Shows FlexCache.*/
075        FlexCache,
076        /**Shows ImageCache.*/
077        ImageCache;
078    }
079
080    /**Mode.*/
081    private Mode m_mode;
082
083    /** The file table filter input. */
084    private TextField m_siteTableFilter;
085
086    /**
087     * public constructor.<p>
088     *
089     * @param mode of app
090     */
091    public CmsCacheViewApp(Mode mode) {
092
093        m_mode = mode;
094    }
095
096    /**
097     * Creates in info button for java cache statistics.<p>
098     *
099     * @return CmsInfoButton
100     */
101    public static CmsInfoButton getJavaStatisticButton() {
102
103        return getJavaStatisticButton(OpenCms.getMemoryMonitor().getMemoryStatus());
104
105    }
106
107    /**
108     * Creates in info button for java cache statistics.<p>
109     * @param memory memory object
110     *
111     * @return CmsInfoButton
112     */
113    public static CmsInfoButton getJavaStatisticButton(CmsMemoryStatus memory) {
114
115        Map<String, String> infoMap = new LinkedHashMap<String, String>();
116
117        infoMap.put(
118            CmsVaadinUtils.getMessageText(Messages.GUI_CACHE_JAVA_HEAP_MAX_0),
119            CmsFileUtil.formatFilesize(
120                memory.getMaxMemory() * 1048576,
121                A_CmsUI.getCmsObject().getRequestContext().getLocale()));
122        infoMap.put(
123            CmsVaadinUtils.getMessageText(Messages.GUI_CACHE_JAVA_HEAP_TOTAL_0),
124            CmsFileUtil.formatFilesize(
125                memory.getTotalMemory() * 1048576,
126                A_CmsUI.getCmsObject().getRequestContext().getLocale()));
127        infoMap.put(
128            CmsVaadinUtils.getMessageText(Messages.GUI_CACHE_JAVA_HEAP_USED_0),
129            CmsFileUtil.formatFilesize(
130                memory.getUsedMemory() * 1048576,
131                A_CmsUI.getCmsObject().getRequestContext().getLocale()));
132        infoMap.put(
133            CmsVaadinUtils.getMessageText(Messages.GUI_CACHE_JAVA_HEAP_FREE_0),
134            CmsFileUtil.formatFilesize(
135                memory.getFreeMemory() * 1048576,
136                A_CmsUI.getCmsObject().getRequestContext().getLocale()));
137
138        CmsInfoButton info = new CmsInfoButton(infoMap);
139        VerticalLayout prog = new VerticalLayout();
140        Label label = new Label();
141        label.setContentMode(ContentMode.HTML);
142        label.setValue(
143            "<p>" + CmsVaadinUtils.getMessageText(Messages.GUI_CACHE_FLEXCACHE_LABEL_MEMORY_BLOCK_0) + "</p>");
144        prog.addComponent(label);
145        prog.addComponent(getProgressBar((((float)memory.getUsage() / 100))));
146        info.addAdditionalElement(prog, 0);
147        info.setWindowCaption(CmsVaadinUtils.getMessageText(Messages.GUI_CACHE_FLEX_0));
148        info.setDescription(CmsVaadinUtils.getMessageText(Messages.GUI_CACHE_FLEX_0));
149        return info;
150    }
151
152    /**
153     * Gets a Progressbar with css style set.<p>
154     *
155     * @param value of the bar
156     * @return vaadin ProgressBar
157     */
158    public static ProgressBar getProgressBar(float value) {
159
160        ProgressBar res = new ProgressBar(value);
161        String style = "";
162        if (value > 0.75) {
163            style = "o-nearlyfull";
164        }
165        if (value > 0.9) {
166            style = "o-full";
167        }
168        res.addStyleName(style);
169        return res;
170    }
171
172    /**
173     * Creates in info button for flex cache statistics.<p>
174     *
175     * @return CmsInfoButton
176     */
177    protected static CmsInfoButton getFlexStatisticButton() {
178
179        Map<String, String> infoMap = new LinkedHashMap<String, String>();
180
181        CmsFlexCache cache = OpenCms.getFlexCache();
182        CmsLruCache entryLruCache = cache.getEntryLruCache();
183
184        infoMap.put(
185            CmsVaadinUtils.getMessageText(Messages.GUI_CACHE_FLEXCACHE_LABEL_STATS_KEYS_0),
186            String.valueOf(cache.keySize()));
187        infoMap.put(
188            CmsVaadinUtils.getMessageText(Messages.GUI_CACHE_FLEXCACHE_LABEL_STATS_VARIATIONS_0),
189            String.valueOf(cache.size()));
190        infoMap.put(
191            CmsVaadinUtils.getMessageText(Messages.GUI_CACHE_FLEXCACHE_LABEL_MEMORY_MAXSIZE_0),
192            CmsFileUtil.formatFilesize(
193                entryLruCache.getMaxCacheCosts(),
194                A_CmsUI.getCmsObject().getRequestContext().getLocale()));
195        infoMap.put(
196            CmsVaadinUtils.getMessageText(Messages.GUI_CACHE_FLEXCACHE_LABEL_MEMORY_CURSIZE_0),
197            CmsFileUtil.formatFilesize(
198                entryLruCache.getObjectCosts(),
199                A_CmsUI.getCmsObject().getRequestContext().getLocale()));
200        CmsInfoButton info = new CmsInfoButton(infoMap);
201        VerticalLayout prog = new VerticalLayout();
202        Label label = new Label();
203        label.setContentMode(ContentMode.HTML);
204        label.setValue(
205            "<p>" + CmsVaadinUtils.getMessageText(Messages.GUI_CACHE_FLEXCACHE_LABEL_MEMORY_BLOCK_0) + "</p>");
206        prog.addComponent(label);
207
208        prog.addComponent(
209            getProgressBar((float)entryLruCache.getObjectCosts() / (float)entryLruCache.getMaxCacheCosts()));
210        info.addAdditionalElement(prog, 0);
211        info.setWindowCaption(CmsVaadinUtils.getMessageText(Messages.GUI_CACHE_FLEX_0));
212        info.setDescription(CmsVaadinUtils.getMessageText(Messages.GUI_CACHE_FLEX_0));
213        return info;
214    }
215
216    /**
217     * Creates in info button for image cache statistics.<p>
218     *
219     * @return CmsInfoButton
220     */
221    protected static CmsInfoButton getImageStatisticButton() {
222
223        long size = 0L;
224        if (new File(CmsImageLoader.getImageRepositoryPath()).exists()) {
225            size = FileUtils.sizeOfDirectory(new File(CmsImageLoader.getImageRepositoryPath()));
226        }
227
228        Map<String, String> infoMap = new LinkedHashMap<String, String>();
229
230        infoMap.put(
231            CmsVaadinUtils.getMessageText(Messages.GUI_CACHE_IMAGECACHE_LABEL_MEMORY_BLOCK_0),
232            CmsFileUtil.formatFilesize(size, A_CmsUI.getCmsObject().getRequestContext().getLocale()));
233
234        CmsInfoButton info = new CmsInfoButton(infoMap);
235
236        info.setWindowCaption(CmsVaadinUtils.getMessageText(Messages.GUI_CACHE_IMAGE_0));
237        info.setDescription(CmsVaadinUtils.getMessageText(Messages.GUI_CACHE_IMAGE_0));
238        return info;
239    }
240
241    /**
242     * @see org.opencms.ui.apps.A_CmsWorkplaceApp#getBreadCrumbForState(java.lang.String)
243     */
244    @Override
245    protected LinkedHashMap<String, String> getBreadCrumbForState(String state) {
246
247        LinkedHashMap<String, String> crumbs = new LinkedHashMap<String, String>();
248
249        if (CmsStringUtil.isEmptyOrWhitespaceOnly(state)) {
250            if (Mode.FlexCache.equals(m_mode)) {
251                crumbs.put("", CmsVaadinUtils.getMessageText(Messages.GUI_CACHE_VIEW_FLEX_0));
252            } else {
253                crumbs.put("", CmsVaadinUtils.getMessageText(Messages.GUI_CACHE_VIEW_IMAGE_0));
254            }
255            return crumbs;
256        }
257        return new LinkedHashMap<String, String>(); //size==1 & state was not empty -> state doesn't match to known path
258    }
259
260    /**
261     * @see org.opencms.ui.apps.A_CmsWorkplaceApp#getComponentForState(java.lang.String)
262     */
263    @Override
264    protected Component getComponentForState(String state) {
265
266        //remove filter field
267        if (m_siteTableFilter != null) {
268            m_infoLayout.removeComponent(m_siteTableFilter);
269            m_siteTableFilter = null;
270        }
271
272        if (Mode.FlexCache.equals(m_mode)) {
273            m_rootLayout.setMainHeightFull(true);
274            return getFlexViewComponent();
275        }
276
277        if (Mode.ImageCache.equals(m_mode)) {
278            m_rootLayout.setMainHeightFull(true);
279            return getImageViewComponent();
280        }
281        return null;
282    }
283
284    /**
285     * @see org.opencms.ui.apps.A_CmsWorkplaceApp#getSubNavEntries(java.lang.String)
286     */
287    @Override
288    protected List<NavEntry> getSubNavEntries(String state) {
289
290        return null;
291
292    }
293
294    /**
295     * Layout for the Flex Cache View includings statistics and cache table.<p>
296     *
297     * @return vaadin component
298     */
299    private Component getFlexViewComponent() {
300
301        final CmsFlexCacheTable table = new CmsFlexCacheTable();
302        m_siteTableFilter = new TextField();
303        m_siteTableFilter.setIcon(FontOpenCms.FILTER);
304        m_siteTableFilter.setInputPrompt(
305            Messages.get().getBundle(UI.getCurrent().getLocale()).key(Messages.GUI_EXPLORER_FILTER_0));
306        m_siteTableFilter.addStyleName(ValoTheme.TEXTFIELD_INLINE_ICON);
307        m_siteTableFilter.setWidth("200px");
308        m_siteTableFilter.addTextChangeListener(new TextChangeListener() {
309
310            private static final long serialVersionUID = 1L;
311
312            public void textChange(TextChangeEvent event) {
313
314                table.filterTable(event.getText());
315            }
316        });
317        m_infoLayout.addComponent(m_siteTableFilter);
318
319        m_uiContext.addToolbarButton(getFlexStatisticButton());
320        m_uiContext.addToolbarButton(CmsFlushCache.getFlushToolButton());
321
322        table.setSizeFull();
323        return table;
324    }
325
326    /**
327     * Creates the view for the image cache.<p>
328     *
329     * @return a vaadin vertical layout with the information about the image cache
330     */
331    private Component getImageViewComponent() {
332
333        m_siteTableFilter = new TextField();
334
335        HorizontalSplitPanel sp = new HorizontalSplitPanel();
336        sp.setSizeFull();
337        VerticalLayout intro = CmsVaadinUtils.getInfoLayout(Messages.GUI_CACHE_IMAGE_INTRODUCTION_0);
338        VerticalLayout nullResult = CmsVaadinUtils.getInfoLayout(Messages.GUI_CACHE_IMAGE_NO_RESULTS_0);
339        final CmsImageCacheTable table = new CmsImageCacheTable(intro, nullResult, m_siteTableFilter);
340
341        sp.setFirstComponent(new CmsImageCacheInput(table));
342
343        VerticalLayout secC = new VerticalLayout();
344        secC.setSizeFull();
345        secC.addComponent(intro);
346        secC.addComponent(nullResult);
347        secC.addComponent(table);
348
349        m_siteTableFilter.setIcon(FontOpenCms.FILTER);
350        m_siteTableFilter.setInputPrompt(
351            Messages.get().getBundle(UI.getCurrent().getLocale()).key(Messages.GUI_EXPLORER_FILTER_0));
352        m_siteTableFilter.addStyleName(ValoTheme.TEXTFIELD_INLINE_ICON);
353        m_siteTableFilter.setWidth("200px");
354        m_siteTableFilter.addTextChangeListener(new TextChangeListener() {
355
356            private static final long serialVersionUID = 1L;
357
358            public void textChange(TextChangeEvent event) {
359
360                table.filterTable(event.getText());
361            }
362        });
363        m_infoLayout.addComponent(m_siteTableFilter);
364
365        m_uiContext.addToolbarButton(getImageStatisticButton());
366        m_uiContext.addToolbarButton(CmsFlushCache.getFlushToolButton());
367        table.setSizeFull();
368        sp.setSecondComponent(secC);
369        sp.setSplitPosition(CmsFileExplorer.LAYOUT_SPLIT_POSITION, Unit.PIXELS);
370
371        table.setVisible(false);
372        nullResult.setVisible(false);
373        m_siteTableFilter.setVisible(false);
374
375        return sp;
376    }
377}