001/*
002 *  Copyright 2017 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.plugins.extraction.execution;
017
018import java.util.ArrayList;
019import java.util.Collection;
020import java.util.HashMap;
021import java.util.List;
022import java.util.Map;
023
024import org.apache.avalon.framework.parameters.Parameters;
025import org.apache.avalon.framework.service.ServiceException;
026import org.apache.avalon.framework.service.ServiceManager;
027import org.apache.cocoon.environment.ObjectModelHelper;
028import org.apache.cocoon.environment.Redirector;
029import org.apache.cocoon.environment.Request;
030import org.apache.cocoon.environment.SourceResolver;
031import org.apache.commons.lang3.StringUtils;
032import org.apache.excalibur.source.SourceException;
033import org.apache.excalibur.source.TraversableSource;
034import org.apache.excalibur.source.impl.FileSource;
035
036import org.ametys.core.cocoon.JSonReader;
037import org.ametys.core.right.RightManager;
038import org.ametys.core.right.RightManager.RightResult;
039import org.ametys.core.user.CurrentUserProvider;
040import org.ametys.core.user.UserIdentity;
041import org.ametys.plugins.core.ui.parameter.files.GetParameterFileAction;
042import org.ametys.plugins.extraction.ExtractionConstants;
043import org.ametys.plugins.extraction.execution.Extraction.ExtractionProfile;
044
045/**
046 * Action for getting extraction definition files
047 */
048public class GetExtractionDefinitionFilesAction extends GetParameterFileAction
049{
050    private RightManager _rightManager;
051    private CurrentUserProvider _currentUserProvider;
052    private ExtractionDefinitionReader _definitionReader;
053    private ExtractionDAO _extractionDAO;
054    
055    @Override
056    public void service(ServiceManager serviceManager) throws ServiceException
057    {
058        super.service(serviceManager);
059        _rightManager = (RightManager) serviceManager.lookup(RightManager.ROLE);
060        _currentUserProvider = (CurrentUserProvider) serviceManager.lookup(CurrentUserProvider.ROLE);
061        _definitionReader = (ExtractionDefinitionReader) serviceManager.lookup(ExtractionDefinitionReader.ROLE);
062        _extractionDAO = (ExtractionDAO) serviceManager.lookup(ExtractionDAO.ROLE);
063    }
064    
065    @Override
066    public Map act(Redirector redirector, SourceResolver resolver, Map objectModel, String source, Parameters parameters) throws Exception
067    {
068        UserIdentity userIdentity = _currentUserProvider.getUser();
069        if (_rightManager.hasRight(userIdentity, ExtractionConstants.EXECUTE_EXTRACTION_RIGHT_ID, "/${WorkspaceName}") != RightResult.RIGHT_ALLOW)
070        {
071            String errorMessage = "User " + userIdentity + " try to list extraction definition files with no sufficient rights"; 
072            getLogger().error(errorMessage);
073            throw new IllegalStateException(errorMessage);
074        }
075        
076        @SuppressWarnings("unchecked")
077        Map<String, Object> jsParameters = (Map<String, Object>) objectModel.get(ObjectModelHelper.PARENT_CONTEXT);
078
079        String profileId = StringUtils.defaultIfEmpty((String) jsParameters.get("profile"), "read_access");
080        
081        if (!"read_access".equals(profileId) && !"write_access".equals(profileId) && !"right_access".equals(profileId))
082        {
083            throw new IllegalArgumentException("Unexpected profile identifier : " + profileId);
084        }
085        
086        ExtractionProfile profile = ExtractionProfile.valueOf(profileId.toUpperCase());
087        
088        Request request = ObjectModelHelper.getRequest(objectModel);
089        
090        String path = StringUtils.defaultString(request.getParameter("path"), "");
091        
092        String rootURI = getRootURI(request);
093        TraversableSource rootDir = (TraversableSource) _srcResolver.resolveURI(rootURI);
094        TraversableSource currentDir = (TraversableSource) _srcResolver.resolveURI(rootURI + (path.length() > 0 ? "/" + path : ""));
095        List<Map<String, Object>> nodes = _fillNodes(currentDir, profile, rootDir, userIdentity);
096        
097        Map<String, Object> result = new HashMap<>();
098        result.put("nodes", nodes);
099        
100        request.setAttribute(JSonReader.OBJECT_TO_READ, result);
101        return EMPTY_MAP;
102    }
103        
104    private List<Map<String, Object>> _fillNodes(TraversableSource currentDir, ExtractionProfile profile, TraversableSource rootDir, UserIdentity userIdentity) throws SourceException, Exception
105    {
106        List<Map<String, Object>> nodes = new ArrayList<>();
107        
108        if (currentDir.exists())
109        {
110            for (TraversableSource child : (Collection<TraversableSource>) currentDir.getChildren())
111            {
112                if (!isIgnoredSource(child))
113                {
114                    if (child.isCollection())
115                    {
116                        Map<String, Object> container = _extractionConainer2JsonObject(child, rootDir);
117
118                        switch (profile)
119                        {
120                            case WRITE_ACCESS:
121                                if ((boolean) container.get("displayForWrite"))
122                                {
123                                    nodes.add(container);
124                                }
125                                break;
126                            case RIGHT_ACCESS:
127                                if ((boolean) container.get("displayForRights"))
128                                {
129                                    nodes.add(container);
130                                }
131                                break;
132                            case READ_ACCESS:
133                            default:
134                                if ((boolean) container.get("displayForRead"))
135                                {
136                                    nodes.add(container);
137                                }
138                                break;
139                        }
140                        
141                    }
142                    else
143                    {
144                        // To parse the extraction definition file only once, check here if the current user can read it
145                        Extraction extraction = _definitionReader.readExtractionDefinitionFile(((FileSource) child).getFile());
146                        
147                        switch (profile)
148                        {
149                            case WRITE_ACCESS:
150                                if (_extractionDAO.hasWriteRightOnExtraction(userIdentity, child, extraction.getAuthor()))
151                                {
152                                    nodes.add(_extraction2JsonObject(extraction, child, rootDir));
153                                }
154                                break;
155                            case RIGHT_ACCESS:
156                                if (_extractionDAO.hasRightAffectationRightOnExtraction(userIdentity, child, extraction.getAuthor()))
157                                {
158                                    nodes.add(_extraction2JsonObject(extraction, child, rootDir));
159                                }
160                                break;
161                            case READ_ACCESS:
162                            default:
163                                if (_extractionDAO.hasReadRightOnExtraction(userIdentity, child, extraction.getAuthor()))
164                                {
165                                    nodes.add(_extraction2JsonObject(extraction, child, rootDir));
166                                }
167                                break;
168                        }
169                        
170                    }
171                }
172            }
173        }
174        return nodes;
175    }
176    @Override
177    protected String getRootURI(Request request)
178    {
179        return ExtractionConstants.DEFINITIONS_DIR;
180    }
181
182    
183    @Override
184    protected boolean isIgnoredSource(TraversableSource source)
185    {
186        return !source.isCollection() && !source.getName().endsWith(".xml");
187    }
188    
189    private Map<String, Object> _extraction2JsonObject(Extraction extraction, TraversableSource file, TraversableSource root)
190    {
191        Map<String, Object> jsonObject = super._resource2JsonObject(file, root);
192
193        jsonObject.putAll(_extractionDAO.getExtractionProperties(extraction, file));
194        
195        return jsonObject;
196    }
197    
198    private Map<String, Object> _extractionConainer2JsonObject(TraversableSource file, TraversableSource root)
199    {
200        Map<String, Object> jsonObject = super._collection2JsonObject(file, root);
201
202        jsonObject.putAll(_extractionDAO.getExtractionContainerProperties(file));
203        
204        return jsonObject;
205    }
206
207}