jruby-stdin-channel 0.1.0-java

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: a28a8e1211996e36c03df35752494e098a5e0cce
4
+ data.tar.gz: 338f1d8ad70d88df8a8f94579acf8943799a7592
5
+ SHA512:
6
+ metadata.gz: 7e4f0a8b6ba5c8ff73990732b70d97313b9529377470e3d6a3549065c3cd5cd99cd0e10bae80bd6336063cb6c047d6c1656f37613b55a1463f2c04a08c8e1990
7
+ data.tar.gz: 3893950157ba0128fbd23797de78df31854ed851cd7d0f3c935999bbe173161a136d6c961f25e3e0c8da04836084e62cee6aa6319da894e15e28df092ec65dc1
@@ -0,0 +1,26 @@
1
+ # encoding: utf-8
2
+
3
+ raise("JRuby required") unless defined?(JRUBY_VERSION)
4
+
5
+ lib = File.expand_path('../lib', __FILE__)
6
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
7
+ require 'jruby_stdin_channel/version'
8
+
9
+ Gem::Specification.new do |s|
10
+ s.name = "jruby-stdin-channel"
11
+ s.version = StdinChannel::VERSION
12
+ s.authors = ["Colin Surprenant"]
13
+ s.date = Time.now.strftime('%Y-%m-%d')
14
+ s.summary = "JRuby extension to expose an interruptible NIO FileChannel for STDIN"
15
+ s.description = s.summary
16
+ s.email = ["colin.surprenant@gmail.com"]
17
+ s.homepage = "http://github.com/colinsurprenant/jruby-stdin-channel"
18
+ s.require_paths = ["lib"]
19
+ s.licenses = ["Apache-2.0"]
20
+ s.platform = "java"
21
+
22
+ s.files = Dir.glob(["jruby-stdin-channel.gemspec", "lib/**/*.{rb,jar}", "src/**/*.java"])
23
+
24
+ s.add_development_dependency "rspec", ">= 2.0.0"
25
+ s.add_development_dependency "rake", ">= 10.0.0"
26
+ end
@@ -0,0 +1,3 @@
1
+ # encoding: utf-8
2
+
3
+ require "jruby_stdin_channel/jruby_stdin_channel"
@@ -0,0 +1,3 @@
1
+ # encoding: utf-8
2
+
3
+ require "jruby_stdin_channel/jruby_stdin_channel"
@@ -0,0 +1,17 @@
1
+ # encoding: utf-8
2
+
3
+ require "java"
4
+
5
+ # local dev setup
6
+ classes_dir = File.expand_path("../../../out/production/main", __FILE__)
7
+
8
+ if File.directory?(classes_dir)
9
+ # if in local dev setup, add to classpath
10
+ $CLASSPATH << classes_dir unless $CLASSPATH.include?(classes_dir)
11
+ else
12
+ # otherwise use included jar
13
+ require "jruby_stdin_channel/jruby_stdin_channel.jar"
14
+ end
15
+
16
+ require "stdin_channel"
17
+ require "jruby_stdin_channel/version"
@@ -0,0 +1,5 @@
1
+ # encoding: utf-8
2
+
3
+ module StdinChannel
4
+ VERSION = "0.1.0"
5
+ end
@@ -0,0 +1,10 @@
1
+ import java.io.IOException;
2
+ import org.jruby.Ruby;
3
+ import org.jruby.runtime.load.BasicLibraryService;
4
+
5
+ public class StdinChannelService implements BasicLibraryService {
6
+ public boolean basicLoad(final Ruby runtime) throws IOException {
7
+ new com.jrubystdinchannel.StdinChannelLibrary().load(runtime, false);
8
+ return true;
9
+ }
10
+ }
@@ -0,0 +1,130 @@
1
+ package com.jrubystdinchannel;
2
+
3
+ import java.io.*;
4
+ import java.lang.reflect.Field;
5
+ import java.nio.ByteBuffer;
6
+ import java.nio.channels.FileChannel;
7
+
8
+ import org.jruby.Ruby;
9
+ import org.jruby.RubyClass;
10
+ import org.jruby.RubyModule;
11
+ import org.jruby.RubyNumeric;
12
+ import org.jruby.RubyObject;
13
+ import org.jruby.RubyString;
14
+ import org.jruby.exceptions.RaiseException;
15
+ import org.jruby.anno.JRubyClass;
16
+ import org.jruby.anno.JRubyMethod;
17
+ import org.jruby.javasupport.JavaObject;
18
+ import org.jruby.runtime.ObjectAllocator;
19
+ import org.jruby.runtime.ThreadContext;
20
+ import org.jruby.runtime.builtin.IRubyObject;
21
+ import org.jruby.runtime.load.Library;
22
+ import org.jruby.javasupport.JavaUtil;
23
+
24
+ public class StdinChannelLibrary implements Library {
25
+ public void load(Ruby runtime, boolean wrap) throws IOException {
26
+ RubyModule mmapModule = runtime.defineModule("StdinChannel");
27
+ RubyClass byteBufferClass = runtime.defineClassUnder("Reader", runtime.getObject(), new ObjectAllocator() {
28
+ public IRubyObject allocate(Ruby runtime, RubyClass rubyClass) {
29
+ return new Reader(runtime, rubyClass);
30
+ }
31
+ }, mmapModule);
32
+ byteBufferClass.defineAnnotatedMethods(Reader.class);
33
+ }
34
+
35
+ @JRubyClass(name = "Reader", parent = "Object")
36
+ public static class Reader extends RubyObject {
37
+
38
+ private FileInputStream in;
39
+ private FileChannel channel;
40
+
41
+ public Reader(Ruby runtime, RubyClass klass) {
42
+ super(runtime, klass);
43
+ }
44
+
45
+ // def initialize
46
+ @JRubyMethod(name = "initialize")
47
+ public IRubyObject initialize(ThreadContext context)
48
+ {
49
+ this.in = interruptibleStdin(context);
50
+ this.channel = in.getChannel();
51
+ return context.nil;
52
+ }
53
+
54
+
55
+ private static FileInputStream interruptibleStdin(ThreadContext context)
56
+ {
57
+ final RaiseException EXTRACT_ERROR = context.runtime.newRuntimeError("cannot find underlying FileInputStream in System.in");
58
+
59
+ try {
60
+ InputStream stdin = System.in;
61
+
62
+ // we expect System.in to be a FilterInputStream, let's setup access to its "in" field
63
+ Field inField = FilterInputStream.class.getDeclaredField("in");
64
+ inField.setAccessible(true);
65
+
66
+ // normally the underlying FileInputStream is directly in the "in" field but
67
+ // let's make sure it's not hidden in another inner FilterInputStream
68
+ while (stdin instanceof FilterInputStream) {
69
+ stdin = (InputStream) inField.get(stdin);
70
+ }
71
+
72
+ // no luck discovering inner FileInputStream ?
73
+ if (!(stdin instanceof FileInputStream)) {
74
+ throw EXTRACT_ERROR;
75
+ }
76
+
77
+ return (FileInputStream) stdin;
78
+ } catch (NoSuchFieldException|IllegalAccessException e) {
79
+ throw EXTRACT_ERROR;
80
+ }
81
+ }
82
+
83
+
84
+ // def read(size)
85
+ @JRubyMethod(name = "read", required = 1)
86
+ public IRubyObject read(ThreadContext context, IRubyObject _size)
87
+ throws IOException
88
+ {
89
+ int size = RubyNumeric.num2int(_size);
90
+
91
+ // not sure if we should not reuse a global ByteBuffer here instead of
92
+ // reallocating a new one at each read call
93
+ ByteBuffer data = ByteBuffer.allocate(size);
94
+ int n;
95
+
96
+ try {
97
+ n = this.channel.read(data);
98
+ } catch (IOException e) {
99
+ throw context.runtime.newIOErrorFromException(e);
100
+ }
101
+
102
+ if (n > 0) {
103
+ byte[] bytes = new byte[n];
104
+ // what is the difference with using data.array() ?
105
+ data.position(0);
106
+ data.get(bytes, 0, n);
107
+ return RubyString.newString(context.runtime, bytes);
108
+ } else if (n == 0) {
109
+ // return new empty String
110
+ return new RubyString(context.runtime, context.runtime.getString());
111
+ } else {
112
+ throw context.runtime.newEOFError();
113
+ }
114
+ }
115
+
116
+ // @return [FileChannel] retrieve native Java FileChannel
117
+ @JRubyMethod(name = "channel")
118
+ public IRubyObject channel(ThreadContext context)
119
+ {
120
+ return JavaUtil.convertJavaToUsableRubyObject(context.runtime, this.channel);
121
+ }
122
+
123
+ @JRubyMethod(name = "close")
124
+ public void close()
125
+ throws IOException
126
+ {
127
+ this.channel.close();
128
+ }
129
+ }
130
+ }
metadata ADDED
@@ -0,0 +1,80 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: jruby-stdin-channel
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: java
6
+ authors:
7
+ - Colin Surprenant
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-05-15 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ requirement: !ruby/object:Gem::Requirement
15
+ requirements:
16
+ - - '>='
17
+ - !ruby/object:Gem::Version
18
+ version: 2.0.0
19
+ name: rspec
20
+ prerelease: false
21
+ type: :development
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - '>='
25
+ - !ruby/object:Gem::Version
26
+ version: 2.0.0
27
+ - !ruby/object:Gem::Dependency
28
+ requirement: !ruby/object:Gem::Requirement
29
+ requirements:
30
+ - - '>='
31
+ - !ruby/object:Gem::Version
32
+ version: 10.0.0
33
+ name: rake
34
+ prerelease: false
35
+ type: :development
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - '>='
39
+ - !ruby/object:Gem::Version
40
+ version: 10.0.0
41
+ description: JRuby extension to expose an interruptible NIO FileChannel for STDIN
42
+ email:
43
+ - colin.surprenant@gmail.com
44
+ executables: []
45
+ extensions: []
46
+ extra_rdoc_files: []
47
+ files:
48
+ - jruby-stdin-channel.gemspec
49
+ - lib/jruby-stdin-channel.rb
50
+ - lib/jruby_stdin_channel.rb
51
+ - lib/jruby_stdin_channel/jruby_stdin_channel.jar
52
+ - lib/jruby_stdin_channel/jruby_stdin_channel.rb
53
+ - lib/jruby_stdin_channel/version.rb
54
+ - src/main/java/StdinChannelService.java
55
+ - src/main/java/com/jrubystdinchannel/StdinChannelLibrary.java
56
+ homepage: http://github.com/colinsurprenant/jruby-stdin-channel
57
+ licenses:
58
+ - Apache-2.0
59
+ metadata: {}
60
+ post_install_message:
61
+ rdoc_options: []
62
+ require_paths:
63
+ - lib
64
+ required_ruby_version: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - '>='
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ required_rubygems_version: !ruby/object:Gem::Requirement
70
+ requirements:
71
+ - - '>='
72
+ - !ruby/object:Gem::Version
73
+ version: '0'
74
+ requirements: []
75
+ rubyforge_project:
76
+ rubygems_version: 2.4.6
77
+ signing_key:
78
+ specification_version: 4
79
+ summary: JRuby extension to expose an interruptible NIO FileChannel for STDIN
80
+ test_files: []