Main.java :  » Development » bluecove-2.1.0 » net » sf » bluecove » obex » Java Open Source

Java Open Source » Development » bluecove 2.1.0 
bluecove 2.1.0 » net » sf » bluecove » obex » Main.java
/**
 *  BlueCove - Java library for Bluetooth
 *  Copyright (C) 2006-2008 Vlad Skarzhevskyy
 * 
 *  Licensed to the Apache Software Foundation (ASF) under one
 *  or more contributor license agreements.  See the NOTICE file
 *  distributed with this work for additional information
 *  regarding copyright ownership.  The ASF licenses this file
 *  to you under the Apache License, Version 2.0 (the
 *  "License"); you may not use this file except in compliance
 *  with the License.  You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing,
 *  software distributed under the License is distributed on an
 *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 *  KIND, either express or implied.  See the License for the
 *  specific language governing permissions and limitations
 *  under the License.
 *
 *  @author vlads
 *  @version $Id: Main.java 2471 2008-12-01 03:44:20Z skarzhevskyy $
 */
package net.sf.bluecove.obex;

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Image;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.net.URL;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
import java.util.Vector;

import javax.bluetooth.LocalDevice;
import javax.bluetooth.RemoteDevice;
import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
import javax.swing.border.EmptyBorder;

/**
 * 
 */
public class Main extends JFrame implements ActionListener, UserInteraction {

  private static final long serialVersionUID = 1L;

  private static final int BLUETOOTH_DISCOVERY_STD_SEC = 11;

  private JLabel iconLabel;

  private String status;

  JProgressBar progressBar;

  private ImageIcon btIcon;

  private ImageIcon transferIcon;

  private ImageIcon searchIcon;

  private ImageIcon downloadIcon;

  private JComboBox cbDevices;

  private JButton btFindDevice;

  private JButton btSend;

  private JButton btCancel;

  private BluetoothInquirer bluetoothInquirer;

  private Hashtable devices = new Hashtable();

  private JFileChooser fileChooser;

  private String fileName;

  private byte[] data;

  private List queue = new Vector();

  protected Main() {
    super("BlueCove OBEX Push");
    this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

    Image btImage = Toolkit.getDefaultToolkit().getImage(Main.class.getResource("/icon.png"));
    btIcon = new ImageIcon(btImage);
    transferIcon = new ImageIcon((Toolkit.getDefaultToolkit().getImage(Main.class.getResource("/transfer.png"))));
    searchIcon = new ImageIcon((Toolkit.getDefaultToolkit().getImage(Main.class.getResource("/search.png"))));
    downloadIcon = new ImageIcon((Toolkit.getDefaultToolkit().getImage(Main.class.getResource("/download.png"))));

    this.setIconImage(btImage);

    JPanel contentPane = (JPanel) this.getContentPane();
    contentPane.setLayout(new BorderLayout(10, 10));
    contentPane.setBorder(new EmptyBorder(10, 10, 10, 10));
    contentPane.setTransferHandler(new DropTransferHandler(this));

    contentPane.addMouseListener(new MouseDoubleClickListener());

    JPanel progressPanel = new JPanel();
    progressPanel.setLayout(new GridBagLayout());
    GridBagConstraints c = new GridBagConstraints();

    iconLabel = new JLabel();
    iconLabel.setIcon(btIcon);
    c.fill = GridBagConstraints.BOTH;
    c.weightx = 1.0;
    progressPanel.add(iconLabel, c);

    progressBar = new JProgressBar(0, 100);
    progressBar.setValue(0);
    progressBar.setStringPainted(true);

    c.fill = GridBagConstraints.HORIZONTAL;
    c.gridwidth = GridBagConstraints.REMAINDER;
    progressPanel.add(progressBar, c);

    getContentPane().add(progressPanel, BorderLayout.NORTH);

    JPanel optionsPanel = new JPanel();

    JLabel deviceLabel = new JLabel("Send to:");
    optionsPanel.add(deviceLabel);
    cbDevices = new JComboBox();
    cbDevices.addItem("{no device found}");
    cbDevices.setEnabled(false);
    optionsPanel.add(cbDevices);
    optionsPanel.add(btFindDevice = new JButton("Find"));
    btFindDevice.addActionListener(this);

    getContentPane().add(optionsPanel, BorderLayout.CENTER);

    JPanel actionPanel = new JPanel();
    actionPanel.setLayout(new BoxLayout(actionPanel, BoxLayout.LINE_AXIS));
    actionPanel.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 5));
    actionPanel.add(Box.createHorizontalGlue());
    actionPanel.add(btSend = new JButton("Send"));
    btSend.addActionListener(this);
    actionPanel.add(Box.createRigidArea(new Dimension(10, 0)));
    actionPanel.add(btCancel = new JButton("Cancel"));
    btCancel.addActionListener(this);

    contentPane.add(actionPanel, BorderLayout.SOUTH);
    btSend.setEnabled(false);
    String selected = Persistence.loadDevices(devices);
    updateDevices(selected);
  }

  private static void createAndShowGUI(final String[] args) {
    final Main app = new Main();
    app.pack();
    app.center();
    app.setVisible(true);
    SwingUtilities.invokeLater(new Runnable() {
      public void run() {
        if (app.initializeBlueCove()) {
          if (args.length != 0) {
            app.downloadFile(args[0]);
          }
        }
      }
    });
  }

  public static void main(final String[] args) {
    SwingUtilities.invokeLater(new Runnable() {
      public void run() {
        createAndShowGUI(args);
      }
    });
  }

  private void center() {
    Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
    this.setLocation(((screenSize.width - this.getWidth()) / 2), ((screenSize.height - this.getHeight()) / 2));
  }

  public void showStatus(final String message) {
    setStatus(message);
  }

  protected void setStatus(final String message) {
    status = message;
    progressBar.setString(message);
  }

  public void setProgressMaximum(int n) {
    progressBar.setMaximum(n);
  }

  public void setProgressValue(int n) {
    progressBar.setValue(n);
    SwingUtilities.invokeLater(new Runnable() {
      public void run() {
        progressBar.setString(status);
      }
    });
  }

  public void setProgressDone() {
    progressBar.setValue(0);
  }

  protected void disabledBluetooth() {
    btFindDevice.setEnabled(false);
    cbDevices.setEnabled(false);
    setStatus("BlueCove not avalable");
    btSend.setEnabled(false);
    iconLabel.setIcon(new ImageIcon((Toolkit.getDefaultToolkit().getImage(Main.class.getResource("/bt-off.png")))));
  }

  protected boolean initializeBlueCove() {
    try {
      LocalDevice localDevice = LocalDevice.getLocalDevice();
      if ("000000000000".equals(localDevice.getBluetoothAddress())) {
        throw new Exception();
      }
      bluetoothInquirer = new BluetoothInquirer(this);
      setStatus("BlueCove Ready");
      return true;
    } catch (Throwable e) {
      Logger.error(e);
      disabledBluetooth();
      return false;
    }
  }

  public void actionPerformed(ActionEvent e) {
    if (e.getSource() == btFindDevice) {
      bluetoothDiscovery();
    } else if (e.getSource() == btCancel) {
      shutdown();
      System.exit(0);
    } else if (e.getSource() == btSend) {
      obexSend();
    }
  }

  private class MouseDoubleClickListener implements MouseListener {

    private long firstClick = 0;

    public void mouseClicked(MouseEvent e) {
      long now = System.currentTimeMillis();
      if ((firstClick != 0) && (firstClick - now < 1000)) {
        fireDoubleClick();
      } else {
        firstClick = now;
      }

    }

    public void mouseEntered(MouseEvent e) {
      firstClick = 0;
    }

    public void mouseExited(MouseEvent e) {
      firstClick = 0;
    }

    public void mousePressed(MouseEvent e) {
    }

    public void mouseReleased(MouseEvent e) {
    }

  }

  public void fireDoubleClick() {
    if (fileChooser == null) {
      fileChooser = new JFileChooser();
      fileChooser.setDialogTitle("Select File to send...");
      fileChooser.setCurrentDirectory(new File(Persistence.getProperty("recentDirectory", ".")));
    }
    int returnVal = fileChooser.showOpenDialog(Main.this);
    if (returnVal == JFileChooser.APPROVE_OPTION) {
      Persistence.setProperty("recentDirectory", fileChooser.getCurrentDirectory().getAbsolutePath());
      downloadFile(DropTransferHandler.getCanonicalFileURL(fileChooser.getSelectedFile()));
      saveConfig();
    }

  }

  private void selectNextFile() {
    if (queue.size() > 0) {
      String url = (String) queue.remove(0);
      downloadFile(url);
    }
  }

  public void queueFile(String url) {
    queue.add(url);
  }

  private void saveConfig() {
    Persistence.storeDevices(devices, getSelectedDeviceAddress());
  }

  private class DiscoveryTimerListener implements ActionListener {
    int seconds = 0;

    public void actionPerformed(ActionEvent e) {
      if (seconds < BLUETOOTH_DISCOVERY_STD_SEC) {
        seconds++;
        setProgressValue(seconds);
      }
    }
  }

  private void addDevice(String btAddress, String name, String obexUrl) {
    String key = btAddress.toLowerCase();
    DeviceInfo di = (DeviceInfo) devices.get(key);
    if (di == null) {
      di = new DeviceInfo();
    }
    di.btAddress = btAddress;
    // Update name if one found
    if (di.name == null) {
      di.name = name;
    } else if (btAddress.equals(di.name)) {
      di.name = name;
    }
    di.obexUrl = obexUrl;
    di.obexServiceFound = true;
    devices.put(key, di);
  }

  private void updateDevices(String selected) {
    cbDevices.removeAllItems();
    if (devices.size() == 0) {
      cbDevices.addItem("{no device found}");
      btSend.setEnabled(false);
      cbDevices.setEnabled(false);
    } else {
      for (Enumeration i = devices.keys(); i.hasMoreElements();) {
        String addr = (String) i.nextElement();
        DeviceInfo di = (DeviceInfo) devices.get(addr);
        cbDevices.addItem(di);
        if ((selected != null) && (selected.equals(di.btAddress))) {
          cbDevices.setSelectedItem(di);
        }
      }
      cbDevices.setEnabled(true);
      btSend.setEnabled(true);
    }
  }

  private void bluetoothDiscovery() {
    final Timer timer = new Timer(1000, new DiscoveryTimerListener());
    progressBar.setMaximum(BLUETOOTH_DISCOVERY_STD_SEC);
    setProgressValue(0);
    Thread t = new Thread() {
      public void run() {
        if (bluetoothInquirer.startInquiry()) {
          iconLabel.setIcon(searchIcon);
          setStatus("Bluetooth discovery started");
          btFindDevice.setEnabled(false);
          btSend.setEnabled(false);
          timer.start();
          while (bluetoothInquirer.inquiring) {
            try {
              Thread.sleep(1000);
            } catch (Exception e) {
            }
          }
          timer.stop();
          // setStatus("Bluetooth discovery finished");

          setProgressValue(0);
          int idx = 0;
          progressBar.setMaximum(bluetoothInquirer.devices.size());
          for (Iterator iter = bluetoothInquirer.devices.iterator(); iter.hasNext();) {
            RemoteDevice dev = (RemoteDevice) iter.next();
            String obexUrl = bluetoothInquirer.findOBEX(dev.getBluetoothAddress());
            if (obexUrl != null) {
              Logger.debug("found obex url", obexUrl);
              addDevice(dev.getBluetoothAddress(), BluetoothInquirer.getFriendlyName(dev), obexUrl);
            }
            idx++;
            setProgressValue(idx);
          }
          setProgressValue(0);
          saveConfig();
          updateDevices(null);
          btFindDevice.setEnabled(true);
          btSend.setEnabled(true);
          iconLabel.setIcon(btIcon);
        }
      }
    };
    t.start();
  }

  private String blueSoleilFindOBEX(String btAddress, String obexUrl) {
    if ("bluesoleil".equals(LocalDevice.getProperty("bluecove.stack"))) {
      RemoteDevice dev = new RemoteDeviceExt(btAddress);
      String foundObexUrl = bluetoothInquirer.findOBEX(dev.getBluetoothAddress());
      if (foundObexUrl != null) {
        Logger.debug("found", btAddress);
        addDevice(dev.getBluetoothAddress(), BluetoothInquirer.getFriendlyName(dev), foundObexUrl);
      }
      return foundObexUrl;
    }
    return obexUrl;
  }

  private DeviceInfo getSelectedDevice() {
    Object o = cbDevices.getSelectedItem();
    if ((o == null) || !(o instanceof DeviceInfo)) {
      return null;
    }
    return (DeviceInfo) o;
  }

  private String getSelectedDeviceAddress() {
    DeviceInfo d = getSelectedDevice();
    if (d == null) {
      return null;
    }
    return d.btAddress;
  }

  private void obexSend() {
    if (fileName == null) {
      setStatus("No file selected");
      return;
    }
    final DeviceInfo d = getSelectedDevice();
    if (d == null) {
      setStatus("No Device selected");
      return;
    }
    final ObexBluetoothClient o = new ObexBluetoothClient(this, fileName, data);
    Thread t = new Thread() {
      public void run() {
        btSend.setEnabled(false);
        iconLabel.setIcon(transferIcon);
        String obexUrl = d.obexUrl;
        if (!d.obexServiceFound) {
          obexUrl = blueSoleilFindOBEX(d.btAddress, obexUrl);
        }
        if (obexUrl != null) {
          if (o.obexPut(obexUrl)) {
            selectNextFile();
          }
        } else {
          setStatus("Service not found");
        }
        btSend.setEnabled(true);
        iconLabel.setIcon(btIcon);
        saveConfig();
      }

    };
    t.start();
  }

  private static String simpleFileName(String filePath) {
    int idx = filePath.lastIndexOf('/');
    if (idx == -1) {
      idx = filePath.lastIndexOf('\\');
    }
    if (idx == -1) {
      return filePath;
    }
    return filePath.substring(idx + 1);
  }

  void downloadFile(final String filePath) {
    Thread t = new Thread() {
      public void run() {
        InputStream is = null;
        try {
          iconLabel.setIcon(downloadIcon);
          String path = filePath;
          String inputFileName;
          File file = new File(filePath);
          if (file.exists()) {
            is = new FileInputStream(file);
            inputFileName = file.getName();
          } else {
            URL url = new URL(path);
            is = url.openConnection().getInputStream();
            inputFileName = url.getFile();
          }
          ByteArrayOutputStream bos = new ByteArrayOutputStream();
          byte[] buffer = new byte[0xFF];
          int i = is.read(buffer);
          int done = 0;
          while (i != -1) {
            bos.write(buffer, 0, i);
            done += i;
            // setProgressValue(done);
            i = is.read(buffer);
          }
          data = bos.toByteArray();
          fileName = simpleFileName(inputFileName);
          setStatus((data.length / 1024) + "k " + fileName);
        } catch (Throwable e) {
          Logger.error(e);
          setStatus("Download error " + e.getMessage());
        } finally {
          IOUtils.closeQuietly(is);
          iconLabel.setIcon(btIcon);
        }
      }
    };
    t.start();

  }

  private void shutdown() {
    if (bluetoothInquirer != null) {
      bluetoothInquirer.shutdown();
      bluetoothInquirer = null;
    }
  }
}
java2s.com  | Contact Us | Privacy Policy
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.