Source Code Cross Referenced for TriggerDef.java in  » Database-DBMS » hsql » org » hsqldb » 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 » Database DBMS » hsql » org.hsqldb 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /* Copyright (c) 2001-2005, The HSQL Development Group
002:         * All rights reserved.
003:         *
004:         * Redistribution and use in source and binary forms, with or without
005:         * modification, are permitted provided that the following conditions are met:
006:         *
007:         * Redistributions of source code must retain the above copyright notice, this
008:         * list of conditions and the following disclaimer.
009:         *
010:         * Redistributions in binary form must reproduce the above copyright notice,
011:         * this list of conditions and the following disclaimer in the documentation
012:         * and/or other materials provided with the distribution.
013:         *
014:         * Neither the name of the HSQL Development Group nor the names of its
015:         * contributors may be used to endorse or promote products derived from this
016:         * software without specific prior written permission.
017:         *
018:         * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
019:         * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
020:         * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
021:         * ARE DISCLAIMED. IN NO EVENT SHALL HSQL DEVELOPMENT GROUP, HSQLDB.ORG,
022:         * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
023:         * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
024:         * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
025:         * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
026:         * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
027:         * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
028:         * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
029:         */
030:
031:        package org.hsqldb;
032:
033:        import org.hsqldb.HsqlNameManager.HsqlName;
034:        import org.hsqldb.lib.HsqlDeque;
035:        import org.hsqldb.lib.StringConverter;
036:        import org.hsqldb.lib.StringUtil;
037:
038:        // peterhudson@users 20020130 - patch 478657 by peterhudson - triggers support
039:        // fredt@users 20020130 - patch 1.7.0 by fredt
040:        // added new class as jdk 1.1 does not allow use of LinkedList
041:        // fredt@users 20030727 - signature and other alterations
042:        // fredt@users 20040430 - changes by mattshaw@users to allow termination of the
043:        // trigger thread -
044:
045:        /**
046:         *  Represents an HSQLDB Trigger definition. <p>
047:         *
048:         *  Provides services regarding HSLDB Trigger execution and metadata. <p>
049:         *
050:         *  Development of the trigger implementation sponsored by Logicscope
051:         *  Realisations Ltd
052:         *
053:         * @author Peter Hudson - Logicscope Realisations Ltd
054:         * @version  1.7.0 (1.0.0.3)
055:         *      Revision History: 1.0.0.1 First release in hsqldb 1.61
056:         *      1.0.0.2 'nowait' support to prevent deadlock 1.0.0.3 multiple row
057:         *      queue for each trigger
058:         */
059:        class TriggerDef extends Thread {
060:
061:            /**
062:             *  member variables
063:             */
064:            static final int NUM_TRIGGER_OPS = 3; // {ins,del,upd}
065:            static final int NUM_TRIGS = NUM_TRIGGER_OPS * 2 * 2; // {b, a},{fer, fes}
066:
067:            // other variables
068:            HsqlName name;
069:            String when;
070:            String operation;
071:            boolean forEachRow;
072:            boolean nowait; // block or overwrite if queue full
073:            int maxRowsQueued; // max size of queue of pending triggers
074:
075:            /**
076:             *  Retrieves the queue size assigned to trigger definitions when no
077:             *  queue size is explicitly declared. <p>
078:             *
079:             * @return the queue size assigned to trigger definitions when no
080:             *      queue size is explicitly declared
081:             */
082:            public static int getDefaultQueueSize() {
083:                return defaultQueueSize;
084:            }
085:
086:            protected static int defaultQueueSize = 1024;
087:            Table table;
088:            Trigger trigger;
089:            String triggerClassName;
090:            int vectorIndex; // index into HsqlArrayList[]
091:
092:            //protected boolean busy;               // firing trigger in progress
093:            protected HsqlDeque pendingQueue; // row triggers pending
094:            protected int rowsQueued; // rows in pendingQueue
095:            protected boolean valid = true; // parsing valid
096:            protected volatile boolean keepGoing = true;
097:
098:            /**
099:             *  Constructs a new TriggerDef object to represent an HSQLDB trigger
100:             *  declared in an SQL CREATE TRIGGER statement.
101:             *
102:             *  Changes in 1.7.2 allow the queue size to be specified as 0. A zero
103:             *  queue size causes the Trigger.fire() code to run in the main thread of
104:             *  execution (fully inside the enclosing transaction). Otherwise, the code
105:             *  is run in the Trigger's own thread.
106:             *  (fredt@users)
107:             *
108:             * @param  name The trigger object's HsqlName
109:             * @param  when the String representation of whether the trigger fires
110:             *      before or after the triggering event
111:             * @param  operation the String representation of the triggering operation;
112:             *      currently insert, update, or delete
113:             * @param  forEach indicates whether the trigger is fired for each row
114:             *      (true) or statement (false)
115:             * @param  table the Table object upon which the indicated operation
116:             *      fires the trigger
117:             * @param  triggerClassName the fully qualified named of the class implementing
118:             *      the org.hsqldb.Trigger (trigger body) interface
119:             * @param  noWait do not wait for available space on the pending queue; if
120:             *      the pending queue does not have fewer than nQueueSize queued items,
121:             *      then overwrite the current tail instead
122:             * @param  queueSize the length to which the pending queue may grow before
123:             *      further additions are either blocked or overwrite the tail entry,
124:             *      as determined by noWait
125:             * @throws HsqlException - Invalid input parameter
126:             */
127:            public TriggerDef(HsqlNameManager.HsqlName name, String when,
128:                    String operation, boolean forEach, Table table,
129:                    String triggerClassName, boolean noWait, int queueSize,
130:                    ClassLoader loader) throws HsqlException {
131:
132:                this .name = name;
133:                this .when = when;
134:                this .operation = operation;
135:                this .forEachRow = forEach;
136:                this .nowait = noWait;
137:                this .maxRowsQueued = queueSize;
138:                this .table = table;
139:                vectorIndex = SqlToIndex();
140:                this .triggerClassName = triggerClassName;
141:                rowsQueued = 0;
142:                pendingQueue = new HsqlDeque();
143:
144:                if (vectorIndex < 0) {
145:                    throw Trace.error(Trace.UNEXPECTED_TOKEN,
146:                            Trace.CREATE_TRIGGER_COMMAND_1);
147:                }
148:
149:                Class cl;
150:
151:                try {
152:                    cl = loader == null ? Class.forName(triggerClassName)
153:                            : loader.loadClass(triggerClassName);
154:                } catch (ClassNotFoundException e) {
155:                    valid = false;
156:                    cl = DefaultTrigger.class;
157:                }
158:
159:                try {
160:
161:                    // dynamically instantiate it
162:                    trigger = (Trigger) cl.newInstance();
163:                } catch (Exception e) {
164:                    valid = false;
165:                    cl = DefaultTrigger.class;
166:                }
167:            }
168:
169:            /**
170:             *  Retrieves the SQL character sequence required to (re)create the
171:             *  trigger, as a StringBuffer
172:             *
173:             * @return the SQL character sequence required to (re)create the
174:             *  trigger
175:             */
176:            public StringBuffer getDDL() {
177:
178:                StringBuffer a = new StringBuffer(256);
179:
180:                a.append(Token.T_CREATE).append(' ');
181:                a.append(Token.T_TRIGGER).append(' ');
182:                a.append(name.statementName).append(' ');
183:                a.append(when).append(' ');
184:                a.append(operation).append(' ');
185:                a.append(Token.T_ON).append(' ');
186:                a.append(table.getName().statementName).append(' ');
187:
188:                if (forEachRow) {
189:                    a.append(Token.T_FOR).append(' ');
190:                    a.append(Token.T_EACH).append(' ');
191:                    a.append(Token.T_ROW).append(' ');
192:                }
193:
194:                if (nowait) {
195:                    a.append(Token.T_NOWAIT).append(' ');
196:                }
197:
198:                if (maxRowsQueued != getDefaultQueueSize()) {
199:                    a.append(Token.T_QUEUE).append(' ');
200:                    a.append(maxRowsQueued).append(' ');
201:                }
202:
203:                a.append(Token.T_CALL).append(' ');
204:                a.append(StringConverter.toQuotedString(triggerClassName, '"',
205:                        false));
206:
207:                return a;
208:            }
209:
210:            /**
211:             *  SqlToIndex method declaration <P>
212:             *
213:             *  Given the SQL creating the trigger, say what the index to the
214:             *  HsqlArrayList[] is
215:             *
216:             * @return  index to the HsqlArrayList[]
217:             */
218:            public int SqlToIndex() {
219:
220:                int indx;
221:
222:                if (operation.equals(Token.T_INSERT)) {
223:                    indx = Trigger.INSERT_AFTER;
224:                } else if (operation.equals(Token.T_DELETE)) {
225:                    indx = Trigger.DELETE_AFTER;
226:                } else if (operation.equals(Token.T_UPDATE)) {
227:                    indx = Trigger.UPDATE_AFTER;
228:                } else {
229:                    return -1;
230:                }
231:
232:                if (when.equals(Token.T_BEFORE)) {
233:                    indx += NUM_TRIGGER_OPS; // number of operations
234:                } else if (!when.equals(Token.T_AFTER)) {
235:                    return -1;
236:                }
237:
238:                if (forEachRow) {
239:                    indx += 2 * NUM_TRIGGER_OPS;
240:                }
241:
242:                return indx;
243:            }
244:
245:            public static int indexToRight(int idx) {
246:
247:                switch (idx) {
248:
249:                case Trigger.DELETE_AFTER:
250:                case Trigger.DELETE_AFTER_ROW:
251:                case Trigger.DELETE_BEFORE:
252:                case Trigger.DELETE_BEFORE_ROW:
253:                    return UserManager.DELETE;
254:
255:                case Trigger.INSERT_AFTER:
256:                case Trigger.INSERT_AFTER_ROW:
257:                case Trigger.INSERT_BEFORE:
258:                case Trigger.INSERT_BEFORE_ROW:
259:                    return UserManager.INSERT;
260:
261:                case Trigger.UPDATE_AFTER:
262:                case Trigger.UPDATE_AFTER_ROW:
263:                case Trigger.UPDATE_BEFORE:
264:                case Trigger.UPDATE_BEFORE_ROW:
265:                    return UserManager.UPDATE;
266:
267:                default:
268:                    return 0;
269:                }
270:            }
271:
272:            /**
273:             *  run method declaration <P>
274:             *
275:             *  the trigger JSP is run in its own thread here. Its job is simply to
276:             *  wait until it is told by the main thread that it should fire the
277:             *  trigger.
278:             */
279:            public void run() {
280:
281:                while (keepGoing) {
282:                    TriggerData triggerData = popPair();
283:
284:                    if (triggerData != null) {
285:                        if (triggerData.username != null) {
286:                            trigger.fire(this .vectorIndex, name.name, table
287:                                    .getName().name, triggerData.oldRow,
288:                                    triggerData.newRow);
289:                        }
290:                    }
291:                }
292:            }
293:
294:            /**
295:             * start the thread if this is threaded
296:             */
297:            public synchronized void start() {
298:
299:                if (maxRowsQueued != 0) {
300:                    super .start();
301:                }
302:            }
303:
304:            /**
305:             * signal the thread to stop
306:             */
307:            public synchronized void terminate() {
308:
309:                keepGoing = false;
310:
311:                notify();
312:            }
313:
314:            /**
315:             *  pop2 method declaration <P>
316:             *
317:             *  The consumer (trigger) thread waits for an event to be queued <P>
318:             *
319:             *  <B>Note: </B> This push/pop pairing assumes a single producer thread
320:             *  and a single consumer thread _only_.
321:             *
322:             * @return  Description of the Return Value
323:             */
324:            synchronized TriggerData popPair() {
325:
326:                if (rowsQueued == 0) {
327:                    try {
328:                        wait(); // this releases the lock monitor
329:                    } catch (InterruptedException e) {
330:
331:                        /* ignore and resume */
332:                    }
333:                }
334:
335:                rowsQueued--;
336:
337:                notify(); // notify push's wait
338:
339:                if (pendingQueue.size() == 0) {
340:                    return null;
341:                } else {
342:                    return (TriggerData) pendingQueue.removeFirst();
343:                }
344:            }
345:
346:            /**
347:             *  The main thread tells the trigger thread to fire by this call.
348:             *  If this Trigger is not threaded then the fire method is caled
349:             *  immediately and executed by the main thread. Otherwise, the row
350:             *  data objects are added to the queue to be used by the Trigger thread.
351:             *
352:             * @param  row1
353:             * @param  row2
354:             */
355:            synchronized void pushPair(Session session, Object[] row1,
356:                    Object[] row2) {
357:
358:                if (maxRowsQueued == 0) {
359:                    trigger.fire(vectorIndex, name.name, table.getName().name,
360:                            row1, row2);
361:
362:                    return;
363:                }
364:
365:                if (rowsQueued >= maxRowsQueued) {
366:                    if (nowait) {
367:                        pendingQueue.removeLast(); // overwrite last
368:                    } else {
369:                        try {
370:                            wait();
371:                        } catch (InterruptedException e) {
372:
373:                            /* ignore and resume */
374:                        }
375:
376:                        rowsQueued++;
377:                    }
378:                } else {
379:                    rowsQueued++;
380:                }
381:
382:                pendingQueue.add(new TriggerData(session, row1, row2));
383:                notify(); // notify pop's wait
384:            }
385:
386:            /**
387:             *  Method declaration
388:             *
389:             * @return
390:             */
391:            public boolean isBusy() {
392:                return rowsQueued != 0;
393:            }
394:
395:            /**
396:             *  Method declaration
397:             *
398:             * @return
399:             */
400:            public boolean isValid() {
401:                return valid;
402:            }
403:
404:            /**
405:             * Class to store the data used to fire a trigger. The username attribute
406:             * is not used but it allows developers to change the signature of the
407:             * fire method of the Trigger class and pass the user name to the Trigger.
408:             */
409:            class TriggerData {
410:
411:                public Object[] oldRow;
412:                public Object[] newRow;
413:                public String username;
414:
415:                public TriggerData(Session session, Object[] oldRow,
416:                        Object[] newRow) {
417:
418:                    this .oldRow = oldRow;
419:                    this .newRow = newRow;
420:                    this .username = session.getUsername();
421:                }
422:            }
423:
424:            static class DefaultTrigger implements  org.hsqldb.Trigger {
425:
426:                public void fire(int i, String name, String table,
427:                        Object[] row1, Object[] row2) {
428:                    throw new RuntimeException("Missing Trigger class!");
429:                }
430:            }
431:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.