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