Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: org/mitre/cvw/DSIController.java


1   /*
2    * Copyright (c) 1996-2000. The MITRE Corporation (http://www.mitre.org/).
3    * All rights reserved.
4    * CVW comes with ABSOLUTELY NO WARRANTY. See license for details.
5    */
6   
7   package org.mitre.cvw;
8   
9   import java.io.*;
10  import java.net.*;
11  import java.util.Date;
12  import java.util.Vector;
13  
14  import org.mitre.cvw.docserv.DocServException;
15  
16  import org.mitre.cvw.docserv.AttributeSignature;
17  import org.mitre.cvw.docclnt.DocFactory;
18  
19  /**
20   * A shell class to handle launching of DocServer threads.
21   * Other classes wishing to control the Document Server and get
22   * information should funnel all calls through this shell.
23   * 
24   * This class also deals with user-interface issues and error
25   * reporting. The calling routine can call into here and never worry
26   * again about what happens. This allows DSIController to run multiple
27   * document server threads and control the results.
28   * 
29   * In beginning, the document server availability was also tied to the 
30   * availability of the Netscape plugin (NPDocServer), since this client 
31   * was an applet.  Now that it is an application, the availability of the 
32   * plugin is not relevant but the code dependency has not been removed.
33   * 
34   * 8/23/00 SRJ MAJOR REWRITE!!!
35   * Added a level above this class (DocumentServerList) to incorporate federation
36   * Did a lot of cleanup and changing. Basically, made this class more of a 
37   * container for each document server encountered. The main entry point will 
38   * now be DocumentServerList
39   * @version 1.0
40   * @author Marc N. Cannava
41   * @author S.R.Jones
42   */
43  public class DSIController extends Object implements ObjectValues {
44  
45    protected String DSHost;      // The base DocServer host
46    protected String DSUrl;       // The docservlet url 
47    protected int DSPort;         // The base DocServer port
48    private static String CheckDir;    // The base checkout directory
49      //  private static String UserName = "unknown";    // The current user name using the client
50      private static String PROTOCOL = "http"; // define the protocol to connect to DS 
51  
52    static CVWCoordinator jcvw = CVWCoordinator.getInstance(); // Pointer to CVW Coordinator object
53    static NPDocServer plugin = NPDocServer.getInstance();
54    DocFactory factory = null;    // the default factory constructor
55  
56    static Vector runTable = new Vector(); // List of running DSI's
57    static Vector runThreads = new Vector(); // List of running DSI threads
58    static Vector docIDTable = new Vector(); // List of docID's w/ops-in-progress
59  
60      DSIParms resultParms; // Holds result for sync() calls
61      //  static Object blockObject; // Indicator for thread completion
62      //Thread runThread; // The thread this object is running on
63  
64    private boolean available = true;
65    private static boolean firstTime = true;
66  
67  /* **********************************
68   * 4/6/98 dage -- static/class methods 
69   */
70  
71  /**
72   * Returns whether connectivity to the document server is available.
73   * @return whether connectivity to the document server is available
74   */
75    public boolean isAvailable() {
76          return available;
77      }
78  
79  /**
80   * Returns teh current instance of this class, instantiates it if first time thru.
81   * @return  the current instance
82   *
83   public static DSIController getInstance(){
84   if (currentDSI == null && available)
85   initDocServerCheck();
86   return currentDSI;
87   }
88  */
89  
90  /**
91   * Checks to see if document server connectivity is available.
92   * @return <code>true</code> if document server connectivity is available
93   */
94    private boolean initDocServerCheck(URL location) {
95      boolean result = false;
96      if(firstTime) {
97        if(CVWCoordinator.DEBUG) System.err.println("DSI: First time thru, initting dsi...");
98        try {
99          initDocServerInterface(location);
100   result = true;
101       } catch (CheckoutDirectoryException e) {
102         checkoutDirNotAvailable();
103         //return;
104       } catch (Throwable e) {
105   System.err.println(e);
106         docGenericError();
107         //return;
108       }
109     }
110     available = result;
111     return result;
112   }
113 
114 /**
115  * Initializes the single instance of this class, checks to make sure 
116  * connectivity to the document server is available, the user checkout dir
117  * exists and tries to start its own thread.
118  * @exception  CheckoutDirectoryException 
119  * @exception  Throwable 
120  */
121   private void initDocServerInterface(URL location) throws CheckoutDirectoryException, Throwable {
122  
123     if(CVWCoordinator.DEBUG) System.err.println("IDSI: Plugin is initted to: "+plugin);
124     if (location == null) throw new ConnectException("Cannot connect to null docserver");
125  
126     DSHost = location.getHost();
127     DSUrl = location.getFile();
128     DSPort = location.getPort();
129 
130     if (DSHost == null) 
131      jcvw.displayError("There was no CVW document server specified in your CVW server configuration file.  Document features are unavailable.",
132                  "CVW Document Server Problem", false);
133     
134 /* 8/7/98 dage - added the following block to see if dshost and dsport are
135  *   even valid
136  */
137     try {
138       Socket s = new Socket(DSHost, DSPort);
139     } catch (Exception v) { 
140   if (v instanceof UnknownHostException) {
141       String host = v.getMessage();
142       jcvw.displayError("You are trying to connect to a document server with name: " 
143             + host + ".  Document features are unavailable.  Please check your configurtion file.", 
144             "Unknown CVW Document Server", false);
145   } else if (v instanceof ConnectException) { 
146       jcvw.displayError("There is a problem connecting to CVW document server: " + 
147             DSHost + ":" + DSPort + ".  Document features are unavailable.",
148             v.getMessage(), false);
149          } else {
150      if (DSHost == null) 
151         jcvw.displayError("There was no CVW document server specified in your CVW server configuration file.  Document features are unavailable.",
152         "CVW Document Server Problem", false);
153     else 
154         jcvw.displayError("There is a problem connecting to CVW document server: " + 
155         DSHost + ":" + DSPort + ".  Document features are unavailable.",
156         "CVW Document Server Problem", false);
157     v.printStackTrace(); 
158          }
159   throw v;
160     }
161  
162     try {
163   if(CVWCoordinator.DEBUG) System.err.println("Calling the dsi constructor..");
164   String name = new String();
165   //if (currentUser != null)
166         //name = currentUser.name;
167   //currentDSI=new DSIController(0);  //dont use the null parm constructor
168   //Thread dsiThread = new Thread(currentDSI);
169   //dsiThread.start();
170   //    } catch (CheckoutDirectoryException exc) {
171   //  if(CVWCoordinator.DEBUG) System.err.println("INIT DSI EXCEPTION: "+exc);
172   //  throw exc;
173     } catch (Throwable exc) {
174   if(CVWCoordinator.DEBUG) System.err.println("INIT DSI GENERAL EXCEPTION: "+exc);
175   throw exc;
176     }
177  
178   }
179 
180 /**
181  * Checks to see if user is currently editing documents, if so warns them,
182  * and user can cancel logout.
183  * @return  <code>true</code> if the logout process should be continued
184  * @exception  CheckoutDirectoryException 
185  * @exception  Throwable 
186  */
187   public boolean docServerLogout() {
188  
189     OkCancelDialog okc;
190     DSIParms dsp=null;
191     DocServerInterface tdsi = new DocServerInterface(this);
192     String docNames = new String();
193     String name = new String();
194     int x;
195     String msg = null;
196  
197     syncWithDocServer();  //clean up cache directory
198 
199     try {
200       dsp=startDSSyncOp(USERSTAT, null);
201       Vector cd = dsp.vectorResult;
202  
203       // Get the names. Since we've sync'ed w/ the docserver, use the DSDB file for this info
204       // we just did this with syncWithDocServer above, but don't know a better way right now
205       DSDB localDB = new DSDB(CheckDir, plugin);
206 
207       int coCount = cd.size();
208       for (int i=0; i<localDB.getCount(); i++) {
209           try {
210               DSDBEntry entry = localDB.getNextEntry();
211               if (entry.ReadWrite() &&
212     (entry.getServer().equals(CVWCoordinator.getInstance().getServerName()))) {
213     // true, so doc is checked out
214                   docNames = docNames + "\"" + entry.Name() + "\" ";
215               } else
216            coCount--;
217           } catch (DBEntryNotFoundException enfe) {}  // error reading DSDB file
218       }
219 
220 
221       docNames = "(" + docNames.trim() + ")";
222       //if (jcvw.DEBUG) System.err.println(docNames);
223  
224       if(coCount > 0) {
225         msg = "You are currently working on "+coCount+" document(s) "+docNames+".  In order to continue working with those documents, your next login must be on the same machine.  If you login from another machine, your changes to those documents will be discarded.";
226       }
227     } catch (DocInUseException e) {
228       msg = "If you are currently working on any documents, in order to continue working with those documents, your next login must be on the same machine.  If you login from another machine, your changes to those documents will be discareded.";
229     }
230  
231    if (msg == null) return true;
232  
233    okc=new OkCancelDialog(jcvw, msg, true, "Documents Opened for Editing", OkCancelDialog.WARNING, OkCancelDialog.OKCANCEL);
234    okc.pack(); okc.setVisible(true);
235    if(okc.cancel) return false;
236    return true;
237   }
238 
239 /**
240  * Synchronize the user's local database file with the information on the 
241  * document server.
242  * @exception  CheckoutDirectoryException 
243  * @exception  Throwable 
244  * @see #verifyCache
245  */
246   public void syncWithDocServer() {
247       try {
248         verifyCache();
249       } catch (DocServException d) {
250         displayError("Couldn't complete verification because the document server did not respond.");
251       }
252    }
253 
254 /**
255  * Preforms the right mouse menu functions on the specified document.
256  * @param document the document to perform the function on
257  * @param function the right mouse menu function
258  * @return  <code>true</code> if the function was performed successfully
259  * @exception  CheckoutDirectoryException 
260  * @exception  Throwable 
261  *
262  * @see #startDSOp
263  */
264    public boolean doDocMenu(CVWDocument document, String function) {
265  
266      Integer docID;
267      docID = new Integer(document.docID);
268      DSIParms indsip= new DSIParms();
269      DSIParms outdsip;
270      indsip.name = document.name;
271      indsip.docID = docID;
272  
273      if(CVWCoordinator.DEBUG) System.err.print("DocID is: "+docID + " ");
274  
275      if(function.startsWith("Open")) {
276        indsip.doOpen=false;
277        indsip.context = null;  // this happened when we changed to application
278        try {
279          if(document.isShortcut()) 
280            indsip.shortcut=true;
281          else
282            indsip.shortcut=false;
283          int indx = startDSOp(DOCOPEN, indsip);
284        } catch (DocInUseException e) {
285      e.printStackTrace();
286           displayDocServInUseError();
287          return false;
288        }
289        return true;
290      }
291 
292      if(function.startsWith("Export")) {
293       String path = plugin.fileBrowse("Export File", "Save", document.name);
294       if (path == null)
295         return false;
296  
297       if (plugin.fileExists(path)) {
298          plugin.removeFile(path);  // if not removed then over write doesnt quite work.
299         }
300  
301        indsip.path = path;
302        try {
303          startDSOp(DOCEXPORT, indsip);
304    jcvw.displayPrvSysMsg("\"" + document.name + "\" is now stored locally on your workstation as " + path + ".");
305          return true;
306        } catch (DocInUseException e) {
307           displayDocServInUseError();
308           return false;
309        }
310      }
311  
312      if(function.startsWith("Check Out")) {
313        try {
314          startDSSyncOp(CHECKOUT, indsip);
315    // track locally that it's checked out
316    document.setCheckOut(true);
317          return true;
318        } catch (DocInUseException e) {
319      e.printStackTrace();
320           displayDocServInUseError();
321          return false;
322        }
323      }
324  
325      indsip.objNum = document.objNum.strValue();
326      if(function.startsWith("Save Changes")) {
327        try {
328          startDSOp(DOCCHECKIN, indsip);
329    // track that's the doc's checked in
330      //9/13/98 dage - not here ... document.setCheckOut(false);
331          return true;
332        } catch (DocInUseException e) {
333           displayDocServInUseError();
334          return false;
335        }
336  
337      }
338  
339      if(function.startsWith("Discard Changes")) {
340        try {
341          startDSOp(REVERT, indsip);
342       //9/13/98 dage - not here ... document.setCheckOut(false);
343          return true;
344        } catch (DocInUseException e) {
345           displayDocServInUseError();
346          return false;
347        }
348      }
349  
350      if(function.startsWith("Delete")) {
351        System.err.println("in doDocMenu funct=Delete");
352        return doDocDelete(document.objNum.strValue(), docID, false);
353      }
354  
355      return false;
356    }
357 
358 /**
359  * Deletes the specified document from the document server.
360  * @param objNum the object number of the document
361  * @param docID the document id of the document
362  * @param finalTime whether this is the final time that the document has
363  * been requested to delete, not final time means the user just requested
364  * the deletion and some initial checks have to be made
365  * @return  whether the delete was successfull
366  * @exception  CheckoutDirectoryException 
367  * @exception  Throwable 
368  */
369   public boolean doDocDelete(String objNum, int docID, boolean finalTime) {
370        System.err.println("in doDocDelete: String, int, boolean, DocToken");
371         return doDocDelete(objNum, new Integer(docID), finalTime);
372    }
373 
374 
375 /**
376  * Deletes the specified document from the document server.
377  * @param objNum the object number of the document
378  * @param docID the document id of the document
379  * @param finalTime whether this is the final time that the document has
380  * been requested to delete, not final time means the user just requested
381  * the deletion and some initial checks have to be made
382  * @return  whether the delete was successfull
383  * @exception  CheckoutDirectoryException 
384  * @exception  Throwable 
385  */
386   public boolean doDocDelete(String objNum, Integer docID, boolean finalTime) {
387     String error_msg = "none";
388     DSIParms indsip=new DSIParms();
389     indsip.docID = docID;
390     DSIParms outdsip;
391  
392     System.err.println("doDocDelete: finalTime is " + finalTime);
393 
394     if (finalTime) {
395       try {
396         outdsip=startDSSyncOp(DOCDELETE,indsip);
397         if(outdsip.exc != null) throw outdsip.exc;
398       } catch (DocServException d) {
399         displayError(d.toString());
400         return false;
401       } catch (DocInUseException d) {
402         displayDocServInUseError();
403         return false;
404       }
405       return true;
406     } else {
407       String status = "None";
408       try {
409         outdsip=startDSSyncOp(DOCSTATUS,indsip);
410         if(outdsip.exc != null) throw outdsip.exc;
411         status = outdsip.stringResult;
412       } catch (DocServException d) {
413         if(CVWCoordinator.DEBUG) System.err.println("DocServException (delete)");
414         error_msg = d.toString();
415       } catch (DocInUseException d) {
416         if(CVWCoordinator.DEBUG) System.err.println("INUSEEXCEPTION (delete)");
417         error_msg = "Document services are in process. Please wait for the last action to complete and try again.";
418       }
419       if (error_msg.equals("none"))
420         if (status.startsWith("None"))
421           return true;
422         else {
423           if(CVWCoordinator.DEBUG) System.err.println("status is "+status);
424 displayError(" You are currently working on that document, so it could not be deleted.  Either save or discard your changes before deleting.");
425         }
426       else
427         displayError(error_msg);
428       return false;
429     }
430   }
431 
432 /**
433  * Returns a new document id needed when copying an existing document.
434  * @param docid the document id of the document to be copied
435  * @return  the new document id
436  * @exception  CheckoutDirectoryException 
437  * @exception  Throwable 
438  */
439    public int getNewDocID(String docid) {
440     
441     Integer newDocId = new Integer("0");;
442     DSIParms inparm = new DSIParms();
443     DSIParms outparm;
444     String name = "Item";
445  
446     int newID = 0;
447  
448     try {
449       inparm.docID = new Integer(docid);
450       outparm=startDSSyncOp(DOCCOPY, inparm);
451       if(outparm.exc != null) throw outparm.exc;
452       newDocId = outparm.integerResult;
453       newID = newDocId.intValue();
454     } catch (DocServException d) {
455       displayError(d.toString());
456       //newID = 0;
457     } catch (DocInUseException e) {
458       displayDocServInUseError();
459       //newID = 0;
460     }
461     return newID;
462   }
463 
464 
465 /**
466  * Checks to see if the document specified can be accessed and is not busy.
467  * @param docID the document to be checked
468  * @return  <code>true</code> if the document can be accessed
469  * @exception  CheckoutDirectoryException 
470  * @exception  Throwable 
471  */
472    public boolean documentIsBusy(String docID) {
473         DSIParms inparm,outparm;
474         inparm = new DSIParms();
475         try {
476           inparm.docID = new Integer(docID);
477           outparm=startDSSyncOp(DOCBUSY, inparm);
478           if(outparm.exc != null) throw outparm.exc;
479         } catch (DocServException d) {
480           displayError(d.toString());
481           return true;
482   } catch (DocInUseException e) {
483       e.printStackTrace();
484           displayDocServInUseError();
485           return true;
486         }
487        return false;
488       }
489 
490 
491 /**
492  * Displays the standard error that the document server is currently busy.
493  * @exception  CheckoutDirectoryException 
494  * @exception  Throwable 
495  */
496    public static void displayDocServInUseError() {
497      displayError("Document services here are in process. Please wait for the last action to complete and try again.");
498    }
499 
500 /**
501  * Displays the standard error that the document server is not installed.
502  * Note: this was pertinent when the doc server availability was tied to the
503  * Netscape plugin.
504  * @exception  CheckoutDirectoryException 
505  * @exception  Throwable 
506  */
507    public static void displayDocServNotInstalled() {
508       if (!firstTime) return;
509       //displayError("The CVW Plugin is either not installed or not available. If you have installed the Plugin, then call your Administrator.");
510       displayError("The CVW Document server is not available.");
511   firstTime = false;
512      }
513 
514 /**
515  * Displays the specified error message.
516  * @param msg the error message to display
517  * @exception  CheckoutDirectoryException 
518  * @exception  Throwable 
519  */
520    public static void displayError(String msg) {
521      if (msg.equals("Invalid document ID")) return;
522      jcvw.displayError(msg, false);
523    }
524 
525 /**
526  * Display error for debugging purposes.
527  * @exception  CheckoutDirectoryException 
528  * @exception  Throwable 
529  */
530   public static void docGenericError() {
531     if (CVWCoordinator.DEBUG) System.err.println("ERROR: Generic error, Document features unavailable.");
532   }
533 /**
534  * Display error for debugging purposes.
535  * @exception  CheckoutDirectoryException 
536  * @exception  Throwable 
537  */
538   public static void checkoutDirNotAvailable() {
539     if (CVWCoordinator.DEBUG) System.err.println("ERROR: Checkout directory not avaiable, Document features unavailable.");
540   }
541 
542 /* 
543  * 4/6/98 dage - end of class/static methods
544  * **********************************/
545   //
546   // The constructors live here.
547   //
548 /**
549  * Constructor
550  * @return 
551  */
552   public DSIController() {
553     if(CVWCoordinator.DEBUG) System.err.println("**** CONSTRUCTED: New DSIController");
554     //    runThread = null;
555     //    if(blockObject == null) {
556     //  blockObject = new Object();
557     //    }
558   }
559 
560 /**
561  * Runs the current thread.
562  */
563   public void run() {
564     int x;
565     boolean handled;
566 
567     //    runThread = Thread.currentThread();
568     if(CVWCoordinator.DEBUG) System.err.println("DSIC: INITIALIZED ");
569 
570 //      synchronized(blockObject) {
571 //        while(true) {
572 
573 //    try {
574 //      if(CVWCoordinator.DEBUG) System.err.println("[DSIC/RUN] WAITING FOR A THREAD");
575 //      blockObject.wait();
576 //      if(CVWCoordinator.DEBUG) System.err.println("[DSIC/RUN] NOTIFIED ABOUT THREAD");
577 //    } catch (InterruptedException e) {
578 //      if(CVWCoordinator.DEBUG) System.err.println("[DSIC/RUN] INTERRUPTED... WHAT?");
579 //    }
580 
581 //    if(CVWCoordinator.DEBUG) System.err.println("DSIC Thread Int: "+Thread.currentThread());
582 //    handled = false;
583 
584 //    while (!handled) { // Make sure we handle a thread now
585 //        for(x=0;x<runThreads.size();x++) {
586 //      if(CVWCoordinator.DEBUG) System.err.println("Checking thread id: ["+x+"]");
587 //      if(isFinished(x)) {
588 //          if(CVWCoordinator.DEBUG) System.err.println("Thread ID: ["+x+"] is ready.");
589 //          handled = true;
590 //          handleThreadReturn(x);
591 //      }
592 //        }
593 //    }
594   
595 //        }
596 //      }
597   }
598 
599 /* 1/23/98 dage - added this because when dsi is inited, the current user name 
600     is not known
601  * 2/6/98 dage - verify cache at this point
602  */
603 /**
604  * Sets the current user name once the user has connected.
605  * @param name the name of the current user
606  */
607   public void setupUser() throws CheckoutDirectoryException {
608     if(CVWCoordinator.DEBUG) System.err.println("Setting up user"); 
609     
610     String sysDir = plugin.getUserCheckoutDir();
611     if (sysDir == null) {
612       // Memory allocation didn't happen, so NULL was returned..
613       //currentDSI = null;
614       throw new CheckoutDirectoryException();
615     }
616 
617     CheckDir = sysDir;
618   
619     if (!plugin.setupCheckoutDir()) {
620   String msg = "Cache directory could not be created/accessed: " + CheckDir;
621         System.err.println(msg);
622   CVWCoordinator.getInstance().displayError(msg, "Cache Access Problem", false);
623       }
624 
625     if (!isAvailable()) {
626        if(CVWCoordinator.DEBUG) System.err.println("cant verify cache");
627   return;
628      }
629 
630     // now set up the DocFactory for this user
631     AttributeSignature as = new AttributeSignature();
632     as.put("Content-Type", new Integer(2));   // just a default int type. meaningless right now
633     factory = new DocFactory(DSHost, DSPort, DSUrl, getUserName(), as);
634 
635     // Verify the cache
636     try {
637       verifyCache();
638     } catch (DocServException e) {
639       // Couldn't verify cache for now
640       System.err.println("Couldn't validate server integrity, continuing.");
641     }
642 
643    }
644 
645 /* 4/10/98 dage - no longer pass in all the parameters, can directly ask
646  *  CVWCoordinator or SysUtils.
647  *
648  *
649  *  4/8/98 dage - need to have some parameter list because subclass
650  *   DocServerInterface needs a constructor with an empty parm list
651  */
652 /**
653  * Constructor
654  * @param dummy
655  * @return 
656  * @exception  CheckoutDirectoryException  
657  */
658   public DSIController(URL location) {
659     int rc=0;
660 
661     //    runThread = null;  // Filled in in the "run" method
662 
663     jcvw.displayPrvSysMsg("Please wait a moment. Performing one-time document initialization ...");
664     if(CVWCoordinator.DEBUG) System.err.println("Init DSIController, Thread: "+Thread.currentThread());
665 
666     //initMimeVector();
667 
668  /*
669  *  for some reason had to add init the blockObject var.
670  */
671 //      if(blockObject == null) {
672 //    blockObject = new Object();
673 //      }
674  
675     initDocServerCheck(location);
676     
677     if(CVWCoordinator.DEBUG) System.err.println("DSI: Done with init, plugin is "+plugin);
678   }
679 
680 /**
681  * Methods to start a DS request, query a current request's status,
682  * and retrieve the results of a request
683  *
684  * Start a request. In general, the philosophy is that we can 
685  * perform *one* operation at a time on a given docID, so we check
686  * to see which docID's are currently having operations performed 
687  * on them. If the docID does not appear, we can continue to start
688  * the operation. Returns a transaction index.
689  * 
690  * @param opcode the operation to perform
691  * @param params the parameters the document server needs
692  * @return  the index of this document server transaction  
693  * @exception  DocInUseException 
694  */
695   public int startDSOp(int opcode, DSIParms params) throws DocInUseException {
696 
697       System.err.println("starting DSOp, code " + opcode);
698     // REMOVE THESE LINES
699       //  if(inUse(params.docID)) throw new DocInUseException();
700     // REMOVE THESE LINES
701 
702     // Add these lines and remove the above ones when a reentrant
703       // plugin is available.
704       if(params.docID.intValue() != 0 && inUse(params.docID))
705            throw new DocInUseException();
706       
707       //      if(this.runThread == null) {
708     // This means that the run() method hasn't gotten around
709     // to initializing the runThread variable yet. Hang around
710     // and wait until this is the case.
711 //      int count=0;
712 //      boolean ready = false;
713 //      while(!ready && count < 10000) {
714 //          if(this.runThread != null) ready=true;
715 //          count++;
716 //      }
717 //      if(!ready) throw new DocInUseException();
718     //      }
719 
720       if(CVWCoordinator.DEBUG) System.err.println("Constructing dsi");
721 //        DocServerInterface dsi = new DocServerInterface(this, opcode, params, 
722 //                    blockObject, 
723 //                    runTable.size()+1);
724 
725       DocServerInterface dsi = new DocServerInterface(this, opcode, params, 
726                   runTable.size()+1);
727 
728       if(CVWCoordinator.DEBUG) System.err.println("Done DSI");
729       
730       Thread pThread = new Thread(dsi);
731     
732       runTable.addElement(dsi); // Enter this DSI into the runtable
733       runThreads.addElement(pThread); // Enter this thread into the runtable
734       docIDTable.addElement(params.docID); // Enter this docID into exclusivity
735 
736       pThread.start();
737 
738       if (CVWCoordinator.DEBUG) System.err.println("returning from startDSOp");
739       return(runTable.size()-1);
740   }
741 
742 
743 /**
744  * Returns true if the docID is currently active/in use.
745  *
746  * NOTE NOTE NOTE
747  * Until the plugin is made re-entrant (i.e., it can support
748  * more than one file open at a time), this routine will always return
749  * TRUE if there is ANY document operation in progress. 
750  * CHANGE THIS ROUTINE for multiple operations on multiple documents,
751  * after the plugin is rewritten.
752  * @param docID the document id to be checked
753  * @return whether the document is in use
754  * @exception  DocInUseException 
755  */
756   public boolean inUse(Integer docID) {
757     int x;
758     Integer id;
759 
760     //// REMOVE THESE LINES
761     //    if(docIDTable.size() > 0) return(true);
762     //    else return(false);
763     //// REMOVE THESE LINES
764 
765     // Add these lines and remove the above ones for multiple
766     // document operations.
767     //
768     for(x=0;x<docIDTable.size();x++) {
769     id=(Integer)docIDTable.elementAt(x);
770     if(id.intValue() == docID.intValue()) return true;
771     }
772     return false;
773   }
774 
775 /**
776  * Start a request, and wait for it to finish. Return the process'
777  * DSI result block.
778  * @param opcode the function to perform
779  * @param params the parameters the document server needs
780  * @return  the result parameters from the document server
781  * @exception  DocInUseException 
782  */
783   public DSIParms startDSSyncOp(int opcode, DSIParms params) throws DocInUseException {
784     int idx;
785     DSIParms parms;
786     System.err.println("starting dssyncOp, code " + opcode);
787 
788     if(params == null) parms = new DSIParms(); 
789     else parms = params;
790 
791     // REMOVE THESE LINES
792     //    if(inUse(parms.docID)) throw new DocInUseException();
793     // REMOVE THESE LINES
794 
795     // No op, just wanted to check if the doc was in use.
796     // Returns the parms passed in.
797     if(opcode == DOCBUSY) return(parms); 
798 
799     // Add these lines and remove the above ones for multiple
800     // doc operations
801     if(parms.docID.intValue() != 0 && inUse(parms.docID))
802   throw new DocInUseException();
803 
804     idx=this.startDSOp(opcode, parms);
805     Thread myThread = (Thread)runThreads.elementAt(idx);
806 
807     while(myThread.isAlive()) {
808       try {
809   if (CVWCoordinator.DEBUG) 
810           System.err.println("[DSIC/SDSSO] WAITING FOR A THREAD");
811 //    synchronized(this) { 
812 //            this.wait(); 
813 //          } // Wait for thread completion 
814   if (CVWCoordinator.DEBUG) 
815           System.err.println("[DSIC/SDSSO] WAITING FOR A THREAD");
816       } catch (Exception e) {
817   // No big deal
818       }
819     } 
820     DSIParms returnParms = handleThreadReturn(idx);
821 
822     return(returnParms);
823   }
824 
825 /**
826  * Check status of request/transaction.
827  * @param transIdx the index of the transaction being checked
828  * @return  <code>true</code> if the transaction is finished
829  */
830   private boolean isFinished(int transIdx) {
831     Thread thr;
832 
833     thr = (Thread)runThreads.elementAt(transIdx);
834     return(!thr.isAlive());
835   }
836 
837 /**
838  * Retrieve results of request.
839  * @param transIdx the index of the transaction being checked
840  * @return  the result parameters from the document server
841  * @exception  DSNotFinishedException 
842  *
843  public DSIParms getResult(int transIdx) throws DSNotFinishedException {
844  DocServerInterface dsi;
845     
846  if(!isFinished(transIdx)) throw new DSNotFinishedException();
847  dsi = (DocServerInterface)runTable.elementAt(transIdx);
848  return(dsi.result);
849  }
850 */
851 
852 /**
853  * Remove this transaction from the indexes, it's no longer
854  * needed. Removes the object from the runtable,
855  * removes the thread from the thread table, and releases the
856  * op lock on the docID
857  * @param transIdx the index of the transaction being checked
858  */
859   private synchronized void releaseDSOp(int transIdx) {
860 
861       if(CVWCoordinator.DEBUG) System.err.println("[RDSO] Cleaning up from tables..");
862       runTable.removeElementAt(transIdx);
863       runThreads.removeElementAt(transIdx);
864       docIDTable.removeElementAt(transIdx);
865       if(CVWCoordinator.DEBUG) System.err.println("[RDSO] Cleaning up complete.");
866   }
867 
868     /**
869      * Cleans up thread information 
870      *
871      * @param thread The thread who's finished processing
872      */
873     public void releaseThreadInfo(Thread thread) {
874   int i;
875 
876   String name = thread.getName();
877   System.err.println("Trying to release thread " + name);
878   for (i = 0; i < runThreads.size(); i++) {
879       Thread t = (Thread)runThreads.elementAt(0);
880       System.err.println("Found thread: " + t.getName());
881       if (t.getName().equals(name)) {
882     System.err.println("Release thread at index: " + i);
883     // see if we need to handle this return first
884     DSIParms dsip = handleThreadReturn(i);
885     //    releaseDSOp(i);
886     return;
887       }
888   }
889     }
890 
891 /**
892  * Handles the return of a particular thread.
893  * @param threadID the thread which has finished
894  */
895   private DSIParms handleThreadReturn(int threadID) {
896 
897     DocServerInterface dsi = (DocServerInterface)runTable.elementAt(threadID);
898     DSIParms dsip=dsi.result;
899     DSIParms indsip=dsi.parms;
900 
901     boolean exc = false;
902     String excMessage = null;
903 
904     if(CVWCoordinator.DEBUG) System.err.println("THREAD RETURNED: ["+threadID+"]; "+Thread.currentThread());
905 
906     try { 
907       // Catch any thrown exceptions
908       if(dsip.exc!= null) {
909   if(CVWCoordinator.DEBUG) System.err.println("THREAD EXCEPTION: "+dsip.exc);
910   throw dsip.exc;
911       }
912 
913       if(CVWCoordinator.DEBUG) System.err.println("NO EXCEPTION, post-process..");
914 
915       // Post-processing
916       if(dsi.operation == DOCCREATE) {
917   // call to moo server
918   Integer docID = dsip.integerResult;
919         String mimeType = dsip.stringResult; 
920   CVWDocument cvwDoc = new CVWDocument();
921   cvwDoc.objectCreate(indsip.name, mimeType, indsip.sessile, indsip.desc, 
922         indsip.path, docID);
923       }
924 
925     } catch (DocServException e) {
926       // RJT calling displayError() here with modality true results in the
927       // OkCancelDialog object unable to receive/process events.  Make call 
928       // after we releaseDSOp() and synchronize().
929       exc = true;
930       excMessage = e.toString();
931     }
932 
933     //    this.resultParms = dsip;
934     if(CVWCoordinator.DEBUG) System.err.println("Releasing thread..");
935     releaseDSOp(threadID);
936     //    synchronized(this) {this.notify();}
937 
938     if (exc) 
939       displayError(excMessage);
940 
941     return dsip;
942   }
943 
944   //
945   // Local public methods
946   //
947 /**
948  * Verifies the cache integrity, database integrity, and
949  * synchronization with the document server.
950  * @exception  DocServException 
951  */
952   private void verifyCache() throws DocServException {
953     DSDBEntry entry;
954     Integer doc;
955     String resultMsg=null;
956     int x;
957     DocServerInterface dsi=new DocServerInterface(this);
958 
959     if(runTable.size() > 0) {
960       displayError("Can't perform integrity check during document operation.");
961       displayError("Please wait for the previous operation to complete.");
962       return;
963     }
964 
965     jcvw.displayPrvSysMsg("Synchronizing your local document database with the document server's data.");
966 
967     // Local DB is okay if we can create it
968     DSDB localDB = new DSDB(this.CheckDir,plugin);
969 
970     // First, check to see if the database agrees
971     // with the document server
972     Vector cdocs = dsi.DocUserStatus();
973 
974     for(x=0;x<cdocs.size();x++) {
975       doc=(Integer)cdocs.elementAt(x);
976       System.err.println("[DS->DB]: Checking doc: "+doc);
977       try {
978   entry=localDB.getEntry(doc.intValue());
979   if(!entry.ReadWrite()) {
980     displayError("You had previously opened \""+entry.Name()+"\" for editing but the system encountered a locking error. Any changes you made will be discarded.  Report this to your administrator.");
981     try {dsi.ClearDocLock(doc.intValue());}
982          catch (DocNotCheckedOutException e) {}
983     catch (DocIDException e) {}
984   }
985       } catch (DBEntryNotFoundException e) {
986   // This is bad; the DocServer has it checked out to us,
987   // but our database doesn't even have it at all.
988   String name;
989   try {
990     name=dsi.GetDocName(doc.intValue());
991   } catch (Exception z) {
992     name="Unknown (#"+doc.intValue()+")";
993   }
994     displayError("You had previously opened \""+name+"\" for editing but it is not on your local computer, perhaps because you were working on another computer.  Any changes you made will be discarded.");
995   try {dsi.ClearDocLock(doc.intValue());}
996        catch (DocNotCheckedOutException f) {}
997   catch (DocIDException f) {}
998       }
999     }
1000
1001    // Now, the other way around: Check if the local DB agrees w/ the
1002    // DocServer
1003    localDB.resetCurrentEntry();
1004    Vector ddocs = new Vector();
1005    boolean found=false;
1006
1007    try {
1008      for(entry=localDB.getNextEntry(); true; entry=localDB.getNextEntry()) {
1009  System.err.print("[DB->DS]: Checking doc: "+entry.getID());
1010  if (!entry.getServer().equals(CVWCoordinator.getInstance().getServerName())) {
1011    //System.err.println(" different doc server.");
1012        } else {
1013  if(entry.ReadWrite()) {
1014    found=false;
1015    for(x=0;x<cdocs.size();x++) {
1016      doc=(Integer)cdocs.elementAt(x);
1017      if(doc.intValue() == entry.getID()) found=true;
1018    }
1019    if(!found) {
1020// dage -- couldnt we make sure that the current user is the user in the 
1021//          db file before deleting
1022      System.err.println(" -- not valid, deleting");
1023      displayError("You had previously opened \""+entry.Name()+"\" for editing but the system encountered a synchronizaton problem. Any changes you made will be discarded.  Report this to your administrator.");
1024      ddocs.addElement(entry);
1025    } else { System.err.println("-- Okay.");}
1026  }
1027      }
1028      }   //end for
1029    } catch (DBEntryNotFoundException e) {} // Terminates loop
1030
1031    System.err.println();
1032
1033    // Go through and delete from the database
1034    for(x=0;x<ddocs.size();x++) {
1035      try {
1036  entry=(DSDBEntry)ddocs.elementAt(x);
1037  System.err.println("[MAINT]: Deleting "+entry.getID());
1038  if(plugin.fileExists(entry.Path())) {
1039    plugin.setFileLock(entry.Path(),(short)0);
1040    plugin.removeFile(entry.Path());
1041  }
1042  localDB.removeEntry(entry);
1043      } catch (DBEntryNotFoundException e) {}
1044    }
1045
1046    // Last, check to see if the database agrees
1047    // with the file cache. Also, clear out any R/O entries.
1048    localDB.resetCurrentEntry();
1049    ddocs = new Vector();
1050
1051    try {
1052      for(entry=localDB.getNextEntry(); true; entry=localDB.getNextEntry()) {
1053  System.err.println("[DB->FS]: Checking doc: "+entry.getID());
1054  if(!plugin.fileExists(entry.Path()) && entry.ReadWrite()) {
1055    displayError("You had previously opened \""+entry.Name()+"\" for editing but it is not on your local computer, perhaps because someone deleted it manually.  Any changes you made will be discarded.");
1056    ddocs.addElement(entry);
1057  } else if(!plugin.fileExists(entry.Path())) {
1058    ddocs.addElement(entry);
1059  } else if(!entry.ReadWrite()) {
1060    System.err.println("\""+entry.Name()+"\" is R/O, clearing ("+entry.getID()+")");
1061    ddocs.addElement(entry);
1062  }
1063      }
1064    } catch (DBEntryNotFoundException e) {} // Terminates loop
1065
1066    // Go through and delete from the database
1067    for(x=0;x<ddocs.size();x++) {
1068      try {
1069  entry=(DSDBEntry)ddocs.elementAt(x);
1070  System.err.println("[MAINT]: Deleting "+entry.getID());
1071  if(plugin.fileExists(entry.Path())) {
1072    plugin.setFileLock(entry.Path(),(short)0);
1073    plugin.removeFile(entry.Path());
1074  }
1075  localDB.removeEntry(entry);
1076      } catch (DBEntryNotFoundException e) {}
1077    }
1078
1079    jcvw.displayPrvSysMsg("Synchronization with the document server is complete.");
1080  }
1081
1082  //
1083  // Private internal utility methods
1084  //
1085
1086    public DocFactory getDocFactory() {
1087  return factory;
1088    }
1089
1090    public URL getDSUrl() throws MalformedURLException {
1091  return (new URL(PROTOCOL, DSHost, DSPort, DSUrl));
1092    }
1093
1094    public String getUserName() {
1095  return CVWUser.getFedUserName();
1096    }
1097
1098}
1099
1100
1101
1102