/*
* Copyright (C) 2003-2008 eXo Platform SAS.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Affero General Public License
* as published by the Free Software Foundation; either version 3
* of the License, or (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see<http://www.gnu.org/licenses/>.
*/
package org.exoplatform.services.wcm.search;
import java.io.ByteArrayOutputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.security.AccessControlException;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.MissingResourceException;
import java.util.ResourceBundle;
import javax.jcr.Node;
import javax.jcr.Session;
import javax.jcr.lock.LockException;
import javax.jcr.version.VersionException;
import org.exoplatform.commons.utils.ListAccess;
import org.exoplatform.portal.application.PortalRequestContext;
import org.exoplatform.portal.config.DataStorage;
import org.exoplatform.portal.config.Query;
import org.exoplatform.portal.config.UserACL;
import org.exoplatform.portal.config.UserPortalConfig;
import org.exoplatform.portal.config.UserPortalConfigService;
import org.exoplatform.portal.config.model.Page;
import org.exoplatform.portal.config.model.PortalConfig;
import org.exoplatform.portal.mop.navigation.Scope;
import org.exoplatform.portal.mop.user.UserNavigation;
import org.exoplatform.portal.mop.user.UserNode;
import org.exoplatform.portal.mop.user.UserPortal;
import org.exoplatform.portal.pom.config.POMSession;
import org.exoplatform.portal.pom.config.POMSessionManager;
import org.exoplatform.services.ecm.publication.IncorrectStateUpdateLifecycleException;
import org.exoplatform.services.ecm.publication.PublicationService;
import org.exoplatform.services.jcr.ext.common.SessionProvider;
import org.exoplatform.services.wcm.portal.LivePortalManagerService;
import org.exoplatform.services.wcm.publication.PublicationDefaultStates;
import org.exoplatform.services.wcm.publication.PublicationUtil;
import org.exoplatform.services.wcm.publication.WCMComposer;
import org.exoplatform.services.wcm.publication.WCMPublicationService;
import org.exoplatform.services.wcm.publication.WebpagePublicationPlugin;
import org.exoplatform.services.wcm.utils.WCMCoreUtils;
import org.exoplatform.webui.core.UIComponent;
import org.exoplatform.webui.form.UIForm;
/**
* Created by The eXo Platform SAS
* Author : Hoa Pham
* hoa.pham@exoplatform.com
* Sep 30, 2008
*/
public class DumpPublicationPlugin extends WebpagePublicationPlugin{
/** The Constant DEFAULT_STATE. */
public static final String DEFAULT_STATE = PublicationDefaultStates.DRAFT;
/** The Constant PUBLICATION. */
public static final String PUBLICATION = "publication:publication";
/** The Constant LIFECYCLE_PROP. */
public static final String LIFECYCLE_PROP = "publication:lifecycleName";
/** The Constant CURRENT_STATE. */
public static final String CURRENT_STATE = "publication:currentState";
/** The Constant HISTORY. */
public static final String HISTORY = "publication:history";
/** The Constant WCM_PUBLICATION_MIXIN. */
public static final String WCM_PUBLICATION_MIXIN = "publication:simplePublication";
/** The Constant LIFECYCLE_NAME. */
public static final String LIFECYCLE_NAME = "Simple publication";
/** The Constant LOCALE_FILE. */
private static final String LOCALE_FILE = "locale.services.publication.lifecycle.simple.SimplePublication";
/** The Constant IMG_PATH. */
public static final String IMG_PATH = "artifacts/";
/**
* Instantiates a new wCM publication plugin.
*/
public DumpPublicationPlugin() {
}
public String getLifecycleType() {
return WCM_PUBLICATION_MIXIN;
}
/* (non-Javadoc)
* @see org.exoplatform.services.ecm.publication.PublicationPlugin#addMixin(javax.jcr.Node)
*/
public void addMixin(Node node) throws Exception {
node.addMixin(WCM_PUBLICATION_MIXIN);
}
/* (non-Javadoc)
* @see org.exoplatform.services.ecm.publication.PublicationPlugin#canAddMixin(javax.jcr.Node)
*/
public boolean canAddMixin(Node node) throws Exception {
List<String> runningPortals = getRunningPortals(node.getSession().getUserID());
if(runningPortals.size() == 0) {
throw new AccessControlException("Current user doesn't have access permission to any portal");
}
if (node.isLocked()) {
throw new LockException("This node is locked");
}
if (!node.isCheckedOut()) {
throw new VersionException("This node is checked-in");
}
return node.canAddMixin(WCM_PUBLICATION_MIXIN);
}
/* (non-Javadoc)
* @see org.exoplatform.services.ecm.publication.PublicationPlugin#changeState(javax.jcr.Node, java.lang.String, java.util.HashMap)
*/
public void changeState(Node node, String newState, HashMap<String, String> context) throws IncorrectStateUpdateLifecycleException, Exception {
Session session = node.getSession();
node.setProperty(CURRENT_STATE, newState);
PublicationService publicationService = WCMCoreUtils.getService(PublicationService.class);
if (newState.equals(PublicationDefaultStates.DRAFT)) {
String lifecycleName = node.getProperty("publication:lifecycleName").getString();
String[] logs = new String[] {new Date().toString(), PublicationDefaultStates.DRAFT, session.getUserID(), "PublicationService.SimplePublicationPlugin.changeState.enrolled", lifecycleName};
publicationService.addLog(node, logs);
} else if (newState.equals(PublicationDefaultStates.PUBLISHED)) {
String[] logs = new String[] {new Date().toString(), PublicationDefaultStates.PUBLISHED, session.getUserID(), "PublicationService.SimplePublicationPlugin.changeState.published"};
publicationService.addLog(node, logs);
} else if (newState.equals(PublicationDefaultStates.ENROLLED)) {
String[] logs = new String[] {new Date().toString(), PublicationDefaultStates.ENROLLED, session.getUserID(), "PublicationService.SimplePublicationPlugin.changeState.published"};
publicationService.addLog(node, logs);
} else {
throw new Exception("WCMPublicationPlugin.changeState : Unknown state : " + node.getProperty(CURRENT_STATE).getString());
}
session.save();
}
/* (non-Javadoc)
* @see org.exoplatform.services.ecm.publication.PublicationPlugin#getPossibleStates()
*/
public String[] getPossibleStates() { return new String[] { PublicationDefaultStates.ENROLLED, PublicationDefaultStates.DRAFT, PublicationDefaultStates.PUBLISHED}; }
/* (non-Javadoc)
* @see org.exoplatform.services.ecm.publication.PublicationPlugin#getStateImage(javax.jcr.Node, java.util.Locale)
*/
public byte[] getStateImage(Node node, Locale locale) throws IOException,
FileNotFoundException, Exception {
byte[] bytes = null;
String fileName= "WCM";
String currentState = node.getProperty(CURRENT_STATE).getString();
if (PublicationDefaultStates.PUBLISHED.equals(currentState)) {
fileName+="Published";
} else {
fileName+="Unpublished";
}
String fileNameLocalized =fileName+"_"+locale.getLanguage();
String completeFileName=IMG_PATH+fileNameLocalized+".gif";
InputStream in = this.getClass().getClassLoader().getResourceAsStream(completeFileName);
if (in==null) {
completeFileName=IMG_PATH+fileName+".gif";
in = this.getClass().getClassLoader().getResourceAsStream(completeFileName);
}
ByteArrayOutputStream out = new ByteArrayOutputStream();
transfer(in, out);
bytes = out.toByteArray();
return bytes;
}
/** The Constant BUFFER_SIZE. */
private static final int BUFFER_SIZE = 512;
/**
* Transfer.
*
* @param in the in
* @param out the out
*
* @return the int
*
* @throws IOException Signals that an I/O exception has occurred.
*/
public static int transfer(InputStream in, OutputStream out) throws IOException {
int total = 0;
byte[] buffer = new byte[BUFFER_SIZE];
int bytesRead = in.read( buffer );
while ( bytesRead != -1 ) {
out.write( buffer, 0, bytesRead );
total += bytesRead;
bytesRead = in.read( buffer );
}
return total;
}
/* (non-Javadoc)
* @see org.exoplatform.services.ecm.publication.PublicationPlugin#getStateUI(javax.jcr.Node, org.exoplatform.webui.core.UIComponent)
*/
public UIForm getStateUI(Node node, UIComponent component) throws Exception {
return null;
}
/* (non-Javadoc)
* @see org.exoplatform.services.ecm.publication.PublicationPlugin#getUserInfo(javax.jcr.Node, java.util.Locale)
*/
public String getUserInfo(Node node, Locale locale) throws Exception {
return null;
}
/**
* Retrives all the running portals.
*
* @param userId the user id
*
* @return the running portals
*
* @throws Exception the exception
*/
private List<String> getRunningPortals(String userId) throws Exception {
POMSessionManager manager = WCMCoreUtils.getService(POMSessionManager.class);
POMSession session = null;
if (manager.getSession() == null) session = manager.openSession();
List<String> listPortalName = new ArrayList<String>();
DataStorage service = WCMCoreUtils.getService(DataStorage.class);
Query<PortalConfig> query = new Query<PortalConfig>(null, null, null, null, PortalConfig.class) ;
ListAccess<PortalConfig> pageList = service.find2(query) ;
List<PortalConfig> portalConfigs = WCMCoreUtils.getAllElementsOfListAccess(pageList);
UserACL userACL = WCMCoreUtils.getService(UserACL.class);
for(PortalConfig portalConfig : portalConfigs) {
if(userACL.hasPermission(portalConfig)) {
listPortalName.add(portalConfig.getName());
}
}
if (session != null) session.close();
return listPortalName;
}
/**
* Gets the services.
*
* @param page the page
*
* @return the services
*
* @throws Exception the exception
*/
public List<String> getListUserNavigationUri(Page page, String remoteUser) throws Exception {
List<String> listPageNavigationUri = new ArrayList<String>();
for (String portalName : getRunningPortals(remoteUser)) {
UserPortalConfigService userPortalConfigService = WCMCoreUtils.getService(UserPortalConfigService.class);
UserPortalConfig userPortalCfg = userPortalConfigService.getUserPortalConfig(portalName,
remoteUser,
PortalRequestContext.USER_PORTAL_CONTEXT);
UserPortal userPortal = userPortalCfg.getUserPortal();
//get nodes
List<UserNavigation> navigationList = userPortal.getNavigations();
for(UserNavigation nav : navigationList) {
UserNode root = userPortal.getNode(nav, Scope.ALL, null, null);
List<UserNode> userNodeList = PublicationUtil.findUserNodeByPageId(root, page.getPageId());
for (UserNode node : userNodeList) {
listPageNavigationUri.add(PublicationUtil.setMixedNavigationUri(portalName, node.getURI()));
}
}
}
return listPageNavigationUri;
}
/**
* Checks if is shared portal.
*
* @param portalName the portal name
*
* @return true, if is shared portal
*
* @throws Exception the exception
*/
@SuppressWarnings("unused")
private boolean isSharedPortal(String portalName) throws Exception{
LivePortalManagerService livePortalManagerService = WCMCoreUtils.getService(LivePortalManagerService.class);
SessionProvider sessionProvider = WCMCoreUtils.getSystemSessionProvider();
Node sharedPortal = livePortalManagerService.getLiveSharedPortal(sessionProvider);
return sharedPortal.getName().equals(portalName);
}
/* (non-Javadoc)
* @see org.exoplatform.services.ecm.publication.PublicationPlugin#getNodeView(javax.jcr.Node, java.util.Map)
*/
public Node getNodeView(Node node, Map<String, Object> context) throws Exception {
WCMPublicationService wcmPublicationService = WCMCoreUtils.getService(WCMPublicationService.class);
String contentState = wcmPublicationService.getContentState(node);
// if node is obsolette
if (PublicationDefaultStates.OBSOLETE.equals(contentState)) return null;
// if current mode is edit mode
if (context.get(WCMComposer.FILTER_MODE).equals(WCMComposer.MODE_EDIT)) return node;
// if current mode is live mode and content is NOT draft
if (!PublicationDefaultStates.DRAFT.equals(contentState)) return node;
// else
return null;
}
/* (non-Javadoc)
* @see org.exoplatform.services.ecm.publication.PublicationPlugin#getLocalizedAndSubstituteMessage(java.util.Locale, java.lang.String, java.lang.String[])
*/
public String getLocalizedAndSubstituteMessage(Locale locale, String key, String[] values)
throws Exception {
ClassLoader cl=this.getClass().getClassLoader();
ResourceBundle resourceBundle= ResourceBundle.getBundle(LOCALE_FILE, locale, cl);
String result = "";
try {
result = resourceBundle.getString(key);
} catch (MissingResourceException e) {
result = key;
}
if(values != null) {
return String.format(result, (Object[])values);
}
return result;
}
@Override
public void updateLifecyleOnChangeContent(Node node, String remoteUser) throws Exception {
updateLifecyleOnChangeContent(node, remoteUser, PublicationDefaultStates.DRAFT);
}
@Override
public void updateLifecyleOnChangeContent(Node node, String remoteUser, String newState) throws Exception {
String state = node.getProperty(CURRENT_STATE).getString();
if (PublicationDefaultStates.DRAFT.equalsIgnoreCase(state)
&& PublicationDefaultStates.DRAFT.equals(newState))
return;
HashMap<String, String> context = new HashMap<String, String>();
changeState(node, newState, context);
}
}