activerecord-jdbc-adapter 50.8-java → 51.1-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.
Files changed (62) hide show
  1. checksums.yaml +5 -5
  2. data/.gitignore +1 -2
  3. data/.travis.yml +26 -51
  4. data/Gemfile +3 -1
  5. data/README.md +9 -11
  6. data/Rakefile +15 -78
  7. data/activerecord-jdbc-adapter.gemspec +2 -2
  8. data/lib/active_record/connection_adapters/mssql_adapter.rb +1 -0
  9. data/lib/active_record/connection_adapters/sqlserver_adapter.rb +1 -0
  10. data/lib/arjdbc/abstract/core.rb +4 -12
  11. data/lib/arjdbc/abstract/database_statements.rb +4 -10
  12. data/lib/arjdbc/abstract/statement_cache.rb +4 -4
  13. data/lib/arjdbc/abstract/transaction_support.rb +2 -9
  14. data/lib/arjdbc/jdbc.rb +4 -0
  15. data/lib/arjdbc/jdbc/column.rb +11 -5
  16. data/lib/arjdbc/jdbc/connection_methods.rb +9 -2
  17. data/lib/arjdbc/jdbc/error.rb +1 -1
  18. data/lib/arjdbc/jdbc/jdbc.rake +4 -0
  19. data/lib/arjdbc/mssql.rb +7 -0
  20. data/lib/arjdbc/mssql/adapter.rb +804 -0
  21. data/lib/arjdbc/mssql/column.rb +200 -0
  22. data/lib/arjdbc/mssql/connection_methods.rb +79 -0
  23. data/lib/arjdbc/mssql/explain_support.rb +99 -0
  24. data/lib/arjdbc/mssql/limit_helpers.rb +231 -0
  25. data/lib/arjdbc/mssql/lock_methods.rb +77 -0
  26. data/lib/arjdbc/mssql/types.rb +343 -0
  27. data/lib/arjdbc/mssql/utils.rb +82 -0
  28. data/lib/arjdbc/mysql/adapter.rb +14 -11
  29. data/lib/arjdbc/mysql/connection_methods.rb +9 -18
  30. data/lib/arjdbc/postgresql/adapter.rb +108 -59
  31. data/lib/arjdbc/postgresql/column.rb +3 -6
  32. data/lib/arjdbc/postgresql/connection_methods.rb +3 -12
  33. data/lib/arjdbc/postgresql/oid_types.rb +14 -93
  34. data/lib/arjdbc/sqlite3/adapter.rb +171 -140
  35. data/lib/arjdbc/sqlite3/connection_methods.rb +1 -2
  36. data/lib/arjdbc/tasks/database_tasks.rb +36 -16
  37. data/lib/arjdbc/tasks/databases.rake +75 -32
  38. data/lib/arjdbc/tasks/databases3.rake +215 -0
  39. data/lib/arjdbc/tasks/databases4.rake +39 -0
  40. data/lib/arjdbc/version.rb +1 -1
  41. data/rakelib/01-tomcat.rake +2 -2
  42. data/rakelib/02-test.rake +3 -0
  43. data/rakelib/compile.rake +70 -0
  44. data/rakelib/db.rake +7 -21
  45. data/rakelib/rails.rake +4 -5
  46. data/src/java/arjdbc/ArJdbcModule.java +15 -5
  47. data/src/java/arjdbc/derby/DerbyRubyJdbcConnection.java +2 -2
  48. data/src/java/arjdbc/jdbc/ConnectionFactory.java +87 -0
  49. data/src/java/arjdbc/jdbc/DataSourceConnectionFactory.java +1 -0
  50. data/src/java/arjdbc/jdbc/RubyJdbcConnection.java +41 -120
  51. data/src/java/arjdbc/mssql/MSSQLRubyJdbcConnection.java +14 -310
  52. data/src/java/arjdbc/mysql/MySQLRubyJdbcConnection.java +2 -2
  53. data/src/java/arjdbc/postgresql/ByteaUtils.java +1 -0
  54. data/src/java/arjdbc/postgresql/PgResultSetMetaDataWrapper.java +23 -0
  55. data/src/java/arjdbc/postgresql/PostgreSQLResult.java +13 -21
  56. data/src/java/arjdbc/postgresql/PostgreSQLRubyJdbcConnection.java +46 -41
  57. data/src/java/arjdbc/util/DateTimeUtils.java +5 -141
  58. data/src/java/arjdbc/util/QuotingUtils.java +7 -6
  59. data/src/java/arjdbc/util/StringHelper.java +20 -6
  60. metadata +25 -16
  61. data/src/java/arjdbc/jdbc/RubyConnectionFactory.java +0 -61
  62. data/src/java/arjdbc/postgresql/PgDateTimeUtils.java +0 -52
@@ -27,6 +27,7 @@ package arjdbc.postgresql;
27
27
 
28
28
  import arjdbc.jdbc.Callable;
29
29
  import arjdbc.jdbc.DriverWrapper;
30
+ import arjdbc.postgresql.PostgreSQLResult;
30
31
  import arjdbc.util.DateTimeUtils;
31
32
  import arjdbc.util.StringHelper;
32
33
 
@@ -54,7 +55,6 @@ import org.joda.time.DateTimeZone;
54
55
  import org.jruby.*;
55
56
  import org.jruby.anno.JRubyMethod;
56
57
  import org.jruby.exceptions.RaiseException;
57
- import org.jruby.ext.bigdecimal.RubyBigDecimal;
58
58
  import org.jruby.javasupport.JavaUtil;
59
59
  import org.jruby.runtime.ObjectAllocator;
60
60
  import org.jruby.runtime.ThreadContext;
@@ -100,7 +100,6 @@ public class PostgreSQLRubyJdbcConnection extends arjdbc.jdbc.RubyJdbcConnection
100
100
  POSTGRES_JDBC_TYPE_FOR.put("line", Types.OTHER);
101
101
  POSTGRES_JDBC_TYPE_FOR.put("lseg", Types.OTHER);
102
102
  POSTGRES_JDBC_TYPE_FOR.put("ltree", Types.OTHER);
103
- POSTGRES_JDBC_TYPE_FOR.put("money", Types.OTHER);
104
103
  POSTGRES_JDBC_TYPE_FOR.put("numrange", Types.OTHER);
105
104
  POSTGRES_JDBC_TYPE_FOR.put("path", Types.OTHER);
106
105
  POSTGRES_JDBC_TYPE_FOR.put("point", Types.OTHER);
@@ -281,30 +280,6 @@ public class PostgreSQLRubyJdbcConnection extends arjdbc.jdbc.RubyJdbcConnection
281
280
  return mapExecuteResult(context, connection, resultSet).toARResult(context);
282
281
  }
283
282
 
284
- @Override
285
- protected void setArrayParameter(final ThreadContext context,
286
- final Connection connection, final PreparedStatement statement,
287
- final int index, final IRubyObject value,
288
- final IRubyObject attribute, final int type) throws SQLException {
289
-
290
- final String typeName = resolveArrayBaseTypeName(context, attribute);
291
- final RubyArray valueForDB = (RubyArray) value.callMethod(context, "values");
292
-
293
- Object[] values;
294
- switch (typeName) {
295
- case "datetime":
296
- case "timestamp": {
297
- values = PgDateTimeUtils.timestampStringArray(context, valueForDB);
298
- break;
299
- }
300
- default:
301
- values = valueForDB.toArray();
302
- break;
303
- }
304
-
305
- statement.setArray(index, connection.createArrayOf(typeName, values));
306
- }
307
-
308
283
  @Override
309
284
  protected void setBlobParameter(final ThreadContext context,
310
285
  final Connection connection, final PreparedStatement statement,
@@ -328,9 +303,47 @@ public class PostgreSQLRubyJdbcConnection extends arjdbc.jdbc.RubyJdbcConnection
328
303
  final Connection connection, final PreparedStatement statement,
329
304
  final int index, IRubyObject value,
330
305
  final IRubyObject attribute, final int type) throws SQLException {
331
- // PGJDBC uses strings internally anyway, so using Timestamp doesn't do any good
332
- String tsString = PgDateTimeUtils.timestampValueToString(context, value, null, true);
333
- statement.setObject(index, tsString, Types.OTHER);
306
+
307
+ if ( value instanceof RubyFloat ) {
308
+ final double doubleValue = ( (RubyFloat) value ).getValue();
309
+ if ( Double.isInfinite(doubleValue) ) {
310
+ setTimestampInfinity(statement, index, doubleValue);
311
+ return;
312
+ }
313
+ }
314
+
315
+ RubyTime timeValue = toTime(context, value);
316
+
317
+ final Timestamp timestamp;
318
+
319
+ if (timeValue.getDateTime().getYear() > 0) {
320
+ timeValue = timeInDefaultTimeZone(context, timeValue);
321
+ DateTime dateTime = timeValue.getDateTime();
322
+ timestamp = new Timestamp(dateTime.getMillis());
323
+
324
+ if (timeValue.getNSec() > 0) timestamp.setNanos((int) (timestamp.getNanos() + timeValue.getNSec()));
325
+
326
+ statement.setTimestamp(index, timestamp, getCalendar(dateTime.getZone()));
327
+ }
328
+ else {
329
+ setTimestampBC(statement, index, timeValue);
330
+ }
331
+ }
332
+
333
+ private static void setTimestampBC(final PreparedStatement statement,
334
+ final int index, final RubyTime timeValue) throws SQLException {
335
+ DateTime dateTime = timeValue.getDateTime();
336
+ @SuppressWarnings("deprecated")
337
+ Timestamp timestamp = new Timestamp(dateTime.getYear() - 1900,
338
+ dateTime.getMonthOfYear() - 1,
339
+ dateTime.getDayOfMonth(),
340
+ dateTime.getHourOfDay(),
341
+ dateTime.getMinuteOfHour(),
342
+ dateTime.getSecondOfMinute(),
343
+ dateTime.getMillisOfSecond() * 1_000_000 + (int) timeValue.getNSec()
344
+ );
345
+
346
+ statement.setObject(index, timestamp);
334
347
  }
335
348
 
336
349
  private static void setTimestampInfinity(final PreparedStatement statement,
@@ -352,8 +365,7 @@ public class PostgreSQLRubyJdbcConnection extends arjdbc.jdbc.RubyJdbcConnection
352
365
  final int index, IRubyObject value,
353
366
  final IRubyObject attribute, final int type) throws SQLException {
354
367
  // to handle more fractional second precision than (default) 59.123 only
355
- String timeStr = DateTimeUtils.timeString(context, value, getDefaultTimeZone(context), true);
356
- statement.setObject(index, timeStr, Types.OTHER);
368
+ super.setTimestampParameter(context, connection, statement, index, value, attribute, type);
357
369
  }
358
370
 
359
371
  @Override
@@ -407,7 +419,8 @@ public class PostgreSQLRubyJdbcConnection extends arjdbc.jdbc.RubyJdbcConnection
407
419
  break;
408
420
 
409
421
  case "enum":
410
- statement.setObject(index, value.toString(), Types.OTHER);
422
+ // FIXME: This doesn't work but it gives a better error message than letting it be treated as a PGobject
423
+ statement.setObject(index, value.toString());
411
424
  break;
412
425
 
413
426
  case "interval":
@@ -428,14 +441,6 @@ public class PostgreSQLRubyJdbcConnection extends arjdbc.jdbc.RubyJdbcConnection
428
441
  }
429
442
  break;
430
443
 
431
- case "money":
432
- if (value instanceof RubyBigDecimal) {
433
- statement.setBigDecimal(index, ((RubyBigDecimal) value).getValue());
434
- } else {
435
- setPGobjectParameter(statement, index, value, columnType);
436
- }
437
- break;
438
-
439
444
  case "lseg":
440
445
  pointValues = parseDoubles(value);
441
446
  statement.setObject(index, new PGlseg(pointValues[0], pointValues[1], pointValues[2], pointValues[3]));
@@ -480,7 +485,7 @@ public class PostgreSQLRubyJdbcConnection extends arjdbc.jdbc.RubyJdbcConnection
480
485
  return points;
481
486
  }
482
487
 
483
- private static Double[] parseDoubles(IRubyObject value) {
488
+ private Double[] parseDoubles(IRubyObject value) {
484
489
  Matcher matches = doubleValuePattern.matcher(value.toString());
485
490
  ArrayList<Double> doubles = new ArrayList<Double>(4); // Paths and polygons may be larger but this covers points/circles/boxes/line segments
486
491
 
@@ -28,10 +28,8 @@ import java.sql.Time;
28
28
  import java.sql.Timestamp;
29
29
  import java.util.TimeZone;
30
30
 
31
- import org.joda.time.Chronology;
32
31
  import org.joda.time.DateTime;
33
32
  import org.joda.time.DateTimeZone;
34
- import org.joda.time.chrono.GJChronology;
35
33
  import org.joda.time.chrono.ISOChronology;
36
34
  import org.jruby.Ruby;
37
35
  import org.jruby.RubyFloat;
@@ -42,7 +40,6 @@ import org.jruby.runtime.Block;
42
40
  import org.jruby.runtime.ThreadContext;
43
41
  import org.jruby.runtime.builtin.IRubyObject;
44
42
  import org.jruby.util.ByteList;
45
- import org.jruby.util.TypeConverter;
46
43
 
47
44
  import static arjdbc.util.StringHelper.decByte;
48
45
 
@@ -52,20 +49,6 @@ import static arjdbc.util.StringHelper.decByte;
52
49
  */
53
50
  public abstract class DateTimeUtils {
54
51
 
55
- private static final GJChronology CHRONO_ITALY_UTC = GJChronology.getInstance(DateTimeZone.UTC);
56
-
57
- public static RubyTime toTime(final ThreadContext context, final IRubyObject value) {
58
- if (!(value instanceof RubyTime)) { // unlikely
59
- return (RubyTime) TypeConverter.convertToTypeWithCheck(value, context.runtime.getTime(), "to_time");
60
- }
61
- return (RubyTime) value;
62
- }
63
-
64
- public static DateTime dateTimeInZone(final DateTime dateTime, final DateTimeZone zone) {
65
- if (zone == dateTime.getZone()) return dateTime;
66
- return dateTime.withZone(zone);
67
- }
68
-
69
52
  @SuppressWarnings("deprecation")
70
53
  public static ByteList timeToString(final Time time) {
71
54
  final ByteList str = new ByteList(8); // hh:mm:ss
@@ -221,11 +204,9 @@ public abstract class DateTimeUtils {
221
204
  final int hours = time.getHours();
222
205
  final int minutes = time.getMinutes();
223
206
  final int seconds = time.getSeconds();
224
- int nanos = time.getNanos(); // max 999-999-999
225
- final int millis = nanos / 1000000;
226
- nanos = nanos % 1000000;
207
+ final int nanos = time.getNanos(); // max 999-999-999
227
208
 
228
- DateTime dateTime = new DateTime(2000, 1, 1, hours, minutes, seconds, millis, defaultZone);
209
+ DateTime dateTime = new DateTime(2000, 1, 1, hours, minutes, seconds, defaultZone);
229
210
  return RubyTime.newTime(context.runtime, dateTime, nanos);
230
211
  }
231
212
 
@@ -238,11 +219,9 @@ public abstract class DateTimeUtils {
238
219
  final int hours = timestamp.getHours();
239
220
  final int minutes = timestamp.getMinutes();
240
221
  final int seconds = timestamp.getSeconds();
241
- int nanos = timestamp.getNanos(); // max 999-999-999
242
- final int millis = nanos / 1000000;
243
- nanos = nanos % 1000000;
222
+ final int nanos = timestamp.getNanos(); // max 999-999-999
244
223
 
245
- DateTime dateTime = new DateTime(year, month, day, hours, minutes, seconds, millis, defaultZone);
224
+ DateTime dateTime = new DateTime(year, month, day, hours, minutes, seconds, 0, defaultZone);
246
225
  return RubyTime.newTime(context.runtime, dateTime, nanos);
247
226
  }
248
227
 
@@ -267,15 +246,6 @@ public abstract class DateTimeUtils {
267
246
  return newDate(context, year, month, day, ISOChronology.getInstance(zone));
268
247
  }
269
248
 
270
- @SuppressWarnings("deprecation")
271
- public static IRubyObject newDate(final ThreadContext context, final Date date) {
272
- final int year = date.getYear() + 1900;
273
- final int month = date.getMonth() + 1;
274
- final int day = date.getDate();
275
-
276
- return newDate(context, year, month, day, CHRONO_ITALY_UTC);
277
- }
278
-
279
249
  // @Deprecated
280
250
  public static Timestamp convertToTimestamp(final RubyFloat value) {
281
251
  final Timestamp timestamp = new Timestamp(value.getLongValue() * 1000); // millis
@@ -570,7 +540,7 @@ public abstract class DateTimeUtils {
570
540
  }
571
541
 
572
542
  private static IRubyObject newDate(final ThreadContext context, final int year, final int month, final int day,
573
- final Chronology chronology) {
543
+ final ISOChronology chronology) {
574
544
  // NOTE: JRuby really needs a native date.rb until than its a bit costly going from ...
575
545
  // java.sql.Date -> allocating a DateTime proxy, help a bit by shooting at the internals
576
546
  //
@@ -607,110 +577,4 @@ public abstract class DateTimeUtils {
607
577
  return n;
608
578
  }
609
579
 
610
-
611
- private static final char[] ZEROS = {'0', '0', '0', '0', '0', '0'};
612
- private static final char[][] NUMBERS;
613
-
614
- static {
615
- // maximum value is 60 (seconds)
616
- NUMBERS = new char[60][];
617
- for (int i = 0; i < NUMBERS.length; i++) {
618
- NUMBERS[i] = ((i < 10 ? "0" : "") + Integer.toString(i)).toCharArray();
619
- }
620
- }
621
-
622
- /**
623
- * Converts a ruby timestamp to a java string, optionally with timezone and timezone adjustment
624
- * @param context
625
- * @param value the ruby value, typically a Time
626
- * @param zone DateTimeZone to adjust to, optional
627
- * @param withZone include timezone in the string?
628
- * @return timestamp as string
629
- */
630
- public static String timestampTimeToString(final ThreadContext context,
631
- final IRubyObject value, DateTimeZone zone, boolean withZone) {
632
- RubyTime timeValue = toTime(context, value);
633
- DateTime dt = timeValue.getDateTime();
634
-
635
- StringBuilder sb = new StringBuilder(36);
636
-
637
- int year = dt.getYear();
638
- if (year <= 0) {
639
- year--;
640
- } else if (zone != null) {
641
- dt = dateTimeInZone(dt, zone);
642
- year = dt.getYear();
643
- }
644
-
645
- Chronology chrono = dt.getChronology();
646
- long millis = dt.getMillis();
647
-
648
- // always use 4 digits for year to avoid short dates being misinterpreted
649
- sb.append(Math.abs(year));
650
- int lead = 4 - sb.length();
651
- if (lead > 0) sb.insert(0, ZEROS, 0, lead);
652
- sb.append('-');
653
- sb.append(NUMBERS[chrono.monthOfYear().get(millis)]);
654
- sb.append('-');
655
- sb.append(NUMBERS[chrono.dayOfMonth().get(millis)]);
656
- if (year < 0) sb.append(" BC");
657
- sb.append(' ');
658
-
659
- appendTime(sb, chrono, millis, (int) timeValue.getUSec(), withZone);
660
-
661
- return sb.toString();
662
- }
663
-
664
- /**
665
- * Converts a ruby time to a java string, optionally with timezone and timezone adjustment
666
- * @param context
667
- * @param value the ruby value, typically a Time
668
- * @param zone DateTimeZone to adjust to, optional
669
- * @param withZone include timezone in the string?
670
- * @return time as string
671
- */
672
- public static String timeString(final ThreadContext context,
673
- final IRubyObject value, DateTimeZone zone, boolean withZone) {
674
- StringBuilder sb = new StringBuilder(21);
675
- RubyTime timeValue = toTime(context, value);
676
- DateTime dt = timeValue.getDateTime();
677
- if (zone != null) dt = dateTimeInZone(dt, zone);
678
-
679
- appendTime(sb, dt.getChronology(), dt.getMillis(), (int) timeValue.getUSec(), withZone);
680
- return sb.toString();
681
- }
682
-
683
- private static void appendTime(StringBuilder sb, Chronology chrono,
684
- long millis, int usec, boolean withZone) {
685
- sb.append(NUMBERS[chrono.hourOfDay().get(millis)]);
686
- sb.append(':');
687
- sb.append(NUMBERS[chrono.minuteOfHour().get(millis)]);
688
- sb.append(':');
689
- sb.append(NUMBERS[chrono.secondOfMinute().get(millis)]);
690
-
691
- // PG has microsecond resolution. Change when nanos are required
692
- int micros = chrono.millisOfSecond().get(millis) * 1000 + usec;
693
- if (micros > 0) {
694
- sb.append('.');
695
-
696
- int len = sb.length();
697
- sb.append(micros);
698
- int lead = 6 - (sb.length() - len);
699
- if (lead > 0) sb.insert(len, ZEROS, 0, lead);
700
-
701
- for (int end = sb.length() - 1; sb.charAt(end) == '0'; end--) {
702
- sb.setLength(end);
703
- }
704
- }
705
-
706
- if (withZone) {
707
- int offset = chrono.getZone().getOffset(millis) / 1000;
708
- int absoff = Math.abs(offset);
709
- int hours = absoff / 3600;
710
- int mins = (absoff - hours * 3600) / 60;
711
-
712
- sb.append(offset < 0 ? '-' : '+');
713
- sb.append(NUMBERS[hours]).append(':').append(NUMBERS[mins]);
714
- }
715
- }
716
580
  }
@@ -52,6 +52,7 @@ public abstract class QuotingUtils {
52
52
  return quoteCharWith(context, string, value, quote, 0, 8);
53
53
  }
54
54
 
55
+ @SuppressWarnings("deprecation")
55
56
  public static RubyString quoteCharWith(
56
57
  final ThreadContext context,
57
58
  final RubyString string,
@@ -71,8 +72,8 @@ public abstract class QuotingUtils {
71
72
  new byte[realSize + newOffset + newSizeDiff],
72
73
  stringBytes.getEncoding(), false
73
74
  );
74
- quotedBytes.setBegin(newOffset);
75
- quotedBytes.setRealSize(0);
75
+ quotedBytes.begin = newOffset;
76
+ quotedBytes.realSize = 0;
76
77
  }
77
78
  quotedBytes.append(bytes, appendFrom, i - appendFrom);
78
79
  quotedBytes.append(quote).append(value); // e.g. "'" => "''"
@@ -87,6 +88,7 @@ public abstract class QuotingUtils {
87
88
  return context.runtime.newString(quotedBytes);
88
89
  }
89
90
 
91
+ @SuppressWarnings("deprecation")
90
92
  public static RubyString quoteCharAndDecorateWith(
91
93
  final ThreadContext context, final RubyString string,
92
94
  final char value, final char quote,
@@ -100,7 +102,7 @@ public abstract class QuotingUtils {
100
102
  final ByteList quoted = new ByteList(
101
103
  new byte[realSize + 2], string.getEncoding(), false
102
104
  );
103
- quoted.setRealSize(0);
105
+ quoted.begin = 0; quoted.realSize = 0;
104
106
  quoted.append(prefix);
105
107
  quoted.append(str.unsafeBytes(), str.getBegin(), realSize);
106
108
  quoted.append(suffix);
@@ -108,9 +110,8 @@ public abstract class QuotingUtils {
108
110
  }
109
111
  // we got a new string with a reserve of 1 byte front and back :
110
112
  final ByteList quoted = quotedString.getByteList();
111
- quoted.setBegin(0);
112
- quoted.unsafeBytes()[0] = prefix;
113
- quoted.setRealSize(quoted.getRealSize() + 1);
113
+ quoted.begin = 0; // setBegin invalidates
114
+ quoted.bytes[0] = prefix; quoted.realSize++;
114
115
  quoted.append(suffix);
115
116
  return quotedString;
116
117
  }
@@ -25,9 +25,12 @@ package arjdbc.util;
25
25
 
26
26
  import java.io.IOException;
27
27
  import java.io.InputStream;
28
+ import java.nio.charset.Charset;
28
29
 
29
30
  import org.jcodings.Encoding;
31
+ import org.jcodings.specific.UTF8Encoding;
30
32
  import org.jruby.Ruby;
33
+ import org.jruby.RubyEncoding;
31
34
  import org.jruby.RubyString;
32
35
  import org.jruby.util.ByteList;
33
36
 
@@ -58,6 +61,18 @@ public abstract class StringHelper {
58
61
  return RubyString.newString(runtime, new ByteList(bytes, false));
59
62
  }
60
63
 
64
+ private static final Charset ASCII_CHARSET = Charset.forName("ISO-8859-1");
65
+
66
+ public static RubyString newASCIIString(final Ruby runtime, final String str) {
67
+ final ByteList byteList = new ByteList(str.getBytes(ASCII_CHARSET), false);
68
+ return RubyString.newString(runtime, byteList);
69
+ }
70
+
71
+ public static RubyString newUTF8String(final Ruby runtime, final byte[] bytes) {
72
+ final ByteList byteList = new ByteList(bytes, false);
73
+ return RubyString.newString(runtime, byteList, UTF8Encoding.INSTANCE);
74
+ }
75
+
61
76
  public static RubyString newDefaultInternalString(final Ruby runtime, final byte[] bytes) {
62
77
  final ByteList byteList = new ByteList(bytes, false);
63
78
  Encoding enc = runtime.getDefaultInternalEncoding();
@@ -68,19 +83,18 @@ public abstract class StringHelper {
68
83
  public static RubyString newDefaultInternalString(final Ruby runtime, final CharSequence str) {
69
84
  Encoding enc = runtime.getDefaultInternalEncoding();
70
85
  if (enc == null) enc = runtime.getEncodingService().getJavaDefault();
71
- return new RubyString(runtime, runtime.getString(), str, enc);
86
+ return RubyString.newString(runtime, new ByteList(RubyEncoding.encode(str, enc.getCharset()), enc));
72
87
  }
73
88
 
74
- // NOTE: a 'better' RubyString.newInternalFromJavaExternal - to be back-ported in JRuby 9.2
75
89
  public static RubyString newDefaultInternalString(final Ruby runtime, final String str) {
76
- Encoding enc = runtime.getDefaultInternalEncoding();
77
- if (enc == null) enc = runtime.getEncodingService().getJavaDefault();
78
- return RubyString.newString(runtime, str, enc);
90
+ return RubyString.newInternalFromJavaExternal(runtime, str);
79
91
  }
80
92
 
81
93
  public static int readBytes(final ByteList output, final InputStream input)
82
94
  throws IOException {
83
- return readBytes(output, input, output.unsafeBytes().length - output.getBegin());
95
+ @SuppressWarnings("deprecation") // capacity :
96
+ final int buffSize = output.bytes.length - output.begin;
97
+ return readBytes(output, input, buffSize);
84
98
  }
85
99
 
86
100
  public static int readBytes(final ByteList output, final InputStream input, int buffSize)