001: package org.jacorb.orb;
002:
003: /*
004: * JacORB - a free Java ORB
005: *
006: * Copyright (C) 1997-2004 Gerald Brose.
007: *
008: * This library is free software; you can redistribute it and/or
009: * modify it under the terms of the GNU Library General Public
010: * License as published by the Free Software Foundation; either
011: * version 2 of the License, or (at your option) any later version.
012: *
013: * This library is distributed in the hope that it will be useful,
014: * but WITHOUT ANY WARRANTY; without even the implied warranty of
015: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
016: * Library General Public License for more details.
017: *
018: * You should have received a copy of the GNU Library General Public
019: * License along with this library; if not, write to the Free
020: * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
021: */
022:
023: import java.util.HashSet;
024:
025: import org.jacorb.config.JacORBConfiguration;
026: import org.omg.CORBA.INTERNAL;
027: import org.omg.CORBA.TypeCode;
028: import org.omg.CORBA.BAD_PARAM;
029: import org.omg.CORBA.BAD_TYPECODE;
030: import org.omg.CORBA.TCKind;
031: import org.omg.CORBA.CompletionStatus;
032:
033: import org.apache.avalon.framework.configuration.*;
034: import org.apache.avalon.framework.logger.Logger;
035:
036: /**
037: * @author Gerald Brose, FU Berlin
038: * @version $Id: ORBSingleton.java,v 1.50 2006/09/10 09:53:19 andre.spiegel Exp $
039: */
040:
041: public class ORBSingleton extends org.omg.CORBA_2_5.ORB {
042: private static final String FACTORY_METHODS_MESG = "The Singleton ORB only permits factory methods";
043:
044: private boolean doStrictCheckOnTypecodeCreation;
045: private Logger logger;
046:
047: /**
048: * in case a singleton orb is created the c'tor will access the JacORB configuration
049: * to configure the orb. otherwise configure needs to be called to properly set up
050: * the created instance.
051: *
052: * @param isSingleton determine if a singleton orb is created.
053: */
054: protected ORBSingleton(boolean isSingleton) {
055: super ();
056:
057: try {
058: if (isSingleton) {
059: Configuration configuration = JacORBConfiguration
060: .getConfiguration(null, null, false);
061:
062: // Don't call configure method as if this has been called from ORB::ctor
063: // class construction order can cause issues.
064: logger = ((org.jacorb.config.Configuration) configuration)
065: .getNamedLogger("jacorb.orb.singleton");
066:
067: doStrictCheckOnTypecodeCreation = configuration
068: .getAttributeAsBoolean(
069: "jacorb.interop.strict_check_on_tc_creation",
070: true);
071:
072: if (logger.isDebugEnabled()) {
073: logger
074: .debug("jacorb.interop.strict_check_on_tc_creation set to "
075: + doStrictCheckOnTypecodeCreation);
076: }
077: logger.info("created ORBSingleton");
078: }
079: } catch (ConfigurationException e) {
080: throw new INTERNAL(e.toString());
081: }
082: }
083:
084: public ORBSingleton() {
085: this (true);
086: }
087:
088: protected void configure(Configuration configuration)
089: throws ConfigurationException {
090: logger = ((org.jacorb.config.Configuration) configuration)
091: .getNamedLogger("jacorb.orb");
092:
093: doStrictCheckOnTypecodeCreation = configuration
094: .getAttributeAsBoolean(
095: "jacorb.interop.strict_check_on_tc_creation",
096: true);
097:
098: if (logger.isDebugEnabled()) {
099: logger
100: .debug("jacorb.interop.strict_check_on_tc_creation set to "
101: + doStrictCheckOnTypecodeCreation);
102: }
103: }
104:
105: /**
106: * Returns the logger of this singleton ORB. Used for testing.
107: */
108: public Logger getLogger() {
109: return logger;
110: }
111:
112: /* factory methods: */
113:
114: public org.omg.CORBA.Any create_any() {
115: return new org.jacorb.orb.Any(this );
116: }
117:
118: /**
119: * Determine if a character is ok to start an id.
120: * (Note that '_' is allowed here - it might have
121: * been inserted by the IDL compiler to avoid clashes
122: * with reserved Java identifiers )
123: * @param character the character in question.
124: */
125:
126: final protected static boolean legalStartChar(int character) {
127: return (character >= 'a' && character <= 'z')
128: || (character == '_')
129: || (character >= 'A' && character <= 'Z');
130: }
131:
132: /**
133: * Determine if a character is ok for the middle of an id.
134: * @param ch the character in question.
135: */
136: final protected static boolean legalNameChar(int ch) {
137: return legalStartChar(ch) || (ch == '_')
138: || (ch >= '0' && ch <= '9');
139: }
140:
141: /**
142: * code>checkTCName</code> checks that a name is a legal IDL name
143: * (CORBA 2.6 4-59).
144: * @throws org.omg.CORBA.BAD_PARAM
145: */
146: private void checkTCName(String name) throws BAD_PARAM {
147: checkTCName(name, false);
148: }
149:
150: /**
151: * <code>checkTCName</code> checks the name is a legal IDL name and
152: * may optionally allow a null string (CORBA 2.6 4-59).
153: *
154: * @param name a <code>String</code> value
155: * @param allowNull a <code>boolean</code> value
156: * @exception BAD_PARAM if an error occurs
157: */
158: private void checkTCName(String name, boolean allowNull)
159: throws BAD_PARAM {
160: if (name == null) {
161: if (allowNull) {
162: return;
163: }
164:
165: throw new BAD_PARAM("Illegal null IDL name", 15,
166: CompletionStatus.COMPLETED_NO);
167: }
168:
169: if (name.length() > 0) {
170: // check that name begins with an ASCII char
171: if (!legalStartChar(name.charAt(0))) {
172: throw new BAD_PARAM(
173: "Illegal start character to IDL name: " + name,
174: 15, CompletionStatus.COMPLETED_NO);
175: }
176: for (int i = 0; i < name.length(); i++) {
177: if (!legalNameChar(name.charAt(i))) {
178: throw new BAD_PARAM("Illegal IDL name: " + name,
179: 15, CompletionStatus.COMPLETED_NO);
180: }
181: }
182: } else {
183: throw new BAD_PARAM("Illegal blank IDL name", 15,
184: CompletionStatus.COMPLETED_NO);
185: }
186: }
187:
188: /**
189: * Check that a repository ID is legal
190: * (cf. CORBA 2.4 chapter 10, section 7.3
191: * @param repId a <code>String</code> value
192: * @exception BAD_PARAM if an error occurs
193: */
194: private void checkTCRepositoryId(String repId) throws BAD_PARAM {
195: if (repId == null || repId.indexOf(':') < 0) {
196: throw new BAD_PARAM("Illegal Repository ID: " + repId, 16,
197: CompletionStatus.COMPLETED_NO);
198: }
199: }
200:
201: /**
202: * check that a type is a legal member type
203: * (cf. CORBA 2.4 chapter 10, section 7.3
204: * @throws org.omg.CORBA.BAD_PARAM
205: */
206:
207: private void checkTCMemberType(TypeCode typeCode)
208: throws BAD_TYPECODE {
209: if (!org.jacorb.orb.TypeCode.isRecursive(typeCode)
210: && (typeCode == null
211: || typeCode.kind().value() == TCKind._tk_null
212: || typeCode.kind().value() == TCKind._tk_void || typeCode
213: .kind().value() == TCKind._tk_except)) {
214: throw new BAD_TYPECODE("Illegal member TypeCode", 2,
215: CompletionStatus.COMPLETED_NO);
216: }
217: }
218:
219: /* TypeCode factory section */
220:
221: public TypeCode create_alias_tc(String id, String name,
222: TypeCode original_type) {
223: checkTCRepositoryId(id);
224: checkTCName(name, true);
225: checkTCMemberType(original_type);
226: return new org.jacorb.orb.TypeCode(
227: org.omg.CORBA.TCKind._tk_alias, id, name, original_type);
228: }
229:
230: public TypeCode create_array_tc(int length, TypeCode element_type) {
231: checkTCMemberType(element_type);
232: return new org.jacorb.orb.TypeCode(
233: org.omg.CORBA.TCKind._tk_array, length, element_type);
234: }
235:
236: public TypeCode create_enum_tc(String id, String name,
237: String[] members) {
238: return create_enum_tc(id, name, members, true);
239: }
240:
241: /**
242: * Allows the possibility of not checking the name when creating this
243: * typecode. This is to cater for compact typecodes where the name
244: * may not be set. Checking of the name will always be true for user
245: * driven requests
246: * @param id
247: * @param name
248: * @param members
249: * @param checkName
250: * @returns TypeCode
251: */
252: TypeCode create_enum_tc(String id, String name, String[] members,
253: boolean checkName) {
254: checkTCRepositoryId(id);
255: checkTCName(name, true);
256:
257: if (checkName) {
258: // check that member names are legal and unique
259: final HashSet names = new HashSet();
260: for (int i = 0; i < members.length; i++) {
261: boolean fault = false;
262:
263: try {
264: checkTCName(members[i]);
265: } catch (BAD_PARAM e) {
266: fault = true;
267: logger.debug("Typecode name check failed", e);
268: }
269:
270: if ((members[i] != null && names.contains(members[i]))
271: || fault) {
272: throw new BAD_PARAM("Illegal enum member name: "
273: + members[i], 17,
274: CompletionStatus.COMPLETED_NO);
275: }
276: names.add(members[i]);
277: }
278: }
279:
280: return new org.jacorb.orb.TypeCode(id, name, members);
281: }
282:
283: public TypeCode create_exception_tc(String id, String name,
284: org.omg.CORBA.StructMember[] members) {
285: return create_exception_tc(id, name, members, true);
286: }
287:
288: /**
289: * Allows the possibility of not checking the name when creating this
290: * typecode. This is to cater for compact typecodes where the name
291: * may not be set. Checking of the name will always be true for user
292: * driven requests
293: * @param id
294: * @param name
295: * @param members
296: * @param checkName
297: * @returns TypeCode
298: */
299: TypeCode create_exception_tc(String id, String name,
300: org.omg.CORBA.StructMember[] members, boolean checkName) {
301: checkTCRepositoryId(id);
302: checkTCName(name, true);
303:
304: // check that member names are legal and unique
305: final HashSet names = new HashSet();
306: for (int i = 0; i < members.length; i++) {
307: checkTCMemberType(members[i].type);
308:
309: if (checkName) {
310: boolean fault = false;
311:
312: try {
313: checkTCName(members[i].name);
314: } catch (BAD_PARAM e) {
315: fault = true;
316: logger.debug("Typecode name check failed", e);
317: }
318:
319: if ((members[i].name != null && names
320: .contains(members[i].name))
321: || fault) {
322: throw new BAD_PARAM(
323: "Illegal exception member name: "
324: + members[i].name, 17,
325: CompletionStatus.COMPLETED_NO);
326: }
327: names.add(members[i].name);
328: }
329: }
330:
331: return new org.jacorb.orb.TypeCode(
332: org.omg.CORBA.TCKind._tk_except, id, name, members);
333: }
334:
335: public TypeCode create_interface_tc(String id, String name) {
336: checkTCRepositoryId(id);
337: checkTCName(name, true);
338: return new org.jacorb.orb.TypeCode(
339: org.omg.CORBA.TCKind._tk_objref, id, name);
340: }
341:
342: public org.omg.CORBA.TypeCode create_fixed_tc(short digits,
343: short scale) {
344: if (digits <= 0 || scale < 0 || scale > digits) {
345: throw new org.omg.CORBA.BAD_PARAM(
346: "Invalid combination of digits and scale factor");
347: }
348: return new org.jacorb.orb.TypeCode(digits, scale);
349: }
350:
351: public org.omg.CORBA.TypeCode create_recursive_tc(String id) {
352: checkTCRepositoryId(id);
353: return new org.jacorb.orb.TypeCode(id);
354: }
355:
356: public TypeCode create_sequence_tc(int bound, TypeCode element_type) {
357: checkTCMemberType(element_type);
358: TypeCode typeCode = new org.jacorb.orb.TypeCode(
359: org.omg.CORBA.TCKind._tk_sequence, bound, element_type);
360: return typeCode;
361: }
362:
363: public TypeCode create_string_tc(int bound) {
364: return new org.jacorb.orb.TypeCode(
365: org.omg.CORBA.TCKind._tk_string, bound);
366: }
367:
368: public TypeCode create_wstring_tc(int bound) {
369: return new org.jacorb.orb.TypeCode(
370: org.omg.CORBA.TCKind._tk_wstring, bound);
371: }
372:
373: public TypeCode create_struct_tc(String id, String name,
374: org.omg.CORBA.StructMember[] members) {
375: return create_struct_tc(id, name, members, true);
376: }
377:
378: /**
379: * Allows the possibility of not checking the name when creating this
380: * typecode. This is to cater for compact typecodes where the name
381: * may not be set. Checking of the name will always be true for user
382: * driven requests
383: * @param id
384: * @param name
385: * @param members
386: * @param checkName
387: * @returns TypeCode
388: */
389: TypeCode create_struct_tc(String id, String name,
390: org.omg.CORBA.StructMember[] members, boolean checkName) {
391: checkTCRepositoryId(id);
392: checkTCName(name, true);
393:
394: // check that member names are legal and unique
395: final HashSet names = new HashSet();
396: for (int i = 0; i < members.length; i++) {
397: if (checkName) {
398: checkTCMemberType(members[i].type);
399: boolean fault = false;
400:
401: try {
402: checkTCName(members[i].name);
403: } catch (BAD_PARAM e) {
404: fault = true;
405: logger.debug("Typecode name check failed", e);
406: }
407:
408: if ((members[i].name != null && names
409: .contains(members[i].name))
410: || fault) {
411: throw new BAD_PARAM("Illegal struct member name: "
412: + members[i].name
413: + (fault ? " (Bad PARAM) " : ""), 17,
414: CompletionStatus.COMPLETED_NO);
415: }
416: names.add(members[i].name);
417: }
418: }
419:
420: org.jacorb.orb.TypeCode typeCode = new org.jacorb.orb.TypeCode(
421: org.omg.CORBA.TCKind._tk_struct, id, name, members);
422:
423: // resolve any recursive references to this TypeCode in its members
424: typeCode.resolveRecursion();
425: return typeCode;
426: }
427:
428: public TypeCode create_union_tc(String id, String name,
429: TypeCode discriminator_type,
430: org.omg.CORBA.UnionMember[] members) {
431: return create_union_tc(id, name, discriminator_type, members,
432: true);
433: }
434:
435: /**
436: * Allows the possibility of not checking the name when creating this
437: * typecode. This is to cater for compact typecodes where the name
438: * may not be set. Checking of the name will always be true for user
439: * driven requests
440: * @param id
441: * @param name
442: * @param members
443: * @param checkName
444: * @returns TypeCode
445: */
446: TypeCode create_union_tc(String id, String name,
447: TypeCode discriminator_type,
448: org.omg.CORBA.UnionMember[] members, boolean checkName) {
449: checkTCRepositoryId(id);
450: checkTCName(name, true);
451:
452: // check discriminator type
453:
454: TypeCode disc_tc = org.jacorb.orb.TypeCode
455: .originalType(discriminator_type);
456:
457: if (disc_tc == null
458: || !(disc_tc.kind().value() == TCKind._tk_short
459: || disc_tc.kind().value() == TCKind._tk_long
460: || disc_tc.kind().value() == TCKind._tk_longlong
461: || disc_tc.kind().value() == TCKind._tk_ushort
462: || disc_tc.kind().value() == TCKind._tk_ulong
463: || disc_tc.kind().value() == TCKind._tk_ulonglong
464: || disc_tc.kind().value() == TCKind._tk_char
465: || disc_tc.kind().value() == TCKind._tk_boolean || disc_tc
466: .kind().value() == TCKind._tk_enum)) {
467: throw new BAD_PARAM("Illegal union discriminator type", 20,
468: CompletionStatus.COMPLETED_NO);
469: }
470:
471: // check that member names are legal (they do not need to be unique)
472:
473: for (int i = 0; i < members.length; i++) {
474: checkTCMemberType(members[i].type);
475:
476: if (checkName) {
477: try {
478: checkTCName(members[i].name);
479: } catch (BAD_PARAM e) {
480: logger.debug("Typecode name check failed", e);
481: throw new BAD_PARAM("Illegal union member name: "
482: + members[i].name, 17,
483: CompletionStatus.COMPLETED_NO);
484: }
485: }
486:
487: // check that member type matches discriminator type or is default
488:
489: org.omg.CORBA.Any label = members[i].label;
490: if (!discriminator_type.equivalent(label.type())
491: && !(label.type().kind().value() == TCKind._tk_octet && label
492: .extract_octet() == (byte) 0)) {
493: throw new BAD_PARAM(
494: "Label type does not match discriminator type",
495: 19, CompletionStatus.COMPLETED_NO);
496: }
497:
498: // check that member labels are unique
499:
500: for (int j = 0; j < i; j++) {
501: if (label.equal(members[j].label)) {
502: throw new BAD_PARAM("Duplicate union case label",
503: 18, CompletionStatus.COMPLETED_NO);
504: }
505: }
506: }
507:
508: org.jacorb.orb.TypeCode typeCode = new org.jacorb.orb.TypeCode(
509: id, name, discriminator_type, members);
510:
511: // resolve any recursive references to this TypeCode in its members
512: typeCode.resolveRecursion();
513: return typeCode;
514: }
515:
516: public TypeCode get_primitive_tc(org.omg.CORBA.TCKind tcKind) {
517: return org.jacorb.orb.TypeCode.get_primitive_tc(tcKind.value());
518: }
519:
520: public org.omg.CORBA.TypeCode create_value_tc(String id,
521: String name, short type_modifier, TypeCode concrete_base,
522: org.omg.CORBA.ValueMember[] members) {
523: checkTCRepositoryId(id);
524:
525: // The name parameter should be a valid IDL name, but in the case of
526: // an RMI valuetype the ORB in jdk1.4 sends a dotted name (such as
527: // "some.package.SomeClass") over the wire. For interoperability with
528: // Sun's ORB we skip the name check in this case.
529:
530: if (!id.startsWith("RMI:")) {
531: checkTCName(name, true);
532: }
533: return new org.jacorb.orb.TypeCode(id, name, type_modifier,
534: concrete_base, members);
535: }
536:
537: public org.omg.CORBA.TypeCode create_value_box_tc(String id,
538: String name, TypeCode boxed_type) {
539: checkTCRepositoryId(id);
540: checkTCName(name, true);
541: return new org.jacorb.orb.TypeCode(
542: org.omg.CORBA.TCKind._tk_value_box, id, name,
543: boxed_type);
544: }
545:
546: public org.omg.CORBA.TypeCode create_abstract_interface_tc(
547: String id, String name) {
548: checkTCRepositoryId(id);
549:
550: // strict_check_on_tc_creation is incompatible with Sun's ValueHandler,
551: // which calls create_abstract_interface_tc() passing an empty string
552: // as the name parameter. checkTCName() then throws
553: //`org.omg.CORBA.BAD_PARAM: Illegal blank IDL name'.
554: if (doStrictCheckOnTypecodeCreation) {
555: checkTCName(name, true);
556: }
557:
558: return new org.jacorb.orb.TypeCode(
559: org.omg.CORBA.TCKind._tk_abstract_interface, id, name);
560: }
561:
562: public org.omg.CORBA.TypeCode create_local_interface_tc(String id,
563: String name) {
564: checkTCRepositoryId(id);
565: checkTCName(name, true);
566: return new org.jacorb.orb.TypeCode(
567: org.omg.CORBA.TCKind._tk_local_interface, id, name);
568: }
569:
570: public org.omg.CORBA.TypeCode create_native_tc(String id,
571: String name) {
572: checkTCRepositoryId(id);
573: checkTCName(name, true);
574: return new org.jacorb.orb.TypeCode(
575: org.omg.CORBA.TCKind._tk_native, id, name);
576: }
577:
578: /* not allowed on the singleton: */
579:
580: public org.omg.CORBA.ExceptionList create_exception_list() {
581: throw new org.omg.CORBA.NO_IMPLEMENT(FACTORY_METHODS_MESG);
582: }
583:
584: public org.omg.CORBA.NVList create_list(int count) {
585: throw new org.omg.CORBA.NO_IMPLEMENT(FACTORY_METHODS_MESG);
586: }
587:
588: public org.omg.CORBA.NamedValue create_named_value(String name,
589: org.omg.CORBA.Any value, int flags) {
590: throw new org.omg.CORBA.NO_IMPLEMENT(FACTORY_METHODS_MESG);
591: }
592:
593: public org.omg.CORBA.NVList create_operation_list(
594: org.omg.CORBA.OperationDef oper) {
595: throw new org.omg.CORBA.NO_IMPLEMENT(FACTORY_METHODS_MESG);
596: }
597:
598: public org.omg.CORBA.NVList create_operation_list(
599: org.omg.CORBA.Object obj) {
600: throw new org.omg.CORBA.NO_IMPLEMENT(FACTORY_METHODS_MESG);
601: }
602:
603: public org.omg.CORBA.Object string_to_object(String str) {
604: throw new org.omg.CORBA.NO_IMPLEMENT(FACTORY_METHODS_MESG);
605: }
606:
607: public org.omg.CORBA.Environment create_environment() {
608: throw new org.omg.CORBA.NO_IMPLEMENT(FACTORY_METHODS_MESG);
609: }
610:
611: public org.omg.CORBA.ContextList create_context_list() {
612: throw new org.omg.CORBA.NO_IMPLEMENT(FACTORY_METHODS_MESG);
613: }
614:
615: public org.omg.CORBA.portable.OutputStream create_output_stream() {
616: throw new org.omg.CORBA.NO_IMPLEMENT(FACTORY_METHODS_MESG);
617: }
618:
619: public org.omg.CORBA.Current get_current() {
620: throw new org.omg.CORBA.NO_IMPLEMENT(FACTORY_METHODS_MESG);
621: }
622:
623: public org.omg.CORBA.Context get_default_context() {
624: throw new org.omg.CORBA.NO_IMPLEMENT(FACTORY_METHODS_MESG);
625: }
626:
627: public org.omg.CORBA.Request get_next_response() {
628: throw new org.omg.CORBA.NO_IMPLEMENT(FACTORY_METHODS_MESG);
629: }
630:
631: public String[] list_initial_services() {
632: throw new org.omg.CORBA.NO_IMPLEMENT(FACTORY_METHODS_MESG);
633: }
634:
635: public String object_to_string(org.omg.CORBA.Object obj) {
636: throw new org.omg.CORBA.NO_IMPLEMENT(FACTORY_METHODS_MESG);
637: }
638:
639: public boolean poll_next_response() {
640: throw new org.omg.CORBA.NO_IMPLEMENT(FACTORY_METHODS_MESG);
641: }
642:
643: public org.omg.CORBA.Object resolve_initial_references(
644: String identifier)
645: throws org.omg.CORBA.ORBPackage.InvalidName {
646: throw new org.omg.CORBA.NO_IMPLEMENT(FACTORY_METHODS_MESG);
647: }
648:
649: public void send_multiple_requests_deferred(
650: org.omg.CORBA.Request[] req) {
651: throw new org.omg.CORBA.NO_IMPLEMENT(FACTORY_METHODS_MESG);
652: }
653:
654: public void send_multiple_requests_oneway(
655: org.omg.CORBA.Request[] req) {
656: throw new org.omg.CORBA.NO_IMPLEMENT(FACTORY_METHODS_MESG);
657: }
658:
659: protected void set_parameters(String[] args,
660: java.util.Properties props) {
661: throw new org.omg.CORBA.NO_IMPLEMENT(FACTORY_METHODS_MESG);
662: }
663:
664: protected void set_parameters(java.applet.Applet app,
665: java.util.Properties props) {
666: throw new org.omg.CORBA.NO_IMPLEMENT(FACTORY_METHODS_MESG);
667: }
668:
669: public void run() {
670: throw new org.omg.CORBA.NO_IMPLEMENT(FACTORY_METHODS_MESG);
671: }
672:
673: public void shutdown(boolean wait_for_completion) {
674: throw new org.omg.CORBA.NO_IMPLEMENT(FACTORY_METHODS_MESG);
675: }
676:
677: public boolean work_pending() {
678: throw new org.omg.CORBA.NO_IMPLEMENT(FACTORY_METHODS_MESG);
679: }
680:
681: public void perform_work() {
682: throw new org.omg.CORBA.NO_IMPLEMENT(FACTORY_METHODS_MESG);
683: }
684: }
|