View Javadoc

1   /*
2    * This file is part of Domingo
3    * an Open Source Java-API to Lotus Notes/Domino
4    * hosted at http://domingo.sourceforge.net
5    *
6    * Copyright (c) 2003-2007 Beck et al. projects GmbH Munich, Germany (http://www.bea.de)
7    *
8    * This library is free software; you can redistribute it and/or
9    * modify it under the terms of the GNU Lesser General Public
10   * License as published by the Free Software Foundation; either
11   * version 2.1 of the License, or (at your option) any later version.
12   *
13   * This library is distributed in the hope that it will be useful,
14   * but WITHOUT ANY WARRANTY; without even the implied warranty of
15   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16   * Lesser General Public License for more details.
17   *
18   * You should have received a copy of the GNU Lesser General Public
19   * License along with this library; if not, write to the Free Software
20   * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21   */
22  
23  package de.bea.domingo.proxy;
24  
25  import lotus.domino.Agent;
26  import lotus.domino.AgentContext;
27  import lotus.domino.Base;
28  import lotus.domino.Database;
29  import lotus.domino.DateRange;
30  import lotus.domino.DateTime;
31  import lotus.domino.DbDirectory;
32  import lotus.domino.Document;
33  import lotus.domino.DocumentCollection;
34  import lotus.domino.EmbeddedObject;
35  import lotus.domino.Form;
36  import lotus.domino.Item;
37  import lotus.domino.Log;
38  import lotus.domino.NotesException;
39  import lotus.domino.RichTextItem;
40  import lotus.domino.Session;
41  import lotus.domino.View;
42  import lotus.domino.ViewEntry;
43  import lotus.domino.ViewEntryCollection;
44  import lotus.domino.ViewNavigator;
45  import de.bea.domingo.DNotesMonitor;
46  import de.bea.domingo.exception.DominoException;
47  import de.bea.domingo.monitor.AbstractMonitorEnabled;
48  import de.bea.domingo.queue.Queue;
49  
50  /***
51   * Implementation of interface <code>NotesRecycler</code> that explicitly
52   * recycles almost all Notes objects.
53   *
54   * <p>This strategy should be used with Lotus Notes R5 while missing explicit
55   * recycle results in memory leaks.</p>
56   *
57   * @author <a href=mailto:kriede@users.sourceforge.net>Kurt Riede</a>
58   */
59  public final class RecycleStrategy extends AbstractMonitorEnabled implements NotesRecycler {
60  
61      /*** Reference to a recycle queue. */
62      private Queue recycleQueue = new NotesRecycleQueue();
63  
64      /*** Indicates whether the DateTime recycle problem is already reported.*/
65      private boolean dateTimeHitfixProblemReported = false;
66  
67      /***
68       * Constructor.
69       *
70       * @param monitor the monitor
71       */
72      public RecycleStrategy(final DNotesMonitor monitor) {
73          super(monitor);
74      }
75  
76      /***
77       * {@inheritDoc}
78       * @see de.bea.domingo.proxy.NotesRecycler#recycleLater(java.lang.Object)
79       */
80      public synchronized void recycleLater(final Object object) {
81          final Base notesBase = getNotesObject(object);
82          if (notesBase != null) {
83              recycleQueue.enqueue(notesBase);
84          }
85      }
86  
87      /***
88       * @see de.bea.domingo.proxy.NotesRecycler#recycleQueue()
89       */
90      public synchronized void recycleQueue() {
91          if (!recycleQueue.isEmpty()) {
92              while (!recycleQueue.isEmpty()) {
93                  final Object obj = recycleQueue.dequeue();
94                  if (obj != null) {
95                      recycle(obj);
96                  }
97              }
98          }
99      }
100 
101     /***
102      * {@inheritDoc}
103      * @see de.bea.domingo.proxy.NotesRecycler#recycle(java.lang.Object)
104      */
105     public synchronized void recycle(final Object object) {
106         final Base notesBase = getNotesObject(object);
107         try {
108             if (notesBase == null) {
109                 return; // ignore null values
110             } else if (notesBase instanceof Session) {
111                 notesBase.recycle();
112             } else if (notesBase instanceof DbDirectory) {
113                 notesBase.recycle();
114             } else if (notesBase instanceof Database) {
115                 notesBase.recycle();
116             } else if (notesBase instanceof Log) {
117                 return; // TODO Check how a Log must be recycled properly. notesBase.recycle();
118             } else if (notesBase instanceof View) {
119                 notesBase.recycle();
120             } else if (notesBase instanceof ViewNavigator) {
121                 notesBase.recycle();
122             } else if (notesBase instanceof ViewEntryCollection) {
123                 return; // don't recycle entry collections
124             } else if (notesBase instanceof ViewEntry) {
125                 notesBase.recycle();
126             } else if (notesBase instanceof DocumentCollection) {
127                 notesBase.recycle();
128             } else if (notesBase instanceof Document) {
129                 notesBase.recycle();
130             } else if (notesBase instanceof Item) {
131                 return; // don't recycle items
132             } else if (notesBase instanceof RichTextItem) {
133                 return; // don't recycle items
134             } else if (notesBase instanceof EmbeddedObject) {
135                 return; // don't recycle embedded objects
136             } else if (notesBase instanceof Form) {
137                 notesBase.recycle();
138             } else if (notesBase instanceof Agent) {
139                 notesBase.recycle();
140             } else if (notesBase instanceof AgentContext) {
141                 notesBase.recycle();
142             } else if (notesBase instanceof DateTime) {
143                 recycleDateTime((DateTime) notesBase);
144             } else if (notesBase instanceof DateRange) {
145                 notesBase.recycle();
146             } else {
147                 getMonitor().debug("No explicit recycle strategy found for class " + notesBase.getClass().getName());
148                 notesBase.recycle();
149             }
150         } catch (NotesException e) {
151             getMonitor().warn("Cannot recycle " + notesBase.getClass().getName(), new DominoException(e));
152         }
153     }
154 
155     /***
156      * Recycles a Notes date/time object.
157      *
158      * @param dateTime the date/time object
159      */
160     private void recycleDateTime(final DateTime dateTime) {
161         try {
162             if (dateTime.getParent() == null) {
163                 //
164                 // DateTime objects that only have a Date component seem
165                 // not to have a parent session in Release 5.0.8 and 5.0.11
166                 // without the HotFix of the file notes.jar from Lotus.
167                 // It is impossible to recycle such objects, so we log an error here.
168                 //
169                 // See also Lotus Software Problem report (SPR):
170                 // http://www.ibm.com/support/docview.wss?uid=sim4ae8f437f0c71ea0b85256c9f00791c48
171                 // -> SPR# MKIN5CYTH4 - Fixed a null pointer exception when calling
172                 //                      the recycle method of DateTime class
173                 //
174                 if (!dateTimeHitfixProblemReported) {
175                     dateTimeHitfixProblemReported = true;
176                     getMonitor().fatalError("recycle a DateTime object without parent session.");
177                 }
178             } else {
179                 dateTime.recycle();
180             }
181         } catch (NotesException e) {
182             getMonitor().warn("recycle DateTime with parent session not available.", new DominoException(e));
183         }
184     }
185 
186     /***
187      * Given any object (might be a Domingo object or a Notes object) returns
188      * the base notes object if available.
189      *
190      * @return notes object
191      */
192     private Base getNotesObject(final Object object) {
193         final Base notesBase;
194         if (object instanceof BaseProxy) {
195             notesBase = ((BaseProxy) object).getNotesObject();
196         } else if (object instanceof Base) {
197             notesBase = (Base) object;
198         } else {
199             notesBase = null;
200         }
201         return notesBase;
202     }
203 }