Source Code Cross Referenced for GenericConfigurationImpl.java in  » J2EE » fleXive » com » flexive » core » configuration » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » J2EE » fleXive » com.flexive.core.configuration 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /***************************************************************
002:         *  This file is part of the [fleXive](R) project.
003:         *
004:         *  Copyright (c) 1999-2008
005:         *  UCS - unique computing solutions gmbh (http://www.ucs.at)
006:         *  All rights reserved
007:         *
008:         *  The [fleXive](R) project is free software; you can redistribute
009:         *  it and/or modify it under the terms of the GNU General Public
010:         *  License as published by the Free Software Foundation;
011:         *  either version 2 of the License, or (at your option) any
012:         *  later version.
013:         *
014:         *  The GNU General Public License can be found at
015:         *  http://www.gnu.org/copyleft/gpl.html.
016:         *  A copy is found in the textfile GPL.txt and important notices to the
017:         *  license from the author are found in LICENSE.txt distributed with
018:         *  these libraries.
019:         *
020:         *  This library is distributed in the hope that it will be useful,
021:         *  but WITHOUT ANY WARRANTY; without even the implied warranty of
022:         *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
023:         *  GNU General Public License for more details.
024:         *
025:         *  For further information about UCS - unique computing solutions gmbh,
026:         *  please see the company website: http://www.ucs.at
027:         *
028:         *  For further information about [fleXive](R), please see the
029:         *  project website: http://www.flexive.org
030:         *
031:         *
032:         *  This copyright notice MUST APPEAR in all copies of the file!
033:         ***************************************************************/package com.flexive.core.configuration;
034:
035:        import com.flexive.core.Database;
036:        import com.flexive.shared.CacheAdmin;
037:        import com.flexive.shared.cache.FxCacheException;
038:        import com.flexive.shared.configuration.Parameter;
039:        import com.flexive.shared.configuration.ParameterData;
040:        import com.flexive.shared.exceptions.*;
041:        import com.flexive.shared.interfaces.GenericConfigurationEngine;
042:        import org.apache.commons.logging.Log;
043:        import org.apache.commons.logging.LogFactory;
044:        import org.apache.commons.lang.SerializationUtils;
045:
046:        import javax.ejb.TransactionAttribute;
047:        import javax.ejb.TransactionAttributeType;
048:        import java.io.Serializable;
049:        import java.sql.Connection;
050:        import java.sql.PreparedStatement;
051:        import java.sql.ResultSet;
052:        import java.sql.SQLException;
053:        import java.util.Collection;
054:        import java.util.HashMap;
055:        import java.util.Map;
056:
057:        /**
058:         * Abstract base class for configuration methods. Implements templated getter/setter
059:         * methods for configuration classes that may add custom behavior like caching.
060:         * <p>
061:         * An implementor must create SQL statements for reading, updating and deleting
062:         * parameters, and a method for obtaining a database connection for the
063:         * configuration table.
064:         * </p>
065:         * <p>
066:         * The <code>setParameter/getParameter</code> methods may be overridden
067:         * to implement custom behavior, e.g. caching of parameter values. Some
068:         * set- and get-methods are declared final because they are wrappers
069:         * for the (non-final) main set/get method.
070:         * </p>
071:         *
072:         * @author Daniel Lichtenberger (daniel.lichtenberger@flexive.com), UCS - unique computing solutions gmbh (http://www.ucs.at)
073:         */
074:
075:        public abstract class GenericConfigurationImpl implements 
076:                GenericConfigurationEngine {
077:            private static final transient Log LOG = LogFactory
078:                    .getLog(GenericConfigurationImpl.class);
079:
080:            /**
081:             * Helper class to place unset parameters in the configuration cache.
082:             */
083:            protected static class UnsetParameter implements  Serializable {
084:                private static final long serialVersionUID = -289868789320707584L;
085:            }
086:
087:            /**
088:             * Helper class to represent null value in the cache (since an unset
089:             * parameter would also be null).
090:             */
091:            protected static class NullParameter implements  Serializable {
092:                private static final long serialVersionUID = -3959509316291057862L;
093:            }
094:
095:            /**
096:             * Return a (new or existing) Connection to the configuration table.
097:             *
098:             * @throws SQLException if the connection could not be retrieved
099:             * @return a Connection to the configuration table.
100:             */
101:            protected abstract Connection getConnection() throws SQLException;
102:
103:            /**
104:             * Return a select statement that selects the given path and key
105:             * and returns the stored value.
106:             * <p>
107:             * Required SELECT arguments:
108:             * <ol>
109:             * <li>value</li>
110:             * </ol>
111:             * </p>
112:             *
113:             * @param conn the current connection
114:             * @param path the requested path
115:             * @param key  the requested key
116:             * @throws SQLException if a database error occurs
117:             * @return a PreparedStatement selecting the value for the given path/key combination
118:             */
119:            protected abstract PreparedStatement getSelectStatement(
120:                    Connection conn, String path, String key)
121:                    throws SQLException;
122:
123:            /**
124:             * Return a select statement that selects all keys and values for the given path.
125:             * <p>
126:             * Required SELECT arguments:
127:             * <ol>
128:             * <li>key</li>
129:             * <li>value</li>
130:             * </ol>
131:             * </p>
132:             *
133:             * @param conn the current connection
134:             * @param path the requested path
135:             * @throws SQLException if a database error occurs
136:             * @return a PreparedStatement selecting all keys and values for the given path
137:             */
138:            protected abstract PreparedStatement getSelectStatement(
139:                    Connection conn, String path) throws SQLException;
140:
141:            /**
142:             * Return an update statement that updates the value for the given
143:             * path/key combination.
144:             *
145:             * @param conn  the current connection
146:             * @param path  path of the parameter
147:             * @param key   key to be updated
148:             * @param value the new value to be stored
149:             * @throws SQLException        if a database error occurs
150:             * @throws FxNoAccessException if the caller is not permitted to update the given parameter
151:             * @return a PreparedStatement updating the given row
152:             */
153:            protected abstract PreparedStatement getUpdateStatement(
154:                    Connection conn, String path, String key, String value)
155:                    throws SQLException, FxNoAccessException;
156:
157:            /**
158:             * Return an insert statement that inserts a new row for the given
159:             * path, key and value.
160:             *
161:             * @param conn  the current connection
162:             * @param path  path of the new row
163:             * @param key   key of the new row
164:             * @param value value of the new row
165:             * @throws SQLException        if a database error occurs
166:             * @throws FxNoAccessException if the caller is not permitted to create the given parameter
167:             * @return a PreparedStatement for inserting the given path/key/value
168:             */
169:            protected abstract PreparedStatement getInsertStatement(
170:                    Connection conn, String path, String key, String value)
171:                    throws SQLException, FxNoAccessException;
172:
173:            /**
174:             * Return a delete statement to delete the given parameter.
175:             *
176:             * @param conn the current connection
177:             * @param path path of the row to be deleted
178:             * @param key  key of the row to be deleted. If null, all keys under the given path should be deleted.
179:             * @return a PreparedStatement for deleting the given path/key
180:             * @throws SQLException        if a database error occurs
181:             * @throws FxNoAccessException if the caller is not permitted to delete the given parameter
182:             */
183:            protected abstract PreparedStatement getDeleteStatement(
184:                    Connection conn, String path, String key)
185:                    throws SQLException, FxNoAccessException;
186:
187:            /**
188:             * Return the cache path for the given configuration parameter path.
189:             * If this method returns null (like the default implementation), caching
190:             * is disabled. Be aware that you have to add the context to your cache path,
191:             * e.g. the user ID for user settings.
192:             *
193:             * @param path the parameter path to be mapped
194:             * @return the mapped parameter path, or null to disable caching
195:             */
196:            protected String getCachePath(String path) {
197:                return null;
198:            }
199:
200:            /**
201:             * Wrapper for simple cache stats. May be used as hook
202:             * for adding cache logging or as an aspectj pointcut.
203:             *
204:             * @param path the parameter path that caused the cache hit
205:             * @param key  the parameter key that caused the cache hit
206:             */
207:            protected void logCacheHit(String path, String key) {
208:                // no cache stats by default
209:            }
210:
211:            /**
212:             * Wrapper for simple cache stats. May be used as hook
213:             * for adding cache logging or as an aspectj pointcut.
214:             *
215:             * @param path the parameter path that caused the cache hit
216:             * @param key  the parameter key that caused the cache hit
217:             */
218:            protected void logCacheMiss(String path, String key) {
219:                // no cache stats by default
220:            }
221:
222:            /**
223:             * {@inheritDoc}
224:             */
225:            @TransactionAttribute(TransactionAttributeType.REQUIRED)
226:            public <T extends Serializable> void put(Parameter<T> parameter,
227:                    String key, T value) throws FxApplicationException {
228:
229:                if (!parameter.isValid(value)) {
230:                    throw new FxUpdateException(
231:                            "ex.configuration.parameter.value", parameter,
232:                            value);
233:                }
234:
235:                // put into DB config table
236:                Connection conn = null;
237:                PreparedStatement stmt = null;
238:                ParameterData<T> data = parameter.getData();
239:                try {
240:                    conn = getConnection();
241:                    stmt = getSelectStatement(conn, data.getPath().getValue(),
242:                            key);
243:                    ResultSet rs = stmt.executeQuery();
244:                    boolean valueExists = rs.next();
245:                    stmt.close();
246:                    stmt = null;
247:                    if (valueExists) {
248:                        // update existing record
249:                        stmt = getUpdateStatement(conn, data.getPath()
250:                                .getValue(), key, value != null ? parameter
251:                                .getDatabaseValue(value) : null);
252:                    } else {
253:                        // create new record
254:                        stmt = getInsertStatement(conn, data.getPath()
255:                                .getValue(), key, value != null ? parameter
256:                                .getDatabaseValue(value) : null);
257:                    }
258:                    stmt.executeUpdate();
259:
260:                    // update cache?
261:                    String cachePath = getCachePath(data.getPath().getValue());
262:                    if (cachePath != null) {
263:                        putCache(
264:                                cachePath,
265:                                key,
266:                                value != null ? (Serializable) SerializationUtils
267:                                        .clone(value)
268:                                        : new NullParameter());
269:                    }
270:                } catch (SQLException se) {
271:                    FxUpdateException ue = new FxUpdateException(LOG, se,
272:                            "ex.db.sqlError", se.getMessage());
273:                    LOG.error(ue, se);
274:                    throw ue;
275:                } finally {
276:                    Database.closeObjects(GenericConfigurationImpl.class, conn,
277:                            stmt);
278:                }
279:            }
280:
281:            /**
282:             * {@inheritDoc}
283:             */
284:            @TransactionAttribute(TransactionAttributeType.REQUIRED)
285:            public final <T extends Serializable> void put(
286:                    Parameter<T> parameter, T value)
287:                    throws FxApplicationException {
288:                put(parameter, parameter.getData().getKey(), value);
289:            }
290:
291:            /**
292:             * Get a configuration parameter identified by a path and a key.
293:             *
294:             * @param parameter the actual parameter instance
295:             * @param path path of the parameter
296:             * @param key  key of the parameter
297:             * @return the parameter value
298:             * @throws FxLoadException     if the parameter could not be loaded
299:             * @throws FxNotFoundException if the parameter does not exist
300:             */
301:            protected <T extends Serializable> Object getParameter(
302:                    Parameter<T> parameter, String path, String key)
303:                    throws FxLoadException, FxNotFoundException {
304:                String cachePath = getCachePath(path);
305:                if (cachePath != null) {
306:                    // try cache first
307:                    try {
308:                        Object value = getCache(cachePath, key);
309:                        if (value != null) {
310:                            logCacheHit(path, key);
311:                            if (value instanceof  UnsetParameter) {
312:                                // check for null object
313:                                throw new FxNotFoundException(
314:                                        "ex.configuration.parameter.notfound",
315:                                        path, key);
316:                            } else if (value instanceof  NullParameter) {
317:                                return null;
318:                            } else {
319:                                return value;
320:                            }
321:                        }
322:                    } catch (FxCacheException e) {
323:                        LOG.error("Cache failure (ignored): " + e.getMessage(),
324:                                e);
325:                    }
326:                }
327:                // load parameter from config table
328:                logCacheMiss(path, key);
329:                Serializable value = loadParameterFromDb(path, key);
330:                if (cachePath != null) {
331:                    // add value to cache
332:                    putCache(cachePath, key, parameter.getValue(value));
333:                }
334:                return value;
335:            }
336:
337:            /**
338:             * {@inheritDoc}
339:             */
340:            @TransactionAttribute(TransactionAttributeType.REQUIRED)
341:            public final <T extends Serializable> T get(Parameter<T> parameter)
342:                    throws FxApplicationException {
343:                return get(parameter, parameter.getData().getKey());
344:            }
345:
346:            /**
347:             * {@inheritDoc}
348:             */
349:            @TransactionAttribute(TransactionAttributeType.REQUIRED)
350:            public final <T extends Serializable> T get(Parameter<T> parameter,
351:                    String key) throws FxApplicationException {
352:                try {
353:                    return parameter.getValue(getParameter(parameter, parameter
354:                            .getPath().getValue(), key));
355:                } catch (FxNotFoundException e) {
356:                    if (parameter.getDefaultValue() != null) {
357:                        return parameter.getDefaultValue();
358:                    } else {
359:                        throw e;
360:                    }
361:                }
362:            }
363:
364:            /**
365:             * {@inheritDoc}
366:             */
367:            @TransactionAttribute(TransactionAttributeType.REQUIRED)
368:            public final <T extends Serializable> T get(Parameter<T> parameter,
369:                    String key, boolean ignoreDefault)
370:                    throws FxApplicationException {
371:                try {
372:                    return parameter.getValue(getParameter(parameter, parameter
373:                            .getPath().getValue(), key));
374:                } catch (FxNotFoundException e) {
375:                    if (!ignoreDefault && parameter.getDefaultValue() != null) {
376:                        return parameter.getDefaultValue();
377:                    } else {
378:                        throw e;
379:                    }
380:                }
381:            }
382:
383:            /**
384:             * {@inheritDoc}
385:             */
386:            @TransactionAttribute(TransactionAttributeType.REQUIRED)
387:            public final <T extends Serializable> Map<String, T> getAll(
388:                    Parameter<T> parameter) throws FxApplicationException {
389:                Connection conn = null;
390:                PreparedStatement stmt = null;
391:                ParameterData<T> data = parameter.getData();
392:                HashMap<String, T> parameters = new HashMap<String, T>();
393:                try {
394:                    conn = getConnection();
395:                    stmt = getSelectStatement(conn, data.getPath().getValue());
396:                    ResultSet rs = stmt.executeQuery();
397:                    while (rs != null && rs.next()) {
398:                        // retrieve parameters and put them in hashmap
399:                        parameters.put(rs.getString(1), parameter.getValue(rs
400:                                .getObject(2)));
401:                    }
402:                    return parameters;
403:                } catch (SQLException se) {
404:                    throw new FxLoadException(LOG, se, "ex.db.sqlError", se
405:                            .getMessage());
406:                } finally {
407:                    Database.closeObjects(GenericConfigurationImpl.class, conn,
408:                            stmt);
409:                }
410:            }
411:
412:            /**
413:             * {@inheritDoc}
414:             */
415:            @TransactionAttribute(TransactionAttributeType.REQUIRED)
416:            public final <T extends Serializable> Collection<String> getKeys(
417:                    Parameter<T> parameter) throws FxApplicationException {
418:                return getAll(parameter).keySet();
419:            }
420:
421:            /**
422:             * {@inheritDoc}
423:             */
424:            @TransactionAttribute(TransactionAttributeType.REQUIRED)
425:            public <T extends Serializable> void remove(Parameter<T> parameter,
426:                    String key) throws FxApplicationException {
427:                Connection conn = null;
428:                PreparedStatement stmt = null;
429:                try {
430:                    conn = getConnection();
431:                    stmt = getDeleteStatement(conn, parameter.getPath()
432:                            .getValue(), key);
433:                    stmt.executeUpdate();
434:                    String cachePath = getCachePath(parameter.getPath()
435:                            .getValue());
436:                    if (cachePath != null) {
437:                        // also remove from cache
438:                        if (key == null) {
439:                            // clear entire cache path
440:                            deleteCache(cachePath);
441:                        } else {
442:                            // clear single value
443:                            deleteCache(cachePath, key);
444:                        }
445:                    }
446:                } catch (SQLException e) {
447:                    throw new FxRemoveException(LOG, e, "ex.db.sqlError", e
448:                            .getMessage());
449:                } finally {
450:                    Database.closeObjects(GenericConfigurationImpl.class, conn,
451:                            stmt);
452:                }
453:            }
454:
455:            /**
456:             * {@inheritDoc}
457:             */
458:            @TransactionAttribute(TransactionAttributeType.REQUIRED)
459:            public final <T extends Serializable> void remove(
460:                    Parameter<T> parameter) throws FxApplicationException {
461:                remove(parameter, parameter.getKey());
462:            }
463:
464:            /**
465:             * {@inheritDoc}
466:             */
467:            @TransactionAttribute(TransactionAttributeType.REQUIRED)
468:            public final <T extends Serializable> void removeAll(
469:                    Parameter<T> parameter) throws FxApplicationException {
470:                remove(parameter, null);
471:            }
472:
473:            /**
474:             * Loads the given parameter from the database. Helper method for implementors.
475:             *
476:             * @param parameter the parameter to be loaded
477:             * @param <T>       value type of the parameter
478:             * @return the parameter value
479:             * @throws FxNotFoundException if the parameter does not exist
480:             * @throws FxLoadException     if the parameter could not be loaded
481:             */
482:            protected <T> T loadParameterFromDb(Parameter<T> parameter)
483:                    throws FxNotFoundException, FxLoadException {
484:                return parameter.getValue(loadParameterFromDb(parameter
485:                        .getPath().getValue(), parameter.getData().getKey()));
486:            }
487:
488:            /**
489:             * Loads the given parameter from the database. Helper method for implementors.
490:             *
491:             * @param path path of the parameter
492:             * @param key  key of the parameter
493:             * @return the parameter value
494:             * @throws FxLoadException     if the parameter could not be loaded
495:             * @throws FxNotFoundException if the parameter does not exist
496:             */
497:            protected Serializable loadParameterFromDb(String path, String key)
498:                    throws FxLoadException, FxNotFoundException {
499:                // get from DB
500:                Connection conn = null;
501:                PreparedStatement stmt = null;
502:                try {
503:                    conn = getConnection();
504:                    stmt = getSelectStatement(conn, path, key);
505:                    ResultSet rs = stmt.executeQuery();
506:                    if (rs != null && rs.next()) {
507:                        return (Serializable) rs.getObject(1);
508:                    } else {
509:                        String cachePath = getCachePath(path);
510:                        if (cachePath != null) {
511:                            // store null object in cache to avoid hitting the DB every time
512:                            putCache(cachePath, key, new UnsetParameter());
513:                        }
514:                        throw new FxNotFoundException(
515:                                "ex.configuration.parameter.notfound", path,
516:                                key);
517:                    }
518:                } catch (SQLException se) {
519:                    throw new FxLoadException(LOG, se, "ex.db.sqlError", se
520:                            .getMessage());
521:                } finally {
522:                    Database.closeObjects(GenericConfigurationImpl.class, conn,
523:                            stmt);
524:                }
525:            }
526:
527:            /**
528:             * Store the given value in the cache.
529:             *
530:             * @param path  the parameter path
531:             * @param key   the parameter key
532:             * @param value the serializable value to be stored
533:             */
534:            protected void putCache(String path, String key, Serializable value) {
535:                try {
536:                    CacheAdmin.getInstance().put(path, key, value);
537:                } catch (FxCacheException e) {
538:                    LOG.error("Failed to update cache (ignored): "
539:                            + e.getMessage());
540:                }
541:            }
542:
543:            /**
544:             * Delete the given parameter from the cache
545:             *
546:             * @param path path of the parameter to be removed
547:             * @param key  key  of the parameter to be removed
548:             */
549:            protected void deleteCache(String path, String key) {
550:                try {
551:                    CacheAdmin.getInstance().remove(path, key);
552:                } catch (FxCacheException e) {
553:                    LOG.error("Failed to update cache (ignored): "
554:                            + e.getMessage());
555:                }
556:            }
557:
558:            /**
559:             * Delete the given path from the cache
560:             *
561:             * @param path the path to be removed
562:             */
563:            protected void deleteCache(String path) {
564:                try {
565:                    CacheAdmin.getInstance().remove(path);
566:                } catch (FxCacheException e) {
567:                    LOG.error("Failed to update cache (ignored): "
568:                            + e.getMessage());
569:                }
570:            }
571:
572:            /**
573:             * Returns the cached value of the given parameter
574:             *
575:             * @param path the parameter path
576:             * @param key  the parameter key
577:             * @return the cached value of the given parameter
578:             * @throws FxCacheException if a cache exception occured
579:             */
580:            protected Serializable getCache(String path, String key)
581:                    throws FxCacheException {
582:                return (Serializable) SerializationUtils
583:                        .clone((Serializable) CacheAdmin.getInstance().get(
584:                                path, key));
585:            }
586:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.