001
014
015 package com.liferay.portlet.plugininstaller.action;
016
017 import com.liferay.portal.deploy.DeployUtil;
018 import com.liferay.portal.events.GlobalStartupAction;
019 import com.liferay.portal.kernel.deploy.auto.AutoDeployDir;
020 import com.liferay.portal.kernel.deploy.auto.AutoDeployListener;
021 import com.liferay.portal.kernel.deploy.auto.AutoDeployUtil;
022 import com.liferay.portal.kernel.log.Log;
023 import com.liferay.portal.kernel.log.LogFactoryUtil;
024 import com.liferay.portal.kernel.servlet.SessionErrors;
025 import com.liferay.portal.kernel.servlet.SessionMessages;
026 import com.liferay.portal.kernel.upload.UploadException;
027 import com.liferay.portal.kernel.upload.UploadPortletRequest;
028 import com.liferay.portal.kernel.util.ArrayUtil;
029 import com.liferay.portal.kernel.util.CharPool;
030 import com.liferay.portal.kernel.util.Constants;
031 import com.liferay.portal.kernel.util.FileUtil;
032 import com.liferay.portal.kernel.util.GetterUtil;
033 import com.liferay.portal.kernel.util.HttpUtil;
034 import com.liferay.portal.kernel.util.ParamUtil;
035 import com.liferay.portal.kernel.util.PropsKeys;
036 import com.liferay.portal.kernel.util.ServerDetector;
037 import com.liferay.portal.kernel.util.StringBundler;
038 import com.liferay.portal.kernel.util.StringPool;
039 import com.liferay.portal.kernel.util.StringUtil;
040 import com.liferay.portal.kernel.util.Validator;
041 import com.liferay.portal.plugin.PluginPackageUtil;
042 import com.liferay.portal.plugin.RepositoryReport;
043 import com.liferay.portal.security.auth.PrincipalException;
044 import com.liferay.portal.security.lang.DoPrivilegedBean;
045 import com.liferay.portal.security.permission.PermissionChecker;
046 import com.liferay.portal.struts.PortletAction;
047 import com.liferay.portal.theme.ThemeDisplay;
048 import com.liferay.portal.tools.deploy.BaseDeployer;
049 import com.liferay.portal.upload.ProgressInputStream;
050 import com.liferay.portal.util.HttpImpl;
051 import com.liferay.portal.util.PortalUtil;
052 import com.liferay.portal.util.PrefsPropsUtil;
053 import com.liferay.portal.util.PropsUtil;
054 import com.liferay.portal.util.PropsValues;
055 import com.liferay.portal.util.WebKeys;
056
057 import java.io.File;
058 import java.io.FileOutputStream;
059 import java.io.IOException;
060
061 import java.net.MalformedURLException;
062 import java.net.URL;
063
064 import java.util.List;
065
066 import javax.portlet.ActionRequest;
067 import javax.portlet.ActionResponse;
068 import javax.portlet.PortletConfig;
069 import javax.portlet.PortletPreferences;
070
071 import javax.servlet.http.HttpServletResponse;
072
073 import org.apache.commons.httpclient.HostConfiguration;
074 import org.apache.commons.httpclient.HttpClient;
075 import org.apache.commons.httpclient.methods.GetMethod;
076 import org.apache.struts.action.ActionForm;
077 import org.apache.struts.action.ActionMapping;
078
079
084 public class InstallPluginAction extends PortletAction {
085
086 @Override
087 public void processAction(
088 ActionMapping mapping, ActionForm form, PortletConfig portletConfig,
089 ActionRequest actionRequest, ActionResponse actionResponse)
090 throws Exception {
091
092 ThemeDisplay themeDisplay = (ThemeDisplay)actionRequest.getAttribute(
093 WebKeys.THEME_DISPLAY);
094
095 PermissionChecker permissionChecker =
096 themeDisplay.getPermissionChecker();
097
098 if (!permissionChecker.isOmniadmin()) {
099 SessionErrors.add(
100 actionRequest, PrincipalException.class.getName());
101
102 setForward(actionRequest, "portlet.plugin_installer.error");
103
104 return;
105 }
106
107 String cmd = ParamUtil.getString(actionRequest, Constants.CMD);
108
109 if (cmd.equals("deployConfiguration")) {
110 deployConfiguration(actionRequest);
111 }
112 else if (cmd.equals("ignorePackages")) {
113 ignorePackages(actionRequest);
114 }
115 else if (cmd.equals("localDeploy")) {
116 localDeploy(actionRequest);
117 }
118 else if (cmd.equals("reloadRepositories")) {
119 reloadRepositories(actionRequest);
120 }
121 else if (cmd.equals("remoteDeploy")) {
122 remoteDeploy(actionRequest);
123 }
124 else if (cmd.equals("unignorePackages")) {
125 unignorePackages(actionRequest);
126 }
127 else if (cmd.equals("uninstall")) {
128 uninstall(actionRequest);
129 }
130
131 sendRedirect(actionRequest, actionResponse);
132 }
133
134 protected void deployConfiguration(ActionRequest actionRequest)
135 throws Exception {
136
137 boolean enabled = ParamUtil.getBoolean(actionRequest, "enabled");
138 String deployDir = ParamUtil.getString(actionRequest, "deployDir");
139 String destDir = ParamUtil.getString(actionRequest, "destDir");
140 long interval = ParamUtil.getLong(actionRequest, "interval");
141 boolean unpackWar = ParamUtil.getBoolean(actionRequest, "unpackWar");
142 boolean customPortletXml = ParamUtil.getBoolean(
143 actionRequest, "customPortletXml");
144 String jbossPrefix = ParamUtil.getString(actionRequest, "jbossPrefix");
145 String tomcatConfDir = ParamUtil.getString(
146 actionRequest, "tomcatConfDir");
147 String tomcatLibDir = ParamUtil.getString(
148 actionRequest, "tomcatLibDir");
149 String pluginRepositoriesTrusted = ParamUtil.getString(
150 actionRequest, "pluginRepositoriesTrusted");
151 String pluginRepositoriesUntrusted = ParamUtil.getString(
152 actionRequest, "pluginRepositoriesUntrusted");
153 boolean pluginNotificationsEnabled = ParamUtil.getBoolean(
154 actionRequest, "pluginNotificationsEnabled");
155 String pluginPackagesIgnored = ParamUtil.getString(
156 actionRequest, "pluginPackagesIgnored");
157
158 PortletPreferences preferences = PrefsPropsUtil.getPreferences();
159
160 preferences.setValue(
161 PropsKeys.AUTO_DEPLOY_ENABLED, String.valueOf(enabled));
162 preferences.setValue(PropsKeys.AUTO_DEPLOY_DEPLOY_DIR, deployDir);
163 preferences.setValue(PropsKeys.AUTO_DEPLOY_DEST_DIR, destDir);
164 preferences.setValue(
165 PropsKeys.AUTO_DEPLOY_INTERVAL, String.valueOf(interval));
166 preferences.setValue(
167 PropsKeys.AUTO_DEPLOY_UNPACK_WAR, String.valueOf(unpackWar));
168 preferences.setValue(
169 PropsKeys.AUTO_DEPLOY_CUSTOM_PORTLET_XML,
170 String.valueOf(customPortletXml));
171 preferences.setValue(PropsKeys.AUTO_DEPLOY_JBOSS_PREFIX, jbossPrefix);
172 preferences.setValue(
173 PropsKeys.AUTO_DEPLOY_TOMCAT_CONF_DIR, tomcatConfDir);
174 preferences.setValue(
175 PropsKeys.AUTO_DEPLOY_TOMCAT_LIB_DIR, tomcatLibDir);
176 preferences.setValue(
177 PropsKeys.PLUGIN_REPOSITORIES_TRUSTED, pluginRepositoriesTrusted);
178 preferences.setValue(
179 PropsKeys.PLUGIN_REPOSITORIES_UNTRUSTED,
180 pluginRepositoriesUntrusted);
181 preferences.setValue(
182 PropsKeys.PLUGIN_NOTIFICATIONS_ENABLED,
183 String.valueOf(pluginNotificationsEnabled));
184 preferences.setValue(
185 PropsKeys.PLUGIN_NOTIFICATIONS_PACKAGES_IGNORED,
186 pluginPackagesIgnored);
187
188 preferences.store();
189
190 reloadRepositories(actionRequest);
191
192 if (_log.isInfoEnabled()) {
193 _log.info("Unregistering auto deploy directories");
194 }
195
196 AutoDeployUtil.unregisterDir("defaultAutoDeployDir");
197
198 if (enabled) {
199 if (_log.isInfoEnabled()) {
200 _log.info("Registering auto deploy directories");
201 }
202
203 List<AutoDeployListener> autoDeployListeners =
204 GlobalStartupAction.getAutoDeployListeners();
205
206 AutoDeployDir autoDeployDir = new AutoDeployDir(
207 "defaultAutoDeployDir", new File(deployDir), new File(destDir),
208 interval, autoDeployListeners);
209
210 AutoDeployUtil.registerDir(autoDeployDir);
211 }
212 else {
213 if (_log.isInfoEnabled()) {
214 _log.info("Not registering auto deploy directories");
215 }
216 }
217 }
218
219 protected String[] getSourceForgeMirrors() {
220 return PropsUtil.getArray(PropsKeys.SOURCE_FORGE_MIRRORS);
221 }
222
223 protected void ignorePackages(ActionRequest actionRequest)
224 throws Exception {
225
226 String pluginPackagesIgnored = ParamUtil.getString(
227 actionRequest, "pluginPackagesIgnored");
228
229 String oldPluginPackagesIgnored = PrefsPropsUtil.getString(
230 PropsKeys.PLUGIN_NOTIFICATIONS_PACKAGES_IGNORED);
231
232 PortletPreferences preferences = PrefsPropsUtil.getPreferences();
233
234 if (Validator.isNotNull(oldPluginPackagesIgnored)) {
235 preferences.setValue(
236 PropsKeys.PLUGIN_NOTIFICATIONS_PACKAGES_IGNORED,
237 oldPluginPackagesIgnored.concat(StringPool.NEW_LINE).concat(
238 pluginPackagesIgnored));
239 }
240 else {
241 preferences.setValue(
242 PropsKeys.PLUGIN_NOTIFICATIONS_PACKAGES_IGNORED,
243 pluginPackagesIgnored);
244 }
245
246 preferences.store();
247
248 PluginPackageUtil.refreshUpdatesAvailableCache();
249 }
250
251 protected void localDeploy(ActionRequest actionRequest) throws Exception {
252 UploadPortletRequest uploadPortletRequest =
253 PortalUtil.getUploadPortletRequest(actionRequest);
254
255 String fileName = null;
256
257 String deploymentContext = ParamUtil.getString(
258 actionRequest, "deploymentContext");
259
260 if (Validator.isNotNull(deploymentContext)) {
261 fileName =
262 BaseDeployer.DEPLOY_TO_PREFIX + deploymentContext + ".war";
263 }
264 else {
265 fileName = GetterUtil.getString(
266 uploadPortletRequest.getFileName("file"));
267
268 int pos = fileName.lastIndexOf(CharPool.PERIOD);
269
270 if (pos != -1) {
271 deploymentContext = fileName.substring(0, pos);
272 }
273 }
274
275 File file = uploadPortletRequest.getFile("file");
276
277 byte[] bytes = FileUtil.getBytes(file);
278
279 if ((bytes == null) || (bytes.length == 0)) {
280 SessionErrors.add(actionRequest, UploadException.class.getName());
281
282 return;
283 }
284
285 try {
286 PluginPackageUtil.registerPluginPackageInstallation(
287 deploymentContext);
288
289 String source = file.toString();
290
291 String deployDir = PrefsPropsUtil.getString(
292 PropsKeys.AUTO_DEPLOY_DEPLOY_DIR,
293 PropsValues.AUTO_DEPLOY_DEPLOY_DIR);
294
295 String destination = deployDir + StringPool.SLASH + fileName;
296
297 FileUtil.copyFile(source, destination);
298
299 SessionMessages.add(actionRequest, "pluginUploaded");
300 }
301 finally {
302 PluginPackageUtil.endPluginPackageInstallation(deploymentContext);
303 }
304 }
305
306 protected void reloadRepositories(ActionRequest actionRequest)
307 throws Exception {
308
309 RepositoryReport repositoryReport =
310 PluginPackageUtil.reloadRepositories();
311
312 SessionMessages.add(
313 actionRequest, WebKeys.PLUGIN_REPOSITORY_REPORT, repositoryReport);
314 }
315
316 protected void remoteDeploy(ActionRequest actionRequest) throws Exception {
317 try {
318 String url = ParamUtil.getString(actionRequest, "url");
319
320 URL urlObj = new URL(url);
321
322 String host = urlObj.getHost();
323
324 if (host.endsWith(".sf.net") || host.endsWith(".sourceforge.net")) {
325 remoteDeploySourceForge(urlObj.getPath(), actionRequest);
326 }
327 else {
328 remoteDeploy(url, urlObj, actionRequest, true);
329 }
330 }
331 catch (MalformedURLException murle) {
332 SessionErrors.add(actionRequest, "invalidUrl", murle);
333 }
334 }
335
336 protected int remoteDeploy(
337 String url, URL urlObj, ActionRequest actionRequest,
338 boolean failOnError)
339 throws Exception {
340
341 int responseCode = HttpServletResponse.SC_OK;
342
343 GetMethod getMethod = null;
344
345 String deploymentContext = ParamUtil.getString(
346 actionRequest, "deploymentContext");
347
348 try {
349 HttpImpl httpImpl = null;
350
351 Object httpObject = HttpUtil.getHttp();
352
353 if (httpObject instanceof DoPrivilegedBean) {
354 DoPrivilegedBean doPrivilegedBean =
355 (DoPrivilegedBean)httpObject;
356
357 httpImpl = (HttpImpl)doPrivilegedBean.getActualBean();
358 }
359 else {
360 httpImpl = (HttpImpl)httpObject;
361 }
362
363 HostConfiguration hostConfiguration = httpImpl.getHostConfiguration(
364 url);
365
366 HttpClient httpClient = httpImpl.getClient(hostConfiguration);
367
368 getMethod = new GetMethod(url);
369
370 String fileName = null;
371
372 if (Validator.isNotNull(deploymentContext)) {
373 fileName =
374 BaseDeployer.DEPLOY_TO_PREFIX + deploymentContext + ".war";
375 }
376 else {
377 fileName = url.substring(url.lastIndexOf(CharPool.SLASH) + 1);
378
379 int pos = fileName.lastIndexOf(CharPool.PERIOD);
380
381 if (pos != -1) {
382 deploymentContext = fileName.substring(0, pos);
383 }
384 }
385
386 PluginPackageUtil.registerPluginPackageInstallation(
387 deploymentContext);
388
389 responseCode = httpClient.executeMethod(
390 hostConfiguration, getMethod);
391
392 if (responseCode != HttpServletResponse.SC_OK) {
393 if (failOnError) {
394 SessionErrors.add(
395 actionRequest, "errorConnectingToUrl",
396 new Object[] {String.valueOf(responseCode)});
397 }
398
399 return responseCode;
400 }
401
402 long contentLength = getMethod.getResponseContentLength();
403
404 String progressId = ParamUtil.getString(
405 actionRequest, Constants.PROGRESS_ID);
406
407 ProgressInputStream pis = new ProgressInputStream(
408 actionRequest, getMethod.getResponseBodyAsStream(),
409 contentLength, progressId);
410
411 String deployDir = PrefsPropsUtil.getString(
412 PropsKeys.AUTO_DEPLOY_DEPLOY_DIR,
413 PropsValues.AUTO_DEPLOY_DEPLOY_DIR);
414
415 String tmpFilePath =
416 deployDir + StringPool.SLASH + _DOWNLOAD_DIR +
417 StringPool.SLASH + fileName;
418
419 File tmpFile = new File(tmpFilePath);
420
421 if (!tmpFile.getParentFile().exists()) {
422 tmpFile.getParentFile().mkdirs();
423 }
424
425 FileOutputStream fos = new FileOutputStream(tmpFile);
426
427 try {
428 pis.readAll(fos);
429
430 if (_log.isInfoEnabled()) {
431 _log.info(
432 "Downloaded plugin from " + urlObj + " has " +
433 pis.getTotalRead() + " bytes");
434 }
435 }
436 finally {
437 pis.clearProgress();
438 }
439
440 getMethod.releaseConnection();
441
442 if (pis.getTotalRead() > 0) {
443 String destination = deployDir + StringPool.SLASH + fileName;
444
445 File destinationFile = new File(destination);
446
447 boolean moved = FileUtil.move(tmpFile, destinationFile);
448
449 if (!moved) {
450 FileUtil.copyFile(tmpFile, destinationFile);
451 FileUtil.delete(tmpFile);
452 }
453
454 SessionMessages.add(actionRequest, "pluginDownloaded");
455 }
456 else {
457 if (failOnError) {
458 SessionErrors.add(
459 actionRequest, UploadException.class.getName());
460 }
461
462 responseCode = HttpServletResponse.SC_INTERNAL_SERVER_ERROR;
463 }
464 }
465 catch (MalformedURLException murle) {
466 SessionErrors.add(actionRequest, "invalidUrl", murle);
467 }
468 catch (IOException ioe) {
469 SessionErrors.add(actionRequest, "errorConnectingToUrl", ioe);
470 }
471 finally {
472 if (getMethod != null) {
473 getMethod.releaseConnection();
474 }
475
476 PluginPackageUtil.endPluginPackageInstallation(deploymentContext);
477 }
478
479 return responseCode;
480 }
481
482 protected void remoteDeploySourceForge(
483 String path, ActionRequest actionRequest)
484 throws Exception {
485
486 String[] sourceForgeMirrors = getSourceForgeMirrors();
487
488 for (int i = 0; i < sourceForgeMirrors.length; i++) {
489 try {
490 String url = sourceForgeMirrors[i] + path;
491
492 if (_log.isDebugEnabled()) {
493 _log.debug("Downloading from SourceForge mirror " + url);
494 }
495
496 URL urlObj = new URL(url);
497
498 boolean failOnError = false;
499
500 if ((i + 1) == sourceForgeMirrors.length) {
501 failOnError = true;
502 }
503
504 int responseCode = remoteDeploy(
505 url, urlObj, actionRequest, failOnError);
506
507 if (responseCode == HttpServletResponse.SC_OK) {
508 return;
509 }
510 }
511 catch (MalformedURLException murle) {
512 SessionErrors.add(actionRequest, "invalidUrl", murle);
513 }
514 }
515 }
516
517 protected void unignorePackages(ActionRequest actionRequest)
518 throws Exception {
519
520 String[] pluginPackagesUnignored = StringUtil.splitLines(
521 ParamUtil.getString(actionRequest, "pluginPackagesUnignored"));
522
523 String[] pluginPackagesIgnored = PrefsPropsUtil.getStringArray(
524 PropsKeys.PLUGIN_NOTIFICATIONS_PACKAGES_IGNORED,
525 StringPool.NEW_LINE,
526 PropsValues.PLUGIN_NOTIFICATIONS_PACKAGES_IGNORED);
527
528 StringBundler sb = new StringBundler();
529
530 for (int i = 0; i < pluginPackagesIgnored.length; i++) {
531 String packageId = pluginPackagesIgnored[i];
532
533 if (!ArrayUtil.contains(pluginPackagesUnignored, packageId)) {
534 sb.append(packageId);
535 sb.append(StringPool.NEW_LINE);
536 }
537 }
538
539 PortletPreferences preferences = PrefsPropsUtil.getPreferences();
540
541 preferences.setValue(
542 PropsKeys.PLUGIN_NOTIFICATIONS_PACKAGES_IGNORED, sb.toString());
543
544 preferences.store();
545
546 PluginPackageUtil.refreshUpdatesAvailableCache();
547 }
548
549 protected void uninstall(ActionRequest actionRequest) throws Exception {
550 String appServerType = ServerDetector.getServerId();
551
552 String deploymentContext = ParamUtil.getString(
553 actionRequest, "deploymentContext");
554
555 File deployDir = new File(
556 DeployUtil.getAutoDeployDestDir(), deploymentContext);
557
558 DeployUtil.undeploy(appServerType, deployDir);
559
560 SessionMessages.add(actionRequest, "triggeredPortletUndeploy");
561 }
562
563 private static final String _DOWNLOAD_DIR = "download";
564
565 private static Log _log = LogFactoryUtil.getLog(InstallPluginAction.class);
566
567 }