Source Code Cross Referenced for BaseDbSingleStorage.java in  » ERP-CRM-Financial » sakai » org » sakaiproject » util » 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 » ERP CRM Financial » sakai » org.sakaiproject.util 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /**********************************************************************************
0002:         * $URL: https://source.sakaiproject.org/svn/db/tags/sakai_2-4-1/db-util/storage/src/java/org/sakaiproject/util/BaseDbSingleStorage.java $
0003:         * $Id: BaseDbSingleStorage.java 7084 2006-03-28 00:27:56Z ggolden@umich.edu $
0004:         ***********************************************************************************
0005:         *
0006:         * Copyright (c) 2003, 2004, 2005, 2006 The Sakai Foundation.
0007:         * 
0008:         * Licensed under the Educational Community License, Version 1.0 (the "License"); 
0009:         * you may not use this file except in compliance with the License. 
0010:         * You may obtain a copy of the License at
0011:         * 
0012:         *      http://www.opensource.org/licenses/ecl1.php
0013:         * 
0014:         * Unless required by applicable law or agreed to in writing, software 
0015:         * distributed under the License is distributed on an "AS IS" BASIS, 
0016:         * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
0017:         * See the License for the specific language governing permissions and 
0018:         * limitations under the License.
0019:         *
0020:         **********************************************************************************/package org.sakaiproject.util;
0021:
0022:        import java.sql.Connection;
0023:        import java.sql.ResultSet;
0024:        import java.sql.SQLException;
0025:        import java.util.Hashtable;
0026:        import java.util.List;
0027:        import java.util.Stack;
0028:        import java.util.Vector;
0029:
0030:        import org.apache.commons.logging.Log;
0031:        import org.apache.commons.logging.LogFactory;
0032:        import org.sakaiproject.db.api.SqlReader;
0033:        import org.sakaiproject.db.api.SqlService;
0034:        import org.sakaiproject.entity.api.Edit;
0035:        import org.sakaiproject.entity.api.Entity;
0036:        import org.sakaiproject.event.cover.UsageSessionService;
0037:        import org.sakaiproject.javax.Filter;
0038:        import org.sakaiproject.time.cover.TimeService;
0039:        import org.w3c.dom.Document;
0040:        import org.w3c.dom.Element;
0041:
0042:        /**
0043:         * <p>
0044:         * BaseDbSingleStorage is a class that stores Resources (of some type) in a database, <br />
0045:         * provides locked access, and generally implements a services "storage" class. The <br />
0046:         * service's storage class can extend this to provide covers to turn Resource and <br />
0047:         * Edit into something more type specific to the service.
0048:         * </p>
0049:         * <p>
0050:         * Note: the methods here are all "id" based, with the following assumptions: <br /> - just the Resource Id field is enough to distinguish one Resource from another <br /> - a resource's reference is based on no more than the resource id <br /> - a
0051:         * resource's id cannot change.
0052:         * </p>
0053:         * <p>
0054:         * In order to handle Unicode characters properly, the SQL statements executed by this class <br />
0055:         * should not embed Unicode characters into the SQL statement text; rather, Unicode values <br />
0056:         * should be inserted as fields in a PreparedStatement. Databases handle Unicode better in fields.
0057:         * </p>
0058:         */
0059:        public class BaseDbSingleStorage {
0060:            /** Our logger. */
0061:            private static Log M_log = LogFactory
0062:                    .getLog(BaseDbSingleStorage.class);
0063:
0064:            /** Table name for resource records. */
0065:            protected String m_resourceTableName = null;
0066:
0067:            /** The field in the resource table that holds the resource id. */
0068:            protected String m_resourceTableIdField = null;
0069:
0070:            /** The additional field names in the resource table that go between the two ids and the xml */
0071:            protected String[] m_resourceTableOtherFields = null;
0072:
0073:            /** The xml tag name for the element holding each actual resource entry. */
0074:            protected String m_resourceEntryTagName = null;
0075:
0076:            /** If true, we do our locks in the remote database. */
0077:            protected boolean m_locksAreInDb = false;
0078:
0079:            /** If true, we do our locks in the remove database using a separate locking table. */
0080:            protected boolean m_locksAreInTable = true;
0081:
0082:            /** The StorageUser to callback for new Resource and Edit objects. */
0083:            protected StorageUser m_user = null;
0084:
0085:            /**
0086:             * Locks, keyed by reference, holding Connections (or, if locks are done locally, holding an Edit).
0087:             */
0088:            protected Hashtable m_locks = null;
0089:
0090:            /** If set, we treat reasource ids as case insensitive. */
0091:            protected boolean m_caseInsensitive = false;
0092:
0093:            /** Injected (by constructor) SqlService. */
0094:            protected SqlService m_sql = null;
0095:
0096:            /**
0097:             * Construct.
0098:             * 
0099:             * @param resourceTableName
0100:             *        Table name for resources.
0101:             * @param resourceTableIdField
0102:             *        The field in the resource table that holds the id.
0103:             * @param resourceTableOtherFields
0104:             *        The other fields in the resource table (between the two id and the xml fields).
0105:             * @param locksInDb
0106:             *        If true, we do our locks in the remote database, otherwise we do them here.
0107:             * @param resourceEntryName
0108:             *        The xml tag name for the element holding each actual resource entry.
0109:             * @param user
0110:             *        The StorageUser class to call back for creation of Resource and Edit objects.
0111:             * @param sqlService
0112:             *        The SqlService.
0113:             */
0114:            public BaseDbSingleStorage(String resourceTableName,
0115:                    String resourceTableIdField,
0116:                    String[] resourceTableOtherFields, boolean locksInDb,
0117:                    String resourceEntryName, StorageUser user,
0118:                    SqlService sqlService) {
0119:                m_resourceTableName = resourceTableName;
0120:                m_resourceTableIdField = resourceTableIdField;
0121:                m_resourceTableOtherFields = resourceTableOtherFields;
0122:                m_locksAreInDb = locksInDb;
0123:                m_resourceEntryTagName = resourceEntryName;
0124:                m_user = user;
0125:                m_sql = sqlService;
0126:            }
0127:
0128:            /**
0129:             * Open and be ready to read / write.
0130:             */
0131:            public void open() {
0132:                // setup for locks
0133:                m_locks = new Hashtable();
0134:            }
0135:
0136:            /**
0137:             * Close.
0138:             */
0139:            public void close() {
0140:                if (!m_locks.isEmpty()) {
0141:                    M_log.warn("close(): locks remain!");
0142:                    // %%%
0143:                }
0144:                m_locks.clear();
0145:                m_locks = null;
0146:            }
0147:
0148:            /**
0149:             * Read one Resource from xml
0150:             * 
0151:             * @param xml
0152:             *        An string containing the xml which describes the resource.
0153:             * @return The Resource object created from the xml.
0154:             */
0155:            protected Entity readResource(String xml) {
0156:                try {
0157:                    // read the xml
0158:                    Document doc = Xml.readDocumentFromString(xml);
0159:
0160:                    // verify the root element
0161:                    Element root = doc.getDocumentElement();
0162:                    if (!root.getTagName().equals(m_resourceEntryTagName)) {
0163:                        M_log.warn("readResource(): not = "
0164:                                + m_resourceEntryTagName + " : "
0165:                                + root.getTagName());
0166:                        return null;
0167:                    }
0168:
0169:                    // re-create a resource
0170:                    Entity entry = m_user.newResource(null, root);
0171:
0172:                    return entry;
0173:                } catch (Exception e) {
0174:                    M_log.debug("readResource(): ", e);
0175:                    return null;
0176:                }
0177:            }
0178:
0179:            /**
0180:             * Check if a Resource by this id exists.
0181:             * 
0182:             * @param id
0183:             *        The id.
0184:             * @return true if a Resource by this id exists, false if not.
0185:             */
0186:            public boolean checkResource(String id) {
0187:                // just see if the record exists
0188:                String sql = "select " + m_resourceTableIdField + " from "
0189:                        + m_resourceTableName + " where ( "
0190:                        + m_resourceTableIdField + " = ? )";
0191:
0192:                Object fields[] = new Object[1];
0193:                fields[0] = caseId(id);
0194:                List ids = m_sql.dbRead(sql, fields, null);
0195:
0196:                return (!ids.isEmpty());
0197:            }
0198:
0199:            /**
0200:             * Get the Resource with this id, or null if not found.
0201:             * 
0202:             * @param id
0203:             *        The id.
0204:             * @return The Resource with this id, or null if not found.
0205:             */
0206:            public Entity getResource(String id) {
0207:                Entity entry = null;
0208:
0209:                // get the user from the db
0210:                String sql = "select XML from " + m_resourceTableName
0211:                        + " where ( " + m_resourceTableIdField + " = ? )";
0212:
0213:                Object fields[] = new Object[1];
0214:                fields[0] = caseId(id);
0215:                List xml = m_sql.dbRead(sql, fields, null);
0216:                if (!xml.isEmpty()) {
0217:                    // create the Resource from the db xml
0218:                    entry = readResource((String) xml.get(0));
0219:                }
0220:
0221:                return entry;
0222:            }
0223:
0224:            public boolean isEmpty() {
0225:                // count
0226:                int count = countAllResources();
0227:                return (count == 0);
0228:            }
0229:
0230:            public List getAllResources() {
0231:                List all = new Vector();
0232:
0233:                // read all users from the db
0234:                String sql = "select XML from " + m_resourceTableName;
0235:                // %%% + "order by " + m_resourceTableOrderField + " asc";
0236:
0237:                List xml = m_sql.dbRead(sql);
0238:
0239:                // process all result xml into user objects
0240:                if (!xml.isEmpty()) {
0241:                    for (int i = 0; i < xml.size(); i++) {
0242:                        Entity entry = readResource((String) xml.get(i));
0243:                        if (entry != null)
0244:                            all.add(entry);
0245:                    }
0246:                }
0247:
0248:                return all;
0249:            }
0250:
0251:            public List getAllResources(int first, int last) {
0252:                String sql;
0253:                Object[] fields = null;
0254:                if ("oracle".equals(m_sql.getVendor())) {
0255:                    // use Oracle RANK function
0256:                    sql = "select XML from" + " (select XML" + " ,RANK() OVER"
0257:                            + " (order by " + m_resourceTableIdField
0258:                            + ") as rank" + " from " + m_resourceTableName
0259:                            + " order by " + m_resourceTableIdField + " asc)"
0260:                            + " where rank between ? and ?";
0261:                    fields = new Object[2];
0262:                    fields[0] = new Long(first);
0263:                    fields[1] = new Long(last);
0264:                } else if ("mysql".equals(m_sql.getVendor())) {
0265:                    // use MySQL SQL LIMIT clause
0266:                    sql = "select XML from " + m_resourceTableName
0267:                            + " order by " + m_resourceTableIdField + " asc "
0268:                            + " limit " + (last - first + 1) + " offset "
0269:                            + (first - 1);
0270:                } else
0271:                // if ("hsqldb".equals(m_sql.getVendor()))
0272:                {
0273:                    // use SQL2000 LIMIT clause
0274:                    sql = "select " + "limit " + (first - 1) + " "
0275:                            + (last - first + 1) + " " + "XML from "
0276:                            + m_resourceTableName + " order by "
0277:                            + m_resourceTableIdField + " asc";
0278:                }
0279:
0280:                List xml = m_sql.dbRead(sql, fields, null);
0281:                List rv = new Vector();
0282:
0283:                // process all result xml into user objects
0284:                if (!xml.isEmpty()) {
0285:                    for (int i = 0; i < xml.size(); i++) {
0286:                        Entity entry = readResource((String) xml.get(i));
0287:                        if (entry != null)
0288:                            rv.add(entry);
0289:                    }
0290:                }
0291:
0292:                return rv;
0293:            }
0294:
0295:            public int countAllResources() {
0296:                List all = new Vector();
0297:
0298:                // read all count
0299:                String sql = "select count(1) from " + m_resourceTableName;
0300:
0301:                List results = m_sql.dbRead(sql, null, new SqlReader() {
0302:                    public Object readSqlResultRecord(ResultSet result) {
0303:                        try {
0304:                            int count = result.getInt(1);
0305:                            return new Integer(count);
0306:                        } catch (SQLException ignore) {
0307:                            return null;
0308:                        }
0309:                    }
0310:                });
0311:
0312:                if (results.isEmpty())
0313:                    return 0;
0314:
0315:                return ((Integer) results.get(0)).intValue();
0316:            }
0317:
0318:            public int countSelectedResourcesWhere(String sqlWhere) {
0319:                List all = new Vector();
0320:
0321:                // read all where count
0322:                String sql = "select count(1) from " + m_resourceTableName
0323:                        + " " + sqlWhere;
0324:                List results = m_sql.dbRead(sql, null, new SqlReader() {
0325:                    public Object readSqlResultRecord(ResultSet result) {
0326:                        try {
0327:                            int count = result.getInt(1);
0328:                            return new Integer(count);
0329:                        } catch (SQLException ignore) {
0330:                            return null;
0331:                        }
0332:                    }
0333:                });
0334:
0335:                if (results.isEmpty())
0336:                    return 0;
0337:
0338:                return ((Integer) results.get(0)).intValue();
0339:            }
0340:
0341:            /**
0342:             * Get all Resources where the given field matches the given value.
0343:             * 
0344:             * @param field
0345:             *        The db field name for the selection.
0346:             * @param value
0347:             *        The value to select.
0348:             * @return The list of all Resources that meet the criteria.
0349:             */
0350:            public List getAllResourcesWhere(String field, String value) {
0351:                // read all users from the db
0352:                String sql = "select XML from " + m_resourceTableName
0353:                        + " where " + field + " = ?";
0354:                Object[] fields = new Object[1];
0355:                fields[0] = value;
0356:                // %%% + "order by " + m_resourceTableOrderField + " asc";
0357:
0358:                return loadResources(sql, fields);
0359:            }
0360:
0361:            protected List loadResources(String sql, Object[] fields) {
0362:                List all = m_sql.dbRead(sql, fields, new SqlReader() {
0363:                    public Object readSqlResultRecord(ResultSet result) {
0364:                        try {
0365:                            // create the Resource from the db xml
0366:                            String xml = result.getString(1);
0367:                            Entity entry = readResource(xml);
0368:                            return entry;
0369:                        } catch (SQLException ignore) {
0370:                            return null;
0371:                        }
0372:                    }
0373:                });
0374:                return all;
0375:            }
0376:
0377:            public List getAllResourcesWhereLike(String field, String value) {
0378:                String sql = "select XML from " + m_resourceTableName
0379:                        + " where " + field + " like ?";
0380:                Object[] fields = new Object[1];
0381:                fields[0] = value;
0382:                // %%% + "order by " + m_resourceTableOrderField + " asc";
0383:
0384:                return loadResources(sql, fields);
0385:            }
0386:
0387:            /**
0388:             * Get selected Resources, filtered by a test on the id field
0389:             * 
0390:             * @param filter
0391:             *        A filter to select what gets returned.
0392:             * @return The list of selected Resources.
0393:             */
0394:            public List getSelectedResources(final Filter filter) {
0395:                List all = new Vector();
0396:
0397:                // read all users from the db
0398:                String sql = "select " + m_resourceTableIdField + ", XML from "
0399:                        + m_resourceTableName;
0400:                // %%% + "order by " + m_resourceTableOrderField + " asc";
0401:
0402:                List xml = m_sql.dbRead(sql, null, new SqlReader() {
0403:                    public Object readSqlResultRecord(ResultSet result) {
0404:                        try {
0405:                            // read the id m_resourceTableIdField
0406:                            String id = result.getString(1);
0407:
0408:                            // read the xml
0409:                            String xml = result.getString(2);
0410:
0411:                            if (!filter.accept(caseId(id)))
0412:                                return null;
0413:
0414:                            return xml;
0415:                        } catch (SQLException ignore) {
0416:                            return null;
0417:                        }
0418:                    }
0419:                });
0420:
0421:                // process all result xml into user objects
0422:                if (!xml.isEmpty()) {
0423:                    for (int i = 0; i < xml.size(); i++) {
0424:                        Entity entry = readResource((String) xml.get(i));
0425:                        if (entry != null)
0426:                            all.add(entry);
0427:                    }
0428:                }
0429:
0430:                return all;
0431:            }
0432:
0433:            /**
0434:             * Get selected Resources, using a supplied where clause
0435:             * 
0436:             * @param sqlWhere
0437:             *        The SQL where clause.
0438:             * @return The list of selected Resources.
0439:             */
0440:            public List getSelectedResourcesWhere(String sqlWhere) {
0441:                List all = new Vector();
0442:
0443:                // read all users from the db
0444:                String sql = "select XML from " + m_resourceTableName + " "
0445:                        + sqlWhere;
0446:                // %%% + "order by " + m_resourceTableOrderField + " asc";
0447:
0448:                List xml = m_sql.dbRead(sql);
0449:
0450:                // process all result xml into user objects
0451:                if (!xml.isEmpty()) {
0452:                    for (int i = 0; i < xml.size(); i++) {
0453:                        Entity entry = readResource((String) xml.get(i));
0454:                        if (entry != null)
0455:                            all.add(entry);
0456:                    }
0457:                }
0458:
0459:                return all;
0460:            }
0461:
0462:            /**
0463:             * Add a new Resource with this id.
0464:             * 
0465:             * @param id
0466:             *        The id.
0467:             * @param others
0468:             *        Other fields for the newResource call
0469:             * @return The locked Resource object with this id, or null if the id is in use.
0470:             */
0471:            public Edit putResource(String id, Object[] others) {
0472:                // create one with just the id, and perhaps some other fields as well
0473:                Entity entry = m_user.newResource(null, id, others);
0474:
0475:                // form the XML and SQL for the insert
0476:                Document doc = Xml.createDocument();
0477:                entry.toXml(doc, new Stack());
0478:                String xml = Xml.writeDocumentToString(doc);
0479:                String statement = "insert into "
0480:                        + m_resourceTableName
0481:                        + insertFields(m_resourceTableIdField,
0482:                                m_resourceTableOtherFields, "XML")
0483:                        + " values ( ?, "
0484:                        + valuesParams(m_resourceTableOtherFields) + " ? )";
0485:
0486:                Object[] flds = m_user.storageFields(entry);
0487:                if (flds == null)
0488:                    flds = new Object[0];
0489:                Object[] fields = new Object[flds.length + 2];
0490:                System.arraycopy(flds, 0, fields, 1, flds.length);
0491:                fields[0] = caseId(entry.getId());
0492:                fields[fields.length - 1] = xml;
0493:
0494:                // process the insert
0495:                boolean ok = m_sql.dbWrite(statement, fields);
0496:
0497:                // if this failed, assume a key conflict (i.e. id in use)
0498:                if (!ok)
0499:                    return null;
0500:
0501:                // now get a lock on the record for edit
0502:                Edit edit = editResource(id);
0503:                if (edit == null) {
0504:                    M_log.warn("putResource(): didn't get a lock!");
0505:                    return null;
0506:                }
0507:
0508:                return edit;
0509:            }
0510:
0511:            /** store the record in content_resource_delete table along with resource_uuid and date */
0512:            public Edit putDeleteResource(String id, String uuid,
0513:                    String userId, Object[] others) {
0514:                Entity entry = m_user.newResource(null, id, others);
0515:
0516:                // form the XML and SQL for the insert
0517:                Document doc = Xml.createDocument();
0518:                entry.toXml(doc, new Stack());
0519:                String xml = Xml.writeDocumentToString(doc);
0520:                String statement = "insert into "
0521:                        + m_resourceTableName
0522:                        + insertDeleteFields(m_resourceTableIdField,
0523:                                m_resourceTableOtherFields, "RESOURCE_UUID",
0524:                                "DELETE_DATE", "DELETE_USERID", "XML")
0525:                        + " values ( ?, "
0526:                        + valuesParams(m_resourceTableOtherFields)
0527:                        + " ? ,? ,? ,?)";
0528:
0529:                Object[] flds = m_user.storageFields(entry);
0530:                if (flds == null)
0531:                    flds = new Object[0];
0532:                Object[] fields = new Object[flds.length + 5];
0533:                System.arraycopy(flds, 0, fields, 1, flds.length);
0534:                fields[0] = caseId(entry.getId());
0535:                // uuid added here
0536:                fields[fields.length - 4] = uuid;
0537:                // date added here
0538:                fields[fields.length - 3] = TimeService.newTime();// .toStringLocalDate();
0539:
0540:                // userId added here
0541:                fields[fields.length - 2] = userId;
0542:                fields[fields.length - 1] = xml;
0543:
0544:                // process the insert
0545:                boolean ok = m_sql.dbWrite(statement, fields);
0546:
0547:                // if this failed, assume a key conflict (i.e. id in use)
0548:                if (!ok)
0549:                    return null;
0550:
0551:                // now get a lock on the record for edit
0552:                Edit edit = editResource(id);
0553:                if (edit == null) {
0554:                    M_log.warn("putResourceDelete(): didn't get a lock!");
0555:                    return null;
0556:                }
0557:
0558:                return edit;
0559:            }
0560:
0561:            /** Construct the SQL statement */
0562:            protected String insertDeleteFields(String before, String[] fields,
0563:                    String uuid, String date, String userId, String after) {
0564:                StringBuffer buf = new StringBuffer();
0565:                buf.append(" (");
0566:                buf.append(before);
0567:                buf.append(",");
0568:                if (fields != null) {
0569:                    for (int i = 0; i < fields.length; i++) {
0570:                        buf.append(fields[i] + ",");
0571:                    }
0572:                }
0573:                buf.append(uuid);
0574:                buf.append(",");
0575:                buf.append(date);
0576:                buf.append(",");
0577:                buf.append(userId);
0578:                buf.append(",");
0579:                buf.append(after);
0580:                buf.append(")");
0581:
0582:                return buf.toString();
0583:            }
0584:
0585:            /** update XML attribute on properties and remove locks */
0586:            public void commitDeleteResource(Edit edit, String uuid) {
0587:                // form the SQL statement and the var w/ the XML
0588:                Document doc = Xml.createDocument();
0589:                edit.toXml(doc, new Stack());
0590:                String xml = Xml.writeDocumentToString(doc);
0591:                Object[] flds = m_user.storageFields(edit);
0592:                if (flds == null)
0593:                    flds = new Object[0];
0594:                Object[] fields = new Object[flds.length + 2];
0595:                System.arraycopy(flds, 0, fields, 0, flds.length);
0596:                fields[fields.length - 2] = xml;
0597:                fields[fields.length - 1] = uuid;// caseId(edit.getId());
0598:
0599:                String statement = "update " + m_resourceTableName + " set "
0600:                        + updateSet(m_resourceTableOtherFields) + " XML = ?"
0601:                        + " where ( RESOURCE_UUID = ? )";
0602:
0603:                if (m_locksAreInDb) {
0604:                    // use this connection that is stored with the lock
0605:                    Connection lock = (Connection) m_locks.get(edit
0606:                            .getReference());
0607:                    if (lock == null) {
0608:                        M_log.warn("commitResource(): edit not in locks");
0609:                        return;
0610:                    }
0611:                    // update, commit, release the lock's connection
0612:                    m_sql.dbUpdateCommit(statement, fields, null, lock);
0613:                    // remove the lock
0614:                    m_locks.remove(edit.getReference());
0615:                }
0616:
0617:                else if (m_locksAreInTable) {
0618:                    // process the update
0619:                    m_sql.dbWrite(statement, fields);
0620:
0621:                    // remove the lock
0622:                    statement = "delete from SAKAI_LOCKS where TABLE_NAME = ? and RECORD_ID = ?";
0623:
0624:                    // collect the fields
0625:                    Object lockFields[] = new Object[2];
0626:                    lockFields[0] = m_resourceTableName;
0627:                    lockFields[1] = internalRecordId(caseId(edit.getId()));
0628:                    boolean ok = m_sql.dbWrite(statement, lockFields);
0629:                    if (!ok) {
0630:                        M_log.warn("commit: missing lock for table: "
0631:                                + lockFields[0] + " key: " + lockFields[1]);
0632:                    }
0633:                } else {
0634:                    // just process the update
0635:                    m_sql.dbWrite(statement, fields);
0636:
0637:                    // remove the lock
0638:                    m_locks.remove(edit.getReference());
0639:                }
0640:            }
0641:
0642:            /**
0643:             * Get a lock on the Resource with this id, or null if a lock cannot be gotten.
0644:             * 
0645:             * @param id
0646:             *        The user id.
0647:             * @return The locked Resource with this id, or null if this records cannot be locked.
0648:             */
0649:            public Edit editResource(String id) {
0650:                Edit edit = null;
0651:
0652:                if (m_locksAreInDb) {
0653:                    if ("oracle".equals(m_sql.getVendor())) {
0654:                        // read the record and get a lock on it (non blocking)
0655:                        String statement = "select XML from "
0656:                                + m_resourceTableName + " where ( "
0657:                                + m_resourceTableIdField + " = '"
0658:                                + Validator.escapeSql(caseId(id)) + "' )"
0659:                                + " for update nowait";
0660:                        StringBuffer result = new StringBuffer();
0661:                        Connection lock = m_sql.dbReadLock(statement, result);
0662:
0663:                        // for missing or already locked...
0664:                        if ((lock == null) || (result.length() == 0))
0665:                            return null;
0666:
0667:                        // make first a Resource, then an Edit
0668:                        Entity entry = readResource(result.toString());
0669:                        edit = m_user.newResourceEdit(null, entry);
0670:
0671:                        // store the lock for this object
0672:                        m_locks.put(entry.getReference(), lock);
0673:                    } else {
0674:                        throw new UnsupportedOperationException(
0675:                                "Record locking only available when configured with Oracle database");
0676:                    }
0677:                }
0678:
0679:                // if the locks are in a separate table in the db
0680:                else if (m_locksAreInTable) {
0681:                    // read the record - fail if not there
0682:                    Entity entry = getResource(id);
0683:                    if (entry == null)
0684:                        return null;
0685:
0686:                    // write a lock to the lock table - if we can do it, we get the lock
0687:                    String statement = "insert into SAKAI_LOCKS"
0688:                            + " (TABLE_NAME,RECORD_ID,LOCK_TIME,USAGE_SESSION_ID)"
0689:                            + " values (?, ?, ?, ?)";
0690:
0691:                    // we need session id and user id
0692:                    String sessionId = UsageSessionService.getSessionId();
0693:                    if (sessionId == null) {
0694:                        sessionId = "";
0695:                    }
0696:
0697:                    // collect the fields
0698:                    Object fields[] = new Object[4];
0699:                    fields[0] = m_resourceTableName;
0700:                    fields[1] = internalRecordId(caseId(id));
0701:                    fields[2] = TimeService.newTime();
0702:                    fields[3] = sessionId;
0703:
0704:                    // add the lock - if fails, someone else has the lock
0705:                    boolean ok = m_sql
0706:                            .dbWriteFailQuiet(null, statement, fields);
0707:                    if (!ok) {
0708:                        return null;
0709:                    }
0710:
0711:                    // we got the lock! - make the edit from the Resource
0712:                    edit = m_user.newResourceEdit(null, entry);
0713:                }
0714:
0715:                // otherwise, get the lock locally
0716:                else {
0717:                    // get the entry, and check for existence
0718:                    Entity entry = getResource(id);
0719:                    if (entry == null)
0720:                        return null;
0721:
0722:                    // we only sync this getting - someone may release a lock out of sync
0723:                    synchronized (m_locks) {
0724:                        // if already locked
0725:                        if (m_locks.containsKey(entry.getReference()))
0726:                            return null;
0727:
0728:                        // make the edit from the Resource
0729:                        edit = m_user.newResourceEdit(null, entry);
0730:
0731:                        // store the edit in the locks by reference
0732:                        m_locks.put(entry.getReference(), edit);
0733:                    }
0734:                }
0735:
0736:                return edit;
0737:            }
0738:
0739:            /**
0740:             * Commit the changes and release the lock.
0741:             * 
0742:             * @param user
0743:             *        The Edit to commit.
0744:             */
0745:            public void commitResource(Edit edit) {
0746:                // form the SQL statement and the var w/ the XML
0747:                Document doc = Xml.createDocument();
0748:                edit.toXml(doc, new Stack());
0749:                String xml = Xml.writeDocumentToString(doc);
0750:                Object[] flds = m_user.storageFields(edit);
0751:                if (flds == null)
0752:                    flds = new Object[0];
0753:                Object[] fields = new Object[flds.length + 2];
0754:                System.arraycopy(flds, 0, fields, 0, flds.length);
0755:                fields[fields.length - 2] = xml;
0756:                fields[fields.length - 1] = caseId(edit.getId());
0757:
0758:                String statement = "update " + m_resourceTableName + " set "
0759:                        + updateSet(m_resourceTableOtherFields) + " XML = ?"
0760:                        + " where ( " + m_resourceTableIdField + " = ? )";
0761:
0762:                if (m_locksAreInDb) {
0763:                    // use this connection that is stored with the lock
0764:                    Connection lock = (Connection) m_locks.get(edit
0765:                            .getReference());
0766:                    if (lock == null) {
0767:                        M_log.warn("commitResource(): edit not in locks");
0768:                        return;
0769:                    }
0770:
0771:                    // update, commit, release the lock's connection
0772:                    m_sql.dbUpdateCommit(statement, fields, null, lock);
0773:
0774:                    // remove the lock
0775:                    m_locks.remove(edit.getReference());
0776:                }
0777:
0778:                else if (m_locksAreInTable) {
0779:                    // process the update
0780:                    m_sql.dbWrite(statement, fields);
0781:
0782:                    // remove the lock
0783:                    statement = "delete from SAKAI_LOCKS where TABLE_NAME = ? and RECORD_ID = ?";
0784:
0785:                    // collect the fields
0786:                    Object lockFields[] = new Object[2];
0787:                    lockFields[0] = m_resourceTableName;
0788:                    lockFields[1] = internalRecordId(caseId(edit.getId()));
0789:                    boolean ok = m_sql.dbWrite(statement, lockFields);
0790:                    if (!ok) {
0791:                        M_log.warn("commit: missing lock for table: "
0792:                                + lockFields[0] + " key: " + lockFields[1]);
0793:                    }
0794:                }
0795:
0796:                else {
0797:                    // just process the update
0798:                    m_sql.dbWrite(statement, fields);
0799:
0800:                    // remove the lock
0801:                    m_locks.remove(edit.getReference());
0802:                }
0803:            }
0804:
0805:            /**
0806:             * Cancel the changes and release the lock.
0807:             * 
0808:             * @param user
0809:             *        The Edit to cancel.
0810:             */
0811:            public void cancelResource(Edit edit) {
0812:                if (m_locksAreInDb) {
0813:                    // use this connection that is stored with the lock
0814:                    Connection lock = (Connection) m_locks.get(edit
0815:                            .getReference());
0816:                    if (lock == null) {
0817:                        M_log.warn("cancelResource(): edit not in locks");
0818:                        return;
0819:                    }
0820:
0821:                    // rollback and release the lock's connection
0822:                    m_sql.dbCancel(lock);
0823:
0824:                    // release the lock
0825:                    m_locks.remove(edit.getReference());
0826:                }
0827:
0828:                else if (m_locksAreInTable) {
0829:                    // remove the lock
0830:                    String statement = "delete from SAKAI_LOCKS where TABLE_NAME = ? and RECORD_ID = ?";
0831:
0832:                    // collect the fields
0833:                    Object lockFields[] = new Object[2];
0834:                    lockFields[0] = m_resourceTableName;
0835:                    lockFields[1] = internalRecordId(caseId(edit.getId()));
0836:                    boolean ok = m_sql.dbWrite(statement, lockFields);
0837:                    if (!ok) {
0838:                        M_log.warn("cancel: missing lock for table: "
0839:                                + lockFields[0] + " key: " + lockFields[1]);
0840:                    }
0841:                }
0842:
0843:                else {
0844:                    // release the lock
0845:                    m_locks.remove(edit.getReference());
0846:                }
0847:            }
0848:
0849:            /**
0850:             * Remove this (locked) Resource.
0851:             * 
0852:             * @param user
0853:             *        The Edit to remove.
0854:             */
0855:            public void removeResource(Edit edit) {
0856:                // form the SQL delete statement
0857:                String statement = "delete from " + m_resourceTableName
0858:                        + " where ( " + m_resourceTableIdField + " = ? )";
0859:
0860:                Object fields[] = new Object[1];
0861:                fields[0] = caseId(edit.getId());
0862:
0863:                if (m_locksAreInDb) {
0864:                    // use this connection that is stored with the lock
0865:                    Connection lock = (Connection) m_locks.get(edit
0866:                            .getReference());
0867:                    if (lock == null) {
0868:                        M_log.warn("removeResource(): edit not in locks");
0869:                        return;
0870:                    }
0871:
0872:                    // process the delete statement, commit, and release the lock's connection
0873:                    m_sql.dbUpdateCommit(statement, fields, null, lock);
0874:
0875:                    // release the lock
0876:                    m_locks.remove(edit.getReference());
0877:                }
0878:
0879:                else if (m_locksAreInTable) {
0880:                    // process the delete statement
0881:                    m_sql.dbWrite(statement, fields);
0882:
0883:                    // remove the lock
0884:                    statement = "delete from SAKAI_LOCKS where TABLE_NAME = ? and RECORD_ID = ?";
0885:
0886:                    // collect the fields
0887:                    Object lockFields[] = new Object[2];
0888:                    lockFields[0] = m_resourceTableName;
0889:                    lockFields[1] = internalRecordId(caseId(edit.getId()));
0890:                    boolean ok = m_sql.dbWrite(statement, lockFields);
0891:                    if (!ok) {
0892:                        M_log.warn("remove: missing lock for table: "
0893:                                + lockFields[0] + " key: " + lockFields[1]);
0894:                    }
0895:                }
0896:
0897:                else {
0898:                    // process the delete statement
0899:                    m_sql.dbWrite(statement, fields);
0900:
0901:                    // release the lock
0902:                    m_locks.remove(edit.getReference());
0903:                }
0904:            }
0905:
0906:            /**
0907:             * Form a string of n question marks with commas, for sql value statements, one for each item in the values array, or an empty string if null.
0908:             * 
0909:             * @param values
0910:             *        The values to be inserted into the sql statement.
0911:             * @return A sql statement fragment for the values part of an insert, one for each value in the array.
0912:             */
0913:            protected String valuesParams(String[] fields) {
0914:                if ((fields == null) || (fields.length == 0))
0915:                    return "";
0916:                StringBuffer buf = new StringBuffer();
0917:                for (int i = 0; i < fields.length; i++) {
0918:                    buf.append(" ?,");
0919:                }
0920:                return buf.toString();
0921:            }
0922:
0923:            /**
0924:             * Form a string of n name=?, for sql update set statements, one for each item in the values array, or an empty string if null.
0925:             * 
0926:             * @param values
0927:             *        The values to be inserted into the sql statement.
0928:             * @return A sql statement fragment for the values part of an insert, one for each value in the array.
0929:             */
0930:            protected String updateSet(String[] fields) {
0931:                if ((fields == null) || (fields.length == 0))
0932:                    return "";
0933:                StringBuffer buf = new StringBuffer();
0934:                for (int i = 0; i < fields.length; i++) {
0935:                    buf.append(fields[i] + " = ?,");
0936:                }
0937:                return buf.toString();
0938:            }
0939:
0940:            /**
0941:             * Form a string of (field, field, field), for sql insert statements, one for each item in the fields array, plus one before, and one after.
0942:             * 
0943:             * @param before
0944:             *        The first field name.
0945:             * @param values
0946:             *        The extra field names, in the middle.
0947:             * @param after
0948:             *        The last field name.
0949:             * @return A sql statement fragment for the insert fields.
0950:             */
0951:            protected String insertFields(String before, String[] fields,
0952:                    String after) {
0953:                StringBuffer buf = new StringBuffer();
0954:                buf.append(" (");
0955:
0956:                buf.append(before);
0957:                buf.append(",");
0958:
0959:                if (fields != null) {
0960:                    for (int i = 0; i < fields.length; i++) {
0961:                        buf.append(fields[i] + ",");
0962:                    }
0963:                }
0964:
0965:                buf.append(after);
0966:
0967:                buf.append(")");
0968:
0969:                return buf.toString();
0970:            }
0971:
0972:            /**
0973:             * Fix the case of resource ids to support case insensitive ids if enabled
0974:             * 
0975:             * @param The
0976:             *        id to fix.
0977:             * @return The id, case modified as needed.
0978:             */
0979:            protected String caseId(String id) {
0980:                if (m_caseInsensitive) {
0981:                    return id.toLowerCase();
0982:                }
0983:
0984:                return id;
0985:            }
0986:
0987:            /**
0988:             * Enable / disable case insensitive ids.
0989:             * 
0990:             * @param setting
0991:             *        true to set case insensitivity, false to set case sensitivity.
0992:             */
0993:            protected void setCaseInsensitivity(boolean setting) {
0994:                m_caseInsensitive = setting;
0995:            }
0996:
0997:            /**
0998:             * Return a record ID to use internally in the database. This is needed for databases (MySQL) that have limits on key lengths. The hash code ensures that the record ID will be unique, even if the DB only considers a prefix of a very long record ID.
0999:             * 
1000:             * @param recordId
1001:             * @return The record ID to use internally in the database
1002:             */
1003:            private String internalRecordId(String recordId) {
1004:                if ("mysql".equals(m_sql.getVendor())) {
1005:                    if (recordId == null)
1006:                        recordId = "null";
1007:                    return recordId.hashCode() + " - " + recordId;
1008:                } else
1009:                // oracle, hsqldb
1010:                {
1011:                    return recordId;
1012:                }
1013:            }
1014:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.