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

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

mercurial