1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 package com.sun.star.uno;
29 
30 import com.sun.star.uno.XWeak;
31 import com.sun.star.uno.UnoRuntime;
32 import com.sun.star.uno.XAdapter;
33 import com.sun.star.uno.XReference;
34 
35 /** This class holds weak reference to an object. It actually holds a reference to a
36     com.sun.star.XAdapter implementation and obtains a hard reference if necessary.
37  */
38 public class WeakReference
39 {
40     private final boolean DEBUG= false;
41     private OWeakRefListener m_listener;
42     // There is no default constructor. Every instance must register itself with the
43     // XAdapter interface, which is done in the constructors. Assume we have this code
44     // WeakReference ref= new WeakReference();
45     // ref = someOtherWeakReference;
46     //
47     // ref would not be notified (XReference.dispose()) because it did not register
48     // itself. Therefore the XAdapter would be kept aliver although this is not
49     // necessary.
50 
51     /** Creates an instance of this class.
52      *@param obj - another instance that is to be copied
53      */
54     public WeakReference(WeakReference obj)
55     {
56         if (obj != null)
57         {
58             Object weakImpl= obj.get();
59             if (weakImpl != null)
60             {
61                 XWeak weak= UnoRuntime.queryInterface(XWeak.class, weakImpl);
62                 if (weak != null)
63                 {
64                     XAdapter adapter= (XAdapter) weak.queryAdapter();
65                     if (adapter != null)
66                         m_listener= new OWeakRefListener(adapter);
67                 }
68             }
69         }
70     }
71 
72     /** Creates an instance of this class.
73      *@param obj XWeak implementation
74      */
75     public WeakReference(Object obj)
76     {
77         XWeak weak= UnoRuntime.queryInterface(XWeak.class, obj);
78         if (weak != null)
79         {
80             XAdapter adapter= (XAdapter) weak.queryAdapter();
81             if (adapter != null)
82                 m_listener= new OWeakRefListener(adapter);
83         }
84     }
85     /** Returns a hard reference to the object that is kept weak by this class.
86      *@return a hard reference to the XWeak implementation.
87      */
88     public Object get()
89     {
90         if (m_listener != null)
91             return m_listener.get();
92         return null;
93     }
94 }
95 
96 /** Implementation of com.sun.star.uno.XReference for use with WeakReference.
97  *  It keeps the XAdapter implementation and registers always with it. Deregistering
98  *  occurs on notification by the adapter and the adapter is released.
99  */
100 class OWeakRefListener implements XReference
101 {
102     private final boolean DEBUG= false;
103     private XAdapter m_adapter;
104 
105     /** The constructor registered this object with adapter.
106      *@param adapter the XAdapter implementation.
107      */
108     OWeakRefListener( XAdapter adapter)
109     {
110         m_adapter= adapter;
111         m_adapter.addReference(this);
112     }
113     /** Method of com.sun.star.uno.XReference. When called, it deregisteres this
114      *  object with the adapter and releases the reference to it.
115      */
116     synchronized public void dispose()
117     {
118         if (m_adapter != null)
119         {
120             m_adapter.removeReference(this);
121             m_adapter= null;
122         }
123     }
124 
125     /** Obtains a hard reference to the object which is kept weak by the adapter
126      *  and returns it.
127      *  @return hard reference to the otherwise weakly kept object.
128      */
129     synchronized Object get()
130     {
131         Object retVal= null;
132         if (m_adapter != null)
133         {
134             retVal= m_adapter.queryAdapted();
135             if (retVal == null)
136             {
137                 // If this object registered as listener with XAdapter while it was notifying
138                 // the listeners then this object might not have been notified. If queryAdapted
139                 // returned null then the weak kept object is dead and the listeners have already
140                 // been notified. And we missed it.
141                 m_adapter.removeReference(this);
142                 m_adapter= null;
143             }
144         }
145         return retVal;
146     }
147 }
148