001/* 002 * (C) Copyright 2006-2012 Nuxeo SA (http://nuxeo.com/) and contributors. 003 * 004 * All rights reserved. This program and the accompanying materials 005 * are made available under the terms of the GNU Lesser General Public License 006 * (LGPL) version 2.1 which accompanies this distribution, and is available at 007 * http://www.gnu.org/licenses/lgpl.html 008 * 009 * This library is distributed in the hope that it will be useful, 010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 012 * Lesser General Public License for more details. 013 * 014 * Contributors: 015 * Nuxeo - initial API and implementation 016 * 017 */ 018package org.nuxeo.connect.client.we; 019 020import java.util.List; 021 022import javax.ws.rs.GET; 023import javax.ws.rs.POST; 024import javax.ws.rs.Path; 025import javax.ws.rs.PathParam; 026import javax.ws.rs.Produces; 027import javax.ws.rs.QueryParam; 028import javax.ws.rs.core.Response; 029 030import org.apache.commons.logging.Log; 031import org.apache.commons.logging.LogFactory; 032import org.nuxeo.connect.client.vindoz.InstallAfterRestart; 033import org.nuxeo.connect.data.DownloadablePackage; 034import org.nuxeo.connect.packages.PackageManager; 035import org.nuxeo.connect.update.LocalPackage; 036import org.nuxeo.connect.update.Package; 037import org.nuxeo.connect.update.PackageException; 038import org.nuxeo.connect.update.PackageUpdateService; 039import org.nuxeo.connect.update.ValidationStatus; 040import org.nuxeo.connect.update.task.Task; 041import org.nuxeo.connect.update.task.standalone.UninstallTask; 042import org.nuxeo.ecm.admin.runtime.PlatformVersionHelper; 043import org.nuxeo.ecm.webengine.WebException; 044import org.nuxeo.ecm.webengine.model.WebObject; 045import org.nuxeo.ecm.webengine.model.impl.DefaultObject; 046import org.nuxeo.runtime.api.Framework; 047 048/** 049 * Provides REST bindings for {@link Package} install management. 050 * 051 * @author <a href="mailto:td@nuxeo.com">Thierry Delprat</a> 052 */ 053@WebObject(type = "uninstallHandler") 054public class UninstallHandler extends DefaultObject { 055 056 protected static final Log log = LogFactory.getLog(UninstallHandler.class); 057 058 @GET 059 @Produces("text/html") 060 @Path(value = "start/{pkgId}") 061 public Object startUninstall(@PathParam("pkgId") String pkgId, @QueryParam("source") String source, 062 @QueryParam("filterOnPlatform") Boolean filterOnPlatform) { 063 try { 064 PackageUpdateService pus = Framework.getLocalService(PackageUpdateService.class); 065 LocalPackage pkg = pus.getPackage(pkgId); 066 Task uninstallTask = pkg.getUninstallTask(); 067 ValidationStatus status = uninstallTask.validate(); 068 if (status.hasErrors()) { 069 return getView("canNotUninstall").arg("status", status).arg("pkg", pkg).arg("source", source); 070 } 071 PackageManager pm = Framework.getLocalService(PackageManager.class); 072 List<DownloadablePackage> pkgToRemove = pm.getUninstallDependencies(pkg, 073 getTargetPlatform(filterOnPlatform)); 074 if (pkgToRemove.size() > 0) { 075 return getView("displayDependencies").arg("pkg", pkg).arg("pkgToRemove", pkgToRemove).arg("source", 076 source); 077 } 078 return getView("startUninstall").arg("status", status).arg("uninstallTask", uninstallTask).arg("pkg", pkg).arg( 079 "source", source); 080 } catch (PackageException e) { 081 log.error("Error during first step of installation", e); 082 return getView("uninstallError").arg("e", e); 083 } 084 } 085 086 /** 087 * @param filterOnPlatform 088 * @return 089 */ 090 private String getTargetPlatform(Boolean filterOnPlatform) { 091 if (filterOnPlatform != Boolean.TRUE) { 092 return null; 093 } 094 return PlatformVersionHelper.getPlatformFilter(); 095 } 096 097 @GET 098 @Produces("text/html") 099 @Path(value = "run/{pkgId}") 100 public Object doUninstall(@PathParam("pkgId") String pkgId, @QueryParam("source") String source, 101 @QueryParam("filterOnPlatform") Boolean filterOnPlatform) { 102 PackageUpdateService pus = Framework.getLocalService(PackageUpdateService.class); 103 try { 104 LocalPackage pkg = pus.getPackage(pkgId); 105 PackageManager pm = Framework.getLocalService(PackageManager.class); 106 List<DownloadablePackage> pkgToRemove = pm.getUninstallDependencies(pkg, 107 getTargetPlatform(filterOnPlatform)); 108 boolean restartRequired = InstallAfterRestart.isNeededForPackage(pkg); 109 if (!restartRequired) { 110 for (DownloadablePackage rpkg : pkgToRemove) { 111 if (InstallAfterRestart.isNeededForPackage(rpkg)) { 112 restartRequired = true; 113 break; 114 } 115 } 116 } 117 if (restartRequired) { 118 InstallAfterRestart.addPackageForUnInstallation(pkg.getName()); 119 return getView("uninstallOnRestart").arg("pkg", pkg).arg("source", source); 120 } else { 121 log.debug("Uninstalling: " + pkgToRemove); 122 Task uninstallTask; 123 for (DownloadablePackage rpkg : pkgToRemove) { 124 LocalPackage localPackage = pus.getPackage(rpkg.getId()); 125 performUninstall(localPackage); 126 } 127 uninstallTask = performUninstall(pkg); 128 return getView("uninstallDone").arg("uninstallTask", uninstallTask).arg("pkg", pkg).arg("source", 129 source); 130 } 131 } catch (PackageException e) { 132 log.error("Error during uninstall of " + pkgId, e); 133 return getView("uninstallError").arg("e", e).arg("source", source); 134 } 135 } 136 137 /** 138 * Run UninstallTask of given local package 139 * 140 * @since 5.6 141 * @param localPackage Package to uninstall 142 * @return {@link UninstallTask} of {@code localPackage} 143 * @throws PackageException If uninstall fails. A rollback is done before the exception is raised. 144 */ 145 protected Task performUninstall(LocalPackage localPackage) throws PackageException { 146 log.info("Uninstalling " + localPackage.getId()); 147 Task uninstallTask = localPackage.getUninstallTask(); 148 try { 149 uninstallTask.run(null); 150 } catch (PackageException e) { 151 log.error("Error during uninstall of " + localPackage.getId(), e); 152 uninstallTask.rollback(); 153 throw e; 154 } 155 return uninstallTask; 156 } 157 158 @POST 159 @Path("restart") 160 public Object restartServer() { 161 PackageUpdateService pus = Framework.getLocalService(PackageUpdateService.class); 162 try { 163 pus.restart(); 164 } catch (PackageException e) { 165 throw WebException.wrap(e); 166 } 167 // TODO create a page that waits for the server to restart 168 return Response.ok().build(); 169 } 170 171}