001/*
002 * (C) Copyright 2006-2016 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 */
019package org.nuxeo.connect.client.we;
020
021import java.util.List;
022
023import javax.ws.rs.GET;
024import javax.ws.rs.Path;
025import javax.ws.rs.PathParam;
026import javax.ws.rs.Produces;
027import javax.ws.rs.QueryParam;
028
029import org.apache.commons.lang3.StringUtils;
030import org.nuxeo.connect.client.status.ConnectStatusHolder;
031import org.nuxeo.connect.client.ui.SharedPackageListingsSettings;
032import org.nuxeo.connect.client.vindoz.InstallAfterRestart;
033import org.nuxeo.connect.connector.http.ConnectUrlConfig;
034import org.nuxeo.connect.data.DownloadablePackage;
035import org.nuxeo.connect.data.DownloadingPackage;
036import org.nuxeo.connect.data.SubscriptionStatusType;
037import org.nuxeo.connect.packages.PackageManager;
038import org.nuxeo.connect.platform.PlatformId;
039import org.nuxeo.connect.update.Package;
040import org.nuxeo.connect.update.PackageState;
041import org.nuxeo.connect.update.PackageType;
042import org.nuxeo.ecm.admin.runtime.PlatformVersionHelper;
043import org.nuxeo.ecm.webengine.model.WebObject;
044import org.nuxeo.ecm.webengine.model.impl.DefaultObject;
045import org.nuxeo.runtime.api.Framework;
046
047/**
048 * Provides REST binding for {@link Package} listings.
049 *
050 * @author <a href="mailto:td@nuxeo.com">Thierry Delprat</a>
051 */
052@WebObject(type = "packageListingProvider")
053public class PackageListingProvider extends DefaultObject {
054
055    public String getConnectBaseUrl() {
056        return ConnectUrlConfig.getBaseUrl();
057    }
058
059    @GET
060    @Produces("text/html")
061    @Path(value = "list")
062    public Object doList(@QueryParam("type") String pkgType, @QueryParam("filterOnPlatform") Boolean filterOnPlatform) {
063        PackageManager pm = Framework.getService(PackageManager.class);
064        PlatformId targetPlatform = getTargetPlatform(filterOnPlatform);
065        List<DownloadablePackage> pkgs;
066        if (StringUtils.isBlank(pkgType)) {
067            pkgs = pm.listPackages(targetPlatform);
068        } else {
069            pkgs = pm.listPackages(PackageType.getByValue(pkgType), targetPlatform);
070        }
071        return getView("simpleListing").arg("pkgs", pm.sort(pkgs))
072                                       .arg("showCommunityInfo", true)
073                                       .arg("source", "list")
074                                       .arg("filterOnPlatform", filterOnPlatform);
075    }
076
077    @GET
078    @Produces("text/html")
079    @Path(value = "updates")
080    public Object getUpdates(@QueryParam("type") String pkgType,
081            @QueryParam("filterOnPlatform") Boolean filterOnPlatform) {
082        PackageManager pm = Framework.getService(PackageManager.class);
083        if (pkgType == null) {
084            pkgType = SharedPackageListingsSettings.instance().get("updates").getPackageTypeFilter();
085        }
086        if (filterOnPlatform == null) {
087            filterOnPlatform = SharedPackageListingsSettings.instance().get("updates").getPlatformFilter();
088        }
089        PlatformId targetPlatform = getTargetPlatform(filterOnPlatform);
090        List<DownloadablePackage> pkgs;
091        if (StringUtils.isBlank(pkgType)) {
092            pkgs = pm.listUpdatePackages(null, targetPlatform);
093        } else {
094            pkgs = pm.listUpdatePackages(PackageType.getByValue(pkgType), targetPlatform);
095        }
096        return getView("simpleListing").arg("pkgs", pm.sort(pkgs))
097                                       .arg("showCommunityInfo", true)
098                                       .arg("source", "updates")
099                                       .arg("filterOnPlatform", filterOnPlatform);
100    }
101
102    @GET
103    @Produces("text/html")
104    @Path(value = "private")
105    public Object getPrivate(@QueryParam("type") String pkgType,
106            @QueryParam("filterOnPlatform") Boolean filterOnPlatform) {
107        PackageManager pm = Framework.getService(PackageManager.class);
108        if (pkgType == null) {
109            pkgType = SharedPackageListingsSettings.instance().get("private").getPackageTypeFilter();
110        }
111        if (filterOnPlatform == null) {
112            filterOnPlatform = SharedPackageListingsSettings.instance().get("private").getPlatformFilter();
113        }
114        PlatformId targetPlatform = getTargetPlatform(filterOnPlatform);
115        List<DownloadablePackage> pkgs;
116        if (StringUtils.isBlank(pkgType)) {
117            pkgs = pm.listPrivatePackages(targetPlatform);
118        } else {
119            pkgs = pm.listPrivatePackages(PackageType.getByValue(pkgType), targetPlatform);
120        }
121        return getView("simpleListing").arg("pkgs", pm.sort(pkgs))
122                                       .arg("showCommunityInfo", true)
123                                       .arg("source", "private")
124                                       .arg("filterOnPlatform", filterOnPlatform);
125    }
126
127    @GET
128    @Produces("text/html")
129    @Path(value = "local")
130    public Object getLocal(@QueryParam("type") String pkgType) {
131        PackageManager pm = Framework.getService(PackageManager.class);
132        if (pkgType == null) {
133            pkgType = SharedPackageListingsSettings.instance().get("local").getPackageTypeFilter();
134        }
135        List<DownloadablePackage> pkgs;
136        if (StringUtils.isBlank(pkgType)) {
137            pkgs = pm.listLocalPackages();
138        } else {
139            pkgs = pm.listLocalPackages(PackageType.getByValue(pkgType));
140        }
141        return getView("simpleListing").arg("pkgs", pm.sort(pkgs))
142                                       .arg("showCommunityInfo", false)
143                                       .arg("source", "local");
144    }
145
146    @GET
147    @Produces("text/html")
148    @Path(value = "remote")
149    public Object getRemote(@QueryParam("type") String pkgType, @QueryParam("onlyRemote") Boolean onlyRemote,
150            @QueryParam("searchString") String searchString, @QueryParam("filterOnPlatform") Boolean filterOnPlatform) {
151        PackageManager pm = Framework.getService(PackageManager.class);
152        if (pkgType == null) {
153            pkgType = SharedPackageListingsSettings.instance().get("remote").getPackageTypeFilter();
154        }
155        if (filterOnPlatform == null) {
156            filterOnPlatform = SharedPackageListingsSettings.instance().get("remote").getPlatformFilter();
157        }
158        if (onlyRemote == null) {
159            onlyRemote = SharedPackageListingsSettings.instance().get("remote").isOnlyRemote();
160        }
161        List<DownloadablePackage> pkgs;
162        PlatformId targetPlatform = getTargetPlatform(filterOnPlatform);
163        if (!StringUtils.isEmpty(searchString)) { // SEARCH IS NOT IMPLEMENTED
164            pkgs = pm.searchPackages(searchString);
165        } else if (onlyRemote) {
166            if (StringUtils.isBlank(pkgType)) {
167                pkgs = pm.listOnlyRemotePackages(targetPlatform);
168            } else {
169                pkgs = pm.listOnlyRemotePackages(PackageType.getByValue(pkgType), targetPlatform);
170            }
171        } else {
172            if (StringUtils.isBlank(pkgType)) {
173                pkgs = pm.listRemoteOrLocalPackages(targetPlatform);
174            } else {
175                pkgs = pm.listRemoteOrLocalPackages(PackageType.getByValue(pkgType), targetPlatform);
176            }
177        }
178        return getView("simpleListing").arg("pkgs", pm.sort(pkgs))
179                                       .arg("showCommunityInfo", false)
180                                       .arg("source", "remote")
181                                       .arg("filterOnPlatform", filterOnPlatform.toString())
182                                       .arg("type", pkgType)
183                                       .arg("onlyRemote", onlyRemote.toString());
184    }
185
186    /**
187     * @return target platform if {@code filterOnPlatform==true} else null
188     * @since 5.6
189     */
190    private PlatformId getTargetPlatform(Boolean filterOnPlatform) {
191        if (filterOnPlatform != Boolean.TRUE) {
192            return null;
193        }
194        return PlatformVersionHelper.getPlatformId();
195    }
196
197    @GET
198    @Produces("text/html")
199    @Path(value = "studio")
200    public Object getStudio() {
201        PackageManager pm = Framework.getService(PackageManager.class);
202        List<DownloadablePackage> pkgs = pm.listAllStudioRemoteOrLocalPackages();
203        List<DownloadablePackage> pkgsWithoutSnapshot = StudioSnapshotHelper.removeSnapshot(pkgs);
204        return getView("simpleListing").arg("pkgs", pm.sort(pkgsWithoutSnapshot))
205                                       .arg("showCommunityInfo", false)
206                                       .arg("source", "studio");
207    }
208
209    public String getStateLabel(Package pkg) {
210        PackageState state = pkg.getPackageState();
211        switch (state) {
212        case REMOTE:
213        case DOWNLOADED:
214        case INSTALLED:
215            return state.getLabel();
216        case DOWNLOADING:
217            DownloadingPackage dpkg = (DownloadingPackage) pkg;
218            return state.getLabel() + " (" + dpkg.getDownloadProgress() + "%)";
219        case INSTALLING:
220            return "installation in progress";
221        case STARTED:
222            return "running";
223        case UNKNOWN:
224        default:
225            return "!?!";
226        }
227    }
228
229    public boolean canInstall(Package pkg) {
230        return PackageState.DOWNLOADED == pkg.getPackageState()
231                && !InstallAfterRestart.isMarkedForInstallAfterRestart(pkg.getId());
232    }
233
234    public boolean needsRestart(Package pkg) {
235        return InstallAfterRestart.isMarkedForInstallAfterRestart(pkg.getId())
236                || PackageState.INSTALLED == pkg.getPackageState()
237                || InstallAfterRestart.isMarkedForUninstallAfterRestart(pkg.getName());
238    }
239
240    public boolean canUnInstall(Package pkg) {
241        return pkg.getPackageState().isInstalled()
242                && !InstallAfterRestart.isMarkedForUninstallAfterRestart(pkg.getName());
243    }
244
245    /**
246     * @since 5.8
247     */
248    public boolean canUpgrade(Package pkg) {
249        return pkg.getPackageState().isInstalled() && pkg.getVersion().isSnapshot()
250                && !InstallAfterRestart.isMarkedForInstallAfterRestart(pkg.getName());
251    }
252
253    public boolean canRemove(Package pkg) {
254        return pkg.isLocal();
255    }
256
257    /**
258     * @since 5.6
259     */
260    public boolean canCancel(Package pkg) {
261        return PackageState.DOWNLOADING == pkg.getPackageState();
262    }
263
264    /**
265     * @since 11.1
266     */
267    public boolean canDownload(DownloadablePackage pkg) {
268        return pkg.getPackageState() == PackageState.REMOTE && (!pkg.hasSubscriptionRequired() //
269                || (ConnectStatusHolder.instance().isRegistred() //
270                        && ConnectStatusHolder.instance().getStatus().status() == SubscriptionStatusType.OK));
271    }
272
273    @GET
274    @Produces("text/html")
275    @Path(value = "details/{pkgId}")
276    public Object getDetails(@PathParam("pkgId") String pkgId) {
277        PackageManager pm = Framework.getService(PackageManager.class);
278        DownloadablePackage pkg = pm.getPackage(pkgId);
279        if (pkg != null) {
280            return getView("pkgDetails").arg("pkg", pkg);
281        } else {
282            return getView("pkgNotFound").arg("pkgId", pkgId);
283        }
284    }
285
286    /**
287     * @since 11.1
288     * @return true if registration is required for download
289     */
290    public boolean registrationRequired(DownloadablePackage pkg) {
291        return pkg.getPackageState() == PackageState.REMOTE && pkg.hasSubscriptionRequired()
292                && (!ConnectStatusHolder.instance().isRegistred() //
293                        || ConnectStatusHolder.instance().getStatus().status() != SubscriptionStatusType.OK);
294    }
295
296}