// jTDS JDBC Driver for Microsoft SQL Server and Sybase // Copyright (C) 2004 The jTDS Project // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2.1 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // package net.sourceforge.jtds.jdbc; import java.io.*; import java.net.NetworkInterface; import java.net.SocketException; import java.util.Enumeration; /** * This class implements inter-process communication (IPC) to the database * server using local named pipes (will only work on Windows). * * @author Adam Etheredge * @version $Id: SharedLocalNamedPipe.java,v 1.12 2007-07-08 21:38:13 bheineman Exp $ */ public class SharedLocalNamedPipe extends SharedSocket { /** * The named pipe as a file. */ RandomAccessFile pipe; /** * Creates a new instance of <code>SharedLocalNamedPipe</code>. * * @param connection the connection object * @throws IOException if an I/O error occurs */ public SharedLocalNamedPipe(JtdsConnection connection) throws IOException { super(connection.getBufferDir(), connection.getTdsVersion(), connection.getServerType()); final String serverName = connection.getServerName(); final String instanceName = connection.getInstanceName(); final StringBuilder pipeName = new StringBuilder(64); pipeName.append("\\\\"); if (serverName == null || serverName.length() == 0) { pipeName.append( '.' ); } else { pipeName.append(serverName); } pipeName.append("\\pipe"); if (instanceName != null && instanceName.length() != 0) { if(!instanceName.startsWith("LOCALDB")) pipeName.append("\\MSSQL$"); else pipeName.append("\\"); pipeName.append(instanceName); } String namedPipePath = DefaultProperties.getNamedPipePath(connection.getServerType(), instanceName); pipeName.append(namedPipePath.replace('/', '\\')); pipe = new RandomAccessFile(pipeName.toString(), "rw"); final int bufferSize = Support.calculateNamedPipeBufferSize( connection.getTdsVersion(), connection.getPacketSize()); setOut(new DataOutputStream( new BufferedOutputStream( new FileOutputStream(pipe.getFD()), bufferSize))); setIn(new DataInputStream( new BufferedInputStream( new FileInputStream(pipe.getFD()), bufferSize))); } String getMAC() { try { Enumeration<NetworkInterface> nics = NetworkInterface.getNetworkInterfaces(); while( nics.hasMoreElements() ) { NetworkInterface nic = nics.nextElement(); try { if( ! nic.isLoopback() && ! nic.isVirtual() ) { byte[] address = nic.getHardwareAddress(); if( address != null ) { String mac = ""; for( int k = 0; k < address.length; k ++ ) { String macValue = String.format("%02X", address[k] ); mac += macValue; } return mac; } } } catch( SocketException e ) { // ignore errors for single NICs } } } catch( SocketException e ) { // error getting network interfaces, return null } return null; } /** * Get the connected status of this socket. * * @return <code>true</code> if the underlying named pipe is connected */ boolean isConnected() { return pipe != null; } /** * Send an network packet. If output for another virtual socket is in * progress this packet will be sent later. * * @param vsock * the {@link VirtualSocket} used by the originating <code>RequestStream</code> * * @param buffer * the data to send * * @exception java.io.IOException * if an I/O error occurs */ byte[] sendNetPacket( VirtualSocket vsock, byte buffer[] ) throws IOException { byte[] ret = super.sendNetPacket(vsock, buffer); getOut().flush(); return ret; } /** * Close the named pipe and virtual sockets and release any resources. */ void close() throws IOException { try { // Close virtual sockets super.close(); getOut().close(); setOut(null); getIn().close(); setIn(null); if (pipe != null) { pipe.close(); } } finally { pipe = null; } } /** * Force close the socket causing any pending reads/writes to fail. * <p> * Used by the login timer to abort a login attempt. */ void forceClose() { try { getOut().close(); } catch (Exception e) { // Ignore } finally { setOut(null); } try { getIn().close(); } catch (Exception e) { // Ignore } finally { setIn(null); } try { if (pipe != null) { pipe.close(); } } catch (IOException ex) { } finally { pipe = null; } } /** * Set the socket timeout. * * @param timeout the timeout value in milliseconds */ protected void setTimeout(int timeout) { // FIXME - implement timeout functionality } }