KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > cayenne > conf > Configuration


1 /*****************************************************************
2  * Licensed to the Apache Software Foundation (ASF) under one
3  * or more contributor license agreements. See the NOTICE file
4  * distributed with this work for additional information
5  * regarding copyright ownership. The ASF licenses this file
6  * to you under the Apache License, Version 2.0 (the
7  * "License"); you may not use this file except in compliance
8  * with the License. You may obtain a copy of the License at
9  *
10  * http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing,
13  * software distributed under the License is distributed on an
14  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15  * KIND, either express or implied. See the License for the
16  * specific language governing permissions and limitations
17  * under the License.
18  ****************************************************************/

19
20 package org.apache.cayenne.conf;
21
22 import java.io.IOException JavaDoc;
23 import java.io.InputStream JavaDoc;
24 import java.util.ArrayList JavaDoc;
25 import java.util.Collection JavaDoc;
26 import java.util.Collections JavaDoc;
27 import java.util.HashMap JavaDoc;
28 import java.util.Iterator JavaDoc;
29 import java.util.List JavaDoc;
30 import java.util.Map JavaDoc;
31
32 import org.apache.cayenne.CayenneRuntimeException;
33 import org.apache.cayenne.ConfigurationException;
34 import org.apache.cayenne.access.DataDomain;
35 import org.apache.cayenne.dataview.DataView;
36 import org.apache.cayenne.event.EventManager;
37 import org.apache.cayenne.util.CayenneMap;
38 import org.apache.cayenne.util.ResourceLocator;
39 import org.apache.commons.collections.Predicate;
40 import org.apache.commons.logging.Log;
41 import org.apache.commons.logging.LogFactory;
42
43 /**
44  * This class is an entry point to Cayenne. It loads all configuration files and
45  * instantiates main Cayenne objects. Used as a singleton via the
46  * {@link #getSharedConfiguration}method.
47  * <p>
48  * To use a custom subclass of Configuration, Java applications must call
49  * {@link #initializeSharedConfiguration}with the subclass as argument. This will create
50  * and initialize a Configuration singleton instance of the specified class. By default
51  * {@link DefaultConfiguration}is instantiated.
52  * </p>
53  *
54  * @author Andrus Adamchik
55  * @author Holger Hoffstaette
56  */

57 public abstract class Configuration {
58
59     private static Log logObj = LogFactory.getLog(Configuration.class);
60
61     public static final String JavaDoc DEFAULT_DOMAIN_FILE = "cayenne.xml";
62     public static final Class JavaDoc DEFAULT_CONFIGURATION_CLASS = DefaultConfiguration.class;
63
64     protected static Configuration sharedConfiguration = null;
65
66     public static final Predicate ACCEPT_ALL_DATAVIEWS = new Predicate() {
67
68         public boolean evaluate(Object JavaDoc dataViewName) {
69             return true;
70         }
71     };
72
73     /**
74      * Lookup map that stores DataDomains with names as keys.
75      */

76     protected CayenneMap dataDomains = new CayenneMap(this);
77     protected DataSourceFactory overrideFactory;
78     protected ConfigStatus loadStatus = new ConfigStatus();
79     protected String JavaDoc domainConfigurationName = DEFAULT_DOMAIN_FILE;
80     protected boolean ignoringLoadFailures;
81     protected ConfigLoaderDelegate loaderDelegate;
82     protected ConfigSaverDelegate saverDelegate;
83     protected ConfigurationShutdownHook configurationShutdownHook = new ConfigurationShutdownHook();
84     protected Map JavaDoc dataViewLocations = new HashMap JavaDoc();
85     protected String JavaDoc projectVersion;
86
87     /**
88      * @since 1.2
89      */

90     protected EventManager eventManager;
91
92     /**
93      * Use this method as an entry point to all Cayenne access objects.
94      * <p>
95      * Note that if you want to provide a custom Configuration, make sure you call one of
96      * the {@link #initializeSharedConfiguration}methods before your application code has
97      * a chance to call this method.
98      */

99     public synchronized static Configuration getSharedConfiguration() {
100         if (Configuration.sharedConfiguration == null) {
101             Configuration.initializeSharedConfiguration();
102         }
103
104         return Configuration.sharedConfiguration;
105     }
106
107     /**
108      * Returns EventManager used by this configuration.
109      *
110      * @since 1.2
111      */

112     public EventManager getEventManager() {
113         return eventManager;
114     }
115
116     /**
117      * Sets EventManager used by this configuration.
118      *
119      * @since 1.2
120      */

121     public void setEventManager(EventManager eventManager) {
122         this.eventManager = eventManager;
123     }
124
125     /**
126      * Creates and initializes shared Configuration object. By default
127      * {@link DefaultConfiguration}will be instantiated and assigned to a singleton
128      * instance of Configuration.
129      */

130     public static void initializeSharedConfiguration() {
131         Configuration.initializeSharedConfiguration(DEFAULT_CONFIGURATION_CLASS);
132     }
133
134     /**
135      * Creates and initializes a shared Configuration object of a custom Configuration
136      * subclass.
137      */

138     public static void initializeSharedConfiguration(Class JavaDoc configurationClass) {
139         Configuration conf = null;
140
141         try {
142             conf = (Configuration) configurationClass.newInstance();
143         }
144         catch (Exception JavaDoc ex) {
145             logObj.error("Error creating shared Configuration: ", ex);
146             throw new ConfigurationException("Error creating shared Configuration."
147                     + ex.getMessage(), ex);
148         }
149
150         Configuration.initializeSharedConfiguration(conf);
151     }
152
153     /**
154      * Sets the shared Configuration object to a new Configuration object. First calls
155      * {@link #canInitialize}and - if permitted -{@link #initialize}followed by
156      * {@link #didInitialize}.
157      */

158     public static void initializeSharedConfiguration(Configuration conf) {
159         // check to see whether we can proceed
160
if (!conf.canInitialize()) {
161             throw new ConfigurationException("Configuration of class "
162                     + conf.getClass().getName()
163                     + " refused to be initialized.");
164         }
165
166         try {
167             // initialize configuration
168
conf.initialize();
169
170             // call post-initialization hook
171
conf.didInitialize();
172
173             // set the initialized Configuration only after success
174
Configuration.sharedConfiguration = conf;
175         }
176         catch (Exception JavaDoc ex) {
177             throw new ConfigurationException(
178                     "Error during Configuration initialization. " + ex.getMessage(),
179                     ex);
180         }
181     }
182
183     /**
184      * Default constructor for new Configuration instances. Simply calls
185      * {@link Configuration#Configuration(String)}.
186      *
187      * @see Configuration#Configuration(String)
188      */

189     protected Configuration() {
190         this(DEFAULT_DOMAIN_FILE);
191     }
192
193     /**
194      * Default constructor for new Configuration instances using the given resource name
195      * as the main domain file.
196      */

197     protected Configuration(String JavaDoc domainConfigurationName) {
198
199         // set domain configuration name
200
this.setDomainConfigurationName(domainConfigurationName);
201
202         this.eventManager = new EventManager();
203     }
204
205     /**
206      * Indicates whether {@link #initialize}can be called. Returning <code>false</code>
207      * allows new instances to delay or refuse the initialization process.
208      */

209     public abstract boolean canInitialize();
210
211     /**
212      * Initializes the new instance.
213      *
214      * @throws Exception
215      */

216     public abstract void initialize() throws Exception JavaDoc;
217
218     /**
219      * Called after successful completion of {@link #initialize}.
220      */

221     public abstract void didInitialize();
222
223     /**
224      * Returns the resource locator used for finding and loading resources.
225      */

226     protected abstract ResourceLocator getResourceLocator();
227
228     /**
229      * Returns a DataDomain as a stream or <code>null</code> if it cannot be found.
230      */

231     // TODO: this method is only used in sublcass (DefaultConfiguration),
232
// should we remove it from here?
233
protected abstract InputStream JavaDoc getDomainConfiguration();
234
235     /**
236      * Returns a DataMap with the given name or <code>null</code> if it cannot be found.
237      */

238     protected abstract InputStream JavaDoc getMapConfiguration(String JavaDoc name);
239
240     protected abstract InputStream JavaDoc getViewConfiguration(String JavaDoc location);
241
242     /**
243      * Returns the name of the main domain configuration resource. Defaults to
244      * {@link Configuration#DEFAULT_DOMAIN_FILE}.
245      */

246     public String JavaDoc getDomainConfigurationName() {
247         return this.domainConfigurationName;
248     }
249
250     /**
251      * Sets the name of the main domain configuration resource.
252      *
253      * @param domainConfigurationName the name of the resource that contains this
254      * Configuration's domain(s).
255      */

256     protected void setDomainConfigurationName(String JavaDoc domainConfigurationName) {
257         this.domainConfigurationName = domainConfigurationName;
258     }
259
260     /**
261      * @since 1.1
262      */

263     public String JavaDoc getProjectVersion() {
264         return projectVersion;
265     }
266
267     /**
268      * @since 1.1
269      */

270     public void setProjectVersion(String JavaDoc projectVersion) {
271         this.projectVersion = projectVersion;
272     }
273
274     /**
275      * Returns an internal property for the DataSource factory that will override any
276      * settings configured in XML. Subclasses may override this method to provide a
277      * special factory for DataSource creation that will take precedence over any
278      * factories configured in a cayenne project.
279      */

280     public DataSourceFactory getDataSourceFactory() {
281         return this.overrideFactory;
282     }
283
284     public void setDataSourceFactory(DataSourceFactory overrideFactory) {
285         this.overrideFactory = overrideFactory;
286     }
287
288     /**
289      * Adds new DataDomain to the list of registered domains. Injects EventManager used by
290      * this configuration into the domain.
291      */

292     public void addDomain(DataDomain domain) {
293         this.dataDomains.put(domain.getName(), domain);
294
295         // inject EventManager
296
if (domain != null) {
297             domain.setEventManager(getEventManager());
298         }
299
300         logObj.debug("added domain: " + domain.getName());
301     }
302
303     /**
304      * Returns registered domain matching <code>name</code> or <code>null</code> if no
305      * such domain is found.
306      */

307     public DataDomain getDomain(String JavaDoc name) {
308         return (DataDomain) this.dataDomains.get(name);
309     }
310
311     /**
312      * Returns default domain of this configuration. If no domains are configured,
313      * <code>null</code> is returned. If more than one domain exists in this
314      * configuration, a CayenneRuntimeException is thrown, indicating that the domain name
315      * must be explicitly specified. In such cases {@link #getDomain(String name)}must be
316      * used instead.
317      */

318     public DataDomain getDomain() {
319         int size = this.dataDomains.size();
320         if (size == 0) {
321             return null;
322         }
323         else if (size == 1) {
324             return (DataDomain) this.dataDomains.values().iterator().next();
325         }
326         else {
327             throw new CayenneRuntimeException(
328                     "More than one domain is configured; use 'getDomain(String name)' instead.");
329         }
330     }
331
332     /**
333      * Unregisters DataDomain matching <code>name<code> from
334      * this Configuration object. Note that any domain database
335      * connections remain open, and it is a responsibility of a
336      * caller to clean it up.
337      */

338     public void removeDomain(String JavaDoc name) {
339         DataDomain domain = (DataDomain) dataDomains.remove(name);
340
341         if (domain != null) {
342             domain.setEventManager(null);
343         }
344
345         logObj.debug("removed domain: " + name);
346     }
347
348     /**
349      * Returns an unmodifiable collection of registered {@link DataDomain}objects.
350      */

351     public Collection JavaDoc getDomains() {
352         return Collections.unmodifiableCollection(dataDomains.values());
353     }
354
355     /**
356      * Returns whether to ignore any failures during map loading or not.
357      *
358      * @return boolean
359      */

360     public boolean isIgnoringLoadFailures() {
361         return this.ignoringLoadFailures;
362     }
363
364     /**
365      * Sets whether to ignore any failures during map loading or not.
366      *
367      * @param ignoringLoadFailures <code>true</code> or <code>false</code>
368      */

369     protected void setIgnoringLoadFailures(boolean ignoringLoadFailures) {
370         this.ignoringLoadFailures = ignoringLoadFailures;
371     }
372
373     /**
374      * Returns the load status.
375      *
376      * @return ConfigStatus
377      */

378     public ConfigStatus getLoadStatus() {
379         return this.loadStatus;
380     }
381
382     /**
383      * Sets the load status.
384      */

385     protected void setLoadStatus(ConfigStatus status) {
386         this.loadStatus = status;
387     }
388
389     /**
390      * Returns a delegate used for controlling the loading of configuration elements.
391      */

392     public ConfigLoaderDelegate getLoaderDelegate() {
393         return loaderDelegate;
394     }
395
396     /**
397      * @since 1.1
398      */

399     public void setLoaderDelegate(ConfigLoaderDelegate loaderDelegate) {
400         this.loaderDelegate = loaderDelegate;
401     }
402
403     /**
404      * @since 1.2
405      */

406     public ConfigSaverDelegate getSaverDelegate() {
407         return saverDelegate;
408     }
409
410     /**
411      * @since 1.2
412      */

413     public void setSaverDelegate(ConfigSaverDelegate saverDelegate) {
414         this.saverDelegate = saverDelegate;
415     }
416
417     /**
418      * Initializes configuration with the location of data views.
419      *
420      * @since 1.1
421      * @param dataViewLocations Map of DataView locations.
422      */

423     public void setDataViewLocations(Map JavaDoc dataViewLocations) {
424         if (dataViewLocations == null)
425             this.dataViewLocations = new HashMap JavaDoc();
426         else
427             this.dataViewLocations = dataViewLocations;
428     }
429
430     /**
431      * @since 1.1
432      */

433     public Map JavaDoc getDataViewLocations() {
434         return dataViewLocations;
435     }
436
437     /**
438      * @since 1.1
439      */

440     public boolean loadDataView(DataView dataView) throws IOException JavaDoc {
441         return loadDataView(dataView, Configuration.ACCEPT_ALL_DATAVIEWS);
442     }
443
444     /**
445      * @since 1.1
446      */

447     public boolean loadDataView(DataView dataView, Predicate dataViewNameFilter)
448             throws IOException JavaDoc {
449
450         if (dataView == null) {
451             throw new IllegalArgumentException JavaDoc("DataView cannot be null.");
452         }
453
454         if (dataViewLocations.size() == 0 || dataViewLocations.size() > 512) {
455             return false;
456         }
457
458         if (dataViewNameFilter == null)
459             dataViewNameFilter = Configuration.ACCEPT_ALL_DATAVIEWS;
460
461         List JavaDoc viewXMLSources = new ArrayList JavaDoc(dataViewLocations.size());
462         int index = 0;
463         for (Iterator JavaDoc i = dataViewLocations.entrySet().iterator(); i.hasNext(); index++) {
464             Map.Entry JavaDoc entry = (Map.Entry JavaDoc) i.next();
465             String JavaDoc name = (String JavaDoc) entry.getKey();
466             if (!dataViewNameFilter.evaluate(name))
467                 continue;
468             String JavaDoc location = (String JavaDoc) entry.getValue();
469             InputStream JavaDoc in = getViewConfiguration(location);
470             if (in != null)
471                 viewXMLSources.add(in);
472         }
473
474         if (viewXMLSources.isEmpty())
475             return false;
476
477         dataView.load((InputStream JavaDoc[]) viewXMLSources
478                 .toArray(new InputStream JavaDoc[viewXMLSources.size()]));
479         return true;
480     }
481
482     /**
483      * Shutdowns all owned domains. Invokes DataDomain.shutdown().
484      */

485     public void shutdown() {
486         Collection JavaDoc domains = getDomains();
487         for (Iterator JavaDoc i = domains.iterator(); i.hasNext();) {
488             DataDomain domain = (DataDomain) i.next();
489             domain.shutdown();
490         }
491     }
492
493     private class ConfigurationShutdownHook extends Thread JavaDoc {
494
495         public void run() {
496             shutdown();
497         }
498     }
499
500     public void installConfigurationShutdownHook() {
501         uninstallConfigurationShutdownHook();
502         Runtime.getRuntime().addShutdownHook(configurationShutdownHook);
503     }
504
505     public void uninstallConfigurationShutdownHook() {
506         Runtime.getRuntime().removeShutdownHook(configurationShutdownHook);
507     }
508 }
509
Popular Tags