Java tutorial
/* * $Id$ * * Copyright 2008 Glencoe Software, Inc. All rights reserved. * Use is subject to license terms supplied in LICENSE.txt */ package ome.services.blitz.impl; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.NoSuchElementException; import java.util.concurrent.Callable; import ome.api.ServiceInterface; import ome.api.StatefulServiceInterface; import ome.logic.HardWiredInterceptor; import ome.services.blitz.fire.AopContextInitializer; import ome.services.blitz.util.BlitzExecutor; import ome.services.blitz.util.IceMethodInvoker; import ome.services.blitz.util.UnregisterServantMessage; import ome.services.throttling.Task; import ome.services.throttling.ThrottlingStrategy; import ome.services.util.Executor; import ome.system.OmeroContext; import ome.util.messages.InternalMessage; import omero.ServerError; import omero.ShutdownInProgress; import omero.api.AMD_StatefulServiceInterface_activate; import omero.api.AMD_StatefulServiceInterface_close; import omero.api.AMD_StatefulServiceInterface_getCurrentEventContext; import omero.api.AMD_StatefulServiceInterface_passivate; import omero.api._ServiceInterfaceOperations; import omero.util.IceMapper; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.aop.framework.ProxyFactory; import org.springframework.beans.BeansException; import org.springframework.beans.FatalBeanException; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; import Ice.Current; import Ice.ObjectAdapterDeactivatedException; /** * {@link ThrottlingStrategy throttled} implementation base class which can be * used by {@link _ServiceInterfaceOperations} implementors and injected into a * tie servant. * * @author Josh Moore, josh at glencoesoftware.com * @since 3.0-Beta4 */ public abstract class AbstractAmdServant implements ApplicationContextAware, CloseableServant { final protected Log log = LogFactory.getLog(getClass()); final protected BlitzExecutor be; /** * If there is no undering ome.* service, then this value can be null. */ protected ServiceInterface service; /** * If a service is provided, then an invoker will be created to cache all of * its methods. */ protected IceMethodInvoker invoker; protected OmeroContext ctx; public AbstractAmdServant(ServiceInterface service, BlitzExecutor be) { this.be = be; this.service = service; } /** * Creates an {@link IceMethodInvoker} for this instance if {@link #service} * is non-null. Otherwise gives subclasses a chance to use the {@link OmeroContext} * via {@link #onSetContext(OmeroContext)} */ public final void setApplicationContext(ApplicationContext ctx) throws BeansException { this.ctx = (OmeroContext) ctx; if (service != null) { this.invoker = new IceMethodInvoker(service, this.ctx); } try { onSetOmeroContext(this.ctx); } catch (Exception e) { throw new FatalBeanException("Error on setOmeroContext", e); } } /** * To be overridden by subclasses. */ public void onSetOmeroContext(OmeroContext context) throws Exception { //no-op } /** * Applies the hard-wired intercepting to this instance. It is not possible * to configure hard-wired interceptors in Spring, instead they must be * passed in at runtime from a properly compiled class. */ public final void applyHardWiredInterceptors(List<HardWiredInterceptor> cptors, AopContextInitializer initializer) { if (service != null) { ProxyFactory wiredService = new ProxyFactory(); wiredService.setInterfaces(service.getClass().getInterfaces()); wiredService.setTarget(service); List<HardWiredInterceptor> reversed = new ArrayList<HardWiredInterceptor>(cptors); Collections.reverse(reversed); for (HardWiredInterceptor hwi : reversed) { wiredService.addAdvice(0, hwi); } wiredService.addAdvice(0, initializer); service = (ServiceInterface) wiredService.getProxy(); } } public final void callInvokerOnRawArgs(Object __cb, Ice.Current __current, Object... args) { if (service == null) { throw new ome.conditions.InternalException("Null service; cannot use callInvoker()"); } this.be.callInvokerOnRawArgs(service, invoker, __cb, __current, args); } public final void callInvokerOnMappedArgs(IceMapper mapper, Object __cb, Ice.Current __current, Object... args) { if (service == null) { throw new ome.conditions.InternalException("Null service; cannot use callInvoker()"); } this.be.callInvokerWithMappedArgs(service, invoker, mapper, __cb, __current, args); } public final void runnableCall(Ice.Current __current, Task r) { this.be.runnableCall(__current, r); } public final <R> void safeRunnableCall(Ice.Current __current, Object cb, boolean isVoid, Callable<R> callable) { this.be.safeRunnableCall(__current, cb, isVoid, callable); } public final void executorWorkCall(Executor.Work work) { throw new UnsupportedOperationException(); } // // StatefulServiceInterface // public final void activate_async(AMD_StatefulServiceInterface_activate __cb, Current __current) { // Do nothing for the moment } public final void passivate_async(AMD_StatefulServiceInterface_passivate __cb, Current __current) { // Do nothing for the moment } public final void getCurrentEventContext_async(AMD_StatefulServiceInterface_getCurrentEventContext __cb, Current __current) throws ServerError { callInvokerOnRawArgs(__cb, __current); } public final void close(Ice.Current __current) { final RuntimeException[] re = new RuntimeException[1]; AMD_StatefulServiceInterface_close cb = new AMD_StatefulServiceInterface_close() { public void ice_exception(Exception ex) { if (ex instanceof RuntimeException) { re[0] = (RuntimeException) ex; } else { re[0] = new RuntimeException(ex); } } public void ice_response() { // ok. } }; close_async(cb, __current); if (re[0] != null) { throw re[0]; } } /** * {@link ome.tools.hibernate.SessionHandler} also * specially catches close() calls, but cannot remove the servant * from the {@link Ice.ObjectAdapter} and thereby prevent any * further communication. Once the invocation is finished, though, * it is possible to raise the message and have the servant * cleaned up. * * @see ticket:1855 */ public final void close_async(AMD_StatefulServiceInterface_close __cb, Ice.Current __current) { // Special call logic: // callInvokerOnRawArgs(__cb, __current); Throwable t = null; // First we call close on the object try { preClose(); if (service instanceof StatefulServiceInterface) { StatefulServiceInterface ss = (StatefulServiceInterface) service; ss.close(); } } catch (NoSuchElementException nsee) { log.info("NoSuchElementException: Login is already gone"); t = nsee; } catch (Throwable t1) { log.error("Error on close, stage1", t1); t = t1; } // Then we publish the close event try { InternalMessage msg = new UnregisterServantMessage(this, __current); ctx.publishMessage(msg); } catch (ObjectAdapterDeactivatedException oade) { log.warn("ObjectAdapter deactivated!"); ShutdownInProgress sip = new ShutdownInProgress(); IceMapper.fillServerError(sip, oade); t = sip; } catch (Throwable t2) { log.error("Error on close, stage2", t2); t = t2; } // Now we've finished that, let's return control to the user. if (t == null) { __cb.ice_response(); } else { __cb.ice_exception(new IceMapper().handleException(t, ctx)); } } protected void preClose() { } }