001/*
002 * (C) Copyright 2013 Nuxeo SA (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 *     dmetzler
018 */
019package org.nuxeo.ecm.restapi.server.jaxrs.adapters;
020
021import javax.servlet.http.HttpServletRequest;
022import javax.servlet.http.HttpServletResponse;
023import javax.ws.rs.POST;
024import javax.ws.rs.Path;
025import javax.ws.rs.PathParam;
026import javax.ws.rs.Produces;
027import javax.ws.rs.core.Context;
028import javax.ws.rs.core.MediaType;
029import javax.ws.rs.core.Response;
030
031import org.nuxeo.ecm.automation.AutomationService;
032import org.nuxeo.ecm.automation.OperationChain;
033import org.nuxeo.ecm.automation.OperationContext;
034import org.nuxeo.ecm.automation.OperationException;
035import org.nuxeo.ecm.automation.OperationType;
036import org.nuxeo.ecm.automation.core.impl.ChainTypeImpl;
037import org.nuxeo.ecm.automation.core.impl.InvokableMethod;
038import org.nuxeo.ecm.automation.jaxrs.io.operations.ExecutionRequest;
039import org.nuxeo.ecm.automation.server.AutomationServer;
040import org.nuxeo.ecm.automation.server.jaxrs.ResponseHelper;
041import org.nuxeo.ecm.automation.server.jaxrs.RestOperationException;
042import org.nuxeo.ecm.core.api.NuxeoException;
043import org.nuxeo.ecm.platform.web.common.exceptionhandling.ExceptionHelper;
044import org.nuxeo.ecm.webengine.model.WebAdapter;
045import org.nuxeo.ecm.webengine.model.impl.DefaultAdapter;
046import org.nuxeo.runtime.api.Framework;
047
048/**
049 * @since 5.7.2 - Web adapter that expose how to run an operation on a document
050 */
051@WebAdapter(name = OperationAdapter.NAME, type = "OperationService")
052@Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_JSON + "+esentity" })
053public class OperationAdapter extends DefaultAdapter {
054
055    public static final String NAME = "op";
056
057    @POST
058    @Path("{operationName}")
059    public Response doPost(@PathParam("operationName") String oid, @Context HttpServletRequest request,
060            @Context HttpServletResponse response, ExecutionRequest xreq) {
061        try {
062            AutomationServer srv = Framework.getService(AutomationServer.class);
063            if (!srv.accept(oid, false, request)) {
064                return ResponseHelper.notFound();
065            }
066
067            AutomationService service = Framework.getService(AutomationService.class);
068
069            OperationType operationType = service.getOperation(oid);
070
071            // If chain, taking the first operation to do the input lookup after
072            if (operationType instanceof ChainTypeImpl) {
073                OperationChain chain = ((ChainTypeImpl) operationType).getChain();
074                if (!chain.getOperations().isEmpty()) {
075                    operationType = service.getOperation(chain.getOperations().get(0).id());
076                } else {
077                    throw new NuxeoException("Chain '" + oid + "' doesn't contain any operation");
078                }
079            }
080
081            for (InvokableMethod method : operationType.getMethods()) {
082                if (getTarget().getAdapter(method.getInputType()) != null) {
083                    xreq.setInput(getTarget().getAdapter(method.getInputType()));
084                    break;
085                }
086            }
087
088            OperationContext ctx = xreq.createContext(request, response, getContext().getCoreSession());
089            Object result = service.run(ctx, oid, xreq.getParams());
090
091            int customHttpStatus = xreq.getRestOperationContext().getHttpStatus();
092            return Response.status(customHttpStatus).entity(result).build();
093        } catch (OperationException cause) {
094            if (ExceptionHelper.unwrapException(cause) instanceof RestOperationException) {
095                int customHttpStatus = ((RestOperationException) ExceptionHelper.unwrapException(cause)).getStatus();
096                throw new NuxeoException("Failed to invoke operation: " + oid, cause, customHttpStatus);
097            }
098            throw new NuxeoException("Failed to invoke operation: " + oid, cause);
099        }
100
101    }
102
103}