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