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: 520432 $ $Date: 2007-03-20 11:35:27 -0400 (Tue, 20 Mar 2007) $ 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 }