FileStorage.java
上传用户:huihesys
上传日期:2007-01-04
资源大小:3877k
文件大小:13k
源码类别:

WEB邮件程序

开发平台:

C/C++

  1. /* CVS ID: $Id: FileStorage.java,v 1.4 2000/04/06 08:02:02 wastl Exp $ */
  2. package net.wastl.webmail.storage;
  3. import java.io.*;
  4. import java.text.*;
  5. import java.util.*;
  6. import java.util.zip.*;
  7. import net.wastl.webmail.server.*;
  8. import net.wastl.webmail.config.*;
  9. import net.wastl.webmail.misc.*;
  10. import net.wastl.webmail.xml.*;
  11. import org.apache.xalan.xslt.*;
  12. /**
  13.  * FileStorage.java
  14.  *
  15.  * Created: Jan 2000
  16.  *
  17.  * Copyright (C) 2000 Sebastian Schaffert
  18.  * 
  19.  * This program is free software; you can redistribute it and/or
  20.  * modify it under the terms of the GNU General Public License
  21.  * as published by the Free Software Foundation; either version 2
  22.  * of the License, or (at your option) any later version.
  23.  * 
  24.  * This program is distributed in the hope that it will be useful,
  25.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  26.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  27.  * GNU General Public License for more details.
  28.  * 
  29.  * You should have received a copy of the GNU General Public License
  30.  * along with this program; if not, write to the Free Software
  31.  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  32.  */
  33. /**
  34.  * This is the FileStorage class is common to all other storage classes in WebMail
  35.  * It provides means of getting and storing data in ZIPFiles and ResourceBundles,
  36.  * for example HTML-templates, binary files and MIME-types
  37.  *
  38.  * @see Storage
  39.  * @author Sebastian Schaffert
  40.  * @versin $Revision: 1.4 $
  41.  */
  42. public abstract class FileStorage extends Storage implements ConfigurationListener {
  43.     protected Hashtable resources;
  44.     
  45.     protected Hashtable file_resources;
  46.     protected Hashtable stylesheet_cache;
  47.     protected Hashtable binary_cache;
  48.     /** Stores Locale/ExpireableCache pairs */
  49.     //protected Hashtable file_cache;;
  50.     protected Authenticator auth;
  51.     
  52.     protected static Hashtable mime_types;
  53.     protected Logger logger;
  54.     protected static DateFormat df=null;
  55.     private boolean init_complete=false;
  56.     
  57.     protected int file_cache_size=40;
  58.     /**
  59.      * Initialize SimpleStorage.
  60.      * Fetch Configuration Information etc.
  61.      */
  62.     public FileStorage(WebMailServer parent) {
  63. super(parent);
  64. initConfig();
  65. cs.addConfigurationListener("AUTH",this);
  66. cs.configRegisterStringKey(this,"MIME TYPES",parent.getProperty("webmail.lib.path")+
  67.    System.getProperty("file.separator")+"mime.types",
  68.    "File with mime type information.");
  69. resources=new Hashtable();
  70. file_resources=new Hashtable();
  71. initCache();
  72. initLog();
  73. // Now included in configuration:
  74. //  initVirtualDomains();
  75. initMIME();
  76. initAuth();
  77. initLanguages();
  78. init_complete=true;
  79.     }
  80.     /**
  81.      * initialize XMLSystemData sysdata
  82.      */
  83.     protected abstract void initConfig();
  84.     protected void initCache() {
  85. // Initialize the file cache
  86. cs.configRegisterIntegerKey(this,"CACHE SIZE FILE","40","Size for the file system cache for every locale");
  87. try {
  88.     file_cache_size=Integer.parseInt("CACHE SIZE FILE");
  89. } catch(NumberFormatException e) {}
  90. //  if(file_cache==null) {
  91. //      file_cache=new Hashtable(5);
  92. //  }
  93. //  Enumeration enum=file_cache.keys();
  94. //  while(enum.hasMoreElements()) {
  95. //      ExpireableCache ec=(ExpireableCache)file_cache.get(enum.nextElement());
  96. //      ec.setCapacity(file_cache_size);
  97. //  }
  98. // Now the same for the stylesheet cache
  99. if(stylesheet_cache == null) {
  100.     stylesheet_cache = new Hashtable(10);
  101. }
  102. Enumeration enum2=stylesheet_cache.keys();
  103. while(enum2.hasMoreElements()) {
  104.     ExpireableCache ec=(ExpireableCache)stylesheet_cache.get(enum2.nextElement());
  105.     ec.setCapacity(file_cache_size);
  106. }
  107. // And for binary files
  108. if(binary_cache == null) {
  109.     binary_cache = new Hashtable(10);
  110. }
  111. Enumeration enum3=binary_cache.keys();
  112. while(enum3.hasMoreElements()) {
  113.     ExpireableCache ec=(ExpireableCache)binary_cache.get(enum3.nextElement());
  114.     ec.setCapacity(file_cache_size);
  115. }
  116.     }
  117.     protected void initLog() {
  118. logger=new Logger(parent,this);
  119.     }
  120.     protected void initAuth() {
  121. System.err.print("  * Authenticator ... ");
  122. Authenticator a=parent.getAuthenticatorHandler().getAuthenticator(getConfig("AUTH"));
  123. if(a!=null) {
  124.     // IMAP level authentication
  125.     auth=a;
  126.     auth.init(this);
  127.     System.err.println("ok. Using "+auth.getClass().getName()+" (v"+auth.getVersion()+") for authentication.");
  128. } else {
  129.     System.err.println("error. Could not initalize any authenticator. Users will not be able to log on.");
  130.     auth=null;
  131. }
  132.     }
  133.     
  134.     protected void initMIME() {
  135. System.err.print("  * MIME types ... ");
  136. if(getConfig("mime types") != null) {
  137.     try {
  138. File f=new File(getConfig("mime types"));
  139. if(f.exists() && f.canRead()) {
  140.     mime_types=new Hashtable();
  141.     BufferedReader in=new BufferedReader(new InputStreamReader(new FileInputStream(f)));
  142.     String line=in.readLine();
  143.     while(line != null) {
  144. if(!line.startsWith("#")) {
  145.     StringTokenizer tok=new StringTokenizer(line);
  146.     if(tok.hasMoreTokens()) {
  147. String type=tok.nextToken();
  148. while(tok.hasMoreTokens()) {
  149.     String key=tok.nextToken();
  150.     mime_types.put(key,type);
  151.     //System.err.println(key+" -> "+type);
  152. }
  153.     }
  154. }
  155. line=in.readLine();
  156.     }
  157.     in.close();
  158.     System.err.println(" loaded from "+getConfig("mime types")+".");
  159. } else {
  160.     System.err.println(" could not find "+getConfig("mime types")+". Will use standard MIME types.");
  161. }
  162.     } catch(IOException ex) {
  163. System.err.println(" could not find "+getConfig("mime types")+". Will use standard MIME types.");
  164.     }
  165. } else {
  166.     System.err.println(" not configured. Will use standard MIME types.");
  167. }
  168.     }
  169.     
  170.     protected void initLanguages() {
  171. System.err.print("  * Available languages ... ");
  172. File f=new File(parent.getProperty("webmail.template.path")+System.getProperty("file.separator"));
  173. String[] flist=f.list(new FFilter());
  174. Locale[] available1=Collator.getAvailableLocales();
  175. // Do this manually, as it is not JDK 1.1 compatible ...
  176. //Vector available=new Vector(Arrays.asList(available1));
  177. Vector available=new Vector(available1.length);
  178. for(int i=0; i<available1.length; i++) {
  179.     available.addElement(available1[i]);
  180. }
  181. String s="";
  182. int count=0;
  183. for(int i=0;i<flist.length;i++) {
  184.     String cur_lang=flist[i];
  185.     Locale loc=new Locale(cur_lang,"","");
  186.     Enumeration enum=available.elements();
  187.     boolean added=false;
  188.     while(enum.hasMoreElements()) {
  189. Locale l=(Locale)enum.nextElement();
  190. if(l.getLanguage().equals(loc.getLanguage())) {
  191.     s+=l.toString()+" ";
  192.     count++;
  193.     added=true;
  194. }
  195.     }
  196.     if(!added) {
  197. s+=loc.toString()+" ";
  198. count++;
  199.     }
  200. }
  201. System.err.println(count+" languages initialized.");
  202. cs.configRegisterStringKey(this,"LANGUAGES",s,"Languages available in WebMail");
  203. setConfig("LANGUAGES",s);
  204.     }
  205.     /**
  206.      * Get the String for key and the specified locale.
  207.      * @param key Identifier for the String
  208.      * @param locale locale of the String to fetch
  209.      */
  210.     public String getStringResource(String key, Locale locale) {
  211. if(resources.get(locale.getLanguage()) != null) {
  212.     return ((ResourceBundle)resources.get(locale.getLanguage())).getString(key);
  213. } else {
  214.     try {
  215. ResourceBundle rc=XMLResourceBundle.getBundle("resources",locale,null);
  216. resources.put(locale.getLanguage(),rc);
  217. return rc.getString(key);
  218.     } catch(Exception e) {
  219. e.printStackTrace();
  220. return "";
  221.     }
  222. }
  223.     }
  224.     /**
  225.      * Return the requested Stylesheet, precompiled and fitting to the locale and theme
  226.      */
  227.     public StylesheetRoot getStylesheet(String name, Locale locale, String theme) throws StylesheetNotFoundException {
  228. String key = locale.getLanguage()+"/"+theme;
  229. AttributedExpireableCache cache=(AttributedExpireableCache)stylesheet_cache.get(key);
  230. if(cache == null) {
  231.     cache=new AttributedExpireableCache(file_cache_size);
  232.     stylesheet_cache.put(key,cache);
  233. }
  234. StylesheetRoot stylesheet=null;
  235.     
  236. String basepath=getBasePath(locale,theme);
  237. File f=new File(basepath+name);
  238. if(!f.exists()) {
  239.     throw new StylesheetNotFoundException("The requested stylesheet "+name+" could not be found.");
  240. }
  241. if(cache.get(name) != null && ((Long)cache.getAttributes(name)).longValue() >= f.lastModified()) {
  242.     // Keep statistics :-)
  243.     cache.hit();
  244.     return (StylesheetRoot)cache.get(name);
  245. } else {
  246.     try {
  247. XSLTInputSource msg_xsl=new XSLTInputSource(basepath+name);
  248. XSLTProcessor processor=XSLTProcessorFactory.getProcessorUsingLiaisonName("org.apache.xalan.xpath.xdom.XercesLiaison");
  249. processor.setDiagnosticsOutput(System.err);
  250. stylesheet=processor.processStylesheet(msg_xsl);
  251. cache.put(name,stylesheet, new Long(f.lastModified()));
  252. cache.miss();
  253.     } catch(Exception ex) { 
  254. System.err.println("Error while compiling stylesheet "+name+", language="+locale.getLanguage()+", theme="+theme+".");
  255. ex.printStackTrace(); 
  256.     }
  257.     return stylesheet;
  258. }
  259.     }
  260.     /**
  261.      * Get a binary file for the specified locale.
  262.      * @param key Identifier for the String
  263.      * @param locale locale of the String to fetch
  264.      */
  265.     public synchronized byte[] getBinaryFile(String name, Locale locale, String theme) throws BinaryNotFoundException {
  266. String key = locale.getLanguage()+"/"+theme;
  267. AttributedExpireableCache cache=(AttributedExpireableCache)binary_cache.get(key);
  268. if(cache == null) {
  269.     cache=new AttributedExpireableCache(file_cache_size);
  270.     binary_cache.put(key,cache);
  271. }
  272. ByteStore bs=null;
  273.       
  274. String basepath=getBasePath(locale,theme);
  275. File f=new File(basepath+name);
  276. if(!f.exists()) {
  277.     throw new BinaryNotFoundException("The file "+name+" could not be found!");
  278. }
  279. if(cache.get(name) != null && ((Long)cache.getAttributes(name)).longValue() >= f.lastModified()) {
  280.     // Keep statistics :-)
  281.     cache.hit();     
  282.     return ((ByteStore)cache.get(name)).getBytes();
  283. } else {     
  284.     try {
  285. bs=ByteStore.getBinaryFromIS(new FileInputStream(f),(int)f.length());
  286.     } catch(IOException ex) { ex.printStackTrace(); }
  287.     cache.put(name,bs,new Long(f.lastModified()));
  288.     
  289.     if(bs != null) {
  290. return bs.getBytes();
  291.     } else {
  292. return new byte[1];
  293.     }
  294. }
  295.     }
  296.     public Authenticator getAuthenticator() {
  297. return auth;
  298.     }
  299.     /**
  300.      * Send a message to the logging facility.
  301.      * @param level severity level of the message
  302.      * @param message the message
  303.      */
  304.     public synchronized void log(int level, String message) {
  305. if(logger != null) {
  306.     logger.log(level,message);
  307. } else {
  308.     System.err.println("LOG("+level+"): "+message);
  309. }
  310.     }   
  311.     protected String formatDate(long date) {
  312. if(df==null) {
  313.     TimeZone tz=TimeZone.getDefault();
  314.     df=DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.DEFAULT, Locale.getDefault());
  315.     df.setTimeZone(tz);
  316. }
  317. String now=df.format(new Date(date));
  318. return now;
  319.     }
  320.     public void shutdown() {
  321. logger.shutdown();
  322.     }
  323.     public String getMimeType(String name) {
  324. if(mime_types == null) {
  325.     return super.getMimeType(name);
  326. } else {
  327.     if(name != null) {
  328. String type="application/unknown";
  329. Enumeration enum=mime_types.keys();
  330. while(enum.hasMoreElements()) {
  331.     String s=(String)enum.nextElement();
  332.     if(name.toLowerCase().endsWith(s)) {
  333. type= (String)mime_types.get(s);
  334.     }
  335. }
  336. return type;
  337.     } else {
  338. return "UNKNOWN";
  339.     }
  340. }
  341.     }
  342.     public void notifyConfigurationChange(String key) {
  343. log(Storage.LOG_DEBUG,"FileStorage: Configuration change notify for key "+key+".");
  344. System.err.println("- Configuration changed: ");
  345. if(key.toUpperCase().startsWith("AUTH")) {
  346.     initAuth();
  347. } else if(key.toUpperCase().startsWith("MIME")) {
  348.     initMIME();
  349. }
  350.     }
  351.     public String toString() {
  352. String s="";
  353. Enumeration enum=stylesheet_cache.keys();
  354. while(enum.hasMoreElements()) {
  355.     String name=(String)enum.nextElement();
  356.     ExpireableCache cache=(ExpireableCache)stylesheet_cache.get(name);
  357.     s+=" - stylesheet cache for "+name+": Capacity "+cache.getCapacity()+", Usage "+cache.getUsage();
  358.     s+=", "+cache.getHits()+" hits, "+cache.getMisses()+" missesn";
  359. }
  360. enum=binary_cache.keys();
  361. while(enum.hasMoreElements()) {
  362.     String name=(String)enum.nextElement();
  363.     ExpireableCache cache=(ExpireableCache)binary_cache.get(name);
  364.     s+=" - binary cache for "+name+": Capacity "+cache.getCapacity()+", Usage "+cache.getUsage();
  365.     s+=", "+cache.getHits()+" hits, "+cache.getMisses()+" missesn";
  366. }
  367. return s;
  368.     }
  369.     /**
  370.      * A filter to find WebMail language packs.
  371.      */
  372.     class FFilter implements FilenameFilter {
  373. FFilter() {
  374. }
  375. public boolean accept(File f, String s) {
  376.     if(f.isDirectory() && s.equals(s.toLowerCase()) && (s.length()==2 || s.equals("default"))) {
  377. //  System.err.println(s+" is a directory");
  378. return true;
  379.     } else {
  380. return false;
  381.     }
  382. }
  383.     }
  384. }