OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [libjava/] [classpath/] [vm/] [reference/] [gnu/] [java/] [nio/] [VMChannel.java] - Blame information for rev 780

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 780 jeremybenn
/* VMChannel.java -- Native interface suppling channel operations.
2
   Copyright (C) 2006 Free Software Foundation, Inc.
3
 
4
This file is part of GNU Classpath.
5
 
6
GNU Classpath is free software; you can redistribute it and/or modify
7
it under the terms of the GNU General Public License as published by
8
the Free Software Foundation; either version 2, or (at your option)
9
any later version.
10
 
11
GNU Classpath is distributed in the hope that it will be useful, but
12
WITHOUT ANY WARRANTY; without even the implied warranty of
13
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14
General Public License for more details.
15
 
16
You should have received a copy of the GNU General Public License
17
along with GNU Classpath; see the file COPYING.  If not, write to the
18
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19
02110-1301 USA.
20
 
21
Linking this library statically or dynamically with other modules is
22
making a combined work based on this library.  Thus, the terms and
23
conditions of the GNU General Public License cover the whole
24
combination.
25
 
26
As a special exception, the copyright holders of this library give you
27
permission to link this library with independent modules to produce an
28
executable, regardless of the license terms of these independent
29
modules, and to copy and distribute the resulting executable under
30
terms of your choice, provided that you also meet, for each linked
31
independent module, the terms and conditions of the license of that
32
module.  An independent module is a module which is not derived from
33
or based on this library.  If you modify this library, you may extend
34
this exception to your version of the library, but you are not
35
obligated to do so.  If you do not wish to do so, delete this
36
exception statement from your version. */
37
 
38
 
39
package gnu.java.nio;
40
 
41
import gnu.classpath.Configuration;
42
 
43
import java.io.IOException;
44
import java.net.Inet4Address;
45
import java.net.Inet6Address;
46
import java.net.InetAddress;
47
import java.net.InetSocketAddress;
48
import java.net.SocketAddress;
49
import java.net.SocketException;
50
import java.nio.ByteBuffer;
51
import java.nio.MappedByteBuffer;
52
 
53
/**
54
 * Native interface to support configuring of channel to run in a non-blocking
55
 * manner and support scatter/gather io operations.
56
 *
57
 * @author Michael Barker <mike@middlesoft.co.uk>
58
 *
59
 */
60
public final class VMChannel
61
{
62
  /**
63
   * Our reference implementation uses an integer to store the native
64
   * file descriptor. Implementations without such support
65
   */
66
  private final State nfd;
67
 
68
  private Kind kind;
69
 
70
  public VMChannel()
71
  {
72
    // XXX consider adding security check here, so only Classpath
73
    // code may create instances.
74
    this.nfd = new State();
75
    kind = Kind.OTHER;
76
  }
77
 
78
  /**
79
   * This constructor is used by the POSIX reference implementation;
80
   * other virtual machines need not support it.
81
   *
82
   * <strong>Important:</strong> do not call this in library code that is
83
   * not specific to Classpath's reference implementation.
84
   *
85
   * @param native_fd The native file descriptor integer.
86
   * @throws IOException
87
   */
88
  VMChannel(final int native_fd) throws IOException
89
  {
90
    this();
91
    this.nfd.setNativeFD(native_fd);
92
  }
93
 
94
  public State getState()
95
  {
96
    return nfd;
97
  }
98
 
99
  static
100
  {
101
    // load the shared library needed for native methods.
102
    if (Configuration.INIT_LOAD_LIBRARY)
103
      {
104
        System.loadLibrary ("javanio");
105
      }
106
    initIDs();
107
  }
108
 
109
  public static VMChannel getStdin() throws IOException
110
  {
111
    return new VMChannel(stdin_fd());
112
  }
113
 
114
  public static VMChannel getStdout() throws IOException
115
  {
116
    return new VMChannel(stdout_fd());
117
  }
118
 
119
  public static VMChannel getStderr() throws IOException
120
  {
121
    return new VMChannel(stderr_fd());
122
  }
123
 
124
  private static native int stdin_fd();
125
  private static native int stdout_fd();
126
  private static native int stderr_fd();
127
 
128
  /**
129
   * Set the file descriptor to have the required blocking
130
   * setting.
131
   *
132
   * @param blocking The blocking flag to set.
133
   */
134
  public void setBlocking(boolean blocking) throws IOException
135
  {
136
    setBlocking(nfd.getNativeFD(), blocking);
137
  }
138
 
139
  private static native void setBlocking(int fd, boolean blocking)
140
    throws IOException;
141
 
142
  public int available() throws IOException
143
  {
144
    return available(nfd.getNativeFD());
145
  }
146
 
147
  private static native int available(int native_fd) throws IOException;
148
 
149
  /**
150
   * Reads a byte buffer directly using the supplied file descriptor.
151
   *
152
   * @param dst Direct Byte Buffer to read to.
153
   * @return Number of bytes read.
154
   * @throws IOException If an error occurs or dst is not a direct buffers.
155
   */
156
  public int read(ByteBuffer dst)
157
    throws IOException
158
  {
159
    return read(nfd.getNativeFD(), dst);
160
  }
161
 
162
  private static native int read(int fd, ByteBuffer dst) throws IOException;
163
 
164
  /**
165
   * Read a single byte.
166
   *
167
   * @return The byte read, or -1 on end of file.
168
   * @throws IOException
169
   */
170
  public int read() throws IOException
171
  {
172
    return read(nfd.getNativeFD());
173
  }
174
 
175
  private static native int read(int fd) throws IOException;
176
 
177
  /**
178
   * Reads into byte buffers directly using the supplied file descriptor.
179
   * Assumes that the buffer list contains DirectBuffers.  Will perform a
180
   * scattering read.
181
   *
182
   * @param dsts An array direct byte buffers.
183
   * @param offset Index of the first buffer to read to.
184
   * @param length The number of buffers to read to.
185
   * @return Number of bytes read.
186
   * @throws IOException If an error occurs or the dsts are not direct buffers.
187
   */
188
  public long readScattering(ByteBuffer[] dsts, int offset, int length)
189
    throws IOException
190
  {
191
    if (offset + length > dsts.length)
192
      throw new IndexOutOfBoundsException("offset + length > dsts.length");
193
 
194
    return readScattering(nfd.getNativeFD(), dsts, offset, length);
195
  }
196
 
197
  private static native long readScattering(int fd, ByteBuffer[] dsts,
198
                                            int offset, int length)
199
    throws IOException;
200
 
201
  /**
202
   * Receive a datagram on this channel, returning the host address
203
   * that sent the datagram.
204
   *
205
   * @param dst Where to store the datagram.
206
   * @return The host address that sent the datagram.
207
   * @throws IOException
208
   */
209
  public SocketAddress receive(ByteBuffer dst) throws IOException
210
  {
211
    if (kind != Kind.SOCK_DGRAM)
212
      throw new SocketException("not a datagram socket");
213
    ByteBuffer hostPort = ByteBuffer.allocateDirect(18);
214
    int hostlen = receive(nfd.getNativeFD(), dst, hostPort);
215
    if (hostlen == 0)
216
      return null;
217
    if (hostlen == 4) // IPv4
218
      {
219
        byte[] addr = new byte[4];
220
        hostPort.get(addr);
221
        int port = hostPort.getShort() & 0xFFFF;
222
        return new InetSocketAddress(Inet4Address.getByAddress(addr), port);
223
      }
224
    if (hostlen == 16) // IPv6
225
      {
226
        byte[] addr = new byte[16];
227
        hostPort.get(addr);
228
        int port = hostPort.getShort() & 0xFFFF;
229
        return new InetSocketAddress(Inet6Address.getByAddress(addr), port);
230
      }
231
 
232
    throw new SocketException("host address received with invalid length: "
233
                              + hostlen);
234
  }
235
 
236
  private static native int receive (int fd, ByteBuffer dst, ByteBuffer address)
237
    throws IOException;
238
 
239
  /**
240
   * Writes from a direct byte bufer using the supplied file descriptor.
241
   * Assumes the buffer is a DirectBuffer.
242
   *
243
   * @param src The source buffer.
244
   * @return Number of bytes written.
245
   * @throws IOException
246
   */
247
  public int write(ByteBuffer src) throws IOException
248
  {
249
    return write(nfd.getNativeFD(), src);
250
  }
251
 
252
  private native int write(int fd, ByteBuffer src) throws IOException;
253
 
254
  /**
255
   * Writes from byte buffers directly using the supplied file descriptor.
256
   * Assumes the that buffer list constains DirectBuffers.  Will perform
257
   * as gathering write.
258
   *
259
   * @param srcs
260
   * @param offset
261
   * @param length
262
   * @return Number of bytes written.
263
   * @throws IOException
264
   */
265
  public long writeGathering(ByteBuffer[] srcs, int offset, int length)
266
    throws IOException
267
  {
268
    if (offset + length > srcs.length)
269
      throw new IndexOutOfBoundsException("offset + length > srcs.length");
270
 
271
    // A gathering write is limited to 16 buffers; when writing, ensure
272
    // that we have at least one buffer with something in it in the 16
273
    // buffer window starting at offset.
274
    while (!srcs[offset].hasRemaining() && offset < srcs.length)
275
      offset++;
276
 
277
    // There are no buffers with anything to write.
278
    if (offset == srcs.length)
279
      return 0;
280
 
281
    // If we advanced `offset' so far that we don't have `length'
282
    // buffers left, reset length to only the remaining buffers.
283
    if (length > srcs.length - offset)
284
      length = srcs.length - offset;
285
 
286
    return writeGathering(nfd.getNativeFD(), srcs, offset, length);
287
  }
288
 
289
  private native long writeGathering(int fd, ByteBuffer[] srcs,
290
                                     int offset, int length)
291
    throws IOException;
292
 
293
  /**
294
   * Send a datagram to the given address.
295
   *
296
   * @param src The source buffer.
297
   * @param dst The destination address.
298
   * @return The number of bytes written.
299
   * @throws IOException
300
   */
301
  public int send(ByteBuffer src, InetSocketAddress dst)
302
    throws IOException
303
  {
304
    InetAddress addr = dst.getAddress();
305
    if (addr == null)
306
      throw new NullPointerException();
307
    if (addr instanceof Inet4Address)
308
      return send(nfd.getNativeFD(), src, addr.getAddress(), dst.getPort());
309
    else if (addr instanceof Inet6Address)
310
      return send6(nfd.getNativeFD(), src, addr.getAddress(), dst.getPort());
311
    else
312
      throw new SocketException("unrecognized inet address type");
313
  }
314
 
315
  // Send to an IPv4 address.
316
  private static native int send(int fd, ByteBuffer src, byte[] addr, int port)
317
    throws IOException;
318
 
319
  // Send to an IPv6 address.
320
  private static native int send6(int fd, ByteBuffer src, byte[] addr, int port)
321
    throws IOException;
322
 
323
  /**
324
   * Write a single byte.
325
   *
326
   * @param b The byte to write.
327
   * @throws IOException
328
   */
329
  public void write(int b) throws IOException
330
  {
331
    write(nfd.getNativeFD(), b);
332
  }
333
 
334
  private static native void write(int fd, int b) throws IOException;
335
 
336
  private native static void initIDs();
337
 
338
  // Network (socket) specific methods.
339
 
340
  /**
341
   * Create a new socket. This method will initialize the native file
342
   * descriptor state of this instance.
343
   *
344
   * @param stream Whether or not to create a streaming socket, or a datagram
345
   *  socket.
346
   * @throws IOException If creating a new socket fails, or if this
347
   *  channel already has its native descriptor initialized.
348
   */
349
  public void initSocket(boolean stream) throws IOException
350
  {
351
    if (nfd.isValid())
352
      throw new IOException("native FD already initialized");
353
    if (stream)
354
      kind = Kind.SOCK_STREAM;
355
    else
356
      kind = Kind.SOCK_DGRAM;
357
    nfd.setNativeFD(socket(stream));
358
  }
359
 
360
  /**
361
   * Create a new socket, returning the native file descriptor.
362
   *
363
   * @param stream Set to true for streaming sockets; false for datagrams.
364
   * @return The native file descriptor.
365
   * @throws IOException If creating the socket fails.
366
   */
367
  private static native int socket(boolean stream) throws IOException;
368
 
369
  /**
370
   * Connect the underlying socket file descriptor to the remote host.
371
   *
372
   * @param saddr The address to connect to.
373
   * @param timeout The connect timeout to use for blocking connects.
374
   * @return True if the connection succeeded; false if the file descriptor
375
   *  is in non-blocking mode and the connection did not immediately
376
   *  succeed.
377
   * @throws IOException If an error occurs while connecting.
378
   */
379
  public boolean connect(InetSocketAddress saddr, int timeout)
380
    throws SocketException
381
  {
382
    int fd;
383
 
384
    InetAddress addr = saddr.getAddress();
385
 
386
    // Translates an IOException into a SocketException to conform
387
    // to the throws clause.
388
    try
389
      {
390
        fd = nfd.getNativeFD();
391
      }
392
    catch (IOException ioe)
393
      {
394
        throw new SocketException(ioe.getMessage());
395
      }
396
 
397
    if (addr instanceof Inet4Address)
398
      return connect(fd, addr.getAddress(), saddr.getPort(),
399
                     timeout);
400
    if (addr instanceof Inet6Address)
401
      return connect6(fd, addr.getAddress(), saddr.getPort(),
402
                      timeout);
403
    throw new SocketException("unsupported internet address");
404
  }
405
 
406
  private static native boolean connect(int fd, byte[] addr, int port, int timeout)
407
    throws SocketException;
408
 
409
  private static native boolean connect6(int fd, byte[] addr, int port, int timeout)
410
    throws SocketException;
411
 
412
  /**
413
   * Disconnect this channel, if it is a datagram socket. Disconnecting
414
   * a datagram channel will disassociate it from any address, so the
415
   * socket will remain open, but can send and receive datagrams from
416
   * any address.
417
   *
418
   * @throws IOException If disconnecting this channel fails, or if this
419
   *  channel is not a datagram channel.
420
   */
421
  public void disconnect() throws IOException
422
  {
423
    if (kind != Kind.SOCK_DGRAM)
424
      throw new IOException("can only disconnect datagram channels");
425
    disconnect(nfd.getNativeFD());
426
  }
427
 
428
  private static native void disconnect(int fd) throws IOException;
429
 
430
  public InetSocketAddress getLocalAddress() throws IOException
431
  {
432
    if (!nfd.isValid())
433
      return null;
434
    ByteBuffer name = ByteBuffer.allocateDirect(18);
435
    int namelen = getsockname(nfd.getNativeFD(), name);
436
    if (namelen == 0) // not bound
437
      return null; // XXX return some wildcard?
438
    if (namelen == 4)
439
      {
440
        byte[] addr = new byte[4];
441
        name.get(addr);
442
        int port = name.getShort() & 0xFFFF;
443
        return new InetSocketAddress(Inet4Address.getByAddress(addr), port);
444
      }
445
    if (namelen == 16)
446
      {
447
        byte[] addr = new byte[16];
448
        name.get(addr);
449
        int port = name.getShort() & 0xFFFF;
450
        return new InetSocketAddress(Inet6Address.getByAddress(addr), port);
451
      }
452
    throw new SocketException("invalid address length");
453
  }
454
 
455
  private static native int getsockname(int fd, ByteBuffer name)
456
    throws IOException;
457
 
458
  /**
459
   * Returns the socket address of the remote peer this channel is connected
460
   * to, or null if this channel is not yet connected.
461
   *
462
   * @return The peer address.
463
   * @throws IOException
464
   */
465
  public InetSocketAddress getPeerAddress() throws IOException
466
  {
467
    if (!nfd.isValid())
468
      return null;
469
    ByteBuffer name = ByteBuffer.allocateDirect(18);
470
    int namelen = getpeername (nfd.getNativeFD(), name);
471
    if (namelen == 0) // not connected yet
472
      return null;
473
    if (namelen == 4) // IPv4
474
      {
475
        byte[] addr = new byte[4];
476
        name.get(addr);
477
        int port = name.getShort() & 0xFFFF;
478
        return new InetSocketAddress(Inet4Address.getByAddress(addr), port);
479
      }
480
    else if (namelen == 16) // IPv6
481
      {
482
        byte[] addr = new byte[16];
483
        name.get(addr);
484
        int port = name.getShort() & 0xFFFF;
485
        return new InetSocketAddress(Inet6Address.getByAddress(addr), port);
486
      }
487
    throw new SocketException("invalid address length");
488
  }
489
 
490
  /*
491
   * The format here is the peer address, followed by the port number.
492
   * The returned value is the length of the peer address; thus, there
493
   * will be LEN + 2 valid bytes put into NAME.
494
   */
495
  private static native int getpeername(int fd, ByteBuffer name)
496
    throws IOException;
497
 
498
  /**
499
   * Accept an incoming connection, returning a new VMChannel, or null
500
   * if the channel is nonblocking and no connection is pending.
501
   *
502
   * @return The accepted connection, or null.
503
   * @throws IOException If an IO error occurs.
504
   */
505
  public VMChannel accept() throws IOException
506
  {
507
    int new_fd = accept(nfd.getNativeFD());
508
    if (new_fd == -1) // non-blocking accept had no pending connection
509
      return null;
510
    return new VMChannel(new_fd);
511
  }
512
 
513
  private static native int accept(int native_fd) throws IOException;
514
 
515
  // File-specific methods.
516
 
517
  /**
518
   * Open a file at PATH, initializing the native state to operate on
519
   * that open file.
520
   *
521
   * @param path The absolute file path.
522
   * @throws IOException If the file cannot be opened, or if this
523
   *  channel was previously initialized.
524
   */
525
  public void openFile(String path, int mode) throws IOException
526
  {
527
    if (nfd.isValid() || nfd.isClosed())
528
      throw new IOException("can't reinitialize this channel");
529
    int fd = open(path, mode);
530
    nfd.setNativeFD(fd);
531
    kind = Kind.FILE;
532
  }
533
 
534
  private static native int open(String path, int mode) throws IOException;
535
 
536
  public long position() throws IOException
537
  {
538
    if (kind != Kind.FILE)
539
      throw new IOException("not a file");
540
    return position(nfd.getNativeFD());
541
  }
542
 
543
  private static native long position(int fd) throws IOException;
544
 
545
  public void seek(long pos) throws IOException
546
  {
547
    if (kind != Kind.FILE)
548
      throw new IOException("not a file");
549
    seek(nfd.getNativeFD(), pos);
550
  }
551
 
552
  private static native void seek(int fd, long pos) throws IOException;
553
 
554
  public void truncate(long length) throws IOException
555
  {
556
    if (kind != Kind.FILE)
557
      throw new IOException("not a file");
558
    truncate(nfd.getNativeFD(), length);
559
  }
560
 
561
  private static native void truncate(int fd, long len) throws IOException;
562
 
563
  public boolean lock(long pos, long len, boolean shared, boolean wait)
564
    throws IOException
565
  {
566
    if (kind != Kind.FILE)
567
      throw new IOException("not a file");
568
    return lock(nfd.getNativeFD(), pos, len, shared, wait);
569
  }
570
 
571
  private static native boolean lock(int fd, long pos, long len,
572
                                     boolean shared, boolean wait)
573
    throws IOException;
574
 
575
  public void unlock(long pos, long len) throws IOException
576
  {
577
    if (kind != Kind.FILE)
578
      throw new IOException("not a file");
579
    unlock(nfd.getNativeFD(), pos, len);
580
  }
581
 
582
  private static native void unlock(int fd, long pos, long len) throws IOException;
583
 
584
  public long size() throws IOException
585
  {
586
    if (kind != Kind.FILE)
587
      throw new IOException("not a file");
588
    return size(nfd.getNativeFD());
589
  }
590
 
591
  private static native long size(int fd) throws IOException;
592
 
593
  public MappedByteBuffer map(char mode, long position, int size)
594
    throws IOException
595
  {
596
    if (kind != Kind.FILE)
597
      throw new IOException("not a file");
598
    return map(nfd.getNativeFD(), mode, position, size);
599
  }
600
 
601
  private static native MappedByteBuffer map(int fd, char mode,
602
                                             long position, int size)
603
    throws IOException;
604
 
605
  public boolean flush(boolean metadata) throws IOException
606
  {
607
    if (kind != Kind.FILE)
608
      throw new IOException("not a file");
609
    return flush(nfd.getNativeFD(), metadata);
610
  }
611
 
612
  private static native boolean flush(int fd, boolean metadata) throws IOException;
613
 
614
  // Close.
615
 
616
  /**
617
   * Close this socket. The socket is also automatically closed when this
618
   * object is finalized.
619
   *
620
   * @throws IOException If closing the socket fails, or if this object has
621
   *  no open socket.
622
   */
623
  public void close() throws IOException
624
  {
625
    nfd.close();
626
  }
627
 
628
  static native void close(int native_fd) throws IOException;
629
 
630
  /**
631
   * <p>Provides a simple mean for the JNI code to find out whether the
632
   * current thread was interrupted by a call to Thread.interrupt().</p>
633
   *
634
   * @return
635
   */
636
  static boolean isThreadInterrupted()
637
  {
638
    return Thread.currentThread().isInterrupted();
639
  }
640
 
641
  // Inner classes.
642
 
643
  /**
644
   * A wrapper for a native file descriptor integer. This tracks the state
645
   * of an open file descriptor, and ensures that
646
   *
647
   * This class need not be fully supported by virtual machines; if a
648
   * virtual machine does not use integer file descriptors, or does and
649
   * wishes to hide that, then the methods of this class may be stubbed out.
650
   *
651
   * System-specific classes that depend on access to native file descriptor
652
   * integers SHOULD declare this fact.
653
   */
654
  public final class State
655
  {
656
    private int native_fd;
657
    private boolean valid;
658
    private boolean closed;
659
 
660
    State()
661
    {
662
      native_fd = -1;
663
      valid = false;
664
      closed = false;
665
    }
666
 
667
    public boolean isValid()
668
    {
669
      return valid;
670
    }
671
 
672
    public boolean isClosed()
673
    {
674
      return closed;
675
    }
676
 
677
    public int getNativeFD() throws IOException
678
    {
679
      if (!valid)
680
        throw new IOException("invalid file descriptor");
681
      return native_fd;
682
    }
683
 
684
    void setNativeFD(final int native_fd) throws IOException
685
    {
686
      if (valid)
687
        throw new IOException("file descriptor already initialized");
688
      this.native_fd = native_fd;
689
      valid = true;
690
    }
691
 
692
    public void close() throws IOException
693
    {
694
      if (!valid)
695
        throw new IOException("invalid file descriptor");
696
      try
697
        {
698
          VMChannel.close(native_fd);
699
        }
700
      finally
701
        {
702
          valid = false;
703
          closed = true;
704
        }
705
    }
706
 
707
    public String toString()
708
    {
709
      if (closed)
710
        return "<<closed>>";
711
      if (!valid)
712
        return "<<invalid>>";
713
      return String.valueOf(native_fd);
714
    }
715
 
716
    protected void finalize() throws Throwable
717
    {
718
      try
719
        {
720
          if (valid)
721
            close();
722
        }
723
      finally
724
        {
725
          super.finalize();
726
        }
727
    }
728
  }
729
 
730
  /**
731
   * An enumeration of possible kinds of channel.
732
   */
733
  static class Kind // XXX enum
734
  {
735
    /** A streaming (TCP) socket. */
736
    static final Kind SOCK_STREAM = new Kind();
737
 
738
    /** A datagram (UDP) socket. */
739
    static final Kind SOCK_DGRAM = new Kind();
740
 
741
    /** A file. */
742
    static final Kind FILE = new Kind();
743
 
744
    /** Something else; not a socket or file. */
745
    static final Kind OTHER = new Kind();
746
 
747
    private Kind() { }
748
  }
749
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.