1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: AppletViewer.java,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
32 import java
.awt
.Toolkit
;
34 import java
.net
.InetAddress
;
36 //import stardiv.applet.AppletMessageHandler;
37 import stardiv
.applet
.AppletExecutionContext
;
38 import stardiv
.applet
.DocumentProxy
;
40 //import stardiv.js.ip.RootTaskManager;
41 //import stardiv.js.ip.BaseObj;
42 //import stardiv.js.ide.Ide;
43 //import stardiv.js.ne.RunTime;
44 //import stardiv.js.base.IdentifierPool;
45 //import stardiv.js.base.Identifier;
46 //import stardiv.memory.AtomUnion;
47 //import stardiv.js.ip.Ctor;
48 import stardiv
.controller
.SjSettings
;
53 import java
.awt
.event
.*;
56 import java
.net
.MalformedURLException
;
60 * A frame to show the applet tag in.
62 class TextFrame
extends Frame
{
64 * Create the tag frame.
66 TextFrame(int x
, int y
, String title
, String text
) {
68 TextArea txt
= new TextArea(20, 60);
70 txt
.setEditable(false);
74 Panel p
= new Panel();
76 Button b
= new Button(amh
.getMessage("button.dismiss", "Dismiss"));
79 class ActionEventListener
implements ActionListener
{
80 public void actionPerformed(ActionEvent evt
) {
84 b
.addActionListener(new ActionEventListener());
90 WindowListener windowEventListener
= new WindowAdapter() {
92 public void windowClosing(WindowEvent evt
) {
97 addWindowListener(windowEventListener
);
99 private static AppletMessageHandler amh
= new AppletMessageHandler("textframe");
104 * The toplevel applet viewer.
106 public class AppletViewer
extends Frame
implements Observer
{
107 com
.sun
.star
.lib
.sandbox
.ResourceViewer resourceViewer
;
112 private static String defaultSaveFile
= "Applet.ser";
115 * Look here for the properties file
117 public static File theUserPropertiesFile
;
118 public static File theAppletViewerPropsFile
;
121 //private RootTaskManager aRTM;
122 //private BaseObj aRootObj;
124 private AppletExecutionContext appletExecutionContext
= null;
125 Hashtable atts
= null;
127 static DocumentProxy documentViewer
= null;
135 * output status messages to this stream
138 PrintStream statusMsgStream
;
140 static Vector contexts
= new Vector();
142 private final class UserActionListener
implements ActionListener
{
143 public void actionPerformed(ActionEvent evt
) {
144 processUserAction(evt
);
149 String sep
= File
.separator
;
151 File userHome
= new File(System
.getProperty("user.home"));
153 File AVHome
= new File(userHome
, ".hotjava");
154 // ensure the props folder can be made
157 theUserPropertiesFile
= new File(AVHome
, "properties");
158 File JH
= new File(System
.getProperty("java.home"));
159 theAppletViewerPropsFile
= new File(JH
, "lib" + sep
+ "appletviewer.properties");
163 * Create the applet viewer
165 public AppletViewer(int x
, int y
, URL doc
, Hashtable atts
, PrintStream statusMsgStream
) {
166 // resourceViewer = new stardiv.util.ResourceViewer();
167 // resourceViewer.show();
168 //sun.awt.ScreenUpdater does not exist in Java 1.4
169 // System.err.println("#*#*#*:" + sun.awt.ScreenUpdater.updater);
170 this.statusMsgStream
= statusMsgStream
;
173 setTitle(amh
.getMessage("tool.title", atts
.get("code")));
175 MenuBar mb
= new MenuBar();
177 Menu m
= new Menu(amh
.getMessage("menu.applet"));
179 addMenuItem(m
, "menuitem.restart");
180 addMenuItem(m
, "menuitem.reload");
181 addMenuItem(m
, "menuitem.stop");
182 addMenuItem(m
, "menuitem.save");
183 addMenuItem(m
, "menuitem.start");
184 addMenuItem(m
, "menuitem.clone");
185 m
.add(new MenuItem("-"));
186 addMenuItem(m
, "menuitem.tag");
187 addMenuItem(m
, "menuitem.info");
188 addMenuItem(m
, "menuitem.edit").setEnabled( false );
189 addMenuItem(m
, "menuitem.encoding");
190 m
.add(new MenuItem("-"));
191 addMenuItem(m
, "menuitem.print");
192 m
.add(new MenuItem("-"));
193 addMenuItem(m
, "menuitem.props");
194 m
.add(new MenuItem("-"));
195 addMenuItem(m
, "menuitem.close");
196 // if (factory.isStandalone()) {
197 addMenuItem(m
, "menuitem.quit");
204 addWindowListener(new WindowAdapter() {
205 public void windowClosing(WindowEvent evt
) {
206 appletExecutionContext
.shutdown();
209 public void windowIconified(WindowEvent evt
) {
210 appletExecutionContext
.sendLoad();
213 public void windowDeiconified(WindowEvent evt
) {
214 appletExecutionContext
.sendStart();
218 add("South", label
= new Label(amh
.getMessage("label.hello")));
220 appletExecutionContext
= new AppletExecutionContext(doc
, atts
, this, 0);
221 appletExecutionContext
.init();
223 appletExecutionContext
.addObserver(this);
224 contexts
.addElement(appletExecutionContext
);
229 // appletExecutionContext.send();
230 appletExecutionContext
.startUp();
233 if( atts.get( "mayscript" ) != null ) {
235 aRTM = aIde.getActRootTaskManager();
236 aRootObj = new BaseObj( aRTM );
237 //Ctor aCtor = new AppletCtor( aRTM, "Window" );
238 //aRootObj.initProperties( aCtor, aCtor.getStaticPropCount(), aCtor.getBasePropCount() );
239 //aRootObj.setCtor( aCtor );
240 aRTM.setRootObj( aRootObj );
241 RunTime aRT = new RunTime( aRootObj, aRTM );
242 aIde.setRootObj( aRootObj );
244 AtomUnion aAU = new AtomUnion();
245 BaseObj aDocument = new BaseObj( aRTM );
246 aAU.setObject( aDocument );
247 Identifier aId = IdentifierPool.aGlobalPool.addIdentifier( "RootObject" );
248 aRootObj.newProperty( aId, aAU );
249 IdentifierPool.aGlobalPool.releaseIdentifier( aId );
251 String pName = (String)atts.get( "name" );
252 if( pName != null ) {
253 BaseObj aApplet = new BaseObj( aRTM );
254 aAU.setObject( aApplet );
255 aId = IdentifierPool.aGlobalPool.addIdentifier( pName );
256 aDocument.newProperty( aId, aAU );
257 IdentifierPool.aGlobalPool.releaseIdentifier( aId );
263 public MenuItem
addMenuItem(Menu m
, String s
) {
264 MenuItem mItem
= new MenuItem(amh
.getMessage(s
));
265 mItem
.addActionListener(new UserActionListener());
272 public void showDocument(URL url
) {
278 public void showDocument(URL url
, String target
) {
284 public void showStatus(String status
) {
285 label
.setText(status
);
288 public void update(Observable observable
, Object status
) {
289 showStatus((String
)status
);
292 public Object
getJavaScriptJSObjectWindow() {
293 //if( aRootObj != null )
294 // return aRootObj.getJSObject();
302 static Hashtable systemParam
= new Hashtable();
305 systemParam
.put("codebase", "codebase");
306 systemParam
.put("code", "code");
307 systemParam
.put("alt", "alt");
308 systemParam
.put("width", "width");
309 systemParam
.put("height", "height");
310 systemParam
.put("align", "align");
311 systemParam
.put("vspace", "vspace");
312 systemParam
.put("hspace", "hspace");
316 * Print the HTML tag.
318 public static void printTag(PrintStream out
, Hashtable atts
) {
319 out
.print("<applet");
321 String v
= (String
)atts
.get("codebase");
323 out
.print(" codebase=\"" + v
+ "\"");
326 v
= (String
)atts
.get("code");
330 out
.print(" code=\"" + v
+ "\"");
331 v
= (String
)atts
.get("width");
335 out
.print(" width=" + v
);
337 v
= (String
)atts
.get("height");
341 out
.print(" height=" + v
);
343 v
= (String
)atts
.get("name");
345 out
.print(" name=\"" + v
+ "\"");
349 // A very slow sorting algorithm
350 int len
= atts
.size();
351 String params
[] = new String
[len
];
353 for (Enumeration e
= atts
.keys() ; e
.hasMoreElements() ;) {
354 String param
= (String
)e
.nextElement();
356 for (; i
< len
; i
++) {
357 if (params
[i
].compareTo(param
) >= 0) {
361 System
.arraycopy(params
, i
, params
, i
+ 1, len
- i
);
366 for (int i
= 0 ; i
< len
; i
++) {
367 String param
= params
[i
];
368 if (systemParam
.get(param
) == null) {
369 out
.println("<param name=" + param
+
370 " value=\"" + atts
.get(param
) + "\">");
373 out
.println("</applet>");
377 * Make sure the atrributes are uptodate.
379 public void updateAtts() {
380 Dimension d
= getSize();
381 Insets in
= getInsets();
382 atts
.put("width", new Integer(d
.width
- (in
.left
+ in
.right
)).toString());
383 atts
.put("height", new Integer(d
.height
- (in
.top
+ in
.bottom
)).toString());
387 * Save the applet to a well known file (for now) as a serialized object
390 // REMIND -- should check that the applet has really stopped
391 FileDialog fd
= new FileDialog(this, "Serialize Applet into File", FileDialog
.SAVE
);
392 // needed for a bug under Solaris...
393 fd
.setDirectory(System
.getProperty("user.dir"));
394 fd
.setFile(defaultSaveFile
);
396 String fname
= fd
.getFile();
400 String dname
= fd
.getDirectory();
401 File file
= new File(dname
, fname
);
404 OutputStream s
= new FileOutputStream(file
);
405 ObjectOutputStream os
= new ObjectOutputStream(s
);
406 showStatus(amh
.getMessage("appletsave.err1",
407 appletExecutionContext
.getApplet().toString(), file
.toString()));
408 os
.writeObject(appletExecutionContext
.getApplet());
409 } catch (IOException ex
) {
410 System
.err
.println(amh
.getMessage("appletsave.err2", ex
));
415 * Clone the viewer and the applet.
418 Point p
= getLocation();
420 // factory.createAppletViewer(p.x + 30, p.y + 10,
421 // pHelper.panel.documentURL, (Hashtable)pHelper.panel.atts.clone());
425 * Show the applet tag.
428 ByteArrayOutputStream out
= new ByteArrayOutputStream();
430 printTag(new PrintStream(out
), atts
);
431 showStatus(amh
.getMessage("applettag"));
433 Point p
= getLocation();
434 new TextFrame(p
.x
+ 50, p
.y
+ 20, amh
.getMessage("applettag.textframe"), out
.toString());
438 * Show the applet info.
441 String str
= appletExecutionContext
.getApplet().getAppletInfo();
443 str
= amh
.getMessage("appletinfo.applet");
447 String atts
[][] = appletExecutionContext
.getApplet().getParameterInfo();
449 for (int i
= 0 ; i
< atts
.length
; i
++) {
450 str
+= atts
[i
][0] + " -- " + atts
[i
][1] + " -- " + atts
[i
][2] + "\n";
453 str
+= amh
.getMessage("appletinfo.param");
456 Point p
= getLocation();
457 new TextFrame(p
.x
+ 50, p
.y
+ 20, amh
.getMessage("appletinfo.textframe"), str
);
462 * Show character encoding type
464 void appletCharacterEncoding() {
465 showStatus(amh
.getMessage("appletencoding", encoding
));
478 PrintJob pj
= Toolkit
.getDefaultToolkit().
479 getPrintJob(this, amh
.getMessage("appletprint.printjob"), (Properties
)null);
483 Dimension pageDim
= pj
.getPageDimension();
484 int pageRes
= pj
.getPageResolution();
485 boolean lastFirst
= pj
.lastPageFirst();
487 Graphics g
= pj
.getGraphics();
489 appletExecutionContext
.getApplet().printComponents(g
);
492 statusMsgStream
.println(amh
.getMessage("appletprint.fail"));
494 statusMsgStream
.println(amh
.getMessage("appletprint.finish"));
498 statusMsgStream
.println(amh
.getMessage("appletprint.cancel"));
506 public synchronized void networkProperties() {
508 props
= new AppletProps(appletExecutionContext
);
511 props
.setVisible(true);
516 * Stop, Destroy, Dispose and Quit an AppletView, then
517 * reclaim resources and exit the program if this is
520 public void appletClose() {
521 appletExecutionContext
.shutdown();
522 contexts
.removeElement(this);
524 if (contexts
.size() == 0) {
530 // public static void writeClasses() {
532 // java.io.FileOutputStream file = new FileOutputStream("classes.txt");
533 // java.io.PrintStream printStream = new java.io.PrintStream(file);
535 // printStream.println("- .* .*");
536 // Enumeration elements = stardiv.util.HardClassContext.classList.elements();
537 // while(elements.hasMoreElements()) {
538 // String string = (String)elements.nextElement();
540 // String packageName = "";
541 // String className = string;
543 // int lastIndex = string.lastIndexOf('.');
544 // if(lastIndex > -1) {
545 // packageName = string.substring(0, lastIndex);
546 // className = string.substring(lastIndex + 1);
549 // printStream.print("+ ");
551 // while((index = packageName.indexOf('.')) > -1) {
552 // printStream.print(packageName.substring(0, index) + "\\\\");
553 // packageName = packageName.substring(index + 1);
555 // printStream.print(packageName + " ");
557 // while((index = className.indexOf('$')) > -1) {
558 // printStream.print(className.substring(0, index) + "\\$");
559 // className = className.substring(index + 1);
561 // printStream.println(className + "\\.class");
565 // catch(java.io.IOException eio) {
566 // System.err.println("IOException:" + eio);
572 * Exit from the program (if not stand alone) - do no clean-up
574 private void appletSystemExit() {
575 // if (factory.isStandalone())
581 * Shutdown all viewers properly then
582 * exit from the program (if not stand alone)
584 protected void appletQuit() {
585 appletExecutionContext
.shutdown();
592 public void processUserAction(ActionEvent evt
) {
594 String label
= ((MenuItem
)evt
.getSource()).getLabel();
596 if (amh
.getMessage("menuitem.restart").equals(label
)) {
597 appletExecutionContext
.restart();
601 if (amh
.getMessage("menuitem.reload").equals(label
)) {
602 appletExecutionContext
.reload();
606 if (amh
.getMessage("menuitem.clone").equals(label
)) {
611 if (amh
.getMessage("menuitem.stop").equals(label
)) {
612 appletExecutionContext
.sendStop();
616 if (amh
.getMessage("menuitem.save").equals(label
)) {
621 if (amh
.getMessage("menuitem.start").equals(label
)) {
622 appletExecutionContext
.sendStart();
626 if (amh
.getMessage("menuitem.tag").equals(label
)) {
631 if (amh
.getMessage("menuitem.info").equals(label
)) {
636 if (amh
.getMessage("menuitem.encoding").equals(label
)) {
637 appletCharacterEncoding();
641 if (amh
.getMessage("menuitem.edit").equals(label
)) {
646 if (amh
.getMessage("menuitem.print").equals(label
)) {
651 if (amh
.getMessage("menuitem.props").equals(label
)) {
656 if (amh
.getMessage("menuitem.close").equals(label
)) {
661 if (/*factory.isStandalone() && */amh
.getMessage("menuitem.quit").equals(label
)) {
665 //statusMsgStream.println("evt = " + evt);
669 * Prepare the enviroment for executing applets.
671 public static void init() {
672 Properties props
= new Properties();
673 props
.put( "http.proxyHost", "wwwproxy" );
674 props
.put( "http.proxyPort", "3128" );
675 props
.put( "ftpProxySet", "true" );
676 props
.put( "ftpProxyHost", "wwwproxy" );
677 props
.put( "ftpProxyPort", "3128" );
678 props
.put( "ftpProxyPort", "3128" );
679 props
.put( "stardiv.debug.trace", "window" );
680 props
.put( "stardiv.debug.warning", "window" );
681 props
.put( "stardiv.debug.error", "window" );
682 props
.put( "stardiv.security.defaultSecurityManager", "true" );
684 // Try loading the appletviewer properties file to get messages, etc.
686 // FileInputStream in = new FileInputStream(theAppletViewerPropsFile);
687 // props.load(new BufferedInputStream(in));
689 // } catch (Exception e) {
690 // System.out.println(amh.getMessage("init.err"));
693 // Try loading the saved user properties file to override some
694 // of the above defaults.
696 FileInputStream in
= new FileInputStream(theUserPropertiesFile
);
697 props
.load(new BufferedInputStream(in
));
699 } catch (Exception e
) {
700 /* is it really necessary to say this?
701 This is always the case the first time we run..
702 System.out.println("[no properties loaded, using defaults]"); */
705 // Install a property list.
707 SjSettings
.changeProperties(props
);
711 * The current character.
718 public static void skipSpace(Reader in
) throws IOException
{
719 while ((c
>= 0) && ((c
== ' ') || (c
== '\t') || (c
== '\n') || (c
== '\r'))) {
727 public static String
scanIdentifier(Reader in
) throws IOException
{
728 StringBuffer buf
= new StringBuffer();
730 if (((c
>= 'a') && (c
<= 'z')) ||
731 ((c
>= 'A') && (c
<= 'Z')) ||
732 ((c
>= '0') && (c
<= '9')) || (c
== '_')) {
736 return buf
.toString();
744 public static Hashtable
scanTag(Reader in
) throws IOException
{
745 Hashtable atts
= new Hashtable();
747 while (c
>= 0 && c
!= '>') {
748 String att
= scanIdentifier(in
);
755 if ((c
== '\'') || (c
== '\"')) {
759 StringBuffer buf
= new StringBuffer();
761 (((quote
< 0) && (c
!= ' ') && (c
!= '\t') &&
762 (c
!= '\n') && (c
!= '\r') && (c
!= '>'))
763 || ((quote
>= 0) && (c
!= quote
)))) {
771 val
= buf
.toString();
773 //statusMsgStream.println("PUT " + att + " = '" + val + "'");
774 atts
.put(att
.toLowerCase(), val
);
783 static String encoding
= null;
785 static private Reader
makeReader(InputStream is
) {
786 if (encoding
!= null) {
788 return new BufferedReader(new InputStreamReader(is
, encoding
));
789 } catch (IOException x
) { }
791 InputStreamReader r
= new InputStreamReader(is
);
792 encoding
= r
.getEncoding();
793 return new BufferedReader(r
);
797 * Scan an html file for <applet> tags
799 public static void parse(URL url
) throws IOException
{
800 parse(url
, System
.out
);
803 public static void parse(URL url
, PrintStream statusMsgStream
) throws IOException
{
806 String requiresNameWarning
= amh
.getMessage("parse.warning.requiresname");
807 String paramOutsideWarning
= amh
.getMessage("parse.warning.paramoutside");
808 String requiresCodeWarning
= amh
.getMessage("parse.warning.requirescode");
809 String requiresHeightWarning
= amh
.getMessage("parse.warning.requiresheight");
810 String requiresWidthWarning
= amh
.getMessage("parse.warning.requireswidth");
811 String appNotLongerSupportedWarning
= amh
.getMessage("parse.warning.appnotLongersupported");
813 java
.net
.URLConnection conn
= url
.openConnection();
814 Reader in
= makeReader(conn
.getInputStream());
815 /* The original URL may have been redirected - this
816 * sets it to whatever URL/codebase we ended up getting
820 Hashtable atts
= null;
830 String nm
= scanIdentifier(in
);
831 if (nm
.equalsIgnoreCase("applet")) {
833 new AppletViewer(x
, y
, url
, atts
, System
.out
);
836 // make sure we don't go too far!
837 Dimension d
= Toolkit
.getDefaultToolkit().getScreenSize();
838 if (x
> d
.width
- 30)
840 if (y
> d
.height
- 30)
847 String nm
= scanIdentifier(in
);
848 if (nm
.equalsIgnoreCase("param")) {
849 Hashtable t
= scanTag(in
);
850 String att
= (String
)t
.get("name");
852 statusMsgStream
.println(requiresNameWarning
);
854 String val
= (String
)t
.get("value");
856 statusMsgStream
.println(requiresNameWarning
);
857 } else if (atts
!= null) {
858 atts
.put(att
.toLowerCase(), val
);
860 statusMsgStream
.println(paramOutsideWarning
);
864 else if (nm
.equalsIgnoreCase("applet")) {
866 if (atts
.get("code") == null && atts
.get("object") == null) {
867 statusMsgStream
.println(requiresCodeWarning
);
869 } else if (atts
.get("width") == null) {
870 statusMsgStream
.println(requiresWidthWarning
);
872 } else if (atts
.get("height") == null) {
873 statusMsgStream
.println(requiresHeightWarning
);
877 else if (nm
.equalsIgnoreCase("app")) {
878 statusMsgStream
.println(appNotLongerSupportedWarning
);
879 Hashtable atts2
= scanTag(in
);
880 nm
= (String
)atts2
.get("class");
882 atts2
.remove("class");
883 atts2
.put("code", nm
+ ".class");
885 nm
= (String
)atts2
.get("src");
888 atts2
.put("codebase", nm
);
890 if (atts2
.get("width") == null) {
891 atts2
.put("width", "100");
893 if (atts2
.get("height") == null) {
894 atts2
.put("height", "100");
896 printTag(statusMsgStream
, atts2
);
897 statusMsgStream
.println();
908 static void usage() {
909 System
.out
.println(amh
.getMessage("usage"));
912 static boolean didInitialize
= false;
915 * mainInit can be called by direct clients
917 public static void mainInit() {
918 if (! didInitialize
) {
919 didInitialize
= true;
929 public static void main(String argv
[]) {
933 if (argv
.length
== 0) {
934 System
.out
.println(amh
.getMessage("main.err.inputfile"));
939 // Parse the documents
940 for (int i
= 0 ; i
< argv
.length
; i
++) {
944 if (argv
[i
].equals("-encoding")) {
945 if(i
+ 1 < argv
.length
) {
955 if (argv
[i
].indexOf(':') <= 1) {
956 String userDir
= System
.getProperty("user.dir");
958 // prepend native separator to path iff not present
959 if (userDir
.charAt(0) == '/' ||
960 userDir
.charAt(0) == java
.io
.File
.separatorChar
) {
965 url
= new URL(prot
+ userDir
.replace(File
.separatorChar
, '/')
967 url
= new URL(url
, argv
[i
]);
969 url
= new URL(argv
[i
]);
973 documentViewer
= DocumentProxy
.getDocumentProxy(url
, Toolkit
.getDefaultToolkit());
974 } catch (MalformedURLException e
) {
975 System
.out
.println(amh
.getMessage("main.err.badurl", argv
[i
], e
.getMessage()));
977 } catch (IOException e
) {
978 System
.out
.println(amh
.getMessage("main.err.io", e
.getMessage()));
979 if (argv
[i
].indexOf(':') < 0) {
980 System
.out
.println(amh
.getMessage("main.err.readablefile", argv
[i
]));
982 System
.out
.println(amh
.getMessage("main.err.correcturl", argv
[i
]));
988 if (documentViewer.countApplets() == 0) {
989 System.out.println(amh.getMessage("main.warning"));
994 private static AppletMessageHandler amh
= new AppletMessageHandler("appletviewer");