/* * Copyright (C) 2009 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.services.jcr.impl.dataflow.session; import org.exoplatform.services.jcr.JcrImplBaseTest; import org.exoplatform.services.jcr.dataflow.ItemState; import org.exoplatform.services.jcr.datamodel.InternalQName; import org.exoplatform.services.jcr.datamodel.NodeData; import org.exoplatform.services.jcr.impl.Constants; import org.exoplatform.services.jcr.impl.core.DummySession; import org.exoplatform.services.jcr.impl.core.NodeImpl; import org.exoplatform.services.jcr.impl.core.SessionDataManager; import org.exoplatform.services.jcr.impl.core.SessionImpl; import org.exoplatform.services.jcr.impl.core.SessionRegistry; import org.exoplatform.services.jcr.impl.dataflow.TransientNodeData; import org.exoplatform.services.jcr.impl.dataflow.TransientPropertyData; import org.exoplatform.services.jcr.impl.dataflow.TransientValueData; import org.exoplatform.services.jcr.util.IdGenerator; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import javax.jcr.Credentials; import javax.jcr.PropertyType; import javax.jcr.Repository; import javax.jcr.RepositoryException; /** * Created by The eXo Platform SAS * * Jun 13, 2007 * * @author <a href="mailto:peter.nedonosko@exoplatform.com.ua">Peter Nedonosko</a> * @version $Id: SessionChangesLogTest.java 11962 2008-03-16 16:31:14Z gazarenkov $ */ public class SessionChangesLogTest extends JcrImplBaseTest { // for makeNotThisThreadLog() method, contains SessionChangesLog and its sessionId private class SessionChangesLogInfo { private final SessionChangesLog slog; private final String sessionId; SessionChangesLogInfo(SessionChangesLog slog, String sessionId) { this.slog = slog; this.sessionId = sessionId; } public SessionChangesLog getLog() { return slog; } public String getSessionId() { return sessionId; } } @Override public void setUp() throws Exception { super.setUp(); NodeImpl testRoot = (NodeImpl)root.addNode("sessionLinkRoot"); session.save(); } @Override protected void tearDown() throws Exception { if (root.hasNode("sessionLinkRoot")) { NodeImpl testRoot = (NodeImpl)root.getNode("sessionLinkRoot"); testRoot.remove(); session.save(); } super.tearDown(); } private SessionChangesLogInfo makeNotThisThreadLog() throws Exception { final SessionChangesLogInfo[] chlog = new SessionChangesLogInfo[1]; final Repository frepository = repository; final Credentials fcredentials = this.credentials /* session.getCredentials() */; Thread thread = new Thread() { @Override public void run() { SessionImpl userSession; try { userSession = (SessionImpl)frepository.login(fcredentials, "ws"); chlog[0] = new SessionChangesLogInfo(new SessionChangesLog(userSession), userSession.getId()); } catch (RepositoryException e) { throw new RuntimeException("testSessionLinkGCedSession(), " + e, e); } userSession = null; } }; thread.start(); thread.join(); return chlog[0]; } private SessionImpl getRegisteredSession(String sessionId) { SessionRegistry sreg = (SessionRegistry)session.getContainer().getComponentInstanceOfType(SessionRegistry.class); return sreg.getSession(sessionId); } public void testSameSession() { SessionChangesLog chlog = new SessionChangesLog(session); assertEquals("Session must be same as given id owns", session, getRegisteredSession(chlog.getSessionId())); } public void testWithoutSession() throws Exception { String id = IdGenerator.generate(); SessionChangesLog chlog = new SessionChangesLog(new DummySession(id)); assertNull("No session should be linked to the log", getRegisteredSession(chlog.getSessionId())); } public void testAnotherThreadSession() throws Exception { SessionChangesLogInfo chlog = makeNotThisThreadLog(); assertEquals("Session must be same as given id owns", chlog.getSessionId(), getRegisteredSession( chlog.getLog().getSessionId()).getId()); } public void testSessionLogout() throws Exception { // test if WeakHashMap does remove at logout SessionChangesLogInfo chlog = makeNotThisThreadLog(); getRegisteredSession(chlog.getLog().getSessionId()).logout(); // gc and wait System.gc(); Thread.currentThread().sleep(5000); assertNull("No session should be linked to the log", getRegisteredSession(chlog.getLog().getSessionId())); } public void testMultipleSessionsLogout() throws Exception { List<SessionChangesLogInfo> logs = new ArrayList<SessionChangesLogInfo>(); NodeImpl testRoot = (NodeImpl)root.getNode("sessionLinkRoot"); NodeData parent = (NodeData)testRoot.getData(); for (int i = 1; i <= 1000; i++) { SessionChangesLogInfo logInfo = makeNotThisThreadLog(); SessionChangesLog slog = logInfo.getLog(); InternalQName qname = InternalQName.parse("[]node" + i); TransientNodeData ndata = TransientNodeData.createNodeData(parent, qname, Constants.NT_UNSTRUCTURED); // jcr:primaryType TransientPropertyData ndpt = TransientPropertyData.createPropertyData(ndata, Constants.JCR_PRIMARYTYPE, PropertyType.NAME, false, new TransientValueData(ndata.getPrimaryTypeName())); slog.add(ItemState.createAddedState(ndata)); slog.add(ItemState.createAddedState(ndpt)); SessionDataManager sdm = getRegisteredSession(logInfo.getLog().getSessionId()).getTransientNodesManager(); sdm.getTransactManager().save(slog); // persist changes logs.add(logInfo); } List<String> sessions = new ArrayList<String>(); for (Iterator<SessionChangesLogInfo> iter = logs.iterator(); iter.hasNext();) { SessionChangesLogInfo slog = iter.next(); iter.remove(); getRegisteredSession(slog.getLog().getSessionId()).logout(); // sessions.add(new String(slog.getSessionId())); } // gc and wait System.gc(); Thread.sleep(5000); // ItemDataChangesLogHood registry = new ItemDataChangesLogHood(); // int linked = 0; // for (String sessionId: sessions) { // if (registry.isSessionLinked(sessionId)) // linked++; // } // assertEquals("No session should be linked ", 0, registry.linkedSessionsCount()); // assertEquals("No session should be linked ", 0, linked); } public void testAddRootChanges() throws Exception { SessionChangesLog changesLog = new SessionChangesLog(session); try { changesLog.add(new ItemState(new TransientPropertyData(Constants.ROOT_PATH, Constants.ROOT_UUID, 0, PropertyType.STRING, null, false), ItemState.ADDED, false, Constants.ROOT_PATH)); } catch (Exception e) { fail("Exception should not be thrown"); } } }