1   /**
2    * Copyright (c) 2000-2007 Liferay, Inc. All rights reserved.
3    *
4    * Permission is hereby granted, free of charge, to any person obtaining a copy
5    * of this software and associated documentation files (the "Software"), to deal
6    * in the Software without restriction, including without limitation the rights
7    * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8    * copies of the Software, and to permit persons to whom the Software is
9    * furnished to do so, subject to the following conditions:
10   *
11   * The above copyright notice and this permission notice shall be included in
12   * all copies or substantial portions of the Software.
13   *
14   * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15   * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16   * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17   * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18   * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19   * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20   * SOFTWARE.
21   */
22  
23  package com.liferay.portlet.plugininstaller.action;
24  
25  import com.liferay.portal.events.GlobalStartupAction;
26  import com.liferay.portal.kernel.deploy.auto.AutoDeployDir;
27  import com.liferay.portal.kernel.deploy.auto.AutoDeployUtil;
28  import com.liferay.portal.kernel.security.permission.PermissionChecker;
29  import com.liferay.portal.kernel.util.ArrayUtil;
30  import com.liferay.portal.kernel.util.Constants;
31  import com.liferay.portal.kernel.util.GetterUtil;
32  import com.liferay.portal.kernel.util.ParamUtil;
33  import com.liferay.portal.kernel.util.StringMaker;
34  import com.liferay.portal.kernel.util.StringPool;
35  import com.liferay.portal.kernel.util.StringUtil;
36  import com.liferay.portal.kernel.util.Validator;
37  import com.liferay.portal.plugin.PluginPackageUtil;
38  import com.liferay.portal.plugin.RepositoryReport;
39  import com.liferay.portal.security.auth.PrincipalException;
40  import com.liferay.portal.struts.PortletAction;
41  import com.liferay.portal.theme.ThemeDisplay;
42  import com.liferay.portal.tools.BaseDeployer;
43  import com.liferay.portal.util.PortalUtil;
44  import com.liferay.portal.util.PrefsPropsUtil;
45  import com.liferay.portal.util.PropsUtil;
46  import com.liferay.portal.util.WebKeys;
47  import com.liferay.util.FileUtil;
48  import com.liferay.util.Http;
49  import com.liferay.util.servlet.ProgressInputStream;
50  import com.liferay.util.servlet.SessionErrors;
51  import com.liferay.util.servlet.SessionMessages;
52  import com.liferay.util.servlet.UploadException;
53  import com.liferay.util.servlet.UploadPortletRequest;
54  
55  import java.io.File;
56  import java.io.FileOutputStream;
57  import java.io.IOException;
58  
59  import java.net.MalformedURLException;
60  import java.net.URL;
61  
62  import java.util.List;
63  
64  import javax.portlet.ActionRequest;
65  import javax.portlet.ActionResponse;
66  import javax.portlet.PortletConfig;
67  import javax.portlet.PortletPreferences;
68  
69  import org.apache.commons.httpclient.HostConfiguration;
70  import org.apache.commons.httpclient.HttpClient;
71  import org.apache.commons.httpclient.methods.GetMethod;
72  import org.apache.commons.logging.Log;
73  import org.apache.commons.logging.LogFactory;
74  import org.apache.struts.action.ActionForm;
75  import org.apache.struts.action.ActionMapping;
76  
77  /**
78   * <a href="InstallPluginAction.java.html"><b><i>View Source</i></b></a>
79   *
80   * @author Jorge Ferrer
81   *
82   */
83  public class InstallPluginAction extends PortletAction {
84  
85      public void processAction(
86              ActionMapping mapping, ActionForm form, PortletConfig config,
87              ActionRequest req, ActionResponse res)
88          throws Exception {
89  
90          ThemeDisplay themeDisplay =
91              (ThemeDisplay)req.getAttribute(WebKeys.THEME_DISPLAY);
92  
93          PermissionChecker permissionChecker =
94              themeDisplay.getPermissionChecker();
95  
96          if (!permissionChecker.isOmniadmin()) {
97              SessionErrors.add(req, PrincipalException.class.getName());
98  
99              setForward(req, "portlet.plugin_installer.error");
100 
101             return;
102         }
103 
104         String cmd = ParamUtil.getString(req, Constants.CMD);
105 
106         if (cmd.equals("deployConfiguration")) {
107             deployConfiguration(req);
108         }
109         else if (cmd.equals("ignorePackages")) {
110             ignorePackages(req);
111         }
112         else if (cmd.equals("localDeploy")) {
113             localDeploy(req);
114         }
115         else if (cmd.equals("reloadRepositories")) {
116             reloadRepositories(req);
117         }
118         else if (cmd.equals("remoteDeploy")) {
119             remoteDeploy(req);
120         }
121         else if (cmd.equals("unignorePackages")) {
122             unignorePackages(req);
123         }
124 
125         sendRedirect(req, res);
126     }
127 
128     protected void deployConfiguration(ActionRequest req) throws Exception {
129         boolean enabled = ParamUtil.getBoolean(req, "enabled");
130         String deployDir = ParamUtil.getString(req, "deployDir");
131         String destDir = ParamUtil.getString(req, "destDir");
132         long interval = ParamUtil.getLong(req, "interval");
133         int blacklistThreshold = ParamUtil.getInteger(
134             req, "blacklistThreshold");
135         boolean unpackWar = ParamUtil.getBoolean(req, "unpackWar");
136         boolean customPortletXml = ParamUtil.getBoolean(
137             req, "customPortletXml");
138         String jbossPrefix = ParamUtil.getString(req, "jbossPrefix");
139         String tomcatConfDir = ParamUtil.getString(req, "tomcatConfDir");
140         String tomcatLibDir = ParamUtil.getString(req, "tomcatLibDir");
141         String pluginRepositoriesTrusted = ParamUtil.getString(
142             req, "pluginRepositoriesTrusted");
143         String pluginRepositoriesUntrusted = ParamUtil.getString(
144             req, "pluginRepositoriesUntrusted");
145         boolean pluginNotificationsEnabled = ParamUtil.getBoolean(
146             req, "pluginNotificationsEnabled");
147         String pluginPackagesIgnored = ParamUtil.getString(
148             req, "pluginPackagesIgnored");
149 
150         PortletPreferences prefs = PrefsPropsUtil.getPreferences();
151 
152         prefs.setValue(PropsUtil.AUTO_DEPLOY_ENABLED, String.valueOf(enabled));
153         prefs.setValue(PropsUtil.AUTO_DEPLOY_DEPLOY_DIR, deployDir);
154         prefs.setValue(PropsUtil.AUTO_DEPLOY_DEST_DIR, destDir);
155         prefs.setValue(
156             PropsUtil.AUTO_DEPLOY_INTERVAL, String.valueOf(interval));
157         prefs.setValue(
158             PropsUtil.AUTO_DEPLOY_BLACKLIST_THRESHOLD,
159             String.valueOf(blacklistThreshold));
160         prefs.setValue(
161             PropsUtil.AUTO_DEPLOY_UNPACK_WAR, String.valueOf(unpackWar));
162         prefs.setValue(
163             PropsUtil.AUTO_DEPLOY_CUSTOM_PORTLET_XML,
164             String.valueOf(customPortletXml));
165         prefs.setValue(PropsUtil.AUTO_DEPLOY_JBOSS_PREFIX, jbossPrefix);
166         prefs.setValue(PropsUtil.AUTO_DEPLOY_TOMCAT_CONF_DIR, tomcatConfDir);
167         prefs.setValue(PropsUtil.AUTO_DEPLOY_TOMCAT_LIB_DIR, tomcatLibDir);
168         prefs.setValue(
169             PropsUtil.PLUGIN_REPOSITORIES_TRUSTED, pluginRepositoriesTrusted);
170         prefs.setValue(
171             PropsUtil.PLUGIN_REPOSITORIES_UNTRUSTED,
172             pluginRepositoriesUntrusted);
173         prefs.setValue(
174             PropsUtil.PLUGIN_NOTIFICATIONS_ENABLED,
175             String.valueOf(pluginNotificationsEnabled));
176         prefs.setValue(
177             PropsUtil.PLUGIN_NOTIFICATIONS_PACKAGES_IGNORED,
178             pluginPackagesIgnored);
179 
180         prefs.store();
181 
182         reloadRepositories(req);
183 
184         if (_log.isInfoEnabled()) {
185             _log.info("Unregistering auto deploy directories");
186         }
187 
188         AutoDeployUtil.unregisterDir("defaultAutoDeployDir");
189 
190         if (enabled) {
191             if (_log.isInfoEnabled()) {
192                 _log.info("Registering auto deploy directories");
193             }
194 
195             List autoDeployListeners =
196                 GlobalStartupAction.getAutoDeployListeners();
197 
198             AutoDeployDir autoDeployDir = new AutoDeployDir(
199                 "defaultAutoDeployDir", new File(deployDir), new File(destDir),
200                 interval, blacklistThreshold, autoDeployListeners);
201 
202             AutoDeployUtil.registerDir(autoDeployDir);
203         }
204         else {
205             if (_log.isInfoEnabled()) {
206                 _log.info("Not registering auto deploy directories");
207             }
208         }
209     }
210 
211     protected void ignorePackages(ActionRequest req) throws Exception {
212         String pluginPackagesIgnored = ParamUtil.getString(
213             req, "pluginPackagesIgnored");
214 
215         String oldPluginPackagesIgnored= PrefsPropsUtil.getString(
216             PropsUtil.PLUGIN_NOTIFICATIONS_PACKAGES_IGNORED);
217 
218         StringMaker sm = new StringMaker();
219 
220         sm.append(oldPluginPackagesIgnored);
221         sm.append(StringPool.NEW_LINE);
222         sm.append(pluginPackagesIgnored);
223 
224         PortletPreferences prefs = PrefsPropsUtil.getPreferences();
225 
226         prefs.setValue(
227             PropsUtil.PLUGIN_NOTIFICATIONS_PACKAGES_IGNORED, sm.toString());
228 
229         prefs.store();
230 
231         PluginPackageUtil.refreshUpdatesAvailableCache();
232     }
233 
234     protected void localDeploy(ActionRequest req) throws Exception {
235         UploadPortletRequest uploadReq =
236             PortalUtil.getUploadPortletRequest(req);
237 
238         String fileName = null;
239 
240         String deploymentContext = ParamUtil.getString(
241             req, "deploymentContext");
242 
243         if (Validator.isNotNull(deploymentContext)) {
244             fileName =
245                 BaseDeployer.DEPLOY_TO_PREFIX + deploymentContext + ".war";
246         }
247         else {
248             fileName = GetterUtil.getString(uploadReq.getFileName("file"));
249 
250             int pos = fileName.lastIndexOf(StringPool.PERIOD);
251 
252             if (pos != -1) {
253                 deploymentContext = fileName.substring(0, pos);
254             }
255         }
256 
257         File file = uploadReq.getFile("file");
258 
259         byte[] bytes = FileUtil.getBytes(file);
260 
261         if ((bytes == null) || (bytes.length == 0)) {
262             SessionErrors.add(req, UploadException.class.getName());
263 
264             return;
265         }
266 
267         try {
268             PluginPackageUtil.registerPluginPackageInstallation(
269                 deploymentContext);
270 
271             String source = file.toString();
272 
273             String deployDir = PrefsPropsUtil.getString(
274                 PropsUtil.AUTO_DEPLOY_DEPLOY_DIR);
275 
276             String destination = deployDir + StringPool.SLASH + fileName;
277 
278             FileUtil.copyFile(source, destination);
279 
280             SessionMessages.add(req, "pluginUploaded");
281         }
282         finally {
283             PluginPackageUtil.endPluginPackageInstallation(deploymentContext);
284         }
285     }
286 
287     protected void reloadRepositories(ActionRequest req) throws Exception {
288         RepositoryReport report = PluginPackageUtil.reloadRepositories();
289 
290         SessionMessages.add(req, WebKeys.PLUGIN_REPOSITORY_REPORT, report);
291     }
292 
293     protected void remoteDeploy(ActionRequest req) throws Exception {
294         GetMethod getMethod = null;
295 
296         String deploymentContext = ParamUtil.getString(
297             req, "deploymentContext");
298 
299         try {
300             String url = ParamUtil.getString(req, "url");
301 
302             URL urlObj = new URL(url);
303 
304             HostConfiguration hostConfig = Http.getHostConfig(url.toString());
305 
306             HttpClient client = Http.getClient(hostConfig);
307 
308             getMethod = new GetMethod(url);
309 
310             String fileName = null;
311 
312             if (Validator.isNotNull(deploymentContext)) {
313                 fileName =
314                     BaseDeployer.DEPLOY_TO_PREFIX + deploymentContext + ".war";
315             }
316             else {
317                 fileName = url.substring(url.lastIndexOf(StringPool.SLASH) + 1);
318 
319                 int pos = fileName.lastIndexOf(StringPool.PERIOD);
320 
321                 if (pos != -1) {
322                     deploymentContext = fileName.substring(0, pos);
323                 }
324             }
325 
326             PluginPackageUtil.registerPluginPackageInstallation(
327                 deploymentContext);
328 
329             int responseCode = client.executeMethod(hostConfig, getMethod);
330 
331             if (responseCode != 200) {
332                 SessionErrors.add(
333                     req, "errorConnectingToUrl",
334                     new Object[] {String.valueOf(responseCode)});
335 
336                 return;
337             }
338 
339             long contentLength = getMethod.getResponseContentLength();
340 
341             String progressId = ParamUtil.getString(req, Constants.PROGRESS_ID);
342 
343             ProgressInputStream pis = new ProgressInputStream(
344                 req, getMethod.getResponseBodyAsStream(), contentLength,
345                 progressId);
346 
347             String deployDir = PrefsPropsUtil.getString(
348                 PropsUtil.AUTO_DEPLOY_DEPLOY_DIR);
349 
350             String tmpFilePath =
351                 deployDir + StringPool.SLASH + _DOWNLOAD_DIR +
352                     StringPool.SLASH + fileName;
353 
354             File tmpFile = new File(tmpFilePath);
355 
356             if (!tmpFile.getParentFile().exists()) {
357                 tmpFile.getParentFile().mkdirs();
358             }
359 
360             FileOutputStream fos = new FileOutputStream(tmpFile);
361 
362             try {
363                 pis.readAll(fos);
364 
365                 if (_log.isInfoEnabled()) {
366                     _log.info(
367                         "Downloaded plugin from " + urlObj + " has " +
368                             pis.getTotalRead() + " bytes");
369                 }
370             }
371             finally {
372                 pis.clearProgress();
373             }
374 
375             getMethod.releaseConnection();
376 
377             if (pis.getTotalRead() > 0) {
378                 String destination = deployDir + StringPool.SLASH + fileName;
379 
380                 File destinationFile = new File(destination);
381 
382                 boolean moved = FileUtil.move(tmpFile, destinationFile);
383 
384                 if (!moved) {
385                     FileUtil.copyFile(tmpFile, destinationFile);
386                     FileUtil.delete(tmpFile);
387                 }
388 
389                 SessionMessages.add(req, "pluginDownloaded");
390             }
391             else {
392                 SessionErrors.add(req, UploadException.class.getName());
393             }
394         }
395         catch (MalformedURLException murle) {
396             SessionErrors.add(req, "invalidUrl", murle);
397         }
398         catch (IOException ioe) {
399             SessionErrors.add(req, "errorConnectingToUrl", ioe);
400         }
401         finally {
402             if (getMethod != null) {
403                 getMethod.releaseConnection();
404             }
405 
406             PluginPackageUtil.endPluginPackageInstallation(deploymentContext);
407         }
408     }
409 
410     protected void unignorePackages(ActionRequest req) throws Exception {
411         String[] pluginPackagesUnignored = StringUtil.split(
412             ParamUtil.getString(req, "pluginPackagesUnignored"),
413             StringPool.NEW_LINE);
414 
415         String[] pluginPackagesIgnored = PrefsPropsUtil.getStringArray(
416             PropsUtil.PLUGIN_NOTIFICATIONS_PACKAGES_IGNORED);
417 
418         StringMaker sm = new StringMaker();
419 
420         for (int i = 0; i < pluginPackagesIgnored.length; i++) {
421             String packageId = pluginPackagesIgnored[i];
422 
423             if (!ArrayUtil.contains(pluginPackagesUnignored, packageId)) {
424                 sm.append(packageId);
425                 sm.append(StringPool.NEW_LINE);
426             }
427         }
428 
429         PortletPreferences prefs = PrefsPropsUtil.getPreferences();
430 
431         prefs.setValue(
432             PropsUtil.PLUGIN_NOTIFICATIONS_PACKAGES_IGNORED, sm.toString());
433 
434         prefs.store();
435 
436         PluginPackageUtil.refreshUpdatesAvailableCache();
437     }
438 
439     private static final String _DOWNLOAD_DIR = "download";
440 
441     private static Log _log = LogFactory.getLog(InstallPluginAction.class);
442 
443 }