/* * Copyright (C) 2003-2017 eXo Platform SAS. * * This is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this software; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA, or see the FSF site: http://www.fsf.org. */ package org.exoplatform.management.uiextension; import org.exoplatform.container.ExoContainerContext; import org.exoplatform.container.PortalContainer; import org.exoplatform.container.component.RequestLifeCycle; import org.exoplatform.management.service.api.Resource; import org.exoplatform.management.service.api.StagingService; import org.exoplatform.management.service.api.SynchronizationService; import org.exoplatform.management.service.api.TargetServer; import org.exoplatform.management.service.handler.ResourceHandlerLocator; import org.exoplatform.management.service.handler.mop.MOPSiteHandler; import org.exoplatform.portal.mop.user.UserNode; import org.exoplatform.portal.webui.util.Util; import org.exoplatform.services.log.ExoLogger; import org.exoplatform.services.log.Log; import org.exoplatform.wcm.webui.Utils; import org.exoplatform.web.application.ApplicationMessage; import org.exoplatform.webui.application.WebuiRequestContext; import org.exoplatform.webui.config.annotation.ComponentConfig; import org.exoplatform.webui.config.annotation.EventConfig; import org.exoplatform.webui.core.UIPopupContainer; import org.exoplatform.webui.core.lifecycle.UIFormLifecycle; import org.exoplatform.webui.core.model.SelectItemOption; import org.exoplatform.webui.event.Event; import org.exoplatform.webui.event.EventListener; import org.exoplatform.webui.form.UIForm; import org.exoplatform.webui.form.UIFormInputInfo; import org.exoplatform.webui.form.UIFormSelectBox; import java.net.ConnectException; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.ResourceBundle; /** * The Class PushSiteForm. * * @author <a href="mailto:bkhanfir@exoplatform.com">Boubaker Khanfir</a> * @version $Revision$ */ @ComponentConfig(lifecycle = UIFormLifecycle.class, template = "classpath:groovy/webui/component/staging/site/PushSite.gtmpl", events = { @EventConfig(listeners = PushSiteForm.CloseActionListener.class), @EventConfig(listeners = PushSiteForm.PushActionListener.class) }) public class PushSiteForm extends UIForm { /** The Constant LOG. */ private static final Log LOG = ExoLogger.getLogger(PushSiteForm.class.getName()); /** The synchronization started. */ protected boolean synchronizationStarted = false; /** The synchronization finished. */ protected boolean synchronizationFinished = true; /** The synchronization error. */ protected Throwable synchronizationError = null; /** The site handler. */ protected static MOPSiteHandler SITE_HANDLER = (MOPSiteHandler) ResourceHandlerLocator.getResourceHandler(StagingService.SITES_PARENT_PATH);; /** The Constant POPUP_WINDOW. */ public static final String POPUP_WINDOW = "PushSitePopupWindow"; /** The Constant TARGET_SERVER_NAME_FIELD_NAME. */ private static final String TARGET_SERVER_NAME_FIELD_NAME = "targetServer"; /** The Constant INFO_FIELD_NAME. */ private static final String INFO_FIELD_NAME = "info"; /** The synchronization service. */ private SynchronizationService synchronizationService; /** The target servers. */ private List<TargetServer> targetServers; /** The message type. */ String messageType = "info"; /** * Instantiates a new push site form. * * @throws Exception the exception */ public PushSiteForm() throws Exception { addUIFormInput(new UIFormInputInfo(INFO_FIELD_NAME, INFO_FIELD_NAME, "")); addUIFormInput(new UIFormSelectBox(TARGET_SERVER_NAME_FIELD_NAME, TARGET_SERVER_NAME_FIELD_NAME, new ArrayList<SelectItemOption<String>>())); } /** * Inits the. * * @throws Exception the exception */ public void init() throws Exception { List<SelectItemOption<String>> itemOptions = getChild(UIFormSelectBox.class).getOptions(); itemOptions.clear(); try { targetServers = synchronizationService.getSynchonizationServers(); } catch (Exception e) { LOG.warn(e); targetServers = new ArrayList<TargetServer>(); } for (TargetServer targetServer : targetServers) { SelectItemOption<String> selectItemOption = new SelectItemOption<String>(targetServer.getName(), targetServer.getId()); itemOptions.add(selectItemOption); } } /** * {@inheritDoc} */ public String[] getActions() { return new String[] { "Push", "Close" }; } /** * Gets the target servers. * * @return the target servers */ public List<TargetServer> getTargetServers() { return targetServers; } /** * Gets the resource bundle. * * @return the resource bundle */ public ResourceBundle getResourceBundle() { return WebuiRequestContext.getCurrentInstance().getApplicationResourceBundle(); } /** * Sets the synchronization service. * * @param synchronizationService the new synchronization service */ public void setSynchronizationService(SynchronizationService synchronizationService) { this.synchronizationService = synchronizationService; } /** * Checks if is synchronization started. * * @return true, if is synchronization started */ public boolean isSynchronizationStarted() { return synchronizationStarted; } /** * Sets the message. * * @param message the message * @param type the type */ public void setMessage(String message, String type) { getUIFormInputInfo(INFO_FIELD_NAME).setValue(message); messageType = type; } /** * Close popup. * * @param pushSiteForm the push site form * @param context the context */ private static void closePopup(PushSiteForm pushSiteForm, WebuiRequestContext context) { UIPopupContainer popupContainer = pushSiteForm.getAncestorOfType(UIPopupContainer.class); if (popupContainer != null) popupContainer.removeChildById(POPUP_WINDOW); context.addUIComponentToUpdateByAjax(popupContainer); } /** * The listener interface for receiving closeAction events. * The class that is interested in processing a closeAction * event implements this interface, and the object created * with that class is registered with a component using the * component's <code>addCloseActionListener</code> method. When * the closeAction event occurs, that object's appropriate * method is invoked. * */ static public class CloseActionListener extends EventListener<PushSiteForm> { /** * {@inheritDoc} */ public void execute(Event<PushSiteForm> event) throws Exception { closePopup(event.getSource(), event.getRequestContext()); } } /** * The listener interface for receiving pushAction events. * The class that is interested in processing a pushAction * event implements this interface, and the object created * with that class is registered with a component using the * component's <code>addPushActionListener</code> method. When * the pushAction event occurs, that object's appropriate * method is invoked. * */ static public class PushActionListener extends EventListener<PushSiteForm> { /** * {@inheritDoc} */ public void execute(Event<PushSiteForm> event) throws Exception { final PushSiteForm pushSiteForm = event.getSource(); ResourceBundle resourceBundle = pushSiteForm.getResourceBundle(); pushSiteForm.setMessage(null, "info"); try { // get target server final TargetServer targetServer = getTargetServer(pushSiteForm); if (targetServer == null) { pushSiteForm.setMessage(resourceBundle.getString("PushSite.msg.targetServerMandatory"), "error"); return; } pushSiteForm.setMessage(resourceBundle.getString("PushSite.msg.synchronizationInProgress"), "info"); if (pushSiteForm.synchronizationFinished && !pushSiteForm.synchronizationStarted) { pushSiteForm.synchronizationStarted = true; pushSiteForm.synchronizationFinished = false; final UserNode userNode = Util.getUIPortal().getSelectedUserNode(); Thread synchronizeThread = new Thread(new Runnable() { @Override public void run() { // Make sure that current container is of type // "PortalContainer" ExoContainerContext.setCurrentContainer(PortalContainer.getInstance()); // Use "PortalContainer" in current transaction RequestLifeCycle.begin(ExoContainerContext.getCurrentContainer()); try { // Synchronize Site synchronizeSite(userNode, targetServer); LOG.info("Synchronization of site '" + userNode.getPageRef().getSite().getName() + "' is done."); } catch (Exception e) { pushSiteForm.synchronizationError = e; } finally { pushSiteForm.synchronizationFinished = true; RequestLifeCycle.end(); } } }); synchronizeThread.start(); } else { if (pushSiteForm.synchronizationStarted) { if (pushSiteForm.synchronizationFinished) { if (pushSiteForm.synchronizationError == null) { pushSiteForm.synchronizationStarted = false; // Update UI Utils.createPopupMessage(pushSiteForm, "PushSite.msg.synchronizationDone", null, ApplicationMessage.INFO); closePopup(event.getSource(), event.getRequestContext()); } else { Throwable tempException = pushSiteForm.synchronizationError; pushSiteForm.synchronizationError = null; pushSiteForm.synchronizationStarted = false; throw tempException; } } } } } catch (Throwable ex) { if (isConnectionException(ex)) { Utils.createPopupMessage(pushSiteForm, "PushSite.msg.unableToConnect", null, ApplicationMessage.ERROR); } else { Utils.createPopupMessage(pushSiteForm, "PushSite.msg.synchronizationError", null, ApplicationMessage.ERROR); } closePopup(event.getSource(), event.getRequestContext()); LOG.error("Synchronization of site '" + Util.getUIPortal().getLabel() + "' failed:", ex); } } /** * Synchronize site. * * @param userNode the user node * @param targetServer the target server * @throws Exception the exception */ private void synchronizeSite(UserNode userNode, TargetServer targetServer) throws Exception { String siteType = userNode.getPageRef().getSite().getType().getName(); String siteName = userNode.getPageRef().getSite().getName(); List<Resource> resources = new ArrayList<Resource>(); Map<String, String> exportOptions = new HashMap<String, String>(); Map<String, String> importOptions = new HashMap<String, String>(); // Synchronize site resources.add(new Resource("/site/" + siteType + "sites/" + siteName, "Site", "Site")); SITE_HANDLER.synchronize(resources, exportOptions, importOptions, targetServer); } /** * Gets the target server. * * @param pushSiteForm the push site form * @return the target server */ private TargetServer getTargetServer(PushSiteForm pushSiteForm) { TargetServer targetServer = null; String targetServerId = pushSiteForm.getUIFormSelectBox(TARGET_SERVER_NAME_FIELD_NAME).getValue(); Iterator<TargetServer> iterator = pushSiteForm.getTargetServers().iterator(); while (iterator.hasNext() && targetServer == null) { TargetServer itTargetServer = iterator.next(); if (itTargetServer.getId().equals(targetServerId)) { targetServer = itTargetServer; } } return targetServer; } /** * Check if the exception has a ConnectionException cause. * * @param ex the ex * @return true, if is connection exception */ private static boolean isConnectionException(Throwable ex) { boolean connectionException = false; Throwable throwable = ex; do { if (throwable instanceof ConnectException) { connectionException = true; } else { throwable = throwable.getCause(); } } while (!connectionException && throwable != null); return connectionException; } } }