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