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: */package org.apache.geronimo.axis.client;
017:
018: import java.lang.reflect.Method;
019: import java.rmi.RemoteException;
020: import java.util.Arrays;
021: import java.util.Iterator;
022: import java.util.Set;
023: import java.util.List;
024: import java.util.Map;
025: import javax.security.auth.Subject;
026: import javax.xml.rpc.holders.Holder;
027: import javax.wsdl.OperationType;
028:
029: import net.sf.cglib.proxy.MethodInterceptor;
030: import net.sf.cglib.proxy.MethodProxy;
031: import org.apache.axis.client.Call;
032: import org.apache.axis.description.ParameterDesc;
033: import org.apache.axis.utils.JavaUtils;
034: import org.apache.geronimo.security.ContextManager;
035: import org.apache.geronimo.security.jaas.NamedUsernamePasswordCredential;
036: import org.apache.geronimo.webservices.saaj.SAAJUniverse;
037:
038: /**
039: * @version $Rev: 520432 $ $Date: 2007-03-20 08:35:27 -0700 (Tue, 20 Mar 2007) $
040: */
041: public class ServiceEndpointMethodInterceptor implements
042: MethodInterceptor {
043:
044: private final GenericServiceEndpoint stub;
045: private final OperationInfo[] operations;
046: private final String credentialsName;
047:
048: public ServiceEndpointMethodInterceptor(
049: GenericServiceEndpoint stub, OperationInfo[] operations,
050: String credentialsName) {
051: this .stub = stub;
052: this .operations = operations;
053: this .credentialsName = credentialsName;
054: }
055:
056: public Object intercept(Object o, Method method, Object[] objects,
057: MethodProxy methodProxy) throws Throwable {
058: SAAJUniverse universe = new SAAJUniverse();
059: universe.set(SAAJUniverse.AXIS1);
060: try {
061: return doIntercept(o, method, objects, methodProxy);
062: } finally {
063: universe.unset();
064: }
065: }
066:
067: private Object doIntercept(Object o, Method method,
068: Object[] objects, MethodProxy methodProxy) throws Throwable {
069: int index = methodProxy.getSuperIndex();
070: OperationInfo operationInfo = operations[index];
071: if (operationInfo == null) {
072: throw new RuntimeException("Operation not mapped: "
073: + method.getName() + " index: " + index
074: + "\n OperationInfos: " + Arrays.asList(operations));
075: }
076: stub.checkCachedEndpoint();
077:
078: Call call = stub.createCall();
079:
080: operationInfo.prepareCall(call);
081:
082: stub.setUpCall(call);
083: if (credentialsName != null) {
084: Subject subject = ContextManager.getNextCaller();
085: if (subject == null) {
086: throw new IllegalStateException(
087: "Subject missing but authentication turned on");
088: } else {
089: Set creds = subject
090: .getPrivateCredentials(NamedUsernamePasswordCredential.class);
091: boolean found = false;
092: for (Iterator iterator = creds.iterator(); iterator
093: .hasNext();) {
094: NamedUsernamePasswordCredential namedUsernamePasswordCredential = (NamedUsernamePasswordCredential) iterator
095: .next();
096: if (credentialsName
097: .equals(namedUsernamePasswordCredential
098: .getName())) {
099: call
100: .setUsername(namedUsernamePasswordCredential
101: .getUsername());
102: call.setPassword(new String(
103: namedUsernamePasswordCredential
104: .getPassword()));
105: found = true;
106: break;
107: }
108: }
109: if (!found) {
110: throw new IllegalStateException(
111: "no NamedUsernamePasswordCredential found for name "
112: + credentialsName);
113: }
114: }
115: }
116: Object response = null;
117: List parameterDescs = operationInfo.getOperationDesc()
118: .getParameters();
119: Object[] unwrapped = extractFromHolders(objects,
120: parameterDescs, operationInfo.getOperationDesc()
121: .getNumInParams());
122: if (operationInfo.getOperationDesc().getMep() == OperationType.REQUEST_RESPONSE) {
123: try {
124: response = call.invoke(unwrapped);
125: } catch (RemoteException e) {
126: throw operationInfo.unwrapFault(e);
127: }
128:
129: if (response instanceof RemoteException) {
130: throw operationInfo
131: .unwrapFault((RemoteException) response);
132: } else {
133: stub.extractAttachments(call);
134: Map outputParameters = call.getOutputParams();
135: putInHolders(outputParameters, objects, parameterDescs);
136: Class returnType = operationInfo.getOperationDesc()
137: .getReturnClass();
138: //return type should never be null... but we are not objecting if wsdl-return-value-mapping is not set.
139: if (response == null
140: || returnType == null
141: || returnType.isAssignableFrom(response
142: .getClass())) {
143: return response;
144: } else {
145: return JavaUtils.convert(response, returnType);
146: }
147: }
148: } else if (operationInfo.getOperationDesc().getMep() == OperationType.ONE_WAY) {
149: //one way
150: call.invokeOneWay(unwrapped);
151: return null;
152: } else {
153: throw new RuntimeException("Invalid messaging style: "
154: + operationInfo.getOperationDesc().getMep());
155: }
156: }
157:
158: private Object[] extractFromHolders(Object[] objects,
159: List parameterDescs, int inParameterCount)
160: throws JavaUtils.HolderException {
161: if (objects.length != parameterDescs.size()) {
162: throw new IllegalArgumentException(
163: "Mismatch parameter count: expected: "
164: + parameterDescs.size() + ", actual: "
165: + objects.length);
166: }
167: Object[] unwrapped = new Object[inParameterCount];
168: int j = 0;
169: for (int i = 0; objects != null && i < objects.length; i++) {
170: Object parameter = objects[i];
171: ParameterDesc parameterDesc = (ParameterDesc) parameterDescs
172: .get(i);
173:
174: if (parameterDesc.getMode() == ParameterDesc.INOUT) {
175: unwrapped[j++] = JavaUtils
176: .getHolderValue((Holder) parameter);
177: } else if (parameterDesc.getMode() == ParameterDesc.IN) {
178: unwrapped[j++] = parameter;
179: }
180: }
181: return unwrapped;
182: }
183:
184: private void putInHolders(Map outputParameters, Object[] objects,
185: List parameterDescs) throws JavaUtils.HolderException {
186: for (int i = 0; i < objects.length; i++) {
187: Object parameter = objects[i];
188: ParameterDesc parameterDesc = (ParameterDesc) parameterDescs
189: .get(i);
190: if ((parameterDesc.getMode() == ParameterDesc.INOUT)
191: || (parameterDesc.getMode() == ParameterDesc.OUT)) {
192: Object returned = outputParameters.get(parameterDesc
193: .getQName());
194: if (returned instanceof Holder) {
195: //TODO this must be a bug somewhere!!!!
196: returned = JavaUtils.getHolderValue(returned);
197: }
198: JavaUtils.setHolderValue((Holder) parameter, returned);
199: }
200: }
201: }
202:
203: }
|