View Javadoc

1   /*
2    * $Id: Libraries.java,v 1.10 2005/06/01 19:55:51 jlerner Exp $
3    *
4    * Copyright (c) 1999-2004, BBN Technologies, LLC.
5    * All rights reserved.
6    * http://www.daml.org/legal/opensource/bbn_license.html
7    */
8    
9   package com.bbn.swede.core.libraries;
10  
11  import java.io.File;
12  import java.io.FilenameFilter;
13  import java.util.ArrayList;
14  import java.util.Collection;
15  import java.util.Iterator;
16  import java.util.List;
17  import java.util.ListIterator;
18  
19  import org.eclipse.core.resources.IWorkspaceRoot;
20  import org.eclipse.core.resources.ResourcesPlugin;
21  import org.eclipse.core.runtime.IPath;
22  import org.eclipse.core.runtime.Platform;
23  import org.eclipse.core.runtime.jobs.IJobChangeEvent;
24  import org.eclipse.core.runtime.jobs.IJobManager;
25  import org.eclipse.core.runtime.jobs.Job;
26  import org.eclipse.core.runtime.jobs.JobChangeAdapter;
27  
28  import com.bbn.swede.core.OWLCore;
29  
30  /***
31   * A singleton class used to gain access to individual ILibraryDescriptor 
32   * objects.
33   * 
34   * 
35   * @author aperezlo
36   */
37  public final class Libraries
38  {
39     /***
40      * File extension for Ontology Libraries stored on disk.
41      */
42     public static final String LIBRARY_EXTENSION = ".swlib";
43     /***
44      * Directory name for storing Ontology Libraries.  This directory will exist
45      * directly underneath the Eclipse workspace.
46      */
47     public static final String LIBRARY_DIRECTORY = ".swlib";
48     /***
49      * Temp directory for internal library operations.
50      */
51     public static final String LIBRARY_TEMP_DIRECTORY = ".tmp";
52     /***
53      * Identifier for storing library references as a session property.
54      */
55     public static final String SESSION_PROPERTY_QUALIFIER = "com.bbn.swede.core.libraries";
56     /***
57      * Delimeter for storing multiple libraries in one session property.
58      */
59     public static final String SESSION_PROPERTY_DELIMETER = "/";
60     
61     private static Libraries _me;
62     
63     private static long _lastUpdateTime;
64     private List _libraries;
65     private static Collection _busyLibraries;
66     
67     
68     private Libraries()
69     {
70        _libraries = new ArrayList();
71        _lastUpdateTime = OWLCore.getPlugin().getPluginPreferences().getLong(
72           OWLCore.PREFERENCE_LIBRARY_UPDATE_SCHEDULE_LAST_TIME_STR);
73        _busyLibraries = new ArrayList();
74     }
75     
76     /***
77      * Used to refresh all libraries.  This method creates and 
78      * schedules {@link RefreshLibraryJob}s for each library to 
79      * accomplish the work. 
80      */
81     public static void refreshAllLibraries()
82     {
83        _lastUpdateTime = System.currentTimeMillis();
84        OWLCore.getPlugin().getPluginPreferences().setValue(
85           OWLCore.PREFERENCE_LIBRARY_UPDATE_SCHEDULE_LAST_TIME_STR,
86           _lastUpdateTime);
87        OWLCore.getPlugin().savePluginPreferences();
88        getInstance().loadLibraries();
89        ILibraryDescriptor ild = null;
90        Iterator i = getInstance()._libraries.iterator();
91        RefreshLibraryJob rlj = null;
92        String nowString = "Library Refesh - " + Long.toString(System.currentTimeMillis());
93        RefreshJobListener rjl = _me.new RefreshJobListener(nowString);
94        while(i.hasNext())
95        {
96           ild = (ILibraryDescriptor) i.next();
97           rlj = new RefreshLibraryJob(ild, nowString, true);
98           rlj.schedule();
99        }
100    }
101    
102    /***
103     * Determines whether a library is due to be refreshed or not.  This
104     * is based on three pieces of information - first, whether the 
105     * automatic update feature is enabled in the Ontology Library 
106     * preferences page, second, whether the required amount of 
107     * time since the last refresh (also specified on that preferences page)
108     * has elapsed, and finally, whether any of the documents in the specified 
109     * library are configured to be automatically updated.
110     * 
111     * @param ild an ILibraryDescriptor object
112     * @return true if a library is due to be refreshed, false otherwise
113     */
114    public static boolean isDueForRefresh(ILibraryDescriptor ild)
115    {
116       long now = System.currentTimeMillis();
117       long frequency = OWLCore.getPlugin().getPluginPreferences().getLong(
118          OWLCore.PREFERENCE_LIBRARY_UPDATE_SCHEDULE_FREQUENCY_STR);
119       long lastTime = _lastUpdateTime;
120       boolean dueTimewise = (lastTime + frequency) < now;
121       boolean preferencesWise = OWLCore.getPlugin().getPluginPreferences()
122          .getBoolean(OWLCore.PREFERENCE_LIBRARY_AUTOMATIC_UPDATE); 
123       boolean libraryWise = false;
124       ILibraryEntryDescriptor iled = null;
125       Iterator i = null;
126       if(ild.isAvailable())
127       {
128          i = ild.getEntryDescriptors().iterator();
129          
130          while(i.hasNext())
131          {
132             iled = (ILibraryEntryDescriptor) i.next();
133             if(Boolean.TRUE.toString().equals(
134                ((LibraryEntryConfiguration)iled.getConfiguration())
135                   .getUpdateSchedule()))
136             {
137                libraryWise = true;
138                break;
139             }
140          }
141       }
142       
143       return dueTimewise && preferencesWise && libraryWise;
144    }
145    
146    /***
147     * Creates a new empty library with the specified name.  Will fail 
148     * if there already exists a library with that name.
149     * 
150     * @param name the name for the new library - the LIBRARY_EXTENSION 
151     * will automatically be appended to the library name.
152     * @return true if the new library could be created, false otherwise
153     */
154    public static boolean createLibrary(String name)
155    {
156       boolean toReturn = false;
157       ILibrary library = null;
158       if(getLibrary(name) == null)
159       {
160          library = new Library(name);
161          synchronized (getInstance()._libraries)
162          {
163             getInstance()._libraries.add(library.createDescriptor());
164          }
165          toReturn = true;
166       }
167 
168       return toReturn;
169    }
170    /***
171     * Retrieves the location on disk of the library directory.
172     * @return the path of the libarary directory, as a string
173     */
174    public static String getLibraryLocationPath()
175    {
176       return ResourcesPlugin.getWorkspace().getRoot().getLocation().append(
177          LIBRARY_DIRECTORY).toOSString()
178          + File.separator;
179    }
180    /***
181     * Retrieves the location on disk of the library temp directory.
182     * @return the path of the library temp directory, as a string.
183     */
184    public static String getLibraryTempLocationPath()
185    {
186       return getLibraryLocationPath() + Libraries.LIBRARY_TEMP_DIRECTORY + File.separator;
187    }
188    
189    /***
190     * Retrieves a temporary path that can be used to edit a specific library.
191     * @param libraryName the library that is about to undergo an edit
192     * @return a temporary location where edits can occur
193     */
194    public static String getLibraryEditPath(String libraryName)
195    {
196       return getLibraryTempLocationPath() + "." + libraryName + "-edit" + File.separator;
197    }
198    
199    /***
200     * Returns the ILibraryDescriptor associated with a particular 
201     * library name.  If no libraries are presently loaded, this 
202     * method will attempt to load the libraries in the library directory. 
203     * 
204     * @param libraryName the name of the desired library
205     * @return the ILibraryDescriptor representing that library, or null if it cannot be found
206     */
207    public static ILibraryDescriptor getLibrary(String libraryName)
208    {
209       Iterator i = null;
210       ILibraryDescriptor temp = null;
211       boolean found = false;
212       if(getInstance()._libraries.size() == 0)
213       {
214          getInstance().loadLibraries();
215       }
216       
217       i = getInstance()._libraries.iterator();
218       while(i.hasNext())
219       {
220          temp = (ILibraryDescriptor) i.next();
221          if(temp.getName().equals(libraryName))
222          {
223             found = true;
224             break;
225          }
226       }
227 
228       temp = !found ? null : temp;
229       return temp;
230    }
231    
232    
233    private List getAlreadyLoadedLibraryNames()
234    {
235       ArrayList toReturn = new ArrayList();
236       ILibraryDescriptor ild = null;
237       LibraryConfiguration lc = null;
238       synchronized (_libraries)
239       {
240          Iterator i = _libraries.iterator();
241          while(i.hasNext())
242          {
243             ild = (ILibraryDescriptor) i.next();
244             toReturn.add(ild.getName() + LIBRARY_EXTENSION);
245          }
246       }
247       return toReturn;
248    }
249    
250    
251    private synchronized File[] getLibraryFilesToLoad()
252    {
253       IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
254       IPath path = root.getLocation().append(LIBRARY_DIRECTORY);
255       File libraryDirectory = new File(path.toOSString());
256       File libraryTempLocation = new File(path.append(LIBRARY_TEMP_DIRECTORY).toOSString());
257       File[] libraries = null;
258 
259       if(!libraryDirectory.exists())
260       {
261          libraryDirectory.mkdir();
262       }
263       if(!libraryTempLocation.exists())
264       {
265          libraryTempLocation.mkdir();
266       }
267       
268       libraries = libraryDirectory.listFiles(new FilenameFilter()
269       {
270          public boolean accept(File arg0, String arg1)
271          {
272             return (arg1.endsWith(LIBRARY_EXTENSION));
273          }
274       });
275       
276       return libraries;
277 
278    }
279    
280    private synchronized void loadLibraries()
281    {
282       File[] libraries = null;
283       ILibrary tempLibrary = null;
284       List loadedLibraryNames = null;
285       ListIterator libraryIterator = null;
286       ILibraryDescriptor ild = null;
287       loadedLibraryNames = getAlreadyLoadedLibraryNames();
288       
289       // do regular library load...
290       libraries = getLibraryFilesToLoad();         
291       for(int i = 0; i < libraries.length; i++)
292       {
293          // check to make sure that we don't already have a version
294          // lying around that we couldn't close up at the beginning 
295          // of the method
296          if(!loadedLibraryNames.contains(libraries[i].getName()))
297          {
298             tempLibrary = new Library(libraries[i]);
299             _libraries.add(tempLibrary.createDescriptor());
300          }
301          else
302          {
303             String tempString = libraries[i].getName();
304             tempString = tempString.substring(0, tempString.lastIndexOf("."));
305             ild = getLibrary(tempString);
306 
307             if(ild.isAvailable())
308             {
309                ild.setLibrary(new Library(libraries[i]));
310             }
311          }
312       }
313       // ...do regular library load
314    }
315    
316    private static Libraries getInstance()
317    {
318       if(_me == null)
319       {
320          _me = new Libraries();
321       }
322       return _me;
323    }
324    
325    /***
326     * Attempts to delete a library from the system.  This will 
327     * make it unavailable in the future, and will physically delete 
328     * the file that holds the library.
329     * 
330     * @param ild the descriptor of the library to delete
331     * @return true if the delete operation was a success, false otherwise
332     */
333    public static boolean deleteLibrary(ILibraryDescriptor ild)
334    {
335       boolean toReturn = true;
336       File f = null;
337       try
338       {
339          toReturn = ild.close();
340          f  = new File(Libraries.getLibraryLocationPath() + ild.getName() + LIBRARY_EXTENSION);
341          toReturn = f.delete();
342          synchronized (getInstance()._libraries)
343          {
344             ild.delete();
345             getInstance()._libraries.remove(ild);
346          }
347       }
348       catch (Exception e)
349       {
350          toReturn = false;
351       }
352       return toReturn;
353    }
354    
355    /***
356     * Retrieves the descriptors of all Ontology Libraries.
357     * @return a List of all <code>ILibraryDescriptor</code>s, one for each 
358     *         library in the system
359     */
360    public static synchronized List getAllLibraries()
361    {
362       List toReturn = new ArrayList();
363       boolean found = false;
364       synchronized (getInstance()._libraries)
365       {
366          toReturn.addAll(getInstance()._libraries);
367          File[] libraries = getInstance().getLibraryFilesToLoad();
368          for(int i = 0; i < libraries.length; i++)
369          {
370             found = false;
371             Iterator j = toReturn.iterator();
372             while(j.hasNext())
373             {
374                if(libraries[i].getName().equals(((ILibraryDescriptor) j.next()).getName() + LIBRARY_EXTENSION))
375                {
376                   found = true;
377                   break;
378                }
379             }
380             if(!found)
381             {
382                getInstance().loadLibraries();
383                toReturn = new ArrayList();
384                toReturn.addAll(getInstance()._libraries);
385                break;
386             }
387          }
388       }
389       
390       
391       return toReturn;
392    }
393    
394    
395    private final class RefreshJobListener extends JobChangeAdapter 
396    {
397       private IJobManager _jobManager;
398       private String _familyName;
399       
400       /***
401        * Creates a listener that monitors library refresh jobs and reacts
402        * when they are all completed.
403        * @param familyName The family name used to create the refresh jobs
404        */
405       public RefreshJobListener(String familyName)
406       {
407          _jobManager = Platform.getJobManager();
408          _familyName = familyName;
409          _jobManager.addJobChangeListener(this);
410       }
411       
412       /*
413        *  (non-Javadoc)
414        * @see org.eclipse.core.runtime.jobs.IJobChangeListener#done(org.eclipse.core.runtime.jobs.IJobChangeEvent)
415        */
416       public void done(IJobChangeEvent event)
417       {
418          Job[] jobs = null;
419          boolean allDone = false;
420          if(event.getJob().belongsTo(_familyName))
421          {
422             allDone = true;
423             jobs = _jobManager.find(_familyName);
424             for(int i = 0; i < jobs.length; i++)
425             {
426                if(jobs[i].getResult() == null)
427                {
428                   allDone = false;
429                   break;
430                }
431             }
432          }
433          if(allDone)
434          {
435             Libraries.getInstance().loadLibraries();
436             _jobManager.removeJobChangeListener(this);
437          }
438       }
439       
440    }
441    
442    
443 }