001 /**
002 *
003 * Licensed to the Apache Software Foundation (ASF) under one or more
004 * contributor license agreements. See the NOTICE file distributed with
005 * this work for additional information regarding copyright ownership.
006 * The ASF licenses this file to You under the Apache License, Version 2.0
007 * (the "License"); you may not use this file except in compliance with
008 * the License. You may obtain a copy of the License at
009 *
010 * http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing, software
013 * distributed under the License is distributed on an "AS IS" BASIS,
014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015 * See the License for the specific language governing permissions and
016 * limitations under the License.
017 */
018 package org.apache.geronimo.axis.client;
019
020 import java.lang.reflect.Method;
021 import java.rmi.RemoteException;
022 import java.util.Arrays;
023 import java.util.Iterator;
024 import java.util.Set;
025 import java.util.List;
026 import java.util.Map;
027 import javax.security.auth.Subject;
028 import javax.xml.rpc.holders.Holder;
029 import javax.wsdl.OperationType;
030
031 import net.sf.cglib.proxy.MethodInterceptor;
032 import net.sf.cglib.proxy.MethodProxy;
033 import org.apache.axis.client.Call;
034 import org.apache.axis.description.ParameterDesc;
035 import org.apache.axis.utils.JavaUtils;
036 import org.apache.geronimo.security.ContextManager;
037 import org.apache.geronimo.security.jaas.NamedUsernamePasswordCredential;
038
039 /**
040 * @version $Rev: 470597 $ $Date: 2006-11-02 15:30:55 -0800 (Thu, 02 Nov 2006) $
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 int index = methodProxy.getSuperIndex();
056 OperationInfo operationInfo = operations[index];
057 if (operationInfo == null) {
058 throw new RuntimeException("Operation not mapped: " + method.getName() + " index: " + index + "\n OperationInfos: " + Arrays.asList(operations));
059 }
060 stub.checkCachedEndpoint();
061
062 Call call = stub.createCall();
063
064 operationInfo.prepareCall(call);
065
066 stub.setUpCall(call);
067 if (credentialsName != null) {
068 Subject subject = ContextManager.getNextCaller();
069 if (subject == null) {
070 throw new IllegalStateException("Subject missing but authentication turned on");
071 } else {
072 Set creds = subject.getPrivateCredentials(NamedUsernamePasswordCredential.class);
073 boolean found = false;
074 for (Iterator iterator = creds.iterator(); iterator.hasNext();) {
075 NamedUsernamePasswordCredential namedUsernamePasswordCredential = (NamedUsernamePasswordCredential) iterator.next();
076 if (credentialsName.equals(namedUsernamePasswordCredential.getName())) {
077 call.setUsername(namedUsernamePasswordCredential.getUsername());
078 call.setPassword(new String(namedUsernamePasswordCredential.getPassword()));
079 found = true;
080 break;
081 }
082 }
083 if (!found) {
084 throw new IllegalStateException("no NamedUsernamePasswordCredential found for name " + credentialsName);
085 }
086 }
087 }
088 Object response = null;
089 List parameterDescs = operationInfo.getOperationDesc().getParameters();
090 Object[] unwrapped = extractFromHolders(objects, parameterDescs, operationInfo.getOperationDesc().getNumInParams());
091 if (operationInfo.getOperationDesc().getMep() == OperationType.REQUEST_RESPONSE) {
092 try {
093 response = call.invoke(unwrapped);
094 } catch (RemoteException e) {
095 throw operationInfo.unwrapFault(e);
096 }
097
098 if (response instanceof RemoteException) {
099 throw operationInfo.unwrapFault((RemoteException) response);
100 } else {
101 stub.extractAttachments(call);
102 Map outputParameters = call.getOutputParams();
103 putInHolders(outputParameters, objects, parameterDescs);
104 Class returnType = operationInfo.getOperationDesc().getReturnClass();
105 //return type should never be null... but we are not objecting if wsdl-return-value-mapping is not set.
106 if (response == null || returnType == null || returnType.isAssignableFrom(response.getClass())) {
107 return response;
108 } else {
109 return JavaUtils.convert(response, returnType);
110 }
111 }
112 } else if (operationInfo.getOperationDesc().getMep() == OperationType.ONE_WAY) {
113 //one way
114 call.invokeOneWay(unwrapped);
115 return null;
116 } else {
117 throw new RuntimeException("Invalid messaging style: " + operationInfo.getOperationDesc().getMep());
118 }
119 }
120
121 private Object[] extractFromHolders(Object[] objects, List parameterDescs, int inParameterCount) throws JavaUtils.HolderException {
122 if (objects.length != parameterDescs.size()) {
123 throw new IllegalArgumentException("Mismatch parameter count: expected: " + parameterDescs.size() + ", actual: " + objects.length);
124 }
125 Object[] unwrapped = new Object[inParameterCount];
126 int j = 0;
127 for (int i = 0; objects != null && i < objects.length; i++) {
128 Object parameter = objects[i];
129 ParameterDesc parameterDesc = (ParameterDesc) parameterDescs.get(i);
130
131 if (parameterDesc.getMode() == ParameterDesc.INOUT) {
132 unwrapped[j++] = JavaUtils.getHolderValue((Holder) parameter);
133 } else if (parameterDesc.getMode() == ParameterDesc.IN) {
134 unwrapped[j++] = parameter;
135 }
136 }
137 return unwrapped;
138 }
139
140 private void putInHolders(Map outputParameters, Object[] objects, List parameterDescs) throws JavaUtils.HolderException {
141 for (int i = 0; i < objects.length; i++) {
142 Object parameter = objects[i];
143 ParameterDesc parameterDesc = (ParameterDesc) parameterDescs.get(i);
144 if ((parameterDesc.getMode() == ParameterDesc.INOUT) ||
145 (parameterDesc.getMode() == ParameterDesc.OUT)) {
146 Object returned = outputParameters.get(parameterDesc.getQName());
147 if (returned instanceof Holder) {
148 //TODO this must be a bug somewhere!!!!
149 returned = JavaUtils.getHolderValue(returned);
150 }
151 JavaUtils.setHolderValue((Holder) parameter, returned);
152 }
153 }
154 }
155
156 }