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