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 */ 25 package com.sun.corba.se.spi.orb ; 26 27 import java.util.StringTokenizer ; 28 import java.util.Arrays ; 29 30 import java.lang.reflect.Array ; 31 32 import java.net.URL ; 33 import java.net.MalformedURLException ; 34 35 import com.sun.corba.se.spi.logging.CORBALogDomains ; 36 37 import com.sun.corba.se.impl.logging.ORBUtilSystemException ; 38 import com.sun.corba.se.impl.orbutil.ObjectUtility ; 39 40 import 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 */ 71 public 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 }