/* * Copyright 2008 Glencoe Software, Inc. All rights reserved. * Use is subject to license terms supplied in LICENSE.txt */ package ome.services.blitz.test.mock; import java.sql.Timestamp; import java.util.Arrays; import java.util.HashMap; import java.util.Map; import java.util.Properties; import net.sf.ehcache.Cache; import ome.model.meta.Session; import ome.security.SecuritySystem; import ome.services.blitz.fire.Ring; import ome.services.blitz.fire.SessionManagerI; import ome.services.blitz.fire.TopicManager; import ome.services.blitz.test.utests.TestCache; import ome.services.blitz.util.BlitzConfiguration; import ome.services.roi.RoiTypes; import ome.services.scheduler.SchedulerFactoryBean; import ome.services.sessions.SessionManager; import ome.services.util.Executor; import ome.system.OmeroContext; import ome.system.Roles; import ome.util.SqlAction; import omero.rtypes; import omero.api.ServiceFactoryPrx; import omero.api.ServiceFactoryPrxHelper; import omero.constants.CLIENTUUID; import omero.util.ModelObjectFactoryRegistry; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.jmock.Mock; import org.jmock.MockObjectTestCase; import org.quartz.JobDetail; import org.quartz.Trigger; import org.springframework.scheduling.quartz.CronTriggerBean; import org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean; import Glacier2.AMD_Router_createSession; import Glacier2.AMD_Router_createSessionFromSecureConnection; import Glacier2.CannotCreateSessionException; import Glacier2.PermissionDeniedException; import Glacier2.SessionNotExistException; import Glacier2.SessionPrx; import Ice.Current; import Ice.InitializationData; import Ice.ObjectPrx; public class MockFixture { public final MockObjectTestCase test; public final SchedulerFactoryBean scheduler; public final BlitzConfiguration blitz; public final SessionManagerI sm; public final SessionManager mgr; public final SecuritySystem ss; public final OmeroContext ctx; public final Executor ex; public final Ring ring; public final String router; public final SqlAction sql; public static OmeroContext basicContext() { return new OmeroContext(new String[] { "classpath:omero/test.xml", "classpath:ome/config.xml", "classpath:ome/services/datalayer.xml", "classpath:ome/services/blitz-servantDefinitions.xml", "classpath:ome/services/blitz-graph-rules.xml", "classpath:ome/services/throttling/throttling.xml", "classpath:ome/services/messaging.xml", // Following 2 required by GeomTool deps. "classpath:ome/services/service-ome.io.nio.PixelsService.xml", "classpath:ome/services/service-ome.io.nio.OriginalFilesService.xml"}); } public MockFixture(MockObjectTestCase test) throws Exception { this(test, basicContext()); } /** * The string arguments sets the {@link SessionManagerI#self} field, which * is used in clustering. */ public MockFixture(MockObjectTestCase test, String name) throws Exception { this(test, basicContext()); } public MockFixture(MockObjectTestCase test, OmeroContext ctx) { this.test = test; this.ctx = ctx; this.ring = (Ring) ctx.getBean("ring"); this.ex = (Executor) ctx.getBean("executor"); this.ss = (SecuritySystem) ctx.getBean("securitySystem"); this.mgr = (SessionManager) ctx.getBean("sessionManager"); this.sql = (SqlAction) ctx.getBean("simpleSqlAction"); // -------------------------------------------- InitializationData id = new InitializationData(); id.properties = Ice.Util.createProperties(); // // The follow properties are necessary for Gateway // // Collocation isn't working (but should) id.properties.setProperty("Ice.Default.CollocationOptimized", "0"); // Gateway calls back on the SF and so needs another thread or // blocks. id.properties.setProperty("Ice.ThreadPool.Client.Size", "2"); id.properties.setProperty("Ice.ThreadPool.Client.SizeMax", "50"); id.properties.setProperty("Ice.ThreadPool.Server.Size", "10"); id.properties.setProperty("Ice.ThreadPool.Server.SizeMax", "100"); // For testing large calls id.properties.setProperty("Ice.MessageSizeMax", "4096"); // Basic configuration id.properties.setProperty("BlitzAdapter.Endpoints", "default -h 127.0.0.1"); // Cluster configuration from etc/internal.cfg id.properties.setProperty("Cluster.Endpoints", "udp -h 224.0.0.5 -p 10000"); id.properties.setProperty("ClusterProxy", "Cluster:udp -h 224.0.0.5 -p 10000"); /* Node node = new Node(); this.mock("executorMock").expects(test.once()).method("execute").will(test.returnValue(node)); this.mock("executorMock").expects(test.once()).method("execute").will(test.returnValue(true)); this.mock("executorMock").expects(test.once()).method("execute").will(test.returnValue(Collections.EMPTY_LIST)); */ blitz = new BlitzConfiguration(id, ring, mgr, ss, ex, 10000); this.sm = (SessionManagerI) blitz.getBlitzManager(); this.sm.setApplicationContext(ctx); this.ctx.addApplicationListener(this.sm); // Reproducing the logic of initializing the ObjectFactories // which typically happens within Spring new rtypes.RTypeObjectFactoryRegistry().setIceCommunicator(blitz.getCommunicator()); new RoiTypes.RoiTypesObjectFactoryRegistry().setIceCommunicator(blitz.getCommunicator()); new ModelObjectFactoryRegistry().setIceCommunicator(blitz.getCommunicator()); /* UNUSED // The following is a bit of spring magic so that we can configure // the adapter in code. If this can be pushed to BlitzConfiguration // for example then we might not need it here anymore. HotSwappableTargetSource ts = (HotSwappableTargetSource) ctx .getBean("swappableAdapterSource"); ts.swap(blitz.getBlitzAdapter()); */ // Add our topic manager TopicManager tm = new TopicManager.Impl(blitz.getCommunicator()); this.ctx.addApplicationListener(tm); // Setup mock router which allows us to use omero.client // rather than solely ServiceFactoryProxies, though it is // still necessary to call the proper mock methods. Ice.ObjectPrx prx = blitz.getBlitzAdapter().add( new MockRouter(this.sm), Ice.Util.stringToIdentity("OMERO.Glacier2/router")); router = "OMERO.Glacier2/router:" + prx.ice_getEndpoints()[0]._toString(); // Finally, starting a scheduler to act like a real // server try { MethodInvokingJobDetailFactoryBean runBeats = new MethodInvokingJobDetailFactoryBean(); runBeats.setBeanName("runBeats"); runBeats.setTargetMethod("requestHeartBeats"); runBeats.setTargetObject(blitz.getBlitzManager()); runBeats.afterPropertiesSet(); CronTriggerBean triggerBeats = new CronTriggerBean(); triggerBeats.setBeanName("triggerBeats"); triggerBeats.setJobDetail((JobDetail) runBeats.getObject()); triggerBeats.setCronExpression("0-59/5 * * * * ?"); triggerBeats.afterPropertiesSet(); scheduler = new SchedulerFactoryBean(); scheduler.setApplicationContext(ctx); scheduler.setTriggers(new Trigger[] { triggerBeats }); scheduler.afterPropertiesSet(); scheduler.start(); } catch (Exception e) { throw new RuntimeException(e); } } public omero.client newClient() { Properties p = new Properties(); p.setProperty("Ice.Default.Router", router); omero.client client = new omero.client(p); return client; } public void tearDown() { mock("executorMock").expects(test.once()).method("execute") .will(test.returnValue(0)); this.blitz.destroy(); scheduler.stop(); // this.ctx.closeAll(); } public OmeroContext getContext() { return this.ctx; } public SessionManagerI getSessionManager() { return this.sm; } public ServiceFactoryPrx createServiceFactory() throws Exception { Session s = session(); Cache cache = cache(); return createServiceFactory(s, cache, "single-client"); } /** * Makes a direct call to SessionManager.create. A call should be made on * <em>some</em> fixture to {@link #prepareServiceFactory(Session, Cache)} * since the call may be re-routed to a clustered instance. */ public ServiceFactoryPrx createServiceFactory(String name, String client) throws Exception { return ServiceFactoryPrxHelper.uncheckedCast(sm.create(name, null, this .current("create", client))); } public ServiceFactoryPrx createServiceFactory(Session s) throws Exception { Cache cache = cache(); return createServiceFactory(s, cache, "single-client"); } public ServiceFactoryPrx createServiceFactory(Session s, Cache cache, String clientId) throws Exception { prepareServiceFactory(s, cache); return ServiceFactoryPrxHelper.uncheckedCast(sm.create("name", null, this.current("create", clientId))); } public void prepareServiceFactory(Session s, Cache cache) { mock("sessionsMock").expects(test.once()).method("find") .will(test.returnValue(s)); mock("securityMock").expects(test.once()).method("getSecurityRoles") .will(test.returnValue(new Roles())); mock("sessionsMock").expects(test.once()).method("create").will( test.returnValue(s)); mock("sessionsMock").expects(test.once()).method("inMemoryCache").will( test.returnValue(cache)); mock("methodMock").expects(test.atLeastOnce()).method("isActive").will( test.returnValue(false)); } public void prepareClose(int referenceCount) { mock("sessionsMock").expects(test.once()).method("detach").will( test.returnValue(referenceCount)); if (referenceCount < 1) { mock("sessionsMock").expects(test.once()).method("close").will( test.returnValue(-2)); } } Ring ring() { return blitz.getRing(); } public Mock mock(String name) { return (Mock) ctx.getBean(name); } public Cache cache() { return new TestCache(); } public Ice.Current current(String method) { return current(method, "my-client-uuid"); } public Ice.Current current(String method, String clientId) { Ice.Current current = new Ice.Current(); current.operation = method; current.adapter = blitz.getBlitzAdapter(); current.ctx = new HashMap<String, String>(); current.ctx.put(CLIENTUUID.value, clientId); return current; } public Session session() { return session("my-session-uuid"); } public Session session(String uuid) { Session session = new Session(); session.setUuid(uuid); session.setStarted(new Timestamp(System.currentTimeMillis())); session.setTimeToIdle(0L); session.setTimeToLive(0L); return session; } public Mock blitzMock(Class serviceClass) { String name = serviceClass.getName(); name = name.replaceFirst("omero", "ome").replace("PrxHelper", ""); // WORKAROUND if (name.equals("ome.api.RenderingEngine")) { name = "omeis.providers.re.RenderingEngine"; } Mock mock = mock("mock-" + name); if (mock == null) { throw new RuntimeException("No mock for serviceClass"); } return mock; } public static class MockRouter extends Glacier2._RouterDisp { private final static Logger log = LoggerFactory.getLogger(MockRouter.class); private final SessionManagerI sm; private final Map<Ice.Connection, SessionPrx> sessionByConnection = new HashMap<Ice.Connection, SessionPrx>(); public MockRouter(SessionManagerI sm) { this.sm = sm; } public void createSessionFromSecureConnection_async( AMD_Router_createSessionFromSecureConnection arg0, Current arg1) throws CannotCreateSessionException, PermissionDeniedException { arg0.ice_exception(new UnsupportedOperationException()); } public void createSession_async(AMD_Router_createSession arg0, String arg1, String arg2, Current arg3) throws CannotCreateSessionException, PermissionDeniedException { try { SessionPrx prx = sm.create(arg1, null, arg3); sessionByConnection.put(arg3.con, prx); log.info(String.format("Storing %s under %s", prx, arg3.con)); arg0.ice_response(prx); } catch (Exception e) { arg0.ice_exception(e); } } public void destroySession(Current arg0) throws SessionNotExistException { SessionPrx prx = sessionByConnection.get(arg0.con); if (prx != null) { log.info("Destroying " + prx); prx.destroy(); } } public String getCategoryForClient(Current arg0) { return sessionByConnection.get(arg0.con).ice_id(); } public int getACMTimeout(Ice.Current arg0) { throw new UnsupportedOperationException(); } public long getSessionTimeout(Current arg0) { throw new UnsupportedOperationException(); } public ObjectPrx[] addProxies(ObjectPrx[] arg0, Current arg1) { log.warn("addProxies called with " + Arrays.deepToString(arg0)); return null; } @SuppressWarnings("deprecation") public void addProxy(ObjectPrx arg0, Current arg1) { log.warn("addProxy called with " + arg0); } public ObjectPrx getClientProxy(Current arg0) { return null; } public ObjectPrx getServerProxy(Current arg0) { return sessionByConnection.get(arg0.con); } public void refreshSession(Ice.Current current) throws Glacier2.SessionNotExistException { throw new UnsupportedOperationException(); } public void refreshSession_async(Glacier2.AMD_Router_refreshSession arg0, Ice.Current arg1) throws Glacier2.SessionNotExistException { throw new UnsupportedOperationException(); } } }