001/*
002 *  Copyright 2016 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.util.ArrayList;
019import java.util.HashMap;
020import java.util.List;
021import java.util.Map;
022
023import org.apache.avalon.framework.parameters.Parameters;
024import org.apache.avalon.framework.service.ServiceException;
025import org.apache.avalon.framework.service.ServiceManager;
026import org.apache.cocoon.acting.ServiceableAction;
027import org.apache.cocoon.environment.ObjectModelHelper;
028import org.apache.cocoon.environment.Redirector;
029import org.apache.cocoon.environment.Request;
030import org.apache.cocoon.environment.SourceResolver;
031
032import org.ametys.core.cocoon.ActionResultGenerator;
033import org.ametys.core.util.JSONUtils;
034import org.ametys.runtime.config.Config;
035import org.ametys.runtime.config.ConfigManager;
036import org.ametys.runtime.config.ConfigParameter;
037import org.ametys.runtime.config.ConfigParameterCheckerDescriptor;
038import org.ametys.runtime.parameter.ParameterChecker;
039import org.ametys.runtime.parameter.ParameterHelper;
040import org.ametys.runtime.parameter.ParameterHelper.ParameterType;
041
042/**
043 * Fetch the test values and dispatch the requests to the appropriate parameter checkers.
044 */
045public class CheckConfigAction extends ServiceableAction
046{
047    /** Helper component gathering utility methods for the management of JSON entities */
048    private JSONUtils _jsonUtils;
049    
050    @Override
051    public void service(ServiceManager serviceManager) throws ServiceException
052    {
053        _jsonUtils = (JSONUtils) serviceManager.lookup(JSONUtils.ROLE);
054    }
055    
056    @SuppressWarnings("unchecked")
057    @Override
058    public Map act(Redirector redirector, SourceResolver resolver, Map objectModel, String source, Parameters parameters) throws Exception
059    {
060        Map<String, String> result = new HashMap<> ();
061        
062        // Handle the 'configuration not initialized' case
063        Map<String, String> oldUntypedValues = null;
064        if (Config.getInstance() == null)
065        {
066            try
067            {
068                oldUntypedValues = Config.read();
069            }
070            catch (Exception e)
071            {
072                oldUntypedValues = new HashMap<>();
073            }
074        }
075        
076        // Fetch the request parameters
077        Request request = ObjectModelHelper.getRequest(objectModel);
078        
079        // Prepare the values for the test
080        String fieldCheckersInfoJSON = request.getParameter("fieldCheckersInfo");
081        Map<String, Object> fieldCheckersInfo = _jsonUtils.convertJsonToMap(fieldCheckersInfoJSON);
082        Map<String, Object> valuesByParameterChecker = _getValuesByParamCheckerId(oldUntypedValues, fieldCheckersInfo);
083
084        // Dispatch the requests
085        for (String fieldCheckerId : valuesByParameterChecker.keySet())
086        {
087            ParameterChecker fieldChecker = (ParameterChecker) ((Map<String, Object>) valuesByParameterChecker.get(fieldCheckerId)).get("checker");
088            List<String> values = (List<String>) ((Map<String, Object>) valuesByParameterChecker.get(fieldCheckerId)).get("values");
089            try 
090            {
091                fieldChecker.check(values); 
092            }
093            catch (Throwable t)
094            {
095                getLogger().error("The test '" + fieldCheckerId + "' failed : \n" + t.getMessage(), t);
096                String msg = t.getMessage() != null ? t.getMessage() : "Unknown error";
097                result.put(fieldCheckerId, msg);
098            }
099        }
100        
101        request.setAttribute(ActionResultGenerator.MAP_REQUEST_ATTR, result);
102        return result;
103    }
104
105    /**
106     * Compute the proper values and {@link ParameterChecker} implementations to use for the test and order them by parameter checker id
107     * @param oldUntypedValues the map of old untyped values of the configuration
108     * @param paramCheckersInfo the information concerning the parameter checkers
109     * @return the map of values lists ordered by parameter checker
110     */
111    @SuppressWarnings("unchecked")
112    private Map<String, Object> _getValuesByParamCheckerId(Map<String, String> oldUntypedValues, Map<String, Object> paramCheckersInfo)
113    {
114        Map<String, Object> result = new HashMap<> ();
115        
116        Map<String, ConfigParameter> configParams = ConfigManager.getInstance().getParameters();
117        for (String paramCheckerId : paramCheckersInfo.keySet())
118        {
119            Map<String, Object> valuesByParamCheckerId = new HashMap<> (); 
120            
121            // Check the ids of the parameter checkers and build the parameter checkers' list
122            ConfigParameterCheckerDescriptor parameterCheckerDescriptor = ConfigManager.getInstance().getParameterChecker(paramCheckerId);
123            if (parameterCheckerDescriptor == null)
124            {
125                throw new IllegalArgumentException("The parameter checker '" + paramCheckerId + "' was not found.");
126            }
127            
128            ParameterChecker parameterChecker  = parameterCheckerDescriptor.getParameterChecker();
129            
130            valuesByParamCheckerId.put("checker", parameterChecker);
131            
132            List<String> paramNames = (List<String>) ((Map<String, Object>) paramCheckersInfo.get(paramCheckerId)).get("testParamsNames");
133            List<String> paramRawValues = (List<String>) ((Map<String, Object>) paramCheckersInfo.get(paramCheckerId)).get("rawTestValues");
134            
135            List<String> values = new ArrayList<> ();
136            
137            // Compute the proper values for the test
138            for (int i = 0; i < paramNames.size(); i++)
139            {
140                String paramName = paramNames.get(i);
141                String untypedValue = ParameterHelper.valueToString(paramRawValues.get(i));
142                
143                // Handle password field
144                if (untypedValue == null && configParams.get(paramName).getType() == ParameterType.PASSWORD)
145                {
146                    String typedValue = null;
147                    if (Config.getInstance() != null)
148                    {
149                        // Fetch the value of an empty password field
150                        typedValue = Config.getInstance().getValueAsString(paramName);
151                    }
152                    else if (oldUntypedValues != null)
153                    {
154                        typedValue = oldUntypedValues.get(paramName);
155                    }
156                    
157                    values.add(typedValue);
158                }
159                else
160                {
161                    values.add(untypedValue);
162                }
163            }
164            
165            valuesByParamCheckerId.put("values", values);
166            
167            result.put(paramCheckerId, valuesByParamCheckerId);
168        }
169        
170        return result;
171    }
172}