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