KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jvyamlb > SafeConstructorImpl


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) 2007 Ola Bini <ola@ologix.com>
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.jvyamlb;
29
30 import java.io.FileInputStream JavaDoc;
31 import java.io.InputStream JavaDoc;
32
33 import java.util.Calendar JavaDoc;
34 import java.util.HashMap JavaDoc;
35 import java.util.HashSet JavaDoc;
36 import java.util.Iterator JavaDoc;
37 import java.util.List JavaDoc;
38 import java.util.Map JavaDoc;
39 import java.util.Set JavaDoc;
40
41 import java.util.regex.Matcher JavaDoc;
42 import java.util.regex.Pattern JavaDoc;
43
44 import org.jvyamlb.nodes.Node;
45
46 import org.jvyamlb.util.Base64Coder;
47
48 import org.jruby.util.ByteList;
49
50 /**
51  * @author <a HREF="mailto:ola.bini@ki.se">Ola Bini</a>
52  */

53 public class SafeConstructorImpl extends BaseConstructorImpl {
54     private final static Map JavaDoc yamlConstructors = new HashMap JavaDoc();
55     private final static Map JavaDoc yamlMultiConstructors = new HashMap JavaDoc();
56     private final static Map JavaDoc yamlMultiRegexps = new HashMap JavaDoc();
57     public YamlConstructor getYamlConstructor(final Object JavaDoc key) {
58         YamlConstructor mine = (YamlConstructor)yamlConstructors.get(key);
59         if(mine == null) {
60             mine = super.getYamlConstructor(key);
61         }
62         return mine;
63     }
64
65     public YamlMultiConstructor getYamlMultiConstructor(final Object JavaDoc key) {
66         YamlMultiConstructor mine = (YamlMultiConstructor)yamlMultiConstructors.get(key);
67         if(mine == null) {
68             mine = super.getYamlMultiConstructor(key);
69         }
70         return mine;
71     }
72
73     public Pattern JavaDoc getYamlMultiRegexp(final Object JavaDoc key) {
74         Pattern JavaDoc mine = (Pattern JavaDoc)yamlMultiRegexps.get(key);
75         if(mine == null) {
76             mine = super.getYamlMultiRegexp(key);
77         }
78         return mine;
79     }
80
81     public Set JavaDoc getYamlMultiRegexps() {
82         final Set JavaDoc all = new HashSet JavaDoc(super.getYamlMultiRegexps());
83         all.addAll(yamlMultiRegexps.keySet());
84         return all;
85     }
86
87     public static void addConstructor(final String JavaDoc tag, final YamlConstructor ctor) {
88         yamlConstructors.put(tag,ctor);
89     }
90
91     public static void addMultiConstructor(final String JavaDoc tagPrefix, final YamlMultiConstructor ctor) {
92         yamlMultiConstructors.put(tagPrefix,ctor);
93         yamlMultiRegexps.put(tagPrefix,Pattern.compile("^"+tagPrefix));
94     }
95
96     public SafeConstructorImpl(final Composer composer) {
97         super(composer);
98     }
99
100     private static ByteList into(String JavaDoc v) {
101         return new ByteList(v.getBytes(),false);
102     }
103
104     private final static Map JavaDoc BOOL_VALUES = new HashMap JavaDoc();
105     static {
106         BOOL_VALUES.put(into("yes"),Boolean.TRUE);
107         BOOL_VALUES.put(into("Yes"),Boolean.TRUE);
108         BOOL_VALUES.put(into("YES"),Boolean.TRUE);
109         BOOL_VALUES.put(into("no"),Boolean.FALSE);
110         BOOL_VALUES.put(into("No"),Boolean.FALSE);
111         BOOL_VALUES.put(into("NO"),Boolean.FALSE);
112         BOOL_VALUES.put(into("true"),Boolean.TRUE);
113         BOOL_VALUES.put(into("True"),Boolean.TRUE);
114         BOOL_VALUES.put(into("TRUE"),Boolean.TRUE);
115         BOOL_VALUES.put(into("false"),Boolean.FALSE);
116         BOOL_VALUES.put(into("False"),Boolean.FALSE);
117         BOOL_VALUES.put(into("FALSE"),Boolean.FALSE);
118         BOOL_VALUES.put(into("on"),Boolean.TRUE);
119         BOOL_VALUES.put(into("On"),Boolean.TRUE);
120         BOOL_VALUES.put(into("ON"),Boolean.TRUE);
121         BOOL_VALUES.put(into("off"),Boolean.FALSE);
122         BOOL_VALUES.put(into("Off"),Boolean.FALSE);
123         BOOL_VALUES.put(into("OFF"),Boolean.FALSE);
124     }
125
126     public static Object JavaDoc constructYamlNull(final Constructor ctor, final Node node) {
127         return null;
128     }
129     
130     public static Object JavaDoc constructYamlBool(final Constructor ctor, final Node node) {
131         final Object JavaDoc val = ctor.constructScalar(node);
132         return BOOL_VALUES.get(val);
133     }
134
135     public static Object JavaDoc constructYamlOmap(final Constructor ctor, final Node node) {
136         return ctor.constructPairs(node);
137     }
138
139     public static Object JavaDoc constructYamlPairs(final Constructor ctor, final Node node) {
140         return constructYamlOmap(ctor,node);
141     }
142
143     public static Object JavaDoc constructYamlSet(final Constructor ctor, final Node node) {
144         return ((Map JavaDoc)ctor.constructMapping(node)).keySet();
145     }
146
147     public static Object JavaDoc constructYamlStr(final Constructor ctor, final Node node) {
148         final ByteList value = (ByteList)ctor.constructScalar(node);
149         return value.length() == 0 ? (ByteList)null : value;
150     }
151
152     public static Object JavaDoc constructYamlSeq(final Constructor ctor, final Node node) {
153         return ctor.constructSequence(node);
154     }
155
156     public static Object JavaDoc constructYamlMap(final Constructor ctor, final Node node) {
157         return ctor.constructMapping(node);
158     }
159
160     public static Object JavaDoc constructUndefined(final Constructor ctor, final Node node) {
161         throw new ConstructorException(null,"could not determine a constructor for the tag " + node.getTag(),null);
162     }
163
164     private final static Pattern JavaDoc TIMESTAMP_REGEXP = Pattern.compile("^([0-9][0-9][0-9][0-9])-([0-9][0-9]?)-([0-9][0-9]?)(?:(?:[Tt]|[ \t]+)([0-9][0-9]?):([0-9][0-9]):([0-9][0-9])(?:\\.([0-9]*))?(?:[ \t]*(Z|([-+][0-9][0-9]?)(?::([0-9][0-9])?)?))?)?$");
165     private final static Pattern JavaDoc YMD_REGEXP = Pattern.compile("^([0-9][0-9][0-9][0-9])-([0-9][0-9]?)-([0-9][0-9]?)$");
166     public static Object JavaDoc constructYamlTimestamp(final Constructor ctor, final Node node) {
167         Matcher JavaDoc match = YMD_REGEXP.matcher(node.getValue().toString());
168         if(match.matches()) {
169             final String JavaDoc year_s = match.group(1);
170             final String JavaDoc month_s = match.group(2);
171             final String JavaDoc day_s = match.group(3);
172             final Calendar JavaDoc cal = Calendar.getInstance();
173             cal.clear();
174             if(year_s != null) {
175                 cal.set(Calendar.YEAR,Integer.parseInt(year_s));
176             }
177             if(month_s != null) {
178                 cal.set(Calendar.MONTH,Integer.parseInt(month_s)-1); // Java's months are zero-based...
179
}
180             if(day_s != null) {
181                 cal.set(Calendar.DAY_OF_MONTH,Integer.parseInt(day_s));
182             }
183             return cal.getTime();
184         }
185         match = TIMESTAMP_REGEXP.matcher(node.getValue().toString());
186         if(!match.matches()) {
187             return ctor.constructPrivateType(node);
188         }
189         final String JavaDoc year_s = match.group(1);
190         final String JavaDoc month_s = match.group(2);
191         final String JavaDoc day_s = match.group(3);
192         final String JavaDoc hour_s = match.group(4);
193         final String JavaDoc min_s = match.group(5);
194         final String JavaDoc sec_s = match.group(6);
195         final String JavaDoc fract_s = match.group(7);
196         final String JavaDoc utc = match.group(8);
197         final String JavaDoc timezoneh_s = match.group(9);
198         final String JavaDoc timezonem_s = match.group(10);
199         
200         int usec = 0;
201         if(fract_s != null) {
202             usec = Integer.parseInt(fract_s);
203             if(usec != 0) {
204                 while(10*usec < 1000) {
205                     usec *= 10;
206                 }
207             }
208         }
209         final Calendar JavaDoc cal = Calendar.getInstance();
210         cal.clear();
211         if("Z".equalsIgnoreCase(utc)) {
212             cal.setTimeZone(java.util.TimeZone.getTimeZone("GMT"));
213         } else {
214             if(timezoneh_s != null || timezonem_s != null) {
215                 int zone = 0;
216                 int sign = +1;
217                 if(timezoneh_s != null) {
218                     if(timezoneh_s.startsWith("-")) {
219                         sign = -1;
220                     }
221                     zone += Integer.parseInt(timezoneh_s.substring(1))*3600000;
222                 }
223                 if(timezonem_s != null) {
224                     zone += Integer.parseInt(timezonem_s)*60000;
225                 }
226                 cal.set(Calendar.ZONE_OFFSET,sign*zone);
227             }
228         }
229         if(year_s != null) {
230             cal.set(Calendar.YEAR,Integer.parseInt(year_s));
231         }
232         if(month_s != null) {
233             cal.set(Calendar.MONTH,Integer.parseInt(month_s)-1); // Java's months are zero-based...
234
}
235         if(day_s != null) {
236             cal.set(Calendar.DAY_OF_MONTH,Integer.parseInt(day_s));
237         }
238         if(hour_s != null) {
239             cal.set(Calendar.HOUR_OF_DAY,Integer.parseInt(hour_s));
240         }
241         if(min_s != null) {
242             cal.set(Calendar.MINUTE,Integer.parseInt(min_s));
243         }
244         if(sec_s != null) {
245             cal.set(Calendar.SECOND,Integer.parseInt(sec_s));
246         }
247         cal.set(Calendar.MILLISECOND,usec);
248
249         return cal.getTime();
250     }
251
252     public static Object JavaDoc constructYamlInt(final Constructor ctor, final Node node) {
253         String JavaDoc value = ctor.constructScalar(node).toString().replaceAll("_","");
254         int sign = +1;
255         char first = value.charAt(0);
256         if(first == '-') {
257             sign = -1;
258             value = value.substring(1);
259         } else if(first == '+') {
260             value = value.substring(1);
261         }
262         int base = 10;
263         if(value.equals("0")) {
264             return new Long JavaDoc(0);
265         } else if(value.startsWith("0b")) {
266             value = value.substring(2);
267             base = 2;
268         } else if(value.startsWith("0x")) {
269             value = value.substring(2);
270             base = 16;
271         } else if(value.startsWith("0")) {
272             value = value.substring(1);
273             base = 8;
274         } else if(value.indexOf(':') != -1) {
275             final String JavaDoc[] digits = value.split(":");
276             int bes = 1;
277             int val = 0;
278             for(int i=0,j=digits.length;i<j;i++) {
279                 val += (Long.parseLong(digits[(j-i)-1])*bes);
280                 bes *= 60;
281             }
282             return new Integer JavaDoc(sign*val);
283         } else {
284             return new Long JavaDoc(sign * Long.parseLong(value));
285         }
286         return new Long JavaDoc(sign * Long.parseLong(value,base));
287     }
288
289     private final static Double JavaDoc INF_VALUE_POS = new Double JavaDoc(Double.POSITIVE_INFINITY);
290     private final static Double JavaDoc INF_VALUE_NEG = new Double JavaDoc(Double.NEGATIVE_INFINITY);
291     private final static Double JavaDoc NAN_VALUE = new Double JavaDoc(Double.NaN);
292
293     public static Object JavaDoc constructYamlFloat(final Constructor ctor, final Node node) {
294         String JavaDoc value = ctor.constructScalar(node).toString().replaceAll("_","");
295         int sign = +1;
296         char first = value.charAt(0);
297         if(first == '-') {
298             sign = -1;
299             value = value.substring(1);
300         } else if(first == '+') {
301             value = value.substring(1);
302         }
303         final String JavaDoc valLower = value.toLowerCase();
304         if(valLower.equals(".inf")) {
305             return sign == -1 ? INF_VALUE_NEG : INF_VALUE_POS;
306         } else if(valLower.equals(".nan")) {
307             return NAN_VALUE;
308         } else if(value.indexOf(':') != -1) {
309             final String JavaDoc[] digits = value.split(":");
310             int bes = 1;
311             double val = 0.0;
312             for(int i=0,j=digits.length;i<j;i++) {
313                 val += (Double.parseDouble(digits[(j-i)-1])*bes);
314                 bes *= 60;
315             }
316             return new Double JavaDoc(sign*val);
317         } else {
318             return Double.valueOf(value);
319         }
320     }
321
322     public static Object JavaDoc constructYamlBinary(final Constructor ctor, final Node node) {
323         final String JavaDoc[] values = ctor.constructScalar(node).toString().split("[\n\u0085]|(?:\r[^\n])");
324         final StringBuffer JavaDoc vals = new StringBuffer JavaDoc();
325         for(int i=0,j=values.length;i<j;i++) {
326             vals.append(values[i].trim());
327         }
328         return Base64Coder.decode(ByteList.plain(vals));
329     }
330
331     public static Object JavaDoc constructSpecializedSequence(final Constructor ctor, final String JavaDoc pref, final Node node) {
332         List JavaDoc outp = null;
333         try {
334             final Class JavaDoc seqClass = Class.forName(pref);
335             outp = (List JavaDoc)seqClass.newInstance();
336         } catch(final Exception JavaDoc e) {
337             throw new YAMLException("Can't construct a sequence from class " + pref + ": " + e.toString());
338         }
339         outp.addAll((List JavaDoc)ctor.constructSequence(node));
340         return outp;
341     }
342
343     public static Object JavaDoc constructSpecializedMap(final Constructor ctor, final String JavaDoc pref, final Node node) {
344         Map JavaDoc outp = null;
345         try {
346             final Class JavaDoc mapClass = Class.forName(pref);
347             outp = (Map JavaDoc)mapClass.newInstance();
348         } catch(final Exception JavaDoc e) {
349             throw new YAMLException("Can't construct a mapping from class " + pref + ": " + e.toString());
350         }
351         outp.putAll((Map JavaDoc)ctor.constructMapping(node));
352         return outp;
353     }
354
355     private static Object JavaDoc fixValue(final Object JavaDoc inp, final Class JavaDoc outp) {
356         if(inp == null) {
357             return null;
358         }
359         final Class JavaDoc inClass = inp.getClass();
360         if(outp.isAssignableFrom(inClass)) {
361             return inp;
362         }
363         if(inClass == Long JavaDoc.class && (outp == Integer JavaDoc.class || outp == Integer.TYPE)) {
364             return new Integer JavaDoc(((Long JavaDoc)inp).intValue());
365         }
366         if(inClass == Long JavaDoc.class && (outp == Short JavaDoc.class || outp == Short.TYPE)) {
367             return new Short JavaDoc((short)((Long JavaDoc)inp).intValue());
368         }
369         if(inClass == Long JavaDoc.class && (outp == Character JavaDoc.class || outp == Character.TYPE)) {
370             return new Character JavaDoc((char)((Long JavaDoc)inp).intValue());
371         }
372         if(inClass == Double JavaDoc.class && (outp == Float JavaDoc.class || outp == Float.TYPE)) {
373             return new Float JavaDoc(((Double JavaDoc)inp).floatValue());
374         }
375         return inp;
376     }
377
378     public static Object JavaDoc constructJava(final Constructor ctor, final String JavaDoc pref, final Node node) {
379         Object JavaDoc outp = null;
380         try {
381             final Class JavaDoc cl = Class.forName(pref);
382             outp = cl.newInstance();
383             final Map JavaDoc values = (Map JavaDoc)ctor.constructMapping(node);
384             java.lang.reflect.Method JavaDoc[] ems = cl.getMethods();
385             for(final Iterator JavaDoc iter = values.keySet().iterator();iter.hasNext();) {
386                 final Object JavaDoc key = iter.next();
387                 final Object JavaDoc value = values.get(key);
388                 final String JavaDoc keyName = key.toString();
389                 final String JavaDoc mName = "set" + Character.toUpperCase(keyName.charAt(0)) + keyName.substring(1);
390                 for(int i=0,j=ems.length;i<j;i++) {
391                     if(ems[i].getName().equals(mName) && ems[i].getParameterTypes().length == 1) {
392                         ems[i].invoke(outp, new Object JavaDoc[]{fixValue(value, ems[i].getParameterTypes()[0])});
393                         break;
394                     }
395                 }
396             }
397         } catch(final Exception JavaDoc e) {
398             throw new YAMLException("Can't construct a java object from class " + pref + ": " + e.toString());
399         }
400         return outp;
401     }
402
403     static {
404         BaseConstructorImpl.addConstructor("tag:yaml.org,2002:null",new YamlConstructor() {
405                 public Object JavaDoc call(final Constructor self, final Node node) {
406                     return constructYamlNull(self,node);
407                 }
408             });
409         addConstructor("tag:yaml.org,2002:bool",new YamlConstructor() {
410                 public Object JavaDoc call(final Constructor self, final Node node) {
411                     return constructYamlBool(self,node);
412                 }
413             });
414         addConstructor("tag:yaml.org,2002:omap",new YamlConstructor() {
415                 public Object JavaDoc call(final Constructor self, final Node node) {
416                     return constructYamlOmap(self,node);
417                 }
418             });
419         addConstructor("tag:yaml.org,2002:pairs",new YamlConstructor() {
420                 public Object JavaDoc call(final Constructor self, final Node node) {
421                     return constructYamlPairs(self,node);
422                 }
423             });
424         addConstructor("tag:yaml.org,2002:set",new YamlConstructor() {
425                 public Object JavaDoc call(final Constructor self, final Node node) {
426                     return constructYamlSet(self,node);
427                 }
428             });
429         addConstructor("tag:yaml.org,2002:int",new YamlConstructor() {
430                 public Object JavaDoc call(final Constructor self, final Node node) {
431                     return constructYamlInt(self,node);
432                 }
433             });
434         addConstructor("tag:yaml.org,2002:float",new YamlConstructor() {
435                 public Object JavaDoc call(final Constructor self, final Node node) {
436                     return constructYamlFloat(self,node);
437                 }
438             });
439         addConstructor("tag:yaml.org,2002:timestamp",new YamlConstructor() {
440                 public Object JavaDoc call(final Constructor self, final Node node) {
441                     return constructYamlTimestamp(self,node);
442                 }
443             });
444         addConstructor("tag:yaml.org,2002:timestamp#ymd",new YamlConstructor() {
445                 public Object JavaDoc call(final Constructor self, final Node node) {
446                     return constructYamlTimestamp(self,node);
447                 }
448             });
449         addConstructor("tag:yaml.org,2002:str",new YamlConstructor() {
450                 public Object JavaDoc call(final Constructor self, final Node node) {
451                     return constructYamlStr(self,node);
452                 }
453             });
454         addConstructor("tag:yaml.org,2002:binary",new YamlConstructor() {
455                 public Object JavaDoc call(final Constructor self, final Node node) {
456                     return constructYamlBinary(self,node);
457                 }
458             });
459         addConstructor("tag:yaml.org,2002:seq",new YamlConstructor() {
460                 public Object JavaDoc call(final Constructor self, final Node node) {
461                     return constructYamlSeq(self,node);
462                 }
463             });
464         addConstructor("tag:yaml.org,2002:map",new YamlConstructor() {
465                 public Object JavaDoc call(final Constructor self, final Node node) {
466                     return constructYamlMap(self,node);
467                 }
468             });
469         addConstructor(null,new YamlConstructor() {
470                 public Object JavaDoc call(final Constructor self, final Node node) {
471                     return self.constructPrivateType(node);
472                 }
473             });
474
475         addMultiConstructor("tag:yaml.org,2002:seq:",new YamlMultiConstructor() {
476                 public Object JavaDoc call(final Constructor self, final String JavaDoc pref, final Node node) {
477                     return constructSpecializedSequence(self,pref,node);
478                 }
479             });
480         addMultiConstructor("tag:yaml.org,2002:map:",new YamlMultiConstructor() {
481                 public Object JavaDoc call(final Constructor self, final String JavaDoc pref, final Node node) {
482                     return constructSpecializedMap(self,pref,node);
483                 }
484             });
485         addMultiConstructor("!java/object:",new YamlMultiConstructor() {
486                 public Object JavaDoc call(final Constructor self, final String JavaDoc pref, final Node node) {
487                     return constructJava(self,pref,node);
488                 }
489             });
490     }
491
492     public static void main(final String JavaDoc[] args) throws Exception JavaDoc {
493         final String JavaDoc filename = args[0];
494         System.out.println("Reading of file: \"" + filename + "\"");
495
496         final ByteList input = new ByteList(1024);
497         final InputStream JavaDoc reader = new FileInputStream JavaDoc(filename);
498         byte[] buff = new byte[1024];
499         int read = 0;
500         while(true) {
501             read = reader.read(buff);
502             input.append(buff,0,read);
503             if(read < 1024) {
504                 break;
505             }
506         }
507         reader.close();
508         final long before = System.currentTimeMillis();
509         for(int i=0;i<1;i++) {
510             final Constructor ctor = new SafeConstructorImpl(new ComposerImpl(new ParserImpl(new ScannerImpl(input)),new ResolverImpl()));
511             for(final Iterator JavaDoc iter = ctor.eachDocument();iter.hasNext();) {
512                 iter.next();
513                 //System.out.println(iter.next());
514
}
515         }
516         final long after = System.currentTimeMillis();
517         final long time = after-before;
518         final double timeS = (after-before)/1000.0;
519         System.out.println("Walking through the nodes for the file: " + filename + " took " + time + "ms, or " + timeS + " seconds");
520     }
521 }// SafeConstructorImpl
522
Popular Tags