1
22
23 package com.liferay.portlet.plugininstaller.action;
24
25 import com.liferay.portal.deploy.DeployUtil;
26 import com.liferay.portal.events.GlobalStartupAction;
27 import com.liferay.portal.kernel.deploy.auto.AutoDeployDir;
28 import com.liferay.portal.kernel.deploy.auto.AutoDeployListener;
29 import com.liferay.portal.kernel.deploy.auto.AutoDeployUtil;
30 import com.liferay.portal.kernel.util.ArrayUtil;
31 import com.liferay.portal.kernel.util.Constants;
32 import com.liferay.portal.kernel.util.GetterUtil;
33 import com.liferay.portal.kernel.util.HttpUtil;
34 import com.liferay.portal.kernel.util.ParamUtil;
35 import com.liferay.portal.kernel.util.ServerDetector;
36 import com.liferay.portal.kernel.util.StringMaker;
37 import com.liferay.portal.kernel.util.StringPool;
38 import com.liferay.portal.kernel.util.StringUtil;
39 import com.liferay.portal.kernel.util.Validator;
40 import com.liferay.portal.plugin.PluginPackageUtil;
41 import com.liferay.portal.plugin.RepositoryReport;
42 import com.liferay.portal.security.auth.PrincipalException;
43 import com.liferay.portal.security.permission.PermissionChecker;
44 import com.liferay.portal.struts.PortletAction;
45 import com.liferay.portal.theme.ThemeDisplay;
46 import com.liferay.portal.tools.BaseDeployer;
47 import com.liferay.portal.util.HttpImpl;
48 import com.liferay.portal.util.PrefsPropsUtil;
49 import com.liferay.portal.util.PropsUtil;
50 import com.liferay.portal.util.PropsValues;
51 import com.liferay.portal.util.UploadRequestUtil;
52 import com.liferay.portal.util.WebKeys;
53 import com.liferay.util.FileUtil;
54 import com.liferay.util.servlet.ProgressInputStream;
55 import com.liferay.util.servlet.SessionErrors;
56 import com.liferay.util.servlet.SessionMessages;
57 import com.liferay.util.servlet.UploadException;
58 import com.liferay.util.servlet.UploadPortletRequest;
59
60 import java.io.File;
61 import java.io.FileOutputStream;
62 import java.io.IOException;
63
64 import java.net.MalformedURLException;
65 import java.net.URL;
66
67 import java.util.List;
68
69 import javax.portlet.ActionRequest;
70 import javax.portlet.ActionResponse;
71 import javax.portlet.PortletConfig;
72 import javax.portlet.PortletPreferences;
73
74 import javax.servlet.http.HttpServletResponse;
75
76 import org.apache.commons.httpclient.HostConfiguration;
77 import org.apache.commons.httpclient.HttpClient;
78 import org.apache.commons.httpclient.methods.GetMethod;
79 import org.apache.commons.logging.Log;
80 import org.apache.commons.logging.LogFactory;
81 import org.apache.struts.action.ActionForm;
82 import org.apache.struts.action.ActionMapping;
83
84
92 public class InstallPluginAction extends PortletAction {
93
94 public void processAction(
95 ActionMapping mapping, ActionForm form, PortletConfig config,
96 ActionRequest req, ActionResponse res)
97 throws Exception {
98
99 ThemeDisplay themeDisplay =
100 (ThemeDisplay)req.getAttribute(WebKeys.THEME_DISPLAY);
101
102 PermissionChecker permissionChecker =
103 themeDisplay.getPermissionChecker();
104
105 if (!permissionChecker.isOmniadmin()) {
106 SessionErrors.add(req, PrincipalException.class.getName());
107
108 setForward(req, "portlet.plugin_installer.error");
109
110 return;
111 }
112
113 String cmd = ParamUtil.getString(req, Constants.CMD);
114
115 if (cmd.equals("deployConfiguration")) {
116 deployConfiguration(req);
117 }
118 else if (cmd.equals("ignorePackages")) {
119 ignorePackages(req);
120 }
121 else if (cmd.equals("localDeploy")) {
122 localDeploy(req);
123 }
124 else if (cmd.equals("reloadRepositories")) {
125 reloadRepositories(req);
126 }
127 else if (cmd.equals("remoteDeploy")) {
128 remoteDeploy(req);
129 }
130 else if (cmd.equals("unignorePackages")) {
131 unignorePackages(req);
132 }
133 else if (cmd.equals("uninstall")) {
134 uninstall(req);
135 }
136
137 sendRedirect(req, res);
138 }
139
140 protected void deployConfiguration(ActionRequest req) throws Exception {
141 boolean enabled = ParamUtil.getBoolean(req, "enabled");
142 String deployDir = ParamUtil.getString(req, "deployDir");
143 String destDir = ParamUtil.getString(req, "destDir");
144 long interval = ParamUtil.getLong(req, "interval");
145 int blacklistThreshold = ParamUtil.getInteger(
146 req, "blacklistThreshold");
147 boolean unpackWar = ParamUtil.getBoolean(req, "unpackWar");
148 boolean customPortletXml = ParamUtil.getBoolean(
149 req, "customPortletXml");
150 String jbossPrefix = ParamUtil.getString(req, "jbossPrefix");
151 String tomcatConfDir = ParamUtil.getString(req, "tomcatConfDir");
152 String tomcatLibDir = ParamUtil.getString(req, "tomcatLibDir");
153 String pluginRepositoriesTrusted = ParamUtil.getString(
154 req, "pluginRepositoriesTrusted");
155 String pluginRepositoriesUntrusted = ParamUtil.getString(
156 req, "pluginRepositoriesUntrusted");
157 boolean pluginNotificationsEnabled = ParamUtil.getBoolean(
158 req, "pluginNotificationsEnabled");
159 String pluginPackagesIgnored = ParamUtil.getString(
160 req, "pluginPackagesIgnored");
161
162 PortletPreferences prefs = PrefsPropsUtil.getPreferences();
163
164 prefs.setValue(PropsUtil.AUTO_DEPLOY_ENABLED, String.valueOf(enabled));
165 prefs.setValue(PropsUtil.AUTO_DEPLOY_DEPLOY_DIR, deployDir);
166 prefs.setValue(PropsUtil.AUTO_DEPLOY_DEST_DIR, destDir);
167 prefs.setValue(
168 PropsUtil.AUTO_DEPLOY_INTERVAL, String.valueOf(interval));
169 prefs.setValue(
170 PropsUtil.AUTO_DEPLOY_BLACKLIST_THRESHOLD,
171 String.valueOf(blacklistThreshold));
172 prefs.setValue(
173 PropsUtil.AUTO_DEPLOY_UNPACK_WAR, String.valueOf(unpackWar));
174 prefs.setValue(
175 PropsUtil.AUTO_DEPLOY_CUSTOM_PORTLET_XML,
176 String.valueOf(customPortletXml));
177 prefs.setValue(PropsUtil.AUTO_DEPLOY_JBOSS_PREFIX, jbossPrefix);
178 prefs.setValue(PropsUtil.AUTO_DEPLOY_TOMCAT_CONF_DIR, tomcatConfDir);
179 prefs.setValue(PropsUtil.AUTO_DEPLOY_TOMCAT_LIB_DIR, tomcatLibDir);
180 prefs.setValue(
181 PropsUtil.PLUGIN_REPOSITORIES_TRUSTED, pluginRepositoriesTrusted);
182 prefs.setValue(
183 PropsUtil.PLUGIN_REPOSITORIES_UNTRUSTED,
184 pluginRepositoriesUntrusted);
185 prefs.setValue(
186 PropsUtil.PLUGIN_NOTIFICATIONS_ENABLED,
187 String.valueOf(pluginNotificationsEnabled));
188 prefs.setValue(
189 PropsUtil.PLUGIN_NOTIFICATIONS_PACKAGES_IGNORED,
190 pluginPackagesIgnored);
191
192 prefs.store();
193
194 reloadRepositories(req);
195
196 if (_log.isInfoEnabled()) {
197 _log.info("Unregistering auto deploy directories");
198 }
199
200 AutoDeployUtil.unregisterDir("defaultAutoDeployDir");
201
202 if (enabled) {
203 if (_log.isInfoEnabled()) {
204 _log.info("Registering auto deploy directories");
205 }
206
207 List<AutoDeployListener> autoDeployListeners =
208 GlobalStartupAction.getAutoDeployListeners();
209
210 AutoDeployDir autoDeployDir = new AutoDeployDir(
211 "defaultAutoDeployDir", new File(deployDir), new File(destDir),
212 interval, blacklistThreshold, autoDeployListeners);
213
214 AutoDeployUtil.registerDir(autoDeployDir);
215 }
216 else {
217 if (_log.isInfoEnabled()) {
218 _log.info("Not registering auto deploy directories");
219 }
220 }
221 }
222
223 protected String[] getSourceForgeMirrors() {
224 return PropsUtil.getArray(PropsUtil.SOURCE_FORGE_MIRRORS);
225 }
226
227 protected void ignorePackages(ActionRequest req) throws Exception {
228 String pluginPackagesIgnored = ParamUtil.getString(
229 req, "pluginPackagesIgnored");
230
231 String oldPluginPackagesIgnored= PrefsPropsUtil.getString(
232 PropsUtil.PLUGIN_NOTIFICATIONS_PACKAGES_IGNORED);
233
234 StringMaker sm = new StringMaker();
235
236 sm.append(oldPluginPackagesIgnored);
237 sm.append(StringPool.NEW_LINE);
238 sm.append(pluginPackagesIgnored);
239
240 PortletPreferences prefs = PrefsPropsUtil.getPreferences();
241
242 prefs.setValue(
243 PropsUtil.PLUGIN_NOTIFICATIONS_PACKAGES_IGNORED, sm.toString());
244
245 prefs.store();
246
247 PluginPackageUtil.refreshUpdatesAvailableCache();
248 }
249
250 protected void localDeploy(ActionRequest req) throws Exception {
251 UploadPortletRequest uploadReq =
252 UploadRequestUtil.getUploadPortletRequest(req);
253
254 String fileName = null;
255
256 String deploymentContext = ParamUtil.getString(
257 req, "deploymentContext");
258
259 if (Validator.isNotNull(deploymentContext)) {
260 fileName =
261 BaseDeployer.DEPLOY_TO_PREFIX + deploymentContext + ".war";
262 }
263 else {
264 fileName = GetterUtil.getString(uploadReq.getFileName("file"));
265
266 int pos = fileName.lastIndexOf(StringPool.PERIOD);
267
268 if (pos != -1) {
269 deploymentContext = fileName.substring(0, pos);
270 }
271 }
272
273 File file = uploadReq.getFile("file");
274
275 byte[] bytes = FileUtil.getBytes(file);
276
277 if ((bytes == null) || (bytes.length == 0)) {
278 SessionErrors.add(req, UploadException.class.getName());
279
280 return;
281 }
282
283 try {
284 PluginPackageUtil.registerPluginPackageInstallation(
285 deploymentContext);
286
287 String source = file.toString();
288
289 String deployDir = PrefsPropsUtil.getString(
290 PropsUtil.AUTO_DEPLOY_DEPLOY_DIR,
291 PropsValues.AUTO_DEPLOY_DEPLOY_DIR);
292
293 String destination = deployDir + StringPool.SLASH + fileName;
294
295 FileUtil.copyFile(source, destination);
296
297 SessionMessages.add(req, "pluginUploaded");
298 }
299 finally {
300 PluginPackageUtil.endPluginPackageInstallation(deploymentContext);
301 }
302 }
303
304 protected void reloadRepositories(ActionRequest req) throws Exception {
305 RepositoryReport report = PluginPackageUtil.reloadRepositories();
306
307 SessionMessages.add(req, WebKeys.PLUGIN_REPOSITORY_REPORT, report);
308 }
309
310 protected void remoteDeploy(ActionRequest req) throws Exception {
311 try {
312 String url = ParamUtil.getString(req, "url");
313
314 URL urlObj = new URL(url);
315
316 String host = urlObj.getHost();
317
318 if (host.endsWith(".sf.net") || host.endsWith(".sourceforge.net")) {
319 remoteDeploySourceForge(urlObj.getPath(), req);
320 }
321 else {
322 remoteDeploy(url, urlObj, req, true);
323 }
324 }
325 catch (MalformedURLException murle) {
326 SessionErrors.add(req, "invalidUrl", murle);
327 }
328 }
329
330 protected int remoteDeploy(
331 String url, URL urlObj, ActionRequest req, boolean failOnError)
332 throws Exception {
333
334 int responseCode = HttpServletResponse.SC_OK;
335
336 GetMethod getMethod = null;
337
338 String deploymentContext = ParamUtil.getString(
339 req, "deploymentContext");
340
341 try {
342 HttpImpl httpImpl = (HttpImpl)HttpUtil.getHttp();
343
344 HostConfiguration hostConfig = httpImpl.getHostConfig(url);
345
346 HttpClient client = httpImpl.getClient(hostConfig);
347
348 getMethod = new GetMethod(url);
349
350 String fileName = null;
351
352 if (Validator.isNotNull(deploymentContext)) {
353 fileName =
354 BaseDeployer.DEPLOY_TO_PREFIX + deploymentContext + ".war";
355 }
356 else {
357 fileName = url.substring(url.lastIndexOf(StringPool.SLASH) + 1);
358
359 int pos = fileName.lastIndexOf(StringPool.PERIOD);
360
361 if (pos != -1) {
362 deploymentContext = fileName.substring(0, pos);
363 }
364 }
365
366 PluginPackageUtil.registerPluginPackageInstallation(
367 deploymentContext);
368
369 responseCode = client.executeMethod(hostConfig, getMethod);
370
371 if (responseCode != HttpServletResponse.SC_OK) {
372 if (failOnError) {
373 SessionErrors.add(
374 req, "errorConnectingToUrl",
375 new Object[] {String.valueOf(responseCode)});
376 }
377
378 return responseCode;
379 }
380
381 long contentLength = getMethod.getResponseContentLength();
382
383 String progressId = ParamUtil.getString(req, Constants.PROGRESS_ID);
384
385 ProgressInputStream pis = new ProgressInputStream(
386 req, getMethod.getResponseBodyAsStream(), contentLength,
387 progressId);
388
389 String deployDir = PrefsPropsUtil.getString(
390 PropsUtil.AUTO_DEPLOY_DEPLOY_DIR,
391 PropsValues.AUTO_DEPLOY_DEPLOY_DIR);
392
393 String tmpFilePath =
394 deployDir + StringPool.SLASH + _DOWNLOAD_DIR +
395 StringPool.SLASH + fileName;
396
397 File tmpFile = new File(tmpFilePath);
398
399 if (!tmpFile.getParentFile().exists()) {
400 tmpFile.getParentFile().mkdirs();
401 }
402
403 FileOutputStream fos = new FileOutputStream(tmpFile);
404
405 try {
406 pis.readAll(fos);
407
408 if (_log.isInfoEnabled()) {
409 _log.info(
410 "Downloaded plugin from " + urlObj + " has " +
411 pis.getTotalRead() + " bytes");
412 }
413 }
414 finally {
415 pis.clearProgress();
416 }
417
418 getMethod.releaseConnection();
419
420 if (pis.getTotalRead() > 0) {
421 String destination = deployDir + StringPool.SLASH + fileName;
422
423 File destinationFile = new File(destination);
424
425 boolean moved = FileUtil.move(tmpFile, destinationFile);
426
427 if (!moved) {
428 FileUtil.copyFile(tmpFile, destinationFile);
429 FileUtil.delete(tmpFile);
430 }
431
432 SessionMessages.add(req, "pluginDownloaded");
433 }
434 else {
435 if (failOnError) {
436 SessionErrors.add(req, UploadException.class.getName());
437 }
438
439 responseCode = HttpServletResponse.SC_INTERNAL_SERVER_ERROR;
440 }
441 }
442 catch (MalformedURLException murle) {
443 SessionErrors.add(req, "invalidUrl", murle);
444 }
445 catch (IOException ioe) {
446 SessionErrors.add(req, "errorConnectingToUrl", ioe);
447 }
448 finally {
449 if (getMethod != null) {
450 getMethod.releaseConnection();
451 }
452
453 PluginPackageUtil.endPluginPackageInstallation(deploymentContext);
454 }
455
456 return responseCode;
457 }
458
459 protected void remoteDeploySourceForge(String path, ActionRequest req)
460 throws Exception {
461
462 String[] sourceForgeMirrors = getSourceForgeMirrors();
463
464 for (int i = 0; i < sourceForgeMirrors.length; i++) {
465 try {
466 String url = sourceForgeMirrors[i] + path;
467
468 if (_log.isDebugEnabled()) {
469 _log.debug("Downloading from SourceForge mirror " + url);
470 }
471
472 URL urlObj = new URL(url);
473
474 boolean failOnError = false;
475
476 if ((i + 1) == sourceForgeMirrors.length) {
477 failOnError = true;
478 }
479
480 int responseCode = remoteDeploy(url, urlObj, req, failOnError);
481
482 if (responseCode == HttpServletResponse.SC_OK) {
483 return;
484 }
485 }
486 catch (MalformedURLException murle) {
487 SessionErrors.add(req, "invalidUrl", murle);
488 }
489 }
490 }
491
492 protected void unignorePackages(ActionRequest req) throws Exception {
493 String[] pluginPackagesUnignored = StringUtil.split(
494 ParamUtil.getString(req, "pluginPackagesUnignored"),
495 StringPool.NEW_LINE);
496
497 String[] pluginPackagesIgnored = PrefsPropsUtil.getStringArray(
498 PropsUtil.PLUGIN_NOTIFICATIONS_PACKAGES_IGNORED,
499 StringPool.NEW_LINE,
500 PropsValues.PLUGIN_NOTIFICATIONS_PACKAGES_IGNORED);
501
502 StringMaker sm = new StringMaker();
503
504 for (int i = 0; i < pluginPackagesIgnored.length; i++) {
505 String packageId = pluginPackagesIgnored[i];
506
507 if (!ArrayUtil.contains(pluginPackagesUnignored, packageId)) {
508 sm.append(packageId);
509 sm.append(StringPool.NEW_LINE);
510 }
511 }
512
513 PortletPreferences prefs = PrefsPropsUtil.getPreferences();
514
515 prefs.setValue(
516 PropsUtil.PLUGIN_NOTIFICATIONS_PACKAGES_IGNORED, sm.toString());
517
518 prefs.store();
519
520 PluginPackageUtil.refreshUpdatesAvailableCache();
521 }
522
523 protected void uninstall(ActionRequest req) throws Exception {
524 String appServerType = ServerDetector.getServerId();
525
526 String deploymentContext = ParamUtil.getString(
527 req, "deploymentContext");
528
529 if (appServerType.startsWith(ServerDetector.JBOSS_ID)) {
530 deploymentContext += ".war";
531 }
532
533 File deployDir = new File(
534 DeployUtil.getAutoDeployDestDir() + "/" + deploymentContext);
535
536 DeployUtil.undeploy(appServerType, deployDir);
537 }
538
539 private static final String _DOWNLOAD_DIR = "download";
540
541 private static Log _log = LogFactory.getLog(InstallPluginAction.class);
542
543 }