001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one
003: * or more contributor license agreements. See the NOTICE file
004: * distributed with this work for additional information
005: * regarding copyright ownership. The ASF licenses this file
006: * to you under the Apache License, Version 2.0 (the
007: * "License"); you may not use this file except in compliance
008: * with the License. You may obtain a copy of the License at
009: *
010: * http://www.apache.org/licenses/LICENSE-2.0
011: *
012: * Unless required by applicable law or agreed to in writing,
013: * software distributed under the License is distributed on an
014: * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015: * KIND, either express or implied. See the License for the
016: * specific language governing permissions and limitations
017: * under the License.
018: */
019:
020: package org.apache.axis2.context;
021:
022: import org.apache.axiom.om.util.UUIDGenerator;
023: import org.apache.axis2.AxisFault;
024: import org.apache.axis2.description.AxisService;
025: import org.apache.axis2.description.AxisServiceGroup;
026: import org.apache.axis2.engine.AxisConfiguration;
027: import org.apache.axis2.i18n.Messages;
028: import org.apache.axis2.util.MetaDataEntry;
029: import org.apache.axis2.util.ObjectStateUtils;
030: import org.apache.commons.logging.Log;
031: import org.apache.commons.logging.LogFactory;
032:
033: import java.io.Externalizable;
034: import java.io.IOException;
035: import java.io.ObjectInput;
036: import java.io.ObjectOutput;
037: import java.util.HashMap;
038: import java.util.Iterator;
039: import java.util.Map;
040:
041: public class ServiceGroupContext extends AbstractContext implements
042: Externalizable {
043:
044: /*
045: * setup for logging
046: */
047: private static final Log log = LogFactory
048: .getLog(ServiceGroupContext.class);
049:
050: private static final String myClassName = "ServiceGroupContext";
051:
052: /**
053: * @serial The serialization version ID tracks the version of the class.
054: * If a class definition changes, then the serialization/externalization
055: * of the class is affected. If a change to the class is made which is
056: * not compatible with the serialization/externalization of the class,
057: * then the serialization version ID should be updated.
058: * Refer to the "serialVer" utility to compute a serialization
059: * version ID.
060: */
061: private static final long serialVersionUID = 9014471144479928885L;
062:
063: /**
064: * @serial Tracks the revision level of a class to identify changes to the
065: * class definition that are compatible to serialization/externalization.
066: * If a class definition changes, then the serialization/externalization
067: * of the class is affected.
068: * Refer to the writeExternal() and readExternal() methods.
069: */
070: // supported revision levels, add a new level to manage compatible changes
071: private static final int REVISION_1 = 1;
072: // current revision level of this object
073: private static final int revisionID = REVISION_1;
074:
075: private transient AxisServiceGroup axisServiceGroup;
076: private String id;
077: private Map serviceContextMap;
078:
079: //----------------------------------------------------------------
080: // MetaData for data to be restored in activate after readExternal
081: //----------------------------------------------------------------
082:
083: /**
084: * Indicates whether the message context has been reconstituted
085: * and needs to have its object references reconciled
086: */
087: private transient boolean needsToBeReconciled = false;
088:
089: /**
090: * The AxisServiceContext metadata will be used during
091: * activate to match up with an existing object
092: */
093: private transient MetaDataEntry metaAxisServiceGroup = null;
094:
095: //----------------------------------------------------------------
096: // end MetaData section
097: //----------------------------------------------------------------
098:
099: // simple constructor
100: public ServiceGroupContext() {
101: super (null);
102: serviceContextMap = new HashMap();
103: }
104:
105: public ServiceGroupContext(ConfigurationContext parent,
106: AxisServiceGroup axisServiceGroup) {
107: super (parent);
108: this .axisServiceGroup = axisServiceGroup;
109: serviceContextMap = new HashMap();
110: // initially set the id to the axisServiceGroup
111: if (axisServiceGroup != null) {
112: setId(axisServiceGroup.getServiceGroupName());
113: }
114: }
115:
116: public AxisServiceGroup getDescription() {
117: checkActivateWarning("getDescription");
118: return axisServiceGroup;
119: }
120:
121: public String getId() {
122: return id;
123: }
124:
125: /**
126: * Gets a service context. Creates a new one from AxisService.
127: * There is no need to store service context inside serviceGroup
128: * context as well.
129: *
130: * @param service the AxisService for which to get a context
131: * @return Returns ServiceContext.
132: * @throws AxisFault if something goes wrong
133: */
134: public ServiceContext getServiceContext(AxisService service)
135: throws AxisFault {
136: AxisService axisService = axisServiceGroup.getService(service
137: .getName());
138: if (axisService == null) {
139: throw new AxisFault(Messages.getMessage(
140: "invalidserviceinagroup", service.getName(),
141: axisServiceGroup.getServiceGroupName()));
142: }
143: if (serviceContextMap == null) {
144: serviceContextMap = new HashMap();
145: }
146: ServiceContext serviceContext = (ServiceContext) serviceContextMap
147: .get(service.getName());
148: if (serviceContext == null) {
149: serviceContext = new ServiceContext(service, this );
150: getRootContext().contextCreated(serviceContext);
151: serviceContextMap.put(service.getName(), serviceContext);
152: }
153: return serviceContext;
154: }
155:
156: public Iterator getServiceContexts() {
157: if (serviceContextMap == null) {
158: serviceContextMap = new HashMap();
159: }
160: if (serviceContextMap.isEmpty()) {
161: return null;
162: }
163: return serviceContextMap.values().iterator();
164: }
165:
166: public void setId(String id) {
167: this .id = id;
168: }
169:
170: /**
171: * Adds the specified service context object to the
172: * lists of service contexts for this service group
173: * context.
174: *
175: * @param srvctx The ServiceContext object to add
176: */
177: public void addServiceContext(ServiceContext srvctx) {
178: if (srvctx == null) {
179: return;
180: }
181:
182: AxisService axisService = srvctx.getAxisService();
183:
184: if (axisService == null) {
185: return;
186: }
187:
188: if (serviceContextMap == null) {
189: serviceContextMap = new HashMap();
190: }
191:
192: serviceContextMap.put(axisService.getName(), srvctx);
193:
194: }
195:
196: /**
197: * Finds the service context object that corresponds
198: * to the specified name from the list
199: * of service contexts for this service group
200: * context.
201: *
202: * @param name The name associated with the ServiceContext
203: * @return The ServiceContext associated with the name,
204: * or null, if none can be found
205: */
206: public ServiceContext findServiceContext(String name) {
207: if (serviceContextMap == null) {
208: return null;
209: }
210:
211: return (ServiceContext) serviceContextMap.get(name);
212: }
213:
214: /**
215: * Finds the service context object that corresponds
216: * to the specified AxisService from the list
217: * of service contexts for this service group
218: * context.
219: *
220: * @param axisSrv the AxisService whose context we're looking for
221: * @return The ServiceContext associated with the AxisService
222: * or null, if none can be found
223: */
224: public ServiceContext findServiceContext(AxisService axisSrv) {
225: if (axisSrv == null) {
226: return null;
227: }
228:
229: if (serviceContextMap == null) {
230: return null;
231: }
232:
233: return (ServiceContext) serviceContextMap
234: .get(axisSrv.getName());
235: }
236:
237: /**
238: * This will do a copy of the properties from this context object
239: * to the properties of the specified context object.
240: *
241: * @param context The ServiceGroupContext object to hold the merged properties
242: */
243: public void putContextProperties(ServiceGroupContext context) {
244: if (context != null) {
245: // get the current properties on this context object
246: Map props = getProperties();
247:
248: // copy them to the specified context object
249: context.mergeProperties(props);
250: }
251: }
252:
253: /* ===============================================================
254: * Externalizable support
255: * ===============================================================
256: */
257:
258: /**
259: * Save the contents of this object.
260: * <p/>
261: * NOTE: Transient fields and static fields are not saved.
262: * Also, objects that represent "static" data are
263: * not saved, except for enough information to be
264: * able to find matching objects when the message
265: * context is re-constituted.
266: *
267: * @param out The stream to write the object contents to
268: * @throws IOException
269: */
270: public void writeExternal(ObjectOutput out) throws IOException {
271: // write out contents of this object
272:
273: //---------------------------------------------------------
274: // in order to handle future changes to the message
275: // context definition, be sure to maintain the
276: // object level identifiers
277: //---------------------------------------------------------
278: // serialization version ID
279: out.writeLong(serialVersionUID);
280:
281: // revision ID
282: out.writeInt(revisionID);
283:
284: //---------------------------------------------------------
285: // various simple fields
286: //---------------------------------------------------------
287:
288: out.writeLong(getLastTouchedTime());
289:
290: if (id == null) {
291: // generate an ID to use when this object is restored
292: id = UUIDGenerator.getUUID();
293: }
294:
295: ObjectStateUtils.writeString(out, id, "ServiceGroupContext.id");
296:
297: //---------------------------------------------------------
298: // properties
299: //---------------------------------------------------------
300: Map tmpMap = getProperties();
301:
302: HashMap tmpHashMap = null;
303:
304: if ((tmpMap != null) && (!tmpMap.isEmpty())) {
305: tmpHashMap = new HashMap(tmpMap);
306: }
307:
308: ObjectStateUtils.writeHashMap(out, tmpHashMap,
309: "ServiceGroupContext.properties");
310:
311: //---------------------------------------------------------
312: // AxisServiceGroup
313: //---------------------------------------------------------
314:
315: String axisServGrpMarker = "ServiceGroupContext.axisServiceGroup";
316: ObjectStateUtils.writeString(out, axisServGrpMarker,
317: axisServGrpMarker);
318:
319: if (axisServiceGroup == null) {
320: out.writeBoolean(ObjectStateUtils.EMPTY_OBJECT);
321: } else {
322: out.writeBoolean(ObjectStateUtils.ACTIVE_OBJECT);
323: metaAxisServiceGroup = new MetaDataEntry(axisServiceGroup
324: .getClass().getName(), axisServiceGroup
325: .getServiceGroupName());
326: ObjectStateUtils.writeObject(out, metaAxisServiceGroup,
327: "ServiceGroupContext.metaAxisServiceGroup");
328: }
329:
330: //---------------------------------------------------------
331: // parent
332: //---------------------------------------------------------
333:
334: // the parent is the ConfigurationContext object, which
335: // at this time, is not being saved.
336: // instead, we will need to register this ServiceGroupObject
337: // with the existing ConfigurationContext object when
338: // this object is reconstituted
339:
340: }
341:
342: /**
343: * Restore the contents of the object that was previously saved.
344: * <p/>
345: * NOTE: The field data must read back in the same order and type
346: * as it was written. Some data will need to be validated when
347: * resurrected.
348: *
349: * @param in The stream to read the object contents from
350: * @throws IOException
351: * @throws ClassNotFoundException
352: */
353: public void readExternal(ObjectInput in) throws IOException,
354: ClassNotFoundException {
355: // set the flag to indicate that the message context is being
356: // reconstituted and will need to have certain object references
357: // to be reconciled with the current engine setup
358: needsToBeReconciled = true;
359:
360: // trace point
361: if (log.isTraceEnabled()) {
362: log
363: .trace(myClassName
364: + ":readExternal(): BEGIN bytes available in stream ["
365: + in.available() + "] ");
366: }
367:
368: // serialization version ID
369: long suid = in.readLong();
370:
371: // revision ID
372: int revID = in.readInt();
373:
374: // make sure the object data is in a version we can handle
375: if (suid != serialVersionUID) {
376: throw new ClassNotFoundException(
377: ObjectStateUtils.UNSUPPORTED_SUID);
378: }
379:
380: // make sure the object data is in a revision level we can handle
381: if (revID != REVISION_1) {
382: throw new ClassNotFoundException(
383: ObjectStateUtils.UNSUPPORTED_REVID);
384: }
385:
386: //---------------------------------------------------------
387: // various simple fields
388: //---------------------------------------------------------
389:
390: long time = in.readLong();
391: setLastTouchedTime(time);
392:
393: id = ObjectStateUtils.readString(in, "ServiceGroupContext.id");
394:
395: //---------------------------------------------------------
396: // properties
397: //---------------------------------------------------------
398:
399: HashMap tmpHashMap = ObjectStateUtils.readHashMap(in,
400: "ServiceGroupContext.properties");
401:
402: properties = new HashMap();
403: if (tmpHashMap != null) {
404: setProperties(tmpHashMap);
405: }
406:
407: //---------------------------------------------------------
408: // AxisServiceGroup
409: //---------------------------------------------------------
410:
411: // axisServiceGroup is not usable until the meta data has been reconciled
412: axisServiceGroup = null;
413:
414: ObjectStateUtils.readString(in,
415: "ServiceGroupContext.axisServiceGroup");
416:
417: boolean metaAxisServiceGrpIsActive = in.readBoolean();
418:
419: if (metaAxisServiceGrpIsActive == ObjectStateUtils.ACTIVE_OBJECT) {
420: metaAxisServiceGroup = (MetaDataEntry) ObjectStateUtils
421: .readObject(in,
422: "ServiceGroupContext.metaAxisServiceGroup");
423: } else {
424: metaAxisServiceGroup = null;
425: }
426:
427: //---------------------------------------------------------
428: // parent
429: //---------------------------------------------------------
430:
431: // the parent is the ConfigurationContext object, whic
432: // at this time, is not being saved.
433: // instead, we will need to register this ServiceGroupObject
434: // with the existing ConfigurationContext object when
435: // this object is reconstituted
436:
437: //---------------------------------------------------------
438: // other
439: //---------------------------------------------------------
440: serviceContextMap = new HashMap();
441:
442: //---------------------------------------------------------
443: // done
444: //---------------------------------------------------------
445:
446: }
447:
448: /**
449: * Some parts of the object restored from the
450: * readExternal deserialization work cannot be completed until
451: * we have a configurationContext. This method checks to see
452: * if additional work needs to be done in order to complete
453: * the object reconstitution.
454: *
455: * @param cc the active ConfigurationContext
456: */
457: public void activate(ConfigurationContext cc) {
458: // see if there's any work to do
459: if (!needsToBeReconciled) {
460: // return quick
461: return;
462: }
463:
464: // get the axis configuration
465: AxisConfiguration axisConfig = cc.getAxisConfiguration();
466:
467: // We previously saved metaAxisServiceGroup; restore it
468: if (metaAxisServiceGroup != null) {
469: axisServiceGroup = ObjectStateUtils.findServiceGroup(
470: axisConfig, metaAxisServiceGroup.getClassName(),
471: metaAxisServiceGroup.getQNameAsString());
472: } else {
473: axisServiceGroup = null;
474: }
475:
476: // set parent
477: this .setParent(cc);
478:
479: // register with the parent
480: cc.addServiceGroupContextIntoSoapSessionTable(this );
481:
482: //-------------------------------------------------------
483: // done, reset the flag
484: //-------------------------------------------------------
485: needsToBeReconciled = false;
486:
487: }
488:
489: /**
490: * Compares key parts of the state from the current instance of
491: * this class with the specified instance to see if they are
492: * equivalent.
493: * <p/>
494: * This differs from the java.lang.Object.equals() method in
495: * that the equals() method generally looks at both the
496: * object identity (location in memory) and the object state
497: * (data).
498: * <p/>
499: *
500: * @param ctx The object to compare with
501: * @return TRUE if this object is equivalent with the specified object
502: * that is, key fields match
503: * FALSE, otherwise
504: */
505: public boolean isEquivalent(ServiceGroupContext ctx) {
506: // NOTE: the input object is expected to exist (ie, be non-null)
507:
508: if (!this .axisServiceGroup.equals(ctx.getDescription())) {
509: return false;
510: }
511:
512: String ctxid = ctx.getId();
513:
514: if ((this .id != null) && (ctxid != null)) {
515: if (!this .id.equals(ctxid)) {
516: return false;
517: }
518:
519: } else if ((this .id == null) && (ctxid == null)) {
520: // keep going
521: } else {
522: // mismatch
523: return false;
524: }
525:
526: // TODO: consider checking the parent objects for equivalency
527:
528: // TODO: consider checking fields from the super class for equivalency
529:
530: return true;
531: }
532:
533: /**
534: * Trace a warning message, if needed, indicating that this
535: * object needs to be activated before accessing certain fields.
536: *
537: * @param methodname The method where the warning occurs
538: */
539: private void checkActivateWarning(String methodname) {
540: if (needsToBeReconciled) {
541: log
542: .warn(myClassName
543: + ":"
544: + methodname
545: + "(): ****WARNING**** "
546: + myClassName
547: + ".activate(configurationContext) needs to be invoked.");
548: }
549: }
550:
551: public ConfigurationContext getRootContext() {
552: //parent of the ServiceGroupContext is the ConfigurationContext
553: return (ConfigurationContext) this.getParent();
554: }
555: }
|