Package purejavacomm

Source Code of purejavacomm.CommPortIdentifier

/*
* Copyright (c) 2011, Kustaa Nyholm / SpareTimeLabs
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this list
* of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice, this
* list of conditions and the following disclaimer in the documentation and/or other
* materials provided with the distribution.
* Neither the name of the Kustaa Nyholm or SpareTimeLabs nor the names of its
* contributors may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*/

package purejavacomm;

// FIXME no mechanism to warn about duplicate port names
import static jtermios.JTermios.*;

import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;

import jtermios.Termios;

public class CommPortIdentifier {
  public static final int PORT_SERIAL = 1;
  public static final int PORT_PARALLEL = 2;
  private static volatile Object m_Mutex = new Object();
  private volatile String m_PortName;
  private volatile int m_PortType;
  private volatile CommDriver m_Driver;

  private volatile static Hashtable<String, CommPortIdentifier> m_PortIdentifiers = new Hashtable<String, CommPortIdentifier>();
  private volatile static Hashtable<CommPort, CommPortIdentifier> m_OpenPorts = new Hashtable<CommPort, CommPortIdentifier>();
  private volatile static Hashtable<CommPortIdentifier, String> m_Owners = new Hashtable<CommPortIdentifier, String>();
  private volatile Hashtable<CommPortIdentifier, List<CommPortOwnershipListener>> m_OwnerShipListeners = new Hashtable<CommPortIdentifier, List<CommPortOwnershipListener>>();

  @Override
  public boolean equals(Object x) {
    return (x instanceof CommPortIdentifier) && m_PortName.equals(((CommPortIdentifier) x).m_PortName);
  }

  @Override
  public int hashCode() {
    return m_PortName.hashCode();
  }

  /**
   * This has not been tested at all
   */
  public static void addPortName(String portName, int portType, CommDriver driver) {
    synchronized (m_Mutex) {
      m_PortIdentifiers.put(portName, new CommPortIdentifier(portName, portType, driver));
    }
  }

  private CommPortIdentifier(String name, int portType, CommDriver driver) {
    m_PortName = name;
    m_PortType = portType;
    m_Driver = driver;
  }

  public static CommPortIdentifier getPortIdentifier(String portName) throws NoSuchPortException {
    synchronized (m_Mutex) {
      boolean ENUMERATE = false;
      for (CommPortIdentifier portid : m_OpenPorts.values())
        if (portid.getName().equals(portName))
          return portid;
      if (ENUMERATE) { // enumerating ports takes time, lets see if we can avoid it
        Enumeration e = getPortIdentifiers();
        while (e.hasMoreElements()) {
          CommPortIdentifier portid = (CommPortIdentifier) e.nextElement();
          if (portid.getName().equals(portName))
            return portid;
        }
      } else {
        CommPortIdentifier portid = m_PortIdentifiers.get(portName);
        if (portid != null)
          return portid;

        // check if we can open a port with the given name
        int fd = jtermios.JTermios.open(portName, O_RDWR | O_NOCTTY | O_NONBLOCK);
        if (fd != -1) {
          // yep, it exists, now check to see if it's really a serial
          // port
          if (tcgetattr(fd, new Termios()) != -1 || errno() != ENOTTY) {
            jtermios.JTermios.close(fd);
            return new CommPortIdentifier(portName, PORT_SERIAL,
                null);
          } else {
            // Not a serial port, or we can't access it
            jtermios.JTermios.close(fd);
          }
        } else if (errno() != ENOENT) {
          // exists but couldn't open. cannot throw anything here, so
          // return a port for it. Might not be a TTY after all, but
          // no way to check that without opening it
          return new CommPortIdentifier(portName, PORT_SERIAL, null);
        }
      }
      throw new NoSuchPortException();
    }
  }

  public static CommPortIdentifier getPortIdentifier(CommPort port) throws NoSuchPortException {
    synchronized (m_Mutex) {
      CommPortIdentifier portid = m_OpenPorts.get(port);
      if (portid == null)
        throw new NoSuchPortException();
      return portid;
    }
  }

  public CommPort open(String appname, int timeout) throws PortInUseException {
    synchronized (m_Mutex) {
      long t0 = System.currentTimeMillis();

      String owner = m_Owners.get(this);
      if (owner != null) {
        fireOwnershipEvent(CommPortOwnershipListener.PORT_OWNERSHIP_REQUESTED);
        try {
          while (System.currentTimeMillis() - t0 < timeout) {
            m_Mutex.wait(5);
            if (!isCurrentlyOwned())
              break;
          }
        } catch (InterruptedException ie) {
          // can't throw it, can't swallow it, try to propagate it
          Thread.currentThread().interrupt();
        }
      }
      if (isCurrentlyOwned())
        throw new PortInUseException();

      CommPortIdentifier info = m_PortIdentifiers.get(m_PortName);
      CommPort port;
      if (info != null)
        port = info.m_Driver.getCommPort(m_PortName, info.m_PortType);
      else
        port = new PureJavaSerialPort(m_PortName, timeout); // FIXME timeout here is not used
      m_OpenPorts.put(port, this);
      m_Owners.put(this, appname);
      fireOwnershipEvent(CommPortOwnershipListener.PORT_OWNED);
      return port;
    }
  }

  /* package */
  static void close(CommPort port) {
    synchronized (m_Mutex) {
      CommPortIdentifier portid = m_OpenPorts.remove(port);
      if (portid != null) {
        portid.fireOwnershipEvent(CommPortOwnershipListener.PORT_UNOWNED);
        m_Owners.remove(portid);
      }
    }
  }

  public CommPort open(java.io.FileDescriptor fd) throws UnsupportedCommOperationException {
    throw new UnsupportedCommOperationException("open from file descriptor not supported");
  }

  public String getName() {
    return m_PortName;
  }

  public int getPortType() {
    return m_PortType;
  }

  public static Enumeration getPortIdentifiers() {
    synchronized (m_Mutex) {

      return new Enumeration() {
        List<CommPortIdentifier> m_PortIDs;
        { // insert the  'addPortName' ports to the dynamic port list
          m_PortIDs = new LinkedList<CommPortIdentifier>();
          for (CommPortIdentifier portid : m_PortIdentifiers.values())
            m_PortIDs.add(portid);
          // and now add the PureSerialPorts
          List<String> pureports = getPortList();
          if (pureports != null)
            for (String name : pureports)
              m_PortIDs.add(new CommPortIdentifier(name, PORT_SERIAL, null));
        }
        Iterator<CommPortIdentifier> m_Iterator = m_PortIDs.iterator();

        public boolean hasMoreElements() {
          return m_Iterator != null ? m_Iterator.hasNext() : false;
        }

        public Object nextElement() {
          return m_Iterator.next();
        };
      };
    }
  }

  public String getCurrentOwner() {
    synchronized (m_Mutex) {
      return m_Owners.get(this);
    }
  }

  public boolean isCurrentlyOwned() {
    return getCurrentOwner() != null;
  }

  public void addPortOwnershipListener(CommPortOwnershipListener listener) {
    synchronized (m_Mutex) {
      List<CommPortOwnershipListener> list = m_OwnerShipListeners.get(this);
      if (list == null) {
        list = new LinkedList<CommPortOwnershipListener>();
        m_OwnerShipListeners.put(this, list);
      }
      list.add(listener);
    }
  }

  public void removePortOwnershipListener(CommPortOwnershipListener listener) {
    synchronized (m_Mutex) {
      List<CommPortOwnershipListener> list = m_OwnerShipListeners.get(this);
      if (list == null)
        return;
      list.remove(listener);
      if (list.isEmpty())
        m_OwnerShipListeners.remove(this);

    }
  }

  private void fireOwnershipEvent(int type) {
    synchronized (m_Mutex) {
      List<CommPortOwnershipListener> list = m_OwnerShipListeners.get(this);
      if (list == null)
        return;
      for (CommPortOwnershipListener listener : list)
        listener.ownershipChange(type);
    }
  }
}
TOP

Related Classes of purejavacomm.CommPortIdentifier

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.