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        StringBuilder sb = new StringBuilder();
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              .append("\"")
079              .append(pkgs.get(i).getId())
080              .append("\",")
081              .append(" \"progress\" : ")
082              .append(pkgs.get(i).getDownloadProgress())
083              .append("}");
084        }
085        sb.append("]");
086        return sb.toString();
087    }
088
089    @GET
090    @Produces("text/html")
091    @Path(value = "progressPage/{pkgId}")
092    public Object getDownloadProgressPage(@PathParam("pkgId") String pkgId, @QueryParam("source") String source,
093            @QueryParam("install") Boolean install, @QueryParam("depCheck") Boolean depCheck,
094            @QueryParam("type") String pkgType, @QueryParam("onlyRemote") Boolean onlyRemote,
095            @QueryParam("filterOnPlatform") Boolean filterOnPlatform) {
096        DownloadablePackage pkg = getDownloadingPackage(pkgId);
097        boolean downloadOver = false;
098        // flag to start install after download
099        if (install == null) {
100            install = false;
101        }
102        if (depCheck == null) {
103            depCheck = true;
104        }
105        if (pkg == null) {
106            PackageManager pm = Framework.getService(PackageManager.class);
107            pkg = pm.getPackage(pkgId);
108            if (pkg.getPackageState() != PackageState.DOWNLOADING) {
109                downloadOver = true;
110            }
111        }
112        return getView("downloadStarted").arg("pkg", pkg)
113                                         .arg("source", source)
114                                         .arg("over", downloadOver)
115                                         .arg("install", install)
116                                         .arg("depCheck", depCheck)
117                                         .arg("filterOnPlatform", filterOnPlatform.toString())
118                                         .arg("type", pkgType.toString())
119                                         .arg("onlyRemote", onlyRemote.toString());
120    }
121
122    protected DownloadingPackage getDownloadingPackage(String pkgId) {
123        ConnectDownloadManager cdm = Framework.getService(ConnectDownloadManager.class);
124        List<DownloadingPackage> pkgs = cdm.listDownloadingPackages();
125        for (DownloadingPackage pkg : pkgs) {
126            if (pkg.getId().equals(pkgId)) {
127                return pkg;
128            }
129        }
130        return null;
131    }
132
133    @GET
134    @Produces("text/html")
135    @Path(value = "start/{pkgId}")
136    public Object startDownload(@PathParam("pkgId") String pkgId, @QueryParam("source") String source,
137            @QueryParam("install") Boolean install, @QueryParam("depCheck") Boolean depCheck,
138            @QueryParam("type") String pkgType, @QueryParam("onlyRemote") Boolean onlyRemote,
139            @QueryParam("filterOnPlatform") Boolean filterOnPlatform) {
140        PackageManager pm = Framework.getService(PackageManager.class);
141        // flag to start install after download
142        if (install == null) {
143            install = false;
144        }
145        if (depCheck == null) {
146            depCheck = true;
147        }
148        if (!RequestHelper.isInternalLink(getContext())) {
149            DownloadablePackage pkg = pm.getPackage(pkgId);
150            return getView("confirmDownload").arg("pkg", pkg).arg("source", source);
151        }
152        try {
153            pm.download(pkgId);
154        } catch (ConnectServerError e) {
155            return getView("downloadError").arg("e", e);
156        }
157        return getView("downloadStarted").arg("pkg", getDownloadingPackage(pkgId))
158                                         .arg("source", source)
159                                         .arg("over", false)
160                                         .arg("install", install)
161                                         .arg("depCheck", depCheck)
162                                         .arg("filterOnPlatform", filterOnPlatform.toString())
163                                         .arg("type", pkgType.toString())
164                                         .arg("onlyRemote", onlyRemote.toString());
165    }
166
167    @GET
168    @Produces(MediaType.APPLICATION_JSON)
169    @Path(value = "startDownloads")
170    public String startDownloads(@QueryParam("pkgList") String pkgList) {
171        if (RequestHelper.isInternalLink(getContext())) {
172            if (pkgList != null) {
173                String[] pkgs = pkgList.split("/");
174                PackageManager pm = Framework.getService(PackageManager.class);
175                try {
176                    log.info("Starting download for packages " + Arrays.toString(pkgs));
177                    pm.download(Arrays.asList(pkgs));
178                } catch (ConnectServerError e) {
179                    log.error(e, e);
180                }
181                // here we generate a fake progress report so that if some
182                // download are very fast, they will still be visible on the
183                // client side
184                StringBuilder sb = new StringBuilder();
185                sb.append("[");
186                for (int i = 0; i < pkgs.length; i++) {
187                    if (i > 0) {
188                        sb.append(",");
189                    }
190                    sb.append("{ \"pkgid\" : ")
191                      .append("\"")
192                      .append(pkgs[i])
193                      .append("\",")
194                      .append(" \"progress\" : 0}");
195                }
196                sb.append("]");
197                return sb.toString();
198            }
199        }
200        return "[]";
201    }
202
203    /**
204     * @since 5.6
205     */
206    @GET
207    @Path(value = "cancel/{pkgId}")
208    public Object cancelDownload(@PathParam("pkgId") String pkgId, @QueryParam("source") String source) {
209        PackageManager pm = Framework.getService(PackageManager.class);
210        pm.cancelDownload(pkgId);
211        return redirect(getPrevious().getPath() + "/packages/" + source);
212    }
213
214}