Source Code Cross Referenced for CommandExecutor.java in  » Ajax » GWT » com » google » gwt » user » client » 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 » Ajax » GWT » com.google.gwt.user.client 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*
002:         * Copyright 2007 Google Inc.
003:         * 
004:         * Licensed under the Apache License, Version 2.0 (the "License"); you may not
005:         * use this file except in compliance with the License. You may obtain a copy of
006:         * the License at
007:         * 
008:         * http://www.apache.org/licenses/LICENSE-2.0
009:         * 
010:         * Unless required by applicable law or agreed to in writing, software
011:         * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
012:         * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
013:         * License for the specific language governing permissions and limitations under
014:         * the License.
015:         */
016:        package com.google.gwt.user.client;
017:
018:        import com.google.gwt.core.client.GWT;
019:        import com.google.gwt.core.client.GWT.UncaughtExceptionHandler;
020:
021:        import java.util.ArrayList;
022:        import java.util.Iterator;
023:        import java.util.List;
024:
025:        /**
026:         * Class which executes {@link Command}s and {@link IncrementalCommand}s after
027:         * all currently pending event handlers have completed. This class attempts to
028:         * protect against slow script warnings by running commands in small time
029:         * increments.
030:         * 
031:         * <p>
032:         * It is still possible that a poorly written command could cause a slow script
033:         * warning which a user may choose to cancel. In that event, a
034:         * {@link CommandCanceledException} or an
035:         * {@link IncrementalCommandCanceledException} is reported through the current
036:         * {@link UncaughtExceptionHandler} depending on the type of command which
037:         * caused the warning. All other commands will continue to be executed.
038:         * </p>
039:         * 
040:         * TODO(mmendez): Can an SSW be detected without using a timer? Currently, if a
041:         * {@link Command} or an {@link IncrementalCommand} calls either
042:         * {@link Window#alert(String)} or the JavaScript <code>alert(String)</code>
043:         * methods directly or indirectly then the {@link #cancellationTimer} can fire,
044:         * resulting in a false SSW cancellation detection.
045:         */
046:        class CommandExecutor {
047:
048:            /**
049:             * A circular iterator used by this class. This iterator will wrap back to
050:             * zero when it hits the end of the commands.
051:             */
052:            private class CircularIterator implements  Iterator<Object> {
053:                /**
054:                 * Index of the element where this iterator should wrap back to the
055:                 * beginning of the collection.
056:                 */
057:                private int end;
058:
059:                /**
060:                 * Index of the last item returned by {@link #next()}.
061:                 */
062:                private int last = -1;
063:
064:                /**
065:                 * Index of the next command to execute.
066:                 */
067:                private int next = 0;
068:
069:                /**
070:                 * Returns <code>true</code> if there are more commands in the queue.
071:                 * 
072:                 * @return <code>true</code> if there are more commands in the queue.
073:                 */
074:                public boolean hasNext() {
075:                    return next < end;
076:                }
077:
078:                /**
079:                 * Returns the next command from the queue. When the end of the dispatch
080:                 * region is reached it will wrap back to the start.
081:                 * 
082:                 * @return next command from the queue.
083:                 */
084:                public Object next() {
085:                    last = next;
086:                    Object command = commands.get(next++);
087:                    if (next >= end) {
088:                        next = 0;
089:                    }
090:
091:                    return command;
092:                }
093:
094:                /**
095:                 * Removes the command which was previously returned by {@link #next()}.
096:                 * 
097:                 * @return the command which was previously returned by {@link #next()}.
098:                 */
099:                public void remove() {
100:                    assert (last >= 0);
101:
102:                    commands.remove(last);
103:                    --end;
104:
105:                    if (last <= next) {
106:                        if (--next < 0) {
107:                            next = 0;
108:                        }
109:                    }
110:
111:                    last = -1;
112:                }
113:
114:                /**
115:                 * Returns the last element returned by {@link #next()}.
116:                 * 
117:                 * @return last element returned by {@link #next()}
118:                 */
119:                private Object getLast() {
120:                    assert (last >= 0);
121:                    return commands.get(last);
122:                }
123:
124:                private void setEnd(int end) {
125:                    assert (end >= next);
126:
127:                    this .end = end;
128:                }
129:
130:                private void setLast(int last) {
131:                    this .last = last;
132:                }
133:
134:                private boolean wasRemoved() {
135:                    return last == -1;
136:                }
137:            }
138:
139:            /**
140:             * Default amount of time to wait before assuming that a script cancellation
141:             * has taken place. This should be a platform dependent value, ultimately we
142:             * may need to acquire this value based on a rebind decision. For now, we
143:             * chose the smallest value known to cause an SSW.
144:             */
145:            private static final long DEFAULT_CANCELLATION_TIMEOUT_MILLIS = 10000;
146:
147:            /**
148:             * Default amount of time to spend dispatching commands before we yield to the
149:             * system.
150:             */
151:            private static final long DEFAULT_TIME_SLICE_MILLIS = 100;
152:
153:            /**
154:             * Returns true the end time has been reached or exceeded.
155:             * 
156:             * @param currentTimeMillis current time in milliseconds
157:             * @param startTimeMillis end time in milliseconds
158:             * @return true if the end time has been reached
159:             */
160:            private static boolean hasTimeSliceExpired(long currentTimeMillis,
161:                    long startTimeMillis) {
162:                return Math.abs(currentTimeMillis - startTimeMillis) >= DEFAULT_TIME_SLICE_MILLIS;
163:            }
164:
165:            /**
166:             * Timer used to recover from script cancellations arising from slow script
167:             * warnings.
168:             */
169:            private final Timer cancellationTimer = new Timer() {
170:                @Override
171:                public void run() {
172:                    if (!isExecuting()) {
173:                        /*
174:                         * If we are not executing, then the cancellation timer expired right
175:                         * about the time that the command dispatcher finished -- we are okay so
176:                         * we just exit.
177:                         */
178:                        return;
179:                    }
180:
181:                    doCommandCanceled();
182:                }
183:            };
184:
185:            /**
186:             * Commands that need to be executed.
187:             */
188:            private final List<Object> commands = new ArrayList<Object>();
189:
190:            /**
191:             * Set to <code>true</code> when we are actively dispatching commands.
192:             */
193:            private boolean executing = false;
194:
195:            /**
196:             * Timer used to drive the dispatching of commands in the background.
197:             */
198:            private final Timer executionTimer = new Timer() {
199:                @Override
200:                public void run() {
201:                    assert (!isExecuting());
202:
203:                    setExecutionTimerPending(false);
204:
205:                    doExecuteCommands(System.currentTimeMillis());
206:                }
207:            };
208:
209:            /**
210:             * Set to <code>true</code> when we are waiting for a dispatch timer event
211:             * to fire.
212:             */
213:            private boolean executionTimerPending = false;
214:
215:            /**
216:             * The single circular iterator instance that we use to iterate over the
217:             * collection of commands.
218:             */
219:            private final CircularIterator iterator = new CircularIterator();
220:
221:            /**
222:             * Submits a {@link Command} for execution.
223:             * 
224:             * @param command command to submit
225:             */
226:            public void submit(Command command) {
227:                commands.add(command);
228:
229:                maybeStartExecutionTimer();
230:            }
231:
232:            /**
233:             * Submits an {@link IncrementalCommand} for execution.
234:             * 
235:             * @param command command to submit
236:             */
237:            public void submit(IncrementalCommand command) {
238:                commands.add(command);
239:
240:                maybeStartExecutionTimer();
241:            }
242:
243:            /**
244:             * Reports either a {@link CommandCanceledException} or an
245:             * {@link IncrementalCommandCanceledException} back through the
246:             * {@link UncaughtExceptionHandler} if one is set.
247:             */
248:            protected void doCommandCanceled() {
249:                Object cmd = iterator.getLast();
250:                iterator.remove();
251:                assert (cmd != null);
252:
253:                RuntimeException ex = null;
254:                if (cmd instanceof  Command) {
255:                    ex = new CommandCanceledException((Command) cmd);
256:                } else if (cmd instanceof  IncrementalCommand) {
257:                    ex = new IncrementalCommandCanceledException(
258:                            (IncrementalCommand) cmd);
259:                }
260:
261:                if (ex != null) {
262:                    UncaughtExceptionHandler ueh = GWT
263:                            .getUncaughtExceptionHandler();
264:                    if (ueh != null) {
265:                        ueh.onUncaughtException(ex);
266:                    }
267:                }
268:
269:                setExecuting(false);
270:
271:                maybeStartExecutionTimer();
272:            }
273:
274:            /**
275:             * This method will dispatch commands from the command queue. It will dispatch
276:             * commands until one of the following conditions is <code>true</code>:
277:             * <ul>
278:             * <li>It consumed its dispatching time slice {@value #DEFAULT_TIME_SLICE_MILLIS}</li>
279:             * <li>It encounters a <code>null</code> in the command queue</li>
280:             * <li>All commands which were present at the start of the dispatching have
281:             * been removed from the command queue</li>
282:             * <li>The command that it was processing was canceled due to a false 
283:             * cancellation -- in this case we exit without updating any state</li> 
284:             * </ul>
285:             * 
286:             * @param startTimeMillis the time when this method started
287:             */
288:            protected void doExecuteCommands(long startTimeMillis) {
289:                assert (!isExecutionTimerPending());
290:
291:                boolean wasCanceled = false;
292:                try {
293:                    setExecuting(true);
294:
295:                    iterator.setEnd(commands.size());
296:
297:                    cancellationTimer
298:                            .schedule((int) DEFAULT_CANCELLATION_TIMEOUT_MILLIS);
299:
300:                    while (iterator.hasNext()) {
301:                        Object element = iterator.next();
302:
303:                        boolean removeCommand = true;
304:                        try {
305:                            if (element == null) {
306:                                // null forces a yield or pause in execution
307:                                return;
308:                            }
309:
310:                            if (element instanceof  Command) {
311:                                Command command = (Command) element;
312:                                command.execute();
313:                            } else if (element instanceof  IncrementalCommand) {
314:                                IncrementalCommand incrementalCommand = (IncrementalCommand) element;
315:                                removeCommand = !incrementalCommand.execute();
316:                            }
317:
318:                        } finally {
319:                            wasCanceled = iterator.wasRemoved();
320:                            if (wasCanceled) {
321:                                /*
322:                                 * The iterator may have already had its remove method called, if
323:                                 * it has, then we need to exit without updating any state 
324:                                 */
325:                                return;
326:                            }
327:
328:                            if (removeCommand) {
329:                                iterator.remove();
330:                            }
331:                        }
332:
333:                        if (hasTimeSliceExpired(System.currentTimeMillis(),
334:                                startTimeMillis)) {
335:                            // the time slice has expired
336:                            return;
337:                        }
338:                    }
339:                } finally {
340:                    if (!wasCanceled) {
341:                        cancellationTimer.cancel();
342:
343:                        setExecuting(false);
344:
345:                        maybeStartExecutionTimer();
346:                    }
347:                }
348:            }
349:
350:            /**
351:             * Starts the dispatch timer if there are commands to dispatch and we are not
352:             * waiting for a dispatch timer and we are not actively dispatching.
353:             */
354:            protected void maybeStartExecutionTimer() {
355:                if (!commands.isEmpty() && !isExecutionTimerPending()
356:                        && !isExecuting()) {
357:                    setExecutionTimerPending(true);
358:                    executionTimer.schedule(1);
359:                }
360:            }
361:
362:            /**
363:             * This method is for testing only.
364:             */
365:            List<Object> getPendingCommands() {
366:                return commands;
367:            }
368:
369:            /**
370:             * This method is for testing only.
371:             */
372:            void setExecuting(boolean executing) {
373:                this .executing = executing;
374:            }
375:
376:            /**
377:             * This method is for testing only.
378:             */
379:            void setLast(int last) {
380:                iterator.setLast(last);
381:            }
382:
383:            /**
384:             * Returns <code>true</code> if this instance is currently dispatching
385:             * commands.
386:             * 
387:             * @return <code>true</code> if this instance is currently dispatching
388:             *         commands
389:             */
390:            private boolean isExecuting() {
391:                return executing;
392:            }
393:
394:            /**
395:             * Returns <code>true</code> if a the dispatch timer was scheduled but it
396:             * still has not fired.
397:             * 
398:             * @return <code>true</code> if a the dispatch timer was scheduled but it
399:             *         still has not fired
400:             */
401:            private boolean isExecutionTimerPending() {
402:                return executionTimerPending;
403:            }
404:
405:            private void setExecutionTimerPending(boolean pending) {
406:                executionTimerPending = pending;
407:            }
408:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.