1
2
3
4
5
6
7
8
9
10
11
12
13 package com.eviware.soapui.support.components;
14
15 import java.awt.BorderLayout;
16 import java.awt.Component;
17 import java.awt.Toolkit;
18 import java.awt.event.ActionEvent;
19
20 import javax.swing.AbstractAction;
21 import javax.swing.Action;
22 import javax.swing.JEditorPane;
23 import javax.swing.JLabel;
24 import javax.swing.JPanel;
25 import javax.swing.SwingUtilities;
26
27 import org.mozilla.interfaces.nsIHttpChannel;
28 import org.mozilla.interfaces.nsIRequest;
29 import org.mozilla.interfaces.nsISupports;
30 import org.mozilla.interfaces.nsIURI;
31 import org.mozilla.interfaces.nsIWeakReference;
32 import org.mozilla.interfaces.nsIWebBrowser;
33 import org.mozilla.interfaces.nsIWebProgress;
34 import org.mozilla.interfaces.nsIWebProgressListener;
35 import org.mozilla.xpcom.Mozilla;
36 import org.mozilla.xpcom.XPCOMException;
37
38 import com.eviware.soapui.SoapUI;
39 import com.eviware.soapui.support.Tools;
40 import com.eviware.soapui.support.UISupport;
41 import com.eviware.soapui.support.xml.XmlUtils;
42 import com.teamdev.jxbrowser.WebBrowser;
43 import com.teamdev.jxbrowser.WebBrowserFactory;
44 import com.teamdev.jxbrowser.WebBrowserWindow;
45 import com.teamdev.jxbrowser.WindowCreator;
46 import com.teamdev.jxbrowser.event.LocationEvent;
47 import com.teamdev.jxbrowser.event.RequestAdapter;
48 import com.teamdev.jxbrowser.event.StatusChangeEvent;
49 import com.teamdev.jxbrowser.event.StatusChangeListener;
50 import com.teamdev.jxbrowser.mozilla.MozillaWebBrowser;
51 import com.teamdev.xpcom.Xpcom;
52
53 public class BrowserComponent implements nsIWebProgressListener, nsIWeakReference, StatusChangeListener
54 {
55 private WebBrowser browser;
56 private static WebBrowserFactory webBrowserFactory;
57 private JPanel panel = new JPanel( new BorderLayout() );
58 private JPanel statusBar;
59 private JLabel statusLabel;
60 private String errorPage;
61 private WebBrowserWindow browserWindowAdapter = new BrowserWindowAdapter();
62 private final boolean addToolbar;
63 private boolean showingErrorPage;
64 public String url;
65 private static Boolean initialized = false;
66
67 public BrowserComponent( boolean addToolbar )
68 {
69 this.addToolbar = addToolbar;
70
71 if( !initialized )
72 {
73 synchronized( initialized )
74 {
75 if( !initialized )
76 {
77 try
78 {
79 if( !isJXBrowserDisabled() )
80 {
81 if( Xpcom.isMacOSX() )
82 {
83 final String currentCP = System.getProperty( "java.class.path" );
84 final String appleJavaExtentions = ":/System/Library/Java";
85 System.setProperty( "java.class.path", currentCP + appleJavaExtentions );
86 }
87
88 Xpcom.initialize();
89 }
90
91 initialized = true;
92 }
93 catch( Throwable t )
94 {
95 t.printStackTrace();
96 }
97 }
98 }
99 }
100 }
101
102 public static boolean isJXBrowserDisabled()
103 {
104 String disable = System.getProperty( "soapui.jxbrowser.disable", "nope" );
105 if( disable.equals( "true" ) )
106 return true;
107
108 if( !disable.equals( "false" ) && "64".equals( System.getProperty( "sun.arch.data.model" ) ) )
109 return true;
110
111 return false;
112 }
113
114 public Component getComponent()
115 {
116 if( isJXBrowserDisabled() )
117 {
118 JEditorPane jxbrowserDisabledPanel = new JEditorPane();
119 jxbrowserDisabledPanel.setText( "browser component disabled" );
120 panel.add( jxbrowserDisabledPanel );
121 }
122 else
123 {
124 if( browser == null )
125 {
126 initBrowser();
127 navigate( "about:blank", null );
128
129 statusBar = new JPanel();
130 statusLabel = new JLabel();
131 statusBar.add( statusLabel, BorderLayout.CENTER );
132
133 if( addToolbar )
134 panel.add( buildToolbar(), BorderLayout.NORTH );
135
136 panel.add( browser.getComponent(), BorderLayout.CENTER );
137 panel.add( statusBar, BorderLayout.SOUTH );
138
139 panel.repaint();
140 }
141 }
142 return panel;
143 }
144
145 private Component buildToolbar()
146 {
147 JXToolBar toolbar = UISupport.createToolbar();
148
149 toolbar.addFixed( UISupport.createToolbarButton( new BackAction() ) );
150 toolbar.addRelatedGap();
151 toolbar.addFixed( UISupport.createToolbarButton( new ForwardAction() ) );
152
153 toolbar.addGlue();
154
155 return toolbar;
156 }
157
158 private class BackAction extends AbstractAction
159 {
160 public BackAction()
161 {
162 putValue( SMALL_ICON, UISupport.createImageIcon( "/arrow_left.png" ) );
163 putValue( Action.SHORT_DESCRIPTION, "Navigate to previous selection" );
164 }
165
166 public void actionPerformed( ActionEvent e )
167 {
168 if( browser.getHistory().getCurrentPosition() == 0 )
169 Toolkit.getDefaultToolkit().beep();
170 else
171 browser.goBack();
172 }
173 }
174
175 private class ForwardAction extends AbstractAction
176 {
177 public ForwardAction()
178 {
179 putValue( SMALL_ICON, UISupport.createImageIcon( "/arrow_right.png" ) );
180 putValue( Action.SHORT_DESCRIPTION, "Navigate to next selection" );
181 }
182
183 public void actionPerformed( ActionEvent e )
184 {
185
186
187
188
189
190 browser.goForward();
191 }
192 }
193
194 public void initBrowser()
195 {
196 if( webBrowserFactory == null )
197 webBrowserFactory = WebBrowserFactory.getInstance();
198
199 browser = webBrowserFactory.createBrowser();
200 nsIWebBrowser nsWebBrowser = ( ( MozillaWebBrowser )browser ).getWebBrowser();
201 nsWebBrowser.addWebBrowserListener( this, nsIWebProgressListener.NS_IWEBPROGRESSLISTENER_IID );
202 browser.addStatusChangeListener( this );
203
204 browser.setWindowCreator( new WindowCreator()
205 {
206 public WebBrowserWindow createChildWindow( Component parentComponent, long flags )
207 {
208 return browserWindowAdapter;
209 }
210 } );
211
212 browser.deactivate();
213 }
214
215 public void release()
216 {
217 if( browser != null )
218 {
219 browser.stop();
220 browser.deactivate();
221
222 nsIWebBrowser nsWebBrowser = ( ( MozillaWebBrowser )browser ).getWebBrowser();
223 nsWebBrowser.removeWebBrowserListener( this, nsIWebProgressListener.NS_IWEBPROGRESSLISTENER_IID );
224 browser.removeStatusChangeListener( this );
225 browser.dispose();
226 }
227
228 browser = null;
229 }
230
231 public void setContent( String contentAsString, String contentType, String contextUri )
232 {
233 if( browser == null )
234 {
235 initBrowser();
236 }
237 browser.setContentWithContext( contentAsString, contentType, contextUri );
238 }
239
240 public void setContent( String content, String contentType )
241 {
242
243
244 if( browser == null )
245 {
246 initBrowser();
247 }
248
249 try
250 {
251 browser.setContent( content, contentType );
252 }
253 catch( Throwable t )
254 {
255 SoapUI.logError( t );
256 }
257 }
258
259 public boolean navigate( String url, String errorPage )
260 {
261 if( browser == null )
262 {
263 initBrowser();
264 }
265
266 if( errorPage != null )
267 setErrorPage( errorPage );
268
269 this.url = url;
270 SwingUtilities.invokeLater( new Navigator() );
271
272 return true;
273 }
274
275 public String getContent()
276 {
277 return browser == null ? null : XmlUtils.serialize( browser.getDocument() );
278 }
279
280 private final class Navigator implements Runnable
281 {
282 public void run()
283 {
284 try
285 {
286 browser.navigate( getUrl() );
287 }
288 catch( Throwable e )
289 {
290 SoapUI.log( e.toString() );
291 }
292 }
293 }
294
295 public String getUrl()
296 {
297 return url;
298 }
299
300 public void setUrl( String url )
301 {
302 navigate( url, null );
303 }
304
305 public nsISupports queryInterface( String uuid )
306 {
307 return Mozilla.queryInterface( this, uuid );
308 }
309
310 public nsISupports queryReferent( String uuid )
311 {
312 return Mozilla.queryInterface( this, uuid );
313 }
314
315 public void onLocationChange( nsIWebProgress arg0, nsIRequest arg1, nsIURI arg2 )
316 {
317 }
318
319 public void onProgressChange( nsIWebProgress arg0, nsIRequest arg1, int arg2, int arg3, int arg4, int arg5 )
320 {
321 }
322
323 public void onSecurityChange( nsIWebProgress arg0, nsIRequest arg1, long arg2 )
324 {
325 }
326
327 public void onStateChange( nsIWebProgress arg0, nsIRequest request, long arg2, long arg3 )
328 {
329 try
330 {
331 if( !getUrl().equals( "about:blank" ) )
332 {
333 nsIHttpChannel ch = null;
334 try {
335 ch = ( nsIHttpChannel )request.queryInterface( nsIHttpChannel.NS_IHTTPCHANNEL_IID );
336 }
337 catch( XPCOMException e )
338 {
339 if( (!browser.getLocationURL().equals( errorPage )) && ( e.errorcode != 2147500034l ) )
340 {
341 SoapUI.log.warn( "Error [" + e.getMessage() + "] for " + e.errorcode );
342 browser.navigate( errorPage );
343 }
344 }
345 if( ch != null && ch.getResponseStatus() >= 400 )
346 {
347
348 if( !showingErrorPage )
349 showErrorPage();
350 }
351 }
352 }
353 catch( XPCOMException e )
354 {
355
356
357
358
359
360 }
361 }
362
363 private void showErrorPage()
364 {
365 showingErrorPage = true;
366 browser.navigate( errorPage );
367 showingErrorPage = false;
368 }
369
370 public String getErrorPage()
371 {
372 return errorPage;
373 }
374
375 public void setErrorPage( String errorPage )
376 {
377 this.errorPage = errorPage;
378 }
379
380 public void onStatusChange( nsIWebProgress arg0, nsIRequest arg1, long arg2, String arg3 )
381 {
382 }
383
384 private class BrowserWindowAdapter implements WebBrowserWindow
385 {
386 private boolean resizable;
387
388 public void close()
389 {
390 }
391
392 public boolean isClosed()
393 {
394 return true;
395 }
396
397 public void setModal( boolean arg0 )
398 {
399 }
400
401 public void setSize( int arg0, int arg1 )
402 {
403 }
404
405 public void setVisible( boolean arg0 )
406 {
407 }
408
409 public void setWebBrowser( WebBrowser arg0 )
410 {
411 if( arg0 != null )
412 {
413 arg0.addRequestListener( new RequestAdapter()
414 {
415
416 @Override
417 public void locationChanged( final LocationEvent arg0 )
418 {
419 if( !arg0.getLocation().equals( "about:blank" ) )
420 {
421 if( UISupport.confirm( "Open url [" + arg0.getLocation() + "] in external browser?", "Open URL" ) )
422 Tools.openURL( arg0.getLocation() );
423
424 arg0.getWebBrowser().stop();
425 arg0.getWebBrowser().deactivate();
426 arg0.getWebBrowser().dispose();
427 arg0.getWebBrowser().removeRequestListener( this );
428 }
429
430 }
431 } );
432
433
434
435
436
437
438 }
439
440 }
441
442 public boolean isResizable()
443 {
444 return resizable;
445 }
446
447 public void setResizable( boolean resizable )
448 {
449 this.resizable = resizable;
450 }
451 }
452
453 public void statusChanged( final StatusChangeEvent event )
454 {
455 if( statusLabel != null )
456 {
457 SwingUtilities.invokeLater( new Runnable()
458 {
459 public void run()
460 {
461 statusLabel.setText( event.getStatus() );
462 }
463 } );
464 }
465 }
466
467 public boolean isBrowserInitialised() {
468 return browser != null;
469 }
470 }