Source Code Cross Referenced for JGraphpadSVGServer.java in  » Graphic-Library » jgraphpad » com » jgraph » svgplugin » 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 » Graphic Library » jgraphpad » com.jgraph.svgplugin 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /* 
002:         * $Id: JGraphpadSVGServer.java,v 1.2 2006/01/31 12:10:34 gaudenz Exp $
003:         * Copyright (c) 2001-2005, Gaudenz Alder
004:         * 
005:         * All rights reserved.
006:         * 
007:         * See LICENSE file for license details. If you are unable to locate
008:         * this file please contact info (at) jgraph (dot) com.
009:         */
010:        package com.jgraph.svgplugin;
011:
012:        import java.awt.Color;
013:        import java.awt.image.BufferedImage;
014:        import java.io.BufferedReader;
015:        import java.io.ByteArrayInputStream;
016:        import java.io.ByteArrayOutputStream;
017:        import java.io.IOException;
018:        import java.io.InputStream;
019:        import java.io.InputStreamReader;
020:        import java.io.OutputStream;
021:        import java.io.PrintWriter;
022:        import java.net.ServerSocket;
023:        import java.net.Socket;
024:        import java.net.URLEncoder;
025:        import java.util.Date;
026:        import java.util.Enumeration;
027:        import java.util.Locale;
028:        import java.util.Properties;
029:        import java.util.StringTokenizer;
030:        import java.util.TimeZone;
031:
032:        import javax.imageio.ImageIO;
033:        import javax.swing.JPanel;
034:
035:        import org.jgraph.JGraph;
036:        import org.jgraph.graph.GraphLayoutCache;
037:
038:        import com.jgraph.JGraphEditor;
039:        import com.jgraph.JGraphpad;
040:        import com.jgraph.editor.JGraphEditorDiagram;
041:        import com.jgraph.editor.JGraphEditorModel;
042:        import com.jgraph.editor.JGraphEditorResources;
043:        import com.jgraph.pad.util.JGraphpadImageEncoder;
044:
045:        /**
046:         * Simple webserver to stream SVG, PNG and JPG content to clients. This
047:         * implementation is based on nanoHttpd (http://nanohttpd.sourceforge.net/).
048:         */
049:        public class JGraphpadSVGServer {
050:
051:            /**
052:             * Some HTTP response status codes
053:             */
054:            public static final String HTTP_OK = "200 OK",
055:                    HTTP_REDIRECT = "301 Moved Permanently",
056:                    HTTP_FORBIDDEN = "403 Forbidden",
057:                    HTTP_NOTFOUND = "404 Not Found",
058:                    HTTP_BADREQUEST = "400 Bad Request",
059:                    HTTP_INTERNALERROR = "500 Internal Server Error",
060:                    HTTP_NOTIMPLEMENTED = "501 Not Implemented";
061:
062:            /**
063:             * Common mime types for dynamic content
064:             */
065:            public static final String MIME_PLAINTEXT = "text/plain",
066:                    MIME_HTML = "text/html",
067:                    MIME_DEFAULT_BINARY = "application/octet-stream",
068:                    MIME_PNG = "image/png", MIME_JPG = "image/jpeg";
069:
070:            /**
071:             * Holds the socket the server is listening on.
072:             */
073:            protected ServerSocket serverSocket;
074:
075:            /**
076:             * References the enclosing editor.
077:             */
078:            protected JGraphEditor editor;
079:
080:            /**
081:             * Starts a HTTP server for the enclosing editor on the specified port.
082:             * <p>
083:             * Throws an IOException if the socket is already in use
084:             */
085:            public JGraphpadSVGServer(JGraphEditor editor, int port)
086:                    throws IOException {
087:                this .editor = editor;
088:                serverSocket = new ServerSocket(port);
089:                Thread t = new Thread(new Runnable() {
090:                    public void run() {
091:                        try {
092:                            while (true)
093:                                new HTTPSession(serverSocket.accept());
094:                        } catch (IOException ioe) {
095:                            // ignore
096:                        }
097:                    }
098:                });
099:                t.setDaemon(true);
100:                t.start();
101:            }
102:
103:            /**
104:             * Serves the response for the specified request. This returns a HTML index
105:             * containing the links to the diagrams in the editor's document model, or
106:             * one of the diagrams as an SVG, JPG or PNG image.
107:             * 
108:             * @param uri
109:             *            Percent-decoded URI without parameters, for example
110:             *            "/index.cgi"
111:             * @param method
112:             *            "GET", "POST" etc.
113:             * @param parms
114:             *            Parsed, percent decoded parameters from URI and, in case of
115:             *            POST, data.
116:             * @param header
117:             *            Header entries, percent decoded
118:             * @return HTTP response, see class Response for details
119:             * @throws IOException
120:             */
121:            public Response serve(String uri, String method, Properties header,
122:                    Properties parms) throws IOException {
123:                Response response = null;
124:                String format = parms.getProperty("format");
125:                JGraph graph = getGraph(uri);
126:                if (uri.equals("/"))
127:                    response = serveIndex();
128:                else if (graph != null) {
129:
130:                    // Responds with a simple HTML info if the graph is empty
131:                    if (graph.getModel().getRootCount() == 0)
132:                        response = new Response(HTTP_OK, MIME_HTML,
133:                                JGraphEditorResources
134:                                        .getString("GraphContainsNoData"));
135:
136:                    // Otherwise responds with the image in the requested format
137:                    else if (format == null)
138:                        response = serveSVG(graph);
139:                    else if (JGraphpad.isImage(format))
140:                        response = serveImage(graph, format);
141:                }
142:                return response;
143:            }
144:
145:            /**
146:             * Produces an SVG image of the specified graph.
147:             */
148:            protected Response serveSVG(JGraph graph) throws IOException {
149:                OutputStream out = new ByteArrayOutputStream();
150:                JGraphpadSVGAction.writeSVG(graph, out, 10);
151:                out.close();
152:                return new Response(HTTP_OK, JGraphpadSVGAction.MIME_SVG, out
153:                        .toString());
154:            }
155:
156:            /**
157:             * Produces a JPG or PNG image of the specified graph.
158:             */
159:            protected Response serveImage(JGraph graph, String format)
160:                    throws IOException {
161:                ByteArrayOutputStream out = new ByteArrayOutputStream();
162:                BufferedImage img = graph.getImage(Color.white, 5);
163:                if (format.equalsIgnoreCase("gif"))
164:                    JGraphpadImageEncoder.writeGIF(img, out);
165:                else
166:                    ImageIO.write(img, format, out);
167:                out.close();
168:                return new Response(HTTP_OK,
169:                        (format.equalsIgnoreCase("png")) ? MIME_PNG : MIME_JPG,
170:                        out.toByteArray());
171:            }
172:
173:            /**
174:             * Produces a HTML index page of all diagrams in the document model.
175:             */
176:            protected Response serveIndex() {
177:                String content = "";
178:                JGraphEditorModel model = (JGraphEditorModel) editor.getModel();
179:                Object root = model.getRoot();
180:                int childCount = model.getChildCount(root);
181:                if (childCount == 0)
182:                    content += JGraphEditorResources.getString("NoDocument");
183:                for (int i = 0; i < model.getChildCount(root); i++) {
184:                    Object child = model.getChild(root, i);
185:                    for (int j = 0; j < model.getChildCount(child); j++) {
186:                        Object diagram = model.getChild(child, j);
187:                        String label = String.valueOf(child) + "."
188:                                + String.valueOf(diagram);
189:                        content += label + ":&nbsp;";
190:                        content += "<a href=\"" + String.valueOf(i) + "/"
191:                                + String.valueOf(j) + "/\">SVG</a>&nbsp;";
192:                        content += "<a href=\"" + String.valueOf(i) + "/"
193:                                + String.valueOf(j)
194:                                + "?format=png\">PNG</a>&nbsp;";
195:                        content += "<a href=\"" + String.valueOf(i) + "/"
196:                                + String.valueOf(j)
197:                                + "?format=jpg\">JPG</a>&nbsp;";
198:                        content += "<a href=\"" + String.valueOf(i) + "/"
199:                                + String.valueOf(j)
200:                                + "?format=gif\">GIF</a></br>";
201:                    }
202:                }
203:                return new Response(HTTP_OK, MIME_HTML, content);
204:            }
205:
206:            /**
207:             * Returns a JGraph for the specified reference. The refence is of the form
208:             * i/j/k/... where i is the index of the first parent in the model, j is the
209:             * index of the child etc. If the model element is a
210:             * {@link JGraphEditorDiagram} then a graph is created using
211:             * {@link #createGraph(GraphLayoutCache)} and returned.
212:             */
213:            protected JGraph getGraph(String reference) {
214:                try {
215:                    Object parent = editor.getModel().getRoot();
216:                    String[] path = reference.substring(1).split("/");
217:                    for (int i = 0; i < path.length; i++)
218:                        parent = editor.getModel().getChild(parent,
219:                                Integer.parseInt(path[i]));
220:                    if (parent instanceof  JGraphEditorDiagram) {
221:                        GraphLayoutCache cache = ((JGraphEditorDiagram) parent)
222:                                .getGraphLayoutCache();
223:                        return createGraph(cache);
224:                    }
225:                } catch (Exception e) {
226:                    // ignore
227:                }
228:                return null;
229:            }
230:
231:            /**
232:             * Creates a new graph for the specified cache and puts it into the
233:             * backingFrame component hierachy.
234:             */
235:            protected JGraph createGraph(GraphLayoutCache cache) {
236:                JGraph graph = editor.getFactory().createGraph(cache);
237:                // "Headless Swing Hack"
238:                JPanel panel = new JPanel();
239:                panel.setDoubleBuffered(false);
240:                panel.add(graph);
241:                panel.setVisible(true); // required
242:                panel.setEnabled(true); // also required
243:                panel.addNotify(); // simlutes pack on jframe
244:                panel.validate();
245:                return graph;
246:            }
247:
248:            /**
249:             * HTTP response. Return one of these from serve().
250:             */
251:            public class Response {
252:                /**
253:                 * Default constructor: response = HTTP_OK, data = mime = 'null'
254:                 */
255:                public Response() {
256:                    this .status = HTTP_OK;
257:                }
258:
259:                /**
260:                 * Basic constructor.
261:                 */
262:                public Response(String status, String mimeType, InputStream data) {
263:                    this .status = status;
264:                    this .mimeType = mimeType;
265:                    this .data = data;
266:                }
267:
268:                /**
269:                 * Convenience method that makes an InputStream out of given text.
270:                 */
271:                public Response(String status, String mimeType, String txt) {
272:                    this (status, mimeType, txt.getBytes());
273:                }
274:
275:                /**
276:                 * Convenience method that makes an InputStream out of given text.
277:                 */
278:                public Response(String status, String mimeType, byte[] bytes) {
279:                    this .status = status;
280:                    this .mimeType = mimeType;
281:                    this .data = new ByteArrayInputStream(bytes);
282:                }
283:
284:                /**
285:                 * Convenience method that makes an InputStream out of given text.
286:                 */
287:                public Response(String status, String mimeType, OutputStream out) {
288:                    this .status = status;
289:                    this .mimeType = mimeType;
290:                }
291:
292:                /**
293:                 * Adds given line to the header.
294:                 */
295:                public void addHeader(String name, String value) {
296:                    header.put(name, value);
297:                }
298:
299:                /**
300:                 * HTTP status code after processing, eg "200 OK", HTTP_OK
301:                 */
302:                public String status;
303:
304:                /**
305:                 * MIME type of content, e.g. "text/html"
306:                 */
307:                public String mimeType;
308:
309:                /**
310:                 * Data of the response, may be null.
311:                 */
312:                public InputStream data;
313:
314:                /**
315:                 * Headers for the HTTP response. Use addHeader() to add lines.
316:                 */
317:                public Properties header = new Properties();
318:            }
319:
320:            /**
321:             * Handles one session, i.e. parses the HTTP request and returns the
322:             * response.
323:             */
324:            private class HTTPSession implements  Runnable {
325:                public HTTPSession(Socket s) {
326:                    mySocket = s;
327:                    Thread t = new Thread(this );
328:                    t.setDaemon(true);
329:                    t.start();
330:                }
331:
332:                public void run() {
333:                    try {
334:                        InputStream is = mySocket.getInputStream();
335:                        if (is == null)
336:                            return;
337:                        BufferedReader in = new BufferedReader(
338:                                new InputStreamReader(is));
339:
340:                        // Read the request line
341:                        StringTokenizer st = new StringTokenizer(in.readLine());
342:                        if (!st.hasMoreTokens())
343:                            sendError(HTTP_BADREQUEST,
344:                                    "BAD REQUEST: Syntax error. Usage: GET /example/file.html");
345:
346:                        String method = st.nextToken();
347:
348:                        if (!st.hasMoreTokens())
349:                            sendError(HTTP_BADREQUEST,
350:                                    "BAD REQUEST: Missing URI. Usage: GET /example/file.html");
351:
352:                        String uri = decodePercent(st.nextToken());
353:
354:                        // Decode parameters from the URI
355:                        Properties parms = new Properties();
356:                        int qmi = uri.indexOf('?');
357:                        if (qmi >= 0) {
358:                            decodeParms(uri.substring(qmi + 1), parms);
359:                            uri = decodePercent(uri.substring(0, qmi));
360:                        }
361:
362:                        // If there's another token, it's protocol version,
363:                        // followed by HTTP headers. Ignore version but parse headers.
364:                        Properties header = new Properties();
365:                        if (st.hasMoreTokens()) {
366:                            String line = in.readLine();
367:                            while (line.trim().length() > 0) {
368:                                int p = line.indexOf(':');
369:                                header.put(line.substring(0, p).trim(), line
370:                                        .substring(p + 1).trim());
371:                                line = in.readLine();
372:                            }
373:                        }
374:
375:                        // If the method is POST, there may be parameters
376:                        // in data section, too, read another line:
377:                        if (method.equalsIgnoreCase("POST"))
378:                            decodeParms(in.readLine(), parms);
379:
380:                        // Ok, now do the serve()
381:                        Response r = serve(uri, method, header, parms);
382:                        if (r == null)
383:                            sendError(HTTP_INTERNALERROR,
384:                                    "SERVER INTERNAL ERROR: Serve() returned a null response.");
385:                        else
386:                            sendResponse(r.status, r.mimeType, r.header, r.data);
387:
388:                        in.close();
389:                    } catch (Exception ioe) {
390:                        try {
391:                            sendError(HTTP_INTERNALERROR,
392:                                    "SERVER INTERNAL ERROR: IOException: "
393:                                            + ioe.getMessage());
394:                        } catch (Throwable t) {
395:                        }
396:                    }
397:                }
398:
399:                /**
400:                 * Decodes the percent encoding scheme. <br/>For example:
401:                 * "an+example%20string" -> "an example string"
402:                 */
403:                private String decodePercent(String str)
404:                        throws InterruptedException {
405:                    try {
406:                        StringBuffer sb = new StringBuffer();
407:                        for (int i = 0; i < str.length(); i++) {
408:                            char c = str.charAt(i);
409:                            switch (c) {
410:                            case '+':
411:                                sb.append(' ');
412:                                break;
413:                            case '%':
414:                                sb.append((char) Integer.parseInt(str
415:                                        .substring(i + 1, i + 3), 16));
416:                                i += 2;
417:                                break;
418:                            default:
419:                                sb.append(c);
420:                                break;
421:                            }
422:                        }
423:                        return new String(sb.toString().getBytes());
424:                    } catch (Exception e) {
425:                        sendError(HTTP_BADREQUEST,
426:                                "BAD REQUEST: Bad percent-encoding.");
427:                        return null;
428:                    }
429:                }
430:
431:                /**
432:                 * Decodes parameters in percent-encoded URI-format ( e.g.
433:                 * "name=Jack%20Daniels&pass=Single%20Malt" ) and adds them to given
434:                 * Properties.
435:                 */
436:                private void decodeParms(String parms, Properties p)
437:                        throws InterruptedException {
438:                    if (parms == null)
439:                        return;
440:
441:                    StringTokenizer st = new StringTokenizer(parms, "&");
442:                    while (st.hasMoreTokens()) {
443:                        String e = st.nextToken();
444:                        int sep = e.indexOf('=');
445:                        if (sep >= 0)
446:                            p.put(decodePercent(e.substring(0, sep)).trim(),
447:                                    decodePercent(e.substring(sep + 1)));
448:                    }
449:                }
450:
451:                /**
452:                 * Returns an error message as a HTTP response and throws
453:                 * InterruptedException to stop furhter request processing.
454:                 */
455:                private void sendError(String status, String msg)
456:                        throws InterruptedException {
457:                    sendResponse(status, MIME_PLAINTEXT, null,
458:                            new ByteArrayInputStream(msg.getBytes()));
459:                    throw new InterruptedException();
460:                }
461:
462:                /**
463:                 * Sends given response to the socket.
464:                 */
465:                private void sendResponse(String status, String mime,
466:                        Properties header, InputStream data) {
467:                    try {
468:                        if (status == null)
469:                            throw new Error(
470:                                    "sendResponse(): Status can't be null.");
471:
472:                        OutputStream out = mySocket.getOutputStream();
473:                        PrintWriter pw = new PrintWriter(out);
474:                        pw.print("HTTP/1.0 " + status + " \r\n");
475:
476:                        if (mime != null)
477:                            pw.print("Content-Type: " + mime + "\r\n");
478:
479:                        if (header == null
480:                                || header.getProperty("Date") == null)
481:                            pw.print("Date: " + gmtFrmt.format(new Date())
482:                                    + "\r\n");
483:
484:                        if (header != null) {
485:                            Enumeration e = header.keys();
486:                            while (e.hasMoreElements()) {
487:                                String key = (String) e.nextElement();
488:                                String value = header.getProperty(key);
489:                                pw.print(key + ": " + value + "\r\n");
490:                            }
491:                        }
492:
493:                        pw.print("\r\n");
494:                        pw.flush();
495:
496:                        if (data != null) {
497:                            byte[] buff = new byte[2048];
498:                            int read = 2048;
499:                            while (read == 2048) {
500:                                read = data.read(buff, 0, 2048);
501:                                out.write(buff, 0, read);
502:                            }
503:                        }
504:                        out.flush();
505:                        out.close();
506:                        if (data != null)
507:                            data.close();
508:                    } catch (IOException ioe) {
509:                        // Couldn't write? No can do.
510:                        try {
511:                            mySocket.close();
512:                        } catch (Throwable t) {
513:                        }
514:                    }
515:                }
516:
517:                private Socket mySocket;
518:
519:                private BufferedReader myIn;
520:            };
521:
522:            /**
523:             * URL-encodes everything between "/"-characters. Encodes spaces as '%20'
524:             * instead of '+'.
525:             */
526:            private String encodeUri(String uri) {
527:                String newUri = "";
528:                StringTokenizer st = new StringTokenizer(uri, "/ ", true);
529:                while (st.hasMoreTokens()) {
530:                    String tok = st.nextToken();
531:                    if (tok.equals("/"))
532:                        newUri += "/";
533:                    else if (tok.equals(" "))
534:                        newUri += "%20";
535:                    else
536:                        newUri += URLEncoder.encode(tok);
537:                }
538:                return newUri;
539:            }
540:
541:            /**
542:             * GMT date formatter
543:             */
544:            private static java.text.SimpleDateFormat gmtFrmt;
545:            static {
546:                gmtFrmt = new java.text.SimpleDateFormat(
547:                        "E, d MMM yyyy HH:mm:ss 'GMT'", Locale.US);
548:                gmtFrmt.setTimeZone(TimeZone.getTimeZone("GMT"));
549:            }
550:
551:            /**
552:             * @return Returns the serverSocket.
553:             */
554:            public ServerSocket getServerSocket() {
555:                return serverSocket;
556:            }
557:
558:            /**
559:             * @param serverSocket
560:             *            The serverSocket to set.
561:             */
562:            public void setServerSocket(ServerSocket serverSocket) {
563:                this.serverSocket = serverSocket;
564:            }
565:
566:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.