Package org.geoserver.gwc.web.diskquota

Source Code of org.geoserver.gwc.web.diskquota.DiskQuotaConfigPanel

/* (c) 2014 Open Source Geospatial Foundation - all rights reserved
* (c) 2001 - 2013 OpenPlans
* This code is licensed under the GPL 2.0 license, available at the root
* application directory.
*/
package org.geoserver.gwc.web.diskquota;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.logging.Logger;

import org.apache.wicket.AttributeModifier;
import org.apache.wicket.Component;
import org.apache.wicket.ajax.AjaxRequestTarget;
import org.apache.wicket.ajax.form.AjaxFormComponentUpdatingBehavior;
import org.apache.wicket.markup.html.WebMarkupContainer;
import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.markup.html.form.CheckBox;
import org.apache.wicket.markup.html.form.DropDownChoice;
import org.apache.wicket.markup.html.form.Radio;
import org.apache.wicket.markup.html.form.RadioGroup;
import org.apache.wicket.markup.html.form.TextField;
import org.apache.wicket.markup.html.panel.Panel;
import org.apache.wicket.model.IModel;
import org.apache.wicket.model.LoadableDetachableModel;
import org.apache.wicket.model.Model;
import org.apache.wicket.model.PropertyModel;
import org.apache.wicket.model.StringResourceModel;
import org.geoserver.gwc.GWC;
import org.geoserver.web.GeoServerApplication;
import org.geoserver.web.wicket.LocalizedChoiceRenderer;
import org.geotools.util.logging.Logging;
import org.geowebcache.diskquota.DiskQuotaConfig;
import org.geowebcache.diskquota.ExpirationPolicy;
import org.geowebcache.diskquota.QuotaStoreFactory;
import org.geowebcache.diskquota.jdbc.JDBCConfiguration;
import org.geowebcache.diskquota.jdbc.JDBCQuotaStoreFactory;
import org.geowebcache.diskquota.jdbc.SQLDialect;
import org.geowebcache.diskquota.storage.Quota;
import org.geowebcache.diskquota.storage.StorageUnit;
import org.springframework.context.ApplicationContext;

/**
* A panel to configure the global disk quota settings.
*
* @author groldan
*
*/
public class DiskQuotaConfigPanel extends Panel {
    private static final long serialVersionUID = 1L;

    private static final Logger LOGGER = Logging.getLogger(DiskQuotaConfigPanel.class);

    private final IModel<StorageUnit> configQuotaUnitModel;

    private final IModel<Double> configQuotaValueModel;

    public DiskQuotaConfigPanel(final String id, final IModel<DiskQuotaConfig> diskQuotaConfigModel,
            final IModel<JDBCConfiguration> jdbcQuotaConfigModel) {
        super(id, diskQuotaConfigModel);

        final DiskQuotaConfig diskQuotaConfig = diskQuotaConfigModel.getObject();

        Quota globalQuota = diskQuotaConfig.getGlobalQuota();
        if (globalQuota == null) {
            LOGGER.info("There's no GWC global disk quota configured, setting a default of 100MiB");
            globalQuota = new Quota(100, StorageUnit.MiB);
            diskQuotaConfig.setGlobalQuota(globalQuota);
        }

        // use this two payload models to let the user configure the global quota as a decimal value
        // plus a storage unit. Then at form sumbission we'll transform them back to a BigInteger
        // representing the quota byte count
        BigInteger bytes = globalQuota.getBytes();
        StorageUnit bestRepresentedUnit = StorageUnit.bestFit(bytes);
        BigDecimal transformedQuota = StorageUnit.B.convertTo(new BigDecimal(bytes),
                bestRepresentedUnit);
        configQuotaValueModel = new Model<Double>(transformedQuota.doubleValue());

        configQuotaUnitModel = new Model<StorageUnit>(bestRepresentedUnit);
       
        addDiskQuotaIntegrationEnablement(diskQuotaConfigModel);
       
        addDiskQuotaStoreChooser(diskQuotaConfigModel, jdbcQuotaConfigModel);

        addDiskBlockSizeConfig(diskQuotaConfigModel);

        addCleanUpFrequencyConfig(diskQuotaConfigModel);

        addGlobalQuotaConfig(diskQuotaConfigModel, configQuotaValueModel, configQuotaUnitModel);

        addGlobalExpirationPolicyConfig(diskQuotaConfigModel);

    }

    private void addDiskQuotaStoreChooser(IModel<DiskQuotaConfig> diskQuotaModel, IModel<JDBCConfiguration> jdbcQuotaConfigModel) {
        final WebMarkupContainer quotaStoreContainer = new WebMarkupContainer("quotaStoreContainer");
        quotaStoreContainer.setOutputMarkupId(true);
        add(quotaStoreContainer);
       
        // get the list of supported quota store types
        ApplicationContext applicationContext = GeoServerApplication.get().getApplicationContext();
        Map<String, QuotaStoreFactory> factories = applicationContext.getBeansOfType(QuotaStoreFactory.class);
        List<String> storeNames = new ArrayList<String>();
        for (QuotaStoreFactory sf : factories.values()) {
            storeNames.addAll(sf.getSupportedStoreNames());
        }
        Collections.sort(storeNames);
       
        // add the drop down chooser
        PropertyModel<String> storeNameModel = new PropertyModel<String>(diskQuotaModel, "quotaStore");
        if(diskQuotaModel.getObject().getQuotaStore() == null) {
            storeNameModel.setObject(JDBCQuotaStoreFactory.H2_STORE);
        }
        final DropDownChoice<String> quotaStoreChooser = new DropDownChoice<String>("diskQuotaStore", storeNameModel, storeNames,
                new LocalizedChoiceRenderer(this));
        quotaStoreChooser.setOutputMarkupId(true);
        quotaStoreContainer.add(quotaStoreChooser);
       
        // add the JDBC container
        final WebMarkupContainer jdbcContainer = new WebMarkupContainer("jdbcQuotaStoreContainer");
        jdbcContainer.setOutputMarkupId(true);
        jdbcContainer.setVisible("JDBC".equals(quotaStoreChooser.getModelObject()));
        quotaStoreContainer.add(jdbcContainer);
       
        // add a chooser for the dialect type
        List<String> dialectBeanNames = new ArrayList<String>(applicationContext.getBeansOfType(SQLDialect.class).keySet());
        List<String> dialectNames = new ArrayList<String>();
        for (String beanName : dialectBeanNames) {
            int idx = beanName.indexOf("QuotaDialect");
            if(idx > 0) {
                dialectNames.add(beanName.substring(0, idx));
            }
        }
        JDBCConfiguration config = jdbcQuotaConfigModel.getObject();
        IModel<String> dialectModel = new PropertyModel<String>(jdbcQuotaConfigModel, "dialect");
        DropDownChoice<String> dialectChooser = new DropDownChoice<String>("dialectChooser", dialectModel, dialectNames);
        dialectChooser.setRequired(true);
        jdbcContainer.add(dialectChooser);
       
        // add a chooser for the connection type
        List<String> connectionTypes = Arrays.asList("JNDI", "PRIVATE_POOL");
        Model<String> connectionTypeModel = new Model<String>();
        if(config.getJNDISource() == null) {
            connectionTypeModel.setObject("PRIVATE_POOL");
        } else {
            connectionTypeModel.setObject("JNDI");
        }
        final DropDownChoice<String> connectionTypeChooser = new DropDownChoice<String>("connectionTypeChooser",
                connectionTypeModel, connectionTypes, new LocalizedChoiceRenderer(this));
        connectionTypeChooser.setOutputMarkupId(true);
        jdbcContainer.add(connectionTypeChooser);
       
        // make the JDBC configuration visible only when the user chose a JDBC store
        quotaStoreChooser.add(new AjaxFormComponentUpdatingBehavior("onChange") {
           
            @Override
            protected void onUpdate(AjaxRequestTarget target) {
                jdbcContainer.setVisible("JDBC".equals(quotaStoreChooser.getModelObject()));
                target.addComponent(quotaStoreContainer);
            }
        });
       
        // a container for jndi and local private pool options
        final WebMarkupContainer connectionTypeContainer = new WebMarkupContainer("connectionTypeContainer");
        connectionTypeContainer.setOutputMarkupId(true);
        jdbcContainer.add(connectionTypeContainer);
       
        // add a field for editing the JNDI connection parameters
        final WebMarkupContainer jndiContainer = new WebMarkupContainer("jndiLocationContainer");
        jndiContainer.setVisible(config.getJNDISource() != null);
        connectionTypeContainer.add(jndiContainer);
        IModel<String> jndiModel = new PropertyModel<String>(jdbcQuotaConfigModel, "jNDISource");
        TextField<String> jndiLocation = new TextField<String>("jndiLocation", jndiModel);
        jndiLocation.setRequired(true);
        jndiContainer.add(jndiLocation);
       
        // and a panel to edit the private jdbc pool
        IModel<JDBCConfiguration.ConnectionPoolConfiguration> poolConfigurationModel =
                new PropertyModel<JDBCConfiguration.ConnectionPoolConfiguration>(jdbcQuotaConfigModel, "connectionPool");
        final JDBCConnectionPoolPanel privatePoolPanel = new JDBCConnectionPoolPanel("connectionPoolConfigurator", poolConfigurationModel);
        privatePoolPanel.setVisible(config.getJNDISource() == null);
        connectionTypeContainer.add(privatePoolPanel);
       
        // make the two ways to configure the JDBC store show up as alternatives
        connectionTypeChooser.add(new AjaxFormComponentUpdatingBehavior("onChange") {
           
            @Override
            protected void onUpdate(AjaxRequestTarget target) {
                boolean jndiVisible = "JNDI".equals(connectionTypeChooser.getModelObject());
                jndiContainer.setVisible(jndiVisible);
                privatePoolPanel.setVisible(!jndiVisible);
                target.addComponent(connectionTypeContainer);
            }
        });
       
    }

    private void addGlobalQuotaConfig(final IModel<DiskQuotaConfig> diskQuotaModel,
            IModel<Double> quotaValueModel, IModel<StorageUnit> unitModel) {

        final IModel<Quota> globalQuotaModel = new PropertyModel<Quota>(diskQuotaModel,
                "globalQuota");

        final IModel<Quota> globalUsedQuotaModel = new LoadableDetachableModel<Quota>() {
            private static final long serialVersionUID = 1L;

            @Override
            protected Quota load() {
                GWC gwc = GWC.get();
                if (!gwc.isDiskQuotaAvailable()) {
                    return new Quota();// fake
                }
                return gwc.getGlobalUsedQuota();
            }
        };

        Object[] progressMessageParams = { globalUsedQuotaModel.getObject().toNiceString(),
                globalQuotaModel.getObject().toNiceString() };
        IModel<String> progressMessageModel = new StringResourceModel(
                "DiskQuotaConfigPanel.usedQuotaMessage", null, progressMessageParams);
        addGlobalQuotaStatusBar(globalQuotaModel, globalUsedQuotaModel, progressMessageModel);

        TextField<Double> quotaValue = new TextField<Double>("globalQuota", quotaValueModel);
        quotaValue.setRequired(true);
        add(quotaValue);

        List<? extends StorageUnit> units = Arrays.asList(StorageUnit.MiB, StorageUnit.GiB,
                StorageUnit.TiB);
        DropDownChoice<StorageUnit> quotaUnitChoice;
        quotaUnitChoice = new DropDownChoice<StorageUnit>("globalQuotaUnits", unitModel, units);
        add(quotaUnitChoice);
    }

    private void addGlobalExpirationPolicyConfig(final IModel<DiskQuotaConfig> diskQuotaModel) {
        IModel<ExpirationPolicy> globalQuotaPolicyModel = new PropertyModel<ExpirationPolicy>(
                diskQuotaModel, "globalExpirationPolicyName");

        RadioGroup<ExpirationPolicy> globalQuotaPolicy;
        globalQuotaPolicy = new RadioGroup<ExpirationPolicy>("globalQuotaExpirationPolicy",
                globalQuotaPolicyModel);
        add(globalQuotaPolicy);

        IModel<ExpirationPolicy> lfuModel = new Model<ExpirationPolicy>(ExpirationPolicy.LFU);
        IModel<ExpirationPolicy> lruModel = new Model<ExpirationPolicy>(ExpirationPolicy.LRU);

        Radio<ExpirationPolicy> globalQuotaPolicyLFU;
        Radio<ExpirationPolicy> globalQuotaPolicyLRU;
        globalQuotaPolicyLFU = new Radio<ExpirationPolicy>("globalQuotaPolicyLFU", lfuModel);
        globalQuotaPolicyLRU = new Radio<ExpirationPolicy>("globalQuotaPolicyLRU", lruModel);

        globalQuotaPolicy.add(globalQuotaPolicyLFU);
        globalQuotaPolicy.add(globalQuotaPolicyLRU);
    }

    @SuppressWarnings({ "unchecked", "rawtypes" })
    private void addCleanUpFrequencyConfig(final IModel<DiskQuotaConfig> diskQuotaModel) {

        final DiskQuotaConfig diskQuotaConfig = diskQuotaModel.getObject();

        int frequency = diskQuotaConfig.getCacheCleanUpFrequency();
        TimeUnit unit = diskQuotaConfig.getCacheCleanUpUnits();
        if (TimeUnit.SECONDS != unit) {
            frequency = (int) TimeUnit.SECONDS.convert(frequency, unit);
            diskQuotaConfig.setCacheCleanUpFrequency(frequency);
            diskQuotaConfig.setCacheCleanUpUnits(TimeUnit.SECONDS);
        }

        IModel<Integer> cleanUpFreqModel;
        cleanUpFreqModel = new PropertyModel<Integer>(diskQuotaModel, "cacheCleanUpFrequency");
        TextField<Integer> cleanUpFreq = new TextField<Integer>("cleanUpFreq", cleanUpFreqModel);
        cleanUpFreq.setRequired(true);
        cleanUpFreq.add(new AttributeModifier("title", true, new StringResourceModel(
                "DiskQuotaConfigPanel.cleanUpFreq.title", (Component) null, null)));
        add(cleanUpFreq);
        {
            Date lastRun = diskQuotaConfig.getLastCleanUpTime();
            String resourceId;
            HashMap<String, String> params = new HashMap<String, String>();
            if (lastRun == null) {
                resourceId = "DiskQuotaConfigPanel.cleanUpLastRunNever";
            } else {
                resourceId = "DiskQuotaConfigPanel.cleanUpLastRun";
                long timeAgo = (System.currentTimeMillis() - lastRun.getTime()) / 1000;
                String timeUnits = "s";
                if (timeAgo > 60 * 60 * 24) {
                    timeUnits = "d";
                    timeAgo /= 60 * 60 * 24;
                } else if (timeAgo > 60 * 60) {
                    timeUnits = "h";
                    timeAgo /= 60 * 60;
                } else if (timeAgo > 60) {
                    timeUnits = "m";
                    timeAgo /= 60;
                }
                params.put("x", String.valueOf(timeAgo));
                params.put("timeUnit", timeUnits);
            }
            IModel<String> lastRunModel = new StringResourceModel(resourceId, this, new Model(
                    params));
            add(new Label("cleanUpLastRun", lastRunModel));
        }
    }

    private void addDiskBlockSizeConfig(final IModel<DiskQuotaConfig> diskQuotaModel) {
        IModel<Integer> blockSizeModel;
        blockSizeModel = new PropertyModel<Integer>(diskQuotaModel, "diskBlockSize");
        TextField<Integer> diskBlockSize = new TextField<Integer>("diskBlockSize", blockSizeModel);
        diskBlockSize.setRequired(true);
        diskBlockSize.add(new AttributeModifier("title", true, new StringResourceModel(
                "DiskQuotaConfigPanel.diskBlockSize.title", (Component) null, null)));
        add(diskBlockSize);
    }

    private void addDiskQuotaIntegrationEnablement(IModel<DiskQuotaConfig> diskQuotaModel) {
        IModel<Boolean> quotaEnablementModel = new PropertyModel<Boolean>(diskQuotaModel, "enabled");
        CheckBox diskQuotaIntegration = checkbox("enableDiskQuota", quotaEnablementModel,
                "DiskQuotaConfigPanel.enableDiskQuota.title");
        add(diskQuotaIntegration);
    }

    private void addGlobalQuotaStatusBar(final IModel<Quota> globalQuotaModel,
            final IModel<Quota> globalUsedQuotaModel, IModel<String> progressMessageModel) {

        Quota limit = globalQuotaModel.getObject();
        Quota used = globalUsedQuotaModel.getObject();

        BigInteger limitValue = limit.getBytes();
        BigInteger usedValue = used.getBytes();

        StorageUnit bestUnitForLimit = StorageUnit.bestFit(limitValue);
        StorageUnit bestUnitForUsed = StorageUnit.bestFit(usedValue);

        StorageUnit biggerUnit = bestUnitForLimit.compareTo(bestUnitForUsed) > 0 ? bestUnitForLimit
                : bestUnitForUsed;

        BigDecimal showLimit = StorageUnit.B.convertTo(new BigDecimal(limitValue), biggerUnit);
        BigDecimal showUsed = StorageUnit.B.convertTo(new BigDecimal(usedValue), biggerUnit);

        final IModel<Number> limitModel = new Model<Number>(showLimit);
        final IModel<Number> usedModel = new Model<Number>(showUsed);

        StatusBar statusBar = new StatusBar("globalQuotaProgressBar", limitModel, usedModel,
                progressMessageModel);

        add(statusBar);
    }

    public StorageUnit getStorageUnit() {
        return configQuotaUnitModel.getObject();
    }

    public Object getQuotaValue() {
        // REVISIT: it seems Wicket is sending back a plain string instead of a BigDecimal
        return configQuotaValueModel.getObject();
    }

    static CheckBox checkbox(String id, IModel<Boolean> model, String titleKey) {
        CheckBox checkBox = new CheckBox(id, model);
        if (null != titleKey) {
            AttributeModifier attributeModifier = new AttributeModifier("title", true,
                    new StringResourceModel(titleKey, (Component) null, null));
            checkBox.add(attributeModifier);
        }
        return checkBox;
    }
}
TOP

Related Classes of org.geoserver.gwc.web.diskquota.DiskQuotaConfigPanel

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.