001/*
002 * (C) Copyright 2018 Nuxeo (http://nuxeo.com/) and others.
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 *
016 * Contributors:
017 *     pierre
018 */
019package org.nuxeo.ecm.automation.core.operations.services.bulk;
020
021import java.io.IOException;
022
023import javax.servlet.http.HttpServletResponse;
024
025import org.nuxeo.ecm.automation.OperationException;
026import org.nuxeo.ecm.automation.core.Constants;
027import org.nuxeo.ecm.automation.core.annotations.Context;
028import org.nuxeo.ecm.automation.core.annotations.Operation;
029import org.nuxeo.ecm.automation.core.annotations.OperationMethod;
030import org.nuxeo.ecm.automation.core.annotations.Param;
031import org.nuxeo.ecm.automation.core.util.PageProviderHelper;
032import org.nuxeo.ecm.automation.core.util.Properties;
033import org.nuxeo.ecm.automation.core.util.StringList;
034import org.nuxeo.ecm.core.api.CoreSession;
035import org.nuxeo.ecm.core.api.NuxeoException;
036import org.nuxeo.ecm.core.bulk.BulkAdminService;
037import org.nuxeo.ecm.core.bulk.BulkService;
038import org.nuxeo.ecm.core.bulk.io.BulkParameters;
039import org.nuxeo.ecm.core.bulk.message.BulkCommand;
040import org.nuxeo.ecm.core.bulk.message.BulkStatus;
041import org.nuxeo.ecm.platform.query.api.PageProvider;
042import org.nuxeo.ecm.platform.query.api.PageProviderDefinition;
043import org.nuxeo.ecm.platform.query.api.PageProviderService;
044
045/**
046 * Automation operation that can run an http enabled Bulk Action.
047 *
048 * @since 10.2
049 */
050@Operation(id = BulkRunAction.ID, category = Constants.CAT_SERVICES, label = "Run a bulk command", addToStudio = true, description = "Run a bulk action on a set of documents expressed by a NXQL.")
051public class BulkRunAction {
052
053    public static final String ID = "Bulk.RunAction";
054
055    @Context
056    protected BulkService service;
057
058    @Context
059    protected BulkAdminService admin;
060
061    @Context
062    protected CoreSession session;
063
064    @Param(name = "query", required = false)
065    protected String query;
066
067    @Param(name = "providerName", required = false)
068    protected String providerName;
069
070    @Param(name = "queryParams", required = false)
071    protected StringList queryParams;
072
073    @Param(name = PageProviderService.NAMED_PARAMETERS, required = false, description = "Named parameters to pass to the page provider to "
074            + "fill in query variables.")
075    protected Properties namedParameters;
076
077    @Param(name = "quickFilters", required = false, description = "Quick filter " + "properties (separated by comma)")
078    protected StringList quickFilters;
079
080    @Param(name = "action", required = true)
081    protected String action;
082
083    @Param(name = "repositoryName", required = false)
084    protected String repositoryName;
085
086    @Param(name = "bucketSize", required = false)
087    protected int bucketSize;
088
089    @Param(name = "batchSize", required = false)
090    protected int batchSize;
091
092    @Param(name = "parameters", required = false)
093    protected String parametersAsJson;
094
095    @OperationMethod(asyncService = BulkService.class)
096    public BulkStatus run() throws IOException, OperationException {
097
098        if (!admin.getActions().contains(action)) {
099            throw new NuxeoException("Action '" + action + "' not found", HttpServletResponse.SC_NOT_FOUND);
100        }
101        if (!admin.isHttpEnabled(action) && !session.getPrincipal().isAdministrator()) {
102            throw new NuxeoException("Action '" + action + "' denied", HttpServletResponse.SC_FORBIDDEN);
103        }
104
105        if (query == null && providerName == null) {
106            throw new OperationException("Query and ProviderName cannot be both null");
107        }
108
109        String userName = session.getPrincipal().getName();
110
111        PageProviderDefinition def = query != null ? PageProviderHelper.getQueryPageProviderDefinition(query)
112                : PageProviderHelper.getPageProviderDefinition(providerName);
113
114        if (def == null) {
115            throw new OperationException("Could not get Provider Definition from either query or provider name");
116        }
117
118        PageProvider<?> provider = PageProviderHelper.getPageProvider(session, def, namedParameters,
119                queryParams != null ? queryParams.toArray(new String[0]) : null);
120        query = PageProviderHelper.buildQueryStringWithAggregates(provider);
121
122        if (query.contains("?")) {
123            throw new OperationException("Query parameters could not be parsed");
124        }
125
126        BulkCommand.Builder builder = new BulkCommand.Builder(action, query).user(userName);
127        try {
128            builder.params(BulkParameters.paramsToMap(parametersAsJson));
129        } catch (IOException e) {
130            throw new OperationException("Could not parse parameters, expecting valid json value", e);
131        }
132
133        if (repositoryName != null) {
134            builder.repository(repositoryName);
135        } else {
136            builder.repository(session.getRepositoryName());
137        }
138        if (bucketSize > 0) {
139            builder.bucket(bucketSize);
140        }
141        if (batchSize > 0) {
142            builder.batch(batchSize);
143        }
144        String commandId = service.submit(builder.build());
145        return service.getStatus(commandId);
146    }
147}