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 java.applet.Applet;
26  import java.lang.ref.WeakReference;
27  import java.util.Collection;
28  import java.util.ConcurrentModificationException;
29  import java.util.HashMap;
30  import java.util.Iterator;
31  import java.util.Map;
32  
33  import lotus.domino.NotesError;
34  import lotus.domino.NotesException;
35  import lotus.domino.NotesFactory;
36  import lotus.domino.NotesThread;
37  import lotus.domino.Session;
38  import de.bea.domingo.DNotesFactory;
39  import de.bea.domingo.DNotesMonitor;
40  import de.bea.domingo.DNotesRuntimeException;
41  import de.bea.domingo.DSession;
42  import de.bea.domingo.cache.Cache;
43  import de.bea.domingo.cache.WeakCache;
44  import de.bea.domingo.exception.DominoException;
45  import de.bea.domingo.i18n.ResourceManager;
46  import de.bea.domingo.i18n.Resources;
47  import de.bea.domingo.monitor.MonitorEnabled;
48  import de.bea.domingo.monitor.NullMonitor;
49  
50  /***
51   * Factory for sessions to Notes/Domino.
52   *
53   * @author <a href=mailto:kriede@users.sourceforge.net>Kurt Riede</a>
54   */
55  public final class NotesProxyFactory extends DNotesFactory implements MonitorEnabled {
56  
57      ////////////////////////////////////////////////
58      // constants
59      ////////////////////////////////////////////////
60  
61      /*** Retry count while waiting for disposal. */
62      public static final int MAX_DISPOSE_TRIES = 10;
63  
64      /*** Time to wait for garbage collector [milliseconds]. */
65      public static final int TIME_WAIT_FOR_GC = 100;
66  
67      /*** Threshold size for weak cache. */
68      public static final int DEFAULT_CACHE_THRESHOLD = 2000;
69  
70      /*** Key for map of default IIOP session. */
71      public static final String DEFAULT_IIOP_SESSION_KEY = "defaultIIOPSession";
72  
73      /*** Internationalized resources. */
74      private static final Resources RESOURCES = ResourceManager.getPackageResources(NotesProxyFactory.class);
75  
76      ////////////////////////////////////////////////
77      // instance attributes
78      ////////////////////////////////////////////////
79  
80      /*** Associated internal session (local call only). */
81      private DSession fInternalSession;
82  
83      /*** Map of all IIOP session (one session for each host and username). */
84      private Map fIiopSessions = new HashMap();
85  
86      /*** Base Monitor instance. */
87      private DNotesMonitor fMonitor = null;
88  
89      /*** Reference to recycle strategy implementation. */
90      private NotesRecycler fRecycler = null;
91  
92      /*** Central weak cache for all Notes Proxy classes. */
93      private Cache fBaseCache = new WeakCache();
94  
95      /*** Threshold size for weak cache. */
96      private int fCacheThreshold = DEFAULT_CACHE_THRESHOLD;
97  
98      ////////////////////////////////////////////////
99      // creation
100     ////////////////////////////////////////////////
101 
102     /***
103      * Default constructor.
104      *
105      * <p>Must be public to allow abstract factory (the base class) to create
106      * an instance of this class.</p>
107      */
108     public NotesProxyFactory() {
109         setMonitor(NullMonitor.getInstance());
110         fCacheThreshold = DNotesFactory.getIntProperty("de.bea.domingo.cache.threshold", DEFAULT_CACHE_THRESHOLD);
111     }
112 
113     /***
114      * Package-private constructor to create a factory from within the Lotus Notes VM with
115      * restricted security.
116      *
117      * @param threshold Threshold size for weak cache
118      */
119     public NotesProxyFactory(final int threshold) {
120         setMonitor(NullMonitor.getInstance());
121         if (threshold > 0) {
122             fCacheThreshold = threshold;
123         } else {
124             fCacheThreshold = DEFAULT_CACHE_THRESHOLD;
125         }
126     }
127 
128     /***
129      * Shutdown thread of Domingo, disposes all resources.
130      *
131      * @author <a href="mailto:kriede@users.sourceforge.net">Kurt Riede</a>
132      */
133     public final class DNotesShutdownThread extends Thread {
134 
135         /***
136          * Tries to disposes all related resources.
137          *
138          * @see java.lang.Runnable#run()
139          */
140         public void run() {
141             try {
142                 getMonitor().debug(RESOURCES.getString("shutdownhook.starting"));
143                 getMonitor().debug("baseCache.size = " + getBaseCache().size());
144                 DNotesFactory.dispose();
145                 getMonitor().debug(RESOURCES.getString("shutdownhook.finished"));
146             } catch (DNotesRuntimeException e) {
147                 getMonitor().warn(e.getLocalizedMessage(), e);
148             }
149             super.run();
150         }
151     }
152 
153     /***
154      * Chooses a recycling strategy based on the Notes Client Release.
155      *
156      * Currently we think that even with R6 and later, the
157      * {@link RecycleStrategy} is the best choice and we don't use the
158      * {@link NoRecycleStrategy}. Especially the indeterministic caching of
159      * documents prohibits the {@link NoRecycleStrategy}.
160      *
161      * @param session the Notes Session
162      */
163     private void setRecycler(final Session session) {
164         fRecycler = new RecycleStrategy(getMonitor());
165     }
166 
167     /***
168      * Returns the central weak cache of all notes objects.
169      *
170      * @return central weak cache of all notes objects
171      */
172     public Cache getBaseCache() {
173         return fBaseCache;
174     }
175 
176     /***
177      * @see de.bea.domingo.DNotesFactory#gc()
178      * @deprecated only use this method for testing
179      */
180     public void gc() {
181         preprocessMethod();
182     }
183 
184     /***
185      * <p>In this single threaded implementation, first the own reference
186      * to the session is nulled and then we wait for the weak cache to
187      * be finalized.
188      *
189      * @param force indicates if disposal should happen even if still any
190      *              strong or soft reference exists. if <code>false</code>,
191      *              only weak references must remain.
192      *
193      * @see de.bea.domingo.DNotesFactory#dispose()
194      * @see de.bea.domingo.DNotesFactory#dispose(boolean)
195      * @see java.lang.ref.WeakReference
196      * @deprecated use {@link #disposeInternal(boolean)} instead
197      */
198     public void disposeInternal(final boolean force) {
199         disposeInstance(force);
200     }
201 
202     /***
203      * <p>In this single threaded implementation, first the own reference
204      * to the session is nulled and then we wait for the weak cache to
205      * be finalized.
206      *
207      * @see de.bea.domingo.DNotesFactory#dispose()
208      * @see de.bea.domingo.DNotesFactory#dispose(boolean)
209      * @see java.lang.ref.WeakReference
210      */
211     public void disposeInstance() {
212         disposeInstance(false);
213     }
214 
215     /***
216      * <p>In this single threaded implementation, first the own reference
217      * to the session is nulled and then we wait for the weak cache to
218      * be finalized.
219      *
220      * <p>Equivalent to
221      * <code>{link {@link #disposeInstance(boolean) disposeInstance(false)}</code></p>.
222      *
223      * @param force indicates if disposal should happen even if still any
224      *              strong or soft reference exists. if <code>false</code>,
225      *              only weak references must remain.
226      *
227      * @see de.bea.domingo.DNotesFactory#dispose()
228      * @see de.bea.domingo.DNotesFactory#dispose(boolean)
229      * @see java.lang.ref.WeakReference
230      */
231     public void disposeInstance(final boolean force) {
232         System.gc();
233         recycleQueue();
234         fInternalSession = null;
235         if (force) {
236             disposeStrong();
237         } else {
238             disposeWeak();
239         }
240         if (fBaseCache.size() > 0) {
241             final int k = logUndisposedObjects();
242             if (k > 1) {
243                 getMonitor().warn("There are still " + k + " undisposed objects in the object cache:");
244             } else {
245                 getMonitor().warn("There is still one undisposed object in the object cache:");
246             }
247             if (k > 0) {
248                 getMonitor().warn("Unable to dispose all objects.");
249             } else {
250                 getMonitor().info("All objects in object cache disposed successfully.");
251             }
252         }
253         if (getMonitor().isDebugEnabled()) {
254             getMonitor().debug("DateTime counter is " + BaseProxy.getCountDateTime());
255         }
256     }
257 
258     /***
259      * Disposes all objects that have only weak references.
260      * All objects that still have strong references, are not disposed.
261      */
262     private void disposeWeak() {
263         int tries = 0;
264         while (fBaseCache.size() > 0 && tries < MAX_DISPOSE_TRIES) {
265             tries++;
266             getMonitor().debug("Waiting for notes disposal. (" + fBaseCache.size() + " objects in queue)");
267             System.gc();
268             recycleQueue();
269             sleep(TIME_WAIT_FOR_GC);
270         }
271     }
272 
273     /***
274      * Disposes all objects even if there are still strong references left.
275      * All objects that still have strong references, are not valid anymore afterwards.
276      */
277     private void disposeStrong() {
278         Collection values = fBaseCache.values();
279         while (values.size() > 0) {
280             try {
281                 final Iterator objects = values.iterator();
282                 while (objects.hasNext()) {
283                     Object obj = objects.next();
284                     if (obj != null) {
285                         if (obj instanceof WeakReference) {
286                             obj = ((WeakReference) obj).get();
287                         }
288                         if (obj != null) {
289                             recycleLater(obj);
290                         }
291                     }
292                 }
293                 recycleQueue();
294                 fBaseCache.clear();
295             } catch (ConcurrentModificationException e) {
296                 getMonitor().debug("Concurrent modification in disposeStrong(); retry recycle");
297             }
298         }
299     }
300 
301     /***
302      * Logs and counts all undisposed objects to the current monitor.
303      * @return number of undisposed objects
304      */
305     private int logUndisposedObjects() {
306         final Iterator iterator = fBaseCache.values().iterator();
307         int i = 0;
308         int k = 0;
309         while (iterator.hasNext()) {
310             Object obj = iterator.next();
311             i++;
312             if (obj != null) {
313                 if (obj instanceof WeakReference) {
314                     obj = ((WeakReference) obj).get();
315                 }
316                 if (obj != null) {
317                     k = k + 1;
318                     getMonitor().warn("undisposed object " + k + ": " + obj.getClass().getName() + "." + obj.toString());
319                 }
320             }
321         }
322         return k;
323     }
324 
325     /***
326      * Sleep some milliseconds unless interrupted.
327      *
328      * @param millis time to sleep in milliseconds
329      */
330     private synchronized void sleep(final int millis) {
331         try {
332             wait(millis);
333         } catch (InterruptedException e) {
334             return;
335         }
336     }
337 
338     /***
339      * Recycles resources associated with an object.
340      *
341      * <p>Static delegation method to associated recycle strategy.</p>
342      *
343      * @param object the object to recycle
344      *
345      * @see de.bea.domingo.proxy.NotesRecycler#recycle(java.lang.Object)
346      */
347     void recycle(final Object object) {
348         if (fRecycler != null) {
349             fRecycler.recycle(object);
350         }
351     }
352 
353     /***
354      * @see de.bea.domingo.proxy.NotesRecycler#recycleLater(java.lang.Object)
355      */
356     void recycleLater(final Object object) {
357         if (fRecycler != null) {
358             fRecycler.recycleLater(object);
359         }
360     }
361 
362     /***
363      * @see de.bea.domingo.proxy.NotesRecycler#recycleQueue()
364      */
365     void recycleQueue() {
366         if (fRecycler != null) {
367             fRecycler.recycleQueue();
368         }
369     }
370 
371     ////////////////////////////////////////////////
372     //    interface DNotesFactory
373     ////////////////////////////////////////////////
374 
375     /***
376      * {@inheritDoc}
377      * @see de.bea.domingo.DNotesFactory#getSession()
378      */
379     public DSession getSession() throws DNotesRuntimeException {
380         if (fInternalSession == null) {
381             try {
382                 preprocessMethod();
383                 final Session session = NotesFactory.createSession();
384                 fInternalSession = SessionProxy.getInstance(this, session, getMonitor());
385                 setRecycler(session);
386                 logSsession(session);
387                 handleShutdownHook();
388             } catch (NotesException e) {
389                 throw new NotesProxyRuntimeException(RESOURCES.getString("cannot.create.session"), new DominoException(e));
390             } catch (UnsatisfiedLinkError e) {
391                 if (e.getMessage().indexOf("java.library.path") >= 0) {
392                     throw new NotesProxyRuntimeException(RESOURCES.getString("notes.installation.not.found"), e);
393                 } else if (e.getMessage().indexOf("NGetWrapper") >= 0 || e.getMessage().indexOf("NCreateSession") >= 0) {
394                     throw new NotesProxyRuntimeException(RESOURCES.getString("notes.installation.not.found"), e);
395                 } else {
396                     throw new NotesProxyRuntimeException(e.getMessage(), e);
397                 }
398             } catch (NoClassDefFoundError e) {
399                 throw new NotesProxyRuntimeException(RESOURCES.getString("notes.jar.missing.in.classpath"), e);
400             }
401         }
402         return fInternalSession;
403     }
404 
405     /***
406      * {@inheritDoc}
407      * @see de.bea.domingo.DNotesFactory#getSession(java.lang.String)
408      */
409     public DSession getSession(final String serverUrl) throws DNotesRuntimeException {
410         DSession session = (DSession) fIiopSessions.get(serverUrl);
411         if (session == null) {
412             try {
413                 preprocessMethod();
414                 final Session notesSession = NotesFactory.createSession(serverUrl);
415                 session = SessionProxy.getInstance(this, notesSession, getMonitor());
416                 setRecycler(notesSession);
417                 handleShutdownHook();
418                 fIiopSessions.put(serverUrl, session);
419             } catch (NotesException e) {
420                 throw new NotesProxyRuntimeException(RESOURCES.getString("cannot.create.session"), new DominoException(e));
421             } catch (NoClassDefFoundError e) {
422                 if (e.getMessage().indexOf("lotus/domino/cso/Session") >= 0) {
423                     throw new NotesProxyRuntimeException(RESOURCES.getString("ncso.missing"), e);
424                 }
425             }
426        }
427         return session;
428     }
429 
430     /***
431      * {@inheritDoc}
432      * @see de.bea.domingo.DNotesFactory#getSession(java.lang.String, java.lang.String, java.lang.String)
433      */
434     public DSession getSession(final String host, final String user, final String passwd) throws DNotesRuntimeException {
435         DSession session = (DSession) fIiopSessions.get(host + ":" + user);
436         if (session == null || !session.isValid()) {
437             try {
438                 preprocessMethod();
439                 final Session notesSession = NotesFactory.createSession(host, user, passwd);
440                 session = SessionProxy.getInstance(this, notesSession, getMonitor());
441                 setRecycler(notesSession);
442                 fIiopSessions.put(host + ":" + user, session);
443             } catch (NotesException e) {
444                 throw new NotesProxyRuntimeException(RESOURCES.getString("cannot.create.session"), new DominoException(e));
445             } catch (NoClassDefFoundError e) {
446                 if (e.getMessage().indexOf("lotus/domino/cso/Session") >= 0) {
447                     throw new NotesProxyRuntimeException(RESOURCES.getString("ncso.missing"), e);
448                 } else {
449                     throw e;
450                 }
451             }
452         }
453         return session;
454     }
455 
456     /***
457      * {@inheritDoc}
458      * @see de.bea.domingo.DNotesFactory#getSessionSSL(java.lang.String, java.lang.String, java.lang.String)
459      */
460     public DSession getSessionSSL(final String host, final String user, final String passwd) throws DNotesRuntimeException {
461         String[] args = new String[1];
462         args[0] = "-ORBEnableSSLSecurity";
463         return getSession(host, args, user, passwd);
464     }
465 
466     /***
467      * {@inheritDoc}
468      * @see de.bea.domingo.DNotesFactory#getSession(java.lang.String, java.lang.String[], java.lang.String, java.lang.String)
469      */
470     public DSession getSession(final String host, final String[] args, final String user, final String passwd)
471             throws DNotesRuntimeException {
472         DSession session = (DSession) fIiopSessions.get(host + ":" + user + ":" + args);
473         if (session == null || !session.isValid()) {
474             try {
475                 preprocessMethod();
476                 final Session notesSession = NotesFactory.createSession(host, args, user, passwd);
477                 session = SessionProxy.getInstance(this, notesSession, getMonitor());
478                 setRecycler(notesSession);
479                 fIiopSessions.put(host + ":" + user, session);
480             } catch (NotesException e) {
481                 throw new NotesProxyRuntimeException(RESOURCES.getString("cannot.create.session"), new DominoException(e));
482             } catch (NoClassDefFoundError e) {
483                 if (e.getMessage().indexOf("lotus/domino/cso/Session") >= 0) {
484                     throw new NotesProxyRuntimeException(RESOURCES.getString("ncso.missing"), e);
485                 }
486             }
487         }
488         return session;
489     }
490 
491     /***
492      * {@inheritDoc}
493      * @see de.bea.domingo.DNotesFactory#getSession(java.applet.Applet, java.lang.String, java.lang.String)
494      */
495     public DSession getSession(final Applet applet, final String user, final String passwd) throws DNotesRuntimeException {
496         DSession session = null;
497         try {
498             preprocessMethod();
499             final Session notesSession = NotesFactory.createSession(applet, user, passwd);
500             session = SessionProxy.getInstance(this, notesSession, getMonitor());
501             setRecycler(notesSession);
502         } catch (NotesException e) {
503             if (e.id == NotesError.NOTES_ERR_SESOPEN_FAILED) {
504                 throw new NotesProxyRuntimeException(RESOURCES.getString("cannot.create.session"), new DominoException(e));
505             } else {
506                 throw new NotesProxyRuntimeException(RESOURCES.getString("cannot.create.session"), new DominoException(e));
507             }
508         } catch (NoClassDefFoundError e) {
509             if (e.getMessage().indexOf("lotus/domino/cso/Session") >= 0) {
510                 throw new NotesProxyRuntimeException(RESOURCES.getString("ncso.missing"), e);
511             }
512         }
513         return session;
514     }
515 
516     /***
517      * {@inheritDoc}
518      * @see de.bea.domingo.DNotesFactory#getSession(java.lang.Object)
519      */
520     public DSession getSession(final Object notesSession) throws DNotesRuntimeException {
521         return SessionProxy.getInstance(this, (Session) notesSession, getMonitor());
522     }
523 
524     /***
525      * {@inheritDoc}
526      * @see de.bea.domingo.DNotesFactory#getSessionWithFullAccess()
527      */
528     public DSession getSessionWithFullAccess() throws DNotesRuntimeException {
529         if (fInternalSession == null) {
530             try {
531                 preprocessMethod();
532                 final Session session = NotesFactory.createSessionWithFullAccess();
533                 fInternalSession = SessionProxy.getInstance(this, session, getMonitor());
534                 setRecycler(session);
535                 logSsession(session);
536                 handleShutdownHook();
537             } catch (NotesException e) {
538                 throw new NotesProxyRuntimeException(RESOURCES.getString("cannot.create.session"), new DominoException(e));
539             } catch (UnsatisfiedLinkError e) {
540                 if (e.getMessage().indexOf("java.library.path") >= 0) {
541                     throw new NotesProxyRuntimeException(RESOURCES.getString("notes.installation.not.found"), e);
542                 } else if (e.getMessage().indexOf("NGetWrapper") >= 0 || e.getMessage().indexOf("NCreateSession") >= 0) {
543                     throw new NotesProxyRuntimeException(RESOURCES.getString("notes.installation.not.found"), e);
544                 } else {
545                     throw new NotesProxyRuntimeException(e.getMessage(), e);
546                 }
547             } catch (NoClassDefFoundError e) {
548                 throw new NotesProxyRuntimeException(RESOURCES.getString("notes.jar.missing.in.classpath"), e);
549             }
550         }
551         return fInternalSession;
552     }
553 
554     /***
555      * {@inheritDoc}
556      * @see de.bea.domingo.DNotesFactory#getSessionWithFullAccess(java.lang.String)
557      */
558     public DSession getSessionWithFullAccess(final String password) throws DNotesRuntimeException {
559         if (fInternalSession == null) {
560             try {
561                 preprocessMethod();
562                 final Session session = NotesFactory.createSessionWithFullAccess(password);
563                 fInternalSession = SessionProxy.getInstance(this, session, getMonitor());
564                 setRecycler(session);
565                 logSsession(session);
566                 handleShutdownHook();
567             } catch (NotesException e) {
568                 throw new NotesProxyRuntimeException(RESOURCES.getString("cannot.create.session"), new DominoException(e));
569             } catch (UnsatisfiedLinkError e) {
570                 if (e.getMessage().indexOf("java.library.path") >= 0) {
571                     throw new NotesProxyRuntimeException(RESOURCES.getString("notes.installation.not.found"), e);
572                 } else if (e.getMessage().indexOf("NGetWrapper") >= 0 || e.getMessage().indexOf("NCreateSession") >= 0) {
573                     throw new NotesProxyRuntimeException(RESOURCES.getString("notes.installation.not.found"), e);
574                 } else {
575                     throw new NotesProxyRuntimeException(e.getMessage(), e);
576                 }
577             } catch (NoClassDefFoundError e) {
578                 throw new NotesProxyRuntimeException(RESOURCES.getString("notes.jar.missing.in.classpath"), e);
579             }
580         }
581         return fInternalSession;
582     }
583 
584     /***
585      * If requested and possible, adds a shutdown hook to dispose domingo
586      * on termination of the virtual machine.
587      */
588     private void handleShutdownHook() {
589         final boolean shutdownhook = DNotesFactory.getBooleanProperty("de.bea.domingo.shutdownhook", true);
590         if (shutdownhook) {
591             if (checkPermission("shutdownHooks")) {
592                 Runtime.getRuntime().addShutdownHook(new DNotesShutdownThread());
593             } else {
594                 getMonitor().warn(RESOURCES.getString("shutdownhook.not.allowed"));
595             }
596         }
597     }
598 
599     /***
600      * Checks if the requested access, specified by the given permission name,
601      * is permitted based on the security policy currently in effect.
602      *
603      * @param name the name of the RuntimePermission.
604      * @return <code>true</code> if access is permitted based on the current
605      *         security policy, else <code>false</code>
606      * @see java.lang.SecurityManager#checkPermission(java.security.Permission)
607      */
608     private boolean checkPermission(final String name) {
609         final SecurityManager sm = System.getSecurityManager();
610         if (sm == null) {
611             return true;
612         }
613         try {
614             sm.checkPermission(new RuntimePermission(name));
615         } catch (SecurityException e) {
616             return false;
617         }
618         return true;
619     }
620 
621     /***
622      * Logs information of a session to the current monitor.
623      *
624      * @param session a session
625      * @throws NotesException if any problem occured with the session
626      */
627     private void logSsession(final Session session) throws NotesException {
628         final DNotesMonitor monitor = getMonitor();
629         String currentVersion = "(unknown version)";
630         try {
631             currentVersion = session.getNotesVersion();
632         } catch (NotesException e) {
633             monitor.warn(RESOURCES.getString("cannot.get.notes.version"), new DominoException(e));
634         }
635         if (session.getClass().getName().equals("lotus.domino.cso.Session")) {
636             monitor.info(RESOURCES.getString("connect.to.domino.1", currentVersion));
637         } else {
638             monitor.info(RESOURCES.getString("connect.to.notes.1", currentVersion));
639         }
640         monitor.debug(RESOURCES.getString("local.session.established"));
641         monitor.debug("    " + RESOURCES.getString("notes.user") + ": " + session.getUserName());
642         monitor.debug("    " + RESOURCES.getString("notes.version") + ": " + session.getNotesVersion());
643         monitor.debug("    " + RESOURCES.getString("notes.platform") + ": " + session.getPlatform());
644         monitor.debug("    " + RESOURCES.getString("notes.data") + ": " + session.getEnvironmentString("Directory", true));
645     }
646 
647     /***
648      * @see de.bea.domingo.DNotesFactory#sinitThread()
649      */
650     public void sinitThread() {
651         getMonitor().debug(RESOURCES.getString("thread.initialize"));
652         try {
653             NotesThread.sinitThread();
654         } catch (UnsatisfiedLinkError e) {
655             getMonitor().debug("Local Notes Client not accessable; only remote connections possible");
656         } catch (NoClassDefFoundError e) {
657             getMonitor().debug("Local Notes Client not accessable; only remote connections possible");
658         }
659     }
660 
661     /***
662      * @see de.bea.domingo.DNotesFactory#stermThread()
663      */
664     public void stermThread() {
665         getMonitor().debug(RESOURCES.getString("thread.terminate"));
666         try {
667             NotesThread.stermThread();
668         } catch (UnsatisfiedLinkError e) {
669             getMonitor().debug("Local Notes Client not accessable.");
670         } catch (NoClassDefFoundError e) {
671             getMonitor().debug("Local Notes Client not accessable.");
672         }
673     }
674 
675     /***
676      * Preprocessing before each method invocation.
677      */
678     void preprocessMethod() {
679         final int size1 = getBaseCache().size();
680         if (fCacheThreshold != 0) {
681             if (size1 > fCacheThreshold) {
682                 getMonitor().debug("baseCache.size = " + size1 + "; recycle queue now");
683                 System.gc();
684             }
685         }
686         recycleQueue();
687         final int size2 = getBaseCache().size();
688         if (size1 != size2) {
689             getMonitor().debug("baseCache.size = " + size2 + "; after recycling queue");
690         }
691     }
692 
693     /***
694      * {@inheritDoc}
695      * @see de.bea.domingo.DNotesFactory#getMonitor()
696      */
697     public DNotesMonitor getMonitor() {
698         return fMonitor;
699     }
700 
701     /***
702      * {@inheritDoc}
703      * @see de.bea.domingo.DNotesFactory#setMonitor(de.bea.domingo.DNotesMonitor)
704      */
705     public void setMonitor(final DNotesMonitor theMonitor) {
706         this.fMonitor = theMonitor;
707     }
708 }