001: /*
002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003: *
004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
005: *
006: * The contents of this file are subject to the terms of either the GNU
007: * General Public License Version 2 only ("GPL") or the Common Development
008: * and Distribution License("CDDL") (collectively, the "License"). You
009: * may not use this file except in compliance with the License. You can obtain
010: * a copy of the License at https://glassfish.dev.java.net/public/CDDL+GPL.html
011: * or glassfish/bootstrap/legal/LICENSE.txt. See the License for the specific
012: * language governing permissions and limitations under the License.
013: *
014: * When distributing the software, include this License Header Notice in each
015: * file and include the License file at glassfish/bootstrap/legal/LICENSE.txt.
016: * Sun designates this particular file as subject to the "Classpath" exception
017: * as provided by Sun in the GPL Version 2 section of the License file that
018: * accompanied this code. If applicable, add the following below the License
019: * Header, with the fields enclosed by brackets [] replaced by your own
020: * identifying information: "Portions Copyrighted [year]
021: * [name of copyright owner]"
022: *
023: * Contributor(s):
024: *
025: * If you wish your version of this file to be governed by only the CDDL or
026: * only the GPL Version 2, indicate your decision by adding "[Contributor]
027: * elects to include this software in this distribution under the [CDDL or GPL
028: * Version 2] license." If you don't indicate a single choice of license, a
029: * recipient has the option to distribute your version of this file under
030: * either the CDDL, the GPL Version 2 or to extend the choice of license to
031: * its licensees as provided above. However, if you add GPL Version 2 code
032: * and therefore, elected the GPL Version 2 license, then the option applies
033: * only if the new code is made subject to such option by the copyright
034: * holder.
035: */
036:
037: package com.sun.xml.ws.tx.common;
038:
039: import com.sun.xml.ws.api.WSBinding;
040: import com.sun.xml.ws.api.model.JavaMethod;
041: import com.sun.xml.ws.api.model.SEIModel;
042: import com.sun.xml.ws.api.model.wsdl.WSDLBoundOperation;
043: import com.sun.xml.ws.api.model.wsdl.WSDLPort;
044: import com.sun.xml.ws.policy.AssertionSet;
045: import com.sun.xml.ws.policy.Policy;
046: import com.sun.xml.ws.policy.PolicyAssertion;
047: import com.sun.xml.ws.policy.PolicyException;
048: import com.sun.xml.ws.policy.PolicyMap;
049: import com.sun.xml.ws.policy.PolicyMapExtender;
050: import com.sun.xml.ws.policy.PolicyMapKey;
051: import com.sun.xml.ws.policy.PolicySubject;
052: import com.sun.xml.ws.policy.jaxws.spi.PolicyMapUpdateProvider;
053: import com.sun.xml.ws.policy.sourcemodel.AssertionData;
054: import static com.sun.xml.ws.tx.common.Constants.AT_ALWAYS_CAPABILITY;
055: import static com.sun.xml.ws.tx.common.Constants.AT_ASSERTION;
056: import static com.sun.xml.ws.tx.common.Constants.WSP2002_OPTIONAL;
057: import com.sun.xml.ws.tx.common.TransactionAnnotationProcessor.TransactionAttributeType;
058:
059: import javax.xml.namespace.QName;
060: import java.util.ArrayList;
061: import java.util.Collection;
062: import java.util.logging.Level;
063:
064: /**
065: * From CMT EJB methods generate wsdl:binding/wsdl:operations with semantically equivalent WS-AT Policy Assertion(s).
066: * <p/>
067: * Known limitation: not accounting for ejb deployment descriptor, only working off of TransactionAttribute annotations.
068: */
069: public class TxMapUpdateProvider implements PolicyMapUpdateProvider {
070:
071: final static private TxLogger logger = TxLogger
072: .getATLogger(TxMapUpdateProvider.class);
073:
074: static private boolean nonJavaEEContainer = false;
075:
076: /**
077: * Update policy map with operation scope of correct ws-at policy assertions.
078: * <p/>
079: * Only looking for this for java to wsdl at tool time.
080: *
081: * @param policyMapMutator
082: * @param policyMap
083: * @param model
084: * @param wsBinding
085: */
086: public void update(final PolicyMapExtender policyMapMutator,
087: final PolicyMap policyMap, final SEIModel model,
088: final WSBinding wsBinding) throws PolicyException {
089: final String METHOD_NAME = "update";
090:
091: if (nonJavaEEContainer) {
092: return;
093: }
094:
095: // For each method of a CMT EJB, map its effective javax.ejb.TransactionAttribute to semantically equivalent
096: // ws-at policy assertion.
097: if (model != null) {
098: final Collection<? extends JavaMethod> methods = model
099: .getJavaMethods();
100: Class CMTEJB = null;
101: TransactionAttributeType classDefaultTxnAttr = null;
102: for (JavaMethod method : methods) {
103:
104: if (CMTEJB == null) {
105: boolean isCMTEJB = false;
106: final Class theClass = method.getSEIMethod()
107: .getDeclaringClass();
108: try {
109: isCMTEJB = TransactionAnnotationProcessor
110: .isContainerManagedEJB(theClass);
111: } catch (NoClassDefFoundError e) {
112: // running in a container that does not support EJBs; terminate processing of EJB annotations
113: nonJavaEEContainer = true;
114: logger
115: .fine(
116: METHOD_NAME,
117: LocalizationMessages
118: .NON_EE_CONTAINER_2005("NoClassDefFoundError: "
119: + e
120: .getLocalizedMessage()));
121: return;
122: }
123: if (isCMTEJB) {
124: // perform class level caching of info
125: CMTEJB = theClass;
126: classDefaultTxnAttr = TransactionAnnotationProcessor
127: .getTransactionAttributeDefault(theClass);
128: } else {
129: // not a CMT EJB, no transaction attributes to look for; just return
130: return;
131: }
132: }
133:
134: // we have a CMT EJB. Map its transaction attribute to proper ws-at policy assertion.
135:
136: final TransactionAttributeType txnAttr = TransactionAnnotationProcessor
137: .getEffectiveTransactionAttribute(method
138: .getSEIMethod(), classDefaultTxnAttr);
139: final String policyId = model.getBoundPortTypeName()
140: .getLocalPart()
141: + "_"
142: + method.getOperationName()
143: + "_WSAT_Policy";
144: final Policy policy = mapTransactionAttribute2WSATPolicy(
145: policyId, txnAttr);
146: if (policy != null) {
147: // insert ws-at policy assertion in operation scope into policyMapMutator
148: final PolicyMapKey operationKey = PolicyMap
149: .createWsdlOperationScopeKey(model
150: .getServiceQName(), model
151: .getPortName(), new QName(model
152: .getTargetNamespace(), method
153: .getOperationName()));
154: final PolicySubject generatedWsatPolicySubject = new PolicySubject(
155: method, policy);
156: if (logger.isLogging(Level.FINE)) {
157: logger
158: .fine(
159: METHOD_NAME,
160: LocalizationMessages
161: .ADD_AT_POLICY_ASSERTION_2007(
162: model
163: .getPortName()
164: .toString(),
165: method
166: .getOperationName(),
167: policy
168: .toString(),
169: txnAttr
170: .toString(),
171: CMTEJB
172: .getName(),
173: method
174: .getMethod()
175: .getName()));
176: } else {
177: logger
178: .info(
179: METHOD_NAME,
180: LocalizationMessages
181: .ADD_AT_POLICY_ASSERTION_2007(
182: model
183: .getPortName()
184: .toString(),
185: method
186: .getOperationName(),
187: policy.getId(),
188: txnAttr
189: .toString(),
190: CMTEJB
191: .getName(),
192: method
193: .getMethod()
194: .getName()));
195: }
196: policyMapMutator.putOperationSubject(operationKey,
197: generatedWsatPolicySubject);
198: }
199: } // for each method in CMT EJB
200: }
201: }
202:
203: static class WsatPolicyAssertion extends PolicyAssertion {
204:
205: static private AssertionData createAssertionData(
206: final QName assertionQName, final boolean isOptional) {
207: final AssertionData result = AssertionData
208: .createAssertionData(assertionQName);
209: result.setOptionalAttribute(isOptional);
210: if (isOptional) {
211: // patch for wsit 419
212: result.setAttribute(WSP2002_OPTIONAL, "true");
213: }
214: return result;
215: }
216:
217: WsatPolicyAssertion(final QName wsatPolicyAssertionName,
218: final boolean isOptional) {
219: super (createAssertionData(wsatPolicyAssertionName,
220: isOptional), null, null);
221: }
222: }
223:
224: static final private WsatPolicyAssertion AT_ASSERTION_OPTIONAL = new WsatPolicyAssertion(
225: AT_ASSERTION, true);
226: static final private WsatPolicyAssertion AT_ASSERTION_REQUIRED = new WsatPolicyAssertion(
227: AT_ASSERTION, false);
228: static final private WsatPolicyAssertion AT_ALWAYS_CAPABILITY_PA = new WsatPolicyAssertion(
229: AT_ALWAYS_CAPABILITY, false);
230:
231: /**
232: * Pass in what the effective transaction attribute for a given Container Manager Transaction EJB method and return the
233: * semantically closest WS-AT policy assertion.
234: * <p/>
235: * This is best match between Java EE Transaction Attribute and WS-AT Policy Assertion.
236: * There are a number of differences between them.
237: */
238: private Policy mapTransactionAttribute2WSATPolicy(final String id,
239: final TransactionAttributeType txnAttr) {
240:
241: switch (txnAttr) {
242: case NOT_SUPPORTED:
243: case NEVER: // ws-at does not require exception thrown if txn propagated with no assertion.
244: // no ws-at policy assertion on wsdl:binding/wsdl:operation is equivalent of no
245: // claim.
246: return null;
247:
248: case MANDATORY:
249: return createATPolicy(id, AT_ASSERTION_REQUIRED);
250:
251: case SUPPORTS:
252: return createATPolicy(id, AT_ASSERTION_OPTIONAL);
253:
254: case REQUIRES_NEW:
255: return createATPolicy(id, AT_ALWAYS_CAPABILITY_PA);
256:
257: case REQUIRED:
258: return createATPolicy(id, AT_ASSERTION_OPTIONAL,
259: AT_ALWAYS_CAPABILITY_PA);
260:
261: default:
262: return null;
263: }
264: }
265:
266: static private Policy createATPolicy(final String id,
267: final WsatPolicyAssertion atpa) {
268: return createATPolicy(id, atpa, null);
269: }
270:
271: static private Policy createATPolicy(final String id,
272: final WsatPolicyAssertion pa1, final WsatPolicyAssertion pa2) {
273: final ArrayList<AssertionSet> assertionSets = new ArrayList<AssertionSet>(
274: 1);
275: final int numAssertions = (pa2 == null ? 1 : 2);
276: final ArrayList<PolicyAssertion> assertions = new ArrayList<PolicyAssertion>(
277: numAssertions);
278: assertions.add(pa1);
279: if (pa2 != null) {
280: assertions.add(pa2);
281: }
282: assertionSets.add(AssertionSet.createAssertionSet(assertions));
283: return Policy.createPolicy(null, id, assertionSets);
284: }
285: }
|