KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > Yasna > forum > PropertyManager


1 /**
2  * Copyright (C) 2001 Yasna.com. All rights reserved.
3  *
4  * ===================================================================
5  * The Apache Software License, Version 1.1
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  *
11  * 1. Redistributions of source code must retain the above copyright
12  * notice, this list of conditions and the following disclaimer.
13  *
14  * 2. Redistributions in binary form must reproduce the above copyright
15  * notice, this list of conditions and the following disclaimer in
16  * the documentation and/or other materials provided with the
17  * distribution.
18  *
19  * 3. The end-user documentation included with the redistribution,
20  * if any, must include the following acknowledgment:
21  * "This product includes software developed by
22  * Yasna.com (http://www.yasna.com)."
23  * Alternately, this acknowledgment may appear in the software itself,
24  * if and wherever such third-party acknowledgments normally appear.
25  *
26  * 4. The names "Yazd" and "Yasna.com" must not be used to
27  * endorse or promote products derived from this software without
28  * prior written permission. For written permission, please
29  * contact yazd@yasna.com.
30  *
31  * 5. Products derived from this software may not be called "Yazd",
32  * nor may "Yazd" appear in their name, without prior written
33  * permission of Yasna.com.
34  *
35  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
36  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
37  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
38  * DISCLAIMED. IN NO EVENT SHALL YASNA.COM OR
39  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
40  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
41  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
42  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
43  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
44  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
45  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
46  * SUCH DAMAGE.
47  * ====================================================================
48  *
49  * This software consists of voluntary contributions made by many
50  * individuals on behalf of Yasna.com. For more information
51  * on Yasna.com, please see <http://www.yasna.com>.
52  */

53
54 package com.Yasna.forum;
55
56 import com.Yasna.forum.database.DbConnectionManager;
57
58 import javax.naming.InitialContext JavaDoc;
59 import java.util.*;
60 import java.io.*;
61 import java.sql.ResultSet JavaDoc;
62 import java.sql.Connection JavaDoc;
63 import java.sql.PreparedStatement JavaDoc;
64 import java.sql.SQLException JavaDoc;
65
66 /**
67  * Manages properties for the entire Yazd system. Properties are merely
68  * pieces of information that need to be saved in between server restarts. The
69  * class also reports the version of Yazd.
70  * <p>
71  * At the moment, properties are stored in a Java Properties file. In a version
72  * of Yazd coming soon, the properties file format will move to XML. XML
73  * properties will allow hierarchical property structures which may mean the
74  * API of this class will have to change.
75  * <p>
76  * Yazd properties are only meant to be set and retrevied by core Yazd classes.
77  * Therefore, skin writers should probably ignore this class.
78  * <p>
79  * This class is implemented as a singleton since many classloaders seem to
80  * take issue with doing classpath resource loading from a static context.
81  */

82 public class PropertyManager {
83
84     /**
85      * The Major version number of Yazd. i.e. 1.x.x
86      */

87     private static final int MAJOR_VERSION = 3;
88
89     /**
90      * The Minor version number of Yazd. i.e. x.1.x.
91      */

92     private static final int MINOR_VERSION = 0;
93
94     /**
95      * The revision version number of Yazd. i.e. x.x.1.
96      */

97     private static final int REVISION_VERSION = 1;
98
99     private static PropertyManager manager = null;
100     private static Object JavaDoc managerLock = new Object JavaDoc();
101     private static String JavaDoc propsName = "/yazd.properties";
102     private static boolean loadFromDb = true;
103     private static final String JavaDoc LOAD_PROPERTIES="select name,propvalue from yazdProps";
104     private static final String JavaDoc DELETE_PROPERTIES="delete from yazdProps";
105     private static final String JavaDoc INSERT_PROPERTIES="insert into yazdProps(name,propvalue) values (?,?)";
106
107     /**
108      * Returns a Yazd property.
109      *
110      * @param name the name of the property to return.
111      * @return the property value specified by name.
112      */

113     public static String JavaDoc getProperty(String JavaDoc name) {
114         if (manager == null) {
115             synchronized(managerLock) {
116                 if (manager == null) {
117                     manager = new PropertyManager(propsName);
118                 }
119             }
120         }
121         return manager.getProp(name);
122     }
123     public static void setPath(String JavaDoc path){
124         if (manager == null) {
125             synchronized(managerLock) {
126                 if (manager == null) {
127                     manager = new PropertyManager(propsName);
128                 }
129             }
130         }
131         manager.setProp("path",path);
132     }
133     /**
134      * Sets a Yazd property. If the property doesn't already exists, a new
135      * one will be created.
136      *
137      * @param name the name of the property being set.
138      * @param value the value of the property being set.
139      */

140     public static void setProperty(String JavaDoc name, String JavaDoc value) {
141         if (manager == null) {
142             synchronized(managerLock) {
143                 if (manager == null) {
144                     manager = new PropertyManager(propsName);
145                 }
146             }
147         }
148         manager.setProp(name, value);
149     }
150
151     /**
152      * Deletes a Yazd property. If the property doesn't exist, the method
153      * does nothing.
154      *
155      * @param name the name of the property to delete.
156      */

157     public static void deleteProperty(String JavaDoc name) {
158         if (manager == null) {
159             synchronized(managerLock) {
160                 if (manager == null) {
161                     manager = new PropertyManager(propsName);
162                 }
163             }
164         }
165         manager.deleteProp(name);
166     }
167
168     /**
169      * Returns the names of the Yazd properties.
170      *
171      * @return an Enumeration of the Yazd property names.
172      */

173     public static Enumeration propertyNames() {
174         if (manager == null) {
175             synchronized(managerLock) {
176                 if (manager == null) {
177                     manager = new PropertyManager(propsName);
178                 }
179             }
180         }
181         return manager.propNames();
182     }
183
184     /**
185      * Returns true if the properties are readable. This method is mainly
186      * valuable at setup time to ensure that the properties file is setup
187      * correctly.
188      */

189     public static boolean propertyFileIsReadable() {
190         if (manager == null) {
191             synchronized(managerLock) {
192                 if (manager == null) {
193                     manager = new PropertyManager(propsName);
194                 }
195             }
196         }
197         return manager.propFileIsReadable();
198     }
199
200     /**
201      * Returns true if the properties are writable. This method is mainly
202      * valuable at setup time to ensure that the properties file is setup
203      * correctly.
204      */

205     public static boolean propertyFileIsWritable() {
206         if (manager == null) {
207             synchronized(managerLock) {
208                 if (manager == null) {
209                     manager = new PropertyManager(propsName);
210                 }
211             }
212         }
213         return manager.propFileIsWritable();
214     }
215
216     /**
217      * Returns true if the yazd.properties file exists where the path property
218      * purports that it does.
219      */

220     public static boolean propertyFileExists() {
221         if (manager == null) {
222             synchronized(managerLock) {
223                 if (manager == null) {
224                     manager = new PropertyManager(propsName);
225                 }
226             }
227         }
228         return manager.propFileExists();
229     }
230
231     /**
232      * Returns the version number of Yazd as a String. i.e. -- major.minor.revision
233      */

234     public static String JavaDoc getYazdVersion() {
235         return MAJOR_VERSION + "." + MINOR_VERSION + "." + REVISION_VERSION;
236     }
237
238     /**
239      * Returns the major version number of Yazd. i.e. -- 1.x.x
240      */

241     public static int getYazdVersionMajor() {
242         return MAJOR_VERSION;
243     }
244
245     /**
246      * Returns the minor version number of Yazd. i.e. -- x.1.x
247      */

248     public static int getYazdVersionMinor() {
249         return MINOR_VERSION;
250     }
251
252     /**
253      * Returns the revision version number of Yazd. i.e. -- x.x.1
254      */

255     public static int getYazdVersionRevision() {
256         return REVISION_VERSION;
257     }
258
259     private Properties properties = null;
260     private Object JavaDoc propertiesLock = new Object JavaDoc();
261     private String JavaDoc resourceURI;
262
263     /**
264      * Creates a new PropertyManager. Singleton access only.
265      */

266     private PropertyManager(String JavaDoc resourceURI) {
267         this.resourceURI = resourceURI;
268     }
269
270     /**
271      * Gets a Yazd property. Yazd properties are stored in yazd.properties.
272      * The properties file should be accesible from the classpath. Additionally,
273      * it should have a path field that gives the full path to where the
274      * file is located. Getting properties is a fast operation.
275      *
276      * @param name the name of the property to get.
277      * @return the property specified by name.
278      */

279     protected String JavaDoc getProp(String JavaDoc name) {
280         //If properties aren't loaded yet. We also need to make this thread
281
//safe, so synchronize...
282
if (properties == null) {
283             synchronized(propertiesLock) {
284                 //Need an additional check
285
if (properties == null) {
286                     loadProps();
287                 }
288             }
289         }
290         String JavaDoc property = properties.getProperty(name);
291         if (property == null) {
292             return null;
293         }
294         else {
295             return property.trim();
296         }
297     }
298
299     /**
300      * Sets a Yazd property. Because the properties must be saved to disk
301      * every time a property is set, property setting is relatively slow.
302      */

303     protected void setProp(String JavaDoc name, String JavaDoc value) {
304         //Only one thread should be writing to the file system at once.
305
synchronized (propertiesLock) {
306             //Create the properties object if necessary.
307
if (properties == null) {
308                 loadProps();
309             }
310             properties.setProperty(name, value);
311             saveProps();
312         }
313     }
314
315     protected void deleteProp(String JavaDoc name) {
316         //Only one thread should be writing to the file system at once.
317
synchronized (propertiesLock) {
318             //Create the properties object if necessary.
319
if (properties == null) {
320                 loadProps();
321             }
322             properties.remove(name);
323             saveProps();
324         }
325     }
326
327     protected Enumeration propNames() {
328         //If properties aren't loaded yet. We also need to make this thread
329
//safe, so synchronize...
330
if (properties == null) {
331             synchronized(propertiesLock) {
332                 //Need an additional check
333
if (properties == null) {
334                     loadProps();
335                 }
336             }
337         }
338         return properties.propertyNames();
339     }
340
341     /**
342      * Loads Yazd properties from the disk.
343      */

344     private void loadProps() {
345         switch(getLoadSource()){
346             case 2:
347                 System.err.println("Loading Properties from database");
348                 loadPropsFromDb();
349                 break;
350             default:
351                 System.err.println("Loading Properties from yolanda.properties");
352                 loadPropsFromFile();
353         }
354
355     }
356     private void loadPropsFromFile() {
357         properties = new Properties();
358         InputStream in = null;
359         try {
360             in = getClass().getResourceAsStream(resourceURI);
361             properties.load(in);
362         }
363         catch (Exception JavaDoc e) {
364             System.err.println("Error reading Yolanda properties in PropertyManager.loadProps() " + e);
365             e.printStackTrace();
366         }
367         finally {
368             try {
369                 in.close();
370             } catch (Exception JavaDoc e) { }
371         }
372     }
373     private void loadPropsFromDb() {
374         properties = new Properties();
375         Connection JavaDoc con = null;
376         PreparedStatement JavaDoc pstmt = null;
377         try {
378             con = DbConnectionManager.getConnection();
379             pstmt = con.prepareStatement(LOAD_PROPERTIES);
380             ResultSet JavaDoc rs = pstmt.executeQuery();
381             while(rs.next()) {
382                 String JavaDoc name = rs.getString("name");
383                 String JavaDoc value = rs.getString("propvalue");
384                 properties.put(name, value);
385             }
386         }
387         catch( Exception JavaDoc e ) {
388             loadFromDb=false;
389             System.err.println("Error in Property Manager:loadProperties():" + e.getMessage());
390         }
391         finally {
392             try { pstmt.close(); }
393             catch (Exception JavaDoc e) { e.printStackTrace(); }
394             try { con.close(); }
395             catch (Exception JavaDoc e) { e.printStackTrace(); }
396         }
397     }
398
399
400
401     /**
402      * Saves Yazd properties to disk.
403      */

404     private void saveProps() {
405         //Now, save the properties to disk. In order for this to work, the user
406
//needs to have set the path field in the properties file. Trim
407
//the String to make sure there are no extra spaces.
408
if(propFileIsWritable()){
409             String JavaDoc path = properties.getProperty("path").trim();
410             OutputStream out = null;
411             try {
412                 out = new FileOutputStream(path);
413                 properties.store(out, "yazd.properties -- " + (new java.util.Date JavaDoc()));
414             }
415             catch (Exception JavaDoc ioe) {
416                 System.err.println("There was an error writing yazd.properties to " + path + ". " +
417                         "Ensure that the path exists and that the Yazd process has permission " +
418                         "to write to it -- " + ioe);
419                 ioe.printStackTrace();
420             }
421             finally {
422                 try {
423                     out.close();
424                 } catch (Exception JavaDoc e) { }
425             }
426         }
427         // If everything is fine and working, we will store a copy of the properties in the database.
428
// This will be useful if the user wishes to change from using the file properties to a database properties setting.
429
if(properties.getProperty("setup")!=null && properties.getProperty("setup").equals("true")){
430             Connection JavaDoc con = null;
431             PreparedStatement JavaDoc pstmt = null;
432             try {
433                 con = DbConnectionManager.getConnection();
434                 //Delete all old values.
435
pstmt = con.prepareStatement(DELETE_PROPERTIES);
436                 pstmt.execute();
437                 pstmt.close();
438                 //Now insert new values.
439
pstmt = con.prepareStatement(INSERT_PROPERTIES);
440                 Enumeration enume = properties.keys();
441                 while (enume.hasMoreElements()) {
442                     String JavaDoc name = (String JavaDoc)enume.nextElement();
443                     String JavaDoc value = (String JavaDoc)properties.get(name);
444                     pstmt.setString(1, name);
445                     pstmt.setString(2, value);
446                     pstmt.executeUpdate();
447                 }
448             }
449             catch( SQLException JavaDoc sqle ) {
450                 System.err.println(sqle);
451             }
452             finally {
453                 try { pstmt.close(); }
454                 catch (Exception JavaDoc e) { e.printStackTrace(); }
455                 try { con.close(); }
456                 catch (Exception JavaDoc e) { e.printStackTrace(); }
457             }
458
459         }
460     }
461     /**
462      * this method checks to see if the application is already setup or not.
463      * If the application is setup, then you can load the properties from database.
464      * Otherwise it has to be determined how the application is being setup. Are we using
465      * the default connection pooler or a different db connection pooler.
466      * @return value of the source
467      */

468
469     private int getLoadSource(){
470         int loadsource=1; //assume that application is not setup.
471
// check to see if we are loading from the database using a context provider
472
try{
473             InitialContext JavaDoc ctxt = new InitialContext JavaDoc ();
474             ctxt.lookup(DbConnectionManager.CONTEXT_JDBC_NAME);
475             loadsource=2;
476         }catch(Exception JavaDoc e){
477
478         }
479         return loadsource;
480
481     }
482
483     /**
484      * Returns true if the properties are readable. This method is mainly
485      * valuable at setup time to ensure that the properties file is setup
486      * correctly.
487      */

488     public boolean propFileIsReadable() {
489         try {
490             InputStream in = getClass().getResourceAsStream(resourceURI);
491             return true;
492         }
493         catch (Exception JavaDoc e) {
494             return false;
495         }
496     }
497
498     /**
499      * Returns true if the yazd.properties file exists where the path property
500      * purports that it does.
501      */

502     public boolean propFileExists() {
503         String JavaDoc path = getProp("path");
504         if( path == null ) {
505             return false;
506         }
507         File file = new File(path);
508         if (file.isFile()) {
509             return true;
510         }
511         else {
512             return false;
513         }
514     }
515
516     /**
517      * Returns true if the properties are writable. This method is mainly
518      * valuable at setup time to ensure that the properties file is setup
519      * correctly.
520      */

521     public boolean propFileIsWritable() {
522         String JavaDoc path = getProp("path");
523         File file = new File(path);
524         if (file.isFile()) {
525             //See if we can write to the file
526
if (file.canWrite()) {
527                 return true;
528             }
529             else {
530                 return false;
531             }
532         }
533         else {
534             return false;
535         }
536     }
537 }
538
Popular Tags