Source Code Cross Referenced for WDataTransferer.java in  » 6.0-JDK-Platform » windows » sun » awt » windows » 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 » 6.0 JDK Platform » windows » sun.awt.windows 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*
002:         * Copyright 2000-2007 Sun Microsystems, Inc.  All Rights Reserved.
003:         * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004:         *
005:         * This code is free software; you can redistribute it and/or modify it
006:         * under the terms of the GNU General Public License version 2 only, as
007:         * published by the Free Software Foundation.  Sun designates this
008:         * particular file as subject to the "Classpath" exception as provided
009:         * by Sun in the LICENSE file that accompanied this code.
010:         *
011:         * This code is distributed in the hope that it will be useful, but WITHOUT
012:         * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013:         * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
014:         * version 2 for more details (a copy is included in the LICENSE file that
015:         * accompanied this code).
016:         *
017:         * You should have received a copy of the GNU General Public License version
018:         * 2 along with this work; if not, write to the Free Software Foundation,
019:         * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020:         *
021:         * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
022:         * CA 95054 USA or visit www.sun.com if you need additional information or
023:         * have any questions.
024:         */
025:
026:        package sun.awt.windows;
027:
028:        import java.awt.Image;
029:        import java.awt.Graphics2D;
030:        import java.awt.Transparency;
031:
032:        import java.awt.color.ColorSpace;
033:
034:        import java.awt.datatransfer.DataFlavor;
035:        import java.awt.datatransfer.FlavorTable;
036:        import java.awt.datatransfer.Transferable;
037:        import java.awt.datatransfer.UnsupportedFlavorException;
038:
039:        import java.awt.geom.AffineTransform;
040:
041:        import java.awt.image.BufferedImage;
042:        import java.awt.image.ColorModel;
043:        import java.awt.image.ComponentColorModel;
044:        import java.awt.image.DataBuffer;
045:        import java.awt.image.DataBufferByte;
046:        import java.awt.image.DataBufferInt;
047:        import java.awt.image.DirectColorModel;
048:        import java.awt.image.ImageObserver;
049:        import java.awt.image.Raster;
050:        import java.awt.image.WritableRaster;
051:
052:        import java.io.BufferedInputStream;
053:        import java.io.BufferedReader;
054:        import java.io.ByteArrayInputStream;
055:        import java.io.InputStream;
056:        import java.io.InputStreamReader;
057:        import java.io.IOException;
058:        import java.io.UnsupportedEncodingException;
059:
060:        import java.net.URL;
061:
062:        import java.util.Arrays;
063:        import java.util.Collections;
064:        import java.util.HashMap;
065:        import java.util.Map;
066:        import java.util.SortedMap;
067:
068:        import sun.awt.Mutex;
069:        import sun.awt.datatransfer.DataTransferer;
070:        import sun.awt.datatransfer.ToolkitThreadBlockedHandler;
071:
072:        import sun.awt.image.ImageRepresentation;
073:        import sun.awt.image.ToolkitImage;
074:
075:        /**
076:         * Platform-specific support for the data transfer subsystem.
077:         *
078:         * @author David Mendenhall
079:         * @author Danila Sinopalnikov
080:         * @version 1.32, 05/05/07
081:         *
082:         * @since 1.3.1
083:         */
084:        public class WDataTransferer extends DataTransferer {
085:            private static final String[] predefinedClipboardNames = { "",
086:                    "TEXT", "BITMAP", "METAFILEPICT", "SYLK", "DIF", "TIFF",
087:                    "OEM TEXT", "DIB", "PALETTE", "PENDATA", "RIFF", "WAVE",
088:                    "UNICODE TEXT", "ENHMETAFILE", "HDROP", "LOCALE", "DIBV5" };
089:
090:            private static final Map predefinedClipboardNameMap;
091:            static {
092:                Map tempMap = new HashMap(predefinedClipboardNames.length, 1.0f);
093:                for (int i = 1; i < predefinedClipboardNames.length; i++) {
094:                    tempMap.put(predefinedClipboardNames[i], Long.valueOf(i));
095:                }
096:                predefinedClipboardNameMap = Collections
097:                        .synchronizedMap(tempMap);
098:            }
099:
100:            /**
101:             * from winuser.h
102:             */
103:            public static final int CF_TEXT = 1;
104:            public static final int CF_METAFILEPICT = 3;
105:            public static final int CF_DIB = 8;
106:            public static final int CF_ENHMETAFILE = 14;
107:            public static final int CF_HDROP = 15;
108:            public static final int CF_LOCALE = 16;
109:
110:            public static final long CF_HTML = registerClipboardFormat("HTML Format");
111:            public static final long CFSTR_INETURL = registerClipboardFormat("UniformResourceLocator");
112:            public static final long CF_PNG = registerClipboardFormat("PNG");
113:            public static final long CF_JFIF = registerClipboardFormat("JFIF");
114:
115:            private static final Long L_CF_LOCALE = (Long) predefinedClipboardNameMap
116:                    .get(predefinedClipboardNames[CF_LOCALE]);
117:
118:            private static final DirectColorModel directColorModel = new DirectColorModel(
119:                    24, 0x00FF0000, /* red mask   */
120:                    0x0000FF00, /* green mask */
121:                    0x000000FF); /* blue mask  */
122:
123:            private static final int[] bandmasks = new int[] {
124:                    directColorModel.getRedMask(),
125:                    directColorModel.getGreenMask(),
126:                    directColorModel.getBlueMask() };
127:
128:            /**
129:             * Singleton constructor
130:             */
131:            private WDataTransferer() {
132:            }
133:
134:            private static WDataTransferer transferer;
135:
136:            public static WDataTransferer getInstanceImpl() {
137:                if (transferer == null) {
138:                    synchronized (WDataTransferer.class) {
139:                        if (transferer == null) {
140:                            transferer = new WDataTransferer();
141:                        }
142:                    }
143:                }
144:                return transferer;
145:            }
146:
147:            public SortedMap getFormatsForFlavors(DataFlavor[] flavors,
148:                    FlavorTable map) {
149:                SortedMap retval = super .getFormatsForFlavors(flavors, map);
150:
151:                // The Win32 native code does not support exporting LOCALE data, nor
152:                // should it.
153:                retval.remove(L_CF_LOCALE);
154:
155:                return retval;
156:            }
157:
158:            public String getDefaultUnicodeEncoding() {
159:                return "utf-16le";
160:            }
161:
162:            public byte[] translateTransferable(Transferable contents,
163:                    DataFlavor flavor, long format) throws IOException {
164:                byte[] bytes = super .translateTransferable(contents, flavor,
165:                        format);
166:
167:                if (format == CF_HTML) {
168:                    bytes = HTMLCodec.convertToHTMLFormat(bytes);
169:                }
170:                return bytes;
171:            }
172:
173:            protected Object translateBytesOrStream(InputStream str,
174:                    byte[] bytes, DataFlavor flavor, long format,
175:                    Transferable localeTransferable) throws IOException {
176:                if (format == CF_HTML && flavor.isFlavorTextType()) {
177:                    if (str == null) {
178:                        str = new ByteArrayInputStream(bytes);
179:                        bytes = null;
180:                    }
181:
182:                    str = new HTMLCodec(str, EHTMLReadMode.HTML_READ_SELECTION);
183:                }
184:
185:                if (format == CFSTR_INETURL
186:                        && URL.class.equals(flavor.getRepresentationClass())) {
187:                    if (bytes == null) {
188:                        bytes = inputStreamToByteArray(str);
189:                        str = null;
190:                    }
191:                    String charset = getDefaultTextCharset();
192:                    if (localeTransferable != null
193:                            && localeTransferable
194:                                    .isDataFlavorSupported(javaTextEncodingFlavor)) {
195:                        try {
196:                            charset = new String((byte[]) localeTransferable
197:                                    .getTransferData(javaTextEncodingFlavor),
198:                                    "UTF-8");
199:                        } catch (UnsupportedFlavorException cannotHappen) {
200:                        }
201:                    }
202:                    return new URL(new String(bytes, charset));
203:                }
204:
205:                return super .translateBytesOrStream(str, bytes, flavor, format,
206:                        localeTransferable);
207:            }
208:
209:            public boolean isLocaleDependentTextFormat(long format) {
210:                return format == CF_TEXT || format == CFSTR_INETURL;
211:            }
212:
213:            public boolean isFileFormat(long format) {
214:                return format == CF_HDROP;
215:            }
216:
217:            protected Long getFormatForNativeAsLong(String str) {
218:                Long format = (Long) predefinedClipboardNameMap.get(str);
219:                if (format == null) {
220:                    format = Long.valueOf(registerClipboardFormat(str));
221:                }
222:                return format;
223:            }
224:
225:            protected String getNativeForFormat(long format) {
226:                return (format < predefinedClipboardNames.length) ? predefinedClipboardNames[(int) format]
227:                        : getClipboardFormatName(format);
228:            }
229:
230:            private final ToolkitThreadBlockedHandler handler = new WToolkitThreadBlockedHandler();
231:
232:            public ToolkitThreadBlockedHandler getToolkitThreadBlockedHandler() {
233:                return handler;
234:            }
235:
236:            /**
237:             * Calls the Win32 RegisterClipboardFormat function to register
238:             * a non-standard format.
239:             */
240:            private static native long registerClipboardFormat(String str);
241:
242:            /**
243:             * Calls the Win32 GetClipboardFormatName function which is
244:             * the reverse operation of RegisterClipboardFormat.
245:             */
246:            private static native String getClipboardFormatName(long format);
247:
248:            public boolean isImageFormat(long format) {
249:                return format == CF_DIB || format == CF_ENHMETAFILE
250:                        || format == CF_METAFILEPICT || format == CF_PNG
251:                        || format == CF_JFIF;
252:            }
253:
254:            protected byte[] imageToPlatformBytes(Image image, long format)
255:                    throws IOException {
256:                String mimeType = null;
257:                if (format == CF_PNG) {
258:                    mimeType = "image/png";
259:                } else if (format == CF_JFIF) {
260:                    mimeType = "image/jpeg";
261:                }
262:                if (mimeType != null) {
263:                    return imageToStandardBytes(image, mimeType);
264:                }
265:
266:                int width = 0;
267:                int height = 0;
268:
269:                if (image instanceof  ToolkitImage) {
270:                    ImageRepresentation ir = ((ToolkitImage) image)
271:                            .getImageRep();
272:                    ir.reconstruct(ImageObserver.ALLBITS);
273:                    width = ir.getWidth();
274:                    height = ir.getHeight();
275:                } else {
276:                    width = image.getWidth(null);
277:                    height = image.getHeight(null);
278:                }
279:
280:                // Fix for 4919639.
281:                // Some Windows native applications (e.g. clipbrd.exe) do not handle
282:                // 32-bpp DIBs correctly.
283:                // As a workaround we switched to 24-bpp DIBs.
284:                // MSDN prescribes that the bitmap array for a 24-bpp should consist of
285:                // 3-byte triplets representing blue, green and red components of a
286:                // pixel respectively. Additionally each scan line must be padded with
287:                // zeroes to end on a LONG data-type boundary. LONG is always 32-bit.
288:                // We render the given Image to a BufferedImage of type TYPE_3BYTE_BGR
289:                // with non-default scanline stride and pass the resulting data buffer
290:                // to the native code to fill the BITMAPINFO structure.
291:                int mod = (width * 3) % 4;
292:                int pad = mod > 0 ? 4 - mod : 0;
293:
294:                ColorSpace cs = ColorSpace.getInstance(ColorSpace.CS_sRGB);
295:                int[] nBits = { 8, 8, 8 };
296:                int[] bOffs = { 2, 1, 0 };
297:                ColorModel colorModel = new ComponentColorModel(cs, nBits,
298:                        false, false, Transparency.OPAQUE, DataBuffer.TYPE_BYTE);
299:                WritableRaster raster = Raster.createInterleavedRaster(
300:                        DataBuffer.TYPE_BYTE, width, height, width * 3 + pad,
301:                        3, bOffs, null);
302:
303:                BufferedImage bimage = new BufferedImage(colorModel, raster,
304:                        false, null);
305:
306:                // Some Windows native applications (e.g. clipbrd.exe) do not understand 
307:                // top-down DIBs.
308:                // So we flip the image vertically and create a bottom-up DIB. 
309:                AffineTransform imageFlipTransform = new AffineTransform(1, 0,
310:                        0, -1, 0, height);
311:
312:                Graphics2D g2d = bimage.createGraphics();
313:
314:                try {
315:                    g2d.drawImage(image, imageFlipTransform, null);
316:                } finally {
317:                    g2d.dispose();
318:                }
319:
320:                DataBufferByte buffer = (DataBufferByte) raster.getDataBuffer();
321:
322:                byte[] imageData = buffer.getData();
323:                return imageDataToPlatformImageBytes(imageData, width, height,
324:                        format);
325:            }
326:
327:            /**
328:             * Returns a byte array which contains data special for the given format
329:             * and for the given image data.
330:             */
331:            private native byte[] imageDataToPlatformImageBytes(
332:                    byte[] imageData, int width, int height, long format);
333:
334:            /**
335:             * Translates either a byte array or an input stream which contain
336:             * platform-specific image data in the given format into an Image.
337:             */
338:            protected Image platformImageBytesOrStreamToImage(InputStream str,
339:                    byte[] bytes, long format) throws IOException {
340:                String mimeType = null;
341:                if (format == CF_PNG) {
342:                    mimeType = "image/png";
343:                } else if (format == CF_JFIF) {
344:                    mimeType = "image/jpeg";
345:                }
346:                if (mimeType != null) {
347:                    return standardImageBytesOrStreamToImage(str, bytes,
348:                            mimeType);
349:                }
350:
351:                if (bytes == null) {
352:                    bytes = inputStreamToByteArray(str);
353:                }
354:
355:                int[] imageData = platformImageBytesToImageData(bytes, format);
356:                if (imageData == null) {
357:                    throw new IOException("data translation failed");
358:                }
359:
360:                int len = imageData.length - 2;
361:                int width = imageData[len];
362:                int height = imageData[len + 1];
363:
364:                DataBufferInt buffer = new DataBufferInt(imageData, len);
365:                WritableRaster raster = Raster.createPackedRaster(buffer,
366:                        width, height, width, bandmasks, null);
367:
368:                return new BufferedImage(directColorModel, raster, false, null);
369:            }
370:
371:            /**
372:             * Translates a byte array which contains platform-specific image data in
373:             * the given format into an integer array which contains pixel values in 
374:             * ARGB format. The two last elements in the array specify width and
375:             * height of the image respectively.
376:             */
377:            private native int[] platformImageBytesToImageData(byte[] bytes,
378:                    long format) throws IOException;
379:
380:            protected native String[] dragQueryFile(byte[] bytes);
381:        }
382:
383:        final class WToolkitThreadBlockedHandler extends Mutex implements 
384:                ToolkitThreadBlockedHandler {
385:
386:            public void enter() {
387:                if (!isOwned()) {
388:                    throw new IllegalMonitorStateException();
389:                }
390:                unlock();
391:                startSecondaryEventLoop();
392:                lock();
393:            }
394:
395:            public void exit() {
396:                if (!isOwned()) {
397:                    throw new IllegalMonitorStateException();
398:                }
399:                WToolkit.quitSecondaryEventLoop();
400:            }
401:
402:            private native void startSecondaryEventLoop();
403:        }
404:
405:        enum EHTMLReadMode {
406:            HTML_READ_ALL, HTML_READ_FRAGMENT, HTML_READ_SELECTION
407:        }
408:
409:        /**
410:         * on decode: This stream takes an InputStream which provides data in CF_HTML format,
411:         * strips off the description and context to extract the original HTML data.
412:         * 
413:         * on encode: static convertToHTMLFormat is responsible for HTML clipboard header creation
414:         */
415:        class HTMLCodec extends InputStream {
416:            //static section
417:            public static final String ENCODING = "UTF-8";
418:
419:            public static final String VERSION = "Version:";
420:            public static final String START_HTML = "StartHTML:";
421:            public static final String END_HTML = "EndHTML:";
422:            public static final String START_FRAGMENT = "StartFragment:";
423:            public static final String END_FRAGMENT = "EndFragment:";
424:            public static final String START_SELECTION = "StartSelection:"; //optional
425:            public static final String END_SELECTION = "EndSelection:"; //optional
426:
427:            public static final String START_FRAGMENT_CMT = "<!--StartFragment-->";
428:            public static final String END_FRAGMENT_CMT = "<!--EndFragment-->";
429:            public static final String SOURCE_URL = "SourceURL:";
430:            public static final String DEF_SOURCE_URL = "about:blank";
431:
432:            public static final String EOLN = "\r\n";
433:
434:            private static final String VERSION_NUM = "1.0";
435:            private static final int PADDED_WIDTH = 10;
436:
437:            private static String toPaddedString(int n, int width) {
438:                String string = "" + n;
439:                int len = string.length();
440:                if (n >= 0 && len < width) {
441:                    char[] array = new char[width - len];
442:                    Arrays.fill(array, '0');
443:                    StringBuffer buffer = new StringBuffer(width);
444:                    buffer.append(array);
445:                    buffer.append(string);
446:                    string = buffer.toString();
447:                }
448:                return string;
449:            }
450:
451:            /**
452:             * convertToHTMLFormat adds the MS HTML clipboard header to byte array that 
453:             * contains the parameters pairs.
454:             * 
455:             * The consequence of parameters is fixed, but some or all of them could be
456:             * omitted. One parameter per one text line.
457:             * It looks like that:
458:             * 
459:             * Version:1.0\r\n                -- current supported version
460:             * StartHTML:000000192\r\n        -- shift in array to the first byte after the header
461:             * EndHTML:000000757\r\n          -- shift in array of last byte for HTML syntax analysis
462:             * StartFragment:000000396\r\n    -- shift in array jast after <!--StartFragment-->
463:             * EndFragment:000000694\r\n      -- shift in array before start  <!--EndFragment-->
464:             * StartSelection:000000398\r\n   -- shift in array of the first char in copied selection
465:             * EndSelection:000000692\r\n     -- shift in array of the last char in copied selection
466:             * SourceURL:http://sun.com/\r\n  -- base URL for related referenses
467:             * <HTML>...<BODY>...<!--StartFragment-->.....................<!--EndFragment-->...</BODY><HTML>
468:             * ^                                     ^ ^                ^^                                 ^
469:             * \ StartHTML                           | \-StartSelection | \EndFragment              EndHTML/
470:             *                                       \-StartFragment    \EndSelection
471:             * 
472:             *Combinations with tags sequence  
473:             *<!--StartFragment--><HTML>...<BODY>...</BODY><HTML><!--EndFragment-->
474:             * or
475:             *<HTML>...<!--StartFragment-->...<BODY>...</BODY><!--EndFragment--><HTML>
476:             * are vailid too.
477:             */
478:            public static byte[] convertToHTMLFormat(byte[] bytes) {
479:                // Calculate section offsets
480:                String htmlPrefix = "";
481:                String htmlSuffix = "";
482:                {
483:                    //we have extend the fragment to full HTML document correctly 
484:                    //to avoid HTML and BODY tags doubling
485:                    String stContext = new String(bytes);
486:                    String stUpContext = stContext.toUpperCase();
487:                    if (-1 == stUpContext.indexOf("<HTML")) {
488:                        htmlPrefix = "<HTML>";
489:                        htmlSuffix = "</HTML>";
490:                        if (-1 == stUpContext.indexOf("<BODY")) {
491:                            htmlPrefix = htmlPrefix + "<BODY>";
492:                            htmlSuffix = "</BODY>" + htmlSuffix;
493:                        }
494:                        ;
495:                    }
496:                    ;
497:                    htmlPrefix = htmlPrefix + START_FRAGMENT_CMT;
498:                    htmlSuffix = END_FRAGMENT_CMT + htmlSuffix;
499:                }
500:
501:                String stBaseUrl = DEF_SOURCE_URL;
502:                int nStartHTML = VERSION.length() + VERSION_NUM.length()
503:                        + EOLN.length() + START_HTML.length() + PADDED_WIDTH
504:                        + EOLN.length() + END_HTML.length() + PADDED_WIDTH
505:                        + EOLN.length() + START_FRAGMENT.length()
506:                        + PADDED_WIDTH + EOLN.length() + END_FRAGMENT.length()
507:                        + PADDED_WIDTH + EOLN.length() + SOURCE_URL.length()
508:                        + stBaseUrl.length() + EOLN.length();
509:                int nStartFragment = nStartHTML + htmlPrefix.length();
510:                int nEndFragment = nStartFragment + bytes.length - 1;
511:                int nEndHTML = nEndFragment + htmlSuffix.length();
512:
513:                StringBuilder header = new StringBuilder(nStartFragment
514:                        + START_FRAGMENT_CMT.length());
515:                //header
516:                header.append(VERSION);
517:                header.append(VERSION_NUM);
518:                header.append(EOLN);
519:
520:                header.append(START_HTML);
521:                header.append(toPaddedString(nStartHTML, PADDED_WIDTH));
522:                header.append(EOLN);
523:
524:                header.append(END_HTML);
525:                header.append(toPaddedString(nEndHTML, PADDED_WIDTH));
526:                header.append(EOLN);
527:
528:                header.append(START_FRAGMENT);
529:                header.append(toPaddedString(nStartFragment, PADDED_WIDTH));
530:                header.append(EOLN);
531:
532:                header.append(END_FRAGMENT);
533:                header.append(toPaddedString(nEndFragment, PADDED_WIDTH));
534:                header.append(EOLN);
535:
536:                header.append(SOURCE_URL);
537:                header.append(stBaseUrl);
538:                header.append(EOLN);
539:
540:                //HTML 
541:                header.append(htmlPrefix);
542:
543:                byte[] headerBytes = null, trailerBytes = null;
544:
545:                try {
546:                    headerBytes = new String(header).getBytes(ENCODING);
547:                    trailerBytes = htmlSuffix.getBytes(ENCODING);
548:                } catch (UnsupportedEncodingException cannotHappen) {
549:                }
550:
551:                byte[] retval = new byte[headerBytes.length + bytes.length
552:                        + trailerBytes.length];
553:
554:                System.arraycopy(headerBytes, 0, retval, 0, headerBytes.length);
555:                System.arraycopy(bytes, 0, retval, headerBytes.length,
556:                        bytes.length - 1);
557:                System.arraycopy(trailerBytes, 0, retval, headerBytes.length
558:                        + bytes.length - 1, trailerBytes.length);
559:                retval[retval.length - 1] = 0;
560:
561:                return retval;
562:            }
563:
564:            ////////////////////////////////////
565:            //decoder instance data and methods:
566:
567:            private final BufferedInputStream bufferedStream;
568:            private boolean descriptionParsed = false;
569:            private boolean closed = false;
570:
571:            // InputStreamReader uses an 8K buffer. The size is not customizable.
572:            public static final int BYTE_BUFFER_LEN = 8192;
573:
574:            // CharToByteUTF8.getMaxBytesPerChar returns 3, so we should not buffer
575:            // more chars than 3 times the number of bytes we can buffer.
576:            public static final int CHAR_BUFFER_LEN = BYTE_BUFFER_LEN / 3;
577:
578:            private static final String FAILURE_MSG = "Unable to parse HTML description: ";
579:            private static final String INVALID_MSG = " invalid";
580:
581:            //HTML header mapping: 
582:            private long iHTMLStart,// StartHTML -- shift in array to the first byte after the header
583:                    iHTMLEnd, // EndHTML -- shift in array of last byte for HTML syntax analysis
584:                    iFragStart,// StartFragment -- shift in array jast after <!--StartFragment-->
585:                    iFragEnd, // EndFragment -- shift in array before start <!--EndFragment-->
586:                    iSelStart, // StartSelection -- shift in array of the first char in copied selection
587:                    iSelEnd; // EndSelection -- shift in array of the last char in copied selection
588:            private String stBaseURL; // SourceURL -- base URL for related referenses
589:            private String stVersion; // Version -- current supported version
590:
591:            //Stream reader markers:
592:            private long iStartOffset, iEndOffset, iReadCount;
593:
594:            private EHTMLReadMode readMode;
595:
596:            public HTMLCodec(InputStream _bytestream, EHTMLReadMode _readMode)
597:                    throws IOException {
598:                bufferedStream = new BufferedInputStream(_bytestream,
599:                        BYTE_BUFFER_LEN);
600:                readMode = _readMode;
601:            }
602:
603:            public synchronized String getBaseURL() throws IOException {
604:                if (!descriptionParsed) {
605:                    parseDescription();
606:                }
607:                return stBaseURL;
608:            }
609:
610:            public synchronized String getVersion() throws IOException {
611:                if (!descriptionParsed) {
612:                    parseDescription();
613:                }
614:                return stVersion;
615:            }
616:
617:            /** 
618:             * parseDescription parsing HTML clipboard header as it described in 
619:             * comment to convertToHTMLFormat 
620:             */
621:            private void parseDescription() throws IOException {
622:                stBaseURL = null;
623:                stVersion = null;
624:
625:                // initialization of array offset pointers
626:                // to the same "uninitialized" state.
627:                iHTMLEnd = iHTMLStart = iFragEnd = iFragStart = iSelEnd = iSelStart = -1;
628:
629:                bufferedStream.mark(BYTE_BUFFER_LEN);
630:                String astEntries[] = new String[] {
631:                        //common                                               
632:                        VERSION, START_HTML, END_HTML, START_FRAGMENT,
633:                        END_FRAGMENT,
634:                        //ver 1.0
635:                        START_SELECTION, END_SELECTION, SOURCE_URL };
636:                BufferedReader bufferedReader = new BufferedReader(
637:                        new InputStreamReader(bufferedStream, ENCODING),
638:                        CHAR_BUFFER_LEN);
639:                long iHeadSize = 0;
640:                long iCRSize = EOLN.length();
641:                int iEntCount = astEntries.length;
642:                boolean bContinue = true;
643:
644:                for (int iEntry = 0; iEntry < iEntCount; ++iEntry) {
645:                    String stLine = bufferedReader.readLine();
646:                    if (null == stLine) {
647:                        break;
648:                    }
649:                    //some header entries are optional, but the order is fixed.
650:                    for (; iEntry < iEntCount; ++iEntry) {
651:                        if (!stLine.startsWith(astEntries[iEntry])) {
652:                            continue;
653:                        }
654:                        iHeadSize += stLine.length() + iCRSize;
655:                        String stValue = stLine.substring(
656:                                astEntries[iEntry].length()).trim();
657:                        if (null != stValue) {
658:                            try {
659:                                switch (iEntry) {
660:                                case 0:
661:                                    stVersion = stValue;
662:                                    break;
663:                                case 1:
664:                                    iHTMLStart = Integer.parseInt(stValue);
665:                                    break;
666:                                case 2:
667:                                    iHTMLEnd = Integer.parseInt(stValue);
668:                                    break;
669:                                case 3:
670:                                    iFragStart = Integer.parseInt(stValue);
671:                                    break;
672:                                case 4:
673:                                    iFragEnd = Integer.parseInt(stValue);
674:                                    break;
675:                                case 5:
676:                                    iSelStart = Integer.parseInt(stValue);
677:                                    break;
678:                                case 6:
679:                                    iSelEnd = Integer.parseInt(stValue);
680:                                    break;
681:                                case 7:
682:                                    stBaseURL = stValue;
683:                                    break;
684:                                }
685:                                ;
686:                            } catch (NumberFormatException e) {
687:                                throw new IOException(FAILURE_MSG
688:                                        + astEntries[iEntry] + " value " + e
689:                                        + INVALID_MSG);
690:                            }
691:                        }
692:                        break;
693:                    }
694:                }
695:                //some entries could absent in HTML header,
696:                //so we have find they by another way.
697:                if (-1 == iHTMLStart)
698:                    iHTMLStart = iHeadSize;
699:                if (-1 == iFragStart)
700:                    iFragStart = iHTMLStart;
701:                if (-1 == iFragEnd)
702:                    iFragEnd = iHTMLEnd;
703:                if (-1 == iSelStart)
704:                    iSelStart = iFragStart;
705:                if (-1 == iSelEnd)
706:                    iSelEnd = iFragEnd;
707:
708:                //one of possible modes
709:                switch (readMode) {
710:                case HTML_READ_ALL:
711:                    iStartOffset = iHTMLStart;
712:                    iEndOffset = iHTMLEnd;
713:                    break;
714:                case HTML_READ_FRAGMENT:
715:                    iStartOffset = iFragStart;
716:                    iEndOffset = iFragEnd;
717:                    break;
718:                case HTML_READ_SELECTION:
719:                default:
720:                    iStartOffset = iSelStart;
721:                    iEndOffset = iSelEnd;
722:                    break;
723:                }
724:
725:                bufferedStream.reset();
726:                if (-1 == iStartOffset) {
727:                    throw new IOException(FAILURE_MSG + "invalid HTML format.");
728:                }
729:                iReadCount = bufferedStream.skip(iStartOffset);
730:                if (iStartOffset != iReadCount) {
731:                    throw new IOException(FAILURE_MSG
732:                            + "Byte stream ends in description.");
733:                }
734:                descriptionParsed = true;
735:            }
736:
737:            public synchronized int read() throws IOException {
738:                if (closed) {
739:                    throw new IOException("Stream closed");
740:                }
741:
742:                if (!descriptionParsed) {
743:                    parseDescription();
744:                }
745:                if (-1 != iEndOffset && iReadCount >= iEndOffset) {
746:                    return -1;
747:                }
748:
749:                int retval = bufferedStream.read();
750:                if (retval == -1) {
751:                    return -1;
752:                }
753:                ++iReadCount;
754:                return retval;
755:            }
756:
757:            public synchronized void close() throws IOException {
758:                if (!closed) {
759:                    closed = true;
760:                    bufferedStream.close();
761:                }
762:            }
763:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.