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