KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jruby > RubyIconv


1 /***** BEGIN LICENSE BLOCK *****
2  * Version: CPL 1.0/GPL 2.0/LGPL 2.1
3  *
4  * The contents of this file are subject to the Common Public
5  * License Version 1.0 (the "License"); you may not use this file
6  * except in compliance with the License. You may obtain a copy of
7  * the License at http://www.eclipse.org/legal/cpl-v10.html
8  *
9  * Software distributed under the License is distributed on an "AS
10  * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
11  * implied. See the License for the specific language governing
12  * rights and limitations under the License.
13  *
14  * Copyright (C) 2006 Thomas E Enebo <enebo@acm.org>
15  *
16  * Alternatively, the contents of this file may be used under the terms of
17  * either of the GNU General Public License Version 2 or later (the "GPL"),
18  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
19  * in which case the provisions of the GPL or the LGPL are applicable instead
20  * of those above. If you wish to allow use of your version of this file only
21  * under the terms of either the GPL or the LGPL, and not to allow others to
22  * use your version of this file under the terms of the CPL, indicate your
23  * decision by deleting the provisions above and replace them with the notice
24  * and other provisions required by the GPL or the LGPL. If you do not delete
25  * the provisions above, a recipient may use your version of this file under
26  * the terms of any one of the CPL, the GPL or the LGPL.
27  ***** END LICENSE BLOCK *****/

28 package org.jruby;
29
30 import java.nio.ByteBuffer JavaDoc;
31 import java.nio.CharBuffer JavaDoc;
32 import java.nio.charset.CharacterCodingException JavaDoc;
33 import java.nio.charset.Charset JavaDoc;
34 import java.nio.charset.CharsetDecoder JavaDoc;
35 import java.nio.charset.CharsetEncoder JavaDoc;
36 import java.nio.charset.CodingErrorAction JavaDoc;
37 import java.nio.charset.UnmappableCharacterException JavaDoc;
38 import java.nio.charset.UnsupportedCharsetException JavaDoc;
39
40 import org.jruby.runtime.Block;
41 import org.jruby.runtime.CallbackFactory;
42 import org.jruby.runtime.ObjectAllocator;
43 import org.jruby.runtime.builtin.IRubyObject;
44
45 import org.jruby.util.ByteList;
46
47 public class RubyIconv extends RubyObject {
48     public RubyIconv(Ruby runtime, RubyClass type) {
49         super(runtime, type);
50     }
51     
52     private static ObjectAllocator ICONV_ALLOCATOR = new ObjectAllocator() {
53         public IRubyObject allocate(Ruby runtime, RubyClass klass) {
54             return new RubyIconv(runtime, klass);
55         }
56     };
57
58     public static void createIconv(Ruby runtime) {
59         RubyClass iconvClass = runtime.defineClass("Iconv", runtime.getObject(), ICONV_ALLOCATOR);
60
61         RubyClass argumentError = runtime.getClass("ArgumentError");
62         iconvClass.defineClassUnder("IllegalSequence", argumentError, argumentError.getAllocator());
63         iconvClass.defineClassUnder("InvalidCharacter", argumentError, argumentError.getAllocator());
64         iconvClass.defineClassUnder("InvalidEncoding", argumentError, argumentError.getAllocator());
65         
66         CallbackFactory callbackFactory = runtime.callbackFactory(RubyIconv.class);
67
68         iconvClass.getMetaClass().defineFastMethod("iconv", callbackFactory.getOptSingletonMethod("iconv"));
69         iconvClass.getMetaClass().defineFastMethod("conv", callbackFactory.getOptSingletonMethod("conv"));
70         
71         iconvClass.defineMethod("initialize", callbackFactory.getOptMethod("initialize"));
72         //iconvClass.defineMethod("iconv", callbackFactory.getOptMethod("iconv"));
73

74         // FIXME: JRUBY-310: Add all other iconv methods...Sopen, Iclose, Iiconv
75
// FIXME: JRUBY-309: Implement IConv Exception classes (e.g. Iconv::IllegalSequence and friends)
76
}
77
78     // FIXME: I believe that we are suppose to keep partial character contents between calls
79
// so that we can pass in arbitrary chunks of bytes. Charset Encoder needs to be able to
80
// handle this or we need to be able detect it somehow.
81
/*
82     public IRubyObject iconv(IRubyObject[] args) {
83         RubyArray array = getRuntime().newArray();
84         
85         for (int i = 0; i < args.length; i++) {
86             try {
87                 array.append(convert(fromEncoding, toEncoding, args[i].convertToString()));
88             } catch (UnsupportedEncodingException e) {
89                 throw getRuntime().newErrnoEINVALError("iconv(" + toEncoding + ", " +
90                         fromEncoding + ", " + args[i] + ")");
91             }
92         }
93
94         return array;
95     }
96     */

97     
98     public IRubyObject initialize(IRubyObject[] args, Block unusedBlock) {
99         checkArgumentCount(args, 2, 2);
100         
101         //toEncoding = args[0].convertToString().toString();
102
//fromEncoding = args[1].convertToString().toString();
103

104         return this;
105     }
106
107     public static IRubyObject iconv(IRubyObject recv, IRubyObject[] args, Block unusedBlock) {
108         return convertWithArgs(recv, args, "iconv");
109     }
110     
111     public static IRubyObject conv(IRubyObject recv, IRubyObject[] args, Block unusedBlock) {
112         return convertWithArgs(recv, args, "conv").join(recv.getRuntime().newString(""));
113     }
114     
115     public static RubyArray convertWithArgs(IRubyObject recv, IRubyObject[] args, String JavaDoc function) {
116         recv.checkArgumentCount(args, 3, -1);
117
118         String JavaDoc fromEncoding = args[1].convertToString().toString();
119         String JavaDoc toEncoding = args[0].convertToString().toString();
120         RubyArray array = recv.getRuntime().newArray();
121         
122         for (int i = 2; i < args.length; i++) {
123             array.append(convert2(fromEncoding, toEncoding, args[i].convertToString()));
124         }
125
126         return array;
127     }
128     
129     /*
130     private static IRubyObject convert(String fromEncoding, String toEncoding, RubyString original)
131         throws UnsupportedEncodingException {
132         // Get all bytes from PLAIN string pretend they are not encoded in any way.
133         byte[] string = original.getBytes();
134         // Now create a string pretending it is from fromEncoding
135         string = new String(string, fromEncoding).getBytes(toEncoding);
136         // Finally recode back to PLAIN
137         return RubyString.newString(original.getRuntime(), string);
138     }
139     */

140
141     // FIXME: We are assuming that original string will be raw bytes. If -Ku is provided
142
// this will not be true, but that is ok for now. Deal with that when someone needs it.
143
private static IRubyObject convert2(String JavaDoc fromEncoding, String JavaDoc toEncoding, RubyString original) {
144         try {
145             // Get all bytes from string and pretend they are not encoded in any way.
146
byte[] bytes = original.getBytes();
147             ByteBuffer JavaDoc buf = ByteBuffer.wrap(bytes);
148
149             CharsetDecoder JavaDoc decoder = Charset.forName(fromEncoding).newDecoder();
150             
151             decoder.onUnmappableCharacter(CodingErrorAction.REPORT);
152             CharBuffer JavaDoc cbuf = decoder.decode(buf);
153             CharsetEncoder JavaDoc encoder = Charset.forName(toEncoding).newEncoder();
154             
155             encoder.onUnmappableCharacter(CodingErrorAction.REPORT);
156             buf = encoder.encode(cbuf);
157             byte[] arr = buf.array();
158             return RubyString.newString(original.getRuntime(), new ByteList(arr,0,buf.limit()));
159         } catch (UnsupportedCharsetException JavaDoc e) {
160             throw original.getRuntime().newInvalidEncoding("invalid encoding");
161         } catch (UnmappableCharacterException JavaDoc e) {
162         } catch (CharacterCodingException JavaDoc e) {
163         }
164         return original.getRuntime().getNil();
165     }
166 }
167
Popular Tags