KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > sync4j > server > config > Configuration


1 /**
2  * Copyright (C) 2003-2005 Funambol
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 2 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17  */

18 package sync4j.server.config;
19
20 import java.io.IOException JavaDoc;
21 import java.io.File JavaDoc;
22
23 import java.net.NetworkInterface JavaDoc;
24 import java.util.Enumeration JavaDoc;
25 import java.net.InetAddress JavaDoc;
26 import java.net.*;
27
28 import java.util.Iterator JavaDoc;
29 import java.util.logging.ConsoleHandler JavaDoc;
30 import java.util.logging.FileHandler JavaDoc;
31 import java.util.logging.Handler JavaDoc;
32 import java.util.logging.Level JavaDoc;
33 import java.util.logging.Logger JavaDoc;
34 import java.util.logging.LogManager JavaDoc;
35
36 import sync4j.framework.config.*;
37 import sync4j.framework.engine.SyncStrategy;
38 import sync4j.framework.engine.pipeline.PipelineManager;
39 import sync4j.framework.security.Officer;
40 import sync4j.framework.server.session.SessionHandler;
41 import sync4j.framework.server.store.PersistentStore;
42 import sync4j.framework.tools.beans.BeanFactory;
43 import sync4j.framework.tools.beans.BeanException;
44
45 import sync4j.server.admin.UserManager;
46
47 /**
48  * Incapsulates all the configuration information about the Sync4j Engine.
49  * Configuration parameters are stored as properties in a Map structure. The
50  * key is the name of the parameter and it is strucured in dotted separated
51  * namespaces. The value of the parameter is the value of the key and can be of
52  * any type. Accessor methods are provided to get the value of the parameter in
53  * a particular type (such as String, int, double, boolean, ...).<br>
54  * Access to getXXX() and setXXX() methods are synchronized.
55  * <p>
56  * This class follows the Singleton pattern, therefore it cannot be directly
57  * instantiated; an internal instance is created just once and returned at any
58  * getConfiguration() call.
59  *
60  * @author Stefano Fornari @ funambol
61  *
62  * @version $Id: Configuration.java,v 1.10 2005/06/04 16:58:15 nichele Exp $
63  */

64 public class Configuration
65 implements java.io.Serializable JavaDoc, ConfigurationConstants {
66
67     // ------------------------------------------------------------ Private data
68

69     /**
70      * The server configuration
71      */

72     private ServerConfiguration serverConfig;
73
74     private static Configuration singleton;
75     private transient ClassLoader JavaDoc classLoader = null;
76
77     //
78
// In order to have a logger completely independent by any configuration,
79
// we use a standard anounymous logger. This will be used for error
80
// notification only.
81
//
82
private static transient Logger JavaDoc log = Logger.getAnonymousLogger();
83
84     // -------------------------------------------------------------- properties
85

86     /** Getter for property classLoader.
87      * @return Value of property classLoader.
88      *
89      */

90     public ClassLoader JavaDoc getClassLoader() {
91         return classLoader;
92     }
93
94     /** Setter for property classLoader.
95      * @param classLoader New value of property classLoader.
96      *
97      */

98     public void setClassLoader(ClassLoader JavaDoc classLoader) {
99         this.classLoader = classLoader;
100     }
101
102     // ------------------------------------------------------------ Constructors
103

104     /**
105      * This is disabled for normal use since this class is a singleton.
106      */

107     protected Configuration() {
108     }
109
110     /**
111      * Returns the singleton instance. It created the instance the first time it
112      * is called.
113      *
114      * @return the singleton instance.
115      */

116     public static synchronized Configuration getConfiguration() {
117         if (singleton == null) {
118             singleton = new Configuration();
119             try {
120                 URL configPath = ConfigTools.fixURL(getConfigPath());
121                 ConfigClassLoader cl = new ConfigClassLoader(
122                                            new URL[] { configPath },
123                                            Configuration.class.getClassLoader()
124
125                                        );
126                 singleton.serverConfig =
127                     (ServerConfiguration)ConfigTools.getBeanInstance(cl, BEAN_SERVER_CONFIGURATION);
128
129                 singleton.setClassLoader(cl);
130
131                 singleton.setLoggingConfiguration();
132
133                 singleton.setServerURI();
134
135             } catch (Exception JavaDoc e) {
136                 if (log.isLoggable(Level.SEVERE)) {
137                     log.severe("Fatal error creating the configuration object: " + e.getMessage());
138                 }
139                 log.throwing(Configuration.class.getName(), "getConfiguration", e);
140
141                 //
142
// In case of error we just create an empty instance
143
//
144
singleton = new Configuration();
145             }
146         }
147         return singleton;
148     }
149
150     // ---------------------------------------------------------- Public methods
151

152     /**
153      * Getter for property serverConfig.
154      * @return Value of property serverConfig.
155      */

156     public ServerConfiguration getServerConfig() {
157         return serverConfig;
158     }
159
160     /**
161      * Load the server configuration
162      */

163     public void loadServerConfig() {
164         //
165
// In order to load the server configuration, we call the static
166
// synchronized getConfiguration method after we have set the singleton object
167
// to null. So, the getConfiguration method reload the server configuration bean
168
// and re-set all the properties depends on it
169
//
170
singleton = null;
171         getConfiguration();
172     }
173
174     /**
175      * Creates and returns a new SyncStrategy instance from the configured
176      * <i>serverConfig.getEngineConfiguration().strategy</i> property
177      *
178      * @return the newly created instance
179      */

180     public SyncStrategy getStrategy() {
181         try {
182             return (SyncStrategy)ConfigTools.getBeanInstance(
183                 classLoader,
184                 serverConfig.getEngineConfiguration().getStrategy()
185             );
186         } catch (Exception JavaDoc e) {
187             if (log.isLoggable(Level.SEVERE)) {
188                 log.severe("Error creating the SyncStrategy object: " + e.getMessage());
189             }
190             log.throwing(getClass().getName(), "getStartegy", e);
191         }
192
193         return null;
194     }
195
196     /**
197      * Creates and returns a new PersistentStore instance from the configured
198      * <i>serverConfig.getEngineConfiguration().store</i> property
199      *
200      * @return the newly created instance
201      */

202     public PersistentStore getStore() {
203         try {
204             return (PersistentStore)ConfigTools.getBeanInstance(
205                 classLoader,
206                 serverConfig.getEngineConfiguration().getStore()
207             );
208         } catch (Exception JavaDoc e) {
209             if (log.isLoggable(Level.SEVERE)) {
210                 log.severe("Error creating the PersistentStore object: " + e.getMessage());
211             }
212             log.throwing(getClass().getName(), "getStore", e);
213         }
214
215         return null;
216     }
217
218     /**
219      * Creates and returns a new Officer instance from the configured
220      * <i>serverConfig.getEngineConfiguration().getOfficer</i> property
221      *
222      * @return the newly created instance
223      */

224     public Officer getOfficer() {
225         try {
226             return (Officer)ConfigTools.getBeanInstance(
227                 classLoader,
228                 serverConfig.getEngineConfiguration().getOfficer()
229             );
230         } catch (Exception JavaDoc e) {
231             if (log.isLoggable(Level.SEVERE)) {
232                 log.severe("Error creating the SecurityOfficer object: " + e.getMessage());
233             }
234             log.throwing(getClass().getName(), "getOfficer", e);
235         }
236
237         return null;
238     }
239
240
241     /**
242      * Creates and returns a new SessionHandler instance from the configured
243      * <i>serverConfig.getEngineConfiguration().sessionHandler</i> property
244      *
245      * @return the newly created instance
246      */

247     public SessionHandler getSessionHandler() {
248         try {
249             return (SessionHandler)ConfigTools.getBeanInstance(
250                 classLoader,
251                 serverConfig.getEngineConfiguration().getSessionHandler()
252             );
253         } catch (Exception JavaDoc e) {
254             if (log.isLoggable(Level.SEVERE)) {
255                 log.severe("Error creating the SessionHandler object: " + e.getMessage());
256             }
257             log.throwing(getClass().getName(), "getSessionHandler", e);
258         }
259
260         return null;
261     }
262
263     /**
264      * Creates and returns a new PipelineManager instance from the configured
265      * <i>serverConfig.getEngineConfiguration().pipelineManager</i> property
266      *
267      * @return the newly created instance
268      */

269     public PipelineManager getPipelineManager() {
270         try {
271             return (PipelineManager)ConfigTools.getBeanInstance(
272                 classLoader,
273                 serverConfig.getEngineConfiguration().getPipelineManager()
274             );
275         } catch (Exception JavaDoc e) {
276             if (log.isLoggable(Level.SEVERE)) {
277                 log.severe("Error creating the PipelineManager object: " + e.getMessage());
278             }
279             log.throwing(getClass().getName(), "getPipelineManager", e);
280         }
281
282         return null;
283     }
284
285     /**
286      * Creates and returns a new UserManager instance from the configured
287      * <i>serverConfig.getEngineConfiguration().userManager</i> property
288      *
289      * @return the newly created instance
290      */

291     public UserManager getUserManager() {
292         try {
293             return (UserManager)ConfigTools.getBeanInstance(
294                 classLoader,
295                 serverConfig.getEngineConfiguration().getUserManager()
296             );
297         } catch (Exception JavaDoc e) {
298             if (log.isLoggable(Level.SEVERE)) {
299                 log.severe("Error creating the UserManager object: " + e.getMessage());
300             }
301             log.throwing(getClass().getName(), "getUserManager", e);
302         }
303
304         return null;
305     }
306
307     /**
308      * Creates and returns a new Logging instance from the configured
309      * <i>serverConfig.getEngineConfiguration().logging</i> property
310      *
311      * @return the newly created instance
312      */

313     public LoggingConfiguration getLoggingConfiguration() {
314         try {
315             return (LoggingConfiguration)ConfigTools.getBeanInstance(
316                 classLoader,
317                 serverConfig.getEngineConfiguration().getLoggingConfiguration()
318             );
319         } catch (Exception JavaDoc e) {
320             if (log.isLoggable(Level.SEVERE)) {
321                 log.severe("Error creating the LoggingConfiguration object: " + e.getMessage());
322             }
323             log.throwing(getClass().getName(), "getLoggingConfiguration", e);
324         }
325         return null;
326     }
327
328     /**
329      * Configures the logging system accordingly to the
330      * sync4j/server/logging/Logging.xml server bean.
331      *
332      * @throws IOException in case of errors setting up file handlers
333      *
334      */

335     public void setLoggingConfiguration() throws IOException JavaDoc {
336
337         //
338
// First of all reinitialize logging
339
//
340
LogManager JavaDoc lm = LogManager.getLogManager();
341         lm.reset();
342         lm.readConfiguration();
343
344         //
345
// Now we can reconfigure Sync4j logging
346
//
347
Logger JavaDoc l;
348         LoggerConfiguration conf;
349         LoggingConfiguration lc = getLoggingConfiguration();
350
351         Handler JavaDoc h;
352         Iterator JavaDoc i = lc.getLoggers().iterator();
353         while(i.hasNext()) {
354
355             conf = (LoggerConfiguration)i.next();
356
357             //
358
// If this logger inherits from its parent, just skip logger
359
// configuration.
360
//
361
if (conf.isInherit()) {
362                 continue;
363             }
364
365             l = Logger.getLogger(conf.getName());
366
367             //
368
// first remove all old handlers
369
//
370
Handler JavaDoc[] handlers = l.getHandlers();
371             for (int j=0; ((handlers != null) && (j<handlers.length)); ++j) {
372                 handlers[j].flush();
373                 handlers[j].close();
374                 l.removeHandler(handlers[j]);
375             }
376             l.setUseParentHandlers(false);
377
378             //
379
// Now process the new handlers.
380
// Note that at the handler stage we set level to ALL (use the
381
// logger level to select the logging granularity.
382
//
383
if (conf.isConsoleOutput()) {
384                 h = new ConsoleHandler JavaDoc();
385                 h.setFormatter(new sync4j.framework.logging.SimpleFormatter());
386                 h.setLevel(Level.ALL);
387                 l.addHandler(h);
388             }
389
390             if (conf.isFileOutput()) {
391                 String JavaDoc pattern = conf.getPattern();
392
393                 if (new File JavaDoc(pattern).isAbsolute() == false) {
394                     pattern = getSync4jHome() + File.separator + pattern;
395                 }
396
397                 if ((pattern == null) || (pattern.trim().length() == 0)) {
398                     pattern = "logs/sync4j%t.log";
399                 }
400                 h = new FileHandler JavaDoc(
401                     pattern ,
402                     conf.getLimit()*1048576,
403                     conf.getCount(),
404                     conf.isAppend()
405                 );
406                 h.setFormatter(new sync4j.framework.logging.SimpleFormatter());
407                 h.setLevel(Level.ALL);
408                 l.addHandler(h);
409             }
410
411             if (LoggerConfiguration.LEVEL_OFF.equalsIgnoreCase(conf.getLevel())) {
412                 l.setLevel(Level.OFF);
413             } else if (LoggerConfiguration.LEVEL_SEVERE.equalsIgnoreCase(conf.getLevel())) {
414                 l.setLevel(Level.SEVERE);
415             } else if (LoggerConfiguration.LEVEL_INFO.equalsIgnoreCase(conf.getLevel())) {
416                 l.setLevel(Level.INFO);
417             } else if (LoggerConfiguration.LEVEL_ALL.equalsIgnoreCase(conf.getLevel())) {
418                 l.setLevel(Level.ALL);
419             }
420
421         }
422     }
423
424     /**
425      * Loads and instantiate a bean by its config name. In this case the bean
426      * is not looked up in the internal configuration map, but is created
427      * directly by the means of the BeanFactory. This call is a shortcut for:
428      * <code>
429      *
430      * ClassLoader cl = Configuration.getConfiguration().getClassLoader();
431      * Object o = BeanFactory.getBeanInstance(cl, beanName);
432      *
433      * </code>
434      *
435      * @param beanName the complete beanName
436      *
437      * @return the bean instance
438      *
439      * @throws BeanException in case of instantiation error
440      */

441     public Object JavaDoc getBeanInstanceByName(String JavaDoc beanName)
442     throws BeanException {
443         return BeanFactory.getBeanInstance(classLoader, beanName);
444     }
445
446     /**
447      * Saves an instantiate of a server bean to the given name under the config
448      * path.
449      *
450      * @param beanName the complete beanName
451      * @param obj the bean instance
452      *
453      *
454      * @throws BeanException in case of instantiation error
455      */

456     public void setBeanInstance(String JavaDoc beanName, Object JavaDoc o)
457     throws BeanException {
458         BeanFactory.saveBeanInstance(o, new File JavaDoc(getConfigPath(), beanName));
459     }
460     
461     /**
462      * Returns the Sync4j home as set as follows (the first value found is
463      * taken):
464      * <ul>
465      * <li>the system property sync4j.home</li>
466      * <li>the current directory</i>
467      * </ul>
468      *
469      * @return the Sync4j home as set as discribed above.
470      */

471     public static String JavaDoc getSync4jHome() {
472         return System.getProperty(PROPERTY_SYSTEM_SYNC4J_HOME, ".");
473     }
474
475     /**
476      * Returns the config path calculated as getSync4jHome() + CONFIG_PATH
477      *
478      * @return the config path calculated as getSync4jHome() + CONFIG_PATH
479      */

480     public static String JavaDoc getConfigPath() {
481         return getSync4jHome() + CONFIG_PATH;
482     }
483
484     public String JavaDoc toString() {
485         StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
486
487         sb.append(getClass().getName()).append('\n')
488           .append("serverInfo: ").append(serverConfig.getServerInfo()).append('\n')
489           .append("engineConfiguration: ").append(serverConfig.getEngineConfiguration()).append('\n')
490           .append("classLoader: " + classLoader).append('\n');
491
492         return sb.toString();
493     }
494
495     /**
496      * The server URI is optional into Sync4j.properties: so if it's not given,
497      * it should be set at default value http://<localhost>:8080/sync4j/sync
498      * This is to avoid to change the configuration in order to access at the
499      * server remotely. When server URI is specified, the given value must be
500      * used instead of the default.
501      */

502     private void setServerURI() {
503         String JavaDoc serverURI = null;
504         try {
505             serverURI =
506                 singleton.getServerConfig().getEngineConfiguration().getServerURI();
507             if (log.isLoggable(Level.FINEST)) {
508                 log.finest("Server URI set: " + serverURI);
509             }
510
511             if (serverURI == null || serverURI.equals("")) {
512
513                 if (log.isLoggable(Level.WARNING)) {
514                     log.warning("serverURI property not provided; looking for local ip address.");
515                 }
516
517                 serverURI = "http://"
518                           + getServerAddress()
519                           + ":8080/sync4j/sync"
520                           ;
521
522                 singleton.getServerConfig().getEngineConfiguration().setServerURI(serverURI);
523             }
524         } catch (Exception JavaDoc e) {
525             String JavaDoc msg = "Error in setting default server URI";
526             log.severe(msg + ": " + e.getMessage());
527             log.throwing(Configuration.class.getName(), "setServerURI", e);
528             throw new ConfigurationException(msg);
529         }
530
531         if (log.isLoggable(Level.INFO)) {
532             log.info("ServerURI: " + serverURI);
533         }
534     }
535
536     /**
537      * Get the server address checking all network interfaces. If there is an address
538      * not loopback len 4 bytes return it, also return the host name. If a error
539      * occurs getting the host name, returns <i>localhost</i>
540      * @return String
541      */

542     private String JavaDoc getServerAddress() {
543         NetworkInterface JavaDoc iface = null;
544         InetAddress JavaDoc ia = null;
545         String JavaDoc address = null;
546
547         try {
548             for (Enumeration JavaDoc ifaces = NetworkInterface.getNetworkInterfaces();
549                                       ifaces.hasMoreElements(); ) {
550                 iface = (NetworkInterface JavaDoc)ifaces.nextElement();
551                 for (Enumeration JavaDoc ips = iface.getInetAddresses(); ips.hasMoreElements(); ) {
552                     ia = (InetAddress JavaDoc)ips.nextElement();
553                     if (!ia.isLoopbackAddress() && (ia.getAddress().length == 4)) {
554                         address = ia.getHostAddress();
555
556                         if (log.isLoggable(Level.WARNING)) {
557                             log.warning("Local address <" + address + "> found on interface <" +
558                                         iface + ">");
559                         }
560                         return address;
561                     }
562
563                 }
564             }
565         } catch (SocketException ex) {
566             if (log.isLoggable(Level.SEVERE)) {
567                 log.severe(ex.getMessage());
568             }
569             return null;
570         }
571
572         if (address == null) {
573             if (log.isLoggable(Level.WARNING)) {
574                 log.warning("Non loopback address found, using local host name. " +
575                             "If you want to access the server from an external network, please check your network " +
576                             "configuration and/or provide a valid serverURI " +
577                             "property in Sync4j.xml. For local access, ignore this message.");
578             }
579
580             try {
581                 address = java.net.InetAddress.getLocalHost().getHostName();
582             } catch (UnknownHostException ex) {
583                 if (log.isLoggable(Level.SEVERE)) {
584                     log.severe(ex.getMessage());
585                 }
586                 return null;
587             }
588         }
589         return address;
590     }
591 }
592
Popular Tags