View Javadoc

1   /*
2    * Copyright (c) 2004 International Decision Systems, Inc.  All Rights Reserved.
3    *
4    * By using this Software, You acknowledge that the Software is a valuable asset
5    * and trade secret of either International Decision Systems, Inc. ("IDSI") or a
6    * third party supplier of IDSI and constitutes confidential and proprietary
7    * information.
8    *
9    * NEITHER IDSI NOR ANY AGENT OR PERSON ACTING FOR OR WITH IDSI HAS MADE OR DOES
10   * MAKE ANY STATEMENTS, AFFIRMATIONS, REPRESENTATIONS OR WARRANTIES WHATSOEVER
11   * TO YOU, WHETHER EXPRESS OR IMPLIED, AS TO THE SOFTWARE, THE QUALITY OR
12   * CONDITION OF THE SOFTWARE, OR THE OPERATING CHARACTERISTICS OR RELIABILITY OF
13   * THE SOFTWARE, OR ITS SUITABILITY FOR ANY GENERAL OR PARTICULAR PURPOSE, OR AS
14   * TO ANY OTHER MATTER WHATSOEVER; ANY AND ALL OTHER WARRANTIES INCLUDING
15   * WITHOUT LIMITATION ANY WARRANTIES IMPLIED BY LAW, SUCH AS THE IMPLIED
16   * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND TITLE,
17   * USE AND NON-INFRINGEMENT; ARE HEREBY EXPRESSLY DISCLAIMED AND EXCLUDED.
18  */
19  package net.sourceforge.addam.impexp;
20  
21  import org.apache.commons.codec.binary.Base64;
22  import org.apache.tools.ant.BuildException;
23  
24  import java.lang.reflect.Constructor;
25  import java.lang.reflect.Method;
26  import java.util.HashMap;
27  import java.util.Map;
28  import java.sql.Blob;
29  import java.sql.SQLException;
30  import java.io.InputStream;
31  
32  /**
33   * This class defines the codec standard used for data import/export.
34   * The implementations are private.
35   *
36   * @author TIM3
37   * @since Feb 17, 2005 12:47:30 PM
38   */
39  public abstract class DataCodec {
40  
41      abstract public String encode(Object o);
42  
43      abstract public Object decode(String s);
44  
45      static final Map decoders = new HashMap();
46  
47      static DataCodec getCodec(String className) throws NoSuchCodec {
48          DataCodec decoder = (DataCodec) decoders.get(className);
49          final Class STRINGPARAM[] = {java.lang.String.class};
50          if (decoder == null) {
51              // prefer standard java timestamp
52              if (className.equals("oracle.sql.TIMESTAMP")) {
53                  className = "java.sql.Timestamp";
54              }
55              if (className.equals("byte[]")) {
56                  return new ByteArrayCodec();
57              } else if (className.equals("oracle.sql.BLOB")) {
58                  return new BlobCodec();
59              } else  if (className.equals("java.sql.Blob")) {
60                  return new BlobCodec();
61              } else {
62                  Class theClass = null;
63                  Constructor constructor = null;
64                  Method valueOfMethod = null;
65  
66                  try {
67                      theClass = Class.forName(className);
68                  } catch (ClassNotFoundException e) {
69                      throw new NoSuchCodec(className);
70                  }
71  
72                  try {
73                      constructor = theClass.getConstructor(STRINGPARAM);
74                  } catch (NoSuchMethodException e) {
75                      // ignore constructor exception, try for static valueOf
76                  }
77  
78                  if (constructor == null) {
79                      try {
80                          valueOfMethod = theClass.getMethod("valueOf", STRINGPARAM);
81                      } catch (NoSuchMethodException e) {
82                          throw new NoSuchCodec(className);
83                      }
84                      decoder = new StandardCodec(valueOfMethod);
85                  } else {
86                      decoder = new StandardCodec(constructor);
87                  }
88              }
89          }
90          return decoder;
91      }
92  
93      // uses Base64 encoding to encode/decode a byte array
94      static class BlobCodec extends DataCodec {
95  
96          public String encode(Object o) {
97              Blob b = (Blob)o;
98              String result;
99              try {
100                 if (b.length() > (1024*1024)) {
101                     throw new BuildException("Blob is larger than 1 meg");
102                 }
103                 byte byteBuf[] = new byte[(int)b.length()];
104                 InputStream s = b.getBinaryStream();
105                 s.read(byteBuf);
106                 byte[] encodedBytes = Base64.encodeBase64(byteBuf);
107                 result = new String(encodedBytes);
108             } catch (Exception e) {
109                 throw new BuildException(e);
110             }
111             return result;
112         }
113 
114         public Object decode(String s) {
115             byte[] decodedBytes = Base64.decodeBase64(s.getBytes());
116             return decodedBytes;
117         }
118     }
119 
120     // uses Base64 encoding to encode/decode a byte array
121     static class ByteArrayCodec extends DataCodec {
122 
123         public String encode(Object o) {
124             byte[] encodedBytes = Base64.encodeBase64((byte[]) o);
125             return new String(encodedBytes);
126         }
127 
128         public Object decode(String s) {
129             byte[] decodedBytes = Base64.decodeBase64(s.getBytes());
130             return decodedBytes;
131         }
132     }
133 
134     // relies on a static valueOf() and instance "toString()" methods
135     static class StandardCodec extends DataCodec {
136 
137         final Constructor constructor;
138         final Method valueOfMethod;
139 
140         StandardCodec(Constructor constructor) {
141             this.constructor = constructor;
142             this.valueOfMethod = null;
143         }
144 
145         StandardCodec(Method valueOfMethod) {
146             this.valueOfMethod = valueOfMethod;
147             this.constructor = null;
148         }
149 
150         public String encode(Object o) {
151             return o == null ? "" : o.toString();
152         }
153 
154         public Object decode(String s) {
155             Object result = null;
156 
157             // return null for empty strings
158             if (s != null && s.length() > 0) {
159                 Object args[] = {s};
160                 try {
161                     if (constructor != null) {
162                         // try the constructor
163                         result = constructor.newInstance(args);
164                     } else if (valueOfMethod != null) {
165                         // when invoking static method, use null for the object
166                         result = valueOfMethod.invoke(null, args);
167                     } else {
168                         // probably a clob... not much we can do but return the string
169                         result = s;
170                     }
171                 } catch (Exception e) {
172                     e.printStackTrace();
173                     throw new BuildException(e);
174                 }
175             }
176 
177             return result;
178         }
179 
180 
181     }
182 
183     static class NoSuchCodec extends Exception {
184         NoSuchCodec(String className) {
185             super("no decoder for class " + className + " could be found");
186         }
187     }
188 }