001 /**
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements. See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License. You may obtain a copy of the License at
008 *
009 * http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017 package org.apache.camel.model;
018
019 import javax.xml.bind.annotation.XmlAccessType;
020 import javax.xml.bind.annotation.XmlAccessorType;
021 import javax.xml.bind.annotation.XmlAttribute;
022 import javax.xml.bind.annotation.XmlRootElement;
023 import javax.xml.bind.annotation.XmlTransient;
024
025 import org.apache.camel.Processor;
026 import org.apache.camel.processor.WrapProcessor;
027 import org.apache.camel.spi.Policy;
028 import org.apache.camel.spi.RouteContext;
029 import org.apache.camel.spi.TransactedPolicy;
030 import org.apache.camel.util.ObjectHelper;
031
032 /**
033 * Represents an XML <policy/> element
034 *
035 * @version
036 */
037 @XmlRootElement(name = "policy")
038 @XmlAccessorType(XmlAccessType.FIELD)
039 public class PolicyDefinition extends OutputDefinition<PolicyDefinition> {
040
041 // TODO: Align this code with TransactedDefinition
042
043 @XmlTransient
044 protected Class<? extends Policy> type;
045 @XmlAttribute(required = true)
046 protected String ref;
047 @XmlTransient
048 private Policy policy;
049
050 public PolicyDefinition() {
051 }
052
053 public PolicyDefinition(Policy policy) {
054 this.policy = policy;
055 }
056
057 @Override
058 public String toString() {
059 return "Policy[" + description() + "]";
060 }
061
062 protected String description() {
063 if (policy != null) {
064 return policy.toString();
065 } else {
066 return "ref:" + ref;
067 }
068 }
069
070 @Override
071 public String getShortName() {
072 // a policy can be a hidden disguise for a transacted definition
073 boolean transacted = type != null && type.isAssignableFrom(TransactedPolicy.class);
074 return transacted ? "transacted" : "policy";
075 }
076
077 @Override
078 public String getLabel() {
079 return getShortName() + "[" + getDescription() + "]";
080 }
081
082 @Override
083 public boolean isAbstract() {
084 // policy should NOT be abstract
085 return false;
086 }
087
088 public String getRef() {
089 return ref;
090 }
091
092 public void setRef(String ref) {
093 this.ref = ref;
094 }
095
096 /**
097 * Sets a policy type that this definition should scope within.
098 * <p/>
099 * Is used for convention over configuration situations where the policy
100 * should be automatic looked up in the registry and it should be based
101 * on this type. For instance a {@link org.apache.camel.spi.TransactedPolicy}
102 * can be set as type for easy transaction configuration.
103 * <p/>
104 * Will by default scope to the wide {@link Policy}
105 *
106 * @param type the policy type
107 */
108 public void setType(Class<? extends Policy> type) {
109 this.type = type;
110 }
111
112 /**
113 * Sets a reference to use for lookup the policy in the registry.
114 *
115 * @param ref the reference
116 * @return the builder
117 */
118 public PolicyDefinition ref(String ref) {
119 setRef(ref);
120 return this;
121 }
122
123 @Override
124 public Processor createProcessor(RouteContext routeContext) throws Exception {
125 Policy policy = resolvePolicy(routeContext);
126 ObjectHelper.notNull(policy, "policy", this);
127
128 // before wrap
129 policy.beforeWrap(routeContext, this);
130
131 // create processor after the before wrap
132 Processor childProcessor = this.createChildProcessor(routeContext, true);
133
134 // wrap
135 Processor target = policy.wrap(routeContext, childProcessor);
136
137 // wrap the target so it becomes a service and we can manage its lifecycle
138 WrapProcessor wrap = new WrapProcessor(target, childProcessor);
139 return wrap;
140 }
141
142 protected Policy resolvePolicy(RouteContext routeContext) {
143 if (policy != null) {
144 return policy;
145 }
146 // reuse code on transacted definition to do the resolution
147 return TransactedDefinition.doResolvePolicy(routeContext, getRef(), type);
148 }
149
150 }