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.message.Attachment;
29import com.sun.xml.internal.ws.api.message.Headers;
30import com.sun.xml.internal.ws.api.message.Message;
31import com.sun.xml.internal.ws.message.ByteArrayAttachment;
32import com.sun.xml.internal.ws.message.DataHandlerAttachment;
33import com.sun.xml.internal.ws.message.JAXBAttachment;
34import com.sun.xml.internal.ws.model.ParameterImpl;
35import com.sun.xml.internal.ws.spi.db.XMLBridge;
36
37import java.io.UnsupportedEncodingException;
38import java.net.URLEncoder;
39import java.util.UUID;
40import javax.activation.DataHandler;
41import javax.xml.transform.Source;
42import javax.xml.ws.WebServiceException;
43
44/**
45 * Puts a non-payload message parameter to {@link Message}.
46 *
47 * <p>
48 * Instance of this class is used to handle header parameters and attachment parameters.
49 * They add things to {@link Message}.
50 *
51 * @see BodyBuilder
52 * @author Kohsuke Kawaguchi
53 * @author Jitendra Kotamraju
54 */
55abstract class MessageFiller {
56
57    /**
58     * The index of the method invocation parameters that this object looks for.
59     */
60    protected final int methodPos;
61
62    protected MessageFiller( int methodPos) {
63        this.methodPos = methodPos;
64    }
65
66    /**
67     * Moves an argument of a method invocation into a {@link Message}.
68     */
69    abstract void fillIn(Object[] methodArgs, Message msg);
70
71    /**
72     * Adds a parameter as an MIME attachment to {@link Message}.
73     */
74    static abstract class AttachmentFiller extends MessageFiller {
75        protected final ParameterImpl param;
76        protected final ValueGetter getter;
77        protected final String mimeType;
78        private final String contentIdPart;
79
80        protected AttachmentFiller(ParameterImpl param, ValueGetter getter) {
81            super(param.getIndex());
82            this.param = param;
83            this.getter = getter;
84            mimeType = param.getBinding().getMimeType();
85            try {
86                contentIdPart = URLEncoder.encode(param.getPartName(), "UTF-8")+'=';
87            } catch (UnsupportedEncodingException e) {
88                throw new WebServiceException(e);
89            }
90        }
91
92        /**
93         * Creates an MessageFiller based on the parameter type
94         *
95         * @param param
96         *      runtime Parameter that abstracts the annotated java parameter
97         * @param getter
98         *      Gets a value from an object that represents a parameter passed
99         *      as a method argument.
100         */
101        public static MessageFiller createAttachmentFiller(ParameterImpl param, ValueGetter getter) {
102            Class type = (Class)param.getTypeInfo().type;
103            if (DataHandler.class.isAssignableFrom(type) || Source.class.isAssignableFrom(type)) {
104                return new DataHandlerFiller(param, getter);
105            } else if (byte[].class==type) {
106                return new ByteArrayFiller(param, getter);
107            } else if(isXMLMimeType(param.getBinding().getMimeType())) {
108                return new JAXBFiller(param, getter);
109            } else {
110                return new DataHandlerFiller(param, getter);
111            }
112        }
113
114        String getContentId() {
115            return contentIdPart+UUID.randomUUID()+"@jaxws.sun.com";
116        }
117    }
118
119    private static class ByteArrayFiller extends AttachmentFiller {
120        protected ByteArrayFiller(ParameterImpl param, ValueGetter getter) {
121            super(param, getter);
122        }
123        void fillIn(Object[] methodArgs, Message msg) {
124            String contentId = getContentId();
125            Object obj = getter.get(methodArgs[methodPos]);
126            Attachment att = new ByteArrayAttachment(contentId,(byte[])obj,mimeType);
127            msg.getAttachments().add(att);
128        }
129    }
130
131    private static class DataHandlerFiller extends AttachmentFiller {
132        protected DataHandlerFiller(ParameterImpl param, ValueGetter getter) {
133            super(param, getter);
134        }
135        void fillIn(Object[] methodArgs, Message msg) {
136            String contentId = getContentId();
137            Object obj = getter.get(methodArgs[methodPos]);
138            DataHandler dh = (obj instanceof DataHandler) ? (DataHandler)obj : new DataHandler(obj,mimeType);
139            Attachment att = new DataHandlerAttachment(contentId, dh);
140            msg.getAttachments().add(att);
141        }
142    }
143
144    private static class JAXBFiller extends AttachmentFiller {
145        protected JAXBFiller(ParameterImpl param, ValueGetter getter) {
146            super(param, getter);
147        }
148        void fillIn(Object[] methodArgs, Message msg) {
149            String contentId = getContentId();
150            Object obj = getter.get(methodArgs[methodPos]);
151            Attachment att = new JAXBAttachment(contentId, obj, param.getXMLBridge(), mimeType);
152            msg.getAttachments().add(att);
153        }
154    }
155
156    /**
157     * Adds a parameter as an header.
158     */
159    static final class Header extends MessageFiller {
160        private final XMLBridge bridge;
161        private final ValueGetter getter;
162
163        protected Header(int methodPos, XMLBridge bridge, ValueGetter getter) {
164            super(methodPos);
165            this.bridge = bridge;
166            this.getter = getter;
167        }
168
169        void fillIn(Object[] methodArgs, Message msg) {
170            Object value = getter.get(methodArgs[methodPos]);
171            msg.getHeaders().add(Headers.create(bridge,value));
172        }
173    }
174
175    private static boolean isXMLMimeType(String mimeType){
176        return (mimeType.equals("text/xml") || mimeType.equals("application/xml"));
177    }
178
179}
180