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 }