OperationFactory.java revision 608:7e06bf1dcb09
1/*
2 * Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.  Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25package com.sun.corba.se.spi.orb ;
26
27import java.util.StringTokenizer ;
28import java.util.Arrays ;
29
30import java.lang.reflect.Array ;
31
32import java.net.URL ;
33import java.net.MalformedURLException ;
34
35import com.sun.corba.se.spi.logging.CORBALogDomains ;
36
37import com.sun.corba.se.impl.logging.ORBUtilSystemException ;
38import com.sun.corba.se.impl.orbutil.ObjectUtility ;
39
40import sun.corba.SharedSecrets;
41
42/** This is a static factory class for commonly used operations
43* for property parsing.  The following operations are supported:
44* <ul>
45* <li>maskErrorAction( Operation op ) executes op and returns the result.  If op throws an
46* exception, the result is null.
47* <li>indexAction( int arg ) returns the [arg] element of value, which must be an Object[]</li>
48* <li>identityAction() return the value</li>
49* <li>booleanAction() return a Boolean representing true or false values of the String value</li>
50* <li>integerAction() returns an Integer for the String value, which must be a decimal integer</li>
51* <li>stringAction() returns the String value</li>
52* <li>classAction() returns a class for the String value, as loaded by the ORB classloader</li>
53* <li>setFlagAction() always return Boolean.TRUE</li>
54* <li>URLAction() returns a java.net.URL for the String value, which must be a valid URL</li>
55* <li>integerRangeAction( int min, int max ) returns an Integer for the String value, which must be a
56* decimal integer in the range min to max inclusive</li>
57* <li>listAction( String sep, Operation ) tokenizes the String value with sep as separator, then
58* applies the Operation to each token, and returns an array of the result</li>
59* <li>sequenceAction( String, Operation[] ) tokenizes the String value with sep as separator, then
60* applies each Operation in the Operation array to successive tokens, and returns an array of the results</li>
61* <li>compose( Operation op1, Operation op2 ) is the operation that applies op2 to the result of applying
62* op1 to the value</li>
63* <li>mapAction( Operation ) applies the Operation to each element of an array of objects, and returns
64* an array of the results</li>
65* <li>mapSequenceAction( Operation[] ) applies the corresponding element of the Operation array to an
66* element of the Object[] value, and returns an array of the results</li>
67* <li>convertIntegerToShort coerces an Integer into a Short.</li>
68* </ul>
69* Other operations can be directly defined, and combined using these basic operations.
70*/
71public abstract class OperationFactory {
72    private OperationFactory() {}
73
74    private static String getString( Object obj )
75    {
76        if (obj instanceof String)
77            return (String)obj ;
78        else
79            throw new Error( "String expected" ) ;
80    }
81
82    private static Object[] getObjectArray( Object obj )
83    {
84        if (obj instanceof Object[])
85            return (Object[])obj ;
86        else
87            throw new Error( "Object[] expected" ) ;
88    }
89
90    private static StringPair getStringPair( Object obj )
91    {
92        if (obj instanceof StringPair)
93            return (StringPair)obj ;
94        else
95            throw new Error( "StringPair expected" ) ;
96    }
97
98    private static abstract class OperationBase implements Operation{
99        public boolean equals( Object obj )
100        {
101            if (this==obj)
102                return true ;
103
104            if (!(obj instanceof OperationBase))
105                return false ;
106
107            OperationBase other = (OperationBase)obj ;
108
109            return toString().equals( other.toString() ) ;
110        }
111
112        public int hashCode()
113        {
114            return toString().hashCode() ;
115        }
116    }
117
118    private static class MaskErrorAction extends OperationBase
119    {
120        private Operation op ;
121
122        public MaskErrorAction( Operation op )
123        {
124            this.op = op ;
125        }
126
127        public Object operate( Object arg )
128        {
129            try {
130                return op.operate( arg ) ;
131            } catch (java.lang.Exception exc) {
132                return null ;
133            }
134        }
135
136        public String toString()
137        {
138            return "maskErrorAction(" + op + ")" ;
139        }
140    }
141
142    public static Operation maskErrorAction( Operation op )
143    {
144        return new MaskErrorAction( op ) ;
145    }
146
147    private static class IndexAction extends OperationBase
148    {
149        private int index ;
150
151        public IndexAction( int index )
152        {
153            this.index = index ;
154        }
155
156        public Object operate( Object value )
157        {
158            return getObjectArray( value )[ index ] ;
159        }
160
161        public String toString()
162        {
163            return "indexAction(" + index + ")" ;
164        }
165    }
166
167    public static Operation indexAction( int index )
168    {
169        return new IndexAction( index ) ;
170    }
171
172    private static class SuffixAction extends OperationBase
173    {
174        public Object operate( Object value )
175        {
176            return getStringPair( value ).getFirst() ;
177        }
178
179        public String toString() { return "suffixAction" ; }
180    }
181
182    private static Operation suffixActionImpl = new SuffixAction() ;
183
184    private static class ValueAction extends OperationBase
185    {
186        public Object operate( Object value )
187        {
188            return getStringPair( value ).getSecond() ;
189        }
190
191        public String toString() { return "valueAction" ; }
192    }
193
194    private static Operation valueActionImpl = new ValueAction() ;
195
196    private static class IdentityAction extends OperationBase
197    {
198        public Object operate( Object value )
199        {
200            return value ;
201        }
202
203        public String toString() { return "identityAction" ; }
204    }
205
206    private static Operation identityActionImpl = new IdentityAction() ;
207
208    private static class BooleanAction extends OperationBase
209    {
210        public Object operate( Object value )
211        {
212            return new Boolean( getString( value ) ) ;
213        }
214
215        public String toString() { return "booleanAction" ; }
216    }
217
218    private static Operation booleanActionImpl = new BooleanAction() ;
219
220    private static class IntegerAction extends OperationBase
221    {
222        public Object operate( Object value )
223        {
224            return new Integer( getString( value ) ) ;
225        }
226
227        public String toString() { return "integerAction" ; }
228    }
229
230    private static Operation integerActionImpl = new IntegerAction() ;
231
232    private static class StringAction extends OperationBase
233    {
234        public Object operate( Object value )
235        {
236            return value ;
237        }
238
239        public String toString() { return "stringAction" ; }
240    }
241
242    private static Operation stringActionImpl = new StringAction() ;
243
244    private static class ClassAction extends OperationBase
245    {
246        public Object operate( Object value )
247        {
248            String className = getString( value ) ;
249
250            try {
251                Class<?> result =
252                    SharedSecrets.getJavaCorbaAccess().loadClass( className ) ;
253                return result ;
254            } catch (Exception exc) {
255                ORBUtilSystemException wrapper = ORBUtilSystemException.get(
256                    CORBALogDomains.ORB_LIFECYCLE ) ;
257                throw wrapper.couldNotLoadClass( exc, className ) ;
258            }
259        }
260
261        public String toString() { return "classAction" ; }
262    }
263
264    private static Operation classActionImpl = new ClassAction() ;
265
266    private static class SetFlagAction extends OperationBase
267    {
268        public Object operate( Object value )
269        {
270            return Boolean.TRUE ;
271        }
272
273        public String toString() { return "setFlagAction" ; }
274    }
275
276    private static Operation setFlagActionImpl = new SetFlagAction() ;
277
278    private static class URLAction extends OperationBase
279    {
280        public Object operate( Object value )
281        {
282            String val = (String)value ;
283            try {
284                return new URL( val ) ;
285            } catch (MalformedURLException exc) {
286                ORBUtilSystemException wrapper = ORBUtilSystemException.get(
287                    CORBALogDomains.ORB_LIFECYCLE ) ;
288                throw wrapper.badUrl( exc, val ) ;
289            }
290        }
291
292        public String toString() { return "URLAction" ; }
293    }
294
295    private static Operation URLActionImpl = new URLAction() ;
296
297    public static Operation identityAction()
298    {
299        return identityActionImpl ;
300    }
301
302    public static Operation suffixAction()
303    {
304        return suffixActionImpl ;
305    }
306
307    public static Operation valueAction()
308    {
309        return valueActionImpl ;
310    }
311
312    public static Operation booleanAction()
313    {
314        return booleanActionImpl ;
315    }
316
317    public static Operation integerAction()
318    {
319        return integerActionImpl ;
320    }
321
322    public static Operation stringAction()
323    {
324        return stringActionImpl ;
325    }
326
327    public static Operation classAction()
328    {
329        return classActionImpl ;
330    }
331
332    public static Operation setFlagAction()
333    {
334        return setFlagActionImpl ;
335    }
336
337    public static Operation URLAction()
338    {
339        return URLActionImpl ;
340    }
341
342    private static class IntegerRangeAction extends OperationBase
343    {
344        private int min ;
345        private int max ;
346
347        IntegerRangeAction( int min, int max )
348        {
349            this.min = min ;
350            this.max = max ;
351        }
352
353        public Object operate( Object value )
354        {
355            int result = Integer.parseInt( getString( value ) ) ;
356            if ((result >= min) && (result <= max))
357                return new Integer( result ) ;
358            else
359                throw new IllegalArgumentException(
360                    "Property value " + result + " is not in the range " +
361                    min + " to " + max ) ;
362        }
363
364        public String toString() {
365            return "integerRangeAction(" + min + "," + max + ")" ;
366        }
367    }
368
369    public static Operation integerRangeAction( int min, int max )
370    {
371        return new IntegerRangeAction( min, max ) ;
372    }
373
374    private static class ListAction extends OperationBase {
375        private String sep ;
376        private Operation act ;
377
378        ListAction( String sep, Operation act )
379        {
380            this.sep = sep ;
381            this.act = act ;
382        }
383
384        // Note that this method carefully constructs an array of the type
385        // of the first result, rather than just using Object[], which is
386        // not convertible into the correct type.  Also note that no tokens
387        // results in a null result.
388        public Object operate( Object value )
389        {
390            StringTokenizer st = new StringTokenizer( getString( value ),
391                sep ) ;
392            int length = st.countTokens() ;
393            Object result = null ;
394            int ctr = 0 ;
395            while (st.hasMoreTokens()) {
396                String next = st.nextToken() ;
397                Object val = act.operate( next ) ;
398                if (result == null)
399                    result = Array.newInstance( val.getClass(), length ) ;
400                Array.set( result, ctr++, val ) ;
401            }
402
403            return result ;
404        }
405
406        public String toString() {
407            return "listAction(separator=\"" + sep +
408                "\",action=" + act + ")" ;
409        }
410    }
411
412    public static Operation listAction( String sep, Operation act )
413    {
414        return new ListAction( sep, act ) ;
415    }
416
417    private static class SequenceAction extends OperationBase
418    {
419        private String sep ;
420        private Operation[] actions ;
421
422        SequenceAction( String sep, Operation[] actions )
423        {
424            this.sep = sep ;
425            this.actions = actions ;
426        }
427
428        public Object operate( Object value )
429        {
430            StringTokenizer st = new StringTokenizer( getString( value ),
431                sep ) ;
432
433            int numTokens = st.countTokens() ;
434            if (numTokens != actions.length)
435                throw new Error(
436                    "Number of tokens and number of actions do not match" ) ;
437
438            int ctr = 0 ;
439            Object[] result = new Object[ numTokens ] ;
440            while (st.hasMoreTokens()) {
441                Operation act = actions[ctr] ;
442                String next = st.nextToken() ;
443                result[ctr++] = act.operate( next ) ;
444            }
445
446            return result ;
447        }
448
449        public String toString() {
450            return "sequenceAction(separator=\"" + sep +
451                "\",actions=" +
452                Arrays.toString(actions) + ")" ;
453        }
454    }
455
456    public static Operation sequenceAction( String sep,
457        Operation[] actions )
458    {
459        return new SequenceAction( sep, actions ) ;
460    }
461
462    private static class ComposeAction extends OperationBase
463    {
464        private Operation op1 ;
465        private Operation op2 ;
466
467        ComposeAction( Operation op1, Operation op2 )
468        {
469            this.op1 = op1 ;
470            this.op2 = op2 ;
471        }
472
473        public Object operate( Object value )
474        {
475            return op2.operate( op1.operate( value ) ) ;
476        }
477
478        public String toString() {
479            return "composition(" + op1 + "," + op2 + ")" ;
480        }
481    }
482
483    public static Operation compose( Operation op1, Operation op2 )
484    {
485        return new ComposeAction( op1, op2 ) ;
486    }
487
488    private static class MapAction extends OperationBase
489    {
490        Operation op ;
491
492        MapAction( Operation op )
493        {
494            this.op = op ;
495        }
496
497        public Object operate( Object value )
498        {
499            Object[] values = (Object[])value ;
500            Object[] result = new Object[ values.length ] ;
501            for (int ctr=0; ctr<values.length; ctr++ )
502                result[ctr] = op.operate( values[ctr] ) ;
503            return result ;
504        }
505
506        public String toString() {
507            return "mapAction(" + op + ")" ;
508        }
509    }
510
511    public static Operation mapAction( Operation op )
512    {
513        return new MapAction( op ) ;
514    }
515
516    private static class MapSequenceAction extends OperationBase
517    {
518        private Operation[] op ;
519
520        public MapSequenceAction( Operation[] op )
521        {
522            this.op = op ;
523        }
524
525        // XXX Does this correctly handle array types?  It seems
526        // that hetereogeneous arrays work this way, while
527        // homogeneous arrays need to use Array.newInstance tricks.
528        public Object operate( Object value )
529        {
530            Object[] values = (Object[])value ;
531            Object[] result = new Object[ values.length ] ;
532            for (int ctr=0; ctr<values.length; ctr++ )
533                result[ctr] = op[ctr].operate( values[ctr] ) ;
534            return result ;
535        }
536
537        public String toString() {
538            return "mapSequenceAction(" +
539                Arrays.toString(op) + ")" ;
540        }
541    }
542
543    public static Operation mapSequenceAction( Operation[] op )
544    {
545        return new MapSequenceAction( op ) ;
546    }
547
548    private static class ConvertIntegerToShort extends OperationBase
549    {
550        public Object operate( Object value )
551        {
552            Integer val = (Integer)value ;
553            return new Short( val.shortValue() ) ;
554        }
555
556        public String toString() {
557            return "ConvertIntegerToShort" ;
558        }
559    }
560
561    private static Operation convertIntegerToShortImpl = new ConvertIntegerToShort() ;
562
563    public static Operation convertIntegerToShort()
564    {
565        return convertIntegerToShortImpl ;
566    }
567}
568