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