001/*
002 * Copyright (c) 2014 Nuxeo SA (http://nuxeo.com/) and others.
003 *
004 * All rights reserved. This program and the accompanying materials
005 * are made available under the terms of the Eclipse Public License v1.0
006 * which accompanies this distribution, and is available at
007 * http://www.eclipse.org/legal/epl-v10.html
008 *
009 * Contributors:
010 *     bstefanescu
011 *     vpasquier <vpasquier@nuxeo.com>
012 */
013package org.nuxeo.ecm.automation.server.jaxrs;
014
015import java.io.IOException;
016import java.security.Principal;
017import java.util.HashSet;
018import java.util.List;
019
020import javax.mail.MessagingException;
021import javax.servlet.http.HttpServletRequest;
022import javax.servlet.http.HttpServletResponse;
023import javax.ws.rs.GET;
024import javax.ws.rs.POST;
025import javax.ws.rs.Path;
026import javax.ws.rs.PathParam;
027import javax.ws.rs.QueryParam;
028import javax.ws.rs.core.Context;
029import javax.ws.rs.core.Response;
030
031import org.nuxeo.ecm.automation.AutomationService;
032import org.nuxeo.ecm.automation.ConflictOperationException;
033import org.nuxeo.ecm.automation.OperationException;
034import org.nuxeo.ecm.automation.OperationNotFoundException;
035import org.nuxeo.ecm.automation.OperationType;
036import org.nuxeo.ecm.automation.core.Constants;
037import org.nuxeo.ecm.automation.jaxrs.LoginInfo;
038import org.nuxeo.ecm.automation.jaxrs.io.operations.AutomationInfo;
039import org.nuxeo.ecm.core.api.Blob;
040import org.nuxeo.ecm.core.api.CoreSession;
041import org.nuxeo.ecm.core.api.DocumentModel;
042import org.nuxeo.ecm.core.api.IdRef;
043import org.nuxeo.ecm.core.api.NuxeoPrincipal;
044import org.nuxeo.ecm.core.api.PropertyException;
045import org.nuxeo.ecm.platform.web.common.exceptionhandling.ExceptionHelper;
046import org.nuxeo.ecm.webengine.WebException;
047import org.nuxeo.ecm.webengine.jaxrs.session.SessionFactory;
048import org.nuxeo.ecm.webengine.model.WebObject;
049import org.nuxeo.ecm.webengine.model.impl.ModuleRoot;
050import org.nuxeo.runtime.api.Framework;
051
052/**
053 * @author <a href="mailto:bs@nuxeo.com">Bogdan Stefanescu</a>
054 */
055@Path("/automation")
056@WebObject(type = "automation")
057public class AutomationResource extends ModuleRoot {
058
059    protected AutomationService service;
060
061    public AutomationResource() {
062        this.service = Framework.getLocalService(AutomationService.class);
063    }
064
065    @Path("/doc")
066    public Object getDocPage() {
067        return newObject("doc");
068    }
069
070    @Path("/debug")
071    public Object getDebugPage() {
072        return newObject("debug");
073    }
074
075    /**
076     * Gets the content of the blob or blobs (multipart/mixed) located by the given doc uid and property path.
077     */
078    @SuppressWarnings("unchecked")
079    @GET
080    @Path("/files/{uid}")
081    public Object getFile(@Context HttpServletRequest request, @PathParam("uid") String uid,
082            @QueryParam("path") String path) {
083        try {
084            CoreSession session = SessionFactory.getSession(request);
085            DocumentModel doc = session.getDocument(new IdRef(uid));
086            Object obj = null;
087            try {
088                obj = doc.getPropertyValue(path);
089            } catch (PropertyException e) {
090                return ResponseHelper.notFound();
091            }
092            if (obj == null) {
093                return ResponseHelper.notFound();
094            }
095            if (obj instanceof List<?>) {
096                List<?> list = (List<?>) obj;
097                if (list.isEmpty()) {
098                    return ResponseHelper.notFound();
099                }
100                if (list.get(0) instanceof Blob) { // a list of blobs -> use
101                    // multipart/mixed
102                    return ResponseHelper.blobs((List<Blob>) list);
103                }
104            } else if (obj instanceof Blob) {
105                return ResponseHelper.blob((Blob) obj);
106            }
107            return ResponseHelper.notFound();
108        } catch (MessagingException | IOException e) {
109            throw WebException.newException(e);
110        }
111    }
112
113    @GET
114    public AutomationInfo doGet() throws OperationException {
115        return new AutomationInfo(service);
116    }
117
118    @POST
119    @Path("/login")
120    public Object login(@Context HttpServletRequest request) {
121        Principal p = request.getUserPrincipal();
122        if (p instanceof NuxeoPrincipal) {
123            NuxeoPrincipal np = (NuxeoPrincipal) p;
124            List<String> groups = np.getAllGroups();
125            HashSet<String> set = new HashSet<String>(groups);
126            return new LoginInfo(np.getName(), set, np.isAdministrator());
127        } else {
128            return Response.status(401).build();
129        }
130    }
131
132    @Path("/{oid}")
133    public Object getExecutable(@PathParam("oid") String oid) {
134        if (oid.startsWith(Constants.CHAIN_ID_PREFIX)) {
135            oid = oid.substring(6);
136            return new ChainResource(service, oid);
137        } else {
138            try {
139                OperationType op = service.getOperation(oid);
140                return new OperationResource(service, op);
141            } catch (OperationException cause) {
142                if (cause instanceof ConflictOperationException) {
143                    return WebException.newException("Failed to invoke operation: " + oid, cause,
144                            HttpServletResponse.SC_CONFLICT);
145                } else if (cause instanceof OperationNotFoundException) {
146                    return WebException.newException("Failed to invoke " + "operation: " + oid, cause,
147                            HttpServletResponse.SC_NOT_FOUND);
148                } else {
149                    Throwable unWrapException = ExceptionHelper.unwrapException(cause);
150                    if (unWrapException instanceof RestOperationException) {
151                        int customHttpStatus = ((RestOperationException) unWrapException).getStatus();
152                        throw WebException.newException("Failed to invoke operation: " + oid, cause, customHttpStatus);
153                    }
154                    throw WebException.newException("Failed to invoke operation: " + oid, cause);
155                }
156            }
157        }
158    }
159
160    @Path("/batch")
161    public Object getBatchManager() {
162        return newObject("batch");
163    }
164
165}