001: /*
002: * Copyright 2004,2005 The Apache Software Foundation.
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: */
016:
017: package org.apache.axis2.description;
018:
019: import org.apache.axiom.om.OMElement;
020: import org.apache.axis2.AxisFault;
021: import org.apache.axis2.util.Utils;
022: import org.apache.axis2.util.JavaUtils;
023: import org.apache.axis2.engine.AxisConfiguration;
024: import org.apache.axis2.i18n.Messages;
025: import org.apache.axis2.modules.Module;
026: import org.apache.commons.logging.Log;
027: import org.apache.commons.logging.LogFactory;
028: import org.apache.neethi.Assertion;
029: import org.apache.neethi.Policy;
030:
031: import java.util.ArrayList;
032: import java.util.HashMap;
033: import java.util.Iterator;
034: import java.util.List;
035: import java.util.Collection;
036: import java.util.Map;
037:
038: public abstract class AxisDescription implements ParameterInclude,
039: DescriptionConstants {
040:
041: protected AxisDescription parent = null;
042:
043: private ParameterInclude parameterInclude;
044:
045: private PolicyInclude policyInclude = null;
046:
047: private HashMap children;
048:
049: protected Map engagedModules;
050:
051: // Holds the documentation details for each element
052: private String documentation;
053:
054: // creating a logger instance
055: private Log log = LogFactory.getLog(this .getClass());
056:
057: public AxisDescription() {
058: parameterInclude = new ParameterIncludeImpl();
059: children = new HashMap();
060: }
061:
062: public void addParameter(Parameter param) throws AxisFault {
063: if (param == null) {
064: return;
065: }
066:
067: if (isParameterLocked(param.getName())) {
068: throw new AxisFault(Messages.getMessage(
069: "paramterlockedbyparent", param.getName()));
070: }
071:
072: parameterInclude.addParameter(param);
073: }
074:
075: public void addParameter(String name, Object value)
076: throws AxisFault {
077: addParameter(new Parameter(name, value));
078: }
079:
080: public void removeParameter(Parameter param) throws AxisFault {
081: parameterInclude.removeParameter(param);
082: }
083:
084: public void deserializeParameters(OMElement parameterElement)
085: throws AxisFault {
086:
087: parameterInclude.deserializeParameters(parameterElement);
088:
089: }
090:
091: /**
092: * If the parameter found in the current decription then the paremeter will be
093: * writable else it will be read only
094: * @param name
095: * @return
096: */
097: public Parameter getParameter(String name) {
098: Parameter parameter = parameterInclude.getParameter(name);
099: if (parameter != null) {
100: parameter.setEditable(true);
101: return parameter;
102: }
103: if (parent != null) {
104: parameter = parent.getParameter(name);
105: if (parameter != null) {
106: parameter.setEditable(false);
107: }
108: return parameter;
109: }
110: return null;
111: }
112:
113: public Object getParameterValue(String name) {
114: Parameter param = getParameter(name);
115: if (param == null) {
116: return null;
117: }
118: return param.getValue();
119: }
120:
121: public boolean isParameterTrue(String name) {
122: Parameter param = getParameter(name);
123: return param != null && JavaUtils.isTrue(param.getValue());
124: }
125:
126: public ArrayList getParameters() {
127: return parameterInclude.getParameters();
128: }
129:
130: public boolean isParameterLocked(String parameterName) {
131:
132: if (this .parent != null
133: && this .parent.isParameterLocked(parameterName)) {
134: return true;
135: }
136:
137: Parameter parameter = getParameter(parameterName);
138: return parameter != null && parameter.isLocked();
139: }
140:
141: public String getDocumentation() {
142: return documentation;
143: }
144:
145: public void setDocumentation(String documentation) {
146: this .documentation = documentation;
147: }
148:
149: public void setParent(AxisDescription parent) {
150: this .parent = parent;
151: }
152:
153: public AxisDescription getParent() {
154: return parent;
155: }
156:
157: public void setPolicyInclude(PolicyInclude policyInclude) {
158: this .policyInclude = policyInclude;
159: }
160:
161: public PolicyInclude getPolicyInclude() {
162: if (policyInclude == null) {
163: policyInclude = new PolicyInclude(this );
164: }
165: return policyInclude;
166: }
167:
168: // NOTE - These are NOT typesafe!
169: public void addChild(AxisDescription child) {
170: children.put(child.getKey(), child);
171: }
172:
173: public void addChild(Object key, AxisDescription child) {
174: children.put(key, child);
175: }
176:
177: public Iterator getChildren() {
178: return children.values().iterator();
179: }
180:
181: public AxisDescription getChild(Object key) {
182: return (AxisDescription) children.get(key);
183: }
184:
185: public void removeChild(Object key) {
186: children.remove(key);
187: }
188:
189: /**
190: * This method sets the policy as the default of this AxisDescription
191: * instance. Further more this method does the followings.
192: * <p/>
193: * (1) Engage whatever modules necessary to execute new the effective policy
194: * of this AxisDescription instance. (2) Disengage whatever modules that are
195: * not necessary to execute the new effective policy of this AxisDescription
196: * instance. (3) Check whether each module can execute the new effective
197: * policy of this AxisDescription instance. (4) If not throw an AxisFault to
198: * notify the user. (5) Else notify each module about the new effective
199: * policy.
200: *
201: * @param policy the new policy of this AxisDescription instance. The effective
202: * policy is the merge of this argument with effective policy of
203: * parent of this AxisDescription.
204: * @throws AxisFault if any module is unable to execute the effective policy of
205: * this AxisDescription instance successfully or no module to
206: * execute some portion (one or more PrimtiveAssertions ) of
207: * that effective policy.
208: */
209: public void applyPolicy(Policy policy) throws AxisFault {
210: AxisConfiguration configuration = getAxisConfiguration();
211:
212: if (configuration == null) {
213: // FIXME return or throw an Exception?
214: return;
215: }
216:
217: // sets AxisDescription policy
218: getPolicyInclude().setPolicy(policy);
219:
220: /*
221: * now we should take the effective one .. it is necessary since
222: * AxisDescription.applyPolicy(..) doesn't override policies at the
223: * Upper levels.
224: */
225: Policy effPolicy = getPolicyInclude().getEffectivePolicy();
226:
227: /*
228: * for the moment we consider policies with only one alternative. If the
229: * policy contains multiple alternatives only the first alternative will
230: * be considered.
231: */
232: Iterator iterator = effPolicy.getAlternatives();
233: if (!iterator.hasNext()) {
234: throw new AxisFault(
235: "Policy doesn't contain any policy alternatives");
236: }
237:
238: List assertionList = (List) iterator.next();
239:
240: Assertion assertion;
241: String namespaceURI;
242:
243: List moduleList;
244:
245: List namespaceList = new ArrayList();
246: List modulesToEngage = new ArrayList();
247:
248: for (Iterator assertions = assertionList.iterator(); assertions
249: .hasNext();) {
250: assertion = (Assertion) assertions.next();
251: namespaceURI = assertion.getName().getNamespaceURI();
252:
253: moduleList = configuration
254: .getModulesForPolicyNamesapce(namespaceURI);
255:
256: if (moduleList == null) {
257: log.debug("can't find any module to process "
258: + assertion.getName() + " type assertions");
259: continue;
260: }
261:
262: if (!canSupportAssertion(assertion, moduleList)) {
263: throw new AxisFault("atleast one module can't support "
264: + assertion.getName());
265: }
266:
267: if (!namespaceList.contains(namespaceURI)) {
268: namespaceList.add(namespaceURI);
269: modulesToEngage.addAll(moduleList);
270: }
271: }
272:
273: /*
274: * FIXME We need to disengage any modules that are already engaged *but*
275: * has nothing to do with the policy to apply
276: */
277:
278: engageModulesToAxisDescription(modulesToEngage, this );
279: }
280:
281: /**
282: * Applies the policies on the Description Hierarchy recursively.
283: *
284: * @throws AxisFault an error occurred applying the policy
285: */
286: public void applyPolicy() throws AxisFault {
287:
288: AxisConfiguration configuration = getAxisConfiguration();
289: if (configuration == null) {
290: return; // CHECKME: May be we need to throw an Exception ??
291: }
292:
293: Policy effPolicy = getApplicablePolicy(this );
294:
295: if (effPolicy != null) {
296:
297: /*
298: * for the moment we consider policies with only one alternative. If
299: * the policy contains multiple alternatives only the first
300: * alternative will be considered.
301: */
302: Iterator iterator = effPolicy.getAlternatives();
303: if (!iterator.hasNext()) {
304: throw new AxisFault(
305: "Policy doesn't contain any policy alternatives");
306: }
307:
308: List assertionList = (List) iterator.next();
309:
310: Assertion assertion;
311: String namespaceURI;
312:
313: List moduleList;
314:
315: List namespaceList = new ArrayList();
316: List modulesToEngage = new ArrayList();
317:
318: for (Iterator assertions = assertionList.iterator(); assertions
319: .hasNext();) {
320: assertion = (Assertion) assertions.next();
321: namespaceURI = assertion.getName().getNamespaceURI();
322:
323: moduleList = configuration
324: .getModulesForPolicyNamesapce(namespaceURI);
325:
326: if (moduleList == null) {
327: log.debug("can't find any module to process "
328: + assertion.getName() + " type assertions");
329: continue;
330: }
331:
332: if (!canSupportAssertion(assertion, moduleList)) {
333: throw new AxisFault(
334: "atleast one module can't support "
335: + assertion.getName());
336: }
337:
338: if (!namespaceList.contains(namespaceURI)) {
339: namespaceList.add(namespaceURI);
340: modulesToEngage.addAll(moduleList);
341: }
342: }
343:
344: /*
345: * FIXME We need to disengage any modules that are already engaged
346: * *but* has nothing to do with the policy to apply
347: */
348:
349: engageModulesToAxisDescription(modulesToEngage, this );
350:
351: }
352:
353: AxisDescription child;
354:
355: for (Iterator children = getChildren(); children.hasNext();) {
356: child = (AxisDescription) children.next();
357: child.applyPolicy();
358: }
359: }
360:
361: private boolean canSupportAssertion(Assertion assertion,
362: List moduleList) {
363:
364: AxisModule axisModule;
365: Module module;
366:
367: for (Iterator iterator = moduleList.iterator(); iterator
368: .hasNext();) {
369: axisModule = (AxisModule) iterator.next();
370: // FIXME is this step really needed ??
371: // Shouldn't axisMoudle.getModule always return not-null value ??
372: module = axisModule.getModule();
373:
374: if (!(module == null || module
375: .canSupportAssertion(assertion))) {
376: log.debug(axisModule.getName()
377: + " says it can't support "
378: + assertion.getName());
379: return false;
380: }
381: }
382:
383: return true;
384: }
385:
386: private void engageModulesToAxisDescription(List moduleList,
387: AxisDescription description) throws AxisFault {
388:
389: AxisModule axisModule;
390: Module module;
391:
392: for (Iterator iterator = moduleList.iterator(); iterator
393: .hasNext();) {
394: axisModule = (AxisModule) iterator.next();
395: // FIXME is this step really needed ??
396: // Shouldn't axisMoudle.getModule always return not-null value ??
397: module = axisModule.getModule();
398:
399: if (!(module == null || description.isEngaged(axisModule
400: .getName()))) {
401: // engages the module to AxisDescription
402: description.engageModule(axisModule);
403: // notifies the module about the engagement
404: axisModule.getModule().engageNotify(description);
405: }
406: }
407: }
408:
409: public AxisConfiguration getAxisConfiguration() {
410:
411: if (this instanceof AxisConfiguration) {
412: return (AxisConfiguration) this ;
413: }
414:
415: if (this .parent != null) {
416: return this .parent.getAxisConfiguration();
417: }
418:
419: return null;
420: }
421:
422: public abstract Object getKey();
423:
424: /**
425: * Engage a Module at this level
426: *
427: * @param axisModule the Module to engage
428: * @throws AxisFault if there's a problem engaging
429: */
430: public void engageModule(AxisModule axisModule) throws AxisFault {
431: engageModule(axisModule, this );
432: }
433:
434: /**
435: * Engage a Module at this level, keeping track of which level the engage was originally
436: * called from. This is meant for internal use only.
437: *
438: * @param axisModule module to engage
439: * @param source the AxisDescription which originally called engageModule()
440: * @throws AxisFault if there's a problem engaging
441: */
442: public void engageModule(AxisModule axisModule,
443: AxisDescription source) throws AxisFault {
444: if (engagedModules == null)
445: engagedModules = new HashMap();
446: String moduleName = axisModule.getName();
447: for (Iterator iterator = engagedModules.values().iterator(); iterator
448: .hasNext();) {
449: AxisModule tempAxisModule = ((AxisModule) iterator.next());
450: String tempModuleName = tempAxisModule.getName();
451:
452: if (moduleName.equals(tempModuleName)) {
453: String existing = tempAxisModule.getVersion();
454: if (!Utils.checkVersion(axisModule.getVersion(),
455: existing)) {
456: throw new AxisFault(Messages.getMessage(
457: "mismatchedModuleVersions", getClass()
458: .getName(), moduleName, existing));
459: }
460: }
461:
462: }
463:
464: // Let the Module know it's being engaged. If it's not happy about it, it can throw.
465: Module module = axisModule.getModule();
466: if (module != null) {
467: module.engageNotify(this );
468: }
469:
470: // If we have anything specific to do, let that happen
471: onEngage(axisModule, source);
472:
473: engagedModules.put(Utils.getModuleName(axisModule.getName(),
474: axisModule.getVersion()), axisModule);
475: }
476:
477: protected void onEngage(AxisModule module, AxisDescription engager)
478: throws AxisFault {
479: // Default version does nothing, feel free to override
480: }
481:
482: static Collection NULL_MODULES = new ArrayList(0);
483:
484: public Collection getEngagedModules() {
485: return engagedModules == null ? NULL_MODULES : engagedModules
486: .values();
487: }
488:
489: /**
490: * Check if a given module is engaged at this level.
491: *
492: * @param moduleName module to investigate.
493: * @return true if engaged, false if not.
494: * TODO: Handle versions? isEngaged("addressing") should be true even for versioned modulename...
495: */
496: public boolean isEngaged(String moduleName) {
497: return engagedModules != null
498: && engagedModules.keySet().contains(moduleName);
499: }
500:
501: public boolean isEngaged(AxisModule axisModule) {
502: String id = Utils.getModuleName(axisModule.getName(),
503: axisModule.getVersion());
504: return engagedModules != null
505: && engagedModules.keySet().contains(id);
506: }
507:
508: public void disengageModule(AxisModule module) throws AxisFault {
509: if (module == null || engagedModules == null)
510: return;
511: // String id = Utils.getModuleName(module.getName(), module.getVersion());
512: if (isEngaged(module)) {
513: onDisengage(module);
514: engagedModules.remove(Utils.getModuleName(module.getName(),
515: module.getVersion()));
516: }
517: }
518:
519: protected void onDisengage(AxisModule module) throws AxisFault {
520: // Base version does nothing
521: }
522:
523: private Policy getApplicablePolicy(AxisDescription axisDescription) {
524:
525: if (axisDescription instanceof AxisOperation) {
526: AxisOperation operation = (AxisOperation) axisDescription;
527: AxisService service = operation.getAxisService();
528:
529: if (service != null) {
530:
531: AxisEndpoint axisEndpoint = service.getEndpoint(service
532: .getEndpointName());
533:
534: AxisBinding axisBinding = null;
535:
536: if (axisEndpoint != null) {
537: axisBinding = axisEndpoint.getBinding();
538: }
539:
540: AxisBindingOperation axisBindingOperation = null;
541:
542: if (axisBinding != null) {
543: axisBindingOperation = (AxisBindingOperation) axisBinding
544: .getChild(operation.getName());
545: }
546:
547: if (axisBindingOperation != null) {
548: return axisBindingOperation.getEffectivePolicy();
549: }
550: }
551:
552: return operation.getPolicyInclude().getEffectivePolicy();
553:
554: } else if (axisDescription instanceof AxisService) {
555: AxisService service = (AxisService) axisDescription;
556:
557: AxisEndpoint axisEndpoint = service.getEndpoint(service
558: .getEndpointName());
559: AxisBinding axisBinding = null;
560:
561: if (axisEndpoint != null) {
562: axisBinding = axisEndpoint.getBinding();
563: }
564:
565: if (axisBinding != null) {
566: return axisBinding.getEffectivePolicy();
567: }
568:
569: return service.getPolicyInclude().getEffectivePolicy();
570:
571: } else {
572: return axisDescription.getPolicyInclude()
573: .getEffectivePolicy();
574: }
575: }
576: }
|