KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > cocoon > components > modules > input > DigestMetaModule


1 /*
2  * Copyright 1999-2004 The Apache Software Foundation.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16 package org.apache.cocoon.components.modules.input;
17
18 import org.apache.avalon.framework.configuration.Configuration;
19 import org.apache.avalon.framework.configuration.ConfigurationException;
20 import org.apache.avalon.framework.thread.ThreadSafe;
21
22 import org.apache.cocoon.util.HashMap;
23
24 import java.net.URLEncoder JavaDoc;
25 import java.security.MessageDigest JavaDoc;
26 import java.security.NoSuchAlgorithmException JavaDoc;
27 import java.security.NoSuchProviderException JavaDoc;
28 import java.util.Iterator JavaDoc;
29 import java.util.Map JavaDoc;
30 import java.io.UnsupportedEncodingException JavaDoc;
31
32 /** Meta module that obtains values from other module and returns
33  * message digest of value. Very useful for storing and checking
34  * passwords. Input module configured through nested element
35  * "input-module", message digest algorithm, security provider, salt,
36  * and URL encoded output configurable through elements "algorithm",
37  * "provider", "salt", "encode". Defaults are "sha", null, "salt", and
38  * "false". Available value for encode are "none" (returns byte[]),
39  * "string" (return hash as string), "url" (returns url encoded
40  * string), "hex" (returns string of hex values).
41  *
42  * @author <a HREF="mailto:haul@apache.org">Christian Haul</a>
43  * @version CVS $Id: DigestMetaModule.java 30932 2004-07-29 17:35:38Z vgritsenko $
44  */

45 public class DigestMetaModule extends AbstractMetaModule implements ThreadSafe {
46
47     private String JavaDoc defaultAlgorithm = "SHA";
48     private String JavaDoc defaultProvider = null;
49     private String JavaDoc defaultSalt = "salt";
50     private String JavaDoc defaultEncode = "false";
51
52     /** output encoding none */
53     static final int ENCODING_NONE = 0;
54     /** output encoding url encoding */
55     static final int ENCODING_STR = 1;
56     /** output encoding hex */
57     static final int ENCODING_URL = 2;
58     /** output encoding hex */
59     static final int ENCODING_HEX = 3;
60
61     private static final HashMap encodingNames;
62     /** setup mapping tables */
63     static {
64         HashMap names = new HashMap();
65         names.put("false", new Integer JavaDoc(ENCODING_NONE));
66         names.put("no", new Integer JavaDoc(ENCODING_NONE));
67         names.put("none", new Integer JavaDoc(ENCODING_NONE));
68         names.put("string", new Integer JavaDoc(ENCODING_STR));
69         names.put("yes", new Integer JavaDoc(ENCODING_URL));
70         names.put("true", new Integer JavaDoc(ENCODING_URL));
71         names.put("hex", new Integer JavaDoc(ENCODING_HEX));
72         encodingNames = names;
73         names = null;
74     }
75
76
77     public void configure(Configuration config) throws ConfigurationException {
78
79         this.inputConf = config.getChild("input-module");
80         this.defaultInput = this.inputConf.getAttribute("name", this.defaultInput);
81
82         this.defaultAlgorithm = this.inputConf.getAttribute("algorithm",this.defaultAlgorithm);
83         this.defaultProvider = this.inputConf.getAttribute("provider",this.defaultProvider);
84         this.defaultSalt = this.inputConf.getAttribute("salt",this.defaultSalt);
85         this.defaultEncode = this.inputConf.getAttribute("encode","false");
86
87         // preferred
88
this.defaultAlgorithm = config.getChild("algorithm").getValue(this.defaultAlgorithm);
89         this.defaultProvider = config.getChild("provider").getValue(this.defaultProvider);
90         this.defaultSalt = config.getChild("salt").getValue(this.defaultSalt);
91         this.defaultEncode = config.getChild("encode").getValue(this.defaultEncode);
92
93         if (encodingNames.get(this.defaultEncode) == null) {
94             if (getLogger().isErrorEnabled())
95                 getLogger().error("Requested encoding is unknown: "+this.defaultEncode);
96             this.defaultEncode="false";
97         }
98     }
99
100
101     public Object JavaDoc getAttribute( String JavaDoc name, Configuration modeConf, Map objectModel )
102         throws ConfigurationException {
103
104         if (!this.initialized) {
105             this.lazy_initialize();
106         }
107         if (this.defaultInput == null) {
108             if (getLogger().isWarnEnabled())
109                 getLogger().warn("No input module given. FAILING");
110             return null;
111         }
112
113         // obtain correct configuration objects
114
// default vs dynamic
115
Configuration inputConfig = null;
116         String JavaDoc inputName=null;
117         String JavaDoc algorithm = this.defaultAlgorithm;
118         String JavaDoc provider = this.defaultProvider;
119         String JavaDoc salt = this.defaultSalt;
120         int encode = ((Integer JavaDoc) encodingNames.get(this.defaultEncode)).intValue();
121         if (modeConf!=null) {
122             inputName = modeConf.getChild("input-module").getAttribute("name",null);
123             if (inputName != null) {
124                 inputConfig = modeConf.getChild("input-module");
125             }
126             // read necessary parameters
127
algorithm = modeConf.getAttribute("algorithm", algorithm);
128             provider = modeConf.getAttribute("provider", provider);
129             salt = modeConf.getAttribute("salt", salt);
130             encode = ((Integer JavaDoc) encodingNames.get(modeConf.getAttribute("encode", this.defaultEncode))).intValue();
131
132             // preferred
133
algorithm = modeConf.getChild("algorithm").getValue(algorithm);
134             provider = modeConf.getChild("provider").getValue(provider);
135             salt = modeConf.getChild("salt").getValue(salt);
136             encode = ((Integer JavaDoc) encodingNames.get(modeConf.getChild("encode").getValue(this.defaultEncode))).intValue();
137         }
138
139
140         Object JavaDoc value = getValue(name, objectModel,
141                                 this.input, this.defaultInput, this.inputConf,
142                                 null, inputName, inputConfig);
143         
144         if (value != null)
145             try {
146                 MessageDigest JavaDoc md = (provider==null ? MessageDigest.getInstance(algorithm) :
147                                     MessageDigest.getInstance(algorithm,provider));
148                 
149                 md.update((salt+(value instanceof String JavaDoc? (String JavaDoc)value : value.toString())).getBytes());
150                 return encodeByteArray(md.digest(),encode);
151
152             } catch (NoSuchAlgorithmException JavaDoc nsae) {
153                 if (getLogger().isWarnEnabled())
154                     getLogger().warn("A problem occurred acquiring digest algorithm '" + algorithm
155                                      + (provider==null?"":"' from '"+provider) +"': " + nsae.getMessage());
156             } catch (NoSuchProviderException JavaDoc nspe) {
157                 if (getLogger().isWarnEnabled())
158                     getLogger().warn("A problem occurred acquiring digest algorithm '" + algorithm
159                                      + (provider==null?"":"' from '"+provider) +"': " + nspe.getMessage());
160             }
161
162         return null;
163     }
164
165
166     public Iterator JavaDoc getAttributeNames( Configuration modeConf, Map objectModel )
167         throws ConfigurationException {
168
169          if (!this.initialized) {
170              this.lazy_initialize();
171         }
172         if (this.defaultInput == null) {
173             if (getLogger().isWarnEnabled())
174                 getLogger().warn("No input module given. FAILING");
175             return null;
176         }
177
178         // obtain correct configuration objects
179
// default vs dynamic
180
Configuration inputConfig = null;
181         String JavaDoc inputName=null;
182         if (modeConf!=null) {
183             inputName = modeConf.getChild("input-module").getAttribute("name",null);
184             if (inputName != null) {
185                 inputConfig = modeConf.getChild("input-module");
186             }
187         }
188
189         Iterator JavaDoc names = getNames(objectModel,
190                                   this.input, this.defaultInput, this.inputConf,
191                                   null, inputName, inputConfig);
192         
193         return names;
194
195    }
196
197
198     public Object JavaDoc[] getAttributeValues( String JavaDoc name, Configuration modeConf, Map objectModel )
199         throws ConfigurationException {
200
201         if (!this.initialized) {
202             this.lazy_initialize();
203         }
204         if (this.defaultInput == null) {
205             if (getLogger().isWarnEnabled())
206                 getLogger().warn("No input module given. FAILING");
207             return null;
208         }
209
210         // obtain correct configuration objects
211
// default vs dynamic
212
Configuration inputConfig = null;
213         String JavaDoc inputName=null;
214         String JavaDoc algorithm = this.defaultAlgorithm;
215         String JavaDoc provider = this.defaultProvider;
216         String JavaDoc salt = this.defaultSalt;
217         int encode = ((Integer JavaDoc) encodingNames.get(this.defaultEncode)).intValue();
218         if (modeConf!=null) {
219             inputName = modeConf.getChild("input-module").getAttribute("name",null);
220             if (inputName != null) {
221                 inputConfig = modeConf.getChild("input-module");
222             }
223             // read necessary parameters
224
algorithm = modeConf.getAttribute("algorithm", algorithm);
225             provider = modeConf.getAttribute("provider" , provider );
226             salt = modeConf.getAttribute("salt" , salt );
227             encode = ((Integer JavaDoc) encodingNames.get(modeConf.getAttribute("encode" , this.defaultEncode))).intValue();
228
229             // preferred
230
algorithm = modeConf.getChild("algorithm").getValue(algorithm);
231             provider = modeConf.getChild("provider").getValue(provider);
232             salt = modeConf.getChild("salt").getValue(salt);
233             encode = ((Integer JavaDoc) encodingNames.get(modeConf.getChild("encode").getValue(this.defaultEncode))).intValue();
234         }
235
236         Object JavaDoc[] values = getValues(name, objectModel,
237                                     this.input, this.defaultInput, this.inputConf,
238                                     null, inputName, inputConfig);
239         Object JavaDoc[] result = null;
240
241         if (values != null) {
242             try {
243                 MessageDigest JavaDoc md = (provider==null ? MessageDigest.getInstance(algorithm) :
244                                     MessageDigest.getInstance(algorithm,provider));
245                 
246                 result = new Object JavaDoc[values.length];
247                 for (int i=0; i<values.length; i++) {
248                     md.update((salt + (values[i] instanceof String JavaDoc? (String JavaDoc)values[i] :
249                                        values[i].toString())).getBytes());
250                     result[i] = encodeByteArray(md.digest(), encode);
251                 }
252                 return result;
253             } catch (NoSuchAlgorithmException JavaDoc nsae) {
254                 if (getLogger().isWarnEnabled())
255                     getLogger().warn("A problem occurred acquiring digest algorithm '" + algorithm
256                                      + (provider==null?"":"' from '"+provider) +"': " + nsae.getMessage());
257             } catch (NoSuchProviderException JavaDoc nspe) {
258                 if (getLogger().isWarnEnabled())
259                     getLogger().warn("A problem occurred acquiring digest algorithm '" + algorithm
260                                      + (provider==null?"":"' from '"+provider) +"': " + nspe.getMessage());
261             }
262         }
263         return result;
264     }
265
266
267     /**
268      * Create the output representation.
269      * @param b a <code>byte[]</code>
270      * @param encode an <code>int</code>, one of {@link #ENCODING_NONE},{@link #ENCODING_URL},{@link #ENCODING_HEX}
271      * @return an <code>Object</code>
272      */

273     Object JavaDoc encodeByteArray(byte[] b, int encode) {
274         Object JavaDoc result = null;
275         switch(encode) {
276         case ENCODING_HEX:
277             result = byte2Hex(b);
278             break;
279         case ENCODING_STR:
280             try {
281                 result = new String JavaDoc(b, "UTF-8");
282             } catch (UnsupportedEncodingException JavaDoc uee) {
283                 if (getLogger().isErrorEnabled())
284                     getLogger().error("UTF-8 not supported -- cannot convert message digest to String.");
285             }
286             break;
287         case ENCODING_URL:
288             try {
289                 String JavaDoc str = new String JavaDoc(b, "UTF-8");
290                 result = URLEncoder.encode(str);
291             } catch (UnsupportedEncodingException JavaDoc uee) {
292                 if (getLogger().isErrorEnabled())
293                     getLogger().error("UTF-8 not supported -- cannot convert message digest to String.");
294             }
295             break;
296         case ENCODING_NONE:
297             // nothing to do
298
break;
299         default:
300             // should not happen
301
}
302         return result;
303     }
304
305     /**
306      * Create a hex representation of a byte array.
307      *
308      * @param b a <code>byte[]</code> value
309      * @return a <code>String</code> value
310      */

311     static String JavaDoc byte2Hex ( byte[] b ) {
312         StringBuffer JavaDoc sb = new StringBuffer JavaDoc( b.length * 2 );
313         for ( int i=0 ; i < b.length ; i++ ) {
314             sb.append( hexChar [ ( b[i] & 0xf0 ) >>> 4 ] ) ;
315             sb.append( hexChar [ ( b[i] & 0x0f ) ] ) ;
316         }
317         return sb.toString() ;
318     }
319
320
321     /**
322      * hex digits lookup table
323      */

324     static char[] hexChar = {
325         '0' , '1' , '2' , '3' ,
326         '4' , '5' , '6' , '7' ,
327         '8' , '9' , 'a' , 'b' ,
328         'c' , 'd' , 'e' , 'f'
329     };
330
331 }
332
Popular Tags