/* * Copyright (C) 2003-2007 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.ks.bbcode.core; import java.util.ArrayList; import java.util.List; import javax.jcr.Node; import javax.jcr.NodeIterator; import javax.jcr.query.Query; import javax.jcr.query.QueryManager; import javax.jcr.query.QueryResult; import org.exoplatform.container.ExoContainerContext; import org.exoplatform.ks.bbcode.api.BBCode; import org.exoplatform.ks.bbcode.api.BBCodeService; import org.exoplatform.ks.bbcode.spi.BBCodeData; import org.exoplatform.ks.bbcode.spi.BBCodePlugin; import org.exoplatform.ks.common.jcr.KSDataLocation; import org.exoplatform.ks.common.jcr.SessionManager; import org.exoplatform.management.ManagementAware; import org.exoplatform.management.ManagementContext; import org.exoplatform.management.annotations.Managed; import org.exoplatform.management.annotations.ManagedDescription; import org.exoplatform.management.jmx.annotations.NameTemplate; import org.exoplatform.management.jmx.annotations.Property; import org.exoplatform.services.jcr.ext.common.SessionProvider; import org.exoplatform.services.log.ExoLogger; import org.exoplatform.services.log.Log; import org.picocontainer.Startable; /** * Managed service implementation for {@link BBCodeService}. * Stores BBCodes in JCR at {@link KSDataLocation#getBBCodesLocation()} * @author <a href="mailto:patrice.lamarque@exoplatform.com">Patrice Lamarque</a> * @version $Revision$ */ @Managed @NameTemplate(@Property(key = "service", value = "bbcode")) @ManagedDescription("BBCodes management") public class BBCodeServiceImpl implements Startable, BBCodeService, ManagementAware { public final static String BBCODE_NODE_TYPE = "exo:forumBBCode".intern(); public final static String BBCODE_HOME_NODE_TYPE = "exo:forumBBCodeHome".intern(); private List<BBCodePlugin> plugins; private KSDataLocation dataLocator; private SessionManager sessionManager; private List<String> activeBBCodesCache; private ManagementContext context; private static Log log = ExoLogger.getLogger(BBCodeServiceImpl.class); public BBCodeServiceImpl() { activeBBCodesCache = new ArrayList<String>(); plugins = new ArrayList<BBCodePlugin>(); } public BBCodeServiceImpl(KSDataLocation dataLocator) { this(); setDataLocator(dataLocator); } private Node getBBcodeHome(SessionProvider sProvider) throws Exception { String path = dataLocator.getBBCodesLocation(); return sessionManager.getSession(sProvider).getRootNode().getNode(path); } /** * {@inheritDoc} */ public void registerBBCodePlugin(BBCodePlugin plugin) throws Exception { plugins.add(plugin); } /** * {@inheritDoc} */ public void initDefaultBBCodes() throws Exception { SessionProvider sProvider = SessionProvider.createSystemProvider(); try { Node bbCodeHome = getBBcodeHome(sProvider); NodeIterator iter = bbCodeHome.getNodes(); if (iter.getSize() <= 0) { List<BBCode> bbCodes = new ArrayList<BBCode>(); for (BBCodePlugin pln : plugins) { List<BBCodeData> codeDatas = pln.getBBCodeData(); for (BBCodeData codeData : codeDatas) { BBCode bbCode = new BBCode(); bbCode.setTagName(codeData.getTagName()); bbCode.setReplacement(codeData.getReplacement()); bbCode.setDescription(codeData.getDescription()); bbCode.setExample(codeData.getExample()); bbCode.setOption(Boolean.parseBoolean(codeData.getIsOption())); bbCode.setActive(Boolean.parseBoolean(codeData.getIsActive())); bbCodes.add(bbCode); if (log.isDebugEnabled()) { log.debug("Registered " + bbCode); } } managePlugin(pln); } if (!bbCodes.isEmpty()) { this.save(bbCodes); } } } finally { sProvider.close(); } } /** * * @param pln */ private void managePlugin(BBCodePlugin pln) { try { if (context != null) { context.register(pln); } else { log.warn("No Management context is available for " + getClass()); } } catch (Exception e) { log.error("Failed to register BBCode plugin " + pln.getName(), e); } } /** * {@inheritDoc} */ public void save(List<BBCode> bbcodes) throws Exception { SessionProvider sProvider = SessionProvider.createSystemProvider(); try { Node bbCodeHome = getBBcodeHome(sProvider); Node bbcNode; for (BBCode bbcode : bbcodes) { bbcNode = createNode(bbCodeHome, bbcode); bbcNode.setProperty("exo:tagName", bbcode.getTagName()); bbcNode.setProperty("exo:replacement", bbcode.getReplacement()); bbcNode.setProperty("exo:example", bbcode.getExample()); bbcNode.setProperty("exo:description", bbcode.getDescription()); bbcNode.setProperty("exo:isActive", bbcode.isActive()); bbcNode.setProperty("exo:isOption", bbcode.isOption()); } if (bbCodeHome.isNew()) { bbCodeHome.getSession().save(); } else { bbCodeHome.save(); } synchronized (activeBBCodesCache) { activeBBCodesCache.clear(); } } catch (Exception e) { log.error("Error saving BBCodes", e); } finally { sProvider.close(); } } private Node createNode(Node bbCodeHome, BBCode bbcode) throws Exception { Node bbcNode; String name = getNodeName(bbcode); try { bbcNode = bbCodeHome.getNode(bbcode.getId()); if (!name.equals(bbcode.getId())) { bbcNode.remove(); bbcNode = bbCodeHome.addNode(name, BBCODE_NODE_TYPE); } } catch (Exception e) { bbcNode = bbCodeHome.addNode(name, BBCODE_NODE_TYPE); } return bbcNode; } /** * create a suitable node name for a given bbcode * @param bbcode * @return */ private String getNodeName(BBCode bbcode) { String id = bbcode.getTagName() + ((bbcode.isOption()) ? "=" : ""); return id; } /** * {@inheritDoc} */ private BBCode nodeToBBCode(Node bbcNode) throws Exception { BBCode bbCode = new BBCode(); bbCode.setId(bbcNode.getName()); bbCode.setTagName(bbcNode.getProperty("exo:tagName").getString()); bbCode.setReplacement(bbcNode.getProperty("exo:replacement").getString()); bbCode.setExample(bbcNode.getProperty("exo:example").getString()); if (bbcNode.hasProperty("exo:description")) bbCode.setDescription(bbcNode.getProperty("exo:description").getString()); bbCode.setActive(bbcNode.getProperty("exo:isActive").getBoolean()); bbCode.setOption(bbcNode.getProperty("exo:isOption").getBoolean()); return bbCode; } /** * {@inheritDoc} */ public List<BBCode> getAll() throws Exception { SessionProvider sProvider = SessionProvider.createSystemProvider(); List<BBCode> bbcodes = new ArrayList<BBCode>(); try { Node bbCodeHome = getBBcodeHome(sProvider); NodeIterator iter = bbCodeHome.getNodes(); while (iter.hasNext()) { try { Node bbcNode = iter.nextNode(); bbcodes.add(nodeToBBCode(bbcNode)); } catch (Exception e) { log.error("Error loading BBCodes", e); } } } finally { sProvider.close(); } return bbcodes; } /** * {@inheritDoc} */ public List<String> getActive() throws Exception { SessionProvider sProvider = SessionProvider.createSystemProvider(); if (activeBBCodesCache.isEmpty()) { try { Node bbCodeHome = getBBcodeHome(sProvider); if (bbCodeHome == null) { return activeBBCodesCache; } QueryManager qm = bbCodeHome.getSession().getWorkspace().getQueryManager(); StringBuilder pathQuery = new StringBuilder(); // new Query().path(bbCodeHome.getPath()).type(BBCODE_NODE_TYPE).predicate("@exo:isActive='true'").toString(); pathQuery.append("/jcr:root").append(bbCodeHome.getPath()).append("/element(*,").append(BBCODE_NODE_TYPE).append(")[@exo:isActive='true']"); Query query = qm.createQuery(pathQuery.toString(), Query.XPATH); QueryResult result = query.execute(); NodeIterator iter = result.getNodes(); String tagName = ""; synchronized (activeBBCodesCache) { while (iter.hasNext()) { Node bbcNode = iter.nextNode(); tagName = bbcNode.getName(); activeBBCodesCache.add(tagName); } } } finally { sProvider.close(); } } return activeBBCodesCache; } /** * {@inheritDoc} */ public BBCode findById(String id) throws Exception { SessionProvider sProvider = SessionProvider.createSystemProvider(); BBCode bbCode = new BBCode(); Node bbcNode; try { Node bbCodeHome = getBBcodeHome(sProvider); try { bbcNode = bbCodeHome.getNode(id); bbCode = nodeToBBCode(bbcNode); } catch (Exception e) { log.error("Error loading BBCode" + id, e); } } finally { sProvider.close(); } return bbCode; } /** * {@inheritDoc} */ public void delete(String bbcodeId) throws Exception { SessionProvider sProvider = SessionProvider.createSystemProvider(); Node bbCodeHome = getBBcodeHome(sProvider); try { bbCodeHome.getNode(bbcodeId).remove(); bbCodeHome.save(); synchronized (activeBBCodesCache) { activeBBCodesCache.clear(); } } catch (Exception e) { log.error("Error removing BBCode" + bbcodeId, e); } finally { sProvider.close(); } } public void start() { try { initDefaultBBCodes(); } catch (Exception e) { log.error("Default BBCodes failed to initialize", e); } } private <T> T getComponent(Class<T> type) { return type.cast(ExoContainerContext.getCurrentContainer().getComponentInstanceOfType(type)); } public void stop() { } public void setContext(ManagementContext context) { this.context = context; } public KSDataLocation getDataLocator() { return dataLocator; } public void setDataLocator(KSDataLocation dataLocator) { this.dataLocator = dataLocator; this.sessionManager = dataLocator.getSessionManager(); } public List<BBCodePlugin> getPlugins() { return plugins; } public void setPlugins(List<BBCodePlugin> plugins) { this.plugins = plugins; } }