Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Initial import of Java XenAPI console viewer from http://community.ci…

…trix.com/cdn/xs/sdks (licensed GPL + linking exception)
  • Loading branch information...
commit b79ae86e8f6e7d9e69faac6cf67dc863c01847e9 1 parent 4862758
David Scott authored
Showing with 4,167 additions and 4 deletions.
  1. +16 −4 OMakefile
  2. +26 −0 java/Console.html
  3. +339 −0 java/GPL-2
  4. +35 −0 java/LICENSE
  5. +12 −0 java/OMakefile
  6. +30 −0 java/build.xml
  7. +43 −0 java/com/citrix/xenserver/console/ConnectionListener.java
  8. +37 −0 java/com/citrix/xenserver/console/ConsoleListener.java
  9. +231 −0 java/com/citrix/xenserver/console/Initialize.java
  10. +117 −0 java/com/citrix/xenserver/console/KeyMap.java
  11. +170 −0 java/com/citrix/xenserver/console/KeyMap.properties
  12. +108 −0 java/com/citrix/xenserver/console/Main.java
  13. +221 −0 java/com/citrix/xenserver/console/RawHTTP.java
  14. +97 −0 java/com/citrix/xenserver/console/SSLHelper.java
  15. +826 −0 java/com/citrix/xenserver/console/VNCCanvas.java
  16. +66 −0 java/com/citrix/xenserver/console/VNCClient.java
  17. +325 −0 java/com/citrix/xenserver/console/VNCControls.java
  18. +113 −0 java/com/citrix/xenserver/console/VNCFullscreen.java
  19. +48 −0 java/com/citrix/xenserver/console/VNCPixelFormat.java
  20. +1,302 −0 java/com/citrix/xenserver/console/VNCStream.java
  21. BIN  java/com/citrix/xenserver/console/attach_24.png
  22. BIN  java/com/citrix/xenserver/console/button-graphic-console.png
  23. BIN  java/com/citrix/xenserver/console/button-options.png
  24. BIN  java/com/citrix/xenserver/console/cad_24.png
  25. BIN  java/com/citrix/xenserver/console/detach_24.png
  26. +5 −0 ocaml/idl/js_backend/OMakefile
View
20 OMakefile
@@ -60,7 +60,7 @@ export CLEAN_OBJS
clean:
rm -rf doc/
-.SUBDIRS: ocaml scripts
+.SUBDIRS: ocaml scripts java javascript
if $(not $(defined-env COMPILE_OCAML))
@@ -69,6 +69,9 @@ if $(not $(defined-env COMPILE_OCAML))
if $(not $(defined-env COMPILE_JS))
COMPILE_JS = yes
export
+if $(not $(defined-env COMPILE_JAVA))
+ COMPILE_JAVA = yes
+ export
# inherits COMPILE_XENSTUFF from the Makefile (NB don't set it here or else
# you can't build the fakeserver etc on a machine without Xen, e.g. an Apple)
@@ -87,10 +90,19 @@ JS_PHASE1=
JS_PHASE2=js_binding
JS_PHASE3=
+# Java ##############################################################################
+JAVA_PHASE1= XenServerConsole.jar
+JAVA_PHASE2=
+JAVA_PHASE3=
+
JS_PHASE1_TARGETS = $(if $(equal $(COMPILE_JS), yes), $(JS_PHASE1), none)
JS_PHASE2_TARGETS = $(if $(equal $(COMPILE_JS), yes), $(JS_PHASE2), none)
JS_PHASE3_TARGETS = $(if $(equal $(COMPILE_JS), yes), $(JS_PHASE3), none)
+JAVA_PHASE1_TARGETS = $(if $(equal $(COMPILE_JAVA), yes), $(JAVA_PHASE1), none)
+JAVA_PHASE2_TARGETS = $(if $(equal $(COMPILE_JAVA), yes), $(JAVA_PHASE2), none)
+JAVA_PHASE3_TARGETS = $(if $(equal $(COMPILE_JAVA), yes), $(JAVA_PHASE3), none)
+
# Phase 3 targets divided into two depending on whether we're building the Xen stuff or not:
OCAML_PHASE3_XEN = \
ocaml/xapi/xapi \
@@ -162,14 +174,14 @@ OCAML_PHASE3_TARGETS = $(if $(equal $(COMPILE_OCAML), yes), $(OCAML_PHASE3), non
# phase1: build stdlib2
.PHONY: phase1
-phase1: $(OCAML_PHASE1_TARGETS) $(JS_PHASE1_TARGETS)
+phase1: $(OCAML_PHASE1_TARGETS) $(JS_PHASE1_TARGETS) $(JAVA_PHASE1_TARGETS)
mkdir -p $(DIST) $(DIST)/bin
# phase2: build compilers and make autogenerated files
.PHONY: phase2
-phase2: $(OCAML_PHASE2_TARGETS) $(JS_PHASE2_TARGETS)
+phase2: $(OCAML_PHASE2_TARGETS) $(JS_PHASE2_TARGETS) $(JAVA_PHASE2_TARGETS)
# phase3: use autogenerated files to make apps
.PHONY: phase3
-phase3: $(OCAML_PHASE3_TARGETS) $(JS_PHASE3_TARGETS)
+phase3: $(OCAML_PHASE3_TARGETS) $(JS_PHASE3_TARGETS) $(JAVA_PHASE3_TARGETS)
View
26 java/Console.html
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2009 Citrix Systems, Inc.
+ *
+ * Permission to use, copy, modify, and distribute this file for any
+ * purpose with or without fee is hereby granted.
+ */
+
+<html>
+<body>
+<center>
+ <table>
+ <tr>
+ <td>
+ <applet code="com/citrix/xenserver/console/Initialize.class"
+ archive="XenServerConsole.jar"
+ width="800" height="600">
+ <PARAM NAME=SESSION VALUE="OpaqueRef:your_session_here">
+ <PARAM NAME=URL VALUE="https://your.host.here/console.url.here">
+ <PARAM NAME=USEURL VALUE="true">
+ </applet>
+ </td>
+ </tr>
+ </table>
+</center>
+</body>
+</html>
View
339 java/GPL-2
@@ -0,0 +1,339 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Lesser General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) year name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Lesser General
+Public License instead of this License.
View
35 java/LICENSE
@@ -0,0 +1,35 @@
+Copyright (c) 2005-2009 Citrix Systems, Inc.
+
+This library is free software; you can redistribute it and/or modify it under
+the terms of version 2 of the GNU General Public License as published by the
+Free Software Foundation, with the additional linking exception as follows:
+
+ Linking this library statically or dynamically with other modules is
+ making a combined work based on this library. Thus, the terms and
+ conditions of the GNU General Public License cover the whole combination.
+
+ As a special exception, the copyright holders of this library give you
+ permission to link this library with independent modules to produce an
+ executable, regardless of the license terms of these independent modules,
+ and to copy and distribute the resulting executable under terms of your
+ choice, provided that you also meet, for each linked independent module,
+ the terms and conditions of the license of that module. An independent
+ module is a module which is not derived from or based on this library. If
+ you modify this library, you may extend this exception to your version of
+ the library, but you are not obligated to do so. If you do not wish to do
+ so, delete this exception statement from your version.
+
+This program is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+details.
+
+You should have received a copy of the GNU General Public License along with
+this program; if not, write to the Free Software Foundation, Inc., 51 Franklin
+Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+
+This library may be accompanied by pedagogical examples. These do not form
+part of this library, and are licensed for redistribution and modification
+under less restrictive terms. Such examples are licensed clearly at the top
+of each file.
View
12 java/OMakefile
@@ -0,0 +1,12 @@
+.PHONY: XenServerConsole.jar
+XenServerConsole.jar:
+ ant all
+
+.PHONY: clean
+clean:
+ ant clean
+
+.PHONY: install
+install:
+ mkdir -p $(DEBUGDIST)/www
+ $(IDATA) XenServerConsole.jar $(DEBUGDIST)/www
View
30 java/build.xml
@@ -0,0 +1,30 @@
+<!--
+ Copyright (c) 2009 Citrix Systems, Inc.
+
+ Permission to use, copy, modify, and distribute this software for any
+ purpose with or without fee is hereby granted.
+-->
+<project name="XenServerConsole" default="all">
+ <target name="all">
+ <javac srcdir="." destdir="." source="1.5"
+ includes="**/*.java" />
+ <jar destfile="XenServerConsole.jar" basedir="."
+ includes="**/*.class **/*.properties **/*.png">
+ </jar>
+ <zip destfile="XenServerConsole.zip" basedir="."
+ includes="XenServerConsole.jar, Console.html"/>
+
+ <zip destfile="XenServerConsole-src.zip" basedir="."
+ includes="**/*.java **/*.properties **/*.png **/*.html build.xml LICENSE GPL-2"/>
+ </target>
+
+ <target name="clean">
+ <delete>
+ <fileset dir="." includes="**/*.class"/>
+ </delete>
+ <delete file="./XenServerConsole.jar"/>
+ <delete file="./XenServerConsole.zip"/>
+ <delete file="./XenServerConsole-src.zip"/>
+ </target>
+
+</project>
View
43 java/com/citrix/xenserver/console/ConnectionListener.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2005-2009 Citrix Systems, Inc.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as published
+ * by the Free Software Foundation, with the additional linking exception as
+ * follows:
+ *
+ * Linking this library statically or dynamically with other modules is
+ * making a combined work based on this library. Thus, the terms and
+ * conditions of the GNU General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this library give you
+ * permission to link this library with independent modules to produce an
+ * executable, regardless of the license terms of these independent modules,
+ * and to copy and distribute the resulting executable under terms of your
+ * choice, provided that you also meet, for each linked independent module,
+ * the terms and conditions of the license of that module. An independent
+ * module is a module which is not derived from or based on this library. If
+ * you modify this library, you may extend this exception to your version of
+ * the library, but you are not obligated to do so. If you do not wish to do
+ * so, delete this exception statement from your version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc., 51
+ * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+package com.citrix.xenserver.console;
+
+public interface ConnectionListener {
+ public void ConnectionMade();
+
+ public void ConnectionLost(String reason);
+
+ public void ConnectionClosed();
+
+ public void ConnectionFailed(String reason);
+}
View
37 java/com/citrix/xenserver/console/ConsoleListener.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2005-2009 Citrix Systems, Inc.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as published
+ * by the Free Software Foundation, with the additional linking exception as
+ * follows:
+ *
+ * Linking this library statically or dynamically with other modules is
+ * making a combined work based on this library. Thus, the terms and
+ * conditions of the GNU General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this library give you
+ * permission to link this library with independent modules to produce an
+ * executable, regardless of the license terms of these independent modules,
+ * and to copy and distribute the resulting executable under terms of your
+ * choice, provided that you also meet, for each linked independent module,
+ * the terms and conditions of the license of that module. An independent
+ * module is a module which is not derived from or based on this library. If
+ * you modify this library, you may extend this exception to your version of
+ * the library, but you are not obligated to do so. If you do not wish to do
+ * so, delete this exception statement from your version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc., 51
+ * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+package com.citrix.xenserver.console;
+
+public interface ConsoleListener {
+ public void writeline(String line);
+}
View
231 java/com/citrix/xenserver/console/Initialize.java
@@ -0,0 +1,231 @@
+/*
+ * Copyright (c) 2005-2009 Citrix Systems, Inc.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as published
+ * by the Free Software Foundation, with the additional linking exception as
+ * follows:
+ *
+ * Linking this library statically or dynamically with other modules is
+ * making a combined work based on this library. Thus, the terms and
+ * conditions of the GNU General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this library give you
+ * permission to link this library with independent modules to produce an
+ * executable, regardless of the license terms of these independent modules,
+ * and to copy and distribute the resulting executable under terms of your
+ * choice, provided that you also meet, for each linked independent module,
+ * the terms and conditions of the license of that module. An independent
+ * module is a module which is not derived from or based on this library. If
+ * you modify this library, you may extend this exception to your version of
+ * the library, but you are not obligated to do so. If you do not wish to do
+ * so, delete this exception statement from your version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc., 51
+ * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+package com.citrix.xenserver.console;
+
+import javax.swing.BorderFactory;
+import javax.swing.JApplet;
+import javax.swing.JPanel;
+import javax.swing.JScrollPane;
+import javax.swing.JTextArea;
+import javax.swing.SwingUtilities;
+import javax.swing.UIManager;
+
+import java.awt.BorderLayout;
+import java.awt.Color;
+import java.net.URL;
+
+import java.util.logging.Logger;
+import java.util.logging.Level;
+
+public class Initialize extends JApplet implements ConnectionListener,
+ ConsoleListener {
+ private static final Logger logger = Logger.getLogger(Initialize.class.getName());
+
+ static final long serialVersionUID = 0;
+ static public URL path;
+
+ private Main main;
+ private VNCControls controls;
+ private JPanel background = new JPanel(new BorderLayout(), true);
+ private JPanel errorPanel = new JPanel(true);
+ private Thread t;
+ public JTextArea console = new JTextArea();
+
+ private int retries = 5;
+ private boolean connecting = false;
+
+ private boolean logOnConsole = false;
+ private boolean hideCADButton = false;
+
+ private String[] getArgs() {
+ String[] args;
+ if ("true".equals(getParameter("USEURL"))) {
+ args = new String[3];
+ args[0] = getParameter("URL");
+ args[1] = getParameter("SESSION");
+ args[2] = getParameter("USEURL");
+ } else {
+ args = new String[4];
+ args[0] = getParameter("IPADDRESS");
+ args[1] = getParameter("PASSWORD");
+ args[2] = getParameter("USEURL");
+ args[3] = getParameter("PORT");
+ }
+ return args;
+ }
+
+ public void init() {
+ try {
+ logOnConsole = Boolean.valueOf(getParameter("CONSOLELOGGING"));
+ hideCADButton = Boolean.valueOf(getParameter("HIDECAD"));
+ path = getDocumentBase();
+ writeline("");
+ writeline("Loading UI...");
+ UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
+ writeline("Initializing...");
+ String[] args = getArgs();
+ Color c;
+ if (getParameter("BACKCOLOR") != null) {
+ String s = getParameter("BACKCOLOR");
+ String[] vals = s.split(":");
+ if (vals.length == 3 && vals[0].length() == 2
+ && vals[1].length() == 2 && vals[2].length() == 2) {
+ c = new Color(Integer.parseInt(vals[0], 16), Integer
+ .parseInt(vals[1], 16), Integer.parseInt(vals[2],
+ 16));
+ } else {
+ c = Color.WHITE;
+ }
+ } else {
+ c = Color.WHITE;
+ }
+ this.setBackground(c);
+ writeline("Starting main...");
+ main = new Main(args, this, this);
+ writeline("Creating controls...");
+ controls = new VNCControls(main, background, c, !hideCADButton);
+ writeline("Adding controls...");
+ background.add(controls);
+ this.add(background);
+
+ errorPanel.setBackground(c);
+ errorPanel.setLayout(new BorderLayout());
+ console.setBackground(Color.white);
+ console.setEditable(false);
+ JScrollPane areaScrollPane = new JScrollPane(console);
+ areaScrollPane
+ .setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
+ areaScrollPane.setBorder(BorderFactory.createLineBorder(
+ Color.BLACK, 1));
+ errorPanel.add(areaScrollPane, BorderLayout.CENTER);
+ } catch (Exception e) {
+ writeline(e.getMessage());
+ }
+
+ }
+
+ public void start() {
+ writeline("Starting...");
+ main.connect();
+ }
+
+ public void stop() {
+ writeline("Stopping...");
+ if (main != null && main.stream_ != null && main.stream_.isConnected()) {
+ main.stream_.disconnect();
+ }
+ }
+
+ public void destroy() {
+ writeline("Destroying...");
+ }
+
+ public void ConnectionClosed() {
+ writeline("Connection closed");
+ if (retries > 0) {
+
+ controls.consolePanel.remove(main.canvas_);
+ controls.consolePanel.setLayout(new BorderLayout());
+ controls.consolePanel.add(errorPanel);
+ controls.invalidate();
+ controls.validate();
+ controls.consolePanel.invalidate();
+ controls.consolePanel.validate();
+
+ t = new Thread(new Runnable() {
+ public void run() {
+
+ writeline("Reconnecting in 5 seconds...");
+ try {
+ Thread.sleep(5000);
+ } catch (Exception e) {
+ writeline(e.getMessage());
+ }
+ writeline("Retry ".concat(Integer.toString(6 - retries))
+ .concat(" out of 5"));
+ main.connect();
+ retries--;
+ };
+ });
+ t.start();
+ }
+ }
+
+ public void ConnectionLost(String reason) {
+ if (main != null) {
+ if (reason != null) {
+ writeline("Connection lost: ".concat(reason));
+ } else {
+ writeline("Connection lost");
+ }
+ if (!connecting) {
+ connecting = true;
+ ConnectionClosed();
+ }
+ }
+ }
+
+ public void ConnectionMade() {
+ controls.consolePanel.remove(errorPanel);
+ controls.setupConsole();
+ controls.consolePanel.getParent().repaint();
+ controls.consolePanel.invalidate();
+ controls.consolePanel.validate();
+ main.canvas_.requestFocusInWindow();
+ connecting = false;
+ retries = 5;
+ }
+
+ public void ConnectionFailed(String reason) {
+ if (main != null) {
+ writeline("Connection failed: ".concat(reason));
+ // if(!connecting)
+ // {
+ connecting = true;
+ ConnectionClosed();
+ // }
+ }
+ }
+
+ public void writeline(final String line) {
+ SwingUtilities.invokeLater(new Runnable() {
+ public void run() {
+ if (logOnConsole && line != null) {
+ console.append(line);
+ console.append("\n");
+ }
+ System.out.println(line);
+ }
+ });
+ }
+}
View
117 java/com/citrix/xenserver/console/KeyMap.java
@@ -0,0 +1,117 @@
+/*
+ * Copyright (c) 2005-2009 Citrix Systems, Inc.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as published
+ * by the Free Software Foundation, with the additional linking exception as
+ * follows:
+ *
+ * Linking this library statically or dynamically with other modules is
+ * making a combined work based on this library. Thus, the terms and
+ * conditions of the GNU General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this library give you
+ * permission to link this library with independent modules to produce an
+ * executable, regardless of the license terms of these independent modules,
+ * and to copy and distribute the resulting executable under terms of your
+ * choice, provided that you also meet, for each linked independent module,
+ * the terms and conditions of the license of that module. An independent
+ * module is a module which is not derived from or based on this library. If
+ * you modify this library, you may extend this exception to your version of
+ * the library, but you are not obligated to do so. If you do not wish to do
+ * so, delete this exception statement from your version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc., 51
+ * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+package com.citrix.xenserver.console;
+
+import java.awt.event.KeyEvent;
+import java.io.BufferedReader;
+import java.io.InputStreamReader;
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.logging.Logger;
+import java.util.logging.Level;
+
+public class KeyMap {
+ private static final Logger logger = Logger.getLogger(KeyMap.class.getName());
+
+ public static KeyMap getInstance() {
+ return instance_;
+ }
+
+ static KeyMap instance_ = new KeyMap();
+
+ Map<Integer, Integer> map_ = new HashMap<Integer, Integer>();
+
+ public KeyMap() {
+ BufferedReader reader = null;
+ try {
+ reader = new BufferedReader(new InputStreamReader(getClass()
+ .getResourceAsStream("KeyMap.properties")));
+ String line;
+ while ((line = reader.readLine()) != null) {
+ line = line.trim();
+ if (line.length() == 0 || line.startsWith("#")) {
+ continue;
+ }
+ int index = line.indexOf("=0x");
+ if (index == -1) {
+ throw new IOException("malformed line: " + line);
+ }
+ String keycode_str = line.substring(0, index);
+ int keycode = KeyEvent.class.getField(keycode_str).getInt(null);
+ int keysym = Integer.parseInt(line.substring(index + 3), 16);
+ if (map_.containsKey(keycode)) {
+ throw new IOException("Duplicate entry " + line);
+ }
+ map_.put(keycode, keysym);
+ }
+ } catch (Throwable t) {
+ logger.log(Level.WARNING, t.getMessage(), t);
+ }
+ }
+
+ int unicodeToKeysym(int c) {
+ if (c < 0x20) {
+ // The Ctrl- block. By the RFB spec, these should be
+ // transmitted as separate Ctrl and lower-case letter
+ // keystrokes. We've already sent the down-Ctrl, so now we
+ // just need to send the code for the letter. Add 0x60 to move
+ // from the 0-0x1f ASCII range into 0x60-0x7f.
+ return c + 0x60;
+ } else if ((c <= 0x7e) || ((0xa0 <= c) && (c <= 0xff))) {
+ return c;
+ }
+ return -1;
+ }
+
+ public int getKeysym(KeyEvent event) {
+ int result = getMappedKey(event.getKeyCode());
+ if (result == -1) {
+ char c = event.getKeyChar();
+ return c == KeyEvent.CHAR_UNDEFINED ? -1 : unicodeToKeysym(c);
+ } else {
+ return result;
+ }
+ }
+
+ /**
+ * @param keycode
+ * One of the KeyEvent VK_ constants.
+ * @return The keysym for that code, if it is in the map, or -1 otherwise.
+ */
+ public int getMappedKey(int keycode) {
+ Integer ks = map_.get(keycode);
+ return ks == null ? -1 : ks;
+ }
+
+}
View
170 java/com/citrix/xenserver/console/KeyMap.properties
@@ -0,0 +1,170 @@
+VK_SHIFT=0xffe1
+VK_CONTROL=0xffe3
+VK_CAPS_LOCK=0xffe5
+VK_META=0xffe7
+VK_ALT=0xffe9
+# XK_Alt_R
+VK_ALT_GRAPH=0xffea
+# XK_Multi_key
+VK_COMPOSE=0xff20
+# XK_Win_L. VK_WINDOWS is also sent for the right Windows key.
+VK_WINDOWS=0xff5b
+# XK_App
+VK_CONTEXT_MENU=0xff5d
+
+VK_BACK_SPACE=0xff08
+VK_TAB=0xff09
+VK_CLEAR=0xff0b
+VK_ENTER=0xff0d
+VK_PAUSE=0xff13
+VK_SCROLL_LOCK=0xff14
+VK_ESCAPE=0xff1b
+VK_DELETE=0xffff
+
+VK_HOME=0xff50
+VK_LEFT=0xff51
+VK_UP=0xff52
+VK_RIGHT=0xff53
+VK_DOWN=0xff54
+VK_PAGE_UP=0xff55
+VK_PAGE_DOWN=0xff56
+VK_END=0xff57
+VK_BEGIN=0xff58
+
+VK_PRINTSCREEN=0xff61
+VK_INSERT=0xff63
+VK_UNDO=0xff65
+# XK_Redo
+VK_AGAIN=0xff66
+VK_FIND=0xff68
+VK_CANCEL=0xff69
+VK_HELP=0xff6a
+# XK_Mode_switch. I've no idea whether this is right.
+VK_MODECHANGE=0xff7e
+VK_NUM_LOCK=0xff7f
+
+VK_KP_LEFT=0xff96
+VK_KP_UP=0xff97
+VK_KP_RIGHT=0xff98
+VK_KP_DOWN=0xff99
+
+VK_MULTIPLY=0xffaa
+VK_ADD=0xffab
+VK_SEPARATOR=0xffac
+VK_SUBTRACT=0xffad
+VK_DECIMAL=0xffae
+VK_DIVIDE=0xffaf
+
+VK_NUMPAD0=0xffb0
+VK_NUMPAD1=0xffb1
+VK_NUMPAD2=0xffb2
+VK_NUMPAD3=0xffb3
+VK_NUMPAD4=0xffb4
+VK_NUMPAD5=0xffb5
+VK_NUMPAD6=0xffb6
+VK_NUMPAD7=0xffb7
+VK_NUMPAD8=0xffb8
+VK_NUMPAD9=0xffb9
+
+VK_F1=0xffbe
+VK_F2=0xffbf
+VK_F3=0xffc0
+VK_F4=0xffc1
+VK_F5=0xffc2
+VK_F6=0xffc3
+VK_F7=0xffc4
+VK_F8=0xffc5
+VK_F9=0xffc6
+VK_F10=0xffc7
+VK_F11=0xffc8
+VK_F12=0xffc9
+VK_F13=0xffca
+VK_F14=0xffcb
+VK_F15=0xffcc
+VK_F16=0xffcd
+VK_F17=0xffce
+VK_F18=0xffcf
+VK_F19=0xffd0
+VK_F20=0xffd1
+VK_F21=0xffd2
+VK_F22=0xffd3
+VK_F23=0xffd4
+VK_F24=0xffd5
+
+VK_DEAD_GRAVE=0xfe50
+VK_DEAD_ACUTE=0xfe51
+VK_DEAD_CIRCUMFLEX=0xfe52
+VK_DEAD_TILDE=0xfe53
+VK_DEAD_MACRON=0xfe54
+VK_DEAD_BREVE=0xfe55
+VK_DEAD_ABOVEDOT=0xfe56
+VK_DEAD_DIAERESIS=0xfe57
+VK_DEAD_ABOVERING=0xfe58
+VK_DEAD_DOUBLEACUTE=0xfe59
+VK_DEAD_CARON=0xfe5a
+VK_DEAD_CEDILLA=0xfe5b
+VK_DEAD_OGONEK=0xfe5c
+VK_DEAD_IOTA=0xfe5d
+VK_DEAD_VOICED_SOUND=0xfe5e
+VK_DEAD_SEMIVOICED_SOUND=0xfe5f
+
+VK_EURO_SIGN=0x20ac
+# XK_exclamdown
+VK_INVERTED_EXCLAMATION_MARK=0x00a1
+
+# replaced by VK_INPUT_METHOD_ON_OFF for Microsoft Windows and Solaris;
+# might still be used for other platforms
+VK_KANJI=0xff21
+# XK_Muhenkan
+VK_NONCONVERT=0xff22
+# XK_Henkan
+VK_CONVERT=0xff23
+# XK_Romaji
+VK_ROMAN_CHARACTERS=0xff24
+VK_HIRAGANA=0xff25
+VK_KATAKANA=0xff26
+
+# These three are on the Japanese Macintosh keyboard, and select the Japanese
+# input method at the same time as switching mode. Just sending the XK_ for
+# the mode switch might not be enough.
+VK_JAPANESE_ROMAN=0xff24
+VK_JAPANESE_HIRAGANA=0xff25
+VK_JAPANESE_KATAKANA=0xff26
+
+# XK_Zenkaku
+VK_FULL_WIDTH=0xff28
+# XK_Hankaku
+VK_HALF_WIDTH=0xff29
+
+VK_KANA_LOCK=0xff2d
+# replaced by VK_KANA_LOCK for Microsoft Windows and Solaris;
+# might still be used on other platforms
+# XK_Kana_Shift
+VK_KANA=0xff2e
+# XK_Eisu_Shift
+VK_ALPHANUMERIC=0xff2f
+
+# XK_Kanji_Bangou
+VK_CODE_INPUT=0xff37
+# XK_Mae_Koho
+VK_PREVIOUS_CANDIDATE=0xff3e
+# XK_Zen_Koho
+VK_ALL_CANDIDATES=0xff3d
+
+# According to Java: Japanese PC 106 keyboard: kanji. Japanese Solaris
+# keyboard: nihongo.
+# I'm sending XK_Kanji
+VK_INPUT_METHOD_ON_OFF=0xff21
+
+#
+# No known XK_ constants
+#
+
+#VK_FINAL = 0x0018;
+#VK_CUT = 0xFFD1;
+#VK_COPY = 0xFFCD;
+#VK_PASTE = 0xFFCF;
+#VK_PROPS = 0xFFCA;
+#VK_STOP = 0xFFC8;
+# Japanese Solaris keyboard: kakutei
+#VK_ACCEPT
View
108 java/com/citrix/xenserver/console/Main.java
@@ -0,0 +1,108 @@
+/*
+ * Copyright (c) 2005-2009 Citrix Systems, Inc.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as published
+ * by the Free Software Foundation, with the additional linking exception as
+ * follows:
+ *
+ * Linking this library statically or dynamically with other modules is
+ * making a combined work based on this library. Thus, the terms and
+ * conditions of the GNU General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this library give you
+ * permission to link this library with independent modules to produce an
+ * executable, regardless of the license terms of these independent modules,
+ * and to copy and distribute the resulting executable under terms of your
+ * choice, provided that you also meet, for each linked independent module,
+ * the terms and conditions of the license of that module. An independent
+ * module is a module which is not derived from or based on this library. If
+ * you modify this library, you may extend this exception to your version of
+ * the library, but you are not obligated to do so. If you do not wish to do
+ * so, delete this exception statement from your version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc., 51
+ * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+package com.citrix.xenserver.console;
+
+import java.net.Socket;
+import java.net.URL;
+import java.util.logging.Logger;
+import java.util.logging.Level;
+
+import javax.swing.SwingUtilities;
+
+public class Main {
+
+ public static void main(String[] args) throws Throwable {
+ new Main(args, new Initialize(), new Initialize());
+ }
+
+ private static final Logger logger = Logger.getLogger(Main.class.getName());
+
+ public final VNCCanvas canvas_ = new VNCCanvas();
+ public VNCStream stream_;
+ private boolean usessl;
+ private String path;
+ private String auth;
+ private int port;
+ private ConnectionListener _listener;
+ private ConsoleListener _console;
+
+ public boolean firstTime = true;
+
+ public Main(String[] args, ConnectionListener listener,
+ ConsoleListener console) {
+
+ if ("true".equals(args[2])) {
+ usessl = true;
+ } else {
+ usessl = false;
+ port = Integer.parseInt(args[3]);
+ }
+ path = args[0];
+ auth = args[1];
+ stream_ = new VNCStream(canvas_, listener, console);
+ canvas_.setStream(stream_);
+ canvas_.setConsoleListener(console);
+ _listener = listener;
+ _console = console;
+ }
+
+ public void connect() {
+ try {
+ if (usessl) {
+ stream_.disconnect();
+ URL uri = new URL(path);
+ String uuid = auth;
+ RawHTTP http = new RawHTTP("CONNECT", uri.getHost(), 443, uri
+ .getPath().concat("?").concat(uri.getQuery()), uuid,
+ "https".equals(uri.getProtocol()), _listener, _console);
+ http.connect();
+ stream_.connect(http, new char[0]);
+ } else {
+ stream_.disconnect();
+ String password = auth;
+ int n = password.length();
+ char[] c = new char[n];
+ password.getChars(0, n, c, 0);
+ stream_.connectSocket(new Socket(path, port), c);
+ }
+ } catch (final Throwable t) {
+ if (_listener != null) {
+ SwingUtilities.invokeLater(new Runnable() {
+ public void run() {
+ _listener.ConnectionFailed(t.getMessage());
+ }
+ });
+ }
+ }
+ }
+}
View
221 java/com/citrix/xenserver/console/RawHTTP.java
@@ -0,0 +1,221 @@
+/*
+ * Copyright (c) 2005-2009 Citrix Systems, Inc.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as published
+ * by the Free Software Foundation, with the additional linking exception as
+ * follows:
+ *
+ * Linking this library statically or dynamically with other modules is
+ * making a combined work based on this library. Thus, the terms and
+ * conditions of the GNU General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this library give you
+ * permission to link this library with independent modules to produce an
+ * executable, regardless of the license terms of these independent modules,
+ * and to copy and distribute the resulting executable under terms of your
+ * choice, provided that you also meet, for each linked independent module,
+ * the terms and conditions of the license of that module. An independent
+ * module is a module which is not derived from or based on this library. If
+ * you modify this library, you may extend this exception to your version of
+ * the library, but you are not obligated to do so. If you do not wish to do
+ * so, delete this exception statement from your version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc., 51
+ * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+package com.citrix.xenserver.console;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.*;
+import java.security.SecureRandom;
+import java.util.*;
+import java.security.*;
+import java.security.cert.X509Certificate;
+import java.util.logging.Logger;
+import java.util.logging.Level;
+
+import java.util.regex.*;
+
+import javax.net.SocketFactory;
+//import javax.net.ssl.SSLParameters;
+import javax.net.ssl.*;
+import javax.net.ssl.SSLSocket;
+
+//import javax.net.ssl.SSLSocketFactory;
+//import com.sun.net.ssl.SSLContext;
+
+/**
+ * Send an HTTP CONNECT or PUT request to a XenAPI host with a Session ID,
+ * return the connected socket and the Task ID. Used for tunnelling VNC
+ * connections and import/export operations.
+ */
+public final class RawHTTP {
+ private static final Logger logger = Logger.getLogger(RawHTTP.class.getName());
+
+ private static final Pattern END_PATTERN = Pattern.compile("^\r\n$");
+ private static final Pattern HEADER_PATTERN = Pattern
+ .compile("^([A-Z_a-z0-9-]+):\\s*(.*)\r\n$");
+ private static final Pattern HTTP_PATTERN = Pattern
+ .compile("^HTTP/\\d+\\.\\d+ (\\d*) (.*)\r\n$");
+
+ private final String command;
+ private final String host;
+ private final int port;
+ private final String path;
+ private final String session;
+ private final boolean useSSL;
+
+ private final Map<String, String> responseHeaders = new HashMap<String, String>();
+
+ private InputStream ic;
+ private OutputStream oc;
+ private Socket s;
+
+ public InputStream getInputStream() {
+ return ic;
+ }
+
+ public OutputStream getOutputStream() {
+ return oc;
+ }
+
+ public Socket getSocket() {
+ return s;
+ }
+
+ private ConsoleListener _console;
+
+ public RawHTTP(String command, String host, int port, String path,
+ String session, boolean useSSL, ConnectionListener listner,
+ ConsoleListener console) {
+ this.command = command;
+ this.host = host;
+ this.port = port;
+ this.path = path;
+ this.session = session;
+ this.useSSL = useSSL;
+ _console = console;
+ }
+
+ private static final TrustManager[] trustAllCerts = new TrustManager[] {
+ new X509TrustManager() {
+ public X509Certificate[] getAcceptedIssuers() {
+ return null;
+ }
+
+ public void checkClientTrusted(X509Certificate[] certs, String authType) {
+ }
+
+ public void checkServerTrusted(X509Certificate[] certs, String authType) {
+ }
+ }
+ };
+
+ private Socket _getSocket() throws IOException {
+ if (useSSL) {
+ javax.net.ssl.SSLContext context = SSLHelper.getInstance()
+ .getSSLContext();
+ SSLSocket ssl = null;
+ try {
+ context.init(null, trustAllCerts, new SecureRandom());
+ SocketFactory factory = context.getSocketFactory();
+ ssl = (SSLSocket) factory.createSocket(host, port);
+ /* ssl.setSSLParameters(context.getDefaultSSLParameters()); */
+ } catch (IOException e) {
+ _console.writeline("IOException: " + e.getMessage());
+ throw e;
+ } catch (KeyManagementException e) {
+ _console.writeline("KeyManagementException: " + e.getMessage());
+ }
+ return ssl;
+ } else {
+ return new Socket(host, port);
+ }
+ }
+
+ public Socket connect() throws IOException {
+ String[] headers = makeHeaders();
+ s = _getSocket();
+ try {
+ oc = s.getOutputStream();
+ for (String header : headers) {
+ oc.write(header.getBytes());
+ oc.write("\r\n".getBytes());
+ }
+ oc.flush();
+ ic = s.getInputStream();
+ while (true) {
+ String line = readline(ic);
+
+ Matcher m = END_PATTERN.matcher(line);
+ if (m.matches()) {
+ return s;
+ }
+
+ m = HEADER_PATTERN.matcher(line);
+ if (m.matches()) {
+ responseHeaders.put(m.group(1), m.group(2));
+ continue;
+ }
+
+ m = HTTP_PATTERN.matcher(line);
+ if (m.matches()) {
+ String status_code = m.group(1);
+ String reason_phrase = m.group(2);
+ if (!"200".equals(status_code)) {
+ throw new IOException("HTTP status " + status_code
+ + " " + reason_phrase);
+ }
+ } else {
+ throw new IOException("Unknown HTTP line " + line);
+ }
+ }
+ } catch (IOException exn) {
+ s.close();
+ throw exn;
+ } catch (RuntimeException exn) {
+ s.close();
+ throw exn;
+ }
+ }
+
+ public Map<String, String> getResponseHeaders() {
+ return responseHeaders;
+ }
+
+ private String[] makeHeaders() {
+ String[] headers = { String.format("%s %s HTTP/1.0", command, path),
+ String.format("Host: %s", host),
+ String.format("Cookie: session_id=%s", session), "" };
+ return headers;
+ }
+
+ private static String readline(InputStream ic) throws IOException {
+ String result = "";
+ while (true) {
+ try {
+ int c = ic.read();
+
+ if (c == -1) {
+ return result;
+ }
+ result = result + (char) c;
+ if (c == 0x0a /* LF */) {
+ return result;
+ }
+ } catch (IOException e) {
+ ic.close();
+ throw e;
+ }
+ }
+ }
+}
View
97 java/com/citrix/xenserver/console/SSLHelper.java
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 2005-2009 Citrix Systems, Inc.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as published
+ * by the Free Software Foundation, with the additional linking exception as
+ * follows:
+ *
+ * Linking this library statically or dynamically with other modules is
+ * making a combined work based on this library. Thus, the terms and
+ * conditions of the GNU General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this library give you
+ * permission to link this library with independent modules to produce an
+ * executable, regardless of the license terms of these independent modules,
+ * and to copy and distribute the resulting executable under terms of your
+ * choice, provided that you also meet, for each linked independent module,
+ * the terms and conditions of the license of that module. An independent
+ * module is a module which is not derived from or based on this library. If
+ * you modify this library, you may extend this exception to your version of
+ * the library, but you are not obligated to do so. If you do not wish to do
+ * so, delete this exception statement from your version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc., 51
+ * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+package com.citrix.xenserver.console;
+
+import java.security.KeyStore;
+import java.util.logging.Logger;
+import java.util.logging.Level;
+
+import javax.net.ssl.KeyManagerFactory;
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.TrustManagerFactory;
+
+public class SSLHelper {
+ private static final Logger logger = Logger.getLogger(SSLHelper.class.getName());
+
+ public static final String[] cipherSuites = { "TLS_DHE_RSA_WITH_AES_128_CBC_SHA" };
+ private static SSLContext sSSLContext = null;
+ private static SSLHelper instance = new SSLHelper();
+
+ /**
+ * Factory method to get the singleton of this class
+ *
+ * @return <Code>SSLHelper</Code>
+ */
+ public static SSLHelper getInstance() {
+ return instance;
+ }
+
+ public SSLContext getSSLContext() {
+ return sSSLContext;
+ }
+
+ private void init() {
+ try {
+ SSLContext pSSLContext = SSLContext.getInstance("SSL", "SunJSSE");
+
+ // The reference implementation only supports X.509 keys
+ KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509",
+ "SunJSSE");
+ TrustManagerFactory tmf = TrustManagerFactory.getInstance(
+ "SunX509", "SunJSSE");
+
+ // Sun's default kind of key store
+ KeyStore ks = KeyStore.getInstance("JCEKS", "SunJCE");
+
+ char[] password = "b3646d1424de7a06".toCharArray();
+ ks.load(this.getClass().getResourceAsStream("client.ks"), password);
+ // ks.load(ResourceLoader.getResourceAsStream("appserver.ks"),
+ // password);
+ kmf.init(ks, password);
+ tmf.init(ks);
+
+ pSSLContext
+ .init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
+ sSSLContext = pSSLContext;
+ } catch (Exception e) {
+ System.out.println("ERROR: failed to initialize SSLContext: "
+ + e.getMessage());
+ e.printStackTrace();
+ // TODO: handle exceptions
+ }
+ }
+
+ private SSLHelper() {
+ init();
+ }
+}
View
826 java/com/citrix/xenserver/console/VNCCanvas.java
@@ -0,0 +1,826 @@
+/*
+ * Copyright (c) 2005-2009 Citrix Systems, Inc.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as published
+ * by the Free Software Foundation, with the additional linking exception as
+ * follows:
+ *
+ * Linking this library statically or dynamically with other modules is
+ * making a combined work based on this library. Thus, the terms and
+ * conditions of the GNU General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this library give you
+ * permission to link this library with independent modules to produce an
+ * executable, regardless of the license terms of these independent modules,
+ * and to copy and distribute the resulting executable under terms of your
+ * choice, provided that you also meet, for each linked independent module,
+ * the terms and conditions of the license of that module. An independent
+ * module is a module which is not derived from or based on this library. If
+ * you modify this library, you may extend this exception to your version of
+ * the library, but you are not obligated to do so. If you do not wish to do
+ * so, delete this exception statement from your version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc., 51
+ * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+package com.citrix.xenserver.console;
+
+import java.lang.reflect.InvocationTargetException;
+import java.awt.Color;
+import java.awt.Container;
+import java.awt.Cursor;
+import java.awt.Dimension;
+import java.awt.Graphics;
+import java.awt.Graphics2D;
+import java.awt.Image;
+import java.awt.Point;
+import java.awt.Rectangle;
+import java.awt.RenderingHints;
+import java.awt.Toolkit;
+import java.awt.datatransfer.Clipboard;
+import java.awt.datatransfer.ClipboardOwner;
+import java.awt.datatransfer.DataFlavor;
+import java.awt.datatransfer.StringSelection;
+import java.awt.datatransfer.Transferable;
+import java.awt.event.FocusEvent;
+import java.awt.event.FocusListener;
+import java.awt.event.KeyEvent;
+import java.awt.event.KeyListener;
+import java.awt.event.MouseEvent;
+import java.awt.event.MouseListener;
+import java.awt.event.MouseWheelEvent;
+import java.awt.event.MouseMotionListener;
+import java.awt.event.MouseWheelListener;
+import java.awt.event.WindowEvent;
+import java.awt.event.WindowListener;
+import java.awt.image.BufferedImage;
+import java.util.logging.Logger;
+import java.util.logging.Level;
+
+import javax.swing.BorderFactory;
+import javax.swing.ImageIcon;
+import javax.swing.JComponent;
+import javax.swing.JFrame;
+import javax.swing.JScrollPane;
+import javax.swing.SwingUtilities;
+import javax.swing.JPanel;
+
+public class VNCCanvas extends JComponent implements VNCClient, ClipboardOwner,
+ MouseListener, MouseMotionListener, MouseWheelListener, KeyListener,
+ FocusListener {
+ private static final Logger logger = Logger.getLogger(VNCCanvas.class.getName());
+
+ /*
+ * There are two threads coming through here -- the GUI event thread and the
+ * VNC stream. VNC has a tendency to send lots of small rectangles,
+ * especially at startup, so the intention is to gather these up on the
+ * stream thread before punting across to the GUI thread for redraw.
+ * Switching threads on each rectangle causes the GUI thread to stall
+ * processing lots of small updates, blocking other activity in the GUI.
+ *
+ * Accumulation is done on the stream thread, writing to imageGraphics_ and
+ * damageStreamside. When we receive clientFrameBufferUpdate, which is
+ * called whenever a batch of VNC rectangles has been processed,
+ * damageStreamside is copied into damageEventside, and the redraw is
+ * performed.
+ *
+ */
+
+ static final long serialVersionUID = 0;
+
+ private static final KeyMap keyMap = KeyMap.getInstance();
+
+ public boolean isFullscreen = false;
+ public VNCFullscreen screen;
+
+ /**
+ * The width of the border around the panel. This is 1 for the highlight
+ * line, and two for padding.
+ */
+ private static final int BW = 3;
+
+ // private static final Border focusBorder =
+ // BorderFactory.createCompoundBorder(
+ // UIManager.getBorder("Table.focusCellHighlightBorder"),
+ // BorderFactory.createLineBorder(
+ // LookAndFeelManager.PANEL_BACKGROUND_COLOR, 2));
+ // private static final Border noFocusBorder =
+ // BorderFactory.createLineBorder(
+ // LookAndFeelManager.PANEL_BACKGROUND_COLOR, BW);
+
+ private final Toolkit toolkit;
+
+ /**
+ * stream_ may only be changed before the VNCStream is connected.
+ */
+ private VNCStream stream_;
+
+ /**
+ * Volatile, and may be accessed by either the stream or the event thread.
+ * The reference should be copied into the current thread before being
+ * accessed. This will only change when the desktop resizes, in which case
+ * imageGraphics_ will have already changed.
+ */
+ private BufferedImage image_ = null;
+
+ /**
+ * May only be accessed by the stream thread.
+ */
+ private Graphics2D imageGraphics_ = null;
+
+ /**
+ * May only be updated by the stream thread. Damage details will be
+ * accumulated here, and then copied by the event thread into
+ * damageEventside (with the stream thread blocked).
+ */
+ private final Rectangle damageStreamside = new Rectangle();
+
+ private Cursor _cursor;
+
+ /**
+ * May only be accessed by the event thread. Damage details will be copied
+ * here from damageStreamside, when clientFrameBufferUpdate is called.
+ */
+ private final Rectangle damageEventside = new Rectangle();
+
+ /**
+ * May only be accessed from the event thread.
+ */
+ // private BufferedImage thumbnail = null;
+ /**
+ * This reference may be read from any thread, but the instance itself only
+ * be modified from the event thread.
+ */
+ private final ImageIcon thumbnailIcon = new ImageIcon();
+
+ /**
+ * May only be accessed from the event thread.
+ */
+ // private Graphics thumbnailGraphics = null;
+ /**
+ * May only be accessed from the event thread.
+ */
+ // private boolean updateThumbnail = false;
+ /**
+ * May only be accessed from the event thread.
+ */
+ // private double thumbnailRatio;
+ /**
+ * May only be accessed from the event thread.
+ */
+ private String serverText_ = "";
+
+ /**
+ * May only be accessed from the event thread.
+ */
+ // private ConsolePanel panel = null;
+
+ static {
+ // Force early class loading. This pulls in bits of sun.java2d.
+ // BufferedImage i1 =
+ // new BufferedImage(20, 20, BufferedImage.TYPE_INT_RGB);
+ // BufferedImage i2 =
+ // new BufferedImage(18, 18, BufferedImage.TYPE_INT_RGB);
+ // Graphics g1 = i1.getGraphics();
+ // Graphics g2 = i2.getGraphics();
+ // g1.setColor(Color.BLACK);
+ // g1.fillRect(0, 0, 10, 10);
+ // g2.drawImage(i1, 1, 1, 18, 18, 0, 0, 20, 20, null);
+ // g2.copyArea(10, 10, 20, 20, 0, 0);
+ }
+
+ /**
+ * Constructor.
+ */
+ public VNCCanvas() {
+
+ toolkit = Toolkit.getDefaultToolkit();
+
+ // setCursor(LookAndFeelManager.emptyCursor);
+
+ // setBorder(noFocusBorder);
+
+ setDoubleBuffered(true);
+ setOpaque(false);
+
+ BufferedImage blankThumbnail = new BufferedImage(200, 150,
+ BufferedImage.TYPE_INT_RGB);
+ Graphics g = blankThumbnail.getGraphics();
+ g.fillRect(0, 0, 200, 150);
+ thumbnailIcon.setImage(blankThumbnail);
+
+ setFocusTraversalKeysEnabled(false);
+ addFocusListener(this);
+ addMouseListener(this);
+ addMouseMotionListener(this);
+ addMouseWheelListener(this);
+ addKeyListener(this);
+ }
+
+ public Dimension getPreferredSize() {
+ if (image_ != null) {
+ return new Dimension(Translate(_streamWidth),
+ Translate(_streamHeight));
+ }
+ return super.getPreferredSize();
+ }
+
+ public Dimension getMinimumSize() {
+ return getPreferredSize();
+ }
+
+ public Dimension getMaximumSize() {
+ return getPreferredSize();
+ }
+
+ public void setStream(VNCStream stream) {
+ stream_ = stream;
+ }
+
+ private double scaleFactor = 1;
+
+ private void setScaleFactor(double sf) {
+ scaleFactor = sf;
+ }
+
+ private int Translate(int i) {
+ return (int) ((i * scaleFactor));
+ }
+
+ private int TranslateRev(int i) {
+ return (int) (i / (scaleFactor - (double) BW / (double) _streamHeight));
+ }
+
+ public void setUpdateThumbnail(boolean updateThumbnail) {
+ assert SwingUtilities.isEventDispatchThread();
+ // this.updateThumbnail = updateThumbnail;
+ if (updateThumbnail) {
+ repairThumbnail();
+ }
+ }
+
+ private ConsoleListener _console;
+
+ public void setConsoleListener(ConsoleListener console) {
+ _console = console;
+ }
+
+ public void paintComponent(Graphics graphics) {
+
+ if (image_ != null && ui == null) {
+ Graphics2D g2 = (Graphics2D) graphics;
+ g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
+ RenderingHints.VALUE_INTERPOLATION_BILINEAR);
+ g2.setRenderingHint(RenderingHints.KEY_RENDERING,
+ RenderingHints.VALUE_RENDER_SPEED);
+ g2.setRenderingHint(RenderingHints.KEY_ALPHA_INTERPOLATION,
+ RenderingHints.VALUE_ALPHA_INTERPOLATION_SPEED);
+ g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
+ RenderingHints.VALUE_ANTIALIAS_OFF);
+ g2.setRenderingHint(RenderingHints.KEY_COLOR_RENDERING,
+ RenderingHints.VALUE_COLOR_RENDER_SPEED);
+ g2.setRenderingHint(RenderingHints.KEY_DITHERING,
+ RenderingHints.VALUE_DITHER_DISABLE);
+ if (!isFullscreen) {
+ g2.drawImage(image_, BW, BW, Translate(_streamWidth) - 2 * BW,
+ Translate(_streamHeight) - 2 * BW, null);
+ } else {
+ g2.drawImage(image_, 0, 0, Translate(_streamWidth),
+ Translate(_streamHeight), null);
+ }
+ }
+ }
+
+ public void paintBorder(Graphics graphics) {
+ this.setSize(Translate(_streamWidth), Translate(_streamHeight));
+ super.paintBorder(graphics);
+ }
+
+ public void paintComponents(Graphics graphics) {
+
+ }
+
+ private int _windowHeight;
+ private int _windowWidth;
+ private int _streamHeight;
+ private int _streamWidth;
+
+ public int getConsoleLeft() {
+ return (_windowWidth - Translate(_streamWidth)) / 2;
+ }
+
+ public int getConsoleTop() {
+ return (_windowHeight - Translate(_streamHeight)) / 2;
+ }
+
+ public void setMaxHeight(int h) {
+ _windowHeight = h;
+ if (_streamHeight > 1 && _streamWidth > 1) {
+ double sf1 = (double) (_windowHeight) / (double) (_streamHeight);
+ double sf2 = (double) (_windowWidth) / (double) (_streamWidth);
+ if (sf1 < sf2) {
+ setScaleFactor(sf1);
+ } else {
+ setScaleFactor(sf2);
+ }
+ } else {
+ setScaleFactor(1.0);
+ }
+ }
+
+ public void setMaxWidth(int w) {
+ _windowWidth = w;
+ if (_streamWidth > 1 && _streamHeight > 1) {
+ double sf1 = (double) (_windowHeight) / (double) (_streamHeight);
+ double sf2 = (double) (_windowWidth) / (double) (_streamWidth);
+ if (sf1 < sf2) {
+ setScaleFactor(sf1);
+ } else {
+ setScaleFactor(sf2);
+ }
+ } else {
+ setScaleFactor(1.0);
+ }
+
+ }
+
+ public void setVisible(boolean visible) {
+ super.setVisible(visible);
+ if (visible) {
+ stream_.unpause();
+ } else {
+ stream_.pause();
+ }
+ }
+
+ private void pointerEvent(MouseEvent event) {
+ if (this.hasFocus()) {
+ int buttonMask = 0;
+ if ((event.getModifiersEx() & MouseEvent.BUTTON1_DOWN_MASK) != 0) {
+ buttonMask |= 1;
+ }
+ if ((event.getModifiersEx() & MouseEvent.BUTTON2_DOWN_MASK) != 0) {
+ buttonMask |= 2;
+ }
+ if ((event.getModifiersEx() & MouseEvent.BUTTON3_DOWN_MASK) != 0) {
+ buttonMask |= 4;
+ }
+ stream_.pointerEvent(buttonMask, TranslateRev(event.getX()),
+ TranslateRev(event.getY()));
+ // event.consume();
+ }
+ }
+
+ public void mouseReleased(MouseEvent event) {
+ pointerEvent(event);
+ if (this.hasFocus()) {
+ if (_cursor != null) {
+ setCursor(_cursor);
+ } else {
+ int[] pixels = new int[16 * 16];
+ Image image = Toolkit.getDefaultToolkit().createImage(
+ new java.awt.image.MemoryImageSource(16, 16, pixels, 0,
+ 16));
+ setCursor(Toolkit.getDefaultToolkit().createCustomCursor(image,
+ new Point(0, 0), "invisibleCursor"));
+ }
+ }
+ }
+
+ public void mousePressed(MouseEvent event) {
+
+ if (_cursor != null) {
+ setCursor(_cursor);
+ } else {
+ int[] pixels = new int[16 * 16];
+ Image image = Toolkit.getDefaultToolkit()
+ .createImage(
+ new java.awt.image.MemoryImageSource(16, 16,
+ pixels, 0, 16));
+ setCursor(Toolkit.getDefaultToolkit().createCustomCursor(image,
+ new Point(0, 0), "invisibleCursor"));
+ }
+
+ if (!this.hasFocus()) {
+ this.requestFocusInWindow();
+ setCursor(Cursor.getDefaultCursor());
+ }
+ pointerEvent(event);
+ }
+
+ public void mouseExited(MouseEvent event) {
+ setCursor(Cursor.getDefaultCursor());
+
+ }
+
+ public void mouseEntered(MouseEvent event) {
+ if (this.hasFocus()) {
+ if (_cursor != null) {
+ setCursor(_cursor);
+ } else {
+ int[] pixels = new int[16 * 16];
+ Image image = Toolkit.getDefaultToolkit().createImage(
+ new java.awt.image.MemoryImageSource(16, 16, pixels, 0,
+ 16));
+ setCursor(Toolkit.getDefaultToolkit().createCustomCursor(image,
+ new Point(0, 0), "invisibleCursor"));
+ }
+ } else {
+ setCursor(Cursor.getDefaultCursor());
+ }
+ pointerEvent(event);
+ }
+
+ public void mouseClicked(MouseEvent event) {
+
+ if (!this.hasFocus()) {
+ this.requestFocusInWindow();
+ }
+ }
+
+ public void mouseMoved(MouseEvent event) {
+ pointerEvent(event);
+ }
+
+ public void mouseDragged(MouseEvent event) {
+ pointerEvent(event);
+ }
+
+ /**
+ * @see MouseWheelListener#mouseWheelMoved
+ */
+ public void mouseWheelMoved(MouseWheelEvent event) {
+ if (this.hasFocus()) {
+ int x = event.getX();
+ int y = event.getY();
+ int r = event.getWheelRotation();
+
+ stream_.pointerWheelEvent(TranslateRev(x), TranslateRev(y), r);
+ event.consume();
+ }
+ }
+
+ public void keyTyped(KeyEvent event) {
+ event.consume();
+ }
+
+ public void sendCtrlAltDel() {
+ stream_.sendCtrlAltDelete();
+ }
+
+ private void key(KeyEvent event, boolean pressed) {
+ if (this.hasFocus()) {
+ if (event.getKeyCode() == KeyEvent.VK_ALT && event.isControlDown()
+ && isFullscreen) {
+ // Special case for Ctrl-Alt-Ins to be mapped to
+ // Ctrl-Alt-Delete.
+ // stream_.keyEvent(pressed,
+ // keyMap.getMappedKey(KeyEvent.VK_DELETE));
+
+ // Exitfullscreen
+ screen.dispose();
+ isFullscreen = false;
+ // screen = null;
+ } else if (event.getKeyCode() == KeyEvent.VK_ALT
+ && event.isControlDown()) {
+ /* For now disabling Ctrl-Alt fullscreen support
+ final Container root = getParent().getParent();
+ root.remove(getParent());
+ VNCFullscreen fc = new VNCFullscreen((JPanel) getParent(),
+ this, true, getParent().getBackground());
+ fc.addWindowListener(new WindowListener() {
+ public void windowActivated(WindowEvent e) {
+ };
+
+ public void windowClosed(WindowEvent e) {
+ root.add(getParent());
+ setMaxHeight(getParent().getHeight());
+ setMaxWidth(getParent().getWidth());
+ root.invalidate();
+ root.validate();
+ invalidate();
+ repaint();
+ requestFocusInWindow();
+ };
+
+ public void windowClosing(WindowEvent e) {
+ };
+
+ public void windowDeactivated(WindowEvent e) {
+ ((VNCFullscreen) e.getComponent()).dispose();
+ };
+
+ public void windowDeiconified(WindowEvent e) {
+ };
+
+ public void windowIconified(WindowEvent e) {
+ };
+
+ public void windowOpened(WindowEvent e) {
+ };
+ });
+ requestFocusInWindow(); */
+ } else {
+ int keysym = keyMap.getKeysym(event);
+ if (keysym != -1) {
+ stream_.keyEvent(pressed, keysym);
+ }
+ }
+ event.consume();
+ }
+ }
+
+ public void keyReleased(KeyEvent event) {
+ key(event, false);
+ }
+
+ public void clientBell() {
+ // TODO Auto-generated method stub
+
+ }
+
+ public void keyPressed(KeyEvent event) {
+ key(event, true);
+ }
+
+ public JFrame Frame;
+ public JScrollPane ScrollPane;
+
+ /**
+ * @see VNCClient#clientDesktopSize
+ */
+ public void clientDesktopSize(final int width, final int height) {
+ _console.writeline("Desktop size is now " + width + "; " + height);
+ _streamHeight = height;
+ _streamWidth = width;
+
+ if (_windowHeight != 0 && _windowWidth != 0) {
+ setMaxHeight(_windowHeight);
+ setMaxWidth(_windowWidth);
+ }
+
+ final BufferedImage image2 = new BufferedImage(width, height,
+ BufferedImage.TYPE_INT_RGB);
+ imageGraphics_ = (Graphics2D) image2.getGraphics();
+
+ SwingUtilities.invokeLater(new Runnable() {
+ public void run() {
+ image_ = image2;
+ java.awt.Container parent = getParent();
+ if (parent != null) {
+ parent.invalidate();
+ parent.validate();
+ }
+ }
+ });
+
+ }
+
+ /**
+ * Expects to be on the stream thread.
+ */
+ private void damage(int x, int y, int width, int height) {
+ x += BW;
+ y += BW;
+
+ if (damageStreamside.isEmpty()) {
+ damageStreamside.x = Translate(x);
+ damageStreamside.y = Translate(y);
+ damageStreamside.width = Translate(width);
+ damageStreamside.height = Translate(height);
+ } else {
+ damageStreamside.add(new Rectangle(Translate(x), Translate(y),
+ Translate(width), Translate(height)));
+ }
+ }
+
+ /**
+ * Expects to be on the event thread.
+ */
+ private void repair() {
+ if (!damageEventside.isEmpty()) {
+ // repaint causes strange window effects so force paint straight
+ // away, slowness added :(
+ paintImmediately(damageEventside);
+ damageEventside.width = 0;
+ }
+ }
+
+ /**
+ * Expects to be on the event thread.
+ */
+ private void repairThumbnail() {
+ Image i = image_;
+ if (i != null) {
+ // int w = Translate(_streamWidth);
+ // int h = Translate(_streamHeight);
+ // thumbnailGraphics.drawImage(
+ // i,
+ // 0, 0, (int)(w * thumbnailRatio), (int)(h * thumbnailRatio),
+ // 0, 0, w, h, null);
+ }
+ }
+
+ /**
+ * @see VNCClient#clientFrameBufferUpdate
+ */
+ public void clientFrameBufferUpdate() {
+ try {
+ // Note that we block here so that we don't lose any updates to
+ // damageStreamside while the current rectangle is being copied.
+ SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ damageEventside.add(damageStreamside);
+ damageStreamside.width = 0;
+ repair();
+ }
+ });
+ } catch (InterruptedException exn) {
+ _console.writeline(exn.getMessage());
+ } catch (InvocationTargetException exn) {
+ _console.writeline(exn.getMessage());
+ }
+ }
+
+ /**
+ * @see VNCClient#clientDrawImage
+ */
+ public void clientDrawImage(final Image image, final int x, final int y,
+ final int width, final int height) {
+ // this doesn't give as accurate graphics as we would like but it will
+ // get replaced when the window repaints with a nicer looking image
+ imageGraphics_.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
+ RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR);
+ imageGraphics_.setRenderingHint(RenderingHints.KEY_RENDERING,
+ RenderingHints.VALUE_RENDER_SPEED);
+ imageGraphics_.drawImage(image, x, y, null);
+ damage(x, y, width, height);
+ }
+
+ /**
+ * @see VNCClient#clientSetCursor
+ */
+ public void clientSetCursor(Image image, int x, int y) {
+
+ /*
+ * If the image size does not match the platform's preferred cursor
+ * size, then pad out with some transparency. We don't need to do this
+ * on Linux clients it seems, but Windows throws
+ * "java.awt.image.ImagingOpException: Unable to transform src image"
+ * when trying to do the scaling itself.
+ */
+ int imageWidth = image.getWidth(null);
+ int imageHeight = image.getHeight(null);
+ Dimension cursorSize = toolkit.getBestCursorSize(imageWidth,
+ imageHeight);
+
+ if (!(imageWidth > cursorSize.width || imageHeight > cursorSize.height)
+ && (imageWidth < cursorSize.width || imageHeight < cursorSize.height)) {
+ BufferedImage bi = new BufferedImage(cursorSize.width,
+ cursorSize.height, BufferedImage.TYPE_INT_ARGB);
+ Graphics2D g = (Graphics2D) bi.getGraphics();
+ g.setRenderingHint(RenderingHints.KEY_RENDERING,
+ RenderingHints.VALUE_RENDER_SPEED);
+ g.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
+ RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR);
+ g.setColor(new Color(0, 0, 0, 0));
+ g.fillRect(0, 0, cursorSize.width, cursorSize.height);
+ g.drawImage(image, 0, 0, null);
+ image = bi;
+ }
+
+ final Cursor cursor = toolkit.createCustomCursor(image,
+ new Point(x, y), "");
+
+ _cursor = cursor;
+
+ SwingUtilities.invokeLater(new Runnable() {
+ public void run() {
+ setCursor(cursor);
+ }
+ });
+
+ }
+
+ /**
+ * @see VNCClient#clientCopyRectangle
+ */
+ public void clientCopyRectangle(final int x, final int y, final int width,
+ final int height, final int dx, final int dy) {
+ imageGraphics_.copyArea(x, y, width, height, dx - x, dy - y);
+ damage(dx, dy, width, height);
+ }
+
+ /**
+ * @see VNCClient#clientFillRectangle
+ */
+ public void clientFillRectangle(final int x, final int y, final int width,
+ final int height, final Color color) {
+ imageGraphics_.setColor(color);
+ imageGraphics_.fillRect(x, y, width, height);
+ damage(x, y, width, height);
+ }
+
+ /**
+ * @see VNCClient#clientCutText
+ */
+ public void clientCutText(final String text) {
+ SwingUtilities.invokeLater(new Runnable() {
+ public void run() {
+ serverText_ = text;
+ }
+ });
+ }
+
+ public void getClipboard() {
+ StringSelection stringSelection = new StringSelection(serverText_);
+ Clipboard clipboard = toolkit.getSystemClipboard();
+ try {
+ clipboard.setContents(stringSelection, this);
+ } catch (IllegalStateException e) {
+ _console.writeline(e.getMessage());
+ }
+ }
+
+ public void setClipboard() {
+ Clipboard clipboard = toolkit.getSystemClipboard();
+ Transferable contents = clipboard.getContents(null);
+ if ((contents != null)
+ && contents.isDataFlavorSupported(DataFlavor.stringFlavor)) {
+ try {
+ String text = (String) contents
+ .getTransferData(DataFlavor.stringFlavor);
+ stream_.clientCutText(text);
+ } catch (Throwable t) {
+ _console.writeline(t.getMessage());
+ }
+ }
+ }
+
+ public void lostOwnership(Clipboard clipboard, Transferable contents) {
+ }
+
+ /**
+ * @see FocusListener#focusGained
+ */
+ public void focusGained(FocusEvent e) {
+ // Send release events for all the modifier keys.
+
+ // setBorder(focusBorder);
+ if (_cursor != null) {
+ setCursor(_cursor);
+ } else {
+ int[] pixels = new int[16 * 16];
+ Image image = Toolkit.getDefaultToolkit()
+ .createImage(
+ new java.awt.image.MemoryImageSource(16, 16,
+ pixels, 0, 16));
+ setCursor(Toolkit.getDefaultToolkit().createCustomCursor(image,
+ new Point(0, 0), "invisibleCursor"));
+ }
+ if (!isFullscreen) {
+ this.setBorder(BorderFactory.createCompoundBorder(BorderFactory
+ .createLineBorder(Color.BLUE, 1), BorderFactory
+ .createLineBorder(getParent().getBackground(), 2)));
+ } else {
+ this.setBorder(BorderFactory.createEmptyBorder());
+ }
+ this.setFocusable(true);
+
+ sendRelease(KeyEvent.VK_ALT);
+ sendRelease(KeyEvent.VK_CONTROL);
+ sendRelease(KeyEvent.VK_SHIFT);
+ }
+
+ private void sendRelease(int keycode) {
+ stream_.keyEvent(false, keyMap.getMappedKey(keycode));
+ }
+
+ /**
+ * @see FocusListener#focusLost
+ */
+ public void focusLost(FocusEvent e) {
+ if (this.getParent() != null) {
+ if (!isFullscreen) {
+ this.setBorder(BorderFactory.createCompoundBorder(BorderFactory
+ .createLineBorder(getParent().getBackground(), 1),
+ BorderFactory.createLineBorder(getParent()
+ .getBackground(), 2)));
+ } else {
+ this.setBorder(BorderFactory.createEmptyBorder());
+ }
+ setCursor(Cursor.getDefaultCursor());
+ }
+ }
+
+ public ImageIcon getThumbnailIcon() {
+ return thumbnailIcon;
+ }
+}
View
66 java/com/citrix/xenserver/console/VNCClient.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2005-2009 Citrix Systems, Inc.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as published
+ * by the Free Software Foundation, with the additional linking exception as
+ * follows:
+ *
+ * Linking this library statically or dynamically with other modules is
+ * making a combined work based on this library. Thus, the terms and
+ * conditions of the GNU General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this library give you
+ * permission to link this library with independent modules to produce an
+ * executable, regardless of the license terms of these independent modules,
+ * and to copy and distribute the resulting executable under terms of your
+ * choice, provided that you also meet, for each linked independent module,
+ * the terms and conditions of the license of that module. An independent
+ * module is a module which is not derived from or based on this library. If
+ * you modify this library, you may extend this exception to your version of
+ * the library, but you are not obligated to do so. If you do not wish to do
+ * so, delete this exception statement from your version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc., 51
+ * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+package com.citrix.xenserver.console;
+
+import java.awt.Color;
+import java.awt.Image;
+
+/**
+ * All methods in this interface will be called from the VNC connection handler
+ * thread.
+ */
+public interface VNCClient {
+
+ public void clientDrawImage(Image image, int x, int y, int width, int height);
+
+ /**
+ * Set the client-side cursor to the given image. The parameters x and y
+ * specify the cursor hotspot.
+ */
+ public void clientSetCursor(Image image, int x, int y);
+
+ public void clientCopyRectangle(int x, int y, int width, int height,
+ int dx, int dy);
+