요즘 애플릿에 대한 논의가 많지는 않으나 J2SE 1.4에서는 java.applet 패키지의 AppletContext 클래스에 세 가지 메소드가 추가되었다. 많은 사람들이 추가된 사실을 알아채지 못할 수도 있지만, 이 메소드들은 유용한 기능을 제공한다. 즉, 데이터를 스트림에 저장하고 각 스트림을 지정된 키(named key)에 매핑하는 것이다.

정보 저장을 위한 메인 메소드는 setStream()이다.
   public void setStream(String name, InputStream stream)
스트림은 저장 시 키값 (Map과 유사한) 구조의 키에 연결되고, 매핑은 애플릿의 코드베이스에 한정된다. 이 말은 하나의 호스트에서 나온 애플릿이 다른 호스트의 스트림에 액세스하지 못한다는 것을 의미한다.

스트림이 저장된 후에는 싱글 스트림 또는 스트림 전체를 이용하여 이를 검색할 수 있다. 싱글 스트림을 얻으려면 getStream() 메소드를 이용하여 이름별로 요청을 한다.
   public InputStream getStream(String name)
getStreamKeys() 메소드를 이용하여 모든 스트림을 검색하는데, 이 작업을 수행할 때는 Map으로 돌아가지 않는다. 대신, 다음과 같은 String 이름의 Iterator를 얻는다.
   public Iterator getStreamKeys()
사용자가 원하는 특정 스트림의 키 이름을 얻은 후에는 getStream() 메소드를 이용하여 해당 스트림을 얻는다. 이 때, 일반적으로 사용되는 패턴은 다음과 같다.
   Iterator iter = getAppletContext().getStreamKeys();
   if (iter != null) {
     while (iter.hasNext()) {
       String name = iter.next();
       InputStream stream = getAppletContext().getStream(name);
       // read stream...
     }
   }
이들이 인풋 스트림이라는 점을 유념할 것. 문자로 작업하고자 하는 경우에는 반드시 문자 세트를 이용해야 한다. 예를 들어 String 오브젝트를 저장하려면 바이트를 얻어 AppletContext 내의 ByteArrayInputStream에 저장한다.
   String message = ...;
   ByteArrayInputStream bais =
     new ByteArrayInputStream(message.getBytes("UTF-8"));
   getAppletContext().setStream("key-name", bais);   
이 오브젝트를 읽으려면 스트림을 얻어 이를 InputStreamReader로 변환할 때 동일 문자 세트를 전달한다. Reader 오브젝트를 얻은 후에는 다음 예제처럼 문자를 읽을 수 있다.
   InputStream stream = 
     getAppletContext().getStream("key-name");
   InputStreamReader isr = 
     new InputStreamReader(stream, "UTF-8");
   BufferedReader reader = new BufferedReader(isr);
   String line = reader.readLine();
API는 사실상 이것이 전부라 할 수 있다. 'setStream() 메소드를 이용하여 새로운 스트림을 저장하고, getStream()을 이용하여 스트림을 되돌린다. getStreamKeys()를 이용하여 스트림 키 세트를 얻는다. ' 이것이 스트림에 관해 알아 두어야 할 전부인 것처럼 보일지 모르지만, 그렇다면 스트림 컨텐츠를 제거하려면 어떻게 해야 할까? 그 답은 다음과 같다. 특정 키와 연결된 InputStream으로 null을 전달한다. 이렇게 하면 스트림의 컨텐츠가 시스템에서 제거된다.
   getAppletContext().setStream("key-name", null);
이번에는 API의 데모를 살펴보기로 하자. 먼저, 프로그램 로더인 HTML 파일을 생성해야 한다. 200x200의 디스플레이 면적을 필요로 하는 StreamsApplet으로 명명된 애플릿의 경우, HTML 파일에는 다음과 같은 애플릿 태그가 포함되어야 한다.
   <applet code=StreamsApplet width=200 height=200>
   </applet>
StreamsApplet 애플릿은 키값 쌍을 위해 2개의 텍스트 필드를 제공하는데, 이 때 키는 lookup name이며 값은 저장될 InputStream 컨텐츠이다. 아울러 애플릿은 2개의 버튼을 디스플레이한다. 첫 번째 버튼은 명명된 스트림을 추가하고(또는 기존의 것을 업데이트한다), 두 번째 버튼은 명명된 스트림을 제거한다. 애플릿은 JList에 현재의 이름 세트를 표시한다.

Streams Demo


다음은 사용자 인터페이스 생성에 사용되는 코드이다.
   import javax.swing.*;
   import javax.swing.event.*;
   import java.awt.*;
   import java.awt.event.*;
   import java.io.*;
   import java.util.*;

   public class StreamsApplet extends JApplet {
      private static final String CHARSET = "UTF-8";
      JButton add;
      JButton remove;
      JList list;
      JTextField key;
      JTextField value;

      public void init() {
        JLabel keyLabel = new JLabel("Key");
        keyLabel.setDisplayedMnemonic('K');
        key = new JTextField();
        keyLabel.setLabelFor(key);
        JLabel valueLabel = new JLabel("Value");
        valueLabel.setDisplayedMnemonic('V');
        value = new JTextField();
        valueLabel.setLabelFor(value);
        JPanel topPanel = new JPanel(new GridLayout(2,2));
        topPanel.add(keyLabel);
        topPanel.add(key);
        topPanel.add(valueLabel);
        topPanel.add(value);
        add(topPanel, BorderLayout.NORTH);

        list = new JList();
        list.setSelectionMode
          (ListSelectionModel.SINGLE_SELECTION);
        JScrollPane pane = new JScrollPane(list);
        add(pane, BorderLayout.CENTER);

        add = new JButton("Add/Update");
        add.setDisplayedMnemonic('A');
        remove = new JButton("Remove");
        remove.setDisplayedMnemonic('R');
        JPanel bottomPanel = new JPanel();
        bottomPanel.add(add);
        bottomPanel.add(remove);
        add(bottomPanel, BorderLayout.SOUTH);
      }
   }
이제 스트림 추가와 업데이트를 위한 액션을 추가해 보자. Add/Update 버튼 뒤의 ActionListener는 각각의 텍스트 필드에서 이름과 스트림 컨텐츠를 획득한 다음 이를 AppletContext에 저장해야 한다. 스트림을 추가한 후에는 JList에 스트림 목록이 표시되고 ActionListener가 텍스트 필드를 소거해야 한다.
   String keyText = key.getText();
   String valueText = value.getText();
   try {
       ByteArrayInputStream bais =
         new ByteArrayInputStream(valueText.getBytes(CHARSET));
       getAppletContext().setStream(keyText, bais);
   } catch (IOException ioe) {
     JOptionPane.showMessageDialog(StreamsApplet.this,
       "Unable to save", "Error", JOptionPane.ERROR_MESSAGE);
   }
   updateList();
   key.setText("");
   value.setText("");
updateList() 메소드는 상당히 간단한데, 단순히 이름 목록을 얻어 이를 JList에 넣기만 하면 된다.

   DefaultListModel model = new DefaultListModel();
   Iterator<String> iter = getAppletContext().getStreamKeys();
   if (iter != null) {
     while (iter.hasNext()) {
       model.addElement(iter.next());
     }
   }
   list.setModel(model);
Remove 버튼 뒤의 ActionListener는 키 텍스트 필드의 모든 이름에 대해 단순히 스트림을 null로 설정한다. 이 경우에도 제거 후에 이름 목록을 업데이트하고 텍스트 필드를 소거해야 한다.

   String keyText = key.getText();
   try {
     getAppletContext().setStream(keyText, null);
   } catch (IOException ioe) {
     JOptionPane.showMessageDialog(StreamsApplet.this,
       "Unable to clear", "Error", JOptionPane.ERROR_MESSAGE);
   }
   updateList();
   key.setText("");
   value.setText("");
이것으로 작업이 모두 완료된 것은 아니다. 목록에서 이름을 선택하면 현재의 값이 표시되는데, 이 작업은 ListSelectionListener를 통해 이루어진다. 리스너는 JList에서 선택된 값을 획득한 다음 애플릿 컨텍스트에서 스트림을 룩업한다. 이름을 찾을 수 없으면 getStream() 메소드는 null을 리턴한다. 단, JList에는 스트림과 일치하는 이름만 포함되므로 확인 작업이 필요하지는 않다.
   String selection = (String)list.getSelectedValue();
   try {
     InputStream stream = 
       getAppletContext().getStream(selection);
     InputStreamReader isr = 
       new InputStreamReader(stream, CHARSET);
     BufferedReader reader = new BufferedReader(isr);
     String line = reader.readLine();
     key.setText(selection);
     value.setText(line);
   } catch (IOException ioe) {
     JOptionPane.showMessageDialog(StreamsApplet.this,
       "Unable to read", "Error", JOptionPane.ERROR_MESSAGE);
   }
이것을 모두 합치면 애플릿 컨텍스트에 명명된 스트림을 저장할 완벽한 애플릿이 구현된다. 다음은 모든 리스너를 각각의 해당 컴포넌트에 첨부하기 위한 소스의 전체 내용이다.
   import javax.swing.*;
   import javax.swing.event.*;
   import java.awt.*;
   import java.awt.event.*;
   import java.io.*;
   import java.util.*;

   public class StreamsApplet extends JApplet {
      private static final String CHARSET = "UTF-8";
      JButton add;
      JButton remove;
      JList list;
      JTextField key;
      JTextField value;

      public void init() {
        JLabel keyLabel = new JLabel("Key");
        keyLabel.setDisplayedMnemonic('K');
        key = new JTextField();
        keyLabel.setLabelFor(key);
        JLabel valueLabel = new JLabel("Value");
        valueLabel.setDisplayedMnemonic('V');
        value = new JTextField();
        valueLabel.setLabelFor(value);
        JPanel topPanel = new JPanel(new GridLayout(2,2));
        topPanel.add(keyLabel);
        topPanel.add(key);
        topPanel.add(valueLabel);
        topPanel.add(value);
        add(topPanel, BorderLayout.NORTH);

        list = new JList();
        list.setSelectionMode(
          ListSelectionModel.SINGLE_SELECTION);
        JScrollPane pane = new JScrollPane(list);
        add(pane, BorderLayout.CENTER);

        add = new JButton("Add/Update");
        add.setMnemonic('A');
        remove = new JButton("Remove");
        remove.setMnemonic('R');
        JPanel bottomPanel = new JPanel();
        bottomPanel.add(add);
        bottomPanel.add(remove);
        add(bottomPanel, BorderLayout.SOUTH);

        ActionListener addListener = new ActionListener() {
          public void actionPerformed(ActionEvent e) {
            String keyText = key.getText();
            String valueText = value.getText();
            try {
                ByteArrayInputStream bais =
                  new ByteArrayInputStream(
                    valueText.getBytes(CHARSET));
                getAppletContext().setStream(keyText, bais);
            } catch (IOException ioe) {
              JOptionPane.showMessageDialog(StreamsApplet.this,
                "Unable to save", "Error", 
                JOptionPane.ERROR_MESSAGE);
            }
            updateList();
            key.setText("");
            value.setText("");
          }
        };

        add.addActionListener(addListener);

        ActionListener removeListener = new ActionListener() {
          public void actionPerformed(ActionEvent e) {
            String keyText = key.getText();
            try {
              getAppletContext().setStream(keyText, null);
            } catch (IOException ioe) {
              JOptionPane.showMessageDialog(StreamsApplet.this,
                "Unable to clear", "Error", 
                JOptionPane.ERROR_MESSAGE);
            }
            updateList();
            key.setText("");
            value.setText("");
          }
        };

        remove.addActionListener(removeListener);

        ListSelectionListener selectListener = 
          new ListSelectionListener() {
           public void valueChanged(ListSelectionEvent e) {
            String selection = (String)list.getSelectedValue();
            try {
              InputStream stream = 
                getAppletContext().getStream(selection);
              InputStreamReader isr = 
                new InputStreamReader(stream, CHARSET);
              BufferedReader reader = new BufferedReader(isr);
              String line = reader.readLine();
              key.setText(selection);
              value.setText(line);
            } catch (IOException ioe) {
              JOptionPane.showMessageDialog(StreamsApplet.this,
                "Unable to read", "Error", 
                JOptionPane.ERROR_MESSAGE);
            }
          }
        };
        list.addListSelectionListener(selectListener);

        updateList();
      }

      private void updateList() {
        DefaultListModel model = new DefaultListModel();
        Iterator<String> iter = 
          getAppletContext().getStreamKeys();
        if (iter != null) {
          while (iter.hasNext()) {
            model.addElement(iter.next());
          }
        }
        list.setModel(model);
      }
   }
Java 플러그인 기술 덕분에, 대부분의 데스크톱에서도 애플릿을 브라우저에서 실행할 수 있게 되었다. 최신 자바 소프트웨어를 확인하고 새로운 애플릿을 시험해보고 싶다면 java.com을 방문하기 바란다.

"Java SE" 카테고리의 다른 글

2006/04/21 09:45 2006/04/21 09:45

TRACKBACK :: http://blog.sdnkorea.com/blog/trackback/163

댓글을 달아 주세요

  1. 김형국  수정/삭제  댓글쓰기

    재밋는 자료인것같습니다. 나중에 응용된 먼가를 만들면 유용할꺼같네요...

    2007/09/18 10:16
  2. 박정숙  수정/삭제  댓글쓰기

    좋은 정보 감사해요~

    2007/09/19 04:41
[로그인][오픈아이디란?]

◀ Prev 1  ... 412 413 414 415 416 417 418 419 420  ... 626  Next ▶