jruby-stdin-channel 0.1.0-java

Sign up to get free protection for your applications and to get access to all the features.
@@ -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: []