ef37ebddb08bfbf414ee18fc7f14d771383f39c4
[jalview.git] / src / jalview / bin / Cache.java
1 /*
2  * Jalview - A Sequence Alignment Editor and Viewer
3  * Copyright (C) 2007 AM Waterhouse, J Procter, G Barton, M Clamp, S Searle
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License
7  * as published by the Free Software Foundation; either version 2
8  * of the License, or (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
18  */
19 package jalview.bin;
20
21 import java.io.*;
22 import java.util.*;
23
24 import org.apache.log4j.*;
25
26 /**
27  * Stores and retrieves Jalview Application Properties
28  * Lists and fields within list entries are separated by '|' symbols unless otherwise stated
29  * (|) clauses are alternative values for a tag.
30  * <br><br>Current properties include:
31  * <ul>
32  * <br>logs.Axis.Level - one of the stringified Levels for log4j controlling the logging level for axis (used for web services)
33  * <br>
34  * </li><li>logs.Castor.Level - one of the stringified Levels for log4j controlling the logging level for castor (used for serialization)
35  * <br>
36  * </li><li>logs.Jalview.Level - Cache.log stringified level.
37  * <br>
38  * </li><li>DISCOVERY_START - Boolean - controls if discovery services are queried on startup
39  * </li><li>DISCOVERY_URLS - comma separated list of Discovery Service endpoints.
40  * </li><li>SCREEN_WIDTH
41  * </li><li>SCREEN_HEIGHT
42  * </li><li>SCREEN_Y=285
43  * </li><li>SCREEN_X=371
44  * </li><li>SHOW_FULLSCREEN boolean
45  * </li><li>FONT_NAME java font name for alignment text display
46  * </li><li>FONT_SIZE size of displayed alignment text
47  * </li><li>FONT_STYLE style of font displayed (sequence labels are always italic)
48  * </li><li>GAP_SYMBOL character to treat as gap symbol (usually -,.,' ')
49  * </li><li>LAST_DIRECTORY last directory for browsing alignment
50  * </li><li>USER_DEFINED_COLOURS list of user defined colour scheme files
51  * </li><li>SHOW_FULL_ID show id with '/start-end' numbers appended
52  * </li><li>SHOW_IDENTITY show percentage identity annotation
53  * </li><li>SHOW_QUALITY show alignment quality annotation
54  * </li><li>SHOW_ANNOTATIONS show alignment annotation rows
55  * </li><li>SHOW_CONSERVATION show alignment conservation annotation
56  * </li><li>DEFAULT_COLOUR default colour scheme to apply for a new alignment
57  * </li><li>DEFAULT_FILE_FORMAT file format used to save 
58  * </li><li>STARTUP_FILE file loaded on startup (may be a fully qualified url)
59  * </li><li>SHOW_STARTUP_FILE flag to control loading of startup file
60  * </li><li>VERSION the version of the jalview build
61  * </li><li>BUILD_DATE date of this build
62  * </li><li>LATEST_VERSION the latest jalview version advertised on the www.jalview.org
63  * </li><li>PIR_MODELLER boolean indicating if PIR files are written with MODELLER descriptions
64  * </li><li>(FASTA,MSF,PILEUP,CLUSTAL,BLC,PIR,PFAM)_JVSUFFIX boolean for adding jv suffix to file
65  * </li><li>RECENT_URL list of recently retrieved URLs
66  * </li><li>RECENT_FILE list of recently opened files
67  * </li><li>USE_PROXY flag for whether a http proxy is to be used
68  * </li><li>PROXY_SERVER the proxy
69  * </li><li>PROXY_PORT
70  * </li><li>NOQUESTIONNAIRES true to prevent jalview from checking the questionnaire service
71  * </li><li>QUESTIONNAIRE last questionnaire:responder id string from questionnaire service
72  * </li><li>DAS_LOCAL_SOURCE list of local das sources
73  * </li><li>SHOW_OVERVIEW boolean for overview window display
74  * </li><li>ANTI_ALIAS boolean for smooth fonts
75  * </li><li>RIGHT_ALIGN_IDS boolean
76  * </li><li>AUTO_CALC_CONSENSUS boolean for automatic recalculation of consensus
77  * </li><li>PAD_GAPS boolean
78  * </li><li>ID_ITALICS boolean 
79  * </li><li>SHOW_JV_SUFFIX
80  * </li><li>WRAP_ALIGNMENT
81  * </li><li>EPS_RENDERING (Prompt each time|Lineart|Text) default for EPS rendering style check
82  * </li><li>SORT_ALIGNMENT (No sort|Id|Pairwise Identity)
83  * </li><li>SEQUENCE_LINKS list of name|URL pairs for opening a url with $SEQUENCE_ID$
84  * </li><li>DAS_REGISTRY_URL the registry to query
85  * </li><li>DEFAULT_BROWSER for unix
86  * </li><li>DAS_ACTIVE_SOURCE list of active sources
87  * </li><li>SHOW_MEMUSAGE boolean show memory usage and warning indicator on desktop (false) 
88  * </li><li> 
89  * </li>
90  * 
91  * </ul>
92
93  * @author $author$
94  * @version $Revision$
95  */
96 public class Cache
97 {
98   /**
99    * property giving log4j level for CASTOR loggers
100    */
101   public static final String CASTORLOGLEVEL = "logs.Castor.level";
102   /**
103    * property giving log4j level for AXIS loggers
104    */
105   public static final String AXISLOGLEVEL = "logs.Castor.level";
106   /**
107    * property giving log4j level for Jalview Log
108    */
109   public static final String JALVIEWLOGLEVEL = "logs.Jalview.level";
110   public static final String DAS_LOCAL_SOURCE = "DAS_LOCAL_SOURCE";
111
112   /**
113    * Initialises the Jalview Application Log
114    */
115   public static Logger log;
116
117   /** Jalview Properties */
118   public static Properties applicationProperties = new Properties();
119
120   /** Default file is  ~/.jalview_properties */
121   static String propertiesFile;
122
123   public static void initLogger()
124   {
125     try
126     {
127       ConsoleAppender ap = new ConsoleAppender(new SimpleLayout(),
128       "System.err");
129       ap.setName("JalviewLogger");
130       org.apache.log4j.Logger.getRootLogger().addAppender(ap); // catch all for log output
131       Logger laxis = Logger.getLogger("org.apache.axis");
132       Logger lcastor = Logger.getLogger("org.exolab.castor");
133       jalview.bin.Cache.log = Logger.getLogger("jalview.bin.Jalview");
134
135       laxis.setLevel(Level.toLevel(Cache.getDefault("logs.Axis.Level",
136           Level.INFO.toString())));
137       lcastor.setLevel(Level.toLevel(Cache.getDefault("logs.Castor.Level",
138           Level.INFO.toString())));
139       lcastor = Logger.getLogger("org.exolab.castor.xml");
140       lcastor.setLevel(Level.toLevel(Cache.getDefault("logs.Castor.Level",
141               Level.INFO.toString())));
142       jalview.bin.Cache.log.setLevel(Level.toLevel(Cache.getDefault(
143           "logs.Jalview.level",
144           Level.INFO.toString())));
145       //laxis.addAppender(ap);
146       //lcastor.addAppender(ap);
147       //jalview.bin.Cache.log.addAppender(ap);
148       // Tell the user that debug is enabled
149       jalview.bin.Cache.log.debug("Jalview Debugging Output Follows.");
150     }
151     catch (Exception ex)
152     {
153       System.err.println("Problems initializing the log4j system\n");
154       ex.printStackTrace(System.err);
155     }
156   }
157
158   /** Called when Jalview is started */
159   public static void loadProperties(String propsFile)
160   {
161     propertiesFile = propsFile;
162     if (propsFile == null)
163     {
164       propertiesFile = System.getProperty("user.home") + File.separatorChar +
165           ".jalview_properties";
166     }
167
168     try
169     {
170       FileInputStream fis = new FileInputStream(propertiesFile);
171       applicationProperties.load(fis);
172       applicationProperties.remove("LATEST_VERSION");
173       applicationProperties.remove("VERSION");
174       fis.close();
175     }
176     catch (Exception ex)
177     {
178       System.out.println("Error reading properties file: " + ex);
179     }
180
181     if (getDefault("USE_PROXY", false))
182     {
183       System.out.println("Using proxyServer: " + getDefault("PROXY_SERVER", null) +
184                          " proxyPort: " + getDefault("PROXY_PORT", null));
185       System.setProperty("http.proxyHost", getDefault("PROXY_SERVER", null));
186       System.setProperty("http.proxyPort", getDefault("PROXY_PORT", null));
187     }
188
189     // FIND THE VERSION NUMBER AND BUILD DATE FROM jalview.jar
190     // MUST FOLLOW READING OF LOCAL PROPERTIES FILE AS THE
191     // VERSION MAY HAVE CHANGED SINCE LAST USING JALVIEW
192     try
193     {
194       String buildDetails = "jar:"
195           .concat(
196               Cache.class.getProtectionDomain().getCodeSource().getLocation().
197               toString()
198               .concat("!/.build_properties")
199           );
200
201       java.net.URL localJarFileURL = new java.net.URL(buildDetails);
202
203       InputStream in = localJarFileURL.openStream();
204       applicationProperties.load(in);
205       in.close();
206     }
207     catch (Exception ex)
208     {
209       System.out.println("Error reading build details: " + ex);
210       applicationProperties.remove("VERSION");
211     }
212
213     String jnlpVersion = System.getProperty("jalview.version");
214     String codeVersion = getProperty("VERSION");
215
216     if (codeVersion == null)
217     {
218       // THIS SHOULD ONLY BE THE CASE WHEN TESTING!!
219       codeVersion = "Test";
220       jnlpVersion = "Test";
221     }
222
223     System.out.println("Jalview Version: " + codeVersion);
224
225     // jnlpVersion will be null if we're using InstallAnywhere
226     // Dont do this check if running in headless mode
227     if (jnlpVersion == null && (
228         System.getProperty("java.awt.headless") == null
229         || System.getProperty("java.awt.headless").equals("false")))
230     {
231
232       class VersionChecker
233           extends Thread
234       {
235         public void run()
236         {
237           String jnlpVersion = null;
238           try
239           {
240             java.net.URL url = new java.net.URL(
241                 "http://www.jalview.org/webstart/jalview.jnlp");
242             BufferedReader in = new BufferedReader(new InputStreamReader(url.
243                 openStream()));
244             String line = null;
245             while ( (line = in.readLine()) != null)
246             {
247               if (line.indexOf("jalview.version") == -1)
248               {
249                 continue;
250               }
251
252               line = line.substring(line.indexOf("value=") + 7);
253               line = line.substring(0, line.lastIndexOf("\""));
254               jnlpVersion = line;
255               break;
256             }
257           }
258           catch (Exception ex)
259           {
260             System.out.println(ex);
261             jnlpVersion = getProperty("VERSION");
262           }
263
264           setProperty("LATEST_VERSION", jnlpVersion);
265         }
266       }
267
268       VersionChecker vc = new VersionChecker();
269       vc.start();
270     }
271     else
272     {
273       if (jnlpVersion != null)
274       {
275         setProperty("LATEST_VERSION", jnlpVersion);
276       }
277       else
278       {
279         applicationProperties.remove("LATEST_VERSION");
280       }
281     }
282
283     setProperty("VERSION", codeVersion);
284
285     //LOAD USERDEFINED COLOURS
286     jalview.gui.UserDefinedColours.initUserColourSchemes(getProperty(
287         "USER_DEFINED_COLOURS"));
288     jalview.io.PIRFile.useModellerOutput = Cache.getDefault("PIR_MODELLER", false);
289   }
290
291   /**
292    * Gets Jalview application property of given key. Returns null
293    * if key not found
294    *
295    * @param key Name of property
296    *
297    * @return Property value
298    */
299   public static String getProperty(String key)
300   {
301     return applicationProperties.getProperty(key);
302   }
303
304   /** These methods are used when checking if the saved preference
305    * is different to the default setting
306    */
307
308   public static boolean getDefault(String property, boolean def)
309   {
310     String string = getProperty(property);
311     if (string != null)
312     {
313       def = Boolean.valueOf(string).booleanValue();
314     }
315
316     return def;
317   }
318
319   /** These methods are used when checking if the saved preference
320    * is different to the default setting
321    */
322   public static String getDefault(String property, String def)
323   {
324     String string = getProperty(property);
325     if (string != null)
326     {
327       return string;
328     }
329
330     return def;
331   }
332
333   /**
334    * Stores property in the file "HOME_DIR/.jalview_properties"
335    *
336    * @param key Name of object
337    * @param obj String value of property
338    *
339    * @return String value of property
340    */
341   public static String setProperty(String key, String obj)
342   {
343     try
344     {
345       FileOutputStream out = new FileOutputStream(propertiesFile);
346       applicationProperties.setProperty(key, obj);
347       applicationProperties.store(out, "---JalviewX Properties File---");
348       out.close();
349     }
350     catch (Exception ex)
351     {
352       System.out.println("Error setting property: " + key + " " + obj + "\n" +
353                          ex);
354     }
355     return obj;
356   }
357
358   public static void saveProperties()
359   {
360     try
361     {
362       FileOutputStream out = new FileOutputStream(propertiesFile);
363       applicationProperties.store(out, "---JalviewX Properties File---");
364       out.close();
365     }
366     catch (Exception ex)
367     {
368       System.out.println("Error saving properties: " + ex);
369     }
370   }
371
372   /**
373    * internal vamsas class discovery state
374    */
375   private static int vamsasJarsArePresent = -1;
376   /**
377    * Searches for vamsas client classes on class path.
378    * @return true if vamsas client is present on classpath
379    */
380   public static boolean vamsasJarsPresent()
381   {
382     if (vamsasJarsArePresent == -1)
383     {
384       try
385       {
386         if (jalview.jbgui.GDesktop.class.getClassLoader().loadClass(
387             "uk.ac.vamsas.client.VorbaId") != null)
388         {
389           jalview.bin.Cache.log.debug(
390               "Found Vamsas Classes (uk.ac..vamsas.client.VorbaId can be loaded)");
391           vamsasJarsArePresent = 1;
392           Logger lvclient = Logger.getLogger("uk.ac.vamsas");
393           lvclient.setLevel(Level.toLevel(Cache.getDefault("logs.Vamsas.Level",
394               Level.INFO.toString())));
395
396           lvclient.addAppender(log.getAppender("JalviewLogger"));
397           // Tell the user that debug is enabled
398           lvclient.debug("Jalview Vamsas Client Debugging Output Follows.");
399         }
400       }
401       catch (Exception e)
402       {
403         vamsasJarsArePresent = 0;
404         jalview.bin.Cache.log.debug("Vamsas Classes are not present");
405       }
406     }
407     return (vamsasJarsArePresent > 0);
408   }
409   /**
410    * internal vamsas class discovery state
411    */
412   private static int groovyJarsArePresent = -1;
413   /**
414    * Searches for vamsas client classes on class path.
415    * @return true if vamsas client is present on classpath
416    */
417   public static boolean groovyJarsPresent()
418   {
419     if (groovyJarsArePresent == -1)
420     {
421       try
422       {
423         if (Cache.class.getClassLoader().loadClass(
424             "groovy.lang.GroovyObject") != null)
425         {
426           jalview.bin.Cache.log.debug(
427               "Found Groovy (groovy.lang.GroovyObject can be loaded)");
428           groovyJarsArePresent = 1;
429           Logger lgclient = Logger.getLogger("groovy");
430           lgclient.setLevel(Level.toLevel(Cache.getDefault("logs.Groovy.Level",
431               Level.INFO.toString())));
432
433           lgclient.addAppender(log.getAppender("JalviewLogger"));
434           // Tell the user that debug is enabled
435           lgclient.debug("Jalview Groovy Client Debugging Output Follows.");
436         }
437       }
438       catch (Exception e)
439       {
440         groovyJarsArePresent = 0;
441         jalview.bin.Cache.log.debug("Groovy Classes are not present");
442       }
443     }
444     return (groovyJarsArePresent > 0);
445   }
446
447 }