001package Torello.HTML;
002
003import java.io.*;
004import java.util.Vector;
005import java.net.URL;
006import Torello.HTML.HTMLPage.Parser;
007
008import java.util.concurrent.*;
009import java.util.concurrent.locks.*;
010
011import Torello.JavaDoc.Excuse;
012
013/**
014 * A carbon-copy of class {@link HTMLPage}, augmented with a mechanism for setting <B>a timeout</B> 
015 * so that when scraping web-pages and {@code URL's} from servers that might have a tendency to hang,
016 * freeze, or delay - the Java Virtual Machine can skip and move-on when that timeout expires. 
017 * 
018 * <BR /><BR />
019 * <EMBED CLASS='external-html' DATA-FILE-ID=HTML_PAGE_MWT>
020 * <EMBED CLASS='external-html' DATA-FILE-ID=HTML_PAGE>
021 * 
022 * @see Scrape#getHTML(BufferedReader, int, int)
023 * @see Scrape#getHTML(BufferedReader, String, String)
024 * @see HTMLPage
025 */
026@Torello.JavaDoc.StaticFunctional(Excused="parser", Excuses=Excuse.SINGLETON)
027@Torello.JavaDoc.JDHeaderBackgroundImg
028public class HTMLPageMWT
029{
030    private HTMLPageMWT() { }
031
032    /**
033     * If needing to "swap a proprietary parser" comes up, this is possible.
034     * It just needs to accept the same parameters as the current parser, and produce a 
035     * {@code Vector<HTMLNode>.}  This is not an advised step to take, but if an alternative
036     * parser has been tested and happens to be generating different results, it can be easily
037     * 'swapped out' for the one used now.
038     * @see HTMLPage.Parser
039     * @see HTMLPage.Parser#parse(CharSequence, boolean, String, String, String)
040     */
041    public static Parser parser = ParserRE::parsePageTokens;
042
043
044    // ********************************************************************************************
045    // ********************************************************************************************
046    // These 6 functions presume that the HTML source is from a URL
047    // ********************************************************************************************
048    // ********************************************************************************************
049
050
051    /**
052     * Convenience Method.
053     * <BR />Accepts: {@code URL} and Time-Out Parameters {@code 'timeout' & 'unit'}
054     * <BR />Passes null to parameters
055     * {@code startTag, endTag, rawHTMLFile, matchesFile & justTextFile}.
056     * <BR />Invokes: {@link #getPageTokens(long, TimeUnit, URL, boolean, String, String,
057     *      String, String, String)}
058     */
059    public static Vector<HTMLNode> getPageTokens
060        (long timeout, TimeUnit unit, URL url, boolean eliminateHTMLTags)
061        throws IOException, InterruptedException
062    {
063        return getPageTokens(timeout, unit, url, eliminateHTMLTags, null, null, null, null, null);
064    }
065
066    /**
067     * Convenience Method.
068     * <BR />Accepts: {@code URL} and Time-Out Parameters {@code 'timeout' & 'unit'}
069     * <BR />And-Accepts: {@code 'startTag'} and {@code 'endTag'}
070     * <BR />Passes null to parameters {@code rawHTMLFile, matchesFile & justTextFile}.
071     * <BR />Invokes: {@link #getPageTokens(long, TimeUnit, URL, boolean, String, String,
072     *      String, String, String)}
073     */ 
074    public static Vector<HTMLNode> getPageTokens(
075            long timeout, TimeUnit unit,
076            URL url, boolean eliminateHTMLTags,
077            String startTag, String endTag
078        )
079        throws IOException, InterruptedException
080    {
081        return getPageTokens
082            (timeout, unit, url, eliminateHTMLTags, startTag, endTag, null, null, null);
083    }
084
085    /**
086     * Convenience Method.
087     * <BR />Accepts: {@code URL} and Time-Out Parameters {@code 'timeout' & 'unit'}
088     * <BR />And-Accepts: {@code 'startLineNum'} and {@code 'endLineNum'}
089     * <BR />Passes null to parameters {@code rawHTMLFile, matchesFile & justTextFile}.
090     * <BR />Invokes: {@link #getPageTokens(long, TimeUnit, URL, boolean, int, int,
091     *      String, String, String)}
092     */
093    public static Vector<HTMLNode> getPageTokens(
094            long timeout, TimeUnit unit,
095            URL url, boolean eliminateHTMLTags,
096            int startLineNum, int endLineNum
097        )
098        throws IOException, InterruptedException
099    {
100        return getPageTokens
101            (timeout, unit, url, eliminateHTMLTags, startLineNum, endLineNum, null, null, null);
102    }
103
104    /**
105     * Convenience Method.
106     * <BR />Accepts: {@code URL} and Time-Out Parameters {@code 'timeout' & 'unit'}
107     * <BR />Passes null to {@code startTag} &amp; {@code endTag} parameters.
108     * <BR />Invokes: {@link #getPageTokens(long, TimeUnit, URL, boolean, String, String,
109     *      String, String, String)}
110     */
111    public static Vector<HTMLNode> getPageTokens(
112            long timeout, TimeUnit unit,
113            URL url, boolean eliminateHTMLTags,
114            String rawHTMLFile, String matchesFile, String justTextFile
115        )
116        throws IOException, InterruptedException
117    {
118        return getPageTokens(
119            timeout, unit, url, eliminateHTMLTags, null, null,
120            rawHTMLFile, matchesFile, justTextFile
121        );
122    }
123
124
125    // ********************************************************************************************
126    // ********************************************************************************************
127    // The next 6 functions presume that the input is from a BufferedReader
128    // ********************************************************************************************
129    // ********************************************************************************************
130
131    /**
132     * Convenience Method.
133     * <BR />Accepts: {@code BufferedReader}
134     * <BR />Passes null to parameters
135     * {@code startTag, endTag, rawHTMLFile, matchesFile & justTextFile}.
136     * <BR />Invokes: {@link #getPageTokens(long, TimeUnit, BufferedReader, boolean,
137     *      String, String, String, String, String)}
138     */
139    public static Vector<HTMLNode> getPageTokens
140        (long timeout, TimeUnit unit, BufferedReader br, boolean eliminateHTMLTags)
141        throws IOException, InterruptedException
142    {
143        return getPageTokens
144            (timeout, unit, br, eliminateHTMLTags, null, null, null, null, null);
145    }
146
147    /**
148     * Convenience Method.
149     * <BR />Accepts: {@code BufferedReader}
150     * <BR />And-Accepts: {@code 'startTag'} and {@code 'endTag'}
151     * <BR />Passes null to parameters {@code rawHTMLFile, matchesFile & justTextFile}.
152     * <BR />Invokes: {@link #getPageTokens(long, TimeUnit, BufferedReader, boolean,
153     *      String, String, String, String, String)}
154     */ 
155    public static Vector<HTMLNode> getPageTokens(
156            long timeout, TimeUnit unit,
157            BufferedReader br, boolean eliminateHTMLTags, String startTag, String endTag
158        )
159        throws IOException, InterruptedException
160    {
161        return getPageTokens
162            (timeout, unit, br, eliminateHTMLTags, startTag, endTag, null, null, null);
163    }
164
165    /**
166     * Convenience Method.
167     * <BR />Accepts: {@code BufferedReader}
168     * <BR />And-Accepts: {@code 'startLineNum'} and {@code 'endLineNum'}
169     * <BR />Passes null to parameters {@code rawHTMLFile, matchesFile & justTextFile}.
170     * <BR />Invokes: {@link #getPageTokens(long, TimeUnit, BufferedReader, boolean,
171     *      int, int, String, String, String)}
172     */
173    public static Vector<HTMLNode> getPageTokens(
174            long timeout, TimeUnit unit,
175            BufferedReader br, boolean eliminateHTMLTags,
176            int startLineNum, int endLineNum
177        )
178        throws IOException, InterruptedException
179    {
180        return getPageTokens
181            (timeout, unit, br, eliminateHTMLTags, startLineNum, endLineNum, null, null, null);
182    }
183
184    /**
185     * Convenience Method.
186     * <BR />Accepts: {@code BufferedReader}
187     * <BR />Passes null to {@code startTag} &amp; {@code endTag} parameters.
188     * <BR />Invokes: {@link #getPageTokens(long, TimeUnit, BufferedReader, boolean,
189     *      String, String, String, String, String)}
190     */
191    public static Vector<HTMLNode> getPageTokens(
192            long timeout, TimeUnit unit,
193            BufferedReader br, boolean eliminateHTMLTags,
194            String rawHTMLFile, String matchesFile, String justTextFile
195        )
196        throws IOException, InterruptedException
197    { 
198        return getPageTokens
199            (timeout, unit, br, eliminateHTMLTags, null, null, rawHTMLFile, matchesFile, justTextFile);
200    }
201
202
203    // ********************************************************************************************
204    // ********************************************************************************************
205    // * Receives a "pre-instantiated" BufferedReader for the HTML Source parameter
206    // ********************************************************************************************
207    // ********************************************************************************************
208
209
210    private static final ExecutorService    executor    = Executors.newCachedThreadPool();
211    private static final Lock               lock        = new ReentrantLock();
212
213    /**
214     * If this class has been used to make "multi-threaded" calls that use a Time-Out wait-period,
215     * you might see your Java-Program hang for a few seconds when you would expect it to exit back
216     * to your O.S. normally.
217     *
218     * <BR /><BR /><B>Max Wait Time</B> operates by building a "Timeout &amp; Monitor" thread, and
219     * therefore when a program you have written yourself reaches the end of its code, <I><B>if you
220     * have performed any Internet-Downloads using {@code class HTMLPageMWT}</B></I>, then your
221     * program <I>might not exit immediately,</I> but rather sit at the command-prompt for anywhere
222     * between 10 and 30 seconds before this Timeout-Thread, created in class HTMLPageMWT, dies.
223     *
224     * <BR /><BR /><B CLASS=JDDescLabel>Multi-Threaded:</B>
225     * 
226     * <BR />You may also immediately terminate any additional threads that were started by using
227     * this method.
228     */
229    public static void shutdownMWTThreads() { executor.shutdownNow(); }
230
231    /**
232     * Parses and Vectorizes HTML from a {@code BufferedReader} source.
233     * Spawns a <I>monitor-thread</I> that stops the download if a 
234     * certain, user-specified, time-limit is exceeded.
235     * @param timeout <EMBED CLASS='external-html' DATA-FILE-ID=HTML_PAGE_TIMEOUT>
236     * @param unit <EMBED CLASS='external-html' DATA-FILE-ID=HTML_PAGE_UNIT>
237     * @param br <EMBED CLASS='external-html' DATA-FILE-ID=HTML_PAGE_BR>
238     * @param eliminateHTMLTags <EMBED CLASS='external-html' DATA-FILE-ID=HTML_PAGE_ELIM_HT>
239     * @param startTag <EMBED CLASS='external-html' DATA-FILE-ID=HTML_PAGE_START_TAG>
240     * @param endTag <EMBED CLASS='external-html' DATA-FILE-ID=HTML_PAGE_END_TAG>
241     * @param rawHTMLFile <EMBED CLASS='external-html' DATA-FILE-ID=HTML_PAGE_RAW_HTML>
242     * @param matchesFile <EMBED CLASS='external-html' DATA-FILE-ID=HTML_PAGE_MATCHES_F>
243     * @param justTextFile <EMBED CLASS='external-html' DATA-FILE-ID=HTML_PAGE_JUST_TEXT>
244     * @return <EMBED CLASS='external-html' DATA-FILE-ID=HTML_PAGE_RETURN>
245     * @throws ScrapeException <EMBED CLASS='external-html' DATA-FILE-ID=HTML_PAGE_SCEX2>
246     * @throws IOException <EMBED CLASS='external-html' DATA-FILE-ID=HTML_PAGE_IOEX>
247     * @throws InterruptedException <EMBED CLASS='external-html' DATA-FILE-ID=HTML_PAGE_IEX>
248     * @throws RejectedExecutionException <EMBED CLASS='external-html' DATA-FILE-ID=HTML_PAGE_REEX>
249     */
250    public static Vector<HTMLNode> getPageTokens(
251            long timeout, TimeUnit unit,
252            BufferedReader br, boolean eliminateHTMLTags,
253            String startTag, String endTag,
254            String rawHTMLFile, String matchesFile, String justTextFile
255        )
256        throws IOException, InterruptedException
257    {
258        Callable<Vector<HTMLNode>> threadDownloader = new Callable<Vector<HTMLNode>>()
259        {
260            public Vector<HTMLNode> call() throws Exception
261            {
262                return parser.parse(
263                    Scrape.getHTML(br, startTag, endTag),
264                    eliminateHTMLTags, rawHTMLFile, matchesFile, justTextFile
265                );
266            }
267        };
268
269        lock.lock();
270        Future<Vector<HTMLNode>> future = executor.submit(threadDownloader);
271        lock.unlock();
272
273        try
274            { return future.get(timeout, unit); }
275
276        catch (TimeoutException e) { return null; }
277
278        catch (ExecutionException e)
279        {
280            Throwable originalException = e.getCause();
281            if (originalException == null) throw new RejectedExecutionException(
282                "An Execution Exception was thrown, but it did provide a cause throwable " +
283                "(e.getCause() returned null).  See this exception's getCause() method to " +
284                "view the ExecutionException that has occurred.",
285                e
286            );
287
288            if (originalException instanceof IOException)
289                throw (IOException) originalException;
290
291            if (originalException instanceof RuntimeException)
292                throw (RuntimeException) originalException;
293
294            throw new RejectedExecutionException(
295                "An Execution Exception occurred, but it was neither a RuntimeException, " +
296                "nor IOException.  See this exception's getCause() method to view the " +
297                "underlying error that has occurred.", originalException
298            );
299        }
300    }
301
302    /**
303     * Parses and Vectorizes HTML from a {@code BufferedReader} source.
304     * Spawns a <I>monitor-thread</I> that stops the download if a 
305     * certain, user-specified, time-limit is exceeded.
306     * @param timeout <EMBED CLASS='external-html' DATA-FILE-ID=HTML_PAGE_TIMEOUT>
307     * @param unit <EMBED CLASS='external-html' DATA-FILE-ID=HTML_PAGE_UNIT>
308     * @param br <EMBED CLASS='external-html' DATA-FILE-ID=HTML_PAGE_BR>
309     * @param eliminateHTMLTags <EMBED CLASS='external-html' DATA-FILE-ID=HTML_PAGE_ELIM_HT>
310     * @param startLineNum <EMBED CLASS='external-html' DATA-FILE-ID=HTML_PAGE_START_LN>
311     * @param endLineNum <EMBED CLASS='external-html' DATA-FILE-ID=HTML_PAGE_END_LN>
312     * @param rawHTMLFile <EMBED CLASS='external-html' DATA-FILE-ID=HTML_PAGE_RAW_HTML>
313     * @param matchesFile <EMBED CLASS='external-html' DATA-FILE-ID=HTML_PAGE_MATCHES_F>
314     * @param justTextFile <EMBED CLASS='external-html' DATA-FILE-ID=HTML_PAGE_JUST_TEXT>
315     * @return <EMBED CLASS='external-html' DATA-FILE-ID=HTML_PAGE_RETURN>
316     * @throws IllegalArgumentException <EMBED CLASS='external-html' DATA-FILE-ID=HTML_PAGE_IAEX>
317     * @throws ScrapeException  <EMBED CLASS='external-html' DATA-FILE-ID=HTML_PAGE_SCEX1>
318     * @throws IOException <EMBED CLASS='external-html' DATA-FILE-ID=HTML_PAGE_IOEX>
319     * @throws InterruptedException <EMBED CLASS='external-html' DATA-FILE-ID=HTML_PAGE_IEX>
320     * @throws RejectedExecutionException <EMBED CLASS='external-html' DATA-FILE-ID=HTML_PAGE_REEX>
321     */
322    public static Vector<HTMLNode> getPageTokens(
323            long timeout, TimeUnit unit,
324            BufferedReader br, boolean eliminateHTMLTags,
325            int startLineNum, int endLineNum,
326            String rawHTMLFile, String matchesFile, String justTextFile
327        )
328        throws IOException, InterruptedException
329    {
330        Callable<Vector<HTMLNode>> threadDownloader = new Callable<Vector<HTMLNode>>()
331        {
332            public Vector<HTMLNode> call() throws Exception
333            {
334                return parser.parse(
335                    Scrape.getHTML(br, startLineNum, endLineNum),
336                    eliminateHTMLTags, rawHTMLFile, matchesFile, justTextFile
337                );
338            }
339        };
340
341        lock.lock();
342        Future<Vector<HTMLNode>> future = executor.submit(threadDownloader);
343        lock.unlock();
344
345        try
346            { return future.get(timeout, unit); }
347
348        catch (TimeoutException e) { return null; }
349
350        catch (ExecutionException e)
351        {
352            Throwable originalException = e.getCause();
353
354            if (originalException == null) throw new RejectedExecutionException(
355                "An Execution Exception was thrown, but it did provide a cause throwable " +
356                "(e.getCause() returned null).  See this exception's getCause() method to " +
357                "view the ExecutionException has that occurred.",
358                e
359            );
360
361            if (originalException instanceof IOException)
362                throw (IOException) originalException;
363
364            if (originalException instanceof RuntimeException)
365                throw (RuntimeException) originalException;
366
367            throw new RejectedExecutionException(
368                "An Execution Exception occurred, but it was neither a RuntimeException, nor " +
369                "IOException.  See this exception's getCause() method to view the underlying " +
370                "error that has occurred.", originalException
371            );
372        }
373    }
374
375
376    // ********************************************************************************************
377    // ********************************************************************************************
378    // Receives a java.net.URL for the HTML Source parameter -- that could Timeout/Hang
379    // ********************************************************************************************
380    // ********************************************************************************************
381
382
383    // It must be opened within the Multi-Threaded "Timeout" code (and therefore requires a second
384    // version of these two methods - where Scrape.openConn(url) is *inside* the monitored
385    // downloading thread.
386    
387    /**
388     * Parses and Vectorizes HTML from a URL source.
389     * Spawns a <I>monitor-thread</I> that stops the download if a certain, user-specified,
390     * time-limit is exceeded.
391     * @param timeout <EMBED CLASS='external-html' DATA-FILE-ID=HTML_PAGE_TIMEOUT>
392     * @param unit <EMBED CLASS='external-html' DATA-FILE-ID=HTML_PAGE_UNIT>
393     * @param url <EMBED CLASS='external-html' DATA-FILE-ID=HTML_PAGE_URL>
394     * @param eliminateHTMLTags <EMBED CLASS='external-html' DATA-FILE-ID=HTML_PAGE_ELIM_HT>
395     * @param startTag <EMBED CLASS='external-html' DATA-FILE-ID=HTML_PAGE_START_TAG>
396     * @param endTag <EMBED CLASS='external-html' DATA-FILE-ID=HTML_PAGE_END_TAG>
397     * @param rawHTMLFile <EMBED CLASS='external-html' DATA-FILE-ID=HTML_PAGE_RAW_HTML>
398     * @param matchesFile <EMBED CLASS='external-html' DATA-FILE-ID=HTML_PAGE_MATCHES_F>
399     * @param justTextFile <EMBED CLASS='external-html' DATA-FILE-ID=HTML_PAGE_JUST_TEXT>
400     * @return <EMBED CLASS='external-html' DATA-FILE-ID=HTML_PAGE_RETURN>
401     * @throws ScrapeException <EMBED CLASS='external-html' DATA-FILE-ID=HTML_PAGE_SCEX2>
402     * @throws IOException <EMBED CLASS='external-html' DATA-FILE-ID=HTML_PAGE_IOEX>
403     * @throws InterruptedException <EMBED CLASS='external-html' DATA-FILE-ID=HTML_PAGE_IEX>
404     * @throws RejectedExecutionException <EMBED CLASS='external-html' DATA-FILE-ID=HTML_PAGE_REEX>
405     */
406    public static Vector<HTMLNode> getPageTokens(
407            long timeout, TimeUnit unit,
408            URL url, boolean eliminateHTMLTags,
409            String startTag, String endTag,
410            String rawHTMLFile, String matchesFile, String justTextFile
411        )
412        throws IOException, InterruptedException
413    {
414        Callable<Vector<HTMLNode>> threadDownloader = new Callable<Vector<HTMLNode>>()
415        {
416            public Vector<HTMLNode> call() throws Exception
417            { 
418                return parser.parse(
419                    Scrape.getHTML(Scrape.openConn(url), startTag, endTag),
420                    eliminateHTMLTags, rawHTMLFile, matchesFile, justTextFile
421                );
422            }
423        };
424
425        lock.lock();
426        Future<Vector<HTMLNode>> future = executor.submit(threadDownloader);
427        lock.unlock();
428
429        try
430            { return future.get(timeout, unit); }
431
432        catch (TimeoutException e) { return null; }
433
434        catch (ExecutionException e)
435        {
436            Throwable originalException = e.getCause();
437
438            if (originalException == null) throw new RejectedExecutionException(
439                "An Execution Exception was thrown, but it did provide a cause throwable " +
440                "(e.getCause() returned null).  See this exception's getCause() method to " +
441                "view the ExecutionException that has occurred.", e
442            );
443
444            if (originalException instanceof IOException)
445                throw (IOException) originalException;
446
447            if (originalException instanceof RuntimeException)
448                throw (RuntimeException) originalException;
449
450            throw new RejectedExecutionException(
451                "An Execution Exception occurred, but it was neither a RuntimeException, " +
452                "nor IOException.  See this exception's getCause() method to view the " +
453                "underlying error that has occurred.", originalException
454            );
455        }
456    }
457
458    
459    /**
460     * Parses and Vectorizes HTML from a URL source.
461     * Spawns a <I>monitor-thread</I> that stops the download if a certain, user-specified,
462     * time-limit is exceeded.
463     * @param timeout <EMBED CLASS='external-html' DATA-FILE-ID=HTML_PAGE_TIMEOUT>
464     * @param unit <EMBED CLASS='external-html' DATA-FILE-ID=HTML_PAGE_UNIT>
465     * @param url <EMBED CLASS='external-html' DATA-FILE-ID=HTML_PAGE_URL>
466     * @param eliminateHTMLTags <EMBED CLASS='external-html' DATA-FILE-ID=HTML_PAGE_ELIM_HT>
467     * @param startLineNum <EMBED CLASS='external-html' DATA-FILE-ID=HTML_PAGE_START_LN>
468     * @param endLineNum <EMBED CLASS='external-html' DATA-FILE-ID=HTML_PAGE_END_LN>
469     * @param rawHTMLFile <EMBED CLASS='external-html' DATA-FILE-ID=HTML_PAGE_RAW_HTML>
470     * @param matchesFile <EMBED CLASS='external-html' DATA-FILE-ID=HTML_PAGE_MATCHES_F>
471     * @param justTextFile <EMBED CLASS='external-html' DATA-FILE-ID=HTML_PAGE_JUST_TEXT>
472     * @return <EMBED CLASS='external-html' DATA-FILE-ID=HTML_PAGE_RETURN>
473     * @throws IllegalArgumentException <EMBED CLASS='external-html' DATA-FILE-ID=HTML_PAGE_IAEX>
474     * @throws ScrapeException  <EMBED CLASS='external-html' DATA-FILE-ID=HTML_PAGE_SCEX1>
475     * @throws IOException <EMBED CLASS='external-html' DATA-FILE-ID=HTML_PAGE_IOEX>
476     * @throws InterruptedException <EMBED CLASS='external-html' DATA-FILE-ID=HTML_PAGE_IEX>
477     * @throws RejectedExecutionException <EMBED CLASS='external-html' DATA-FILE-ID=HTML_PAGE_REEX>
478     */
479    public static Vector<HTMLNode> getPageTokens(
480            long timeout, TimeUnit unit,
481            URL url, boolean eliminateHTMLTags,
482            int startLineNum, int endLineNum,
483            String rawHTMLFile, String matchesFile, String justTextFile
484        )
485        throws IOException, InterruptedException
486    {
487        Callable<Vector<HTMLNode>> threadDownloader = new Callable<Vector<HTMLNode>>()
488        {
489            public Vector<HTMLNode> call() throws Exception
490            { 
491                return parser.parse(
492                    Scrape.getHTML(Scrape.openConn(url), startLineNum, endLineNum),
493                    eliminateHTMLTags, rawHTMLFile, matchesFile, justTextFile
494                );
495            }
496        };
497
498        lock.lock();
499        Future<Vector<HTMLNode>> future = executor.submit(threadDownloader);
500        lock.unlock();
501
502        try
503            { return future.get(timeout, unit); }
504
505        catch (TimeoutException e) { return null; }
506
507        catch (ExecutionException e)
508        {
509            Throwable originalException = e.getCause();
510    
511            if (originalException == null) throw new RejectedExecutionException(
512                "An Execution Exception was thrown, but it did provide a cause throwable " +
513                "(e.getCause() returned null).  See this exception's getCause() method to " +
514                "view the ExecutionException has that occurred.",
515                e
516            );
517
518            if (originalException instanceof IOException)
519                throw (IOException) originalException;
520
521            if (originalException instanceof RuntimeException)
522                throw (RuntimeException) originalException;
523
524            throw new RejectedExecutionException(
525                "An Execution Exception occurred, but it was neither a RuntimeException, nor " +
526                "IOException.  See this exception's getCause() method to view the underlying " +
527                "error that has occurred.", originalException
528            );
529        }
530    }
531}