View Javadoc

1   /**
2    *
3    *  Licensed to the Apache Software Foundation (ASF) under one or more
4    *  contributor license agreements.  See the NOTICE file distributed with
5    *  this work for additional information regarding copyright ownership.
6    *  The ASF licenses this file to You under the Apache License, Version 2.0
7    *  (the "License"); you may not use this file except in compliance with
8    *  the License.  You may obtain a copy of the License at
9    *
10   *     http://www.apache.org/licenses/LICENSE-2.0
11   *
12   *  Unless required by applicable law or agreed to in writing, software
13   *  distributed under the License is distributed on an "AS IS" BASIS,
14   *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15   *  See the License for the specific language governing permissions and
16   *  limitations under the License.
17   */
18  package org.apache.geronimo.axis.client;
19  
20  import java.lang.reflect.Method;
21  import java.rmi.RemoteException;
22  import java.util.Arrays;
23  import java.util.Iterator;
24  import java.util.Set;
25  import java.util.List;
26  import java.util.Map;
27  import javax.security.auth.Subject;
28  import javax.xml.rpc.holders.Holder;
29  import javax.wsdl.OperationType;
30  
31  import net.sf.cglib.proxy.MethodInterceptor;
32  import net.sf.cglib.proxy.MethodProxy;
33  import org.apache.axis.client.Call;
34  import org.apache.axis.description.ParameterDesc;
35  import org.apache.axis.utils.JavaUtils;
36  import org.apache.geronimo.security.ContextManager;
37  import org.apache.geronimo.security.jaas.NamedUsernamePasswordCredential;
38  
39  /**
40   * @version $Rev: 470597 $ $Date: 2006-11-02 15:30:55 -0800 (Thu, 02 Nov 2006) $
41   */
42  public class ServiceEndpointMethodInterceptor implements MethodInterceptor {
43  
44      private final GenericServiceEndpoint stub;
45      private final OperationInfo[] operations;
46      private final String credentialsName;
47  
48      public ServiceEndpointMethodInterceptor(GenericServiceEndpoint stub, OperationInfo[] operations, String credentialsName) {
49          this.stub = stub;
50          this.operations = operations;
51          this.credentialsName = credentialsName;
52      }
53  
54      public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
55          int index = methodProxy.getSuperIndex();
56          OperationInfo operationInfo = operations[index];
57          if (operationInfo == null) {
58              throw new RuntimeException("Operation not mapped: " + method.getName() + " index: " + index + "\n OperationInfos: " + Arrays.asList(operations));
59          }
60          stub.checkCachedEndpoint();
61  
62          Call call = stub.createCall();
63  
64          operationInfo.prepareCall(call);
65  
66          stub.setUpCall(call);
67          if (credentialsName != null) {
68              Subject subject = ContextManager.getNextCaller();
69              if (subject == null) {
70                  throw new IllegalStateException("Subject missing but authentication turned on");
71              } else {
72                  Set creds = subject.getPrivateCredentials(NamedUsernamePasswordCredential.class);
73                  boolean found = false;
74                  for (Iterator iterator = creds.iterator(); iterator.hasNext();) {
75                      NamedUsernamePasswordCredential namedUsernamePasswordCredential = (NamedUsernamePasswordCredential) iterator.next();
76                      if (credentialsName.equals(namedUsernamePasswordCredential.getName())) {
77                          call.setUsername(namedUsernamePasswordCredential.getUsername());
78                          call.setPassword(new String(namedUsernamePasswordCredential.getPassword()));
79                          found = true;
80                          break;
81                      }
82                  }
83                  if (!found) {
84                      throw new IllegalStateException("no NamedUsernamePasswordCredential found for name " + credentialsName);
85                  }
86              }
87          }
88          Object response = null;
89          List parameterDescs = operationInfo.getOperationDesc().getParameters();
90          Object[] unwrapped = extractFromHolders(objects, parameterDescs, operationInfo.getOperationDesc().getNumInParams());
91          if (operationInfo.getOperationDesc().getMep() == OperationType.REQUEST_RESPONSE) {
92              try {
93                  response = call.invoke(unwrapped);
94              } catch (RemoteException e) {
95                  throw operationInfo.unwrapFault(e);
96              }
97  
98              if (response instanceof RemoteException) {
99                  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 }