001/*
002 *  Copyright 2012 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.runtime.plugins.admin.configuration;
017
018import java.io.File;
019import java.util.ArrayList;
020import java.util.Collection;
021import java.util.Collections;
022import java.util.HashMap;
023import java.util.List;
024import java.util.Map;
025
026import org.apache.avalon.framework.parameters.Parameters;
027import org.apache.avalon.framework.thread.ThreadSafe;
028import org.apache.cocoon.acting.AbstractAction;
029import org.apache.cocoon.environment.ObjectModelHelper;
030import org.apache.cocoon.environment.Redirector;
031import org.apache.cocoon.environment.Request;
032import org.apache.cocoon.environment.SourceResolver;
033
034import org.ametys.core.cocoon.ActionResultGenerator;
035import org.ametys.runtime.config.ConfigManager;
036import org.ametys.runtime.i18n.I18nizableText;
037import org.ametys.runtime.model.ElementDefinition;
038import org.ametys.runtime.model.type.ElementType;
039import org.ametys.runtime.servlet.RuntimeServlet;
040import org.ametys.runtime.util.AmetysHomeHelper;
041
042
043/**
044 * This action is in charge to get and save the config values entered by the user.<br>
045 * The backup is delegated to <code>Config</code>
046 */
047public class SaveConfigAction extends AbstractAction implements ThreadSafe
048{   
049    public Map act(Redirector redirector, SourceResolver resolver, Map objectModel, String source, Parameters parameters) throws Exception
050    {
051
052        if (getLogger().isDebugEnabled())
053        {
054            getLogger().debug("Starting SaveConfigAction");
055        }
056
057        Request request = ObjectModelHelper.getRequest(objectModel);
058        Map<String, Object> result = new HashMap<> ();
059        
060        try
061        {
062            Map<String, Object> values = new HashMap<>();
063            
064            ConfigManager configManager = ConfigManager.getInstance();
065            Collection<ElementDefinition> definitions = configManager.getConfigurationParameters();
066            Map<String, List<I18nizableText>> errorFields = new HashMap<>();
067            
068            for (ElementDefinition definition : definitions)
069            {
070                final String parameterId = definition.getName();
071                try
072                {
073                    Object value = _getTypedValueFromRequest(request, definition);
074                    values.put(parameterId, value);
075                }
076                catch (Exception e)
077                {
078                    if (getLogger().isWarnEnabled())
079                    {
080                        getLogger().warn("The configuration parameter '" + parameterId + "' is not valid.", e);
081                    }
082                    I18nizableText errorLabel = new I18nizableText("plugin.core", "PLUGINS_CORE_SAVE_PARAMETER_VALUE_INVALID", Collections.singletonList(e.getMessage()));
083                    errorFields.put(parameterId, Collections.singletonList(errorLabel));
084                }
085            }
086            
087            if (errorFields.isEmpty())
088            {
089                // No type error, let's try to save configuration
090                String configFileName = new File(AmetysHomeHelper.getAmetysHomeConfig(), RuntimeServlet.CONFIG_FILE_NAME).getCanonicalPath();
091                errorFields.putAll(configManager.save(values, configFileName));
092            }
093            
094            if (!errorFields.isEmpty())
095            {
096                for (String paramId : errorFields.keySet())
097                {
098                    List<I18nizableText> errors = errorFields.get(paramId);
099                    result.put(paramId, errors);
100                }
101                
102                request.setAttribute(ActionResultGenerator.MAP_REQUEST_ATTR, result);
103                return EMPTY_MAP;
104            }
105        }
106        catch (Exception e)
107        {
108            getLogger().error("An error occured while saving config modifications", e);
109            
110            result.put("error", e.getMessage());
111            request.setAttribute(ActionResultGenerator.MAP_REQUEST_ATTR, result);
112            return EMPTY_MAP;
113        }
114
115        // Set the request attribute for Cocoon reloading
116        if (getLogger().isDebugEnabled())
117        {
118            getLogger().debug("Positionning org.ametys.runtime.reload=true for Cocoon reloading");
119        }
120        request.setAttribute("org.ametys.runtime.reload", true);
121
122        return EMPTY_MAP;
123    }
124
125    private Object _getTypedValueFromRequest(Request request, ElementDefinition definition)
126    {
127        final String parameterId = definition.getName();
128        final ElementType type = definition.getType();
129        
130        Object value = null;
131        if (definition.isMultiple())
132        {
133            String[] valuesAsString = request.getParameterValues(parameterId);
134            if (valuesAsString != null)
135            {
136                List<Object> valuesAsList = new ArrayList<>();
137                for (String valueAsString : valuesAsString)
138                {
139                    valuesAsList.add(type.castValue(valueAsString));
140                }
141                value = valuesAsList.toArray(new Object[valuesAsList.size()]);
142            }
143        }
144        else
145        {
146            final String valueAsString = request.getParameter(parameterId);
147            value = definition.getType().castValue(valueAsString);
148        }
149
150        return value;
151    }
152}