Coverage Report - org.simpleframework.xml.core.SessionManager
 
Classes in this File Line Coverage Branch Coverage Complexity
SessionManager
94%
18/19
75%
6/8
1.875
SessionManager$Reference
100%
7/7
50%
1/2
1.875
 
 1  
 /*
 2  
  * SessionManager May 2010
 3  
  *
 4  
  * Copyright (C) 2006, Niall Gallagher <niallg@users.sf.net>
 5  
  *
 6  
  * Licensed under the Apache License, Version 2.0 (the "License");
 7  
  * you may not use this file except in compliance with the License.
 8  
  * You may obtain a copy of the License at
 9  
  *
 10  
  *     http://www.apache.org/licenses/LICENSE-2.0
 11  
  *
 12  
  * Unless required by applicable law or agreed to in writing, software
 13  
  * distributed under the License is distributed on an "AS IS" BASIS,
 14  
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 
 15  
  * implied. See the License for the specific language governing 
 16  
  * permissions and limitations under the License.
 17  
  */
 18  
 
 19  
 package org.simpleframework.xml.core;
 20  
 
 21  
 /**
 22  
  * The <code>SessionManager</code> is used to manage the sessions that
 23  
  * are used during the serialization process. Sessions are stored in 
 24  
  * thread locals so that should a <code>Converter</code> delegate back
 25  
  * in to the same persister instance, it will acquire the same session
 26  
  * object. This ensures that converters can be used to resolve cycles
 27  
  * in the object graph with the <code>CycleStrategy</code> and also
 28  
  * ensures there is no overhead creating new session objects.
 29  
  * 
 30  
  * @author Niall Gallagher
 31  
  * 
 32  
  * @see org.simpleframework.xml.core.Session
 33  
  */
 34  
 class SessionManager {
 35  
    
 36  
    /**
 37  
     * This is the thread local used to store the sessions objects.
 38  
     */
 39  
    private ThreadLocal<Reference> local;
 40  
    
 41  
    /**
 42  
     * Constructor for the <code>SessionManager</code> object. This 
 43  
     * is used to create a session manager that stores sessions in 
 44  
     * a thread local so that it can be reused on multiple invocations
 45  
     * to the <code>Persister</code> object. References are maintained
 46  
     * to each session created so that it is closed when there are
 47  
     * no longer any more references to the session.
 48  
     */
 49  883
    public SessionManager() {
 50  883
       this.local = new ThreadLocal<Reference>();
 51  883
    }   
 52  
    
 53  
    /**
 54  
     * This is used to open a new <code>Session</code> object. If the
 55  
     * session exists within the thread local it is returned and a
 56  
     * reference count to the session is increased. This ensures that
 57  
     * the session is not disposed of until all references to it are
 58  
     * closed. By default this creates a strict session.
 59  
     * 
 60  
     * @return this returns a strict session from the manager    
 61  
     */
 62  
    public Session open() throws Exception {
 63  24403
       return open(true);
 64  
    }
 65  
 
 66  
    /**
 67  
     * This is used to open a new <code>Session</code> object. If the
 68  
     * session exists within the thread local it is returned and a
 69  
     * reference count to the session is increased. This ensures that
 70  
     * the session is not disposed of until all references to it are
 71  
     * closed. The strictness of the session can be specified.
 72  
     * 
 73  
     * @param strict this determines if the session is strict
 74  
     * 
 75  
     * @return this returns a session from the manager    
 76  
     */
 77  
    public Session open(boolean strict) throws Exception {
 78  98456
       Reference session = local.get();
 79  
       
 80  98456
       if(session != null) {
 81  9
          return session.get();
 82  
       }
 83  98447
       return create(strict);
 84  
    }
 85  
    
 86  
    /**
 87  
     * This is used to create a new <code>Session</code> object. On
 88  
     * creation of the session it is placed on a thread local so 
 89  
     * that it can be acquired by the current thread when required.
 90  
     * 
 91  
     * @param strict this determines if the session is strict
 92  
     * 
 93  
     * @return this returns a new session from the manager    
 94  
     */
 95  
    private Session create(boolean strict) throws Exception {
 96  98447
       Reference session = new Reference(strict);
 97  
       
 98  98447
       if(session != null) {
 99  98447
          local.set(session);
 100  
       }
 101  98447
       return session.get();
 102  
    }
 103  
    
 104  
    /**
 105  
     * This is used to close the session on the thread local. If the
 106  
     * session still has references to it then the reference count
 107  
     * is decreased and the session remains open. This ensures that
 108  
     * we can make recursive calls in to the <code>Persister</code>
 109  
     * and still use the same session object.
 110  
     */
 111  
    public void close() throws Exception {
 112  98455
       Reference session = local.get();
 113  
       
 114  98455
       if(session == null) {
 115  0
          throw new PersistenceException("Session does not exist");
 116  
       } 
 117  98455
       int reference = session.clear();
 118  
       
 119  98455
       if(reference == 0) {
 120  98446
          local.remove();
 121  
       }
 122  98455
    }
 123  
    
 124  
    /**
 125  
     * The <code>Reference</code> object is used to store sessions 
 126  
     * and count references to them. Counting references ensures that
 127  
     * no session is closed or disposed of until all references to 
 128  
     * it have been removed. Once references are removed the session
 129  
     * is discarded and can no longer be acquired.
 130  
     * 
 131  
     * @author Niall Gallagher
 132  
     */
 133  
    private static class Reference {
 134  
 
 135  
       /**
 136  
        * This is the session object that is maintained by this.
 137  
        */
 138  
       private Session session;
 139  
       
 140  
       /**
 141  
        * This is the count of the number of references to this.
 142  
        */
 143  
       private int count;
 144  
 
 145  
       /**
 146  
        * Constructor for the <code>Reference</code> object. This is
 147  
        * used during the serialization process to manage references 
 148  
        * to the sessions that are used by the serializer.
 149  
        * 
 150  
        * @param strict determines whether the session is strict
 151  
        */
 152  98447
       public Reference(boolean strict) {
 153  98447
          this.session = new Session(strict);
 154  98447
       }
 155  
 
 156  
       /**
 157  
        * This is used to acquire the session and increase the count
 158  
        * of references to the session. When the references are all
 159  
        * cleared then the reference counter can no longer be 
 160  
        * increased and the reference should be discarded.
 161  
        * 
 162  
        * @return this returns the session for this reference
 163  
        */
 164  
       public Session get() {
 165  98456
          if(count >= 0) {
 166  98456
             count++;
 167  
          }
 168  98456
          return session;
 169  
       }
 170  
 
 171  
       /**
 172  
        * This is used to clear the references to the session. A
 173  
        * reference is cleared when it is closed from the manager. 
 174  
        * The reference is disposed of when this returns zero or a
 175  
        * negative number indicating all references are gone.
 176  
        * 
 177  
        * @return this returns the number of references this has
 178  
        */
 179  
       public int clear() {
 180  98455
          return --count;
 181  
       }
 182  
    }
 183  
 }