001    /**
002     * Copyright (c) 2000-2012 Liferay, Inc. All rights reserved.
003     *
004     * This library is free software; you can redistribute it and/or modify it under
005     * the terms of the GNU Lesser General Public License as published by the Free
006     * Software Foundation; either version 2.1 of the License, or (at your option)
007     * any later version.
008     *
009     * This library is distributed in the hope that it will be useful, but WITHOUT
010     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
011     * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
012     * details.
013     */
014    
015    package com.liferay.portlet.admin.action;
016    
017    import com.liferay.mail.service.MailServiceUtil;
018    import com.liferay.portal.captcha.CaptchaImpl;
019    import com.liferay.portal.captcha.recaptcha.ReCaptchaImpl;
020    import com.liferay.portal.captcha.simplecaptcha.SimpleCaptchaImpl;
021    import com.liferay.portal.convert.ConvertProcess;
022    import com.liferay.portal.kernel.cache.CacheRegistryUtil;
023    import com.liferay.portal.kernel.cache.MultiVMPoolUtil;
024    import com.liferay.portal.kernel.captcha.Captcha;
025    import com.liferay.portal.kernel.captcha.CaptchaUtil;
026    import com.liferay.portal.kernel.cluster.Address;
027    import com.liferay.portal.kernel.cluster.ClusterExecutorUtil;
028    import com.liferay.portal.kernel.cluster.ClusterLinkUtil;
029    import com.liferay.portal.kernel.cluster.ClusterRequest;
030    import com.liferay.portal.kernel.concurrent.ThreadPoolExecutor;
031    import com.liferay.portal.kernel.dao.shard.ShardUtil;
032    import com.liferay.portal.kernel.exception.SystemException;
033    import com.liferay.portal.kernel.executor.PortalExecutorManagerUtil;
034    import com.liferay.portal.kernel.image.GhostscriptUtil;
035    import com.liferay.portal.kernel.image.ImageMagickUtil;
036    import com.liferay.portal.kernel.io.unsync.UnsyncByteArrayOutputStream;
037    import com.liferay.portal.kernel.io.unsync.UnsyncPrintWriter;
038    import com.liferay.portal.kernel.json.JSONFactoryUtil;
039    import com.liferay.portal.kernel.json.JSONObject;
040    import com.liferay.portal.kernel.log.Log;
041    import com.liferay.portal.kernel.log.LogFactoryUtil;
042    import com.liferay.portal.kernel.mail.Account;
043    import com.liferay.portal.kernel.messaging.BaseAsyncDestination;
044    import com.liferay.portal.kernel.messaging.Destination;
045    import com.liferay.portal.kernel.messaging.DestinationNames;
046    import com.liferay.portal.kernel.messaging.MessageBus;
047    import com.liferay.portal.kernel.messaging.MessageBusUtil;
048    import com.liferay.portal.kernel.messaging.proxy.MessageValuesThreadLocal;
049    import com.liferay.portal.kernel.scripting.ScriptingException;
050    import com.liferay.portal.kernel.scripting.ScriptingUtil;
051    import com.liferay.portal.kernel.search.Indexer;
052    import com.liferay.portal.kernel.search.SearchEngineUtil;
053    import com.liferay.portal.kernel.servlet.DirectServletRegistryUtil;
054    import com.liferay.portal.kernel.servlet.SessionErrors;
055    import com.liferay.portal.kernel.servlet.SessionMessages;
056    import com.liferay.portal.kernel.util.CharPool;
057    import com.liferay.portal.kernel.util.Constants;
058    import com.liferay.portal.kernel.util.InstancePool;
059    import com.liferay.portal.kernel.util.MethodHandler;
060    import com.liferay.portal.kernel.util.MethodKey;
061    import com.liferay.portal.kernel.util.ParamUtil;
062    import com.liferay.portal.kernel.util.ProgressStatusConstants;
063    import com.liferay.portal.kernel.util.ProgressTracker;
064    import com.liferay.portal.kernel.util.PropsKeys;
065    import com.liferay.portal.kernel.util.StringBundler;
066    import com.liferay.portal.kernel.util.StringPool;
067    import com.liferay.portal.kernel.util.StringUtil;
068    import com.liferay.portal.kernel.util.ThreadUtil;
069    import com.liferay.portal.kernel.util.Time;
070    import com.liferay.portal.kernel.util.UnsyncPrintWriterPool;
071    import com.liferay.portal.kernel.util.Validator;
072    import com.liferay.portal.kernel.webcache.WebCachePoolUtil;
073    import com.liferay.portal.kernel.xuggler.XugglerUtil;
074    import com.liferay.portal.model.Portlet;
075    import com.liferay.portal.search.lucene.LuceneHelperUtil;
076    import com.liferay.portal.search.lucene.LuceneIndexer;
077    import com.liferay.portal.search.lucene.cluster.LuceneClusterUtil;
078    import com.liferay.portal.security.auth.PrincipalException;
079    import com.liferay.portal.security.permission.PermissionChecker;
080    import com.liferay.portal.service.PortletLocalServiceUtil;
081    import com.liferay.portal.service.ServiceComponentLocalServiceUtil;
082    import com.liferay.portal.struts.ActionConstants;
083    import com.liferay.portal.struts.PortletAction;
084    import com.liferay.portal.theme.ThemeDisplay;
085    import com.liferay.portal.upload.UploadServletRequestImpl;
086    import com.liferay.portal.util.MaintenanceUtil;
087    import com.liferay.portal.util.PortalInstances;
088    import com.liferay.portal.util.PrefsPropsUtil;
089    import com.liferay.portal.util.PropsValues;
090    import com.liferay.portal.util.ShutdownUtil;
091    import com.liferay.portal.util.WebKeys;
092    import com.liferay.portlet.ActionResponseImpl;
093    import com.liferay.portlet.admin.util.CleanUpPermissionsUtil;
094    import com.liferay.portlet.documentlibrary.util.DLPreviewableProcessor;
095    import com.liferay.util.log4j.Log4JUtil;
096    
097    import java.io.File;
098    
099    import java.util.Enumeration;
100    import java.util.HashSet;
101    import java.util.List;
102    import java.util.Map;
103    import java.util.Set;
104    import java.util.concurrent.CountDownLatch;
105    import java.util.concurrent.TimeUnit;
106    
107    import javax.portlet.ActionRequest;
108    import javax.portlet.ActionResponse;
109    import javax.portlet.PortletConfig;
110    import javax.portlet.PortletContext;
111    import javax.portlet.PortletPreferences;
112    import javax.portlet.PortletSession;
113    import javax.portlet.PortletURL;
114    import javax.portlet.WindowState;
115    
116    import org.apache.log4j.Level;
117    import org.apache.struts.action.ActionForm;
118    import org.apache.struts.action.ActionMapping;
119    
120    /**
121     * @author Brian Wing Shun Chan
122     * @author Shuyang Zhou
123     */
124    public class EditServerAction extends PortletAction {
125    
126            @Override
127            public void processAction(
128                            ActionMapping mapping, ActionForm form, PortletConfig portletConfig,
129                            ActionRequest actionRequest, ActionResponse actionResponse)
130                    throws Exception {
131    
132                    ThemeDisplay themeDisplay = (ThemeDisplay)actionRequest.getAttribute(
133                            WebKeys.THEME_DISPLAY);
134    
135                    PermissionChecker permissionChecker =
136                            themeDisplay.getPermissionChecker();
137    
138                    if (!permissionChecker.isOmniadmin()) {
139                            SessionErrors.add(
140                                    actionRequest, PrincipalException.class.getName());
141    
142                            setForward(actionRequest, "portlet.admin.error");
143    
144                            return;
145                    }
146    
147                    PortletPreferences preferences = PrefsPropsUtil.getPreferences();
148    
149                    String cmd = ParamUtil.getString(actionRequest, Constants.CMD);
150    
151                    String redirect = null;
152    
153                    if (cmd.equals("addLogLevel")) {
154                            addLogLevel(actionRequest);
155                    }
156                    else if (cmd.equals("cacheDb")) {
157                            cacheDb();
158                    }
159                    else if (cmd.equals("cacheMulti")) {
160                            cacheMulti();
161                    }
162                    else if (cmd.equals("cacheServlet")) {
163                            cacheServlet();
164                    }
165                    else if (cmd.equals("cacheSingle")) {
166                            cacheSingle();
167                    }
168                    else if (cmd.equals("cleanUpPermissions")) {
169                            CleanUpPermissionsUtil.cleanUpAddToPagePermissions(actionRequest);
170                    }
171                    else if (cmd.startsWith("convertProcess.")) {
172                            redirect = convertProcess(actionRequest, actionResponse, cmd);
173                    }
174                    else if (cmd.equals("dlPreviews")) {
175                            DLPreviewableProcessor.deleteFiles();
176                    }
177                    else if (cmd.equals("gc")) {
178                            gc();
179                    }
180                    else if (cmd.equals("installXuggler")) {
181                            installXuggler(actionRequest, actionResponse);
182    
183                            setForward(actionRequest, ActionConstants.COMMON_NULL);
184    
185                            return;
186                    }
187                    else if (cmd.equals("reindex")) {
188                            reindex(actionRequest);
189                    }
190                    else if (cmd.equals("reindexDictionaries")) {
191                            reindexDictionaries(actionRequest);
192                    }
193                    else if (cmd.equals("runScript")) {
194                            runScript(portletConfig, actionRequest, actionResponse);
195                    }
196                    else if (cmd.equals("shutdown")) {
197                            shutdown(actionRequest);
198                    }
199                    else if (cmd.equals("threadDump")) {
200                            threadDump();
201                    }
202                    else if (cmd.equals("updateCaptcha")) {
203                            updateCaptcha(actionRequest, preferences);
204                    }
205                    else if (cmd.equals("updateExternalServices")) {
206                            updateExternalServices(actionRequest, preferences);
207                    }
208                    else if (cmd.equals("updateFileUploads")) {
209                            updateFileUploads(actionRequest, preferences);
210                    }
211                    else if (cmd.equals("updateLogLevels")) {
212                            updateLogLevels(actionRequest);
213                    }
214                    else if (cmd.equals("updateMail")) {
215                            updateMail(actionRequest, preferences);
216                    }
217                    else if (cmd.equals("verifyPluginTables")) {
218                            verifyPluginTables();
219                    }
220    
221                    sendRedirect(actionRequest, actionResponse, redirect);
222            }
223    
224            protected void addLogLevel(ActionRequest actionRequest) throws Exception {
225                    String loggerName = ParamUtil.getString(actionRequest, "loggerName");
226                    String priority = ParamUtil.getString(actionRequest, "priority");
227    
228                    Log4JUtil.setLevel(loggerName, priority, true);
229            }
230    
231            protected void cacheDb() throws Exception {
232                    CacheRegistryUtil.clear();
233            }
234    
235            protected void cacheMulti() throws Exception {
236                    MultiVMPoolUtil.clear();
237            }
238    
239            protected void cacheServlet() throws Exception {
240                    DirectServletRegistryUtil.clearServlets();
241            }
242    
243            protected void cacheSingle() throws Exception {
244                    WebCachePoolUtil.clear();
245            }
246    
247            protected String convertProcess(
248                            ActionRequest actionRequest, ActionResponse actionResponse,
249                            String cmd)
250                    throws Exception {
251    
252                    ActionResponseImpl actionResponseImpl =
253                            (ActionResponseImpl)actionResponse;
254    
255                    PortletSession portletSession = actionRequest.getPortletSession();
256    
257                    String className = StringUtil.replaceFirst(
258                            cmd, "convertProcess.", StringPool.BLANK);
259    
260                    ConvertProcess convertProcess = (ConvertProcess)InstancePool.get(
261                            className);
262    
263                    String[] parameters = convertProcess.getParameterNames();
264    
265                    if (parameters != null) {
266                            String[] values = new String[parameters.length];
267    
268                            for (int i = 0; i < parameters.length; i++) {
269                                    String parameter =
270                                            className + StringPool.PERIOD + parameters[i];
271    
272                                    if (parameters[i].contains(StringPool.EQUAL)) {
273                                            String[] parameterPair = StringUtil.split(
274                                                    parameters[i], CharPool.EQUAL);
275    
276                                            parameter =
277                                                    className + StringPool.PERIOD + parameterPair[0];
278                                    }
279    
280                                    values[i] = ParamUtil.getString(actionRequest, parameter);
281                            }
282    
283                            convertProcess.setParameterValues(values);
284                    }
285    
286                    String path = convertProcess.getPath();
287    
288                    if (path != null) {
289                            PortletURL portletURL = actionResponseImpl.createRenderURL();
290    
291                            portletURL.setWindowState(WindowState.MAXIMIZED);
292    
293                            portletURL.setParameter("struts_action", path);
294    
295                            return portletURL.toString();
296                    }
297                    else {
298                            MaintenanceUtil.maintain(portletSession.getId(), className);
299    
300                            MessageBusUtil.sendMessage(
301                                    DestinationNames.CONVERT_PROCESS, className);
302    
303                            return null;
304                    }
305            }
306    
307            protected void gc() throws Exception {
308                    Runtime.getRuntime().gc();
309            }
310    
311            protected String getFileExtensions(
312                    ActionRequest actionRequest, String name) {
313    
314                    String value = ParamUtil.getString(actionRequest, name);
315    
316                    return value.replace(", .", ",.");
317            }
318    
319            protected void installXuggler(
320                            ActionRequest actionRequest, ActionResponse actionResponse)
321                    throws Exception {
322    
323                    ProgressTracker progressTracker = new ProgressTracker(
324                            actionRequest, WebKeys.XUGGLER_INSTALL_STATUS);
325    
326                    progressTracker.addProgress(
327                            ProgressStatusConstants.DOWNLOADING, 15, "downloading-xuggler");
328                    progressTracker.addProgress(
329                            ProgressStatusConstants.COPYING, 70, "copying-xuggler-files");
330    
331                    progressTracker.initialize();
332    
333                    String jarName = ParamUtil.getString(actionRequest, "jarName");
334    
335                    try {
336                            XugglerUtil.installNativeLibraries(jarName, progressTracker);
337    
338                            JSONObject jsonObject = JSONFactoryUtil.createJSONObject();
339    
340                            jsonObject.put("success", Boolean.TRUE);
341    
342                            writeJSON(actionRequest, actionResponse, jsonObject);
343                    }
344                    catch (Exception e) {
345                            JSONObject jsonObject = JSONFactoryUtil.createJSONObject();
346    
347                            jsonObject.put("exception", e.getMessage());
348                            jsonObject.put("success", Boolean.FALSE);
349    
350                            writeJSON(actionRequest, actionResponse, jsonObject);
351                    }
352    
353                    progressTracker.finish();
354            }
355    
356            protected void reindex(ActionRequest actionRequest) throws Exception {
357                    String portletId = ParamUtil.getString(actionRequest, "portletId");
358    
359                    long[] companyIds = PortalInstances.getCompanyIds();
360    
361                    if (LuceneHelperUtil.isLoadIndexFromClusterEnabled()) {
362                            MessageValuesThreadLocal.setValue(
363                                    ClusterLinkUtil.CLUSTER_FORWARD_MESSAGE, true);
364                    }
365    
366                    Set<String> usedSearchEngineIds = new HashSet<String>();
367    
368                    if (Validator.isNull(portletId)) {
369                            for (long companyId : companyIds) {
370                                    try {
371                                            LuceneIndexer luceneIndexer = new LuceneIndexer(companyId);
372    
373                                            luceneIndexer.reindex();
374    
375                                            usedSearchEngineIds.addAll(
376                                                    luceneIndexer.getUsedSearchEngineIds());
377                                    }
378                                    catch (Exception e) {
379                                            _log.error(e, e);
380                                    }
381                            }
382                    }
383                    else {
384                            Portlet portlet = PortletLocalServiceUtil.getPortletById(
385                                    companyIds[0], portletId);
386    
387                            if (portlet == null) {
388                                    return;
389                            }
390    
391                            List<Indexer> indexers = portlet.getIndexerInstances();
392    
393                            if (indexers == null) {
394                                    return;
395                            }
396    
397                            Set<String> searchEngineIds = new HashSet<String>();
398    
399                            for (Indexer indexer : indexers) {
400                                    searchEngineIds.add(indexer.getSearchEngineId());
401                            }
402    
403                            for (String searchEngineId : searchEngineIds) {
404                                    for (long companyId : companyIds) {
405                                            SearchEngineUtil.deletePortletDocuments(
406                                                    searchEngineId, companyId, portletId);
407                                    }
408                            }
409    
410                            for (Indexer indexer : indexers) {
411                                    for (long companyId : companyIds) {
412                                            ShardUtil.pushCompanyService(companyId);
413    
414                                            try {
415                                                    indexer.reindex(
416                                                            new String[] {String.valueOf(companyId)});
417    
418                                                    usedSearchEngineIds.add(indexer.getSearchEngineId());
419                                            }
420                                            catch (Exception e) {
421                                                    _log.error(e, e);
422                                            }
423                                            finally {
424                                                    ShardUtil.popCompanyService();
425                                            }
426                                    }
427                            }
428                    }
429    
430                    if (LuceneHelperUtil.isLoadIndexFromClusterEnabled()) {
431                            Set<BaseAsyncDestination> searchWriterDestinations =
432                                    new HashSet<BaseAsyncDestination>();
433    
434                            MessageBus messageBus = MessageBusUtil.getMessageBus();
435    
436                            for (String usedSearchEngineId : usedSearchEngineIds) {
437                                    String searchWriterDestinationName =
438                                            SearchEngineUtil.getSearchWriterDestinationName(
439                                                    usedSearchEngineId);
440    
441                                    Destination destination = messageBus.getDestination(
442                                            searchWriterDestinationName);
443    
444                                    if (destination instanceof BaseAsyncDestination) {
445                                            BaseAsyncDestination baseAsyncDestination =
446                                                    (BaseAsyncDestination)destination;
447    
448                                            searchWriterDestinations.add(baseAsyncDestination);
449                                    }
450                            }
451    
452                            submitClusterIndexLoadingSyncJob(
453                                    searchWriterDestinations, companyIds);
454                    }
455            }
456    
457            protected void reindexDictionaries(ActionRequest actionRequest)
458                    throws Exception {
459    
460                    long[] companyIds = PortalInstances.getCompanyIds();
461    
462                    for (long companyId : companyIds) {
463                            SearchEngineUtil.indexDictionaries(companyId);
464                    }
465            }
466    
467            protected void runScript(
468                            PortletConfig portletConfig, ActionRequest actionRequest,
469                            ActionResponse actionResponse)
470                    throws Exception {
471    
472                    String language = ParamUtil.getString(actionRequest, "language");
473                    String script = ParamUtil.getString(actionRequest, "script");
474    
475                    PortletContext portletContext = portletConfig.getPortletContext();
476    
477                    Map<String, Object> portletObjects = ScriptingUtil.getPortletObjects(
478                            portletConfig, portletContext, actionRequest, actionResponse);
479    
480                    UnsyncByteArrayOutputStream unsyncByteArrayOutputStream =
481                            new UnsyncByteArrayOutputStream();
482    
483                    UnsyncPrintWriter unsyncPrintWriter = UnsyncPrintWriterPool.borrow(
484                            unsyncByteArrayOutputStream);
485    
486                    portletObjects.put("out", unsyncPrintWriter);
487    
488                    try {
489                            SessionMessages.add(actionRequest, "language", language);
490                            SessionMessages.add(actionRequest, "script", script);
491    
492                            ScriptingUtil.exec(null, portletObjects, language, script);
493    
494                            unsyncPrintWriter.flush();
495    
496                            SessionMessages.add(
497                                    actionRequest, "scriptOutput",
498                                    unsyncByteArrayOutputStream.toString());
499                    }
500                    catch (ScriptingException se) {
501                            SessionErrors.add(
502                                    actionRequest, ScriptingException.class.getName(), se);
503    
504                            _log.error(se.getMessage());
505                    }
506            }
507    
508            protected void shutdown(ActionRequest actionRequest) throws Exception {
509                    long minutes =
510                            ParamUtil.getInteger(actionRequest, "minutes") * Time.MINUTE;
511                    String message = ParamUtil.getString(actionRequest, "message");
512    
513                    if (minutes <= 0) {
514                            ShutdownUtil.cancel();
515                    }
516                    else {
517                            ShutdownUtil.shutdown(minutes, message);
518                    }
519            }
520    
521            protected void submitClusterIndexLoadingSyncJob(
522                            Set<BaseAsyncDestination> baseAsyncDestinations, long[] companyIds)
523                    throws Exception {
524    
525                    if (_log.isInfoEnabled()) {
526                            StringBundler sb = new StringBundler(
527                                    baseAsyncDestinations.size() + 1);
528    
529                            sb.append("[");
530    
531                            for (BaseAsyncDestination baseAsyncDestination :
532                                            baseAsyncDestinations) {
533    
534                                    sb.append(baseAsyncDestination.getName());
535                                    sb.append(", ");
536                            }
537    
538                            sb.setStringAt("]", sb.index() - 1);
539    
540                            _log.info(
541                                    "Synchronizecluster index loading for destinations " +
542                                            sb.toString());
543                    }
544    
545                    int totalWorkersMaxSize = 0;
546    
547                    for (BaseAsyncDestination baseAsyncDestination :
548                                    baseAsyncDestinations) {
549    
550                            totalWorkersMaxSize += baseAsyncDestination.getWorkersMaxSize();
551                    }
552    
553                    if (_log.isInfoEnabled()) {
554                            _log.info(
555                                    "There are " + totalWorkersMaxSize +
556                                            " synchronization threads");
557                    }
558    
559                    CountDownLatch countDownLatch = new CountDownLatch(
560                            totalWorkersMaxSize + 1);
561    
562                    ClusterLoadingSyncJob slaveClusterLoadingSyncJob =
563                            new ClusterLoadingSyncJob(companyIds, countDownLatch, false);
564    
565                    for (BaseAsyncDestination baseAsyncDestination :
566                                    baseAsyncDestinations) {
567    
568                            ThreadPoolExecutor threadPoolExecutor =
569                                    PortalExecutorManagerUtil.getPortalExecutor(
570                                            baseAsyncDestination.getName());
571    
572                            for (int i = 0; i < baseAsyncDestination.getWorkersMaxSize(); i++) {
573                                    threadPoolExecutor.execute(slaveClusterLoadingSyncJob);
574                            }
575                    }
576    
577                    ClusterLoadingSyncJob masterClusterLoadingSyncJob =
578                            new ClusterLoadingSyncJob(companyIds, countDownLatch, true);
579    
580                    ThreadPoolExecutor threadPoolExecutor =
581                            PortalExecutorManagerUtil.getPortalExecutor(
582                                    EditServerAction.class.getName());
583    
584                    threadPoolExecutor.execute(masterClusterLoadingSyncJob);
585            }
586    
587            protected void threadDump() throws Exception {
588                    if (_log.isInfoEnabled()) {
589                            _log.info(ThreadUtil.threadDump());
590                    }
591                    else {
592                            _log.error(
593                                    "Thread dumps require the log level to be at least INFO for " +
594                                            getClass().getName());
595                    }
596            }
597    
598            protected void updateCaptcha(
599                            ActionRequest actionRequest, PortletPreferences preferences)
600                    throws Exception {
601    
602                    boolean reCaptchaEnabled = ParamUtil.getBoolean(
603                            actionRequest, "reCaptchaEnabled");
604                    String reCaptchaPrivateKey = ParamUtil.getString(
605                            actionRequest, "reCaptchaPrivateKey");
606                    String reCaptchaPublicKey = ParamUtil.getString(
607                            actionRequest, "reCaptchaPublicKey");
608    
609                    Captcha captcha = null;
610    
611                    if (reCaptchaEnabled) {
612                            captcha = new ReCaptchaImpl();
613                    }
614                    else {
615                            captcha = new SimpleCaptchaImpl();
616                    }
617    
618                    validateCaptcha(actionRequest);
619    
620                    if (SessionErrors.isEmpty(actionRequest)) {
621                            preferences.setValue(
622                                    PropsKeys.CAPTCHA_ENGINE_IMPL, captcha.getClass().getName());
623                            preferences.setValue(
624                                    PropsKeys.CAPTCHA_ENGINE_RECAPTCHA_KEY_PRIVATE,
625                                    reCaptchaPrivateKey);
626                            preferences.setValue(
627                                    PropsKeys.CAPTCHA_ENGINE_RECAPTCHA_KEY_PUBLIC,
628                                    reCaptchaPublicKey);
629    
630                            preferences.store();
631    
632                            CaptchaImpl captchaImpl = (CaptchaImpl)CaptchaUtil.getCaptcha();
633    
634                            captchaImpl.setCaptcha(captcha);
635                    }
636            }
637    
638            protected void updateExternalServices(
639                            ActionRequest actionRequest, PortletPreferences preferences)
640                    throws Exception {
641    
642                    boolean imageMagickEnabled = ParamUtil.getBoolean(
643                            actionRequest, "imageMagickEnabled");
644                    String imageMagickPath = ParamUtil.getString(
645                            actionRequest, "imageMagickPath");
646                    boolean openOfficeEnabled = ParamUtil.getBoolean(
647                            actionRequest, "openOfficeEnabled");
648                    int openOfficePort = ParamUtil.getInteger(
649                            actionRequest, "openOfficePort");
650                    boolean xugglerEnabled = ParamUtil.getBoolean(
651                            actionRequest, "xugglerEnabled");
652    
653                    preferences.setValue(
654                            PropsKeys.IMAGEMAGICK_ENABLED, String.valueOf(imageMagickEnabled));
655                    preferences.setValue(
656                            PropsKeys.IMAGEMAGICK_GLOBAL_SEARCH_PATH, imageMagickPath);
657                    preferences.setValue(
658                            PropsKeys.OPENOFFICE_SERVER_ENABLED,
659                            String.valueOf(openOfficeEnabled));
660                    preferences.setValue(
661                            PropsKeys.OPENOFFICE_SERVER_PORT, String.valueOf(openOfficePort));
662                    preferences.setValue(
663                            PropsKeys.XUGGLER_ENABLED, String.valueOf(xugglerEnabled));
664    
665                    Enumeration<String> enu = actionRequest.getParameterNames();
666    
667                    while (enu.hasMoreElements()) {
668                            String name = enu.nextElement();
669    
670                            if (name.startsWith("imageMagickLimit")) {
671                                    String key = name.substring(16, name.length()).toLowerCase();
672                                    String value = ParamUtil.getString(actionRequest, name);
673    
674                                    preferences.setValue(
675                                            PropsKeys.IMAGEMAGICK_RESOURCE_LIMIT + key, value);
676                            }
677                    }
678    
679                    preferences.store();
680    
681                    GhostscriptUtil.reset();
682                    ImageMagickUtil.reset();
683            }
684    
685            protected void updateFileUploads(
686                            ActionRequest actionRequest, PortletPreferences preferences)
687                    throws Exception {
688    
689                    long dlFileEntryThumbnailMaxHeight = ParamUtil.getLong(
690                            actionRequest, "dlFileEntryThumbnailMaxHeight");
691                    long dlFileEntryThumbnailMaxWidth = ParamUtil.getLong(
692                            actionRequest, "dlFileEntryThumbnailMaxWidth");
693                    String dlFileExtensions = getFileExtensions(
694                            actionRequest, "dlFileExtensions");
695                    long dlFileMaxSize = ParamUtil.getLong(actionRequest, "dlFileMaxSize");
696                    String journalImageExtensions = getFileExtensions(
697                            actionRequest, "journalImageExtensions");
698                    long journalImageSmallMaxSize = ParamUtil.getLong(
699                            actionRequest, "journalImageSmallMaxSize");
700                    String shoppingImageExtensions = getFileExtensions(
701                            actionRequest, "shoppingImageExtensions");
702                    long scImageMaxSize = ParamUtil.getLong(
703                            actionRequest, "scImageMaxSize");
704                    long scImageThumbnailMaxHeight = ParamUtil.getLong(
705                            actionRequest, "scImageThumbnailMaxHeight");
706                    long scImageThumbnailMaxWidth = ParamUtil.getLong(
707                            actionRequest, "scImageThumbnailMaxWidth");
708                    long shoppingImageLargeMaxSize = ParamUtil.getLong(
709                            actionRequest, "shoppingImageLargeMaxSize");
710                    long shoppingImageMediumMaxSize = ParamUtil.getLong(
711                            actionRequest, "shoppingImageMediumMaxSize");
712                    long shoppingImageSmallMaxSize = ParamUtil.getLong(
713                            actionRequest, "shoppingImageSmallMaxSize");
714                    long uploadServletRequestImplMaxSize = ParamUtil.getLong(
715                            actionRequest, "uploadServletRequestImplMaxSize");
716                    String uploadServletRequestImplTempDir = ParamUtil.getString(
717                            actionRequest, "uploadServletRequestImplTempDir");
718                    long usersImageMaxSize = ParamUtil.getLong(
719                            actionRequest, "usersImageMaxSize");
720    
721                    preferences.setValue(
722                            PropsKeys.DL_FILE_ENTRY_THUMBNAIL_MAX_HEIGHT,
723                            String.valueOf(dlFileEntryThumbnailMaxHeight));
724                    preferences.setValue(
725                            PropsKeys.DL_FILE_ENTRY_THUMBNAIL_MAX_WIDTH,
726                            String.valueOf(dlFileEntryThumbnailMaxWidth));
727                    preferences.setValue(PropsKeys.DL_FILE_EXTENSIONS, dlFileExtensions);
728                    preferences.setValue(
729                            PropsKeys.DL_FILE_MAX_SIZE, String.valueOf(dlFileMaxSize));
730                    preferences.setValue(
731                            PropsKeys.JOURNAL_IMAGE_EXTENSIONS, journalImageExtensions);
732                    preferences.setValue(
733                            PropsKeys.JOURNAL_IMAGE_SMALL_MAX_SIZE,
734                            String.valueOf(journalImageSmallMaxSize));
735                    preferences.setValue(
736                            PropsKeys.SHOPPING_IMAGE_EXTENSIONS, shoppingImageExtensions);
737                    preferences.setValue(
738                            PropsKeys.SHOPPING_IMAGE_LARGE_MAX_SIZE,
739                            String.valueOf(shoppingImageLargeMaxSize));
740                    preferences.setValue(
741                            PropsKeys.SHOPPING_IMAGE_MEDIUM_MAX_SIZE,
742                            String.valueOf(shoppingImageMediumMaxSize));
743                    preferences.setValue(
744                            PropsKeys.SHOPPING_IMAGE_SMALL_MAX_SIZE,
745                            String.valueOf(shoppingImageSmallMaxSize));
746                    preferences.setValue(
747                            PropsKeys.SC_IMAGE_MAX_SIZE, String.valueOf(scImageMaxSize));
748                    preferences.setValue(
749                            PropsKeys.SC_IMAGE_THUMBNAIL_MAX_HEIGHT,
750                            String.valueOf(scImageThumbnailMaxHeight));
751                    preferences.setValue(
752                            PropsKeys.SC_IMAGE_THUMBNAIL_MAX_WIDTH,
753                            String.valueOf(scImageThumbnailMaxWidth));
754                    preferences.setValue(
755                            PropsKeys.UPLOAD_SERVLET_REQUEST_IMPL_MAX_SIZE,
756                            String.valueOf(uploadServletRequestImplMaxSize));
757    
758                    if (Validator.isNotNull(uploadServletRequestImplTempDir)) {
759                            preferences.setValue(
760                                    PropsKeys.UPLOAD_SERVLET_REQUEST_IMPL_TEMP_DIR,
761                                    uploadServletRequestImplTempDir);
762    
763                            UploadServletRequestImpl.setTempDir(
764                                    new File(uploadServletRequestImplTempDir));
765                    }
766    
767                    preferences.setValue(
768                            PropsKeys.USERS_IMAGE_MAX_SIZE, String.valueOf(usersImageMaxSize));
769    
770                    preferences.store();
771            }
772    
773            protected void updateLogLevels(ActionRequest actionRequest)
774                    throws Exception {
775    
776                    Enumeration<String> enu = actionRequest.getParameterNames();
777    
778                    while (enu.hasMoreElements()) {
779                            String name = enu.nextElement();
780    
781                            if (name.startsWith("logLevel")) {
782                                    String loggerName = name.substring(8);
783    
784                                    String priority = ParamUtil.getString(
785                                            actionRequest, name, Level.INFO.toString());
786    
787                                    Log4JUtil.setLevel(loggerName, priority, true);
788                            }
789                    }
790            }
791    
792            protected void updateMail(
793                            ActionRequest actionRequest, PortletPreferences preferences)
794                    throws Exception {
795    
796                    String advancedProperties = ParamUtil.getString(
797                            actionRequest, "advancedProperties");
798                    String pop3Host = ParamUtil.getString(actionRequest, "pop3Host");
799                    String pop3Password = ParamUtil.getString(
800                            actionRequest, "pop3Password");
801                    int pop3Port = ParamUtil.getInteger(actionRequest, "pop3Port");
802                    boolean pop3Secure = ParamUtil.getBoolean(actionRequest, "pop3Secure");
803                    String pop3User = ParamUtil.getString(actionRequest, "pop3User");
804                    String smtpHost = ParamUtil.getString(actionRequest, "smtpHost");
805                    String smtpPassword = ParamUtil.getString(
806                            actionRequest, "smtpPassword");
807                    int smtpPort = ParamUtil.getInteger(actionRequest, "smtpPort");
808                    boolean smtpSecure = ParamUtil.getBoolean(actionRequest, "smtpSecure");
809                    String smtpUser = ParamUtil.getString(actionRequest, "smtpUser");
810    
811                    String storeProtocol = Account.PROTOCOL_POP;
812    
813                    if (pop3Secure) {
814                            storeProtocol = Account.PROTOCOL_POPS;
815                    }
816    
817                    String transportProtocol = Account.PROTOCOL_SMTP;
818    
819                    if (smtpSecure) {
820                            transportProtocol = Account.PROTOCOL_SMTPS;
821                    }
822    
823                    preferences.setValue(PropsKeys.MAIL_SESSION_MAIL, "true");
824                    preferences.setValue(
825                            PropsKeys.MAIL_SESSION_MAIL_ADVANCED_PROPERTIES,
826                            advancedProperties);
827                    preferences.setValue(PropsKeys.MAIL_SESSION_MAIL_POP3_HOST, pop3Host);
828                    preferences.setValue(
829                            PropsKeys.MAIL_SESSION_MAIL_POP3_PASSWORD, pop3Password);
830                    preferences.setValue(
831                            PropsKeys.MAIL_SESSION_MAIL_POP3_PORT, String.valueOf(pop3Port));
832                    preferences.setValue(PropsKeys.MAIL_SESSION_MAIL_POP3_USER, pop3User);
833                    preferences.setValue(PropsKeys.MAIL_SESSION_MAIL_SMTP_HOST, smtpHost);
834                    preferences.setValue(
835                            PropsKeys.MAIL_SESSION_MAIL_SMTP_PASSWORD, smtpPassword);
836                    preferences.setValue(
837                            PropsKeys.MAIL_SESSION_MAIL_SMTP_PORT, String.valueOf(smtpPort));
838                    preferences.setValue(PropsKeys.MAIL_SESSION_MAIL_SMTP_USER, smtpUser);
839                    preferences.setValue(
840                            PropsKeys.MAIL_SESSION_MAIL_STORE_PROTOCOL, storeProtocol);
841                    preferences.setValue(
842                            PropsKeys.MAIL_SESSION_MAIL_TRANSPORT_PROTOCOL, transportProtocol);
843    
844                    preferences.store();
845    
846                    MailServiceUtil.clearSession();
847            }
848    
849            protected void validateCaptcha(ActionRequest actionRequest)
850                    throws Exception {
851    
852                    boolean reCaptchaEnabled = ParamUtil.getBoolean(
853                            actionRequest, "reCaptchaEnabled");
854    
855                    if (!reCaptchaEnabled) {
856                            return;
857                    }
858    
859                    String reCaptchaPrivateKey = ParamUtil.getString(
860                            actionRequest, "reCaptchaPrivateKey");
861                    String reCaptchaPublicKey = ParamUtil.getString(
862                            actionRequest, "reCaptchaPublicKey");
863    
864                    if (Validator.isNull(reCaptchaPublicKey)) {
865                            SessionErrors.add(actionRequest, "reCaptchaPublicKey");
866                    }
867                    else if (Validator.isNull(reCaptchaPrivateKey)) {
868                            SessionErrors.add(actionRequest, "reCaptchaPrivateKey");
869                    }
870            }
871    
872            protected void verifyPluginTables() throws Exception {
873                    ServiceComponentLocalServiceUtil.verifyDB();
874            }
875    
876            private static Log _log = LogFactoryUtil.getLog(EditServerAction.class);
877    
878            private static MethodKey _loadIndexesFromClusterMethodKey = new MethodKey(
879                    LuceneClusterUtil.class, "loadIndexesFromCluster", long[].class,
880                    Address.class);
881    
882            private static class ClusterLoadingSyncJob implements Runnable {
883    
884                    public ClusterLoadingSyncJob(
885                            long[] companyIds, CountDownLatch countDownLatch, boolean master) {
886    
887                            _companyIds = companyIds;
888                            _countDownLatch = countDownLatch;
889                            _master = master;
890                    }
891    
892                    public void run() {
893                            _countDownLatch.countDown();
894    
895                            String logPrefix = StringPool.BLANK;
896    
897                            if (_log.isInfoEnabled()) {
898                                    Thread currentThread = Thread.currentThread();
899    
900                                    if (_master) {
901                                            logPrefix =
902                                                    "Monitor thread name " + currentThread.getName() +
903                                                            " with thread ID " + currentThread.getId();
904                                    }
905                                    else {
906                                            logPrefix =
907                                                    "Thread name " + currentThread.getName() +
908                                                            " with thread ID " + currentThread.getId();
909                                    }
910                            }
911    
912                            if (!_master && _log.isInfoEnabled()) {
913                                    _log.info(
914                                            logPrefix + " synchronized on latch. Waiting for others.");
915                            }
916    
917                            try {
918                                    if (_master) {
919                                            _countDownLatch.await();
920                                    }
921                                    else {
922                                            boolean result = _countDownLatch.await(
923                                                    PropsValues.LUCENE_CLUSTER_INDEX_LOADING_SYNC_TIMEOUT,
924                                                    TimeUnit.MILLISECONDS);
925    
926                                            if (!result) {
927                                                    _log.error(
928                                                            logPrefix + " timed out. You may need to " +
929                                                                    "re-trigger a reindex process.");
930                                            }
931                                    }
932                            }
933                            catch (InterruptedException ie) {
934                                    if (_master) {
935                                            _log.error(
936                                                    logPrefix + " was interrupted. Skip cluster index " +
937                                                            "loading notification.",
938                                                    ie);
939    
940                                            return;
941                                    }
942                                    else {
943                                            _log.error(
944                                                    logPrefix + " was interrupted. You may need to " +
945                                                            "re-trigger a reindex process.",
946                                                    ie);
947                                    }
948                            }
949    
950                            if (_master) {
951                                    Address localClusterNodeAddress =
952                                            ClusterExecutorUtil.getLocalClusterNodeAddress();
953    
954                                    ClusterRequest clusterRequest =
955                                            ClusterRequest.createMulticastRequest(
956                                                    new MethodHandler(
957                                                            _loadIndexesFromClusterMethodKey, _companyIds,
958                                                            localClusterNodeAddress),
959                                                    true);
960    
961                                    try {
962                                            ClusterExecutorUtil.execute(clusterRequest);
963                                    }
964                                    catch (SystemException se) {
965                                            _log.error(
966                                                    "Unable to notify peers to start index loading", se);
967                                    }
968    
969                                    if (_log.isInfoEnabled()) {
970                                            _log.info(
971                                                    logPrefix + " unlocked latch. Notified peers to " +
972                                                            "start index loading.");
973                                    }
974                            }
975                    }
976    
977                    private long[] _companyIds;
978                    private CountDownLatch _countDownLatch;
979                    private boolean _master;
980    
981            }
982    
983    }