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