001/*
002 * (C) Copyright 2006-2014 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 *     Nuxeo - initial API and implementation
018 *
019 */
020package org.nuxeo.connect.client.we;
021
022import java.util.Arrays;
023import java.util.List;
024
025import javax.ws.rs.GET;
026import javax.ws.rs.Path;
027import javax.ws.rs.PathParam;
028import javax.ws.rs.Produces;
029import javax.ws.rs.QueryParam;
030import javax.ws.rs.core.MediaType;
031
032import org.apache.commons.logging.Log;
033import org.apache.commons.logging.LogFactory;
034import org.nuxeo.connect.connector.ConnectServerError;
035import org.nuxeo.connect.data.DownloadablePackage;
036import org.nuxeo.connect.data.DownloadingPackage;
037import org.nuxeo.connect.downloads.ConnectDownloadManager;
038import org.nuxeo.connect.packages.PackageManager;
039import org.nuxeo.connect.update.PackageState;
040import org.nuxeo.ecm.webengine.model.WebObject;
041import org.nuxeo.ecm.webengine.model.impl.DefaultObject;
042import org.nuxeo.runtime.api.Framework;
043
044/**
045 * Provides REST binding for {@link org.nuxeo.connect.update.Package} download management.
046 *
047 * @author <a href="mailto:td@nuxeo.com">Thierry Delprat</a>
048 */
049@WebObject(type = "downloadHandler")
050public class DownloadHandler extends DefaultObject {
051
052    protected static final Log log = LogFactory.getLog(DownloadHandler.class);
053
054    @GET
055    @Produces("text/plain")
056    @Path(value = "progress/{pkgId}")
057    public String getDownloadProgress(@PathParam("pkgId") String pkgId) {
058        DownloadingPackage pkg = getDownloadingPackage(pkgId);
059        if (pkg == null) {
060            return null;
061        }
062        return pkg.getDownloadProgress() + "";
063    }
064
065    @GET
066    @Produces(MediaType.APPLICATION_JSON)
067    @Path(value = "progressAsJSON")
068    public String getDownloadsProgress() {
069        ConnectDownloadManager cdm = Framework.getService(ConnectDownloadManager.class);
070        List<DownloadingPackage> pkgs = cdm.listDownloadingPackages();
071        StringBuffer sb = new StringBuffer();
072        sb.append("[");
073        for (int i = 0; i < pkgs.size(); i++) {
074            if (i > 0) {
075                sb.append(",");
076            }
077            sb.append("{ \"pkgid\" : ");
078            sb.append("\"" + pkgs.get(i).getId() + "\",");
079            sb.append(" \"progress\" : ");
080            sb.append(pkgs.get(i).getDownloadProgress() + "}");
081        }
082        sb.append("]");
083        return sb.toString();
084    }
085
086    @GET
087    @Produces("text/html")
088    @Path(value = "progressPage/{pkgId}")
089    public Object getDownloadProgressPage(@PathParam("pkgId") String pkgId, @QueryParam("source") String source,
090            @QueryParam("install") Boolean install, @QueryParam("depCheck") Boolean depCheck,
091            @QueryParam("type") String pkgType, @QueryParam("onlyRemote") Boolean onlyRemote,
092            @QueryParam("filterOnPlatform") Boolean filterOnPlatform) {
093        DownloadablePackage pkg = getDownloadingPackage(pkgId);
094        boolean downloadOver = false;
095        // flag to start install after download
096        if (install == null) {
097            install = false;
098        }
099        if (depCheck == null) {
100            depCheck = true;
101        }
102        if (pkg == null) {
103            PackageManager pm = Framework.getService(PackageManager.class);
104            pkg = pm.getPackage(pkgId);
105            if (pkg.getPackageState() != PackageState.DOWNLOADING) {
106                downloadOver = true;
107            }
108        }
109        return getView("downloadStarted").arg("pkg", pkg).arg("source", source).arg("over", downloadOver).arg(
110                "install", install).arg("depCheck", depCheck).arg("filterOnPlatform", filterOnPlatform.toString()).arg(
111                "type", pkgType.toString()).arg("onlyRemote", onlyRemote.toString());
112    }
113
114    protected DownloadingPackage getDownloadingPackage(String pkgId) {
115        ConnectDownloadManager cdm = Framework.getService(ConnectDownloadManager.class);
116        List<DownloadingPackage> pkgs = cdm.listDownloadingPackages();
117        for (DownloadingPackage pkg : pkgs) {
118            if (pkg.getId().equals(pkgId)) {
119                return pkg;
120            }
121        }
122        return null;
123    }
124
125    @GET
126    @Produces("text/html")
127    @Path(value = "start/{pkgId}")
128    public Object startDownload(@PathParam("pkgId") String pkgId, @QueryParam("source") String source,
129            @QueryParam("install") Boolean install, @QueryParam("depCheck") Boolean depCheck,
130            @QueryParam("type") String pkgType, @QueryParam("onlyRemote") Boolean onlyRemote,
131            @QueryParam("filterOnPlatform") Boolean filterOnPlatform) {
132        PackageManager pm = Framework.getService(PackageManager.class);
133        // flag to start install after download
134        if (install == null) {
135            install = false;
136        }
137        if (depCheck == null) {
138            depCheck = true;
139        }
140        if (!RequestHelper.isInternalLink(getContext())) {
141            DownloadablePackage pkg = pm.getPackage(pkgId);
142            return getView("confirmDownload").arg("pkg", pkg).arg("source", source);
143        }
144        try {
145            pm.download(pkgId);
146        } catch (ConnectServerError e) {
147            return getView("downloadError").arg("e", e);
148        }
149        return getView("downloadStarted").arg("pkg", getDownloadingPackage(pkgId)).arg("source", source).arg("over",
150                false).arg("install", install).arg("depCheck", depCheck).arg("filterOnPlatform",
151                filterOnPlatform.toString()).arg("type", pkgType.toString()).arg("onlyRemote", onlyRemote.toString());
152    }
153
154    @GET
155    @Produces(MediaType.APPLICATION_JSON)
156    @Path(value = "startDownloads")
157    public String startDownloads(@QueryParam("pkgList") String pkgList) {
158        if (RequestHelper.isInternalLink(getContext())) {
159            if (pkgList != null) {
160                String[] pkgs = pkgList.split("/");
161                PackageManager pm = Framework.getService(PackageManager.class);
162                try {
163                    log.info("Starting download for packages " + Arrays.toString(pkgs));
164                    pm.download(Arrays.asList(pkgs));
165                } catch (ConnectServerError e) {
166                    log.error(e, e);
167                }
168                // here we generate a fake progress report so that if some
169                // download are very fast, they will still be visible on the
170                // client side
171                StringBuffer sb = new StringBuffer();
172                sb.append("[");
173                for (int i = 0; i < pkgs.length; i++) {
174                    if (i > 0) {
175                        sb.append(",");
176                    }
177                    sb.append("{ \"pkgid\" : ");
178                    sb.append("\"" + pkgs[i] + "\",");
179                    sb.append(" \"progress\" : 0}");
180                }
181                sb.append("]");
182                return sb.toString();
183            }
184        }
185        return "[]";
186    }
187
188    /**
189     * @since 5.6
190     */
191    @GET
192    @Path(value = "cancel/{pkgId}")
193    public Object cancelDownload(@PathParam("pkgId") String pkgId, @QueryParam("source") String source) {
194        PackageManager pm = Framework.getService(PackageManager.class);
195        pm.cancelDownload(pkgId);
196        return redirect(getPrevious().getPath() + "/packages/" + source);
197    }
198
199}