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