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