1. /*
  2. * @(#)OperationFactory.java 1.24 03/12/19
  3. *
  4. * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
  5. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
  6. */
  7. package com.sun.corba.se.spi.orb ;
  8. import java.util.StringTokenizer ;
  9. import java.lang.reflect.Array ;
  10. import java.net.URL ;
  11. import java.net.MalformedURLException ;
  12. import com.sun.corba.se.spi.logging.CORBALogDomains ;
  13. import com.sun.corba.se.impl.logging.ORBUtilSystemException ;
  14. import com.sun.corba.se.impl.orbutil.ORBClassLoader ;
  15. import com.sun.corba.se.impl.orbutil.ObjectUtility ;
  16. /** This is a static factory class for commonly used operations
  17. * for property parsing. The following operations are supported:
  18. * <ul>
  19. * <li>maskErrorAction( Operation op ) executes op and returns the result. If op throws an
  20. * exception, the result is null.
  21. * <li>indexAction( int arg ) returns the [arg] element of value, which must be an Object[]</li>
  22. * <li>identityAction() return the value</li>
  23. * <li>booleanAction() return a Boolean representing true or false values of the String value</li>
  24. * <li>integerAction() returns an Integer for the String value, which must be a decimal integer</li>
  25. * <li>stringAction() returns the String value</li>
  26. * <li>classAction() returns a class for the String value, as loaded by the ORB classloader</li>
  27. * <li>setFlagAction() always return Boolean.TRUE</li>
  28. * <li>URLAction() returns a java.net.URL for the String value, which must be a valid URL</li>
  29. * <li>integerRangeAction( int min, int max ) returns an Integer for the String value, which must be a
  30. * decimal integer in the range min to max inclusive</li>
  31. * <li>listAction( String sep, Operation ) tokenizes the String value with sep as separator, then
  32. * applies the Operation to each token, and returns an array of the result</li>
  33. * <li>sequenceAction( String, Operation[] ) tokenizes the String value with sep as separator, then
  34. * applies each Operation in the Operation array to successive tokens, and returns an array of the results</li>
  35. * <li>compose( Operation op1, Operation op2 ) is the operation that applies op2 to the result of applying
  36. * op1 to the value</li>
  37. * <li>mapAction( Operation ) applies the Operation to each element of an array of objects, and returns
  38. * an array of the results</li>
  39. * <li>mapSequenceAction( Operation[] ) applies the corresponding element of the Operation array to an
  40. * element of the Object[] value, and returns an array of the results</li>
  41. * <li>convertIntegerToShort coerces an Integer into a Short.</li>
  42. * </ul>
  43. * Other operations can be directly defined, and combined using these basic operations.
  44. */
  45. public abstract class OperationFactory {
  46. private OperationFactory() {}
  47. private static String getString( Object obj )
  48. {
  49. if (obj instanceof String)
  50. return (String)obj ;
  51. else
  52. throw new Error( "String expected" ) ;
  53. }
  54. private static Object[] getObjectArray( Object obj )
  55. {
  56. if (obj instanceof Object[])
  57. return (Object[])obj ;
  58. else
  59. throw new Error( "Object[] expected" ) ;
  60. }
  61. private static StringPair getStringPair( Object obj )
  62. {
  63. if (obj instanceof StringPair)
  64. return (StringPair)obj ;
  65. else
  66. throw new Error( "StringPair expected" ) ;
  67. }
  68. private static abstract class OperationBase implements Operation{
  69. public boolean equals( Object obj )
  70. {
  71. if (this==obj)
  72. return true ;
  73. if (!(obj instanceof OperationBase))
  74. return false ;
  75. OperationBase other = (OperationBase)obj ;
  76. return toString().equals( other.toString() ) ;
  77. }
  78. public int hashCode()
  79. {
  80. return toString().hashCode() ;
  81. }
  82. }
  83. private static class MaskErrorAction extends OperationBase
  84. {
  85. private Operation op ;
  86. public MaskErrorAction( Operation op )
  87. {
  88. this.op = op ;
  89. }
  90. public Object operate( Object arg )
  91. {
  92. try {
  93. return op.operate( arg ) ;
  94. } catch (java.lang.Exception exc) {
  95. return null ;
  96. }
  97. }
  98. public String toString()
  99. {
  100. return "maskErrorAction(" + op + ")" ;
  101. }
  102. }
  103. public static Operation maskErrorAction( Operation op )
  104. {
  105. return new MaskErrorAction( op ) ;
  106. }
  107. private static class IndexAction extends OperationBase
  108. {
  109. private int index ;
  110. public IndexAction( int index )
  111. {
  112. this.index = index ;
  113. }
  114. public Object operate( Object value )
  115. {
  116. return getObjectArray( value )[ index ] ;
  117. }
  118. public String toString()
  119. {
  120. return "indexAction(" + index + ")" ;
  121. }
  122. }
  123. public static Operation indexAction( int index )
  124. {
  125. return new IndexAction( index ) ;
  126. }
  127. private static class SuffixAction extends OperationBase
  128. {
  129. public Object operate( Object value )
  130. {
  131. return getStringPair( value ).getFirst() ;
  132. }
  133. public String toString() { return "suffixAction" ; }
  134. }
  135. private static Operation suffixActionImpl = new SuffixAction() ;
  136. private static class ValueAction extends OperationBase
  137. {
  138. public Object operate( Object value )
  139. {
  140. return getStringPair( value ).getSecond() ;
  141. }
  142. public String toString() { return "valueAction" ; }
  143. }
  144. private static Operation valueActionImpl = new ValueAction() ;
  145. private static class IdentityAction extends OperationBase
  146. {
  147. public Object operate( Object value )
  148. {
  149. return value ;
  150. }
  151. public String toString() { return "identityAction" ; }
  152. }
  153. private static Operation identityActionImpl = new IdentityAction() ;
  154. private static class BooleanAction extends OperationBase
  155. {
  156. public Object operate( Object value )
  157. {
  158. return new Boolean( getString( value ) ) ;
  159. }
  160. public String toString() { return "booleanAction" ; }
  161. }
  162. private static Operation booleanActionImpl = new BooleanAction() ;
  163. private static class IntegerAction extends OperationBase
  164. {
  165. public Object operate( Object value )
  166. {
  167. return new Integer( getString( value ) ) ;
  168. }
  169. public String toString() { return "integerAction" ; }
  170. }
  171. private static Operation integerActionImpl = new IntegerAction() ;
  172. private static class StringAction extends OperationBase
  173. {
  174. public Object operate( Object value )
  175. {
  176. return value ;
  177. }
  178. public String toString() { return "stringAction" ; }
  179. }
  180. private static Operation stringActionImpl = new StringAction() ;
  181. private static class ClassAction extends OperationBase
  182. {
  183. public Object operate( Object value )
  184. {
  185. String className = getString( value ) ;
  186. try {
  187. Class result = ORBClassLoader.loadClass( className ) ;
  188. return result ;
  189. } catch (Exception exc) {
  190. ORBUtilSystemException wrapper = ORBUtilSystemException.get(
  191. CORBALogDomains.ORB_LIFECYCLE ) ;
  192. throw wrapper.couldNotLoadClass( exc, className ) ;
  193. }
  194. }
  195. public String toString() { return "classAction" ; }
  196. }
  197. private static Operation classActionImpl = new ClassAction() ;
  198. private static class SetFlagAction extends OperationBase
  199. {
  200. public Object operate( Object value )
  201. {
  202. return Boolean.TRUE ;
  203. }
  204. public String toString() { return "setFlagAction" ; }
  205. }
  206. private static Operation setFlagActionImpl = new SetFlagAction() ;
  207. private static class URLAction extends OperationBase
  208. {
  209. public Object operate( Object value )
  210. {
  211. String val = (String)value ;
  212. try {
  213. return new URL( val ) ;
  214. } catch (MalformedURLException exc) {
  215. ORBUtilSystemException wrapper = ORBUtilSystemException.get(
  216. CORBALogDomains.ORB_LIFECYCLE ) ;
  217. throw wrapper.badUrl( exc, val ) ;
  218. }
  219. }
  220. public String toString() { return "URLAction" ; }
  221. }
  222. private static Operation URLActionImpl = new URLAction() ;
  223. public static Operation identityAction()
  224. {
  225. return identityActionImpl ;
  226. }
  227. public static Operation suffixAction()
  228. {
  229. return suffixActionImpl ;
  230. }
  231. public static Operation valueAction()
  232. {
  233. return valueActionImpl ;
  234. }
  235. public static Operation booleanAction()
  236. {
  237. return booleanActionImpl ;
  238. }
  239. public static Operation integerAction()
  240. {
  241. return integerActionImpl ;
  242. }
  243. public static Operation stringAction()
  244. {
  245. return stringActionImpl ;
  246. }
  247. public static Operation classAction()
  248. {
  249. return classActionImpl ;
  250. }
  251. public static Operation setFlagAction()
  252. {
  253. return setFlagActionImpl ;
  254. }
  255. public static Operation URLAction()
  256. {
  257. return URLActionImpl ;
  258. }
  259. private static class IntegerRangeAction extends OperationBase
  260. {
  261. private int min ;
  262. private int max ;
  263. IntegerRangeAction( int min, int max )
  264. {
  265. this.min = min ;
  266. this.max = max ;
  267. }
  268. public Object operate( Object value )
  269. {
  270. int result = Integer.parseInt( getString( value ) ) ;
  271. if ((result >= min) && (result <= max))
  272. return new Integer( result ) ;
  273. else
  274. throw new IllegalArgumentException(
  275. "Property value " + result + " is not in the range " +
  276. min + " to " + max ) ;
  277. }
  278. public String toString() {
  279. return "integerRangeAction(" + min + "," + max + ")" ;
  280. }
  281. }
  282. public static Operation integerRangeAction( int min, int max )
  283. {
  284. return new IntegerRangeAction( min, max ) ;
  285. }
  286. private static class ListAction extends OperationBase {
  287. private String sep ;
  288. private Operation act ;
  289. ListAction( String sep, Operation act )
  290. {
  291. this.sep = sep ;
  292. this.act = act ;
  293. }
  294. // Note that this method carefully constructs an array of the type
  295. // of the first result, rather than just using Object[], which is
  296. // not convertible into the correct type. Also note that no tokens
  297. // results in a null result.
  298. public Object operate( Object value )
  299. {
  300. StringTokenizer st = new StringTokenizer( getString( value ),
  301. sep ) ;
  302. int length = st.countTokens() ;
  303. Object result = null ;
  304. int ctr = 0 ;
  305. while (st.hasMoreTokens()) {
  306. String next = st.nextToken() ;
  307. Object val = act.operate( next ) ;
  308. if (result == null)
  309. result = Array.newInstance( val.getClass(), length ) ;
  310. Array.set( result, ctr++, val ) ;
  311. }
  312. return result ;
  313. }
  314. public String toString() {
  315. return "listAction(separator=\"" + sep +
  316. "\",action=" + act + ")" ;
  317. }
  318. }
  319. public static Operation listAction( String sep, Operation act )
  320. {
  321. return new ListAction( sep, act ) ;
  322. }
  323. private static class SequenceAction extends OperationBase
  324. {
  325. private String sep ;
  326. private Operation[] actions ;
  327. SequenceAction( String sep, Operation[] actions )
  328. {
  329. this.sep = sep ;
  330. this.actions = actions ;
  331. }
  332. public Object operate( Object value )
  333. {
  334. StringTokenizer st = new StringTokenizer( getString( value ),
  335. sep ) ;
  336. int numTokens = st.countTokens() ;
  337. if (numTokens != actions.length)
  338. throw new Error(
  339. "Number of tokens and number of actions do not match" ) ;
  340. int ctr = 0 ;
  341. Object[] result = new Object[ numTokens ] ;
  342. while (st.hasMoreTokens()) {
  343. Operation act = actions[ctr] ;
  344. String next = st.nextToken() ;
  345. result[ctr++] = act.operate( next ) ;
  346. }
  347. return result ;
  348. }
  349. public String toString() {
  350. return "sequenceAction(separator=\"" + sep +
  351. "\",actions=" +
  352. ObjectUtility.compactObjectToString(actions) + ")" ;
  353. }
  354. }
  355. public static Operation sequenceAction( String sep,
  356. Operation[] actions )
  357. {
  358. return new SequenceAction( sep, actions ) ;
  359. }
  360. private static class ComposeAction extends OperationBase
  361. {
  362. private Operation op1 ;
  363. private Operation op2 ;
  364. ComposeAction( Operation op1, Operation op2 )
  365. {
  366. this.op1 = op1 ;
  367. this.op2 = op2 ;
  368. }
  369. public Object operate( Object value )
  370. {
  371. return op2.operate( op1.operate( value ) ) ;
  372. }
  373. public String toString() {
  374. return "composition(" + op1 + "," + op2 + ")" ;
  375. }
  376. }
  377. public static Operation compose( Operation op1, Operation op2 )
  378. {
  379. return new ComposeAction( op1, op2 ) ;
  380. }
  381. private static class MapAction extends OperationBase
  382. {
  383. Operation op ;
  384. MapAction( Operation op )
  385. {
  386. this.op = op ;
  387. }
  388. public Object operate( Object value )
  389. {
  390. Object[] values = (Object[])value ;
  391. Object[] result = new Object[ values.length ] ;
  392. for (int ctr=0; ctr<values.length; ctr++ )
  393. result[ctr] = op.operate( values[ctr] ) ;
  394. return result ;
  395. }
  396. public String toString() {
  397. return "mapAction(" + op + ")" ;
  398. }
  399. }
  400. public static Operation mapAction( Operation op )
  401. {
  402. return new MapAction( op ) ;
  403. }
  404. private static class MapSequenceAction extends OperationBase
  405. {
  406. private Operation[] op ;
  407. public MapSequenceAction( Operation[] op )
  408. {
  409. this.op = op ;
  410. }
  411. // XXX Does this correctly handle array types? It seems
  412. // that hetereogeneous arrays work this way, while
  413. // homogeneous arrays need to use Array.newInstance tricks.
  414. public Object operate( Object value )
  415. {
  416. Object[] values = (Object[])value ;
  417. Object[] result = new Object[ values.length ] ;
  418. for (int ctr=0; ctr<values.length; ctr++ )
  419. result[ctr] = op[ctr].operate( values[ctr] ) ;
  420. return result ;
  421. }
  422. public String toString() {
  423. return "mapSequenceAction(" +
  424. ObjectUtility.compactObjectToString(op) + ")" ;
  425. }
  426. }
  427. public static Operation mapSequenceAction( Operation[] op )
  428. {
  429. return new MapSequenceAction( op ) ;
  430. }
  431. private static class ConvertIntegerToShort extends OperationBase
  432. {
  433. public Object operate( Object value )
  434. {
  435. Integer val = (Integer)value ;
  436. return new Short( val.shortValue() ) ;
  437. }
  438. public String toString() {
  439. return "ConvertIntegerToShort" ;
  440. }
  441. }
  442. private static Operation convertIntegerToShortImpl = new ConvertIntegerToShort() ;
  443. public static Operation convertIntegerToShort()
  444. {
  445. return convertIntegerToShortImpl ;
  446. }
  447. }