반응형
About the Browser

This section explains the architecture of Microsoft Internet Explorer 4.0 and later and provides information you will find helpful when reusing these components.

This topic contains the following sections.

Architectural Overview

Windows Internet Explorer uses Microsoft ActiveX Controls and Active Document interfaces to connect components. The following diagram provides a high-level overview.

Internet Explorer 4.0 Architecture.

IExplore.exe is at the top level; it is a small application that is instantiated when Internet Explorer is loaded. This executable application uses Internet Explorer components to perform the navigation, history maintenance, favorites maintenance, HTML parsing and rendering, and so on, while it supplies the toolbar and frame for the stand-alone browser. IExplorer.exe directly hosts the Shdocvw.dll component.

Shdocvw.dll in turn hosts the Mshtml.dll component, as well as any other Active Document component (such as a Microsoft Office application) that can be loaded in place in the browser when the user navigates to a specific document type. Shdocvw.dll supplies the functionality associated with navigation, in-place linking, favorites and history management, and PICS support. This DLL also exposes interfaces to its host to allow it to be hosted separately as an ActiveX control. The Shdocvw.dll component is more frequently referred to as the WebBrowser Control. In-place linking refers to the ability to click a link in the HTML of the loaded document and to load a new HTML document in the same instance of the WebBrowser Control. If only Mshtml.dll is being hosted, a click on the link results in a new instance of the browser.

Mshtml.dll is the component that performs the HTML parsing and rendering in Internet Explorer 4.0 and later, and it also exposes the HTML document through the Dynamic HTML Object Model. This component hosts the scripting engines, Microsoft virtual machine, ActiveX Controls, plug-ins, and other objects that might be referenced in the loaded HTML document. Mshtml.dll implements the Active Document server interfaces, which allows it to be hosted using standard Component Object Model (COM) interfaces.

As this is an OLE-based architecture, the ambient properties that are commonly used by ActiveX Controls can also be applied to the Internet Explorer components. In this way, a host of the WebBrowser Control can set an ambient property that will filter down to all the frames and controls hosted in the loaded document.

Choosing the Correct Component

The WebBrowser Control provides a rich set of functionality that a host typically requires, such as that for in-place linking. Therefore, it is much more applicable for most applications to host this control instead of MSHTML for browsing or viewing HTML documents. Hosting MSHTML is recommended only for specialized applications, such as parsing HTML. The WalkAll Sample Source Page demonstrates how to host MSHTML.

It should also be noted that although hosting MSHTML is slightly more lightweight than hosting the WebBrowser Control, the savings rarely justify the extra work involved in implementing functionality that is already available in the WebBrowser Control. It is very likely that the WebBrowser Control will already be loaded in memory, and navigating to a frameset page will also result in the WebBrowser Control being loaded as part of the standard working set.

Providing Extra Control

Hosts of the WebBrowser Control and MSHTML components have control over certain functionality. In the case of the WebBrowser Control, this includes navigation, as well as receiving events when the document is loaded. Hosts of either component can obtain extra control over functionality by implementing the IDocHostUIHandler and IDocHostShowUI interfaces. These interfaces are commonly used to override the context menus that are supplied by default for the browser. Their uses also include setting the 3-D border, overriding the location in the registry where options are stored, and extending the Dynamic HTML Object Model.

The component obtains these interfaces from the host by calling QueryInterface on the IOleClientSite interface implemented by the hosting application.

Controlling the Context Menus

A common requirement of hosting the WebBrowser Control is the ability to override or add to the context menus that are displayed as the result of a right-click in the browser window. This is of particular interest to applications that are using the WebBrowser Control to view rich content but do not want the user to know that HTML is being viewed. This is also advantageous for applications that do not want the user to be able to view the HTML source for the content.

There are two techniques available to achieve this. The first involves the use of the IDocHostUIHandler interface and allows an application to disable or replace the context menus. The second technique involves the use of the registry and allows the existing context menus to be extended.

Overriding the Context Menus

The WebBrowser Control's context menus can be overridden entirely by implementing the IDocHostUIHandler::ShowContextMenu method. Returning E_NOTIMPL or S_FALSE from this method indicates to the WebBrowser Control that it should display its own standard context menu. However, returning S_OK causes the WebBrowser Control not to display its menus, and it assumes that the host has performed the appropriate action. The host can disable all context menus or bring up its own context menus. The parameters supplied to the host that implements this method allow that host to identify which of the default menus will be displayed by the WebBrowser Control, as well as the coordinates where the menu will be displayed. This provides the host the full context for the menu. For example, the host can choose to override only the image context menus and not the standard context menus.

Adding to the Standard Context Menus

Items can be added to the existing context menus of the WebBrowser Control by placing entries in the registry and linking these to URLs that execute script. To add items to the standard WebBrowser Control context menus, create or open the following key:

  • HKEY_CURRENT_USER
    • Software
      • Microsoft
        • Internet Explorer
          • MenuExt

Under this key, you create a key whose name contains the text you want displayed in the menu. The default value for this key contains the URL that will be executed. The key name can include the ampersand (&) character, which will cause the character immediately following the & to be underlined. The URL will be loaded inside a hidden HTML dialog box, all the inline script will be executed, and the dialog box will be closed. The hidden HTML dialog's menuArguments property (on the external object) contains the window object of the window on which the context menu item was executed.

The following registry entry adds an item with the title "My Menu Item" to the WebBrowser Control context menu and executes the inline script contained in the file c:\myscript.htm.

  • HKEY_CURRENT_USER
    • Software
      • Microsoft
        • Internet Explorer
          • MenuExt
            • My &Menu Item

            • (Default) = file://c:\myscript.htm

The contents of c:\myscript.htm are as follows:

<SCRIPT LANGUAGE="JavaScript" defer>
   var parentwin = external.menuArguments;
   var doc = parentwin.document;
   var sel = doc.selection;
   var rng = sel.createRange();
   var str = new String(rng.text);

   if(str.length == 0)
      rng.text = "MY INSERTED TEXT";
   else
      rng.text =  str.toUpperCase();
</SCRIPT>

This script obtains the parent window object from external.menuArguments. The parent window object is the WebBrowser Control in which the context menu item was executed. The script then obtains the current selection and, if no selection is present, inserts the text "MY INSERTED TEXT" at the point where the context menu was executed. If there is a selection present, the selected text is changed to uppercase.

Optional keys

Under the item registry key created earlier, there are a couple of optional values. One of these specifies on which context menus this item will appear. The other specifies that the script should be run as a dialog box.

The "Contexts" DWORD value specifies the context menus in which an item will appear. This value is a bit mask consisting of the logical OR of the following values (defined in Mshtmhst.h). These values correspond to the constant passed in an IDocHostUIHandler::ShowContextMenu call.

Value Constant Name Description
0x01 CONTEXT_MENU_DEFAULT Shown on all context menus.
0x02 CONTEXT_MENU_IMAGE Context menu of images only.
0x04 CONTEXT_MENU_CONTROL Context menu of form controls only.
0x08 CONTEXT_MENU_TABLE Context menu of tables only.
0x10 CONTEXT_MENU_TEXTSELECT Context menu of selected text only, including images in a selected region.
0x20 CONTEXT_MENU_ANCHOR Context menu of links only. Does not include linked images or image maps.
0x40 CONTEXT_MENU_UNKNOWN Right-click on none of the above.

So if, for example, you want this simple extension to appear only in the default menu and the text selection menu, you could create a DWORD value in the registry under the My Menu Item key called "Contexts" and set it to 0x11. From C/C++ code, this can be expressed as:

CONTEXT_MENU_DEFAULT | CONTEXT_MENU_TEXTSELECT

The other optional registry DWORD value is "Flags". There is only one valid bit (0x1) for this registry value; it is defined as MENUEXT_SHOWDIALOG in Mshtmhst.h. When this bit is set, the script is run just as if it had been called through the IHTMLWindow2::showModalDialog method. The window that runs the script is not hidden, and the dialog box is not automatically closed after inline and onload script finishes. The external.menuArguments value still contains the window object where the user selected the menu item.

The context menu event

Whenever a context menu extension is triggered, the event object off the main window (external.menuArguments.event) contains information about where the user clicked and which context menu was shown. The mouse coordinates are valid along with srcElement. The type value contains one of the following strings, indicating which context menu was shown to the user:

  • MenuExtDefault
  • MenuExtImage
  • MenuExtControl
  • MenuExtTable
  • MenuExtTextSelect
  • MenuExtAnchor
  • MenuExtUnknown

Another example

This example creates a new menu item on the default context menu. This item, called Show In New Window, can be used to launch a new window that displays only a specific portion of the current document. If something is deeply nested in a frameset, you can easily launch a specific frame in its own window.

Here are the contents of a .reg file that can be run to insert the correct registry settings. Call this file Example2.reg. Double-clicking this file in Windows Explorer will insert the settings in your registry.

REGEDIT4

    [HKEY_CURRENT_USER\Software\Microsoft\Internet Explorer\MenuExt\Show in New Window]
    @="file://c:\\example2.htm"
    "Contexts"=dword:00000001

Here are the contents of c:\example2.htm:

<SCRIPT LANGUAGE="JavaScript" defer>
    window.open(external.menuArguments.location.href);
</SCRIPT>

For more information, see Adding Entries to the Standard Context Menu.

Extending the Dynamic HTML Object Model

It is possible for the hosting application to extend the Dynamic HTML Object Model so that scripts can refer to functionality implemented by the host. Such scripts refer to the host by specifying the external object that is available from the window object. For example, a reference to "window.external.speech" will call the host to resolve the name "speech." All standard script within the document will be executed normally.

This extension mechanism is implemented in the host by providing an IDispatch interface for the object model extension that will have IDispatch::GetIDsOfNames and IDispatch::Invoke called on it to resolve any references to the external object. The IDispatch that the host provides is obtained by the WebBrowser Control or MSHTML component by calling the host's IDocHostUIHandler::GetExternal method.

For an example of how to extend the Dynamic HTML Object Model, see the Driller Sample Source Page.

Download Control

Hosts can control certain aspects of downloading—frames, images, Java, and so on—by implementing both IOleClientSite and an ambient property defined as DISPID_AMBIENT_DLCONTROL. When the host's IDispatch::Invoke method is called with dispidMember set to DISPID_AMBIENT_DLCONTROL, it should place zero or a combination of the following values in pvarResult.

DLCTL_BGSOUNDS The browsing component will play background sounds associated with the document.
DLCTL_DLIMAGES The browsing component will download images from the server.
DLCTL_DOWNLOADONLY The browsing component will download the page but not display it.
DLCTL_FORCEOFFLINE The browsing component will always operate in offline mode. This causes the BINDF_OFFLINEOPERATION flag to be set even if the computer is connected to the Internet when making requests through URLMON.
DLCTL_NO_BEHAVIORS The browsing component will not execute any behaviors.
DLCTL_NO_CLIENTPULL The browsing component will not perform any client pull operations.
DLCTL_NO_DLACTIVEXCTLS The browsing component will not download any ActiveX Controls in the document.
DLCTL_NO_FRAMEDOWNLOAD The browsing component will not download frames but will download and parse the frameset page. The browsing component will also ignore the frameset, and will render no frame tags.
DLCTL_NO_JAVA The browsing component will not execute any Java applets.
DLCTL_NO_METACHARSET The browsing component will suppress HTML Character Sets reflected by meta elements in the document.
DLCTL_NO_RUNACTIVEXCTLS The browsing component will not execute any ActiveX Controls in the document.
DLCTL_NO_SCRIPTS The browsing component will not execute any scripts.
DLCTL_OFFLINE Same as DLCTL_OFFLINEIFNOTCONNECTED.
DLCTL_OFFLINEIFNOTCONNECTED The browsing component will operate in offline mode if not connected to the Internet. This causes the BINDF_GETFROMCACHE_IF_NET_FAIL flag to be set if the computer is connected to the Internet when making requests through URLMON.
DLCTL_PRAGMA_NO_CACHE The browsing component will force the request through to the server and ignore the proxy, even if the proxy indicates that the data is up to date. This causes the BINDF_PRAGMA_NO_CACHE flag to be set when making requests through URLMON.
DLCTL_RESYNCHRONIZE The browsing component will ignore what is in the cache and ask the server for updated information. The cached information will be used if the server indicates that the cached information is up to date. This causes the BINDF_RESYNCHRONIZE flag to be set when making requests through URLMON.
DLCTL_SILENT The browsing component will not display any user interface. This causes the BINDF_SILENTOPERATION flag to be set when making requests through URLMON.
DLCTL_URL_ENCODING_DISABLE_UTF8 The browsing component will disable UTF-8 encoding.
DLCTL_URL_ENCODING_ENABLE_UTF8 The browsing component will enable UTF-8 encoding.
DLCTL_VIDEOS The browsing component will play any video clips that are contained in the document.

Security Manager

Hosts of the browsing components can implement their own security management and override the settings that exist for the WebBrowser Control. This is achieved by implementing the IInternetSecurityManager interface. The browsing component will obtain this interface by calling the host's IServiceProvider::QueryService method with SID_SInternetSecurityManager. For more information on security management, see About URL Security Zones.


반응형

Java 로 사용될 수 있는 Browser Component 에 대하여 (리눅스 플렛폼에서 사용할 목적으로) 조사하였음.

실 사용자의 사용 브라우저와 가장 근접한 렌더링 결과를 내면서 가장 높은 접근성을 가지는 것을 목적으로 조사하였기 때문에.

결과가 Mozilla Compatable 한 방향으로 편중 되어 있음을 미리 염두에 두고 보시면 편할 듯.


http://www.webrenderer.com/index.php

Full Swing 으로 구현된 Mozilla Compatable Browser. 상용이다.

아무래도 돈주고 사는 제품이다 보니, 완성도는 높을 듯. 랜더링,접근성 대비 최상이라고 예상됨.


http://www.icesoft.com/products/icebrowser.html

Full Java로 구현되었으며 Java Application에 Embed 되어 사용되는 목적으로 개발 되었다.

상용제품으로 완성도는 높지만, 가격이 문제. Mozilla Compatable 하지 않으므로 효용성이 떨어짐


http://jazilla.sourceforge.net/

Java로 구현된 Mozilla compatible(HTML,XUL) rendering engine

현재 M4 까지 진행 된 상태 이며, 오픈소스로 진행 되며, M4까지 진행 된 관계로 완성도가 떨어질 것으로 예상.

정확한 완성도는 살펴보지 못 하였음. 관련 자료는 http://sourceforge.net/projects/jazilla/ 에서 다운로드 받을 수 있음.


http://mozillaparser.sourceforge.net/

Mozilla Parser만 연결한 방식, Rendering 이 들어가 있지 않으므로 반쪽 효용성.

JNI 방식이며 설명에도 나와 있지만 연결방식이 매끄럽지 못하여 성능 문제가 있는것 으로 보임.


http://www.eclipse.org/atf/

가장 Stable 하다는 평이 있음. SWT 용 이며, Browser 목적으로 따로 나와 있는 것이 아니고,

ATF에서 사용되는 일부 기능인 만큼, 분석 및 따로 떼어서 작성하는 과정이 필요함. (Firefox,IE 등 모두 연결 가능)


http://www.mozilla.org/projects/blackwood/webclient/

Java WebShell 을 사용하는 개념을 지원하는 Mozilla 프로젝트 (Gecko 뿥만 아니라 Windows에서 IE도 연결 가능하다고 함)

Mozilla 정식 프로젝트 인 만큼 가장 많은 기능을 사용할 수 있으며, 랜더링 또한 Firefox와 같은 수준

접근성 또한 높은 수준으로 제공됨, 다만 Full Java 가 아니기 때문에 완벽한 접근성이 보장되는 것은 아님.


https://jdic.dev.java.net/

java.net 에서 호스트 되는 프로젝트로 Mozilla 뿐만 아니라 IE등의 브라우져를 JNI 방식으로 연결하여 제공한다.

기능성 및 접근성이 많이 떨어진다.


http://jrex.mozdev.org/

Mozilla Gecko를 Embedding 하여 사용할 수 있도록 지원한다. JNI 방식이며 GRE를 설치하여 사용한다.

Mozilla Gecko 1.4  이상 과 호환되며 접근성은 어느정도 제한적 인 것으로 보인다.

반응형
반응형
달송
http://blog.naver.com/drub5?Redirect=Log&logNo=130033212540
알송을 Java로 만든거라고 합니다.


자테온
http://blog.kfmes.com/category/JaTeOn
네이트온을 Java로 만든것입니다.


다들 개발자분들이 자작하신 프로그램입니다.
반응형


JavaSound API 는 자바 플랫폼에서 audio 재생을 지원하기 위해 만들어졌다.
이 API는 J2SE 1.3 버전에서 처음 추가되었고, wav, au, aiff, midi 오디오 포멧만을 지원한
다.

mp3 나 ogg 파일 포멧을 사용하고 싶을때는 어떻게 해야 할까?
이러한 문제점을 해결하기 위해 JavaSound API  에서는 JavaSound Service Provider Interfaces (SPIs) 를 이용한 확장을 지원한다. 이 인터페이스를 통해서, 사용자가 구현하고자 하는 오디오포멧을 지원하면 된다.

이것은  JDBC와 같은 개념이다. DB서버가 각각 다르더라도, JDBC 인터페이스를 통해 통일된 DB프로그래밍을 할수 있는 것과 같은 개념이다.

JavaZoom 의 mp3 플러인
* 특징
- mp3 재생만 지원 (MPEG 1, 2 and 2.5, Layers 1, 2, and 3)
- 현재는 mp3 재생만 지원 (Encoding, Converter, Write 기능은 아직 구현되지 않음)
- 메타데이타 ID3 태그 지원 (artist, album, date, copyright, comments, 정보를 뽑아올수 있다)

mp3 를 파일에서 정보를 뽑아오는 방법
1. File 객체를 이용하여 AudioFileFormat 객체를 생성한다.
2. getFormat() 객체를 호출한다.
3. AudioFormat 인스턴스에서 값을 뽑아온다.

File file = new File("filename.mp3");
AudioFileFormat baseFileFormat = null;
AudioFormat baseFormat = null;
baseFileFormat = AudioSystem.getAudioFileFormat(file);
baseFormat = baseFileFormat.getFormat();
AudioFileFormat.Type type = baseFileFormat.getType();
float frequency = baseFormat.getSampleRate();

To play MP3, you need first to call AudioSystem.getAudioInputStream(file) to get an AudioInputStream from an MP3 file, select the target format (i.e., PCM) according to input MP3 channels and sampling rate, and finally get an AudioInputStream with the target format. If JavaSound doesn't find a matching SPI implementation supporting the MP3-to-PCM conversion, then it will throw an exception.

File file = new File("filename.mp3");
AudioInputStream in= AudioSystem.getAudioInputStream(file);
AudioInputStream din = null;
AudioFormat baseFormat = in.getFormat();
AudioFormat decodedFormat = new AudioFormat(
 AudioFormat.Encoding.PCM_SIGNED, 
 baseFormat.getSampleRate(), 
 16,
 baseFormat.getChannels(), 
 baseFormat.getChannels() * 2,
 baseFormat.getSampleRate(),
 false);
din = AudioSystem.getAudioInputStream(decodedFormat, in);
// Play now.
rawplay(decodedFormat, din);
in.close();

Second, you have to send the decoded PCM data to a SourceDataLine. This means you have to load PCM data from the decoded AudioInputStream into the SourceDataLine buffer until the end of file is reached. JavaSound will send this data to the sound card. Once the file is exhausted, the line resources must be closed.

private void rawplay(AudioFormat targetFormat, AudioInputStream din)  throws IOException, LineUnavailableException {
 byte[] data = new byte[4096];
 SourceDataLine line = getLine(targetFormat);
 if (line != null) {
 // Start
 line.start();
 int nBytesRead = 0, nBytesWritten = 0;
 while (nBytesRead != -1) {
 nBytesRead = din.read(data, 0, data.length);
 if (nBytesRead != -1) nBytesWritten = line.write(data, 0, nBytesRead);
 }
 // Stop
 line.drain();
 line.stop();
 line.close();
 din.close();
 }
}

private SourceDataLine getLine(AudioFormat audioFormat)
 throws LineUnavailableException {
 SourceDataLine res = null;
 DataLine.Info info = new DataLine.Info(SourceDataLine.class, audioFormat);
 res = (SourceDataLine) AudioSystem.getLine(info);
 res.open(audioFormat);
 return res;
}


If you're familiar with JavaSound API, you will notice that source code for playing MP3 is similar to the what you'd use to play a WAV file. The source code sample above has no dependencies upon the MP3 SPI implementation. It's transparent for the developer.

Notice that if the file to play was stored on a web server, we would have used:
URL url = new URL(http://www.myserver.com/filename.mp3); AudioInputStream in= AudioSystem.getAudioInputStream(url);

instead of:
File file = new File("filename.mp3"); AudioInputStream in= AudioSystem.getAudioInputStream(file);

Metadata
Most audio formats include metadata such as title, album, comments, compression quality, encoding, and copyright. ID3 tags, used for MP3, are the best-known metadata format. Depending on ID3 version (v1 or v2), they can be found either at the end or at the beginning of an MP3 file. They include information such as duration, title, album, artist, track number, date, genre, copyright, etc. They can even include lyrics and pictures. The famous (and free) SHOUTcast streaming MP3 server, from Nullsoft, uses a different scheme in order to provide additional metadata such as title streaming, which allows a player to display the current song being played from the online radio stream. All of these metadata items need to be parsed and exposed through the SPI implementation. As of J2SE 1.5, the JavaSound API standardizes the passing of metadata parameters through an immutable java.util.Map:

File file = new File("filename.mp3");
AudioFileFormat baseFileFormat = AudioSystem.getAudioFileFormat(file);
Map properties = baseFileFormat.properties();
String key_author = "author";
String author = (String) properties.get(key_author);
String key_duration = "duration";
Long duration = (Long) properties.get(key_duration);

All metadata keys and types should be provided in the SPI documentation. However, common properties include:
"duration" (Long): Playback duration of file, in microseconds
"author" (String): Name of the author of the file
"title" (String): Title of the file
"copyright" (String): Copyright message
"comment" (String): Arbitrary text

Using Multiple SPIs in an Application
Adding MP3 audio capabilities to the Java platform means adding JAR files containing the MP3 SPI implementation to the runtime CLASSPATH. Adding Ogg Vorbis, Speex, Flac, or Monkey's Audio support would be similar, but could generate conflicts that make other SPI implementations fail. The following situation could occur:

Your runtime application CLASSPATH includes both MP3 and Ogg Vorbis SPIs.
Your application tries to play an MP3 file.
JavaSound's AudioSystem tries Ogg Vorbis SPI first.
The Ogg Vorbis SPI implementation doesn't detect that incoming file isn't an Ogg-Vorbis-compliant stream, so it doesn't throw any exception.
Your application tries to play an MP3 with the Ogg Vorbis SPI. At best you will get a runtime exception (NullPointerException, ArrayIndexOutOfBoundException), and in the worst case, you will hear weird noises or just deadlock.
In the example above, it's true that the problem comes from the Ogg Vorbis SPI implementation, but it's not easy for the SPI provider to have reliable controls (just think about streaming). Thus, each SPI provider has to pay attention to the others. That's the main practical drawback of the JavaSound plugin architecture. So don't be surprised if you have problems making multiple SPIs work together in your application.

Differences with JMF
JMF stands for Java Media Framework. It's an optional J2SE packages that adds multimedia support to the Java platform. It includes audio (GSM, QuickTime, etc.), video (AVI, QuickTime, H.263, etc.) and RTP streaming features. JMF provides a plugin architecture, but it is not compliant with that of JavaSound. In fact, MP3 support was previously included in JMF, but it was removed in 2002 because of licensing issues.

Conclusion
JavaSound rocks. It provides a plugin architecture allowing any third-party provider to add custom audio format support, such as for MP3 files. API is flexible enough to plug most heterogeneous (lossy, lossless) audio formats, whatever their parameters and metadata, to the Java platform -- "Write once, play anywhere."

References and Resources

JLayer: Java library for decoding and converting MP3 files
MP3 SPI: MP3 plugin for the Java platform
Speex SPI: Speex plugin for the Java platform
Ogg Vorbis SPI: Ogg Vorbis plugin for the Java platform
Monkey's Audio SPI: Monkey's Audio plugin for the Java platform
Flac SPI: Flac plugin for the Java platform
SHOUTcast: SHOUTcast streaming MP3 server
jlGui player: Music player for the Java platform -- a WinAmp clone
JavaSound: SUN homepage
Tritonus: Tritonus project
MP3 Tech: MP3 frame header info
ID3: ID3 definition
The JavaZOOM Team are the authors of the open source projects JLayer and jlGui.


<출처: http://zyint.tistory.com/1 >
반응형

SWT 애플리케이션의 개발 과정 중에서 특히, 기본적인 프로토타입을 완성한 이후에, 전개 시 발생될 수 있는 문제에 대하여 고려하여야 합니다. 전통적인 자바 애플리케이션과는 달리, SWT 애플리케이션은 애플리케이션이 작동하기 전에 OS 스팩의 라이브러리들이 로딩되어야 합니다. 이러한 라이브러리들을 지속적으로 전개 및 관리해야 한다는 것은 쉽지 않지만 Sun의 Java Web Start가 도움이 됩니다. SWT와 Java Web Start가 결합하면 클라이언트 측 자바 애플리케이션 구축하는 데에 훌륭한 툴이 됩니다.

SWT 개요

Standard Widget Toolkit (SWT)을 개발 커뮤니티로 도입하기가 여간 까다로운 것이 아니다. 그러한 근거로는 Sun은 Java Foundation Classes (JFC)로 클라이언트 측 애플리케이션 개발자들을 여러 해 동안 회유하고는 있지만, 많은 개발자들은 여러 가지 이유로 이 툴킷 사용을 피하고 있다. 많은 개발자와 아키텍트에게 있어서, 전통적인 데스크탑 애플리케이션처럼 작동하는 클라이언트 측 자바 애플리케이션을 개발하는 것은 아직도 꿈과 같은 일이다.

2001년 중반에, 이클립스 프로젝트가 갑자기 생겨나기 시작했다. 처음에, 이클립스 프로젝트는 자바용 유일한 오픈 소스 Integrated Development Environment (IDE)로 인식되었다. 하지만, 그의 프로젝트의 범위는 훨씬 더 광범위해 졌으며, SWT 툴킷을 탄생시켰다. JFC와 사촌격인 Abstract Window Toolkit (AWT)와 마찬가지로, SWT 툴킷은 개발자용 위젯을 제공한다. 하지만, SWT와 다른 툴킷들과의 주요한 차이점은 SWT가 OS GUI 위젯을 사용하는 방식이다. 이러한 방식은 자바 개발자들에게 크로스 플랫폼 API를 제공하여 원래의 데스크탑 애플리케이션인 것 같은 느낌을 주는 솔루션을 구현할 수 있도록 해준다.




위로


Java Web Start 개요

어떤 언어든, 올바른 툴이 없다면 데스크탑 애플리케이션의 전개와 관리는 개발자들에게 가장 큰 고민거리가 될 것이다. 지원 부서들 조차 새로운 버전의 소프트웨어가 릴리스 될 때 모든 워크스테이션을 업데이트 해야 한다는 생각에 사로잡혀 있으며, 배포 및 관리 요구 사항들을 완화시키기 위해서, 몇년 전 Sun Microsystems는 Java Web Start를 도입했다. 이 기술은 엔드 유저의 워크스테이션에서 자바 애플리케이션의 전개, 관리, 업그레이드를 단순화 한다.

애플리케이션을 시작하는 초기 툴로서 웹 브라우저를 사용하는 Java Web Start는 Sun의 Java Runtime Environment에 포함된 로컬에서 설치된 헬퍼 애플리케이션이다. Java Network Launching Protocol (JNLP) 파일에 액세스 할 때마다, 애플리케이션은 사용자 워크스테이션으로 자동 다운로드 되어 실행을 시작한다. 전체 프로세스는 엔드 유저와의 인터랙션에 대한 필요성이 줄어들었고, 애플리케이션 분산 과정도 단순화 되었다. (참고자료)




위로


파일 뷰어 애플리케이션

Java Web Start를 사용하여 SWT 애플리케이션을 전개하는 방법을 보기 전에, 우리가 전개할 애플리케이션에 대해 잠깐 보도록 하자. 이 글에 소개된 애플리케이션은 이클립스 프로젝트에서 제공하는 예제 애플리케이션이다. 그림 1에서 보듯, 이 애플리케이션은 크로스-플랫폼(cross platform) 파일 뷰어로서 사용자들이 하드 드라이브 상의 파일과 폴더를 볼 수 있도록 한다.


그림 1. Windows XP에서 실행되는 파일 뷰어
File Viewer

SWT와 Java Web Start의 크로스 플랫폼 기능을 설명하기 위해, 이 글의 예제 애플리케이션은 Microsoft Windows와 Red Hat Linux에서 실행되도록 패키징 되어 있다.




위로


환경 요구 사항

본 기사에서 기술한 코드는 하단부에 명기된 링크를 통하여 다운로드 할 수 있다. Java Web Start로 파일 뷰어 애플리케이션을 테스트 하려면, 다음과 같은 조건이 충족되어야 한다. (참고자료의 다운로드 링크 참조)

  • Microsoft Windows XP 또는 Red Hat Linux 8 OS
  • Java 2 SDK, Standard Edition 1.4 또는 이후 버전
  • Apache Ant 1.5.3 또는 이후 버전
  • Jakarta Tomcat 4.1.24 또는 이후 버전

Ant 빌드 스크립트를 크로스 플랫폼으로 만드는 것이 본 글의 목적이지만, 파일 뷰어 애플리케이션은 Microsoft Windows XP와 Red Hat Linux 8 OS에서만 테스트 및 확인되었다. 또한, Tomcat은 로컬 워크스테이션과 8080 포트에서 실행되는 것으로 간주한다. 예제 애플리케이션을 구현 및 설치, 실행해보자.




위로


파일 뷰어 애플리케이션 설치하기

파일 뷰어 애플리케이션을 설치하려면 다음 단계를 따른다.

  1. 참고자료 섹션에서 제공하는 링크를 통해 소스 코드 패키지를 다운로드 한다.
  2. fileviewer.zip 파일을 임시 디렉토리에서 압축을 푼다.



위로


보안과 코드 사인

AWT나 JFC와는 달리, SWT는 OS 본연의 윈도우 환경과 긴밀히 연관되어 있다. SWT는 시스템 라이브러리를 사용하여 플랫폼 독립 API와 기반 OS 간 통합을 관리한다. 기본적으로, Java Web Start에서 실행되는 애플리케이션은 제한된 샌드박스(sandbox)에서 실행된다. 이 환경은 워크스테이션의 파일 시스템, 시스템 라이브러리, 기타 리소스 같은 리소스로의 액세스를 제어한다. SWT는 시스템 라이브러리를 로딩하기 위해서 기본 샌드박스 밖에서 실행되어야 하므로, Java Web Start에 전개된 모든 JAR 파일들은 디지털 서명이 필요하다. 이 애플리케이션은 광범위한 사용자 베이스로 전개할 것은 아니므로 자체 서명 테스트 인증을 만들 것이다.

만일 여러분이 SWT 애플리케이션을 실행 환경에 설치하려면, Thawte 또는 VeriSign 같은 인증 기구에서 인증서를 받아두는 것이 좋다.




위로


자체 서명 인증서 만들기

자체 서명 테스트 인증서를 만들려면 다음과 같이 한다.

  1. 소스 코드의 압축을 풀었던 디렉토리에서 다음 명령어를 실행한다: keytool -genkey -keystore keystore -alias myself.

    패스워드, 이름, 위치를 포함한 새로운 키에 대한 상세를 요청하는 프롬프트가 뜬다. Ant 빌드 프로세스를 사용하려면, 패스워드를 "password"로 설정한다. 패스워드를 "password"로 하지 않으려면, build.xml 파일 내에서 "sign-jars"를 편집한다. 각 JAR 파일을 서명하는 실제 프로세스는 Ant 구현 동안에 완료된다.

  2. 키스토어(Keystore)가 올바르게 생성되었는지를 확인하려면 소스 코드 압축을 풀었던 디렉토리에 다음 명령을 실행한다: keytool -list-keystore keystore

    결과는 다음과 같다:

    Keystore type: jks
    Keystore provider: SUN
           
    Your keystore contains 1 entry
           
    myself, Jun 3, 2003, keyEntry,
    Certificate fingerprint (MD5):B8:C4:48:ED:68:E8:FE:47:83:78:F5:14:4E:28:5C:80




위로


파일 뷰어 애플리케이션 구현하기

파일 뷰어 애플리케이션을 구현하려면, 다음 단계를 따라간다.

  1. 환경을 삭제하려면, 소스 코드 압축을 풀었던 디렉토리에서 ant clean 명령을 실행한다.
  2. ant 명령을 실행하여 빌드 프로세스를 시작한다.

요구 사항에 부합하는 환경이 마련되고 올바르게 설정되었다면 다음과 같은 내용을 볼 수 있다.

Buildfile: build.xml

init:

compile-common:

compile-module:
     [echo] Compiling ...

package-common:

package-swtlib:

sign-jars:
     [echo] Signing JARS...
  [signjar] Signing Jar : D:\FileViewer\dist\swt-lib.jar
  [signjar] Signing Jar : D:\FileViewer\dist\fileviewer.jar
     [copy] Copying 1 file to D:\FileViewer\dist
  [signjar] Signing Jar : D:\FileViewer\dist\swt-win32.jar

package-web:
      [war] Building war: D:\FileViewer\dist\fileviewer.war

default:

BUILD SUCCESSFUL
Total time: 6 seconds




위로


파일 뷰어 애플리케이션 실행하기

Java Web Start를 사용하여 파일 뷰어 애플리케이션을 전개하기 전에, 애플리케이션을 로컬에서 실행해 보자. 애플리케이션을 시작하려면 소스 코드의 압축을 풀었던 디렉토리에서 ant run을 실행한다.

Ant 스크립트를 실행하면 파일 뷰어 애플리케이션이 나타난다. 그림 2는 Red Hat Linux 8에서 실행되는 애플리케이션 모습이다.


그림 2. Red Hat Linux 8에서 실행되는 파일 뷰어
File viewer on Red Hat 8



위로


파일 뷰어 애플리케이션 전개 및 테스트

애플리케이션을 Tomcat 4에 전개하려면 다음과 같이 한다.

  1. Tomcat 4에서 dist 디렉토리에서 webapps 디렉토리로 fileviewer.war 파일을 복사한다.
  2. 스크립트를 실행하여 Tomcat 4를 시작한다.
  3. 웹 브라우저에서 http://localhost:8080/fileviewer/index.html로 들어가서 "Launch Application" 링크를 클릭한다.

    링크를 클릭하고, 애플리케이션의 JAR 파일이 워크스테이션으로 다운로드 되는 동안 다음과 같은 이미지를 볼 수 있다.(그림 3)



    그림 3. 파일 뷰어
    File viewer

  4. 애플리케이션이 처음 다운로드 되면, 다음과 같은 대화 창이 나타난다. (그림 4)

    그림 4. 보안 경고
    Security warning

    "Start"를 클릭하여 파일 뷰어 애플리케이션을 시작한다.




위로


JNLP 파일 구현하기

Sun의 Java Web Start를 사용하여 SWT 애플리케이션을 구현, 배포, 전개하는 방법을 알아보았다. 이제는 JNLP 파일을 구현하는 방법에 대해 알아보자. Java Network Launching Protocol 스팩은 Java Community Process (JCP)에서 관리된다. 이 글의 목적은 이 기술을 사용하여 SWT 애플리케이션을 전개하는 방법을 설명하는 것이기 때문에 그 외 배경 설명은 생략하도록 하겠다. Java Web Start에 대한 자세한 내용은 Steve Kim의 기술자료 "Java Web Start"를 참조하라. (참고자료)

Listing 1은 SWT 애플리케이션의 JNLP 파일에서 사용되는 다양한 태그들이다.


Listing 1. index.jnlp 파일
				
1  <?xmlversion="1.0" encoding="utf-8"?>
2     <jnlp spec="1.0+"codebase="http://localhost:8080/fileviewer"href="index.jnlp">
3         <information>
4                 <title>File Viewer</title>
5                 <vendor>IBM developerWorks</vendor>
6                 <homepage href="index.html"/>
7                 <description>File Viewer</description>
8                 <description kind="short">FileViewer</description>
9         </information>
10        <security>
11                 <all-permissions/>
12         </security>
13         <resources>
14                 <j2se version="1.4"/>
15                 <jar href="fileviewer.jar"/>
16                 <nativelib href="swt-lib.jar"/>
17         </resources>
18         <resources os="Windows"> 
19                 <jar href="swt-win32.jar"/>
20         </resources>
21         <resources os="Linux"> 
22                 <jar href="swt-linux.jar"/>
23         </resources>
24         <application-descmain-class="org.eclipse.swt.examples.fileviewer.FileViewer"/>
25 </jnlp>

이 XML 파일에서 중요한 부분을 살펴보도록 하자.

  1. SWT 애플리케이션은 실행하는 동안 시스템 라이브러리를 로딩해야 하므로, 사용자의 워크스테이션으로 완전히 액세스 해야 한다. 라인 10에서 12번은 애플리케이션이 클라이언트의 환경에 액세스를 요청하는 방법을 나타낸다. Java Web Start가 액세스 허용을 받으려면, 모든 애플리케이션의 JAR 파일들은 디지털 서명이 되어야 한다.
  2. 라인 16번에서 보듯, nativelib 태그를 선언하여 Java Web Start에게 이 JAR 파일에 원래의 라이브러리들이 포함되어 있음을 알려주어야 한다. 예제 파일 뷰어 애플리케이션에서, 이 JAR 파일에는 Windows DLL과 리눅스용 SO 파일 시리즈가 포함된다.
  3. 라인 23번은 각 OS에 대한 SWT JAR를 로딩하는 부분이다. "resources" 태그를 사용하여 특정 OS와 아키텍처에서만 사용될 리소스들을 보호할 수 있다. os 애트리뷰트는 리소스 엘리먼트가 관여할 OS를 지정하며, 해당 값은 엔드 유저의 os.name 자바 시스템 프로퍼티에 기반한다. 이 예제에서는 사용되지 않지만, 자바 라이브러리로 액세스를 제한할 때 arch 애트리뷰트를 사용할 수 있다. arch 애트리뷰트는 엔드 유저의 os.arch 자바 시스템 속성에 기반한다.

JNLP 파일의 다양한 엘리먼트와 포맷에 대한 정보는 참고자료 섹션을 참조하라.




위로


요약

SWT 사용자 인터페이스 툴킷과 Java Web Start가 결합하면 상호 작용하는 클라이언트 측 자바 애플리케이션을 전개하는 훌륭한 툴이 된다. 예제 파일 뷰어 애플리케이션은 Java Web Start를 통해 분산될 독립형 SWT 애플리케이션을 구현하는데 사용할 수 있는 빌드 및 패키징 프레임웍을 제공한다.

기사의 원문보기





위로


다운로드 하십시오

이름 크기 다운로드 방식
os-jws/fileviewer.zip  FTP
다운로드 방식에 대한 정보


참고자료


<출처: http://www.ibm.com/developerworks/kr/library/os-jws/>

반응형

[명사] 쓴 것이 다하면 단 것이 온다는 뜻으로, 고생 끝에 즐거움이 옴을 이르는 말.

쓰디쓴 데낄라를 입안에 머금고 달려온 인내
차가운 바람은 떠나는 나그네의 마음을 시리게 만들었지만..
떠난 이의 발걸음은 결국 떠나온 그 자리를 향하고
다시 돌아온 그 자리엔 와인의 달콤한 향기가...
신이 내린 서글픈 나그네의 선물.. 인내 하는 자에게 주어진 축복..
나그네의 종착역은 자신이 떠나온 자리 그리고 안식처.
그 곳이 바로 'Utopia'
달콤한 향기를 머금은 입가에 남은 미소..
반응형
JNI 콜백 메소드 만들때도 참조하시면 좋습니다.
 
원문: http://www.velocityreviews.com/forums/t360927-setwindowshookex-not-notifing-me-on-key-pressed-using-jni-and-c-dll.html
 
Here is a very simple yet complete working sample of a
low level Windows keyboard hook within a Swing application.
Please try it.

//
// FrameTest.java
//
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class FrameTest extends JFrame {
private JPanel mainPanel;
private JTextArea mainTextArea;
private HookTest hook;

public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
new FrameTest().setVisible(true);
}
});
}

FrameTest() {
super("FrameTest");
setSize(200, 200);
setDefaultCloseOperation(EXIT_ON_CLOSE);
mainPanel = new JPanel();
mainPanel.setLayout(new BorderLayout());
mainTextArea = new JTextArea();
mainPanel.add(mainTextArea, BorderLayout.CENTER);
getContentPane().add(mainPanel);
addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent event) {
hook.unRegisterHook();
}
});
new Thread() {
public void run() {
hook = new HookTest();
hook.registerHook();
}
}.start();
}
}

//
// HookTest.java
//
public class HookTest {
static {
System.loadLibrary("HookTest");
}

void processKey(int key, boolean pressed) {
System.out.println("Java: HookTest.processKey - key = " + key +
(pressed ? " pressed" : " released"));
}

native void registerHook();
native void unRegisterHook();
}

//
// HookTest.h
//
#ifndef _Included_HookTest
#define _Included_HookTest

#include <jni.h>

#ifdef __cplusplus
extern "C" {
#endif

JNIEXPORT void JNICALL Java_HookTest_registerHook(JNIEnv * env, jobject
obj);

JNIEXPORT void JNICALL Java_HookTest_unRegisterHook(JNIEnv * env,
jobject obj);

#ifdef __cplusplus
}
#endif

#endif /* _Included_HookTest */

//
// HookTest.cpp
//
#include <windows.h>
#include "HookTest.h"

HINSTANCE hInst = NULL;
JavaVM * jvm = NULL;
jobject hookObj = NULL;
jmethodID processKeyID = NULL;
DWORD hookThreadId = 0;

extern "C" BOOL APIENTRY DllMain(HINSTANCE _hInst, DWORD reason, LPVOID
reserved) {
switch (reason) {
case DLL_PROCESS_ATTACH:
printf("C++: DllMain - DLL_PROCESS_ATTACH.\n");
hInst = _hInst;
break;
default:
break;
}

return TRUE;
}

LRESULT CALLBACK LowLevelKeyboardProc(int nCode, WPARAM wParam, LPARAM
lParam) {
JNIEnv * env;
KBDLLHOOKSTRUCT * p = (KBDLLHOOKSTRUCT *)lParam;

if (jvm->AttachCurrentThread((void **)&env, NULL) >= 0) {
switch (wParam) {
case WM_KEYDOWN:
case WM_SYSKEYDOWN:
printf("C++: LowLevelKeyboardProc - Key pressed\n");
env->CallVoidMethod(hookObj, processKeyID, p->vkCode,
true);
break;
case WM_KEYUP:
case WM_SYSKEYUP:
printf("C++: LowLevelKeyboardProc - Key released\n");
env->CallVoidMethod(hookObj, processKeyID, p->vkCode,
false);
break;
default:
break;
}
}
else {
printf("C++: LowLevelKeyboardProc - Error on the attach current
thread.\n");
}

return CallNextHookEx(NULL, nCode, wParam, lParam);
}

void MsgLoop() {
MSG message;

while (GetMessage(&message, NULL, 0, 0)) {
TranslateMessage(&message);
DispatchMessage(&message);
}
}

JNIEXPORT void JNICALL Java_HookTest_registerHook(JNIEnv * env, jobject
obj) {
HHOOK hookHandle = SetWindowsHookEx(WH_KEYBOARD_LL,
LowLevelKeyboardProc, hInst, 0);

if (hookHandle == NULL) {
printf("C++: Java_HookTest_registerHook - Hook failed!\n");
return;
}
else {
printf("C++: Java_HookTest_registerHook - Hook successful\n");
}

hookObj = env->NewGlobalRef(obj);
jclass cls = env->GetObjectClass(hookObj);
processKeyID = env->GetMethodID(cls, "processKey", "(IZ)V");
env->GetJavaVM(&jvm);
hookThreadId = GetCurrentThreadId();

MsgLoop();

if (!UnhookWindowsHookEx(hookHandle))
printf("C++: Java_HookTest_registerHook - Unhook failed\n");

else
printf("C++: Java_HookTest_registerHook - Unhook
successful\n");
}

JNIEXPORT void JNICALL Java_HookTest_unRegisterHook(JNIEnv *env,
jobject object) {
if (hookThreadId == 0)
return;

printf("C++: Java_HookTest_unRegisterHook - call
PostThreadMessage.\n");
PostThreadMessage(hookThreadId, WM_QUIT, 0, 0L);
}


Regards
반응형

1. Project > Properties.

2. JRE System Library 의 앞 +를 클릭.

3. Native Library Folder Configuration을 클릭.

4. External Folder 나 Workspace를 선택하여 필요한 패스를 지정


반응형

웹으로 네이트온을 사용할수 있는 사이트

웹 Nateon 메신저 : http://www.sensguy.co.kr
웹 MSN 메신저 : http://webmessenger.msn.com/
사이트 차단해제 프로그램 : http://say2you.tistory.com/396

+ Recent posts