001    /**
002     * Licensed to the Apache Software Foundation (ASF) under one or more
003     * contributor license agreements.  See the NOTICE file distributed with
004     * this work for additional information regarding copyright ownership.
005     * The ASF licenses this file to You under the Apache License, Version 2.0
006     * (the "License"); you may not use this file except in compliance with
007     * the License.  You may obtain a copy of the License at
008     *
009     *      http://www.apache.org/licenses/LICENSE-2.0
010     *
011     * Unless required by applicable law or agreed to in writing, software
012     * distributed under the License is distributed on an "AS IS" BASIS,
013     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014     * See the License for the specific language governing permissions and
015     * limitations under the License.
016     */
017    package org.apache.camel.component.hdfs;
018    
019    import java.io.ByteArrayOutputStream;
020    import java.io.IOException;
021    import java.io.InputStream;
022    import java.nio.ByteBuffer;
023    import javax.xml.ws.Holder;
024    
025    import org.apache.camel.RuntimeCamelException;
026    import org.apache.camel.TypeConverter;
027    import org.apache.hadoop.io.BooleanWritable;
028    import org.apache.hadoop.io.ByteWritable;
029    import org.apache.hadoop.io.BytesWritable;
030    import org.apache.hadoop.io.DoubleWritable;
031    import org.apache.hadoop.io.FloatWritable;
032    import org.apache.hadoop.io.IOUtils;
033    import org.apache.hadoop.io.IntWritable;
034    import org.apache.hadoop.io.LongWritable;
035    import org.apache.hadoop.io.NullWritable;
036    import org.apache.hadoop.io.Text;
037    import org.apache.hadoop.io.Writable;
038    
039    public class HdfsWritableFactories {
040    
041        public enum WritableType {
042            NULL {
043                @Override
044                public Class getWritableClass() {
045                    return NullWritable.class;
046                }
047            },
048    
049            BOOLEAN {
050                @Override
051                public Class getWritableClass() {
052                    return BooleanWritable.class;
053                }
054            },
055    
056            BYTE {
057                @Override
058                public Class getWritableClass() {
059                    return ByteWritable.class;
060                }
061            },
062    
063            INT {
064                @Override
065                public Class getWritableClass() {
066                    return IntWritable.class;
067                }
068            },
069    
070            FLOAT {
071                @Override
072                public Class getWritableClass() {
073                    return FloatWritable.class;
074                }
075            },
076    
077            LONG {
078                @Override
079                public Class getWritableClass() {
080                    return LongWritable.class;
081                }
082            },
083    
084            DOUBLE {
085                @Override
086                public Class getWritableClass() {
087                    return DoubleWritable.class;
088                }
089            },
090    
091            TEXT {
092                @Override
093                public Class getWritableClass() {
094                    return Text.class;
095                }
096            },
097    
098            BYTES {
099                @Override
100                public Class getWritableClass() {
101                    return BytesWritable.class;
102                }
103            };
104    
105            public abstract Class getWritableClass();
106        }
107    
108        interface HdfsWritableFactory {
109    
110            Writable create(Object value, TypeConverter typeConverter, Holder<Integer> size);
111    
112            Object read(Writable writable, Holder<Integer> size);
113        }
114    
115        public static final class HdfsNullWritableFactory implements HdfsWritableFactory {
116    
117            @Override
118            public Writable create(Object value, TypeConverter typeConverter, Holder<Integer> size) {
119                size.value = 0;
120                return NullWritable.get();
121            }
122    
123            @Override
124            public Object read(Writable writable, Holder<Integer> size) {
125                size.value = 0;
126                return null;
127            }
128        }
129    
130        public static final class HdfsByteWritableFactory implements HdfsWritableFactory {
131    
132            private static final int SIZE = 1;
133    
134            @Override
135            public Writable create(Object value, TypeConverter typeConverter, Holder<Integer> size) {
136                size.value = SIZE;
137                ByteWritable writable = new ByteWritable();
138                writable.set(typeConverter.convertTo(Byte.class, value));
139                return writable;
140            }
141    
142            @Override
143            public Object read(Writable writable, Holder<Integer> size) {
144                size.value = SIZE;
145                return ((ByteWritable) writable).get();
146            }
147        }
148    
149        public static final class HdfsBooleanWritableFactory implements HdfsWritableFactory {
150    
151            private static final int SIZE = 1;
152    
153            @Override
154            public Writable create(Object value, TypeConverter typeConverter, Holder<Integer> size) {
155                size.value = SIZE;
156                BooleanWritable writable = new BooleanWritable();
157                writable.set(typeConverter.convertTo(Boolean.class, value));
158                return writable;
159            }
160    
161            @Override
162            public Object read(Writable writable, Holder<Integer> size) {
163                size.value = SIZE;
164                return ((BooleanWritable) writable).get();
165            }
166        }
167    
168        public static final class HdfsBytesWritableFactory implements HdfsWritableFactory {
169    
170            @Override
171            public Writable create(Object value, TypeConverter typeConverter, Holder<Integer> size) {
172                BytesWritable writable = new BytesWritable();
173                ByteBuffer bb = (ByteBuffer) value;
174                writable.set(bb.array(), 0, bb.array().length);
175                size.value = bb.array().length;
176                return writable;
177            }
178    
179            @Override
180            public Object read(Writable writable, Holder<Integer> size) {
181                size.value = ((BytesWritable) writable).getLength();
182                ByteBuffer bb = ByteBuffer.allocate(size.value);
183                bb.put(((BytesWritable) writable).getBytes(), 0, size.value);
184                return bb;
185            }
186        }
187    
188        public static final class HdfsDoubleWritableFactory implements HdfsWritableFactory {
189    
190            private static final int SIZE = 8;
191    
192            @Override
193            public Writable create(Object value, TypeConverter typeConverter, Holder<Integer> size) {
194                size.value = SIZE;
195                DoubleWritable writable = new DoubleWritable();
196                writable.set(typeConverter.convertTo(Double.class, value));
197                return writable;
198            }
199    
200            @Override
201            public Object read(Writable writable, Holder<Integer> size) {
202                size.value = SIZE;
203                return ((DoubleWritable) writable).get();
204            }
205        }
206    
207        public static final class HdfsFloatWritableFactory implements HdfsWritableFactory {
208    
209            private static final int SIZE = 4;
210    
211            @Override
212            public Writable create(Object value, TypeConverter typeConverter, Holder<Integer> size) {
213                size.value = SIZE;
214                FloatWritable writable = new FloatWritable();
215                writable.set(typeConverter.convertTo(Float.class, value));
216                return writable;
217            }
218    
219            @Override
220            public Object read(Writable writable, Holder<Integer> size) {
221                size.value = SIZE;
222                return ((FloatWritable) writable).get();
223            }
224        }
225    
226        public static final class HdfsIntWritableFactory implements HdfsWritableFactory {
227    
228            private static final int SIZE = 4;
229    
230            @Override
231            public Writable create(Object value, TypeConverter typeConverter, Holder<Integer> size) {
232                size.value = SIZE;
233                IntWritable writable = new IntWritable();
234                writable.set(typeConverter.convertTo(Integer.class, value));
235                return writable;
236            }
237    
238            @Override
239            public Object read(Writable writable, Holder<Integer> size) {
240                size.value = SIZE;
241                return ((IntWritable) writable).get();
242            }
243        }
244    
245        public static final class HdfsLongWritableFactory implements HdfsWritableFactory {
246    
247            private static final int SIZE = 8;
248    
249            @Override
250            public Writable create(Object value, TypeConverter typeConverter, Holder<Integer> size) {
251                size.value = SIZE;
252                LongWritable writable = new LongWritable();
253                writable.set(typeConverter.convertTo(Long.class, value));
254                return writable;
255            }
256    
257            @Override
258            public Object read(Writable writable, Holder<Integer> size) {
259                size.value = SIZE;
260                return ((LongWritable) writable).get();
261            }
262        }
263    
264        public static final class HdfsTextWritableFactory implements HdfsWritableFactory {
265    
266            @Override
267            public Writable create(Object value, TypeConverter typeConverter, Holder<Integer> size) {
268                Text writable = new Text();
269                writable.set(typeConverter.convertTo(String.class, value));
270                size.value = writable.getBytes().length;
271                return writable;
272            }
273    
274            @Override
275            public Object read(Writable writable, Holder<Integer> size) {
276                size.value = ((Text) writable).getLength();
277                return writable.toString();
278            }
279        }
280    
281        public static final class HdfsObjectWritableFactory implements HdfsWritableFactory {
282    
283            @Override
284            public Writable create(Object value, TypeConverter typeConverter, Holder<Integer> size) {
285                InputStream  is = null;
286                try {
287                    is = typeConverter.convertTo(InputStream.class, value);
288                    ByteArrayOutputStream bos = new ByteArrayOutputStream();
289                    IOUtils.copyBytes(is, bos, HdfsConstants.DEFAULT_BUFFERSIZE, false);
290                    BytesWritable writable = new BytesWritable();
291                    writable.set(bos.toByteArray(), 0, bos.toByteArray().length);
292                    size.value = bos.toByteArray().length;
293                    return writable;
294                } catch (IOException ex) {
295                    throw new RuntimeCamelException(ex);
296                } finally {
297                    if (is != null) {
298                        try {
299                            is.close();
300                        } catch (IOException e) {
301                            throw new RuntimeException("Error closing stream", e);
302                        }
303                    }
304                }
305            }
306    
307            @Override
308            public Object read(Writable writable, Holder<Integer> size) {
309                size.value = 0;
310                return null;
311            }
312        }
313    
314    }