Skip to content

Commit 1173f52

Browse files
authored
Merge pull request #20483 from BerksanAtes/20439-Skip_settings
Policy related Changes are moved to CXF 3.4
2 parents f325cb3 + 26bf5ae commit 1173f52

File tree

6 files changed

+1242
-1
lines changed

6 files changed

+1242
-1
lines changed

dev/com.ibm.ws.org.apache.cxf.cxf.rt.frontend.jaxws.3.2/bnd.overrides

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ Import-Package: \
3535
javax.xml.bind.*;version=!,\
3636
javax.xml.ws.*;version="[2.3,3)", \
3737
org.apache.cxf.*;version="[3.2.4,4)",\
38+
com.ibm.ws.ffdc,\
3839
*
3940

4041
DynamicImport-Package: com.ibm.ws.jaxws.client
Lines changed: 389 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,389 @@
1+
/**
2+
* Licensed to the Apache Software Foundation (ASF) under one
3+
* or more contributor license agreements. See the NOTICE file
4+
* distributed with this work for additional information
5+
* regarding copyright ownership. The ASF licenses this file
6+
* to you under the Apache License, Version 2.0 (the
7+
* "License"); you may not use this file except in compliance
8+
* with 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,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
package org.apache.cxf.jaxws.interceptors;
20+
import java.awt.Component;
21+
import java.awt.Graphics;
22+
import java.awt.Image;
23+
import java.awt.MediaTracker;
24+
import java.awt.image.BufferedImage;
25+
import java.io.ByteArrayOutputStream;
26+
import java.io.IOException;
27+
import java.io.InputStream;
28+
import java.io.OutputStream;
29+
import java.lang.reflect.Method;
30+
import java.nio.charset.StandardCharsets;
31+
import java.security.AccessController;
32+
import java.security.PrivilegedExceptionAction;
33+
import java.util.ArrayList;
34+
import java.util.Collection;
35+
import java.util.Collections;
36+
import java.util.Iterator;
37+
import java.util.List;
38+
import java.util.Map;
39+
import java.util.Set;
40+
import java.util.UUID;
41+
import java.util.concurrent.ConcurrentHashMap;
42+
import java.util.logging.Level;
43+
import java.util.logging.Logger;
44+
45+
import javax.activation.DataHandler;
46+
import javax.activation.DataSource;
47+
import javax.imageio.ImageIO;
48+
import javax.imageio.ImageWriter;
49+
import javax.imageio.stream.ImageOutputStream;
50+
import javax.xml.bind.JAXBContext;
51+
import javax.xml.stream.XMLStreamException;
52+
import javax.xml.stream.XMLStreamWriter;
53+
import javax.xml.transform.Source;
54+
import javax.xml.transform.stream.StreamSource;
55+
56+
import org.apache.cxf.attachment.AttachmentImpl;
57+
import org.apache.cxf.attachment.ByteDataSource;
58+
import org.apache.cxf.binding.soap.SoapMessage;
59+
import org.apache.cxf.binding.soap.interceptor.AbstractSoapInterceptor;
60+
import org.apache.cxf.binding.soap.model.SoapBodyInfo;
61+
import org.apache.cxf.common.logging.LogUtils;
62+
import org.apache.cxf.databinding.DataBinding;
63+
import org.apache.cxf.helpers.CastUtils;
64+
import org.apache.cxf.helpers.IOUtils;
65+
import org.apache.cxf.helpers.LoadingByteArrayOutputStream;
66+
import org.apache.cxf.interceptor.AttachmentOutInterceptor;
67+
import org.apache.cxf.interceptor.Fault;
68+
import org.apache.cxf.jaxb.JAXBDataBinding;
69+
import org.apache.cxf.message.Attachment;
70+
import org.apache.cxf.message.Exchange;
71+
import org.apache.cxf.message.Message;
72+
import org.apache.cxf.message.MessageUtils;
73+
import org.apache.cxf.phase.Phase;
74+
import org.apache.cxf.service.Service;
75+
import org.apache.cxf.service.model.BindingMessageInfo;
76+
import org.apache.cxf.service.model.BindingOperationInfo;
77+
import org.apache.cxf.service.model.MessagePartInfo;
78+
import org.apache.cxf.staxutils.StaxUtils;
79+
80+
public class SwAOutInterceptor extends AbstractSoapInterceptor {
81+
private static final Logger LOG = LogUtils.getL7dLogger(SwAOutInterceptor.class);
82+
83+
private static final Map<String, Method> SWA_REF_METHOD
84+
= new ConcurrentHashMap<>(4, 0.75f, 2);
85+
private static final Set<String> SWA_REF_NO_METHOD
86+
= Collections.newSetFromMap(new ConcurrentHashMap<String, Boolean>(4, 0.75f, 2));
87+
88+
// Liberty change begin migration of behaviour from CXF 2.6.2
89+
private static boolean skipHasSwaRef;
90+
91+
static {
92+
93+
String skipSwaRef = System.getProperty("cxf.multipart.attachment");
94+
LOG.log(Level.FINE, "cxf.multipart.attachment property is set to " + skipSwaRef);
95+
96+
if (skipSwaRef != null
97+
&& skipSwaRef.trim().length() > 0
98+
&& skipSwaRef.trim().equalsIgnoreCase("false")) {
99+
skipHasSwaRef = true;
100+
} else {
101+
skipHasSwaRef = false;
102+
}
103+
104+
}// Liberty change end
105+
106+
AttachmentOutInterceptor attachOut = new AttachmentOutInterceptor();
107+
108+
public SwAOutInterceptor() {
109+
super(Phase.PRE_LOGICAL);
110+
addAfter(HolderOutInterceptor.class.getName());
111+
addBefore(WrapperClassOutInterceptor.class.getName());
112+
}
113+
114+
private boolean callSWARefMethod(final JAXBContext ctx) {
115+
String cname = ctx.getClass().getName();
116+
Method m = SWA_REF_METHOD.get(cname);
117+
if (m == null && !SWA_REF_NO_METHOD.contains(cname)) {
118+
try {
119+
m = AccessController.doPrivileged(new PrivilegedExceptionAction<Method>() {
120+
121+
public Method run() throws Exception {
122+
Method hasSwaRefMethod = ctx.getClass().getMethod("hasSwaRef", new Class[0]);
123+
if (!hasSwaRefMethod.isAccessible()) {
124+
hasSwaRefMethod.setAccessible(true);
125+
}
126+
return hasSwaRefMethod;
127+
}
128+
});
129+
if (m == null) {
130+
SWA_REF_NO_METHOD.add(cname);
131+
} else {
132+
SWA_REF_METHOD.put(cname, m);
133+
}
134+
} catch (Exception e) {
135+
//ignore
136+
}
137+
}
138+
try {
139+
if (m != null) {
140+
return (Boolean)m.invoke(ctx);
141+
}
142+
} catch (Exception e) {
143+
//ignore
144+
}
145+
return false;
146+
}
147+
148+
public void handleMessage(SoapMessage message) throws Fault {
149+
Exchange ex = message.getExchange();
150+
BindingOperationInfo bop = ex.getBindingOperationInfo();
151+
if (bop == null) {
152+
return;
153+
}
154+
155+
if (bop.isUnwrapped()) {
156+
bop = bop.getWrappedOperation();
157+
}
158+
159+
boolean client = isRequestor(message);
160+
BindingMessageInfo bmi = client ? bop.getInput() : bop.getOutput();
161+
162+
if (bmi == null) {
163+
return;
164+
}
165+
// Liberty change begin migration of behaviour from CXF 2.6.2
166+
Boolean newAttachment = false;
167+
Message exOutMsg = ex.getOutMessage();
168+
if (exOutMsg != null) {
169+
newAttachment = MessageUtils.isTrue(exOutMsg.getContextualProperty("cxf.add.attachments"));
170+
LOG.log(Level.FINE, "Request context attachment property: cxf.add.attachments is set to: " + newAttachment);
171+
} // Liberty change end
172+
173+
SoapBodyInfo sbi = bmi.getExtensor(SoapBodyInfo.class);
174+
175+
if (sbi == null || sbi.getAttachments() == null || sbi.getAttachments().isEmpty()) {
176+
Service s = ex.getService();
177+
DataBinding db = s.getDataBinding();
178+
if (db instanceof JAXBDataBinding
179+
&& hasSwaRef((JAXBDataBinding) db)) {
180+
// Liberty change begin migration of behaviour from CXF 2.6.2
181+
Boolean includeAttachs = false;
182+
Message exInpMsg = ex.getInMessage();
183+
LOG.log(Level.FINE, "Exchange Input message: " + exInpMsg);
184+
if (exInpMsg != null) {
185+
includeAttachs = MessageUtils.isTrue(exInpMsg.getContextualProperty("cxf.add.attachments"));
186+
}
187+
LOG.log(Level.FINE, "Add attachments message property: cxf.add.attachments value is " + includeAttachs);
188+
if (!skipHasSwaRef || includeAttachs || newAttachment) {
189+
setupAttachmentOutput(message);
190+
} else {
191+
skipAttachmentOutput(message);
192+
} // Liberty change end
193+
}
194+
return;
195+
}
196+
processAttachments(message, sbi);
197+
}
198+
protected void processAttachments(SoapMessage message, SoapBodyInfo sbi) {
199+
Collection<Attachment> atts = setupAttachmentOutput(message);
200+
List<Object> outObjects = CastUtils.cast(message.getContent(List.class));
201+
202+
for (MessagePartInfo mpi : sbi.getAttachments()) {
203+
String partName = mpi.getConcreteName().getLocalPart();
204+
String ct = (String) mpi.getProperty(Message.CONTENT_TYPE);
205+
206+
String id = new StringBuilder().append(partName)
207+
.append('=')
208+
.append(UUID.randomUUID())
209+
.append("@apache.org").toString();
210+
211+
// this assumes things are in order...
212+
int idx = mpi.getIndex();
213+
Object o = outObjects.get(idx);
214+
215+
if (o == null) {
216+
continue;
217+
}
218+
outObjects.set(idx, null);
219+
DataHandler dh = null;
220+
221+
// This code could probably be refactored out somewhere...
222+
if (o instanceof Source) {
223+
dh = new DataHandler(createDataSource((Source)o, ct));
224+
} else if (o instanceof Image) {
225+
final Image img = (Image)o;
226+
final String contentType = ct;
227+
dh = new DataHandler(o, ct) {
228+
@Override
229+
public InputStream getInputStream() throws IOException {
230+
LoadingByteArrayOutputStream bout = new LoadingByteArrayOutputStream();
231+
writeTo(bout);
232+
return bout.createInputStream();
233+
}
234+
@Override
235+
public void writeTo(OutputStream out) throws IOException {
236+
ImageWriter writer = null;
237+
Iterator<ImageWriter> writers = ImageIO.getImageWritersByMIMEType(contentType);
238+
if (writers.hasNext()) {
239+
writer = writers.next();
240+
}
241+
if (writer != null) {
242+
BufferedImage bimg = convertToBufferedImage(img);
243+
ImageOutputStream iout = ImageIO.createImageOutputStream(out);
244+
writer.setOutput(iout);
245+
writer.write(bimg);
246+
writer.dispose();
247+
iout.flush();
248+
out.flush();
249+
}
250+
}
251+
};
252+
253+
} else if (o instanceof DataHandler) {
254+
dh = (DataHandler) o;
255+
ct = dh.getContentType();
256+
257+
try {
258+
if ("text/xml".equals(ct)
259+
&& dh.getContent() instanceof Source) {
260+
dh = new DataHandler(createDataSource((Source)dh.getContent(), ct));
261+
}
262+
} catch (IOException e) {
263+
//ignore, use same dh
264+
}
265+
} else if (o instanceof byte[]) {
266+
if (ct == null) {
267+
ct = "application/octet-stream";
268+
}
269+
dh = new DataHandler(new ByteDataSource((byte[])o, ct));
270+
} else if (o instanceof String) {
271+
if (ct == null) {
272+
ct = "text/plain; charset=\'UTF-8\'";
273+
}
274+
dh = new DataHandler(new ByteDataSource(((String)o).getBytes(StandardCharsets.UTF_8), ct));
275+
} else {
276+
throw new Fault(new org.apache.cxf.common.i18n.Message("ATTACHMENT_NOT_SUPPORTED",
277+
LOG, o.getClass()));
278+
}
279+
280+
AttachmentImpl att = new AttachmentImpl(id);
281+
att.setDataHandler(dh);
282+
att.setHeader("Content-Type", ct);
283+
att.setHeader("Content-ID", "<" + id + ">");
284+
atts.add(att);
285+
}
286+
}
287+
288+
protected boolean hasSwaRef(JAXBDataBinding db) {
289+
JAXBContext context = db.getContext();
290+
return callSWARefMethod(context);
291+
}
292+
293+
private DataSource createDataSource(Source o, String ct) {
294+
DataSource ds = null;
295+
296+
if (o instanceof StreamSource) {
297+
StreamSource src = (StreamSource)o;
298+
try {
299+
if (src.getInputStream() != null) {
300+
try (ByteArrayOutputStream bos = new ByteArrayOutputStream(2048)) {
301+
IOUtils.copy(src.getInputStream(), bos, 1024);
302+
ds = new ByteDataSource(bos.toByteArray(), ct);
303+
}
304+
} else {
305+
ds = new ByteDataSource(IOUtils.toString(src.getReader()).getBytes(StandardCharsets.UTF_8),
306+
ct);
307+
}
308+
} catch (IOException e) {
309+
throw new Fault(e);
310+
}
311+
} else {
312+
ByteArrayOutputStream bwriter = new ByteArrayOutputStream();
313+
XMLStreamWriter writer = null;
314+
try {
315+
writer = StaxUtils.createXMLStreamWriter(bwriter);
316+
StaxUtils.copy(o, writer);
317+
writer.flush();
318+
ds = new ByteDataSource(bwriter.toByteArray(), ct);
319+
} catch (XMLStreamException e1) {
320+
throw new Fault(e1);
321+
} finally {
322+
StaxUtils.close(writer);
323+
}
324+
}
325+
return ds;
326+
}
327+
328+
private BufferedImage convertToBufferedImage(Image image) throws IOException {
329+
if (image instanceof BufferedImage) {
330+
return (BufferedImage)image;
331+
}
332+
333+
// Wait until the image is completely loaded
334+
MediaTracker tracker = new MediaTracker(new Component() {
335+
private static final long serialVersionUID = 6412221228374321325L;
336+
});
337+
tracker.addImage(image, 0);
338+
try {
339+
tracker.waitForAll();
340+
} catch (InterruptedException e) {
341+
throw new Fault(e);
342+
}
343+
344+
// Create a BufferedImage so we can write it out later
345+
BufferedImage bufImage = new BufferedImage(
346+
image.getWidth(null),
347+
image.getHeight(null),
348+
BufferedImage.TYPE_INT_ARGB);
349+
350+
Graphics g = bufImage.createGraphics();
351+
g.drawImage(image, 0, 0, null);
352+
return bufImage;
353+
}
354+
355+
private Collection<Attachment> setupAttachmentOutput(SoapMessage message) {
356+
// We have attachments, so add the interceptor
357+
message.getInterceptorChain().add(attachOut);
358+
// We should probably come up with another property for this
359+
message.put(AttachmentOutInterceptor.WRITE_ATTACHMENTS, Boolean.TRUE);
360+
361+
362+
Collection<Attachment> atts = message.getAttachments();
363+
if (atts == null) {
364+
atts = new ArrayList<>();
365+
message.setAttachments(atts);
366+
}
367+
return atts;
368+
}
369+
370+
// Liberty change begin migration of behaviour from CXF 2.6.2
371+
private Collection<Attachment> skipAttachmentOutput(SoapMessage message) {
372+
373+
Collection<Attachment> atts = message.getAttachments();
374+
375+
LOG.log(Level.FINE, "skipAttachmentOutput: getAttachments returned " + atts);
376+
377+
if (atts != null) {
378+
// We have attachments, so add the interceptor
379+
message.getInterceptorChain().add(attachOut);
380+
// We should probably come up with another property for this
381+
message.put(AttachmentOutInterceptor.WRITE_ATTACHMENTS, Boolean.TRUE);
382+
} else {
383+
atts = new ArrayList<Attachment>();
384+
message.setAttachments(atts);
385+
}
386+
387+
return atts;
388+
}// Liberty change end
389+
}

0 commit comments

Comments
 (0)