src/share/classes/com/sun/corba/se/spi/orb/OperationFactory.java

Fri, 24 Sep 2010 22:42:14 -0700

author
skoppar
date
Fri, 24 Sep 2010 22:42:14 -0700
changeset 205
b2fff4b7e8cd
parent 158
91006f157c46
child 475
39d15bbb5741
permissions
-rw-r--r--

6891766: Vulnerabilities in use of reflection in CORBA
Reviewed-by: hawtin

     1 /*
     2  * Copyright (c) 2002, 2010, 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  */
    25 package com.sun.corba.se.spi.orb ;
    27 import java.util.StringTokenizer ;
    28 import java.util.Arrays ;
    30 import java.lang.reflect.Array ;
    32 import java.net.URL ;
    33 import java.net.MalformedURLException ;
    35 import com.sun.corba.se.spi.logging.CORBALogDomains ;
    37 import com.sun.corba.se.impl.logging.ORBUtilSystemException ;
    38 import com.sun.corba.se.impl.orbutil.ORBClassLoader ;
    39 import com.sun.corba.se.impl.orbutil.ObjectUtility ;
    41 /** This is a static factory class for commonly used operations
    42 * for property parsing.  The following operations are supported:
    43 * <ul>
    44 * <li>maskErrorAction( Operation op ) executes op and returns the result.  If op throws an
    45 * exception, the result is null.
    46 * <li>indexAction( int arg ) returns the [arg] element of value, which must be an Object[]</li>
    47 * <li>identityAction() return the value</li>
    48 * <li>booleanAction() return a Boolean representing true or false values of the String value</li>
    49 * <li>integerAction() returns an Integer for the String value, which must be a decimal integer</li>
    50 * <li>stringAction() returns the String value</li>
    51 * <li>classAction() returns a class for the String value, as loaded by the ORB classloader</li>
    52 * <li>setFlagAction() always return Boolean.TRUE</li>
    53 * <li>URLAction() returns a java.net.URL for the String value, which must be a valid URL</li>
    54 * <li>integerRangeAction( int min, int max ) returns an Integer for the String value, which must be a
    55 * decimal integer in the range min to max inclusive</li>
    56 * <li>listAction( String sep, Operation ) tokenizes the String value with sep as separator, then
    57 * applies the Operation to each token, and returns an array of the result</li>
    58 * <li>sequenceAction( String, Operation[] ) tokenizes the String value with sep as separator, then
    59 * applies each Operation in the Operation array to successive tokens, and returns an array of the results</li>
    60 * <li>compose( Operation op1, Operation op2 ) is the operation that applies op2 to the result of applying
    61 * op1 to the value</li>
    62 * <li>mapAction( Operation ) applies the Operation to each element of an array of objects, and returns
    63 * an array of the results</li>
    64 * <li>mapSequenceAction( Operation[] ) applies the corresponding element of the Operation array to an
    65 * element of the Object[] value, and returns an array of the results</li>
    66 * <li>convertIntegerToShort coerces an Integer into a Short.</li>
    67 * </ul>
    68 * Other operations can be directly defined, and combined using these basic operations.
    69 */
    70 public abstract class OperationFactory {
    71     private OperationFactory() {}
    73     private static String getString( Object obj )
    74     {
    75         if (obj instanceof String)
    76             return (String)obj ;
    77         else
    78             throw new Error( "String expected" ) ;
    79     }
    81     private static Object[] getObjectArray( Object obj )
    82     {
    83         if (obj instanceof Object[])
    84             return (Object[])obj ;
    85         else
    86             throw new Error( "Object[] expected" ) ;
    87     }
    89     private static StringPair getStringPair( Object obj )
    90     {
    91         if (obj instanceof StringPair)
    92             return (StringPair)obj ;
    93         else
    94             throw new Error( "StringPair expected" ) ;
    95     }
    97     private static abstract class OperationBase implements Operation{
    98         public boolean equals( Object obj )
    99         {
   100             if (this==obj)
   101                 return true ;
   103             if (!(obj instanceof OperationBase))
   104                 return false ;
   106             OperationBase other = (OperationBase)obj ;
   108             return toString().equals( other.toString() ) ;
   109         }
   111         public int hashCode()
   112         {
   113             return toString().hashCode() ;
   114         }
   115     }
   117     private static class MaskErrorAction extends OperationBase
   118     {
   119         private Operation op ;
   121         public MaskErrorAction( Operation op )
   122         {
   123             this.op = op ;
   124         }
   126         public Object operate( Object arg )
   127         {
   128             try {
   129                 return op.operate( arg ) ;
   130             } catch (java.lang.Exception exc) {
   131                 return null ;
   132             }
   133         }
   135         public String toString()
   136         {
   137             return "maskErrorAction(" + op + ")" ;
   138         }
   139     }
   141     public static Operation maskErrorAction( Operation op )
   142     {
   143         return new MaskErrorAction( op ) ;
   144     }
   146     private static class IndexAction extends OperationBase
   147     {
   148         private int index ;
   150         public IndexAction( int index )
   151         {
   152             this.index = index ;
   153         }
   155         public Object operate( Object value )
   156         {
   157             return getObjectArray( value )[ index ] ;
   158         }
   160         public String toString()
   161         {
   162             return "indexAction(" + index + ")" ;
   163         }
   164     }
   166     public static Operation indexAction( int index )
   167     {
   168         return new IndexAction( index ) ;
   169     }
   171     private static class SuffixAction extends OperationBase
   172     {
   173         public Object operate( Object value )
   174         {
   175             return getStringPair( value ).getFirst() ;
   176         }
   178         public String toString() { return "suffixAction" ; }
   179     }
   181     private static Operation suffixActionImpl = new SuffixAction() ;
   183     private static class ValueAction extends OperationBase
   184     {
   185         public Object operate( Object value )
   186         {
   187             return getStringPair( value ).getSecond() ;
   188         }
   190         public String toString() { return "valueAction" ; }
   191     }
   193     private static Operation valueActionImpl = new ValueAction() ;
   195     private static class IdentityAction extends OperationBase
   196     {
   197         public Object operate( Object value )
   198         {
   199             return value ;
   200         }
   202         public String toString() { return "identityAction" ; }
   203     }
   205     private static Operation identityActionImpl = new IdentityAction() ;
   207     private static class BooleanAction extends OperationBase
   208     {
   209         public Object operate( Object value )
   210         {
   211             return new Boolean( getString( value ) ) ;
   212         }
   214         public String toString() { return "booleanAction" ; }
   215     }
   217     private static Operation booleanActionImpl = new BooleanAction() ;
   219     private static class IntegerAction extends OperationBase
   220     {
   221         public Object operate( Object value )
   222         {
   223             return new Integer( getString( value ) ) ;
   224         }
   226         public String toString() { return "integerAction" ; }
   227     }
   229     private static Operation integerActionImpl = new IntegerAction() ;
   231     private static class StringAction extends OperationBase
   232     {
   233         public Object operate( Object value )
   234         {
   235             return value ;
   236         }
   238         public String toString() { return "stringAction" ; }
   239     }
   241     private static Operation stringActionImpl = new StringAction() ;
   243     private static class ClassAction extends OperationBase
   244     {
   245         public Object operate( Object value )
   246         {
   247             String className = getString( value ) ;
   249             try {
   250                 Class result = ORBClassLoader.loadClass( className ) ;
   251                 return result ;
   252             } catch (Exception exc) {
   253                 ORBUtilSystemException wrapper = ORBUtilSystemException.get(
   254                     CORBALogDomains.ORB_LIFECYCLE ) ;
   255                 throw wrapper.couldNotLoadClass( exc, className ) ;
   256             }
   257         }
   259         public String toString() { return "classAction" ; }
   260     }
   262     private static Operation classActionImpl = new ClassAction() ;
   264     private static class SetFlagAction extends OperationBase
   265     {
   266         public Object operate( Object value )
   267         {
   268             return Boolean.TRUE ;
   269         }
   271         public String toString() { return "setFlagAction" ; }
   272     }
   274     private static Operation setFlagActionImpl = new SetFlagAction() ;
   276     private static class URLAction extends OperationBase
   277     {
   278         public Object operate( Object value )
   279         {
   280             String val = (String)value ;
   281             try {
   282                 return new URL( val ) ;
   283             } catch (MalformedURLException exc) {
   284                 ORBUtilSystemException wrapper = ORBUtilSystemException.get(
   285                     CORBALogDomains.ORB_LIFECYCLE ) ;
   286                 throw wrapper.badUrl( exc, val ) ;
   287             }
   288         }
   290         public String toString() { return "URLAction" ; }
   291     }
   293     private static Operation URLActionImpl = new URLAction() ;
   295     public static Operation identityAction()
   296     {
   297         return identityActionImpl ;
   298     }
   300     public static Operation suffixAction()
   301     {
   302         return suffixActionImpl ;
   303     }
   305     public static Operation valueAction()
   306     {
   307         return valueActionImpl ;
   308     }
   310     public static Operation booleanAction()
   311     {
   312         return booleanActionImpl ;
   313     }
   315     public static Operation integerAction()
   316     {
   317         return integerActionImpl ;
   318     }
   320     public static Operation stringAction()
   321     {
   322         return stringActionImpl ;
   323     }
   325     public static Operation classAction()
   326     {
   327         return classActionImpl ;
   328     }
   330     public static Operation setFlagAction()
   331     {
   332         return setFlagActionImpl ;
   333     }
   335     public static Operation URLAction()
   336     {
   337         return URLActionImpl ;
   338     }
   340     private static class IntegerRangeAction extends OperationBase
   341     {
   342         private int min ;
   343         private int max ;
   345         IntegerRangeAction( int min, int max )
   346         {
   347             this.min = min ;
   348             this.max = max ;
   349         }
   351         public Object operate( Object value )
   352         {
   353             int result = Integer.parseInt( getString( value ) ) ;
   354             if ((result >= min) && (result <= max))
   355                 return new Integer( result ) ;
   356             else
   357                 throw new IllegalArgumentException(
   358                     "Property value " + result + " is not in the range " +
   359                     min + " to " + max ) ;
   360         }
   362         public String toString() {
   363             return "integerRangeAction(" + min + "," + max + ")" ;
   364         }
   365     }
   367     public static Operation integerRangeAction( int min, int max )
   368     {
   369         return new IntegerRangeAction( min, max ) ;
   370     }
   372     private static class ListAction extends OperationBase {
   373         private String sep ;
   374         private Operation act ;
   376         ListAction( String sep, Operation act )
   377         {
   378             this.sep = sep ;
   379             this.act = act ;
   380         }
   382         // Note that this method carefully constructs an array of the type
   383         // of the first result, rather than just using Object[], which is
   384         // not convertible into the correct type.  Also note that no tokens
   385         // results in a null result.
   386         public Object operate( Object value )
   387         {
   388             StringTokenizer st = new StringTokenizer( getString( value ),
   389                 sep ) ;
   390             int length = st.countTokens() ;
   391             Object result = null ;
   392             int ctr = 0 ;
   393             while (st.hasMoreTokens()) {
   394                 String next = st.nextToken() ;
   395                 Object val = act.operate( next ) ;
   396                 if (result == null)
   397                     result = Array.newInstance( val.getClass(), length ) ;
   398                 Array.set( result, ctr++, val ) ;
   399             }
   401             return result ;
   402         }
   404         public String toString() {
   405             return "listAction(separator=\"" + sep +
   406                 "\",action=" + act + ")" ;
   407         }
   408     }
   410     public static Operation listAction( String sep, Operation act )
   411     {
   412         return new ListAction( sep, act ) ;
   413     }
   415     private static class SequenceAction extends OperationBase
   416     {
   417         private String sep ;
   418         private Operation[] actions ;
   420         SequenceAction( String sep, Operation[] actions )
   421         {
   422             this.sep = sep ;
   423             this.actions = actions ;
   424         }
   426         public Object operate( Object value )
   427         {
   428             StringTokenizer st = new StringTokenizer( getString( value ),
   429                 sep ) ;
   431             int numTokens = st.countTokens() ;
   432             if (numTokens != actions.length)
   433                 throw new Error(
   434                     "Number of tokens and number of actions do not match" ) ;
   436             int ctr = 0 ;
   437             Object[] result = new Object[ numTokens ] ;
   438             while (st.hasMoreTokens()) {
   439                 Operation act = actions[ctr] ;
   440                 String next = st.nextToken() ;
   441                 result[ctr++] = act.operate( next ) ;
   442             }
   444             return result ;
   445         }
   447         public String toString() {
   448             return "sequenceAction(separator=\"" + sep +
   449                 "\",actions=" +
   450                 Arrays.toString(actions) + ")" ;
   451         }
   452     }
   454     public static Operation sequenceAction( String sep,
   455         Operation[] actions )
   456     {
   457         return new SequenceAction( sep, actions ) ;
   458     }
   460     private static class ComposeAction extends OperationBase
   461     {
   462         private Operation op1 ;
   463         private Operation op2 ;
   465         ComposeAction( Operation op1, Operation op2 )
   466         {
   467             this.op1 = op1 ;
   468             this.op2 = op2 ;
   469         }
   471         public Object operate( Object value )
   472         {
   473             return op2.operate( op1.operate( value ) ) ;
   474         }
   476         public String toString() {
   477             return "composition(" + op1 + "," + op2 + ")" ;
   478         }
   479     }
   481     public static Operation compose( Operation op1, Operation op2 )
   482     {
   483         return new ComposeAction( op1, op2 ) ;
   484     }
   486     private static class MapAction extends OperationBase
   487     {
   488         Operation op ;
   490         MapAction( Operation op )
   491         {
   492             this.op = op ;
   493         }
   495         public Object operate( Object value )
   496         {
   497             Object[] values = (Object[])value ;
   498             Object[] result = new Object[ values.length ] ;
   499             for (int ctr=0; ctr<values.length; ctr++ )
   500                 result[ctr] = op.operate( values[ctr] ) ;
   501             return result ;
   502         }
   504         public String toString() {
   505             return "mapAction(" + op + ")" ;
   506         }
   507     }
   509     public static Operation mapAction( Operation op )
   510     {
   511         return new MapAction( op ) ;
   512     }
   514     private static class MapSequenceAction extends OperationBase
   515     {
   516         private Operation[] op ;
   518         public MapSequenceAction( Operation[] op )
   519         {
   520             this.op = op ;
   521         }
   523         // XXX Does this correctly handle array types?  It seems
   524         // that hetereogeneous arrays work this way, while
   525         // homogeneous arrays need to use Array.newInstance tricks.
   526         public Object operate( Object value )
   527         {
   528             Object[] values = (Object[])value ;
   529             Object[] result = new Object[ values.length ] ;
   530             for (int ctr=0; ctr<values.length; ctr++ )
   531                 result[ctr] = op[ctr].operate( values[ctr] ) ;
   532             return result ;
   533         }
   535         public String toString() {
   536             return "mapSequenceAction(" +
   537                 Arrays.toString(op) + ")" ;
   538         }
   539     }
   541     public static Operation mapSequenceAction( Operation[] op )
   542     {
   543         return new MapSequenceAction( op ) ;
   544     }
   546     private static class ConvertIntegerToShort extends OperationBase
   547     {
   548         public Object operate( Object value )
   549         {
   550             Integer val = (Integer)value ;
   551             return new Short( val.shortValue() ) ;
   552         }
   554         public String toString() {
   555             return "ConvertIntegerToShort" ;
   556         }
   557     }
   559     private static Operation convertIntegerToShortImpl = new ConvertIntegerToShort() ;
   561     public static Operation convertIntegerToShort()
   562     {
   563         return convertIntegerToShortImpl ;
   564     }
   565 }

mercurial