1/* 2 * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26package com.sun.xml.internal.ws.client.sei; 27 28import com.sun.xml.internal.ws.api.model.Parameter; 29import com.sun.xml.internal.ws.model.ParameterImpl; 30import com.sun.xml.internal.ws.spi.db.PropertyAccessor; 31 32import javax.xml.ws.Holder; 33import javax.xml.ws.WebServiceException; 34import javax.xml.namespace.QName; 35import javax.xml.bind.JAXBException; 36 37/** 38 * Moves a Java value unmarshalled from a response message 39 * to the right place. 40 * 41 * <p> 42 * Sometimes values are returned as a return value, and 43 * others are returned in the {@link Holder} value. Instances 44 * of this interface abstracts this detail. 45 * 46 * <p> 47 * {@link ValueSetter} is a stateless behavior encapsulation. 48 * 49 * @author Kohsuke Kawaguchi 50 */ 51public abstract class ValueSetter { 52 private ValueSetter() {} 53 54 /** 55 * Moves the value to the expected place. 56 * 57 * @param obj 58 * The unmarshalled object. 59 * @param args 60 * The arguments given to the Java method invocation. If {@code obj} 61 * is supposed to be returned as a {@link Holder} value, a suitable 62 * {@link Holder} is obtained from this argument list and {@code obj} 63 * is set. 64 * 65 * @return 66 * if {@code obj} is supposed to be returned as a return value 67 * from the method, this method returns {@code obj}. Otherwise null. 68 */ 69 abstract Object put(Object obj, Object[] args); 70 71 /** 72 * Singleton instance. 73 */ 74 private static final ValueSetter RETURN_VALUE = new ReturnValue(); 75 /** 76 * {@link Param}s with small index numbers are used often, 77 * so we pool them to reduce the footprint. 78 */ 79 private static final ValueSetter[] POOL = new ValueSetter[16]; 80 81 static { 82 for( int i=0; i<POOL.length; i++ ) 83 POOL[i] = new Param(i); 84 } 85 86 /** 87 * Returns a {@link ValueSetter} suitable for the given {@link Parameter}. 88 */ 89 static ValueSetter getSync(ParameterImpl p) { 90 int idx = p.getIndex(); 91 92 if(idx==-1) 93 return RETURN_VALUE; 94 if(idx<POOL.length) 95 return POOL[idx]; 96 else 97 return new Param(idx); 98 } 99 100 101 private static final class ReturnValue extends ValueSetter { 102 Object put(Object obj, Object[] args) { 103 return obj; 104 } 105 } 106 107 static final class Param extends ValueSetter { 108 /** 109 * Index of the argument to put the value to. 110 */ 111 private final int idx; 112 113 public Param(int idx) { 114 this.idx = idx; 115 } 116 117 Object put(Object obj, Object[] args) { 118 Object arg = args[idx]; 119 if(arg!=null) { 120 // we build model in such a way that this is guaranteed 121 assert arg instanceof Holder; 122 ((Holder)arg).value = obj; 123 } 124 // else { 125 // if null is given as a Holder, there's no place to return 126 // the value, so just ignore. 127 // } 128 129 // no value to return 130 return null; 131 } 132 } 133 134 /** 135 * Singleton instance. 136 */ 137 static final ValueSetter SINGLE_VALUE = new SingleValue(); 138 139 /** 140 * Used in case of async invocation, where there is only one OUT parameter 141 */ 142 private static final class SingleValue extends ValueSetter { 143 /** 144 * Set args[0] as the value 145 */ 146 Object put(Object obj, Object[] args) { 147 args[0] = obj; 148 return null; 149 } 150 } 151 152 /** 153 * OUT parameters are set in async bean 154 */ 155 static final class AsyncBeanValueSetter extends ValueSetter { 156 157 private final PropertyAccessor accessor; 158 159 AsyncBeanValueSetter(ParameterImpl p, Class wrapper) { 160 QName name = p.getName(); 161 try { 162 accessor = p.getOwner().getBindingContext().getElementPropertyAccessor( 163 wrapper, name.getNamespaceURI(), name.getLocalPart() ); 164 } catch (JAXBException e) { 165 throw new WebServiceException( // TODO: i18n 166 wrapper+" do not have a property of the name "+name,e); 167 } 168 } 169 170 /** 171 * Sets the property in async bean instance 172 * 173 * @param obj property in async bean 174 * @param args args[0] contains async bean instance 175 * @return null always 176 */ 177 Object put(Object obj, Object[] args) { 178 assert args != null; 179 assert args.length == 1; 180 assert args[0] != null; 181 182 Object bean = args[0]; 183 try { 184 accessor.set(bean, obj); 185 } catch (Exception e) { 186 throw new WebServiceException(e); // TODO:i18n 187 } 188 return null; 189 } 190 191 } 192 193} 194