• Views
  • Iteration Report
  • My Iteration Report
  •  
OMERO.server
  • Login
  • Help/Guide
  • About Trac
  • Preferences
  • Wiki
  • Timeline
  • Roadmap
  • Browse Source
  • View Tickets
  • Search

Context Navigation

  • Last Change
  • Annotate
  • Revision Log

root/trunk/components/server/src/ome/tools/hibernate/ProxyCleanupFilter.java

Revision 2130, 5.4 kB (checked in by jmoore, 11 months ago)

OmeroSessions : Moving active thread flag to ProxyCleanupHandler

  • Removed sessionHandler.cleanThread() from ServiceHandler
  • Now in ProxyCleanupFilter and protected by depth count
  • Property svn:keywords set to
    Date
    Revision
    Id
    URL
Line 
1/*
2 * ome.tools.hibernate.ProxyCleanupFilter
3 *
4 *   Copyright 2006 University of Dundee. All rights reserved.
5 *   Use is subject to license terms supplied in LICENSE.txt
6 */
7
8package ome.tools.hibernate;
9
10// Java imports
11import java.util.ArrayList;
12import java.util.Collection;
13import java.util.HashMap;
14import java.util.HashSet;
15import java.util.IdentityHashMap;
16import java.util.List;
17import java.util.Map;
18import java.util.Set;
19
20import ome.api.StatefulServiceInterface;
21import ome.model.IObject;
22import ome.model.internal.Details;
23import ome.util.ContextFilter;
24import ome.util.Filterable;
25import ome.util.Utils;
26
27import org.aopalliance.intercept.MethodInterceptor;
28import org.aopalliance.intercept.MethodInvocation;
29import org.hibernate.Hibernate;
30import org.hibernate.collection.AbstractPersistentCollection;
31
32/**
33 * removes all proxies from a return graph to prevent ClassCastExceptions and
34 * Session Closed exceptions. You need to be careful with printing. Calling
35 * toString() on an unitialized object will break before filtering is complete.
36 *
37 * Note: we aren't setting the filtered collections here because it's "either
38 * null/unloaded or filtered". We will definitiely filter here, so it would just
39 * increase bandwidth.
40 *
41 * @author Josh Moore &nbsp;&nbsp;&nbsp;&nbsp; <a
42 *         href="mailto:josh.moore@gmx.de">josh.moore@gmx.de</a>
43 * @version 1.0 <small> (<b>Internal version:</b> $Rev$ $Date$) </small>
44 * @since 1.0
45 */
46public class ProxyCleanupFilter extends ContextFilter {
47
48    protected Map unloadedObjectCache = new IdentityHashMap();
49
50    @Override
51    public Filterable filter(String fieldId, Filterable f) {
52        if (f == null) {
53            return null;
54        }
55
56        if (unloadedObjectCache.containsKey(f)) {
57            return (IObject) unloadedObjectCache.get(f);
58        }
59
60        // A proxy; send over the wire in altered form.
61        if (!Hibernate.isInitialized(f)) {
62
63            if (f instanceof IObject) {
64                IObject proxy = (IObject) f;
65                IObject unloaded = (IObject) Utils.trueInstance(f.getClass());
66                unloaded.setId(proxy.getId());
67                unloaded.unload();
68                unloadedObjectCache.put(f, unloaded);
69                return unloaded;
70            } else if (f instanceof Details) {
71                // Currently Details is only "known" non-IObject Filterable
72                return super.filter(fieldId, ((Details) f).shallowCopy());
73            } else {
74                // TODO Here there's not much we can do. copy constructor?
75                throw new RuntimeException(
76                        "Bailing out. Don't want to set to a value to null.");
77            }
78
79            // Not a proxy; it will be serialized and sent over the wire.
80        } else {
81
82            // Any clean up here.
83            return super.filter(fieldId, f);
84
85        }
86
87    }
88
89    @Override
90    public Collection filter(String fieldId, Collection c) {
91        // is a proxy. null it. will be refilled by
92        // MergeEventListener on re-entry.
93        if (null == c || !Hibernate.isInitialized(c)) {
94            return null;
95        }
96
97        Collection retVal = super.filter(fieldId, c);
98
99        // ticket:61 : preventing Hibernate collection types from escaping.
100        if (retVal instanceof AbstractPersistentCollection) {
101            if (retVal instanceof Set) {
102                retVal = new HashSet(retVal);
103            } else if (retVal instanceof List) {
104                retVal = new ArrayList(retVal);
105            }
106
107        } // end ticket:61
108
109        return retVal;
110    }
111
112    @Override
113    public Map filter(String fieldId, Map m) {
114
115        if (null == m || !Hibernate.isInitialized(m)) {
116            return null;
117        }
118
119        Map retVal = super.filter(fieldId, m);
120
121        // ticket:61 : preventing Hibernate collection types from escaping.
122        if (retVal instanceof AbstractPersistentCollection) {
123            retVal = new HashMap(retVal);
124        } // end ticket:61
125
126        return retVal;
127    }
128
129    // TODO FIXME need to further test this.
130    @Override
131    protected void doFilter(String arg0, Object arg1) {
132        if (arg1 instanceof Object[]) {
133            Object[] arr = (Object[]) arg1;
134            for (int i = 0; i < arr.length; i++) {
135                arr[i] = this.filter(arg0, arr[i]);
136            }
137        }
138
139    }
140
141    /** wraps a filter for each invocation */
142    public static class Interceptor implements MethodInterceptor {
143
144        private SessionHandler sessions;
145
146        public void setSessionHandler(SessionHandler handler) {
147            this.sessions = handler;
148        }
149
150        private final ThreadLocal<Integer> depth = new ThreadLocal<Integer>() {
151            @Override
152            protected Integer initialValue() {
153                return Integer.valueOf(0);
154            }
155        };
156
157        public Object invoke(MethodInvocation arg0) throws Throwable {
158
159            int d = depth.get().intValue();
160            if (d == 0) {
161                sessions.cleanThread();
162            }
163
164            Object result;
165            d++;
166            depth.set(d);
167            try {
168
169                result = arg0.proceed();
170                if (!StatefulServiceInterface.class.isAssignableFrom(arg0
171                        .getThis().getClass())) {
172                    result = new ProxyCleanupFilter().filter(null, result);
173                }
174            } finally {
175                d--;
176                depth.set(d);
177            }
178
179            return result;
180        }
181    }
182
183}
Note: See TracBrowser for help on using the browser.

Download in other formats:

  • Plain Text
  • Original Format

Trac Powered

Powered by Trac 0.11
By Edgewall Software.

Visit the Trac open source project at
http://trac.edgewall.org/