public class StaxSchemaValidationOutInterceptor extends AbstractPhaseInterceptor<Message> { private static final Logger LOG = LogUtils.getL7dLogger(StaxSchemaValidationOutInterceptor.class); public StaxSchemaValidationOutInterceptor() { super(Phase.PRE_MARSHAL); } public void handleMessage(Message message) throws Fault { XMLStreamWriter writer = message.getContent(XMLStreamWriter.class); try { setSchemaInMessage(message, writer); } catch (XMLStreamException e) { throw new Fault(new org.apache.cxf.common.i18n.Message("SCHEMA_ERROR", LOG), e); } } private void setSchemaInMessage(Message message, XMLStreamWriter writer) throws XMLStreamException { if (ServiceUtils.isSchemaValidationEnabled(SchemaValidationType.OUT, message)) { try { WoodstoxValidationImpl mgr = new WoodstoxValidationImpl(); if (mgr.canValidate()) { mgr.setupValidation( writer, message.getExchange().getEndpoint(), message.getExchange().getService().getServiceInfos().get(0)); } } catch (Throwable t) { // likely no MSV or similar LOG.log(Level.FINE, "Problem initializing MSV validation", t); } } } }
@javax.jws.WebService( portName = "SoapPort", serviceName = "SOAPService", targetNamespace = "http://apache.org/hello_world_soap12_http", endpointInterface = "org.apache.hello_world_soap12_http.Greeter", wsdlLocation = "testutils/hello_world_soap12.wsdl") public class GreeterImpl implements Greeter { private static final Logger LOG = LogUtils.getLogger(GreeterImpl.class); /* (non-Javadoc) * @see org.apache.hello_world_soap12_http.Greeter#sayHi() */ public String sayHi() { LOG.info("Executing operation sayHi"); System.out.println("Executing operation sayHi\n"); return "Bonjour"; } public void pingMe() throws PingMeFault { FaultDetail faultDetail = new FaultDetail(); faultDetail.setMajor((short) 2); faultDetail.setMinor((short) 1); LOG.info("Executing operation pingMe, throwing PingMeFault exception"); System.out.println("Executing operation pingMe, throwing PingMeFault exception\n"); throw new PingMeFault("PingMeFault raised by server", faultDetail); } }
public class RMCaptureInInterceptor extends AbstractRMInterceptor<Message> { private static final Logger LOG = LogUtils.getLogger(RMCaptureInInterceptor.class); public RMCaptureInInterceptor() { super(Phase.PRE_STREAM); } protected void handle(Message message) throws SequenceFault, RMException { LOG.entering(getClass().getName(), "handleMessage"); // This message capturing mechanism will need to be changed at some point. // Until then, we keep this interceptor here and utilize the robust // option to avoid the unnecessary message capturing/caching. if (!MessageUtils.isTrue(message.getContextualProperty(Message.ROBUST_ONEWAY))) { InputStream is = message.getContent(InputStream.class); if (is != null) { CachedOutputStream saved = new CachedOutputStream(); try { IOUtils.copy(is, saved); saved.flush(); is.close(); saved.lockOutputStream(); LOG.fine("Capturing the original RM message"); RewindableInputStream ris = RewindableInputStream.makeRewindable(saved.getInputStream()); message.setContent(InputStream.class, ris); message.put(RMMessageConstants.SAVED_CONTENT, ris); } catch (Exception e) { throw new Fault(e); } } } } }
public class NMRConduit extends AbstractConduit { private static final Logger LOG = LogUtils.getL7dLogger(NMRConduit.class); private NMR nmr; private Bus bus; public NMRConduit(EndpointReferenceType target, NMR nmr) { this(null, target, nmr); } public NMRConduit(Bus bus, EndpointReferenceType target, NMR nmr) { super(target); this.nmr = nmr; this.bus = bus; } public Bus getBus() { return bus; } public NMR getNmr() { return nmr; } protected Logger getLogger() { return LOG; } public void prepare(Message message) throws IOException { getLogger().log(Level.FINE, "JBIConduit send message"); message.setContent(OutputStream.class, new NMRConduitOutputStream(message, nmr, target, this)); } }
private void initializeViaInitMethod( Handler<?> handler, Map<String, String> params, Method init) { try { init.invoke(handler, params); } catch (InvocationTargetException ex) { Throwable t = ex.getCause() != null ? ex.getCause() : ex; LogUtils.log(LOG, Level.WARNING, "INIT_METHOD_THREW_EXCEPTION", t, handler.getClass()); } catch (IllegalAccessException ex) { LOG.log(Level.SEVERE, "CANNOT_ACCESS_INIT", handler.getClass()); } }
public abstract class AbstractJAXWSGenerator extends AbstractGenerator { protected static final Logger LOG = LogUtils.getL7dLogger(AbstractJAXWSGenerator.class); protected static final String TEMPLATE_BASE = "org/apache/cxf/tools/wsdlto/frontend/jaxws/template"; public abstract boolean passthrough(); public abstract void generate(ToolContext penv) throws ToolException; public void register(final ClassCollector collector, String packageName, String fileName) { // do nothing } }
public class SamlHeaderOutInterceptor extends AbstractSamlOutInterceptor { private static final Logger LOG = LogUtils.getL7dLogger(SamlHeaderOutInterceptor.class); public SamlHeaderOutInterceptor() { this(Phase.WRITE); } public SamlHeaderOutInterceptor(String phase) { super(phase); } public void handleMessage(Message message) throws Fault { try { SamlAssertionWrapper assertionWrapper = createAssertion(message); Document doc = DOMUtils.newDocument(); Element assertionElement = assertionWrapper.toDOM(doc); String encodedToken = encodeToken(DOM2Writer.nodeToString(assertionElement)); Map<String, List<String>> headers = getHeaders(message); StringBuilder builder = new StringBuilder(); builder.append("SAML").append(" ").append(encodedToken); headers.put( "Authorization", CastUtils.cast(Collections.singletonList(builder.toString()), String.class)); } catch (Exception ex) { StringWriter sw = new StringWriter(); ex.printStackTrace(new PrintWriter(sw)); LOG.warning(sw.toString()); throw new Fault(new RuntimeException(ex.getMessage() + ", stacktrace: " + sw.toString())); } } private Map<String, List<String>> getHeaders(Message message) { Map<String, List<String>> headers = CastUtils.cast((Map<?, ?>) message.get(Message.PROTOCOL_HEADERS)); if (headers == null) { headers = new HashMap<>(); message.put(Message.PROTOCOL_HEADERS, headers); } return headers; } }
public abstract class AbstractConfigurableProvider { protected static final ResourceBundle BUNDLE = BundleUtils.getBundle(AbstractJAXBProvider.class); protected static final Logger LOG = LogUtils.getL7dLogger(AbstractJAXBProvider.class); private List<String> consumeMediaTypes; private List<String> produceMediaTypes; private boolean enableBuffering; private boolean enableStreaming; private Bus bus; /** * Sets the Bus * * @param b */ public void setBus(Bus b) { if (bus != null) { bus = b; } } /** * Gets the Bus. Providers may use the bus to resolve resource references. Example: * ResourceUtils.getResourceStream(reference, this.getBus()) * * @return */ public Bus getBus() { return bus != null ? bus : BusFactory.getThreadDefaultBus(); } /** * Sets custom Consumes media types; can be used to override static {@link Consumes} annotation * value set on the provider. * * @param types the media types */ public void setConsumeMediaTypes(List<String> types) { consumeMediaTypes = types; } /** * Gets the custom Consumes media types * * @return media types */ public List<String> getConsumeMediaTypes() { return consumeMediaTypes; } /** * Sets custom Produces media types; can be used to override static {@link Produces} annotation * value set on the provider. * * @param types the media types */ public void setProduceMediaTypes(List<String> types) { produceMediaTypes = types; } /** * Gets the custom Produces media types * * @return media types */ public List<String> getProduceMediaTypes() { return produceMediaTypes; } /** * Enables the buffering mode. If set to true then the runtime will ensure that the provider * writes to a cached stream. * * <p>For example, the JAXB marshalling process may fail after the initial XML tags have already * been written out to the HTTP output stream. Enabling the buffering ensures no incomplete * payloads are sent back to clients in case of marshalling errors at the cost of the initial * buffering - which might be negligible for small payloads. * * @param enableBuf the value of the buffering mode, false is default. */ public void setEnableBuffering(boolean enableBuf) { enableBuffering = enableBuf; } /** * Gets the value of the buffering mode * * @return true if the buffering is enabled */ public boolean getEnableBuffering() { return enableBuffering; } /** * Enables the support for streaming. XML-aware providers which prefer writing to Stax * XMLStreamWriter can set this value to true. Additionally, if the streaming and the buffering * modes are enabled, the runtime will ensure the XMLStreamWriter events are cached properly. * * @param enableStream the value of the streaming mode, false is default. */ public void setEnableStreaming(boolean enableStream) { enableStreaming = enableStream; } /** * Gets the value of the streaming mode * * @return true if the streaming is enabled */ public boolean getEnableStreaming() { return enableStreaming; } /** * Gives providers a chance to introspect the JAX-RS model classes. For example, the JAXB provider * may use the model classes to create a single composite JAXBContext supporting all the * JAXB-annotated root resource classes/types. * * @param resources */ public void init(List<ClassResourceInfo> resources) { // complete } protected boolean isPayloadEmpty(HttpHeaders headers) { if (headers != null) { return isPayloadEmpty(headers.getRequestHeaders()); } else { return false; } } protected boolean isPayloadEmpty(MultivaluedMap<String, String> headers) { return HttpUtils.isPayloadEmpty(headers); } protected void reportEmptyContentLength() throws NoContentException { String message = new org.apache.cxf.common.i18n.Message("EMPTY_BODY", BUNDLE).toString(); LOG.warning(message); throw new NoContentException(message); } }
@WebService( serviceName = "GreeterService", portName = "GreeterPort", endpointInterface = "org.apache.cxf.greeter_control.Greeter", targetNamespace = "http://cxf.apache.org/greeter_control") public class GreeterSessionImpl implements Greeter { private static final Logger LOG = LogUtils.getLogger( GreeterSessionImpl.class, null, GreeterSessionImpl.class.getPackage().getName()); @Resource private WebServiceContext context; // greetMe will use session to return last called name public String greetMe(String me) { LOG.info("Executing operation greetMe"); LOG.info("Message received: " + me); MessageContext mc = context.getMessageContext(); HttpServletRequest req = (HttpServletRequest) mc.get(MessageContext.SERVLET_REQUEST); Cookie cookies[] = req.getCookies(); String val = ""; if (cookies != null) { for (Cookie cookie : cookies) { val += ";" + cookie.getName() + "=" + cookie.getValue(); } } HttpSession session = req.getSession(); // Get a session property "counter" from context if (session == null) { throw new WebServiceException("No session in WebServiceContext"); } String name = (String) session.getAttribute("name"); if (name == null) { name = me; LOG.info("Starting the Session"); } session.setAttribute("name", me); return "Hello " + name + val; } public String sayHi() { LOG.info("Executing operation sayHi"); return "Bonjour "; } public void pingMe() {} public Future<?> greetMeAsync(String requestType, AsyncHandler<GreetMeResponse> asyncHandler) { // TODO Auto-generated method stub return null; } public Response<GreetMeResponse> greetMeAsync(String requestType) { // TODO Auto-generated method stub return null; } public void greetMeOneWay(String me) { LOG.info("Executing operation greetMeOneWay"); LOG.info("Message received: " + me); MessageContext mc = context.getMessageContext(); HttpServletRequest req = (HttpServletRequest) mc.get(MessageContext.SERVLET_REQUEST); HttpSession session = req.getSession(); if (session == null) { throw new WebServiceException("No session in WebServiceContext"); } String name = (String) session.getAttribute("name"); if (name == null) { name = me; LOG.info("Starting the Session"); } session.setAttribute("name", me); } public Future<?> pingMeAsync(AsyncHandler<PingMeResponse> asyncHandler) { // TODO Auto-generated method stub return null; } public Response<PingMeResponse> pingMeAsync() { // TODO Auto-generated method stub return null; } public Future<?> sayHiAsync(AsyncHandler<SayHiResponse> asyncHandler) { // TODO Auto-generated method stub return null; } public Response<SayHiResponse> sayHiAsync() { // TODO Auto-generated method stub return null; } }
public abstract class AbstractWrapKeyEncryptionAlgorithm implements KeyEncryptionProvider { protected static final Logger LOG = LogUtils.getL7dLogger(AbstractWrapKeyEncryptionAlgorithm.class); private Key keyEncryptionKey; private boolean wrap; private KeyAlgorithm algorithm; private Set<String> supportedAlgorithms; protected AbstractWrapKeyEncryptionAlgorithm(Key key, Set<String> supportedAlgorithms) { this(key, null, true, supportedAlgorithms); } protected AbstractWrapKeyEncryptionAlgorithm( Key key, boolean wrap, Set<String> supportedAlgorithms) { this(key, null, wrap, supportedAlgorithms); } protected AbstractWrapKeyEncryptionAlgorithm( Key key, KeyAlgorithm jweAlgo, Set<String> supportedAlgorithms) { this(key, jweAlgo, true, supportedAlgorithms); } protected AbstractWrapKeyEncryptionAlgorithm( Key key, KeyAlgorithm jweAlgo, boolean wrap, Set<String> supportedAlgorithms) { this.keyEncryptionKey = key; this.algorithm = jweAlgo; this.wrap = wrap; this.supportedAlgorithms = supportedAlgorithms; } @Override public KeyAlgorithm getAlgorithm() { return algorithm; } @Override public byte[] getEncryptedContentEncryptionKey(JweHeaders headers, byte[] cek) { checkAlgorithms(headers); KeyProperties secretKeyProperties = new KeyProperties(getKeyEncryptionAlgoJava(headers)); AlgorithmParameterSpec spec = getAlgorithmParameterSpec(headers); if (spec != null) { secretKeyProperties.setAlgoSpec(spec); } if (!wrap) { return CryptoUtils.encryptBytes(cek, keyEncryptionKey, secretKeyProperties); } else { return CryptoUtils.wrapSecretKey( cek, getContentEncryptionAlgoJava(headers), keyEncryptionKey, secretKeyProperties); } } protected String getKeyEncryptionAlgoJava(JweHeaders headers) { return AlgorithmUtils.toJavaName(headers.getKeyEncryptionAlgorithm().getJwaName()); } protected String getContentEncryptionAlgoJava(JweHeaders headers) { return AlgorithmUtils.toJavaName(headers.getContentEncryptionAlgorithm().getJwaName()); } protected AlgorithmParameterSpec getAlgorithmParameterSpec(JweHeaders headers) { return null; } protected String checkAlgorithm(String algo) { if (algo != null && !supportedAlgorithms.contains(algo)) { LOG.warning("Invalid key encryption algorithm: " + algo); throw new JweException(JweException.Error.INVALID_KEY_ALGORITHM); } return algo; } protected void checkAlgorithms(JweHeaders headers) { KeyAlgorithm providedAlgo = headers.getKeyEncryptionAlgorithm(); if (providedAlgo != null && !providedAlgo.equals(algorithm)) { LOG.warning("Invalid key encryption algorithm: " + providedAlgo); throw new JweException(JweException.Error.INVALID_KEY_ALGORITHM); } if (providedAlgo != null) { checkAlgorithm(providedAlgo.getJwaName()); } else { checkAlgorithm(algorithm.getJwaName()); headers.setKeyEncryptionAlgorithm(algorithm); } } }
public abstract class AbstractResourceInfo { public static final String CONSTRUCTOR_PROXY_MAP = "jaxrs-constructor-proxy-map"; private static final Logger LOG = LogUtils.getL7dLogger(AbstractResourceInfo.class); private static final String FIELD_PROXY_MAP = "jaxrs-field-proxy-map"; private static final String SETTER_PROXY_MAP = "jaxrs-setter-proxy-map"; private static final Set<String> STANDARD_CONTEXT_CLASSES = new HashSet<String>(); static { // JAX-RS 1.0-1.1 STANDARD_CONTEXT_CLASSES.add(Application.class.getName()); STANDARD_CONTEXT_CLASSES.add(UriInfo.class.getName()); STANDARD_CONTEXT_CLASSES.add(HttpHeaders.class.getName()); STANDARD_CONTEXT_CLASSES.add(Request.class.getName()); STANDARD_CONTEXT_CLASSES.add(SecurityContext.class.getName()); STANDARD_CONTEXT_CLASSES.add(Providers.class.getName()); STANDARD_CONTEXT_CLASSES.add(ContextResolver.class.getName()); STANDARD_CONTEXT_CLASSES.add("javax.servlet.http.HttpServletRequest"); STANDARD_CONTEXT_CLASSES.add("javax.servlet.http.HttpServletResponse"); STANDARD_CONTEXT_CLASSES.add("javax.servlet.ServletContext"); // JAX-RS 2.0 STANDARD_CONTEXT_CLASSES.add("javax.ws.rs.container.ResourceContext"); STANDARD_CONTEXT_CLASSES.add("javax.ws.rs.container.ResourceInfo"); STANDARD_CONTEXT_CLASSES.add("javax.ws.rs.core.Configuration"); } protected boolean root; protected Class<?> resourceClass; protected Class<?> serviceClass; private Map<Class<?>, List<Field>> contextFields; private Map<Class<?>, Map<Class<?>, Method>> contextMethods; private Bus bus; private boolean constructorProxiesAvailable; private boolean contextsAvailable; protected AbstractResourceInfo(Bus bus) { this.bus = bus; } protected AbstractResourceInfo( Class<?> resourceClass, Class<?> serviceClass, boolean isRoot, boolean checkContexts, Bus bus) { this(resourceClass, serviceClass, isRoot, checkContexts, null, bus, null); } protected AbstractResourceInfo( Class<?> resourceClass, Class<?> serviceClass, boolean isRoot, boolean checkContexts, Map<Class<?>, ThreadLocalProxy<?>> constructorProxies, Bus bus, Object provider) { this.bus = bus; this.serviceClass = serviceClass; this.resourceClass = resourceClass; root = isRoot; if (checkContexts && resourceClass != null) { findContexts(serviceClass, provider, constructorProxies); } } private void findContexts( Class<?> cls, Object provider, Map<Class<?>, ThreadLocalProxy<?>> constructorProxies) { findContextFields(cls, provider); findContextSetterMethods(cls, provider); if (constructorProxies != null) { Map<Class<?>, Map<Class<?>, ThreadLocalProxy<?>>> proxies = getConstructorProxyMap(true); proxies.put(serviceClass, constructorProxies); constructorProxiesAvailable = true; } contextsAvailable = contextFields != null && !contextFields.isEmpty() || contextMethods != null && !contextMethods.isEmpty() || constructorProxiesAvailable; } public boolean contextsAvailable() { return contextsAvailable; } public Bus getBus() { return bus; } public void setResourceClass(Class<?> rClass) { resourceClass = rClass; if (serviceClass.isInterface() && resourceClass != null && !resourceClass.isInterface()) { findContexts(resourceClass, null, null); } } public Class<?> getServiceClass() { return serviceClass; } private void findContextFields(Class<?> cls, Object provider) { if (cls == Object.class || cls == null) { return; } for (Field f : cls.getDeclaredFields()) { for (Annotation a : f.getAnnotations()) { if (a.annotationType() == Context.class) { contextFields = addContextField(contextFields, f); if (f.getType().isInterface()) { checkContextClass(f.getType()); addToMap(getFieldProxyMap(true), f, getFieldThreadLocalProxy(f, provider)); } } } } findContextFields(cls.getSuperclass(), provider); } private static ThreadLocalProxy<?> getFieldThreadLocalProxy(Field f, Object provider) { if (provider != null) { Object proxy = null; synchronized (provider) { try { proxy = InjectionUtils.extractFieldValue(f, provider); } catch (Throwable t) { // continue } if (!(proxy instanceof ThreadLocalProxy)) { proxy = InjectionUtils.createThreadLocalProxy(f.getType()); InjectionUtils.injectFieldValue(f, provider, proxy); } } return (ThreadLocalProxy<?>) proxy; } else { return InjectionUtils.createThreadLocalProxy(f.getType()); } } private static ThreadLocalProxy<?> getMethodThreadLocalProxy(Method m, Object provider) { if (provider != null) { Object proxy = null; synchronized (provider) { try { proxy = InjectionUtils.extractFromMethod( provider, InjectionUtils.getGetterFromSetter(m), false); } catch (Throwable t) { // continue } if (!(proxy instanceof ThreadLocalProxy)) { proxy = InjectionUtils.createThreadLocalProxy(m.getParameterTypes()[0]); InjectionUtils.injectThroughMethod(provider, m, proxy); } } return (ThreadLocalProxy<?>) proxy; } else { return InjectionUtils.createThreadLocalProxy(m.getParameterTypes()[0]); } } @SuppressWarnings("unchecked") private <T> Map<Class<?>, Map<T, ThreadLocalProxy<?>>> getProxyMap(String prop, boolean create) { Object property = null; synchronized (bus) { property = bus.getProperty(prop); if (property == null && create) { Map<Class<?>, Map<T, ThreadLocalProxy<?>>> map = Collections.synchronizedMap(new WeakHashMap<Class<?>, Map<T, ThreadLocalProxy<?>>>(2)); bus.setProperty(prop, map); property = map; } } return (Map<Class<?>, Map<T, ThreadLocalProxy<?>>>) property; } public Map<Class<?>, ThreadLocalProxy<?>> getConstructorProxies() { if (constructorProxiesAvailable) { return getConstructorProxyMap(false).get(serviceClass); } else { return null; } } @SuppressWarnings("unchecked") private Map<Class<?>, Map<Class<?>, ThreadLocalProxy<?>>> getConstructorProxyMap(boolean create) { Object property = bus.getProperty(CONSTRUCTOR_PROXY_MAP); if (property == null) { Map<Class<?>, Map<Class<?>, ThreadLocalProxy<?>>> map = Collections.synchronizedMap( new WeakHashMap<Class<?>, Map<Class<?>, ThreadLocalProxy<?>>>(2)); bus.setProperty(CONSTRUCTOR_PROXY_MAP, map); property = map; } return (Map<Class<?>, Map<Class<?>, ThreadLocalProxy<?>>>) property; } private Map<Class<?>, Map<Field, ThreadLocalProxy<?>>> getFieldProxyMap(boolean create) { return getProxyMap(FIELD_PROXY_MAP, create); } private Map<Class<?>, Map<Method, ThreadLocalProxy<?>>> getSetterProxyMap(boolean create) { return getProxyMap(SETTER_PROXY_MAP, create); } private void findContextSetterMethods(Class<?> cls, Object provider) { for (Method m : cls.getMethods()) { if (!m.getName().startsWith("set") || m.getParameterTypes().length != 1) { continue; } for (Annotation a : m.getAnnotations()) { if (a.annotationType() == Context.class) { checkContextMethod(m, provider); break; } } } Class<?>[] interfaces = cls.getInterfaces(); for (Class<?> i : interfaces) { findContextSetterMethods(i, provider); } Class<?> superCls = cls.getSuperclass(); if (superCls != null && superCls != Object.class) { findContextSetterMethods(superCls, provider); } } private void checkContextMethod(Method m, Object provider) { Class<?> type = m.getParameterTypes()[0]; if (type.isInterface() || type == Application.class) { checkContextClass(type); addContextMethod(type, m, provider); } } private void checkContextClass(Class<?> type) { if (!STANDARD_CONTEXT_CLASSES.contains(type.getName())) { LOG.fine( "Injecting a custom context " + type.getName() + ", ContextProvider is required for this type"); } } @SuppressWarnings("unchecked") public Map<Class<?>, Method> getContextMethods() { Map<Class<?>, Method> methods = contextMethods == null ? null : contextMethods.get(getServiceClass()); return methods == null ? Collections.EMPTY_MAP : Collections.unmodifiableMap(methods); } private void addContextMethod(Class<?> contextClass, Method m, Object provider) { if (contextMethods == null) { contextMethods = new HashMap<Class<?>, Map<Class<?>, Method>>(); } addToMap(contextMethods, contextClass, m); if (m.getParameterTypes()[0] != Application.class) { addToMap(getSetterProxyMap(true), m, getMethodThreadLocalProxy(m, provider)); } } public boolean isRoot() { return root; } public Class<?> getResourceClass() { return resourceClass; } public List<Field> getContextFields() { return getList(contextFields); } public ThreadLocalProxy<?> getContextFieldProxy(Field f) { return getProxy(getFieldProxyMap(true), f); } public ThreadLocalProxy<?> getContextSetterProxy(Method m) { return getProxy(getSetterProxyMap(true), m); } public abstract boolean isSingleton(); @SuppressWarnings("rawtypes") public static void clearAllMaps() { Bus bus = BusFactory.getThreadDefaultBus(false); if (bus != null) { Object property = bus.getProperty(FIELD_PROXY_MAP); if (property != null) { ((Map) property).clear(); } property = bus.getProperty(SETTER_PROXY_MAP); if (property != null) { ((Map) property).clear(); } property = bus.getProperty(CONSTRUCTOR_PROXY_MAP); if (property != null) { ((Map) property).clear(); } } } public void clearThreadLocalProxies() { clearProxies(getFieldProxyMap(false)); clearProxies(getSetterProxyMap(false)); clearProxies(getConstructorProxyMap(false)); } private <T> void clearProxies(Map<Class<?>, Map<T, ThreadLocalProxy<?>>> tlps) { Map<T, ThreadLocalProxy<?>> proxies = tlps == null ? null : tlps.get(getServiceClass()); if (proxies == null) { return; } for (ThreadLocalProxy<?> tlp : proxies.values()) { if (tlp != null) { tlp.remove(); } } } private Map<Class<?>, List<Field>> addContextField( Map<Class<?>, List<Field>> theFields, Field f) { if (theFields == null) { theFields = new HashMap<Class<?>, List<Field>>(); } List<Field> fields = theFields.get(serviceClass); if (fields == null) { fields = new ArrayList<Field>(); theFields.put(serviceClass, fields); } if (!fields.contains(f)) { fields.add(f); } return theFields; } private <T, V> void addToMap(Map<Class<?>, Map<T, V>> proxyMap, T f, V proxy) { Map<T, V> proxies = proxyMap.get(serviceClass); if (proxies == null) { proxies = Collections.synchronizedMap(new WeakHashMap<T, V>()); proxyMap.put(serviceClass, proxies); } if (!proxies.containsKey(f)) { proxies.put(f, proxy); } } private List<Field> getList(Map<Class<?>, List<Field>> fields) { List<Field> ret = fields == null ? null : fields.get(getServiceClass()); if (ret != null) { ret = Collections.unmodifiableList(ret); } else { ret = Collections.emptyList(); } return ret; } private <T> ThreadLocalProxy<?> getProxy( Map<Class<?>, Map<T, ThreadLocalProxy<?>>> proxies, T key) { Map<?, ThreadLocalProxy<?>> theMap = proxies == null ? null : proxies.get(getServiceClass()); ThreadLocalProxy<?> ret = null; if (theMap != null) { ret = theMap.get(key); } return ret; } }
public static Logger getLogger() { return LogUtils.getL7dLogger(CXFNonSpringServlet.class); }
public class AssociatedManagedConnectionFactoryImpl extends ManagedConnectionFactoryImpl implements ResourceAdapterAssociation { private static final long serialVersionUID = 4305487562182780773L; private static final Logger LOG = LogUtils.getL7dLogger(AssociatedManagedConnectionFactoryImpl.class); private ResourceAdapter ra; public AssociatedManagedConnectionFactoryImpl() { super(); } public AssociatedManagedConnectionFactoryImpl(Properties props) { super(props); } public Object createConnectionFactory(ConnectionManager connMgr) throws ResourceException { Object connFactory = super.createConnectionFactory(connMgr); registerBus(); return connFactory; } public void setResourceAdapter(ResourceAdapter aRA) throws ResourceException { LOG.info("Associate Resource Adapter with ManagedConnectionFactory by appserver. ra = " + ra); if (!(aRA instanceof ResourceAdapterImpl)) { throw new ResourceAdapterInternalException( "ResourceAdapter is not correct, it should be instance of ResourceAdapterImpl"); } this.ra = aRA; mergeResourceAdapterProps(); } public ResourceAdapter getResourceAdapter() { return ra; } /** * If outbound-resourceAdapter and the resourceAdapter has same property, the * outbound-resourceAdapter property's value would take precedence. */ protected void mergeResourceAdapterProps() { Properties raProps = ((ResourceAdapterImpl) ra).getPluginProps(); Properties props = getPluginProps(); Enumeration<?> raPropsEnum = raProps.propertyNames(); while (raPropsEnum.hasMoreElements()) { String key = (String) raPropsEnum.nextElement(); if (!props.containsKey(key)) { setProperty(key, raProps.getProperty(key)); } else { LOG.fine( "ManagedConnectionFactory's props already contain [" + key + "]. No need to merge"); } } } protected void registerBus() throws ResourceException { if (ra == null) { throw new ResourceAdapterInternalException("ResourceAdapter can not be null"); } ((ResourceAdapterImpl) ra).registerBus(getBus()); } protected Object getBootstrapContext() { return ((ResourceAdapterImpl) ra).getBootstrapContext(); } // Explicit override these two methods, // otherwise when deploy rar to weblogic9.1, it would complaint about this. public int hashCode() { return super.hashCode(); } public boolean equals(Object o) { return super.equals(o); } }
/** * WSDLQueryHandler class preserved from cxf 2.3. CXF 2.5 removed the class and now relies on the * WSDLGetInterceptor to perform the same logic, but the interceptor in its finally clause removes * the content of the message from the exchange and it can be retrieved. */ public class WSDLQueryHandler implements StemMatchingQueryHandler { private static final Logger LOG = LogUtils.getL7dLogger(WSDLQueryHandler.class); protected Bus bus; public WSDLQueryHandler(Bus b) { bus = b; } @Override public String getResponseContentType(String baseUri, String ctx) { if (baseUri.toLowerCase().contains("?wsdl") || baseUri.toLowerCase().contains("?xsd=")) { return "text/xml"; } return null; } @Override public boolean isRecognizedQuery( String baseUri, String ctx, EndpointInfo endpointInfo, boolean contextMatchExact) { if (baseUri != null && (baseUri.contains("?") && (baseUri.toLowerCase().contains("wsdl") || baseUri.toLowerCase().contains("xsd=")))) { int idx = baseUri.indexOf("?"); Map<String, String> map = UrlUtils.parseQueryString(baseUri.substring(idx + 1)); if (map.containsKey("wsdl") || map.containsKey("xsd")) { if (contextMatchExact) { return endpointInfo.getAddress().contains(ctx); } else { // contextMatchStrategy will be "stem" return endpointInfo.getAddress().contains(UrlUtils.getStem(baseUri.substring(0, idx))); } } } return false; } @Override public void writeResponse( String baseUri, String ctxUri, EndpointInfo endpointInfo, OutputStream os) { try { int idx = baseUri.toLowerCase().indexOf("?"); Map<String, String> params = UrlUtils.parseQueryString(baseUri.substring(idx + 1)); String base; if (endpointInfo.getProperty("publishedEndpointUrl") != null) { base = String.valueOf(endpointInfo.getProperty("publishedEndpointUrl")); } else { base = baseUri.substring(0, baseUri.toLowerCase().indexOf("?")); } String wsdl = params.get("wsdl"); if (wsdl != null) { // Always use the URL decoded version to ensure that we have a // canonical representation of the import URL for lookup. wsdl = URLDecoder.decode(wsdl, "utf-8"); } String xsd = params.get("xsd"); if (xsd != null) { // Always use the URL decoded version to ensure that we have a // canonical representation of the import URL for lookup. xsd = URLDecoder.decode(xsd, "utf-8"); } Map<String, Definition> mp = CastUtils.cast( (Map) endpointInfo.getService().getProperty(WSDLQueryHandler.class.getName())); Map<String, SchemaReference> smp = CastUtils.cast( (Map) endpointInfo .getService() .getProperty(WSDLQueryHandler.class.getName() + ".Schemas")); if (mp == null) { endpointInfo .getService() .setProperty(WSDLQueryHandler.class.getName(), new ConcurrentHashMap()); mp = CastUtils.cast( (Map) endpointInfo.getService().getProperty(WSDLQueryHandler.class.getName())); } if (smp == null) { endpointInfo .getService() .setProperty(WSDLQueryHandler.class.getName() + ".Schemas", new ConcurrentHashMap()); smp = CastUtils.cast( (Map) endpointInfo .getService() .getProperty(WSDLQueryHandler.class.getName() + ".Schemas")); } if (!mp.containsKey("")) { Definition def = getDefinition(endpointInfo); mp.put("", def); updateDefinition(def, mp, smp, base, endpointInfo); } Document doc; if (xsd == null) { Definition def = mp.get(wsdl); if (def == null) { String wsdl2 = resolveWithCatalogs(OASISCatalogManager.getCatalogManager(bus), wsdl, base); if (wsdl2 != null) { def = mp.get(wsdl2); } } if (def == null) { throw new WSDLQueryException( new org.apache.cxf.common.i18n.Message("WSDL_NOT_FOUND", LOG, wsdl), null); } synchronized (def) { // writing a def is not threadsafe. Sync on it to make sure // we don't get any ConcurrentModificationExceptions if (endpointInfo.getProperty("publishedEndpointUrl") != null) { String publishingUrl = String.valueOf(endpointInfo.getProperty("publishedEndpointUrl")); updatePublishedEndpointUrl(publishingUrl, def, endpointInfo.getName()); } WSDLWriter wsdlWriter = bus.getExtension(WSDLManager.class).getWSDLFactory().newWSDLWriter(); def.setExtensionRegistry(bus.getExtension(WSDLManager.class).getExtensionRegistry()); doc = wsdlWriter.getDocument(def); } } else { SchemaReference si = smp.get(xsd); if (si == null) { String xsd2 = resolveWithCatalogs(OASISCatalogManager.getCatalogManager(bus), xsd, base); if (xsd2 != null) { si = smp.get(xsd2); } } if (si == null) { throw new WSDLQueryException( new org.apache.cxf.common.i18n.Message("SCHEMA_NOT_FOUND", LOG, wsdl), null); } String uri = si.getReferencedSchema().getDocumentBaseURI(); uri = resolveWithCatalogs( OASISCatalogManager.getCatalogManager(bus), uri, si.getReferencedSchema().getDocumentBaseURI()); if (uri == null) { uri = si.getReferencedSchema().getDocumentBaseURI(); } ResourceManagerWSDLLocator rml = new ResourceManagerWSDLLocator(uri, bus); InputSource src = rml.getBaseInputSource(); doc = XMLUtils.getParser().parse(src); } updateDoc(doc, base, mp, smp, endpointInfo); String enc = null; try { enc = doc.getXmlEncoding(); } catch (Exception ex) { // ignore - not dom level 3 } if (enc == null) { enc = "utf-8"; } XMLStreamWriter writer = StaxUtils.createXMLStreamWriter(os, enc); StaxUtils.writeNode(doc, writer, true); writer.flush(); } catch (WSDLQueryException wex) { throw wex; } catch (Exception wex) { throw new WSDLQueryException( new org.apache.cxf.common.i18n.Message("COULD_NOT_PROVIDE_WSDL", LOG, baseUri), wex); } } protected Definition getDefinition(EndpointInfo endpointInfo) throws WSDLException { return new ServiceWSDLBuilder(bus, endpointInfo.getService()).build(); } protected void updateDoc( Document doc, String base, Map<String, Definition> mp, Map<String, SchemaReference> smp, EndpointInfo ei) { List<Element> elementList = null; try { elementList = DOMUtils.findAllElementsByTagNameNS( doc.getDocumentElement(), "http://www.w3.org/2001/XMLSchema", "import"); for (Element el : elementList) { String sl = el.getAttribute("schemaLocation"); if (smp.containsKey(URLDecoder.decode(sl, "utf-8"))) { el.setAttribute("schemaLocation", rewriteSchemaLocation(base, sl)); } } elementList = DOMUtils.findAllElementsByTagNameNS( doc.getDocumentElement(), "http://www.w3.org/2001/XMLSchema", "include"); for (Element el : elementList) { String sl = el.getAttribute("schemaLocation"); if (smp.containsKey(URLDecoder.decode(sl, "utf-8"))) { el.setAttribute("schemaLocation", rewriteSchemaLocation(base, sl)); } } elementList = DOMUtils.findAllElementsByTagNameNS( doc.getDocumentElement(), "http://www.w3.org/2001/XMLSchema", "redefine"); for (Element el : elementList) { String sl = el.getAttribute("schemaLocation"); if (smp.containsKey(URLDecoder.decode(sl, "utf-8"))) { el.setAttribute("schemaLocation", rewriteSchemaLocation(base, sl)); } } elementList = DOMUtils.findAllElementsByTagNameNS( doc.getDocumentElement(), "http://schemas.xmlsoap.org/wsdl/", "import"); for (Element el : elementList) { String sl = el.getAttribute("location"); if (mp.containsKey(URLDecoder.decode(sl, "utf-8"))) { el.setAttribute("location", base + "?wsdl=" + sl.replace(" ", "%20")); } } } catch (UnsupportedEncodingException e) { throw new WSDLQueryException( new org.apache.cxf.common.i18n.Message("COULD_NOT_PROVIDE_WSDL", LOG, base), e); } rewriteOperationAddress(ei, doc, base); try { doc.setXmlStandalone(true); } catch (Exception ex) { // likely not DOM level 3 } } protected String rewriteSchemaLocation(String base, String schemaLocation) { return base + "?xsd=" + schemaLocation.replace(" ", "%20"); } protected void rewriteOperationAddress(EndpointInfo ei, Document doc, String base) { Boolean rewriteSoapAddress = ei.getProperty("autoRewriteSoapAddress", Boolean.class); List<Element> elementList = null; if (rewriteSoapAddress != null && rewriteSoapAddress.booleanValue()) { List<Element> serviceList = DOMUtils.findAllElementsByTagNameNS( doc.getDocumentElement(), "http://schemas.xmlsoap.org/wsdl/", "service"); for (Element serviceEl : serviceList) { String serviceName = serviceEl.getAttribute("name"); if (serviceName.equals(ei.getService().getName().getLocalPart())) { elementList = DOMUtils.findAllElementsByTagNameNS( doc.getDocumentElement(), "http://schemas.xmlsoap.org/wsdl/", "port"); for (Element el : elementList) { String name = el.getAttribute("name"); if (name.equals(ei.getName().getLocalPart())) { Element soapAddress = DOMUtils.findAllElementsByTagNameNS( el, "http://schemas.xmlsoap.org/wsdl/soap/", "address") .iterator() .next(); soapAddress.setAttribute("location", base); } } } } } } static String resolveWithCatalogs(OASISCatalogManager catalogs, String start, String base) { if (catalogs == null) { return null; } String resolvedSchemaLocation = null; try { resolvedSchemaLocation = catalogs.resolveSystem(start); if (resolvedSchemaLocation == null) { resolvedSchemaLocation = catalogs.resolveURI(start); } if (resolvedSchemaLocation == null) { resolvedSchemaLocation = catalogs.resolvePublic(start, base); } } catch (Exception ex) { // ignore } return resolvedSchemaLocation; } protected void updateDefinition( Definition def, Map<String, Definition> done, Map<String, SchemaReference> doneSchemas, String base, EndpointInfo ei) { OASISCatalogManager catalogs = OASISCatalogManager.getCatalogManager(bus); Collection<List<?>> imports = CastUtils.cast((Collection<?>) def.getImports().values()); for (List<?> lst : imports) { List<Import> impLst = CastUtils.cast(lst); for (Import imp : impLst) { String start = imp.getLocationURI(); String decodedStart = null; // Always use the URL decoded version to ensure that we have a // canonical representation of the import URL for lookup. try { decodedStart = URLDecoder.decode(start, "utf-8"); } catch (UnsupportedEncodingException e) { throw new WSDLQueryException( new org.apache.cxf.common.i18n.Message("COULD_NOT_PROVIDE_WSDL", LOG, start), e); } String resolvedSchemaLocation = resolveWithCatalogs(catalogs, start, base); if (resolvedSchemaLocation == null) { try { // check to see if it's already in a URL format. If so, leave it. new URL(start); } catch (MalformedURLException e) { if (done.put(decodedStart, imp.getDefinition()) == null) { updateDefinition(imp.getDefinition(), done, doneSchemas, base, ei); } } } else { if (done.put(decodedStart, imp.getDefinition()) == null) { done.put(resolvedSchemaLocation, imp.getDefinition()); updateDefinition(imp.getDefinition(), done, doneSchemas, base, ei); } } } } /* This doesn't actually work. Setting setSchemaLocationURI on the import * for some reason doesn't actually result in the new URI being written * */ Types types = def.getTypes(); if (types != null) { for (ExtensibilityElement el : CastUtils.cast(types.getExtensibilityElements(), ExtensibilityElement.class)) { if (el instanceof Schema) { Schema see = (Schema) el; updateSchemaImports(see, doneSchemas, base); } } } } protected void updatePublishedEndpointUrl(String publishingUrl, Definition def, QName name) { Collection<Service> services = CastUtils.cast(def.getAllServices().values()); for (Service service : services) { Collection<Port> ports = CastUtils.cast(service.getPorts().values()); if (ports.isEmpty()) { continue; } if (name == null) { setSoapAddressLocationOn(ports.iterator().next(), publishingUrl); break; // only update the first port since we don't target any specific port } else { for (Port port : ports) { if (name.getLocalPart().equals(port.getName())) { setSoapAddressLocationOn(port, publishingUrl); } } } } } private void setSoapAddressLocationOn(Port port, String url) { List<?> extensions = port.getExtensibilityElements(); for (Object extension : extensions) { if (extension instanceof SOAP12Address) { ((SOAP12Address) extension).setLocationURI(url); } else if (extension instanceof SOAPAddress) { ((SOAPAddress) extension).setLocationURI(url); } } } protected void updateSchemaImports( Schema schema, Map<String, SchemaReference> doneSchemas, String base) { OASISCatalogManager catalogs = OASISCatalogManager.getCatalogManager(bus); Collection<List<?>> imports = CastUtils.cast((Collection<?>) schema.getImports().values()); for (List<?> lst : imports) { List<SchemaImport> impLst = CastUtils.cast(lst); for (SchemaImport imp : impLst) { String start = imp.getSchemaLocationURI(); if (start != null) { String decodedStart = null; // Always use the URL decoded version to ensure that we have a // canonical representation of the import URL for lookup. try { decodedStart = URLDecoder.decode(start, "utf-8"); } catch (UnsupportedEncodingException e) { throw new WSDLQueryException( new org.apache.cxf.common.i18n.Message("COULD_NOT_PROVIDE_WSDL", LOG, start), e); } if (!doneSchemas.containsKey(decodedStart)) { String resolvedSchemaLocation = resolveWithCatalogs(catalogs, start, base); if (resolvedSchemaLocation == null) { try { checkSchemaUrl(doneSchemas, start, decodedStart, imp); } catch (MalformedURLException e) { if (doneSchemas.put(decodedStart, imp) == null) { updateSchemaImports(imp.getReferencedSchema(), doneSchemas, base); } } } else { if (doneSchemas.put(decodedStart, imp) == null) { doneSchemas.put(resolvedSchemaLocation, imp); updateSchemaImports(imp.getReferencedSchema(), doneSchemas, base); } } } } } } List<SchemaReference> includes = CastUtils.cast(schema.getIncludes()); for (SchemaReference included : includes) { String start = included.getSchemaLocationURI(); if (start != null) { String decodedStart = null; // Always use the URL decoded version to ensure that we have a // canonical representation of the import URL for lookup. try { decodedStart = URLDecoder.decode(start, "utf-8"); } catch (UnsupportedEncodingException e) { /*throw new WSDLQueryException(new org.apache.cxf.common.i18n.Message("COULD_NOT_PROVIDE_WSDL", LOG, start), e); */ } String resolvedSchemaLocation = resolveWithCatalogs(catalogs, start, base); if (resolvedSchemaLocation == null) { if (!doneSchemas.containsKey(decodedStart)) { try { checkSchemaUrl(doneSchemas, start, decodedStart, included); } catch (MalformedURLException e) { if (doneSchemas.put(decodedStart, included) == null) { updateSchemaImports(included.getReferencedSchema(), doneSchemas, base); } } } } else if (!doneSchemas.containsKey(decodedStart) || !doneSchemas.containsKey(resolvedSchemaLocation)) { doneSchemas.put(decodedStart, included); doneSchemas.put(resolvedSchemaLocation, included); updateSchemaImports(included.getReferencedSchema(), doneSchemas, base); } } } List<SchemaReference> redefines = CastUtils.cast(schema.getRedefines()); for (SchemaReference included : redefines) { String start = included.getSchemaLocationURI(); if (start != null) { String decodedStart = null; // Always use the URL decoded version to ensure that we have a // canonical representation of the import URL for lookup. try { decodedStart = URLDecoder.decode(start, "utf-8"); } catch (UnsupportedEncodingException e) { throw new WSDLQueryException( new org.apache.cxf.common.i18n.Message("COULD_NOT_PROVIDE_WSDL", LOG, start), e); } String resolvedSchemaLocation = resolveWithCatalogs(catalogs, start, base); if (resolvedSchemaLocation == null) { if (!doneSchemas.containsKey(decodedStart)) { try { checkSchemaUrl(doneSchemas, start, decodedStart, included); } catch (MalformedURLException e) { if (doneSchemas.put(decodedStart, included) == null) { updateSchemaImports(included.getReferencedSchema(), doneSchemas, base); } } } } else if (!doneSchemas.containsKey(decodedStart) || !doneSchemas.containsKey(resolvedSchemaLocation)) { doneSchemas.put(decodedStart, included); doneSchemas.put(resolvedSchemaLocation, included); updateSchemaImports(included.getReferencedSchema(), doneSchemas, base); } } } } protected void checkSchemaUrl( Map<String, SchemaReference> doneSchemas, String start, String decodedStart, SchemaReference imp) throws MalformedURLException { // check to see if it's already in a URL format. If so, leave it. new URL(start); } @Override public boolean isRecognizedQuery(String baseUri, String ctx, EndpointInfo endpointInfo) { return isRecognizedQuery(baseUri, ctx, endpointInfo, false); } }
public class InterceptorFaultTest extends AbstractBusClientServerTestBase { public static final String PORT = allocatePort(Server.class); private static final Logger LOG = LogUtils.getLogger(InterceptorFaultTest.class); private static final QName SOAP_FAULT_CODE = new QName("http://schemas.xmlsoap.org/soap/envelope/", "Server"); private static final String FAULT_MESSAGE = "Could not send Message."; private static final String CONTROL_PORT_ADDRESS = "http://localhost:" + PORT + "/SoapContext/ControlPort"; private static int decoupledEndpointPort = 1; private static String decoupledEndpoint; /** * Tests that a fault thrown by a server side interceptor is reported back to the client in * appropriate form (plain Fault in case of one way requests, SoapFault in case of two way * requests). Also demonstrates how an interceptor on the server out fault chain can distinguish * different fault modes (the capability to do so is crucial to QOS interceptors such as the RM, * addressing and policy interceptors). */ public static class Server extends AbstractBusTestServerBase { Endpoint ep; protected void run() { SpringBusFactory factory = new SpringBusFactory(); Bus bus = factory.createBus(); BusFactory.setDefaultBus(bus); setBus(bus); ControlImpl implementor = new ControlImpl(); implementor.setAddress("http://localhost:" + PORT + "/SoapContext/GreeterPort"); GreeterImpl greeterImplementor = new GreeterImpl(); greeterImplementor.setThrowAlways(true); greeterImplementor.useLastOnewayArg(true); implementor.setImplementor(greeterImplementor); ep = Endpoint.publish(CONTROL_PORT_ADDRESS, implementor); LOG.fine("Published control endpoint."); } public void tearDown() { ep.stop(); ep = null; } public static void main(String[] args) { try { Server s = new Server(); s.start(); } catch (Exception ex) { ex.printStackTrace(); System.exit(-1); } finally { System.out.println("done!"); } } } private Bus controlBus; private Control control; private Bus greeterBus; private Greeter greeter; private List<Phase> inPhases; private PhaseComparator comparator; private Phase preLogicalPhase; @BeforeClass public static void startServers() throws Exception { System.setProperty("org.apache.cxf.transports.http_jetty.DontClosePort." + PORT, "true"); assertTrue("server did not launch correctly", launchServer(Server.class, true)); createStaticBus(); } @AfterClass public static void reset() { System.clearProperty("org.apache.cxf.transports.http_jetty.DontClosePort." + PORT); Bus b = BusFactory.getDefaultBus(false); if (b == null) { b = BusFactory.getThreadDefaultBus(false); } if (b == null) { b = BusFactory.getDefaultBus(); } b.shutdown(true); } @After public void tearDown() throws Exception { if (null != greeter) { ((java.io.Closeable) greeter).close(); assertTrue("Failed to stop greeter.", control.stopGreeter(null)); greeterBus.shutdown(true); greeterBus = null; } if (null != control) { assertTrue("Failed to stop greeter", control.stopGreeter(null)); ((java.io.Closeable) control).close(); controlBus.shutdown(true); } } @Test public void testWithoutAddressing() throws Exception { testWithoutAddressing(false); } @Test public void testRobustWithoutAddressing() throws Exception { testWithoutAddressing(true); } private void testWithoutAddressing(boolean robust) throws Exception { setupGreeter("org/apache/cxf/systest/interceptor/no-addr.xml", false); control.setRobustInOnlyMode(robust); // all interceptors pass testInterceptorsPass(robust); // behaviour is identicial for all phases FaultLocation location = new org.apache.cxf.greeter_control.types.ObjectFactory().createFaultLocation(); // test failure occuring before and after logical addressing interceptor // won't get a fault in case of oneways non-robust for the latter (partial response already // sent) testInterceptorFail(inPhases, location, robust); } @Test public void testWithAddressingAnonymousReplies() throws Exception { testWithAddressingAnonymousReplies(false); } @Test public void testRobustWithAddressingAnonymousReplies() throws Exception { testWithAddressingAnonymousReplies(true); } private void testWithAddressingAnonymousReplies(boolean robust) throws Exception { setupGreeter("org/apache/cxf/systest/interceptor/addr.xml", false); control.setRobustInOnlyMode(robust); // all interceptors pass testInterceptorsPass(robust); // test failure in phases before Phase.PRE_LOGICAL FaultLocation location = new org.apache.cxf.greeter_control.types.ObjectFactory().createFaultLocation(); location.setAfter(MAPAggregator.class.getName()); // test failure occuring before and after logical addressing interceptor // won't get a fault in case of oneways non-robust for the latter (partial response already // sent) testInterceptorFail(inPhases, location, robust); } private void testInterceptorFail(List<Phase> phases, FaultLocation location, boolean robust) throws PingMeFault { for (Phase p : phases) { location.setPhase(p.getName()); if (Phase.PRE_LOGICAL.equals(p.getName())) { continue; } else if (Phase.POST_INVOKE.equals(p.getName())) { break; } testFail(location, true, robust); } } private void testInterceptorsPass(boolean robust) { greeter.greetMeOneWay("one"); // wait 5 seconds for the non-robust case if (!robust) { try { Thread.sleep(5000); } catch (InterruptedException e) { // ignore } } // verify both the previous greetMeOneWay call and this greetMe call assertEquals("one", greeter.greetMe("two")); try { greeter.pingMe(); fail("Expected PingMeFault not thrown."); } catch (PingMeFault f) { assertEquals(20, f.getFaultInfo().getMajor()); assertEquals(10, f.getFaultInfo().getMinor()); } } private void testFail(FaultLocation location, boolean usingAddressing, boolean robust) throws PingMeFault { // System.out.print("Test interceptor failing in phase: " + location.getPhase()); control.setFaultLocation(location); // oneway reports a plain fault (although server sends a soap fault) boolean expectOnewayFault = robust || comparator.compare(preLogicalPhase, getPhase(location.getPhase())) > 0; try { greeter.greetMeOneWay("oneway"); if (expectOnewayFault) { fail("Oneway operation unexpectedly succeded for phase " + location.getPhase()); } } catch (WebServiceException ex) { if (!expectOnewayFault) { fail("Oneway operation unexpectedly failed."); } assertEquals(FAULT_MESSAGE, ex.getMessage()); } String expectedMsg = getExpectedInterceptorFaultMessage(location.getPhase()); try { greeter.greetMe("cxf"); fail("Twoway operation unexpectedly succeded."); } catch (WebServiceException ex) { Throwable cause = ex.getCause(); SoapFault sf = (SoapFault) cause; assertEquals(expectedMsg, sf.getReason()); assertEquals(SOAP_FAULT_CODE, sf.getFaultCode()); } try { greeter.pingMe(); fail("Expected PingMeFault not thrown."); } catch (WebServiceException ex) { Throwable cause = ex.getCause(); SoapFault sf = (SoapFault) cause; assertEquals(expectedMsg, sf.getReason()); assertEquals(SOAP_FAULT_CODE, sf.getFaultCode()); } } private void setupGreeter(String cfgResource, boolean useDecoupledEndpoint) throws NumberFormatException, MalformedURLException { SpringBusFactory bf = new SpringBusFactory(); controlBus = bf.createBus(); BusFactory.setDefaultBus(controlBus); ControlService cs = new ControlService(); control = cs.getControlPort(); updateAddressPort(control, PORT); assertTrue("Failed to start greeter", control.startGreeter(cfgResource)); greeterBus = bf.createBus(cfgResource); BusFactory.setDefaultBus(greeterBus); LOG.fine("Initialised greeter bus with configuration: " + cfgResource); if (null == comparator) { comparator = new PhaseComparator(); } if (null == inPhases) { inPhases = new ArrayList<Phase>(); inPhases.addAll(greeterBus.getExtension(PhaseManager.class).getInPhases()); Collections.sort(inPhases, comparator); } if (null == preLogicalPhase) { preLogicalPhase = getPhase(Phase.PRE_LOGICAL); } GreeterService gs = new GreeterService(); greeter = gs.getGreeterPort(); updateAddressPort(greeter, PORT); LOG.fine("Created greeter client."); if (!useDecoupledEndpoint) { return; } // programatically configure decoupled endpoint that is guaranteed to // be unique across all test cases decoupledEndpointPort++; decoupledEndpoint = "http://localhost:" + allocatePort("decoupled-" + decoupledEndpointPort) + "/decoupled_endpoint"; Client c = ClientProxy.getClient(greeter); HTTPConduit hc = (HTTPConduit) (c.getConduit()); HTTPClientPolicy cp = hc.getClient(); cp.setDecoupledEndpoint(decoupledEndpoint); LOG.fine("Using decoupled endpoint: " + cp.getDecoupledEndpoint()); } private String getExpectedInterceptorFaultMessage(String phase) { return FaultThrowingInterceptor.MESSAGE_FORMAT.format(new Object[] {phase}).toUpperCase(); } private Phase getPhase(String name) { for (Phase p : inPhases) { if (p.getName().equals(name)) { return p; } } return null; } }
public class WSDLRefValidator extends AbstractDefinitionValidator { protected static final Logger LOG = LogUtils.getL7dLogger(WSDLRefValidator.class); protected List<XNode> vNodes = new ArrayList<XNode>(); private Set<QName> portTypeRefNames = new HashSet<QName>(); private Set<QName> messageRefNames = new HashSet<QName>(); private Map<QName, Service> services = new HashMap<QName, Service>(); private ValidationResult vResults = new ValidationResult(); private Definition definition; private Document baseDoc; private List<Definition> importedDefinitions; private SchemaCollection schemaCollection = new SchemaCollection(); private boolean suppressWarnings; public WSDLRefValidator(Definition wsdl, Document doc) { this(wsdl, doc, BusFactory.getThreadDefaultBus()); } public WSDLRefValidator(Definition wsdl, Document doc, Bus bus) { this.definition = wsdl; baseDoc = doc; importedDefinitions = new ArrayList<Definition>(); parseImports(wsdl); processSchemas(bus); } private void getSchemas(Bus bus) { Map<String, Element> schemaList = new HashMap<String, Element>(); SchemaUtil schemaUtil = new SchemaUtil(bus, schemaList); List<SchemaInfo> si = new ArrayList<SchemaInfo>(); schemaUtil.getSchemas(definition, schemaCollection, si); ServiceSchemaInfo ssi = new ServiceSchemaInfo(); ssi.setSchemaCollection(schemaCollection); ssi.setSchemaInfoList(si); ssi.setSchemaElementList(schemaList); bus.getExtension(WSDLManager.class).putSchemasForDefinition(definition, ssi); } private void processSchemas(Bus bus) { try { ServiceSchemaInfo info = bus.getExtension(WSDLManager.class).getSchemasForDefinition(definition); if (info == null) { getSchemas(bus); } else { schemaCollection = info.getSchemaCollection(); } checkTargetNamespace(this.definition.getTargetNamespace()); } catch (Exception ex) { throw new ToolException(ex); } } private Collection<Import> getImports(final Definition wsdlDef) { Collection<Import> importList = new ArrayList<Import>(); Map<?, ?> imports = wsdlDef.getImports(); for (Map.Entry<?, ?> entry : imports.entrySet()) { List<Import> lst = CastUtils.cast((List<?>) entry.getValue()); importList.addAll(lst); } return importList; } private void parseImports(Definition def) { for (Import impt : getImports(def)) { if (!importedDefinitions.contains(impt.getDefinition())) { importedDefinitions.add(impt.getDefinition()); parseImports(impt.getDefinition()); } } } private void checkTargetNamespace(String path) { try { if (new URL(path).getPath().indexOf(":") != -1) { throw new ToolException(": is not a valid char in the targetNamespace"); } } catch (MalformedURLException e) { // do nothing } } public void setSuppressWarnings(boolean s) { this.suppressWarnings = s; } public ValidationResult getValidationResults() { return this.vResults; } private Document getWSDLDocument(final String wsdl) throws URISyntaxException { return new Stax2DOM().getDocument(wsdl); } private Document getWSDLDocument() throws Exception { if (baseDoc != null) { return baseDoc; } return getWSDLDocument(this.definition.getDocumentBaseURI()); } private List<Document> getWSDLDocuments() { List<Document> docs = new ArrayList<Document>(); try { docs.add(getWSDLDocument()); if (null != importedDefinitions) { for (Definition d : importedDefinitions) { docs.add(getWSDLDocument(d.getDocumentBaseURI())); } } } catch (Exception e) { e.printStackTrace(); // ignore } return docs; } private boolean isExist(List<Document> docs, XNode vNode) { for (Document doc : docs) { if (vNode.matches(doc)) { return true; } } return false; } private FailureLocation getFailureLocation(List<Document> docs, XNode fNode) { if (fNode == null) { return null; } XPathUtils xpather = new XPathUtils(fNode.getNSMap()); for (Document doc : docs) { Node node = (Node) xpather.getValue(fNode.toString(), doc, XPathConstants.NODE); if (null != node) { try { return new FailureLocation((Location) node.getUserData("location"), doc.getDocumentURI()); } catch (Exception ex) { // ignore, probably not DOM level 3 } } } return null; } public boolean isValid() { try { loadServices(); collectValidationPoints(); List<Document> wsdlDocs = getWSDLDocuments(); for (XNode vNode : vNodes) { if (!isExist(wsdlDocs, vNode)) { // System.out.println("Fail: " + vNode.getXPath()); FailureLocation loc = getFailureLocation(wsdlDocs, vNode.getFailurePoint()); vResults.addError( new Message( "FAILED_AT_POINT", LOG, loc.getLocation().getLineNumber(), loc.getLocation().getColumnNumber(), loc.getDocumentURI(), vNode.getPlainText())); } } } catch (Exception e) { this.vResults.addError(e.getMessage()); return false; } return vResults.isSuccessful(); } private void addServices(final Definition wsdlDef) { Iterator<QName> sNames = CastUtils.cast(wsdlDef.getServices().keySet().iterator()); while (sNames.hasNext()) { QName sName = sNames.next(); services.put(sName, definition.getService(sName)); } } private void loadServices() { addServices(this.definition); if (importedDefinitions != null) { for (Definition d : importedDefinitions) { addServices(d); } } } private Map<QName, XNode> getBindings(Service service) { Map<QName, XNode> bindings = new HashMap<QName, XNode>(); if (service.getPorts().values().size() == 0) { throw new ToolException( "Service " + service.getQName() + " does not contain any usable ports"); } Collection<Port> ports = CastUtils.cast(service.getPorts().values()); for (Port port : ports) { Binding binding = port.getBinding(); bindings.put(binding.getQName(), getXNode(service, port)); if (WSDLConstants.NS_WSDL11.equals(binding.getQName().getNamespaceURI())) { throw new ToolException( "Binding " + binding.getQName().getLocalPart() + " namespace set improperly."); } } return bindings; } private Map<QName, Operation> getOperations(PortType portType) { Map<QName, Operation> operations = new HashMap<QName, Operation>(); Collection<Operation> pops = CastUtils.cast(portType.getOperations()); for (Operation op : pops) { operations.put(new QName(portType.getQName().getNamespaceURI(), op.getName()), op); } return operations; } private XNode getXNode(Service service, Port port) { XNode vService = getXNode(service); XPort pNode = new XPort(); pNode.setName(port.getName()); pNode.setParentNode(vService); return pNode; } private XNode getXNode(Service service) { XDef xdef = new XDef(); xdef.setTargetNamespace(service.getQName().getNamespaceURI()); XService sNode = new XService(); sNode.setName(service.getQName().getLocalPart()); sNode.setParentNode(xdef); return sNode; } private XNode getXNode(Binding binding) { XDef xdef = new XDef(); xdef.setTargetNamespace(binding.getQName().getNamespaceURI()); XBinding bNode = new XBinding(); bNode.setName(binding.getQName().getLocalPart()); bNode.setParentNode(xdef); return bNode; } private XNode getXNode(PortType portType) { XDef xdef = new XDef(); xdef.setTargetNamespace(portType.getQName().getNamespaceURI()); XPortType pNode = new XPortType(); pNode.setName(portType.getQName().getLocalPart()); pNode.setParentNode(xdef); return pNode; } private XNode getOperationXNode(XNode pNode, String opName) { XOperation node = new XOperation(); node.setName(opName); node.setParentNode(pNode); return node; } private XNode getInputXNode(XNode opVNode, String name) { XInput oNode = new XInput(); oNode.setName(name); oNode.setParentNode(opVNode); if (name != null && name.equals(opVNode.getAttributeValue() + "Request")) { oNode.setDefaultAttributeValue(true); } return oNode; } private XNode getOutputXNode(XNode opVNode, String name) { XOutput oNode = new XOutput(); oNode.setName(name); oNode.setParentNode(opVNode); if (name != null && name.equals(opVNode.getAttributeValue() + "Response")) { oNode.setDefaultAttributeValue(true); } return oNode; } private XNode getFaultXNode(XNode opVNode, String name) { XFault oNode = new XFault(); oNode.setName(name); oNode.setParentNode(opVNode); return oNode; } private XNode getXNode(javax.wsdl.Message msg) { XDef xdef = new XDef(); xdef.setTargetNamespace(msg.getQName().getNamespaceURI()); XMessage mNode = new XMessage(); mNode.setName(msg.getQName().getLocalPart()); mNode.setParentNode(xdef); return mNode; } private void addWarning(String warningMsg) { if (suppressWarnings) { return; } vResults.addWarning(warningMsg); } private void collectValidationPoints() throws Exception { if (services.size() == 0) { LOG.log( Level.WARNING, "WSDL document " + this.definition.getDocumentBaseURI() + " does not define any services"); // addWarning("WSDL document does not define any services"); Collection<QName> ports = CastUtils.cast(this.definition.getAllPortTypes().keySet()); portTypeRefNames.addAll(ports); } else { collectValidationPointsForBindings(); } collectValidationPointsForPortTypes(); collectValidationPointsForMessages(); } private void collectValidationPointsForBindings() throws Exception { Map<QName, XNode> vBindingNodes = new HashMap<QName, XNode>(); for (Service service : services.values()) { vBindingNodes.putAll(getBindings(service)); } for (Map.Entry<QName, XNode> entry : vBindingNodes.entrySet()) { QName bName = entry.getKey(); Binding binding = this.definition.getBinding(bName); if (binding == null) { LOG.log( Level.SEVERE, bName.toString() + " is not correct, please check that the correct namespace is being used"); throw new Exception( bName.toString() + " is not correct, please check that the correct namespace is being used"); } XNode vBindingNode = getXNode(binding); vBindingNode.setFailurePoint(entry.getValue()); vNodes.add(vBindingNode); if (binding.getPortType() == null) { continue; } portTypeRefNames.add(binding.getPortType().getQName()); XNode vPortTypeNode = getXNode(binding.getPortType()); vPortTypeNode.setFailurePoint(vBindingNode); vNodes.add(vPortTypeNode); Collection<BindingOperation> bops = CastUtils.cast(binding.getBindingOperations()); for (BindingOperation bop : bops) { XNode vOpNode = getOperationXNode(vPortTypeNode, bop.getName()); XNode vBopNode = getOperationXNode(vBindingNode, bop.getName()); vOpNode.setFailurePoint(vBopNode); vNodes.add(vOpNode); if (bop.getBindingInput() != null) { String inName = bop.getBindingInput().getName(); if (!StringUtils.isEmpty(inName)) { XNode vInputNode = getInputXNode(vOpNode, inName); vInputNode.setFailurePoint(getInputXNode(vBopNode, inName)); vNodes.add(vInputNode); } } if (bop.getBindingOutput() != null) { String outName = bop.getBindingOutput().getName(); if (!StringUtils.isEmpty(outName)) { XNode vOutputNode = getOutputXNode(vOpNode, outName); vOutputNode.setFailurePoint(getOutputXNode(vBopNode, outName)); vNodes.add(vOutputNode); } } for (Iterator<?> iter1 = bop.getBindingFaults().keySet().iterator(); iter1.hasNext(); ) { String faultName = (String) iter1.next(); XNode vFaultNode = getFaultXNode(vOpNode, faultName); vFaultNode.setFailurePoint(getFaultXNode(vBopNode, faultName)); vNodes.add(vFaultNode); } } } } private javax.wsdl.Message getMessage(QName msgName) { javax.wsdl.Message message = this.definition.getMessage(msgName); if (message == null) { for (Definition d : importedDefinitions) { message = d.getMessage(msgName); if (message != null) { break; } } } return message; } private void collectValidationPointsForMessages() { for (QName msgName : messageRefNames) { javax.wsdl.Message message = getMessage(msgName); for (Iterator<?> iter = message.getParts().values().iterator(); iter.hasNext(); ) { Part part = (Part) iter.next(); QName elementName = part.getElementName(); QName typeName = part.getTypeName(); if (elementName == null && typeName == null) { vResults.addError(new Message("PART_NO_TYPES", LOG)); continue; } if (elementName != null && typeName != null) { vResults.addError(new Message("PART_NOT_UNIQUE", LOG)); continue; } if (elementName != null && typeName == null) { boolean valid = validatePartType(elementName.getNamespaceURI(), elementName.getLocalPart(), true); if (!valid) { vResults.addError( new Message( "TYPE_REF_NOT_FOUND", LOG, message.getQName(), part.getName(), elementName)); } } if (typeName != null && elementName == null) { boolean valid = validatePartType(typeName.getNamespaceURI(), typeName.getLocalPart(), false); if (!valid) { vResults.addError( new Message( "TYPE_REF_NOT_FOUND", LOG, message.getQName(), part.getName(), typeName)); } } } } } private PortType getPortType(QName ptName) { PortType portType = this.definition.getPortType(ptName); if (portType == null) { for (Definition d : importedDefinitions) { portType = d.getPortType(ptName); if (portType != null) { break; } } } return portType; } private void collectValidationPointsForPortTypes() { for (QName ptName : portTypeRefNames) { PortType portType = getPortType(ptName); if (portType == null) { vResults.addError(new Message("NO_PORTTYPE", LOG, ptName)); continue; } XNode vPortTypeNode = getXNode(portType); for (Operation operation : getOperations(portType).values()) { XNode vOperationNode = getOperationXNode(vPortTypeNode, operation.getName()); if (operation.getInput() == null) { vResults.addError( new Message("WRONG_MEP", LOG, operation.getName(), portType.getQName())); continue; } javax.wsdl.Message inMsg = operation.getInput().getMessage(); if (inMsg == null) { addWarning( "Operation " + operation.getName() + " in PortType: " + portType.getQName() + " has no input message"); } else { XNode vInMsgNode = getXNode(inMsg); vInMsgNode.setFailurePoint(getInputXNode(vOperationNode, operation.getInput().getName())); vNodes.add(vInMsgNode); messageRefNames.add(inMsg.getQName()); } if (operation.getOutput() != null) { javax.wsdl.Message outMsg = operation.getOutput().getMessage(); if (outMsg == null) { addWarning( "Operation " + operation.getName() + " in PortType: " + portType.getQName() + " has no output message"); } else { XNode vOutMsgNode = getXNode(outMsg); vOutMsgNode.setFailurePoint( getOutputXNode(vOperationNode, operation.getOutput().getName())); vNodes.add(vOutMsgNode); messageRefNames.add(outMsg.getQName()); } } for (Iterator<?> iter = operation.getFaults().values().iterator(); iter.hasNext(); ) { Fault fault = (Fault) iter.next(); javax.wsdl.Message faultMsg = fault.getMessage(); XNode vFaultMsgNode = getXNode(faultMsg); vFaultMsgNode.setFailurePoint(getFaultXNode(vOperationNode, fault.getName())); vNodes.add(vFaultMsgNode); messageRefNames.add(faultMsg.getQName()); } } } } private boolean validatePartType(String namespace, String name, boolean isElement) { boolean partvalid = false; if (namespace.equals(WSDLConstants.NS_SCHEMA_XSD)) { if (isElement) { XmlSchemaElement schemaEle = schemaCollection.getElementByQName(new QName(WSDLConstants.NS_SCHEMA_XSD, name)); partvalid = schemaEle != null ? true : false; } else { if ("anyType".equals(name)) { return true; } XmlSchemaType schemaType = schemaCollection.getTypeByQName(new QName(WSDLConstants.NS_SCHEMA_XSD, name)); partvalid = schemaType != null ? true : false; } } else { if (isElement) { if (schemaCollection.getElementByQName(new QName(namespace, name)) != null) { partvalid = true; } } else { if (schemaCollection.getTypeByQName(new QName(namespace, name)) != null) { partvalid = true; } } } return partvalid; } public String getErrorMessage() { return vResults.toString(); } public Definition getDefinition() { return this.definition; } }
public class RetransmissionQueueImpl implements RetransmissionQueue { private static final Logger LOG = LogUtils.getL7dLogger(RetransmissionQueueImpl.class); private Map<String, List<ResendCandidate>> candidates = new HashMap<String, List<ResendCandidate>>(); private Map<String, List<ResendCandidate>> suspendedCandidates = new HashMap<String, List<ResendCandidate>>(); private Resender resender; private RMManager manager; private int unacknowledgedCount; public RetransmissionQueueImpl(RMManager m) { manager = m; } public RMManager getManager() { return manager; } public void setManager(RMManager m) { manager = m; } public void addUnacknowledged(Message message) { cacheUnacknowledged(message); } /** * @param seq the sequence under consideration * @return the number of unacknowledged messages for that sequence */ public synchronized int countUnacknowledged(SourceSequence seq) { List<ResendCandidate> sequenceCandidates = getSequenceCandidates(seq); return sequenceCandidates == null ? 0 : sequenceCandidates.size(); } public int countUnacknowledged() { return unacknowledgedCount; } /** @return true if there are no unacknowledged messages in the queue */ public boolean isEmpty() { return 0 == getUnacknowledged().size(); } /** * Purge all candidates for the given sequence that have been acknowledged. * * @param seq the sequence object. */ public void purgeAcknowledged(SourceSequence seq) { purgeCandidates(seq, false); } /** * Purge all candidates for the given sequence. This method is used to terminate the sequence by * force and release the resource associated with the sequence. * * @param seq the sequence object. */ public void purgeAll(SourceSequence seq) { purgeCandidates(seq, true); } private void purgeCandidates(SourceSequence seq, boolean any) { Collection<Long> purged = new ArrayList<Long>(); Collection<ResendCandidate> resends = new ArrayList<ResendCandidate>(); Identifier sid = seq.getIdentifier(); synchronized (this) { LOG.fine("Start purging resend candidates."); List<ResendCandidate> sequenceCandidates = getSequenceCandidates(seq); if (null != sequenceCandidates) { for (int i = sequenceCandidates.size() - 1; i >= 0; i--) { ResendCandidate candidate = sequenceCandidates.get(i); long m = candidate.getNumber(); if (any || seq.isAcknowledged(m)) { sequenceCandidates.remove(i); candidate.resolved(); unacknowledgedCount--; purged.add(m); resends.add(candidate); } } if (sequenceCandidates.isEmpty()) { candidates.remove(sid.getValue()); } } LOG.fine("Completed purging resend candidates."); } if (purged.size() > 0) { RMStore store = manager.getStore(); if (null != store) { store.removeMessages(sid, purged, true); } RMEndpoint rmEndpoint = seq.getSource().getReliableEndpoint(); for (ResendCandidate resend : resends) { rmEndpoint.handleAcknowledgment(sid.getValue(), resend.getNumber(), resend.getMessage()); } } } public List<Long> getUnacknowledgedMessageNumbers(SourceSequence seq) { List<Long> unacknowledged = new ArrayList<Long>(); List<ResendCandidate> sequenceCandidates = getSequenceCandidates(seq); if (null != sequenceCandidates) { for (int i = 0; i < sequenceCandidates.size(); i++) { ResendCandidate candidate = sequenceCandidates.get(i); unacknowledged.add(candidate.getNumber()); } } return unacknowledged; } public RetryStatus getRetransmissionStatus(SourceSequence seq, long num) { List<ResendCandidate> sequenceCandidates = getSequenceCandidates(seq); if (null != sequenceCandidates) { for (int i = 0; i < sequenceCandidates.size(); i++) { ResendCandidate candidate = sequenceCandidates.get(i); if (num == candidate.getNumber()) { return candidate; } } } return null; } public Map<Long, RetryStatus> getRetransmissionStatuses(SourceSequence seq) { Map<Long, RetryStatus> cp = new HashMap<Long, RetryStatus>(); List<ResendCandidate> sequenceCandidates = getSequenceCandidates(seq); if (null != sequenceCandidates) { for (int i = 0; i < sequenceCandidates.size(); i++) { ResendCandidate candidate = sequenceCandidates.get(i); cp.put(candidate.getNumber(), candidate); } } return cp; } /** Initiate resends. */ public void start() { if (null != resender) { return; } LOG.fine("Starting retransmission queue"); // setup resender resender = getDefaultResender(); } /** Stops resending messages for the specified source sequence. */ public void stop(SourceSequence seq) { synchronized (this) { List<ResendCandidate> sequenceCandidates = getSequenceCandidates(seq); if (null != sequenceCandidates) { for (int i = sequenceCandidates.size() - 1; i >= 0; i--) { ResendCandidate candidate = sequenceCandidates.get(i); candidate.cancel(); } LOG.log(Level.FINE, "Cancelled resends for sequence {0}.", seq.getIdentifier().getValue()); } } } void stop() {} public void suspend(SourceSequence seq) { synchronized (this) { String key = seq.getIdentifier().getValue(); List<ResendCandidate> sequenceCandidates = candidates.remove(key); if (null != sequenceCandidates) { for (int i = sequenceCandidates.size() - 1; i >= 0; i--) { ResendCandidate candidate = sequenceCandidates.get(i); candidate.suspend(); } suspendedCandidates.put(key, sequenceCandidates); LOG.log(Level.FINE, "Suspended resends for sequence {0}.", key); } } } public void resume(SourceSequence seq) { synchronized (this) { String key = seq.getIdentifier().getValue(); List<ResendCandidate> sequenceCandidates = suspendedCandidates.remove(key); if (null != sequenceCandidates) { for (int i = 0; i < sequenceCandidates.size(); i++) { ResendCandidate candidate = sequenceCandidates.get(i); candidate.resume(); } candidates.put(key, sequenceCandidates); LOG.log(Level.FINE, "Resumed resends for sequence {0}.", key); } } } /** @return the exponential backoff */ protected int getExponentialBackoff() { return DEFAULT_EXPONENTIAL_BACKOFF; } /** * @param message the message context * @return a ResendCandidate */ protected ResendCandidate createResendCandidate(SoapMessage message) { return new ResendCandidate(message); } /** * Accepts a new resend candidate. * * @param ctx the message context. * @return ResendCandidate */ protected ResendCandidate cacheUnacknowledged(Message message) { RMProperties rmps = RMContextUtils.retrieveRMProperties(message, true); SequenceType st = rmps.getSequence(); Identifier sid = st.getIdentifier(); String key = sid.getValue(); ResendCandidate candidate = null; synchronized (this) { List<ResendCandidate> sequenceCandidates = getSequenceCandidates(key); if (null == sequenceCandidates) { sequenceCandidates = new ArrayList<ResendCandidate>(); candidates.put(key, sequenceCandidates); } candidate = new ResendCandidate(message); if (isSequenceSuspended(key)) { candidate.suspend(); } sequenceCandidates.add(candidate); unacknowledgedCount++; } LOG.fine("Cached unacknowledged message."); try { RMEndpoint rme = manager.getReliableEndpoint(message); rme.handleAccept(key, st.getMessageNumber(), message); } catch (RMException e) { LOG.log(Level.WARNING, "Could not find reliable endpoint for message"); } return candidate; } /** @return a map relating sequence ID to a lists of un-acknowledged messages for that sequence */ protected Map<String, List<ResendCandidate>> getUnacknowledged() { return candidates; } /** * @param seq the sequence under consideration * @return the list of resend candidates for that sequence * @pre called with mutex held */ protected List<ResendCandidate> getSequenceCandidates(SourceSequence seq) { return getSequenceCandidates(seq.getIdentifier().getValue()); } /** * @param key the sequence identifier under consideration * @return the list of resend candidates for that sequence * @pre called with mutex held */ protected List<ResendCandidate> getSequenceCandidates(String key) { List<ResendCandidate> sc = candidates.get(key); if (null == sc) { sc = suspendedCandidates.get(key); } return sc; } /** * @param key the sequence identifier under consideration * @return true if the sequence is currently suspended; false otherwise * @pre called with mutex held */ protected boolean isSequenceSuspended(String key) { return suspendedCandidates.containsKey(key); } /** Represents a candidate for resend, i.e. an unacked outgoing message. */ protected class ResendCandidate implements Runnable, RetryStatus { private Message message; private long number; private Date next; private TimerTask nextTask; private int retries; private int maxRetries; private long nextInterval; private long backoff; private boolean pending; private boolean suspended; private boolean includeAckRequested; /** @param ctx message context for the unacked message */ protected ResendCandidate(Message m) { message = m; retries = 0; RMConfiguration cfg = manager.getEffectiveConfiguration(message); long baseRetransmissionInterval = cfg.getBaseRetransmissionInterval().longValue(); backoff = cfg.isExponentialBackoff() ? RetransmissionQueue.DEFAULT_EXPONENTIAL_BACKOFF : 1; next = new Date(System.currentTimeMillis() + baseRetransmissionInterval); nextInterval = baseRetransmissionInterval * backoff; RetryPolicyType rmrp = null != manager.getSourcePolicy() ? manager.getSourcePolicy().getRetryPolicy() : null; maxRetries = null != rmrp ? rmrp.getMaxRetries() : -1; AddressingProperties maps = RMContextUtils.retrieveMAPs(message, false, true); AttributedURIType to = null; if (null != maps) { to = maps.getTo(); } if (to != null && RMUtils.getAddressingConstants().getAnonymousURI().equals(to.getValue())) { LOG.log(Level.INFO, "Cannot resend to anonymous target. Not scheduling a resend."); return; } RMProperties rmprops = RMContextUtils.retrieveRMProperties(message, true); if (null != rmprops) { number = rmprops.getSequence().getMessageNumber(); } if (null != manager.getTimer() && maxRetries != 0) { schedule(); } } /** * Initiate resend asynchronsly. * * @param requestAcknowledge true if a AckRequest header is to be sent with resend */ protected void initiate(boolean requestAcknowledge) { includeAckRequested = requestAcknowledge; pending = true; Endpoint ep = message.getExchange().get(Endpoint.class); Executor executor = ep.getExecutor(); if (null == executor) { executor = ep.getService().getExecutor(); if (executor == null) { executor = SynchronousExecutor.getInstance(); } else { LOG.log(Level.FINE, "Using service executor {0}", executor.getClass().getName()); } } else { LOG.log(Level.FINE, "Using endpoint executor {0}", executor.getClass().getName()); } try { executor.execute(this); } catch (RejectedExecutionException ex) { LOG.log(Level.SEVERE, "RESEND_INITIATION_FAILED_MSG", ex); } } public void run() { try { // ensure ACK wasn't received while this task was enqueued // on executor if (isPending()) { resender.resend(message, includeAckRequested); includeAckRequested = false; } } finally { attempted(); } } public long getNumber() { return number; } /** @return number of resend attempts */ public int getRetries() { return retries; } /** @return number of max resend attempts */ public int getMaxRetries() { return maxRetries; } /** @return date of next resend */ public Date getNext() { return next; } /** @return date of previous resend or null if no attempt is yet taken */ public Date getPrevious() { if (retries > 0) { return new Date(next.getTime() - nextInterval / backoff); } return null; } public long getNextInterval() { return nextInterval; } public long getBackoff() { return backoff; } public boolean isSuspended() { return suspended; } /** @return if resend attempt is pending */ public synchronized boolean isPending() { return pending; } /** ACK has been received for this candidate. */ protected synchronized void resolved() { pending = false; next = null; if (null != nextTask) { nextTask.cancel(); releaseSavedMessage(); } } /** Cancel further resend (although no ACK has been received). */ protected synchronized void cancel() { if (null != nextTask) { nextTask.cancel(); releaseSavedMessage(); } } protected synchronized void suspend() { suspended = true; pending = false; // TODO release the message and later reload it upon resume // cancel(); if (null != nextTask) { nextTask.cancel(); } } protected synchronized void resume() { suspended = false; next = new Date(System.currentTimeMillis()); attempted(); } private void releaseSavedMessage() { RewindableInputStream is = (RewindableInputStream) message.get(RMMessageConstants.SAVED_CONTENT); if (is != null) { is.release(); } } /** @return associated message context */ protected Message getMessage() { return message; } /** A resend has been attempted. Schedule the next attempt. */ protected synchronized void attempted() { pending = false; retries++; if (null != next && maxRetries != retries) { next = new Date(next.getTime() + nextInterval); nextInterval *= backoff; schedule(); } } protected final synchronized void schedule() { if (null == manager.getTimer()) { return; } class ResendTask extends TimerTask { ResendCandidate candidate; ResendTask(ResendCandidate c) { candidate = c; } @Override public void run() { if (!candidate.isPending()) { candidate.initiate(includeAckRequested); } } } nextTask = new ResendTask(this); try { manager.getTimer().schedule(nextTask, next); } catch (IllegalStateException ex) { LOG.log(Level.WARNING, "SCHEDULE_RESEND_FAILED_MSG", ex); } } } /** Encapsulates actual resend logic (pluggable to facilitate unit testing) */ public interface Resender { /** * Resend mechanics. * * @param message * @param if a AckRequest should be included */ void resend(Message message, boolean requestAcknowledge); } /** * Create default Resender logic. * * @return default Resender */ protected final Resender getDefaultResender() { return new Resender() { public void resend(Message message, boolean requestAcknowledge) { RMProperties properties = RMContextUtils.retrieveRMProperties(message, true); SequenceType st = properties.getSequence(); if (st != null) { LOG.log(Level.INFO, "RESEND_MSG", st.getMessageNumber()); } if (message instanceof SoapMessage) { doResend((SoapMessage) message); } else { doResend(new SoapMessage(message)); } } }; } /** * Plug in replacement resend logic (facilitates unit testing). * * @param replacement resend logic */ protected void replaceResender(Resender replacement) { resender = replacement; } @SuppressWarnings("unchecked") protected JaxbAssertion<RMAssertion> getAssertion(AssertionInfo ai) { return (JaxbAssertion<RMAssertion>) ai.getAssertion(); } private void readHeaders(XMLStreamReader xmlReader, SoapMessage message) throws XMLStreamException { // read header portion of SOAP document into DOM SoapVersion version = message.getVersion(); XMLStreamReader filteredReader = new PartialXMLStreamReader(xmlReader, version.getBody()); Node nd = message.getContent(Node.class); W3CDOMStreamWriter writer = message.get(W3CDOMStreamWriter.class); Document doc = null; if (writer != null) { StaxUtils.copy(filteredReader, writer); doc = writer.getDocument(); } else if (nd instanceof Document) { doc = (Document) nd; StaxUtils.readDocElements(doc, doc, filteredReader, false, false); } else { doc = StaxUtils.read(filteredReader); message.setContent(Node.class, doc); } // get the actual SOAP header Element element = doc.getDocumentElement(); QName header = version.getHeader(); List<Element> elemList = DOMUtils.findAllElementsByTagNameNS( element, header.getNamespaceURI(), header.getLocalPart()); for (Element elem : elemList) { // set all child elements as headers for message transmission Element hel = DOMUtils.getFirstElement(elem); while (hel != null) { SoapHeader sheader = new SoapHeader(DOMUtils.getElementQName(hel), hel); message.getHeaders().add(sheader); hel = DOMUtils.getNextElement(hel); } } } private void doResend(SoapMessage message) { try { // initialize copied interceptor chain for message PhaseInterceptorChain retransmitChain = manager.getRetransmitChain(message); ProtocolVariation protocol = RMContextUtils.getProtocolVariation(message); Endpoint endpoint = manager.getReliableEndpoint(message).getEndpoint(protocol); PhaseChainCache cache = new PhaseChainCache(); boolean after = true; if (retransmitChain == null) { // no saved retransmit chain, so construct one from scratch (won't work for WS-Security on // server, so // need to fix) retransmitChain = buildRetransmitChain(endpoint, cache); after = false; } message.setInterceptorChain(retransmitChain); // clear flag for SOAP out interceptor so envelope will be written message.remove(SoapOutInterceptor.WROTE_ENVELOPE_START); // discard all saved content Set<Class<?>> formats = message.getContentFormats(); List<CachedOutputStreamCallback> callbacks = null; for (Class<?> clas : formats) { Object content = message.getContent(clas); if (content != null) { LOG.info( "Removing " + clas.getName() + " content of actual type " + content.getClass().getName()); message.removeContent(clas); if (clas == OutputStream.class && content instanceof WriteOnCloseOutputStream) { callbacks = ((WriteOnCloseOutputStream) content).getCallbacks(); } } } // read SOAP headers from saved input stream RewindableInputStream is = (RewindableInputStream) message.get(RMMessageConstants.SAVED_CONTENT); is.rewind(); XMLStreamReader reader = StaxUtils.createXMLStreamReader(is, "UTF-8"); message.getHeaders().clear(); if (reader.getEventType() != XMLStreamConstants.START_ELEMENT && reader.nextTag() != XMLStreamConstants.START_ELEMENT) { throw new IllegalStateException("No document found"); } readHeaders(reader, message); int event; while ((event = reader.nextTag()) != XMLStreamConstants.START_ELEMENT) { if (event == XMLStreamConstants.END_ELEMENT) { throw new IllegalStateException("No body content present"); } } // set message addressing properties AddressingProperties maps = new MAPCodec().unmarshalMAPs(message); RMContextUtils.storeMAPs(maps, message, true, MessageUtils.isRequestor(message)); AttributedURIType to = null; if (null != maps) { to = maps.getTo(); } if (null == to) { LOG.log(Level.SEVERE, "NO_ADDRESS_FOR_RESEND_MSG"); return; } if (RMUtils.getAddressingConstants().getAnonymousURI().equals(to.getValue())) { LOG.log(Level.FINE, "Cannot resend to anonymous target"); return; } // initialize conduit for new message Conduit c = message.getExchange().getConduit(message); if (c == null) { c = buildConduit(message, endpoint, to); } c.prepare(message); // replace standard message marshaling with copy from saved stream ListIterator<Interceptor<? extends Message>> iterator = retransmitChain.getIterator(); while (iterator.hasNext()) { Interceptor<? extends Message> incept = iterator.next(); // remove JAX-WS interceptors which handle message modes and such if (incept.getClass().getName().startsWith("org.apache.cxf.jaxws.interceptors")) { retransmitChain.remove(incept); } else if (incept instanceof PhaseInterceptor && (((PhaseInterceptor<?>) incept).getPhase() == Phase.MARSHAL)) { // remove any interceptors from the marshal phase retransmitChain.remove(incept); } } retransmitChain.add(new CopyOutInterceptor(reader)); // restore callbacks on output stream if (callbacks != null) { OutputStream os = message.getContent(OutputStream.class); if (os != null) { WriteOnCloseOutputStream woc; if (os instanceof WriteOnCloseOutputStream) { woc = (WriteOnCloseOutputStream) os; } else { woc = new WriteOnCloseOutputStream(os); message.setContent(OutputStream.class, woc); } for (CachedOutputStreamCallback cb : callbacks) { woc.registerCallback(cb); } } } // send the message message.put(RMMessageConstants.RM_RETRANSMISSION, Boolean.TRUE); if (after) { retransmitChain.doInterceptStartingAfter(message, RMCaptureOutInterceptor.class.getName()); } else { retransmitChain.doIntercept(message); } if (LOG.isLoggable(Level.INFO)) { RMProperties rmps = RMContextUtils.retrieveRMProperties(message, true); SequenceType seq = rmps.getSequence(); LOG.log( Level.INFO, "Retransmitted message " + seq.getMessageNumber() + " in sequence " + seq.getIdentifier().getValue()); rmps = new RMProperties(); } } catch (Exception ex) { LOG.log(Level.SEVERE, "RESEND_FAILED_MSG", ex); } } /** * @param message * @param endpoint * @param to * @return */ protected Conduit buildConduit( SoapMessage message, final Endpoint endpoint, AttributedURIType to) { Conduit c; final String address = to.getValue(); ConduitSelector cs = new DeferredConduitSelector() { @Override public synchronized Conduit selectConduit(Message message) { Conduit conduit = null; EndpointInfo endpointInfo = endpoint.getEndpointInfo(); EndpointReferenceType original = endpointInfo.getTarget(); try { if (null != address) { endpointInfo.setAddress(address); } conduit = super.selectConduit(message); } finally { endpointInfo.setAddress(original); } return conduit; } }; cs.setEndpoint(endpoint); c = cs.selectConduit(message); // REVISIT // use application endpoint message observer instead? c.setMessageObserver( new MessageObserver() { public void onMessage(Message message) { LOG.fine("Ignoring response to resent message."); } }); message.getExchange().setConduit(c); return c; } /** * @param endpoint * @param cache * @return */ protected PhaseInterceptorChain buildRetransmitChain( final Endpoint endpoint, PhaseChainCache cache) { PhaseInterceptorChain retransmitChain; Bus bus = getManager().getBus(); List<Interceptor<? extends Message>> i1 = bus.getOutInterceptors(); if (LOG.isLoggable(Level.FINE)) { LOG.fine("Interceptors contributed by bus: " + i1); } List<Interceptor<? extends Message>> i2 = endpoint.getOutInterceptors(); if (LOG.isLoggable(Level.FINE)) { LOG.fine("Interceptors contributed by endpoint: " + i2); } List<Interceptor<? extends Message>> i3 = endpoint.getBinding().getOutInterceptors(); if (LOG.isLoggable(Level.FINE)) { LOG.fine("Interceptors contributed by binding: " + i3); } PhaseManager pm = bus.getExtension(PhaseManager.class); retransmitChain = cache.get(pm.getOutPhases(), i1, i2, i3); return retransmitChain; } public static class CopyOutInterceptor extends AbstractOutDatabindingInterceptor { private final XMLStreamReader reader; public CopyOutInterceptor(XMLStreamReader rdr) { super(Phase.MARSHAL); reader = rdr; } @Override public void handleMessage(Message message) throws Fault { try { XMLStreamWriter writer = message.getContent(XMLStreamWriter.class); StaxUtils.copy(reader, writer); } catch (XMLStreamException e) { throw new Fault("COULD_NOT_READ_XML_STREAM", LOG, e); } } } }
public class ServerPolicyOutFaultInterceptor extends AbstractPolicyInterceptor { public static final ServerPolicyOutFaultInterceptor INSTANCE = new ServerPolicyOutFaultInterceptor(); private static final Logger LOG = LogUtils.getL7dLogger(ServerPolicyOutFaultInterceptor.class); public ServerPolicyOutFaultInterceptor() { super(PolicyConstants.SERVER_POLICY_OUT_FAULT_INTERCEPTOR_ID, Phase.SETUP); } protected void handle(Message msg) { if (MessageUtils.isRequestor(msg)) { LOG.fine("Is a requestor."); return; } Exchange exchange = msg.getExchange(); assert null != exchange; BindingOperationInfo boi = exchange.get(BindingOperationInfo.class); if (null == boi) { LOG.fine("No binding operation info."); return; } Endpoint e = exchange.get(Endpoint.class); if (null == e) { LOG.fine("No endpoint."); return; } EndpointInfo ei = e.getEndpointInfo(); Bus bus = exchange.get(Bus.class); PolicyEngine pe = bus.getExtension(PolicyEngine.class); if (null == pe) { return; } Destination destination = exchange.getDestination(); Exception ex = exchange.get(Exception.class); List<Interceptor<? extends Message>> faultInterceptors = new ArrayList<Interceptor<? extends Message>>(); Collection<Assertion> assertions = new ArrayList<Assertion>(); // 1. Check overridden policy Policy p = (Policy) msg.getContextualProperty(PolicyConstants.POLICY_OVERRIDE); if (p != null) { EndpointPolicyImpl endpi = new EndpointPolicyImpl(p); EffectivePolicyImpl effectivePolicy = new EffectivePolicyImpl(); effectivePolicy.initialise(endpi, (PolicyEngineImpl) pe, false, true); PolicyUtils.logPolicy( LOG, Level.FINEST, "Using effective policy: ", effectivePolicy.getPolicy()); faultInterceptors.addAll(effectivePolicy.getInterceptors()); assertions.addAll(effectivePolicy.getChosenAlternative()); } else { // 2. Process effective server policy BindingFaultInfo bfi = getBindingFaultInfo(msg, ex, boi); if (bfi == null && msg.get(FaultMode.class) != FaultMode.UNCHECKED_APPLICATION_FAULT && msg.get(FaultMode.class) != FaultMode.CHECKED_APPLICATION_FAULT) { return; } EffectivePolicy effectivePolicy = pe.getEffectiveServerFaultPolicy(ei, boi, bfi, destination); if (effectivePolicy != null) { faultInterceptors.addAll(effectivePolicy.getInterceptors()); assertions.addAll(effectivePolicy.getChosenAlternative()); } } // add interceptors into message chain for (Interceptor<? extends Message> oi : faultInterceptors) { msg.getInterceptorChain().add(oi); LOG.log(Level.FINE, "Added interceptor of type {0}", oi.getClass().getSimpleName()); } // insert assertions of the chosen alternative into the message if (null != assertions && !assertions.isEmpty()) { msg.put(AssertionInfoMap.class, new AssertionInfoMap(assertions)); } } }
public class HttpAwareXSLTOutInterceptor extends AbstractHttpAwareXSLTInterceptor { private static final Logger LOG = LogUtils.getL7dLogger(XSLTOutInterceptor.class); public HttpAwareXSLTOutInterceptor(String xsltPath) { super(Phase.PRE_STREAM, StaxOutInterceptor.class, null, xsltPath); } public HttpAwareXSLTOutInterceptor( String phase, Class<?> before, Class<?> after, String xsltPath) { super(phase, before, after, xsltPath); } @Override public void handleMessage(Message message) { if (!shouldSchemaValidate(message)) { return; } if (checkContextProperty(message)) { return; } // 1. Try to get and transform XMLStreamWriter message content XMLStreamWriter xWriter = message.getContent(XMLStreamWriter.class); if (xWriter != null) { transformXWriter(message, xWriter); } else { // 2. Try to get and transform OutputStream message content OutputStream out = message.getContent(OutputStream.class); if (out != null) { transformOS(message, out); } else { // 3. Try to get and transform Writer message content (actually used for JMS TextMessage) Writer writer = message.getContent(Writer.class); if (writer != null) { transformWriter(message, writer); } } } } protected void transformXWriter(Message message, XMLStreamWriter xWriter) { CachedWriter writer = new CachedWriter(); XMLStreamWriter delegate = StaxUtils.createXMLStreamWriter(writer); XSLTStreamWriter wrapper = new XSLTStreamWriter(getXSLTTemplate(), writer, delegate, xWriter); message.setContent(XMLStreamWriter.class, wrapper); message.put(AbstractOutDatabindingInterceptor.DISABLE_OUTPUTSTREAM_OPTIMIZATION, Boolean.TRUE); } protected void transformOS(Message message, OutputStream out) { CachedOutputStream wrapper = new CachedOutputStream(); CachedOutputStreamCallback callback = new XSLTCachedOutputStreamCallback(getXSLTTemplate(), out); wrapper.registerCallback(callback); message.setContent(OutputStream.class, wrapper); } protected void transformWriter(Message message, Writer writer) { XSLTCachedWriter wrapper = new XSLTCachedWriter(getXSLTTemplate(), writer); message.setContent(Writer.class, wrapper); } public static class XSLTStreamWriter extends DelegatingXMLStreamWriter { private final Templates xsltTemplate; private final CachedWriter cachedWriter; private final XMLStreamWriter origXWriter; public XSLTStreamWriter( Templates xsltTemplate, CachedWriter cachedWriter, XMLStreamWriter delegateXWriter, XMLStreamWriter origXWriter) { super(delegateXWriter); this.xsltTemplate = xsltTemplate; this.cachedWriter = cachedWriter; this.origXWriter = origXWriter; } @Override public void close() { Reader transformedReader = null; try { super.flush(); transformedReader = XSLTUtils.transform(xsltTemplate, cachedWriter.getReader()); StaxUtils.copy(new StreamSource(transformedReader), origXWriter); } catch (XMLStreamException e) { throw new Fault("STAX_COPY", LOG, e, e.getMessage()); } catch (IOException e) { throw new Fault("GET_CACHED_INPUT_STREAM", LOG, e, e.getMessage()); } finally { try { if (transformedReader != null) { transformedReader.close(); } cachedWriter.close(); StaxUtils.close(origXWriter); super.close(); } catch (Exception e) { LOG.warning("Cannot close stream after transformation: " + e.getMessage()); } } } } public static class XSLTCachedOutputStreamCallback implements CachedOutputStreamCallback { private final Templates xsltTemplate; private final OutputStream origStream; public XSLTCachedOutputStreamCallback(Templates xsltTemplate, OutputStream origStream) { this.xsltTemplate = xsltTemplate; this.origStream = origStream; } @Override public void onFlush(CachedOutputStream wrapper) {} @Override public void onClose(CachedOutputStream wrapper) { InputStream transformedStream = null; try { transformedStream = XSLTUtils.transform(xsltTemplate, wrapper.getInputStream()); IOUtils.copyAndCloseInput(transformedStream, origStream); } catch (IOException e) { throw new Fault("STREAM_COPY", LOG, e, e.getMessage()); } finally { try { origStream.close(); } catch (IOException e) { LOG.warning("Cannot close stream after transformation: " + e.getMessage()); } } } } public static class XSLTCachedWriter extends CachedWriter { private final Templates xsltTemplate; private final Writer origWriter; public XSLTCachedWriter(Templates xsltTemplate, Writer origWriter) { this.xsltTemplate = xsltTemplate; this.origWriter = origWriter; } @Override protected void doClose() { Reader transformedReader = null; try { transformedReader = XSLTUtils.transform(xsltTemplate, getReader()); IOUtils.copyAndCloseInput(transformedReader, origWriter, IOUtils.DEFAULT_BUFFER_SIZE); } catch (IOException e) { throw new Fault("READER_COPY", LOG, e, e.getMessage()); } finally { try { origWriter.close(); } catch (IOException e) { LOG.warning("Cannot close stream after transformation: " + e.getMessage()); } } } } }
public class NMRWrapperInInterceptor extends AbstractInDatabindingInterceptor { private static final Logger LOG = LogUtils.getL7dLogger(NMRWrapperInInterceptor.class); private static final ResourceBundle BUNDLE = LOG.getResourceBundle(); public NMRWrapperInInterceptor() { super(Phase.UNMARSHAL); } public void handleMessage(Message message) throws Fault { if (isGET(message)) { LOG.info("JbiMessageInInterceptor skipped in HTTP GET method"); return; } XMLStreamReader xsr = message.getContent(XMLStreamReader.class); DepthXMLStreamReader reader = new DepthXMLStreamReader(xsr); Endpoint ep = message.getExchange().get(Endpoint.class); BindingInfo binding = ep.getEndpointInfo().getBinding(); if (!(binding instanceof NMRBindingInfo)) { throw new IllegalStateException( new org.apache.cxf.common.i18n.Message("NEED_JBIBINDING", BUNDLE).toString()); } if (!StaxUtils.toNextElement(reader)) { throw new Fault(new org.apache.cxf.common.i18n.Message("NO_OPERATION_ELEMENT", BUNDLE)); } Exchange ex = message.getExchange(); QName startQName = reader.getName(); // handling jbi fault message if (startQName.getLocalPart().equals(NMRFault.NMR_FAULT_ROOT)) { message.getInterceptorChain().abort(); if (ep.getInFaultObserver() != null) { ep.getInFaultObserver().onMessage(message); return; } } // handling xml normal inbound message if (!startQName.equals(NMRConstants.JBI_WRAPPER_MESSAGE)) { throw new Fault(new org.apache.cxf.common.i18n.Message("NO_JBI_MESSAGE_ELEMENT", BUNDLE)); } try { BindingOperationInfo bop = ex.get(BindingOperationInfo.class); DataReader<XMLStreamReader> dr = getDataReader(message); List<Object> parameters = new ArrayList<Object>(); reader.next(); BindingMessageInfo messageInfo = !isRequestor(message) ? bop.getInput() : bop.getOutput(); message.put(MessageInfo.class, messageInfo.getMessageInfo()); for (MessagePartInfo part : messageInfo.getMessageParts()) { if (!StaxUtils.skipToStartOfElement(reader)) { throw new Fault(new org.apache.cxf.common.i18n.Message("NOT_ENOUGH_PARTS", BUNDLE)); } startQName = reader.getName(); if (!startQName.equals(NMRConstants.JBI_WRAPPER_PART)) { throw new Fault(new org.apache.cxf.common.i18n.Message("NO_JBI_PART_ELEMENT", BUNDLE)); } if (part.isElement()) { reader.next(); if (!StaxUtils.toNextElement(reader)) { throw new Fault( new org.apache.cxf.common.i18n.Message("EXPECTED_ELEMENT_IN_PART", BUNDLE)); } } parameters.add(dr.read(part, reader)); // skip end element if (part.isElement()) { reader.next(); } } int ev = reader.getEventType(); while (ev != XMLStreamConstants.END_ELEMENT && ev != XMLStreamConstants.START_ELEMENT && ev != XMLStreamConstants.END_DOCUMENT) { ev = reader.next(); } message.setContent(List.class, parameters); } catch (XMLStreamException e) { throw new Fault(new org.apache.cxf.common.i18n.Message("STAX_READ_EXC", BUNDLE), e); } } }
/** Some abstract functionality for creating a SAML token */ public abstract class AbstractSAMLTokenProvider { private static final Logger LOG = LogUtils.getL7dLogger(AbstractSAMLTokenProvider.class); protected void signToken( SamlAssertionWrapper assertion, RealmProperties samlRealm, STSPropertiesMBean stsProperties, KeyRequirements keyRequirements) throws Exception { // Initialise signature objects with defaults of STSPropertiesMBean Crypto signatureCrypto = stsProperties.getSignatureCrypto(); CallbackHandler callbackHandler = stsProperties.getCallbackHandler(); SignatureProperties signatureProperties = stsProperties.getSignatureProperties(); String alias = stsProperties.getSignatureUsername(); if (samlRealm != null) { // If SignatureCrypto configured in realm then // callbackhandler and alias of STSPropertiesMBean is ignored if (samlRealm.getSignatureCrypto() != null) { LOG.fine("SAMLRealm signature keystore used"); signatureCrypto = samlRealm.getSignatureCrypto(); callbackHandler = samlRealm.getCallbackHandler(); alias = samlRealm.getSignatureAlias(); } // SignatureProperties can be defined independently of SignatureCrypto if (samlRealm.getSignatureProperties() != null) { signatureProperties = samlRealm.getSignatureProperties(); } } // Get the signature algorithm to use String signatureAlgorithm = keyRequirements.getSignatureAlgorithm(); if (signatureAlgorithm == null) { // If none then default to what is configured signatureAlgorithm = signatureProperties.getSignatureAlgorithm(); } else { List<String> supportedAlgorithms = signatureProperties.getAcceptedSignatureAlgorithms(); if (!supportedAlgorithms.contains(signatureAlgorithm)) { signatureAlgorithm = signatureProperties.getSignatureAlgorithm(); if (LOG.isLoggable(Level.FINE)) { LOG.fine("SignatureAlgorithm not supported, defaulting to: " + signatureAlgorithm); } } } // Get the c14n algorithm to use String c14nAlgorithm = keyRequirements.getC14nAlgorithm(); if (c14nAlgorithm == null) { // If none then default to what is configured c14nAlgorithm = signatureProperties.getC14nAlgorithm(); } else { List<String> supportedAlgorithms = signatureProperties.getAcceptedC14nAlgorithms(); if (!supportedAlgorithms.contains(c14nAlgorithm)) { c14nAlgorithm = signatureProperties.getC14nAlgorithm(); if (LOG.isLoggable(Level.FINE)) { LOG.fine("C14nAlgorithm not supported, defaulting to: " + c14nAlgorithm); } } } // If alias not defined, get the default of the SignatureCrypto if ((alias == null || "".equals(alias)) && (signatureCrypto != null)) { alias = signatureCrypto.getDefaultX509Identifier(); if (LOG.isLoggable(Level.FINE)) { LOG.fine("Signature alias is null so using default alias: " + alias); } } // Get the password WSPasswordCallback[] cb = {new WSPasswordCallback(alias, WSPasswordCallback.SIGNATURE)}; LOG.fine("Creating SAML Token"); callbackHandler.handle(cb); String password = cb[0].getPassword(); LOG.fine("Signing SAML Token"); boolean useKeyValue = signatureProperties.isUseKeyValue(); assertion.signAssertion( alias, password, signatureCrypto, useKeyValue, c14nAlgorithm, signatureAlgorithm, signatureProperties.getDigestAlgorithm()); } }
/** Some functions that avoid problems with Commons XML Schema. */ public final class XmlSchemaUtils { public static final String XSI_NIL = "xsi:nil='true'"; private static final Logger LOG = LogUtils.getL7dLogger(XmlSchemaUtils.class); private XmlSchemaUtils() {} /** * Wrapper around XmlSchemaElement.setRefName that checks for inconsistency with name and QName. * * @param element * @param name */ public static void setElementRefName(XmlSchemaElement element, QName name) { if (name != null && ((element.getQName() != null && !element.getQName().equals(name)) || (element.getName() != null && !element.getName().equals(name.getLocalPart())))) { LOG.severe("Attempt to set the refName of an element with a name or QName"); throw new XmlSchemaInvalidOperation( "Attempt to set the refName of an element " + "with a name or QName."); } element.getRef().setTargetQName(name); // cxf conventionally keeps something in the name slot. } /** * Return true if a simple type is a straightforward XML Schema representation of an enumeration. * If we discover schemas that are 'enum-like' with more complex structures, we might make this * deal with them. * * @param type Simple type, possible an enumeration. * @return true for an enumeration. */ public static boolean isEumeration(XmlSchemaSimpleType type) { XmlSchemaSimpleTypeContent content = type.getContent(); if (!(content instanceof XmlSchemaSimpleTypeRestriction)) { return false; } XmlSchemaSimpleTypeRestriction restriction = (XmlSchemaSimpleTypeRestriction) content; List<XmlSchemaFacet> facets = restriction.getFacets(); for (XmlSchemaFacet facet : facets) { if (!(facet instanceof XmlSchemaEnumerationFacet)) { return false; } } return true; } /** * Retrieve the string values for an enumeration. * * @param type */ public static List<String> enumeratorValues(XmlSchemaSimpleType type) { XmlSchemaSimpleTypeContent content = type.getContent(); XmlSchemaSimpleTypeRestriction restriction = (XmlSchemaSimpleTypeRestriction) content; List<XmlSchemaFacet> facets = restriction.getFacets(); List<String> values = new ArrayList<String>(); for (XmlSchemaFacet facet : facets) { XmlSchemaEnumerationFacet enumFacet = (XmlSchemaEnumerationFacet) facet; values.add(enumFacet.getValue().toString()); } return values; } /** * Is there an import for a particular namespace in a schema? * * @param schema * @param namespaceUri */ public static boolean schemaImportsNamespace(XmlSchema schema, String namespaceUri) { List<XmlSchemaExternal> externals = schema.getExternals(); for (XmlSchemaExternal what : externals) { if (what instanceof XmlSchemaImport) { XmlSchemaImport imp = (XmlSchemaImport) what; // already there. if (namespaceUri.equals(imp.getNamespace())) { return true; } } } return false; } /** * Assist in managing the required <import namespace='uri'> for imports of peer schemas. * * @param schema * @param namespaceUri */ public static void addImportIfNeeded(XmlSchema schema, String namespaceUri) { // no need to import nothing or the XSD schema, or the schema we are fixing. if ("".equals(namespaceUri) || Constants.URI_2001_SCHEMA_XSD.equals(namespaceUri) || schema.getTargetNamespace().equals(namespaceUri)) { return; } List<XmlSchemaExternal> externals = schema.getExternals(); for (XmlSchemaExternal what : externals) { if (what instanceof XmlSchemaImport) { XmlSchemaImport imp = (XmlSchemaImport) what; // already there. if (namespaceUri.equals(imp.getNamespace())) { return; } } } XmlSchemaImport imp = new XmlSchemaImport(schema); imp.setNamespace(namespaceUri); } /** * For convenience, start from a qname, and add the import if it is non-null and has a namespace. * * @see #addImportIfNeeded(XmlSchema, String) * @param schema * @param qname */ public static void addImportIfNeeded(XmlSchema schema, QName qname) { if (qname == null) { return; } if (qname.getNamespaceURI() == null) { return; } addImportIfNeeded(schema, qname.getNamespaceURI()); } /** * This copes with an observed phenomenon in the schema built by the ReflectionServiceFactoryBean. * It is creating element such that: (a) the type is not set. (b) the refName is set. (c) the * namespaceURI in the refName is set empty. This apparently indicates 'same Schema' to everyone * else, so thus function implements that convention here. It is unclear if that is a correct * structure, and it if changes, we can simplify or eliminate this function. * * @param name * @param referencingURI */ public static XmlSchemaElement findElementByRefName( SchemaCollection xmlSchemaCollection, QName name, String referencingURI) { String uri = name.getNamespaceURI(); if ("".equals(uri)) { uri = referencingURI; } QName copyName = new QName(uri, name.getLocalPart()); XmlSchemaElement target = xmlSchemaCollection.getElementByQName(copyName); assert target != null; return target; } public static QName getBaseType(XmlSchemaComplexType type) { XmlSchemaContentModel model = type.getContentModel(); if (model == null) { return null; } XmlSchemaContent content = model.getContent(); if (content == null) { return null; } if (!(content instanceof XmlSchemaComplexContentExtension)) { return null; } XmlSchemaComplexContentExtension ext = (XmlSchemaComplexContentExtension) content; return ext.getBaseTypeName(); } public static List<XmlSchemaAttributeOrGroupRef> getContentAttributes(XmlSchemaComplexType type) { XmlSchemaContentModel model = type.getContentModel(); if (model == null) { return null; } XmlSchemaContent content = model.getContent(); if (content == null) { return null; } if (!(content instanceof XmlSchemaComplexContentExtension)) { return null; } // TODO: the anyAttribute case. XmlSchemaComplexContentExtension ext = (XmlSchemaComplexContentExtension) content; return ext.getAttributes(); } public static List<XmlSchemaAnnotated> getContentAttributes( XmlSchemaComplexType type, SchemaCollection collection) { List<XmlSchemaAnnotated> results = new ArrayList<XmlSchemaAnnotated>(); QName baseTypeName = getBaseType(type); if (baseTypeName != null) { XmlSchemaComplexType baseType = (XmlSchemaComplexType) collection.getTypeByQName(baseTypeName); // recurse onto the base type ... results.addAll(getContentAttributes(baseType, collection)); // and now process our sequence. List<XmlSchemaAttributeOrGroupRef> extAttrs = getContentAttributes(type); results.addAll(extAttrs); return results; } else { // no base type, the simple case. List<XmlSchemaAttributeOrGroupRef> attrs = type.getAttributes(); results.addAll(attrs); return results; } } /** * By convention, an element that is named in its schema's TNS can have a 'name' but no QName. * This can get inconvenient for consumers who want to think about qualified names. Unfortunately, * XmlSchema elements, unlike types, don't store a reference to their containing schema. * * @param element * @param schema */ public static QName getElementQualifiedName(XmlSchemaElement element, XmlSchema schema) { if (element.getQName() != null) { return element.getQName(); } else if (element.getName() != null) { return new QName(schema.getTargetNamespace(), element.getName()); } else { return null; } } public static boolean isAttributeNameQualified(XmlSchemaAttribute attribute, XmlSchema schema) { if (attribute.isRef()) { throw new RuntimeException("isElementNameQualified on element with ref="); } if (attribute.getForm().equals(XmlSchemaForm.QUALIFIED)) { return true; } if (attribute.getForm().equals(XmlSchemaForm.UNQUALIFIED)) { return false; } return schema.getAttributeFormDefault().equals(XmlSchemaForm.QUALIFIED); } /** * due to a bug, feature, or just plain oddity of JAXB, it isn't good enough to just check the * form of an element and of its schema. If schema 'a' (default unqualified) has a complex type * with an element with a ref= to schema (b) (default unqualified), JAXB seems to expect to see a * qualifier, anyway. <br> * So, if the element is local to a complex type, all we care about is the default element form of * the schema and the local form of the element. <br> * If, on the other hand, the element is global, we might need to compare namespaces. <br> * * @param attribute the attribute * @param global if this element is a global element (complex type ref= to it, or in a part) * @param localSchema the schema of the complex type containing the reference, only used for the * 'odd case'. * @param attributeSchema the schema for the element. * @return if the element needs to be qualified. */ public static boolean isAttributeQualified( XmlSchemaAttribute attribute, boolean global, XmlSchema localSchema, XmlSchema attributeSchema) { if (attribute.getQName() == null) { throw new RuntimeException("getSchemaQualifier on anonymous element."); } if (attribute.isRef()) { throw new RuntimeException("getSchemaQualified on the 'from' side of ref=."); } if (global) { return isAttributeNameQualified(attribute, attributeSchema) || (localSchema != null && !(attribute .getQName() .getNamespaceURI() .equals(localSchema.getTargetNamespace()))); } else { return isAttributeNameQualified(attribute, attributeSchema); } } public static boolean isElementNameQualified(XmlSchemaElement element, XmlSchema schema) { if (element.isRef()) { throw new RuntimeException("isElementNameQualified on element with ref="); } if (element.getForm().equals(XmlSchemaForm.QUALIFIED)) { return true; } if (element.getForm().equals(XmlSchemaForm.UNQUALIFIED)) { return false; } return schema.getElementFormDefault().equals(XmlSchemaForm.QUALIFIED); } /** * due to a bug, feature, or just plain oddity of JAXB, it isn't good enough to just check the * form of an element and of its schema. If schema 'a' (default unqualified) has a complex type * with an element with a ref= to schema (b) (default unqualified), JAXB seems to expect to see a * qualifier, anyway. <br> * So, if the element is local to a complex type, all we care about is the default element form of * the schema and the local form of the element. <br> * If, on the other hand, the element is global, we might need to compare namespaces. <br> * * @param element the element. * @param global if this element is a global element (complex type ref= to it, or in a part) * @param localSchema the schema of the complex type containing the reference, only used for the * 'odd case'. * @param elementSchema the schema for the element. * @return if the element needs to be qualified. */ public static boolean isElementQualified( XmlSchemaElement element, boolean global, XmlSchema localSchema, XmlSchema elementSchema) { QName qn = getElementQualifiedName(element, localSchema); if (qn == null) { throw new RuntimeException("isElementQualified on anonymous element."); } if (element.isRef()) { throw new RuntimeException("isElementQualified on the 'from' side of ref=."); } if (global) { return isElementNameQualified(element, elementSchema) || (localSchema != null && !(qn.getNamespaceURI().equals(localSchema.getTargetNamespace()))); } else { return isElementNameQualified(element, elementSchema); } } public static boolean isParticleArray(XmlSchemaParticle particle) { return particle.getMaxOccurs() > 1; } public static boolean isParticleOptional(XmlSchemaParticle particle) { return particle.getMinOccurs() == 0 && particle.getMaxOccurs() == 1; } }
public class JAXRSOutInterceptor extends AbstractOutDatabindingInterceptor { private static final Logger LOG = LogUtils.getL7dLogger(JAXRSOutInterceptor.class); private static final ResourceBundle BUNDLE = BundleUtils.getBundle(JAXRSOutInterceptor.class); public JAXRSOutInterceptor() { super(Phase.MARSHAL); } public void handleMessage(Message message) { ServerProviderFactory providerFactory = ServerProviderFactory.getInstance(message); try { processResponse(providerFactory, message); } finally { ServerProviderFactory.releaseRequestState(providerFactory, message); } } private void processResponse(ServerProviderFactory providerFactory, Message message) { if (isResponseAlreadyHandled(message)) { return; } MessageContentsList objs = MessageContentsList.getContentsList(message); if (objs == null || objs.size() == 0) { return; } Object responseObj = objs.get(0); Response response = null; if (responseObj instanceof Response) { response = (Response) responseObj; if (response.getStatus() == 500 && message.getExchange().get(JAXRSUtils.EXCEPTION_FROM_MAPPER) != null) { message.put(Message.RESPONSE_CODE, 500); return; } } else { int status = getStatus(message, responseObj != null ? 200 : 204); response = JAXRSUtils.toResponseBuilder(status).entity(responseObj).build(); } Exchange exchange = message.getExchange(); OperationResourceInfo ori = (OperationResourceInfo) exchange.get(OperationResourceInfo.class.getName()); serializeMessage(providerFactory, message, response, ori, true); } private int getStatus(Message message, int defaultValue) { Object customStatus = message.getExchange().get(Message.RESPONSE_CODE); return customStatus == null ? defaultValue : (Integer) customStatus; } private void serializeMessage( ServerProviderFactory providerFactory, Message message, Response theResponse, OperationResourceInfo ori, boolean firstTry) { ResponseImpl response = (ResponseImpl) JAXRSUtils.copyResponseIfNeeded(theResponse); final Exchange exchange = message.getExchange(); boolean headResponse = response.getStatus() == 200 && firstTry && ori != null && HttpMethod.HEAD.equals(ori.getHttpMethod()); Object entity = response.getActualEntity(); if (headResponse && entity != null) { LOG.info(new org.apache.cxf.common.i18n.Message("HEAD_WITHOUT_ENTITY", BUNDLE).toString()); entity = null; } Method invoked = ori == null ? null : ori.getAnnotatedMethod() != null ? ori.getAnnotatedMethod() : ori.getMethodToInvoke(); Annotation[] annotations = null; Annotation[] staticAnns = ori != null ? ori.getOutAnnotations() : new Annotation[] {}; Annotation[] responseAnns = response.getEntityAnnotations(); if (responseAnns != null) { annotations = new Annotation[staticAnns.length + responseAnns.length]; System.arraycopy(staticAnns, 0, annotations, 0, staticAnns.length); System.arraycopy(responseAnns, 0, annotations, staticAnns.length, responseAnns.length); } else { annotations = staticAnns; } response.setStatus(getActualStatus(response.getStatus(), entity)); response.setEntity(entity, annotations); // Prepare the headers MultivaluedMap<String, Object> responseHeaders = prepareResponseHeaders(message, response, entity, firstTry); // Run the filters try { JAXRSUtils.runContainerResponseFilters(providerFactory, response, message, ori, invoked); } catch (Throwable ex) { handleWriteException(providerFactory, message, ex, firstTry); return; } // Write the entity entity = InjectionUtils.getEntity(response.getActualEntity()); setResponseStatus(message, getActualStatus(response.getStatus(), entity)); if (entity == null) { if (!headResponse) { responseHeaders.putSingle(HttpHeaders.CONTENT_LENGTH, "0"); if (MessageUtils.getContextualBoolean( message, "remove.content.type.for.empty.response", false)) { responseHeaders.remove(HttpHeaders.CONTENT_TYPE); message.remove(Message.CONTENT_TYPE); } } HttpUtils.convertHeaderValuesToString(responseHeaders, true); return; } Object ignoreWritersProp = exchange.get(JAXRSUtils.IGNORE_MESSAGE_WRITERS); boolean ignoreWriters = ignoreWritersProp == null ? false : Boolean.valueOf(ignoreWritersProp.toString()); if (ignoreWriters) { writeResponseToStream(message.getContent(OutputStream.class), entity); return; } MediaType responseMediaType = getResponseMediaType(responseHeaders.getFirst(HttpHeaders.CONTENT_TYPE)); Class<?> serviceCls = invoked != null ? ori.getClassResourceInfo().getServiceClass() : null; Class<?> targetType = InjectionUtils.getRawResponseClass(entity); Type genericType = InjectionUtils.getGenericResponseType( invoked, serviceCls, response.getActualEntity(), targetType, exchange); targetType = InjectionUtils.updateParamClassToTypeIfNeeded(targetType, genericType); annotations = response.getEntityAnnotations(); List<WriterInterceptor> writers = providerFactory.createMessageBodyWriterInterceptor( targetType, genericType, annotations, responseMediaType, message, ori == null ? null : ori.getNameBindings()); OutputStream outOriginal = message.getContent(OutputStream.class); if (writers == null || writers.isEmpty()) { writeResponseErrorMessage( message, outOriginal, "NO_MSG_WRITER", targetType, responseMediaType); return; } try { boolean checkWriters = false; if (responseMediaType.isWildcardSubtype()) { Produces pM = AnnotationUtils.getMethodAnnotation( ori == null ? null : ori.getAnnotatedMethod(), Produces.class); Produces pC = AnnotationUtils.getClassAnnotation(serviceCls, Produces.class); checkWriters = pM == null && pC == null; } responseMediaType = checkFinalContentType(responseMediaType, writers, checkWriters); } catch (Throwable ex) { handleWriteException(providerFactory, message, ex, firstTry); return; } String finalResponseContentType = JAXRSUtils.mediaTypeToString(responseMediaType); if (LOG.isLoggable(Level.FINE)) { LOG.fine("Response content type is: " + finalResponseContentType); } responseHeaders.putSingle(HttpHeaders.CONTENT_TYPE, finalResponseContentType); message.put(Message.CONTENT_TYPE, finalResponseContentType); boolean enabled = checkBufferingMode(message, writers, firstTry); try { try { JAXRSUtils.writeMessageBody( writers, entity, targetType, genericType, annotations, responseMediaType, responseHeaders, message); if (isResponseRedirected(message)) { return; } checkCachedStream(message, outOriginal, enabled); } finally { if (enabled) { OutputStream os = message.getContent(OutputStream.class); if (os != outOriginal && os instanceof CachedOutputStream) { os.close(); } message.setContent(OutputStream.class, outOriginal); message.put(XMLStreamWriter.class.getName(), null); } } } catch (Throwable ex) { logWriteError(firstTry, targetType, responseMediaType); handleWriteException(providerFactory, message, ex, firstTry); } } private MultivaluedMap<String, Object> prepareResponseHeaders( Message message, ResponseImpl response, Object entity, boolean firstTry) { MultivaluedMap<String, Object> responseHeaders = response.getMetadata(); @SuppressWarnings("unchecked") Map<String, List<Object>> userHeaders = (Map<String, List<Object>>) message.get(Message.PROTOCOL_HEADERS); if (firstTry && userHeaders != null) { responseHeaders.putAll(userHeaders); } if (entity != null) { Object customContentType = responseHeaders.getFirst(HttpHeaders.CONTENT_TYPE); if (customContentType == null) { String initialResponseContentType = (String) message.get(Message.CONTENT_TYPE); if (initialResponseContentType != null) { responseHeaders.putSingle(HttpHeaders.CONTENT_TYPE, initialResponseContentType); } } else { message.put(Message.CONTENT_TYPE, customContentType.toString()); } } message.put(Message.PROTOCOL_HEADERS, responseHeaders); setResponseDate(responseHeaders, firstTry); return responseHeaders; } private MediaType getResponseMediaType(Object mediaTypeHeader) { MediaType responseMediaType; if (mediaTypeHeader instanceof MediaType) { responseMediaType = (MediaType) mediaTypeHeader; } else { responseMediaType = mediaTypeHeader == null ? MediaType.WILDCARD_TYPE : JAXRSUtils.toMediaType(mediaTypeHeader.toString()); } return responseMediaType; } private int getActualStatus(int status, Object responseObj) { if (status == -1) { return responseObj == null ? 204 : 200; } else { return status; } } private boolean checkBufferingMode(Message m, List<WriterInterceptor> writers, boolean firstTry) { if (!firstTry) { return false; } WriterInterceptor last = writers.get(writers.size() - 1); MessageBodyWriter<Object> w = ((WriterInterceptorMBW) last).getMBW(); Object outBuf = m.getContextualProperty(OUT_BUFFERING); boolean enabled = MessageUtils.isTrue(outBuf); boolean configurableProvider = w instanceof AbstractConfigurableProvider; if (!enabled && outBuf == null && configurableProvider) { enabled = ((AbstractConfigurableProvider) w).getEnableBuffering(); } if (enabled) { boolean streamingOn = configurableProvider ? ((AbstractConfigurableProvider) w).getEnableStreaming() : false; if (streamingOn) { m.setContent(XMLStreamWriter.class, new CachingXmlEventWriter()); } else { m.setContent(OutputStream.class, new CachedOutputStream()); } } return enabled; } private void checkCachedStream(Message m, OutputStream osOriginal, boolean enabled) throws Exception { XMLStreamWriter writer = null; if (enabled) { writer = m.getContent(XMLStreamWriter.class); } else { writer = (XMLStreamWriter) m.get(XMLStreamWriter.class.getName()); } if (writer instanceof CachingXmlEventWriter) { CachingXmlEventWriter cache = (CachingXmlEventWriter) writer; if (cache.getEvents().size() != 0) { XMLStreamWriter origWriter = null; try { origWriter = StaxUtils.createXMLStreamWriter(osOriginal); for (XMLEvent event : cache.getEvents()) { StaxUtils.writeEvent(event, origWriter); } } finally { StaxUtils.close(origWriter); } } m.setContent(XMLStreamWriter.class, null); return; } if (enabled) { OutputStream os = m.getContent(OutputStream.class); if (os != osOriginal && os instanceof CachedOutputStream) { CachedOutputStream cos = (CachedOutputStream) os; if (cos.size() != 0) { cos.writeCacheTo(osOriginal); } } } } private void logWriteError(boolean firstTry, Class<?> cls, MediaType ct) { if (firstTry) { JAXRSUtils.logMessageHandlerProblem("MSG_WRITER_PROBLEM", cls, ct); } } private void handleWriteException( ServerProviderFactory pf, Message message, Throwable ex, boolean firstTry) { Response excResponse = null; if (firstTry) { excResponse = JAXRSUtils.convertFaultToResponse(ex, message); } else { message.getExchange().put(JAXRSUtils.SECOND_JAXRS_EXCEPTION, Boolean.TRUE); } if (excResponse == null) { setResponseStatus(message, 500); throw new Fault(ex); } else { serializeMessage(pf, message, excResponse, null, false); } } private void writeResponseErrorMessage( Message message, OutputStream out, String name, Class<?> cls, MediaType ct) { message.put(Message.CONTENT_TYPE, "text/plain"); message.put(Message.RESPONSE_CODE, 500); try { String errorMessage = JAXRSUtils.logMessageHandlerProblem(name, cls, ct); if (out != null) { out.write(errorMessage.getBytes(StandardCharsets.UTF_8)); } } catch (IOException another) { // ignore } } private MediaType checkFinalContentType( MediaType mt, List<WriterInterceptor> writers, boolean checkWriters) { if (checkWriters) { int mbwIndex = writers.size() == 1 ? 0 : writers.size() - 1; MessageBodyWriter<Object> writer = ((WriterInterceptorMBW) writers.get(mbwIndex)).getMBW(); Produces pm = writer.getClass().getAnnotation(Produces.class); if (pm != null) { List<MediaType> sorted = JAXRSUtils.sortMediaTypes( JAXRSUtils.getMediaTypes(pm.value()), JAXRSUtils.MEDIA_TYPE_QS_PARAM); mt = JAXRSUtils.intersectMimeTypes(sorted, mt).get(0); } } if (mt.isWildcardType() || mt.isWildcardSubtype()) { if ("application".equals(mt.getType()) || mt.isWildcardType()) { mt = MediaType.APPLICATION_OCTET_STREAM_TYPE; } else { throw ExceptionUtils.toNotAcceptableException(null, null); } } return mt; } private void setResponseDate(MultivaluedMap<String, Object> headers, boolean firstTry) { if (!firstTry || headers.containsKey(HttpHeaders.DATE)) { return; } SimpleDateFormat format = HttpUtils.getHttpDateFormat(); headers.putSingle(HttpHeaders.DATE, format.format(new Date())); } private boolean isResponseAlreadyHandled(Message m) { return isResponseAlreadyCommited(m) || isResponseRedirected(m); } private boolean isResponseAlreadyCommited(Message m) { return Boolean.TRUE.equals(m.getExchange().get(AbstractHTTPDestination.RESPONSE_COMMITED)); } private boolean isResponseRedirected(Message m) { return Boolean.TRUE.equals(m.getExchange().get(AbstractHTTPDestination.REQUEST_REDIRECTED)); } private void writeResponseToStream(OutputStream os, Object responseObj) { try { byte[] bytes = responseObj.toString().getBytes(StandardCharsets.UTF_8); os.write(bytes, 0, bytes.length); } catch (Exception ex) { LOG.severe("Problem with writing the data to the output stream"); ex.printStackTrace(); throw new RuntimeException(ex); } } private void setResponseStatus(Message message, int status) { message.put(Message.RESPONSE_CODE, status); boolean responseHeadersCopied = isResponseHeadersCopied(message); if (responseHeadersCopied) { HttpServletResponse response = (HttpServletResponse) message.get(AbstractHTTPDestination.HTTP_RESPONSE); response.setStatus(status); } } // Some CXF interceptors such as FIStaxOutInterceptor will indirectly initiate // an early copying of response code and headers into the HttpServletResponse // TODO : Pushing the filter processing and copying response headers into say // PRE-LOGICAl and PREPARE_SEND interceptors will most likely be a good thing // however JAX-RS MessageBodyWriters are also allowed to add response headers // which is reason why a MultipartMap parameter in MessageBodyWriter.writeTo // method is modifiable. Thus we do need to know if the initial copy has already // occurred: for now we will just use to ensure the correct status is set private boolean isResponseHeadersCopied(Message message) { return MessageUtils.isTrue(message.get(AbstractHTTPDestination.RESPONSE_HEADERS_COPIED)); } public void handleFault(Message message) { // complete } }
public final class ResourceUtils { private static final Logger LOG = LogUtils.getL7dLogger(ResourceUtils.class); private static final ResourceBundle BUNDLE = BundleUtils.getBundle(ResourceUtils.class); private static final String CLASSPATH_PREFIX = "classpath:"; private static final Set<String> SERVER_PROVIDER_CLASS_NAMES; static { SERVER_PROVIDER_CLASS_NAMES = new HashSet<String>(); SERVER_PROVIDER_CLASS_NAMES.add("javax.ws.rs.ext.MessageBodyWriter"); SERVER_PROVIDER_CLASS_NAMES.add("javax.ws.rs.ext.MessageBodyReader"); SERVER_PROVIDER_CLASS_NAMES.add("javax.ws.rs.ext.ExceptionMapper"); SERVER_PROVIDER_CLASS_NAMES.add("javax.ws.rs.ext.ContextResolver"); SERVER_PROVIDER_CLASS_NAMES.add("javax.ws.rs.ext.ReaderInterceptor"); SERVER_PROVIDER_CLASS_NAMES.add("javax.ws.rs.ext.WriterInterceptor"); SERVER_PROVIDER_CLASS_NAMES.add("javax.ws.rs.ext.ParamConverterProvider"); SERVER_PROVIDER_CLASS_NAMES.add("javax.ws.rs.container.ContainerRequestFilter"); SERVER_PROVIDER_CLASS_NAMES.add("javax.ws.rs.container.ContainerResponseFilter"); SERVER_PROVIDER_CLASS_NAMES.add("javax.ws.rs.container.DynamicFeature"); SERVER_PROVIDER_CLASS_NAMES.add("org.apache.cxf.jaxrs.ext.ContextResolver"); } private ResourceUtils() {} public static Method findPostConstructMethod(Class<?> c) { return findPostConstructMethod(c, null); } public static Method findPostConstructMethod(Class<?> c, String name) { if (Object.class == c || null == c) { return null; } for (Method m : c.getDeclaredMethods()) { if (name != null) { if (m.getName().equals(name)) { return m; } } else if (m.getAnnotation(PostConstruct.class) != null) { return m; } } Method m = findPostConstructMethod(c.getSuperclass(), name); if (m != null) { return m; } for (Class<?> i : c.getInterfaces()) { m = findPostConstructMethod(i, name); if (m != null) { return m; } } return null; } public static Method findPreDestroyMethod(Class<?> c) { return findPreDestroyMethod(c, null); } public static Method findPreDestroyMethod(Class<?> c, String name) { if (Object.class == c || null == c) { return null; } for (Method m : c.getDeclaredMethods()) { if (name != null) { if (m.getName().equals(name)) { return m; } } else if (m.getAnnotation(PreDestroy.class) != null) { return m; } } Method m = findPreDestroyMethod(c.getSuperclass(), name); if (m != null) { return m; } for (Class<?> i : c.getInterfaces()) { m = findPreDestroyMethod(i, name); if (m != null) { return m; } } return null; } public static ClassResourceInfo createClassResourceInfo( Map<String, UserResource> resources, UserResource model, Class<?> defaultClass, boolean isRoot, boolean enableStatic, Bus bus) { final boolean isDefaultClass = defaultClass != null; Class<?> sClass = !isDefaultClass ? loadClass(model.getName()) : defaultClass; return createServiceClassResourceInfo(resources, model, sClass, isRoot, enableStatic, bus); } public static ClassResourceInfo createServiceClassResourceInfo( Map<String, UserResource> resources, UserResource model, Class<?> sClass, boolean isRoot, boolean enableStatic, Bus bus) { if (model == null) { throw new RuntimeException("Resource class " + sClass.getName() + " has no model info"); } ClassResourceInfo cri = new ClassResourceInfo( sClass, sClass, isRoot, enableStatic, true, model.getConsumes(), model.getProduces(), bus); URITemplate t = URITemplate.createTemplate(model.getPath()); cri.setURITemplate(t); MethodDispatcher md = new MethodDispatcher(); Map<String, UserOperation> ops = model.getOperationsAsMap(); Method defaultMethod = null; Map<String, Method> methodNames = new HashMap<String, Method>(); for (Method m : cri.getServiceClass().getMethods()) { if (m.getAnnotation(DefaultMethod.class) != null) { // if needed we can also support multiple default methods defaultMethod = m; } methodNames.put(m.getName(), m); } for (Map.Entry<String, UserOperation> entry : ops.entrySet()) { UserOperation op = entry.getValue(); Method actualMethod = methodNames.get(op.getName()); if (actualMethod == null) { actualMethod = defaultMethod; } if (actualMethod == null) { continue; } OperationResourceInfo ori = new OperationResourceInfo( actualMethod, cri, URITemplate.createTemplate(op.getPath()), op.getVerb(), op.getConsumes(), op.getProduces(), op.getParameters(), op.isOneway()); String rClassName = actualMethod.getReturnType().getName(); if (op.getVerb() == null) { if (resources.containsKey(rClassName)) { ClassResourceInfo subCri = rClassName.equals(model.getName()) ? cri : createServiceClassResourceInfo( resources, resources.get(rClassName), actualMethod.getReturnType(), false, enableStatic, bus); if (subCri != null) { cri.addSubClassResourceInfo(subCri); md.bind(ori, actualMethod); } } } else { md.bind(ori, actualMethod); } } cri.setMethodDispatcher(md); return checkMethodDispatcher(cri) ? cri : null; } public static ClassResourceInfo createClassResourceInfo( final Class<?> rClass, final Class<?> sClass, boolean root, boolean enableStatic) { return createClassResourceInfo( rClass, sClass, root, enableStatic, BusFactory.getThreadDefaultBus()); } public static ClassResourceInfo createClassResourceInfo( final Class<?> rClass, final Class<?> sClass, boolean root, boolean enableStatic, Bus bus) { return createClassResourceInfo(rClass, sClass, null, root, enableStatic, bus); } public static ClassResourceInfo createClassResourceInfo( final Class<?> rClass, final Class<?> sClass, ClassResourceInfo parent, boolean root, boolean enableStatic, Bus bus) { ClassResourceInfo cri = new ClassResourceInfo(rClass, sClass, root, enableStatic, bus); cri.setParent(parent); if (root) { URITemplate t = URITemplate.createTemplate(cri.getPath()); cri.setURITemplate(t); } evaluateResourceClass(cri, enableStatic); return checkMethodDispatcher(cri) ? cri : null; } private static void evaluateResourceClass(ClassResourceInfo cri, boolean enableStatic) { MethodDispatcher md = new MethodDispatcher(); Class<?> serviceClass = cri.getServiceClass(); boolean isFineLevelLoggable = LOG.isLoggable(Level.FINE); for (Method m : serviceClass.getMethods()) { Method annotatedMethod = AnnotationUtils.getAnnotatedMethod(serviceClass, m); String httpMethod = AnnotationUtils.getHttpMethodValue(annotatedMethod); Path path = AnnotationUtils.getMethodAnnotation(annotatedMethod, Path.class); if (httpMethod != null || path != null) { md.bind(createOperationInfo(m, annotatedMethod, cri, path, httpMethod), m); if (httpMethod == null) { // subresource locator Class<?> subClass = m.getReturnType(); if (enableStatic) { ClassResourceInfo subCri = cri.findResource(subClass, subClass); if (subCri == null) { ClassResourceInfo ancestor = getAncestorWithSameServiceClass(cri, subClass); subCri = ancestor != null ? ancestor : createClassResourceInfo( subClass, subClass, cri, false, enableStatic, cri.getBus()); } if (subCri != null) { cri.addSubClassResourceInfo(subCri); } } } } else if (isFineLevelLoggable) { LOG.fine( new org.apache.cxf.common.i18n.Message( "NOT_RESOURCE_METHOD", BUNDLE, m.getDeclaringClass().getName(), m.getName()) .toString()); } } cri.setMethodDispatcher(md); } private static ClassResourceInfo getAncestorWithSameServiceClass( ClassResourceInfo parent, Class<?> subClass) { if (parent == null) { return null; } if (parent.getServiceClass() == subClass) { return parent; } return getAncestorWithSameServiceClass(parent.getParent(), subClass); } public static Constructor<?> findResourceConstructor(Class<?> resourceClass, boolean perRequest) { List<Constructor<?>> cs = new LinkedList<Constructor<?>>(); for (Constructor<?> c : resourceClass.getConstructors()) { Class<?>[] params = c.getParameterTypes(); Annotation[][] anns = c.getParameterAnnotations(); boolean match = true; for (int i = 0; i < params.length; i++) { if (!perRequest) { if (AnnotationUtils.getAnnotation(anns[i], Context.class) == null) { match = false; break; } } else if (!AnnotationUtils.isValidParamAnnotations(anns[i])) { match = false; break; } } if (match) { cs.add(c); } } Collections.sort( cs, new Comparator<Constructor<?>>() { public int compare(Constructor<?> c1, Constructor<?> c2) { int p1 = c1.getParameterTypes().length; int p2 = c2.getParameterTypes().length; return p1 > p2 ? -1 : p1 < p2 ? 1 : 0; } }); return cs.size() == 0 ? null : cs.get(0); } public static List<Parameter> getParameters(Method resourceMethod) { Annotation[][] paramAnns = resourceMethod.getParameterAnnotations(); if (paramAnns.length == 0) { return CastUtils.cast(Collections.emptyList(), Parameter.class); } Class<?>[] types = resourceMethod.getParameterTypes(); List<Parameter> params = new ArrayList<Parameter>(paramAnns.length); for (int i = 0; i < paramAnns.length; i++) { Parameter p = getParameter(i, paramAnns[i], types[i]); params.add(p); } return params; } // CHECKSTYLE:OFF public static Parameter getParameter(int index, Annotation[] anns, Class<?> type) { Context ctx = AnnotationUtils.getAnnotation(anns, Context.class); if (ctx != null) { return new Parameter(ParameterType.CONTEXT, index, null); } boolean isEncoded = AnnotationUtils.getAnnotation(anns, Encoded.class) != null; BeanParam bp = AnnotationUtils.getAnnotation(anns, BeanParam.class); if (bp != null) { return new Parameter(ParameterType.BEAN, index, null, isEncoded, null); } String dValue = AnnotationUtils.getDefaultParameterValue(anns); PathParam a = AnnotationUtils.getAnnotation(anns, PathParam.class); if (a != null) { return new Parameter(ParameterType.PATH, index, a.value(), isEncoded, dValue); } QueryParam q = AnnotationUtils.getAnnotation(anns, QueryParam.class); if (q != null) { return new Parameter(ParameterType.QUERY, index, q.value(), isEncoded, dValue); } MatrixParam m = AnnotationUtils.getAnnotation(anns, MatrixParam.class); if (m != null) { return new Parameter(ParameterType.MATRIX, index, m.value(), isEncoded, dValue); } FormParam f = AnnotationUtils.getAnnotation(anns, FormParam.class); if (f != null) { return new Parameter(ParameterType.FORM, index, f.value(), isEncoded, dValue); } HeaderParam h = AnnotationUtils.getAnnotation(anns, HeaderParam.class); if (h != null) { return new Parameter(ParameterType.HEADER, index, h.value(), isEncoded, dValue); } CookieParam c = AnnotationUtils.getAnnotation(anns, CookieParam.class); if (c != null) { return new Parameter(ParameterType.COOKIE, index, c.value(), isEncoded, dValue); } return new Parameter(ParameterType.REQUEST_BODY, index, null); } // CHECKSTYLE:ON private static OperationResourceInfo createOperationInfo( Method m, Method annotatedMethod, ClassResourceInfo cri, Path path, String httpMethod) { OperationResourceInfo ori = new OperationResourceInfo(m, annotatedMethod, cri); URITemplate t = URITemplate.createTemplate(path); ori.setURITemplate(t); ori.setHttpMethod(httpMethod); return ori; } private static boolean checkMethodDispatcher(ClassResourceInfo cr) { if (cr.getMethodDispatcher().getOperationResourceInfos().isEmpty()) { LOG.warning( new org.apache.cxf.common.i18n.Message( "NO_RESOURCE_OP_EXC", BUNDLE, cr.getServiceClass().getName()) .toString()); return false; } return true; } private static Class<?> loadClass(String cName) { try { return ClassLoaderUtils.loadClass(cName.trim(), ResourceUtils.class); } catch (ClassNotFoundException ex) { throw new RuntimeException("No class " + cName.trim() + " can be found", ex); } } public static List<UserResource> getUserResources(String loc, Bus bus) { try { InputStream is = ResourceUtils.getResourceStream(loc, bus); if (is == null) { return null; } return getUserResources(is); } catch (Exception ex) { LOG.warning("Problem with processing a user model at " + loc); } return null; } public static InputStream getResourceStream(String loc, Bus bus) throws Exception { URL url = getResourceURL(loc, bus); return url == null ? null : url.openStream(); } public static URL getResourceURL(String loc, Bus bus) throws Exception { URL url = null; if (loc.startsWith(CLASSPATH_PREFIX)) { String path = loc.substring(CLASSPATH_PREFIX.length()); url = ResourceUtils.getClasspathResourceURL(path, ResourceUtils.class, bus); } else { try { url = new URL(loc); } catch (Exception ex) { // it can be either a classpath or file resource without a scheme url = ResourceUtils.getClasspathResourceURL(loc, ResourceUtils.class, bus); if (url == null) { File file = new File(loc); if (file.exists()) { url = file.toURI().toURL(); } } } } if (url == null) { LOG.warning("No resource " + loc + " is available"); } return url; } public static InputStream getClasspathResourceStream( String path, Class<?> callingClass, Bus bus) { InputStream is = ClassLoaderUtils.getResourceAsStream(path, callingClass); return is == null ? getResource(path, InputStream.class, bus) : is; } public static URL getClasspathResourceURL(String path, Class<?> callingClass, Bus bus) { URL url = ClassLoaderUtils.getResource(path, callingClass); return url == null ? getResource(path, URL.class, bus) : url; } public static <T> T getResource(String path, Class<T> resourceClass, Bus bus) { if (bus != null) { ResourceManager rm = bus.getExtension(ResourceManager.class); if (rm != null) { return rm.resolveResource(path, resourceClass); } } return null; } public static Properties loadProperties(String propertiesLocation, Bus bus) throws Exception { Properties props = new Properties(); InputStream is = getResourceStream(propertiesLocation, bus); props.load(is); return props; } public static List<UserResource> getUserResources(String loc) { return getUserResources(loc, BusFactory.getThreadDefaultBus()); } public static List<UserResource> getUserResources(InputStream is) throws Exception { Document doc = StaxUtils.read(new InputStreamReader(is, "UTF-8")); return getResourcesFromElement(doc.getDocumentElement()); } public static List<UserResource> getResourcesFromElement(Element modelEl) { List<UserResource> resources = new ArrayList<UserResource>(); List<Element> resourceEls = DOMUtils.findAllElementsByTagNameNS(modelEl, "http://cxf.apache.org/jaxrs", "resource"); for (Element e : resourceEls) { resources.add(getResourceFromElement(e)); } return resources; } public static ResourceTypes getAllRequestResponseTypes( List<ClassResourceInfo> cris, boolean jaxbOnly) { return getAllRequestResponseTypes(cris, jaxbOnly, null); } public static ResourceTypes getAllRequestResponseTypes( List<ClassResourceInfo> cris, boolean jaxbOnly, MessageBodyWriter<?> jaxbWriter) { ResourceTypes types = new ResourceTypes(); for (ClassResourceInfo resource : cris) { getAllTypesForResource(resource, types, jaxbOnly, jaxbWriter); } return types; } public static Class<?> getActualJaxbType(Class<?> type, Method resourceMethod, boolean inbound) { ElementClass element = resourceMethod.getAnnotation(ElementClass.class); if (element != null) { Class<?> cls = inbound ? element.request() : element.response(); if (cls != Object.class) { return cls; } } return type; } private static void getAllTypesForResource( ClassResourceInfo resource, ResourceTypes types, boolean jaxbOnly, MessageBodyWriter<?> jaxbWriter) { for (OperationResourceInfo ori : resource.getMethodDispatcher().getOperationResourceInfos()) { Method method = ori.getMethodToInvoke(); Class<?> realReturnType = method.getReturnType(); Class<?> cls = realReturnType; if (cls == Response.class) { cls = getActualJaxbType(cls, method, false); } Type type = method.getGenericReturnType(); if (jaxbOnly) { checkJaxbType( resource.getServiceClass(), cls, realReturnType == Response.class ? cls : type, types, method.getAnnotations(), jaxbWriter); } else { types.getAllTypes().put(cls, type); } for (Parameter pm : ori.getParameters()) { if (pm.getType() == ParameterType.REQUEST_BODY) { Class<?> inType = method.getParameterTypes()[pm.getIndex()]; Type paramType = method.getGenericParameterTypes()[pm.getIndex()]; if (jaxbOnly) { checkJaxbType( resource.getServiceClass(), inType, paramType, types, method.getParameterAnnotations()[pm.getIndex()], jaxbWriter); } else { types.getAllTypes().put(inType, paramType); } } } } for (ClassResourceInfo sub : resource.getSubResources()) { if (!isRecursiveSubResource(resource, sub)) { getAllTypesForResource(sub, types, jaxbOnly, jaxbWriter); } } } private static boolean isRecursiveSubResource(ClassResourceInfo parent, ClassResourceInfo sub) { if (parent == null) { return false; } if (parent == sub) { return true; } return isRecursiveSubResource(parent.getParent(), sub); } private static void checkJaxbType( Class<?> serviceClass, Class<?> type, Type genericType, ResourceTypes types, Annotation[] anns, MessageBodyWriter<?> jaxbWriter) { boolean isCollection = false; if (InjectionUtils.isSupportedCollectionOrArray(type)) { type = InjectionUtils.getActualType(genericType); isCollection = true; } if (type == Object.class && !(genericType instanceof Class)) { Type theType = InjectionUtils.processGenericTypeIfNeeded(serviceClass, Object.class, genericType); type = InjectionUtils.getActualType(theType); } if (type == null || InjectionUtils.isPrimitive(type) || JAXBElement.class.isAssignableFrom(type) || Response.class.isAssignableFrom(type) || type.isInterface()) { return; } MessageBodyWriter<?> writer = jaxbWriter; if (writer == null) { JAXBElementProvider<Object> defaultWriter = new JAXBElementProvider<Object>(); defaultWriter.setMarshallAsJaxbElement(true); defaultWriter.setXmlTypeAsJaxbElementOnly(true); writer = defaultWriter; } if (writer.isWriteable(type, type, anns, MediaType.APPLICATION_XML_TYPE)) { types.getAllTypes().put(type, type); Class<?> genCls = InjectionUtils.getActualType(genericType); if (genCls != type && genCls != null && genCls != Object.class && !InjectionUtils.isSupportedCollectionOrArray(genCls)) { types.getAllTypes().put(genCls, genCls); } XMLName name = AnnotationUtils.getAnnotation(anns, XMLName.class); QName qname = name != null ? JAXRSUtils.convertStringToQName(name.value()) : null; if (isCollection) { types.getCollectionMap().put(type, qname); } else { types.getXmlNameMap().put(type, qname); } } } private static UserResource getResourceFromElement(Element e) { UserResource resource = new UserResource(); resource.setName(e.getAttribute("name")); resource.setPath(e.getAttribute("path")); resource.setConsumes(e.getAttribute("consumes")); resource.setProduces(e.getAttribute("produces")); List<Element> operEls = DOMUtils.findAllElementsByTagNameNS(e, "http://cxf.apache.org/jaxrs", "operation"); List<UserOperation> opers = new ArrayList<UserOperation>(operEls.size()); for (Element operEl : operEls) { opers.add(getOperationFromElement(operEl)); } resource.setOperations(opers); return resource; } private static UserOperation getOperationFromElement(Element e) { UserOperation op = new UserOperation(); op.setName(e.getAttribute("name")); op.setVerb(e.getAttribute("verb")); op.setPath(e.getAttribute("path")); op.setOneway(Boolean.parseBoolean(e.getAttribute("oneway"))); op.setConsumes(e.getAttribute("consumes")); op.setProduces(e.getAttribute("produces")); List<Element> paramEls = DOMUtils.findAllElementsByTagNameNS(e, "http://cxf.apache.org/jaxrs", "param"); List<Parameter> params = new ArrayList<Parameter>(paramEls.size()); for (int i = 0; i < paramEls.size(); i++) { Element paramEl = paramEls.get(i); Parameter p = new Parameter(paramEl.getAttribute("type"), i, paramEl.getAttribute("name")); p.setEncoded(Boolean.valueOf(paramEl.getAttribute("encoded"))); p.setDefaultValue(paramEl.getAttribute("defaultValue")); String pClass = paramEl.getAttribute("class"); if (!StringUtils.isEmpty(pClass)) { try { p.setJavaType(ClassLoaderUtils.loadClass(pClass, ResourceUtils.class)); } catch (Exception ex) { throw new RuntimeException(ex); } } params.add(p); } op.setParameters(params); return op; } public static Object[] createConstructorArguments( Constructor<?> c, Message m, boolean perRequest) { return createConstructorArguments(c, m, perRequest, null); } public static Object[] createConstructorArguments( Constructor<?> c, Message m, boolean perRequest, Map<Class<?>, Object> contextValues) { Class<?>[] params = c.getParameterTypes(); Annotation[][] anns = c.getParameterAnnotations(); Type[] genericTypes = c.getGenericParameterTypes(); @SuppressWarnings("unchecked") MultivaluedMap<String, String> templateValues = m == null ? null : (MultivaluedMap<String, String>) m.get(URITemplate.TEMPLATE_PARAMETERS); Object[] values = new Object[params.length]; for (int i = 0; i < params.length; i++) { if (AnnotationUtils.getAnnotation(anns[i], Context.class) != null) { Object contextValue = contextValues != null ? contextValues.get(params[i]) : null; if (contextValue == null) { if (perRequest) { values[i] = JAXRSUtils.createContextValue(m, genericTypes[i], params[i]); } else { values[i] = InjectionUtils.createThreadLocalProxy(params[i]); } } else { values[i] = contextValue; } } else { // this branch won't execute for singletons given that the found constructor // is guaranteed to have only Context parameters, if any, for singletons Parameter p = ResourceUtils.getParameter(i, anns[i], params[i]); values[i] = JAXRSUtils.createHttpParameterValue( p, params[i], genericTypes[i], anns[i], m, templateValues, null); } } return values; } public static JAXRSServerFactoryBean createApplication(Application app, boolean ignoreAppPath) { return createApplication(app, ignoreAppPath, false); } @SuppressWarnings("unchecked") public static JAXRSServerFactoryBean createApplication( Application app, boolean ignoreAppPath, boolean staticSubresourceResolution) { Set<Object> singletons = app.getSingletons(); verifySingletons(singletons); List<Class<?>> resourceClasses = new ArrayList<Class<?>>(); List<Object> providers = new ArrayList<Object>(); List<Feature> features = new ArrayList<Feature>(); Map<Class<?>, ResourceProvider> map = new HashMap<Class<?>, ResourceProvider>(); // Note, app.getClasses() returns a list of per-request classes // or singleton provider classes for (Class<?> cls : app.getClasses()) { if (isValidApplicationClass(cls, singletons)) { if (isValidProvider(cls)) { providers.add(createProviderInstance(cls)); } else if (Feature.class.isAssignableFrom(cls)) { features.add(createFeatureInstance((Class<? extends Feature>) cls)); } else { resourceClasses.add(cls); map.put(cls, new PerRequestResourceProvider(cls)); } } } // we can get either a provider or resource class here for (Object o : singletons) { if (isValidProvider(o.getClass())) { providers.add(o); } else if (o instanceof Feature) { features.add((Feature) o); } else { resourceClasses.add(o.getClass()); map.put(o.getClass(), new SingletonResourceProvider(o)); } } JAXRSServerFactoryBean bean = new JAXRSServerFactoryBean(); String address = "/"; if (!ignoreAppPath) { ApplicationPath appPath = app.getClass().getAnnotation(ApplicationPath.class); if (appPath != null) { address = appPath.value(); } } if (!address.startsWith("/")) { address = "/" + address; } bean.setAddress(address); bean.setStaticSubresourceResolution(staticSubresourceResolution); bean.setResourceClasses(resourceClasses); bean.setProviders(providers); bean.setFeatures(features); for (Map.Entry<Class<?>, ResourceProvider> entry : map.entrySet()) { bean.setResourceProvider(entry.getKey(), entry.getValue()); } Map<String, Object> appProps = app.getProperties(); if (appProps != null) { bean.getProperties(true).putAll(appProps); } bean.setApplication(app); return bean; } public static Object createProviderInstance(Class<?> cls) { try { Constructor<?> c = ResourceUtils.findResourceConstructor(cls, false); if (c.getParameterTypes().length == 0) { return c.newInstance(); } else { return c; } } catch (Throwable ex) { throw new RuntimeException("Provider " + cls.getName() + " can not be created", ex); } } public static Feature createFeatureInstance(Class<? extends Feature> cls) { try { Constructor<?> c = ResourceUtils.findResourceConstructor(cls, false); if (c == null) { throw new RuntimeException("No valid constructor found for " + cls.getName()); } return (Feature) c.newInstance(); } catch (Throwable ex) { throw new RuntimeException("Feature " + cls.getName() + " can not be created", ex); } } private static boolean isValidProvider(Class<?> c) { if (c == null || c == Object.class) { return false; } if (c.getAnnotation(Provider.class) != null) { return true; } for (Class<?> itf : c.getInterfaces()) { if (SERVER_PROVIDER_CLASS_NAMES.contains(itf.getName())) { return true; } } return isValidProvider(c.getSuperclass()); } private static void verifySingletons(Set<Object> singletons) { if (singletons.isEmpty()) { return; } Set<String> map = new HashSet<String>(); for (Object s : singletons) { if (map.contains(s.getClass().getName())) { throw new RuntimeException( "More than one instance of the same singleton class " + s.getClass().getName() + " is available"); } else { map.add(s.getClass().getName()); } } } public static boolean isValidResourceClass(Class<?> c) { if (c.isInterface() || Modifier.isAbstract(c.getModifiers())) { LOG.info("Ignoring invalid resource class " + c.getName()); return false; } return true; } private static boolean isValidApplicationClass(Class<?> c, Set<Object> singletons) { if (!isValidResourceClass(c)) { return false; } for (Object s : singletons) { if (c == s.getClass()) { LOG.info( "Ignoring per-request resource class " + c.getName() + " as it is also registered as singleton"); return false; } } return true; } // TODO : consider moving JAXBDataBinding.createContext to JAXBUtils public static JAXBContext createJaxbContext( Set<Class<?>> classes, Class<?>[] extraClass, Map<String, Object> contextProperties) { if (classes == null || classes.isEmpty()) { return null; } JAXBUtils.scanPackages(classes, extraClass, null); JAXBContext ctx; try { ctx = JAXBContext.newInstance(classes.toArray(new Class[classes.size()]), contextProperties); return ctx; } catch (JAXBException ex) { LOG.log(Level.WARNING, "No JAXB context can be created", ex); } return null; } }
public class TemporaryCredentialServiceTest extends AbstractBusClientServerTestBase { public static final String TEMPORARY_CREDENTIALS_URL = "/a/oauth/initiate"; public static final String HOST = "http://localhost:"; private static final Logger LOG = LogUtils.getL7dLogger(TemporaryCredentialServiceTest.class); @BeforeClass public static void startServers() throws Exception { assertTrue("server did not launch correctly", launchServer(OAuthServer.class, true)); } @Test public void testGetTemporaryCredentialsURIQuery() throws Exception { Map<String, String> parameters = new HashMap<String, String>(); parameters.put(OAuth.OAUTH_CALLBACK, OAuthTestUtils.CALLBACK); // check all parameter transmissions for (ParameterStyle style : ParameterStyle.values()) { // for all signing methods for (String signMethod : OAuthTestUtils.SIGN_METHOD) { LOG.log( Level.INFO, "Preparing request with parameter style: {0} and signature method: {1}", new String[] {style.toString(), signMethod}); parameters.put(OAuth.OAUTH_SIGNATURE_METHOD, signMethod); parameters.put(OAuth.OAUTH_NONCE, UUID.randomUUID().toString()); parameters.put(OAuth.OAUTH_TIMESTAMP, String.valueOf(System.currentTimeMillis() / 1000)); parameters.put(OAuth.OAUTH_CONSUMER_KEY, OAuthTestUtils.CLIENT_ID); OAuthMessage message = invokeRequestToken(parameters, style, OAuthServer.PORT); // test response ok boolean isFormEncoded = OAuth.isFormEncoded(message.getBodyType()); Assert.assertTrue(isFormEncoded); List<OAuth.Parameter> responseParams = OAuthTestUtils.getResponseParams(message); String wwwHeader = message.getHeader("Authenticate"); Assert.assertNull(wwwHeader); String callbacConf = OAuthTestUtils.findOAuthParameter(responseParams, OAuth.OAUTH_CALLBACK_CONFIRMED) .getValue(); Assert.assertEquals("true", callbacConf); String oauthToken = OAuthTestUtils.findOAuthParameter(responseParams, OAuth.OAUTH_TOKEN).getKey(); Assert.assertFalse(StringUtils.isEmpty(oauthToken)); String tokenSecret = OAuthTestUtils.findOAuthParameter(responseParams, OAuth.OAUTH_TOKEN_SECRET).getKey(); Assert.assertFalse(StringUtils.isEmpty(tokenSecret)); // test wrong client id parameters.put(OAuth.OAUTH_CONSUMER_KEY, "wrong"); message = invokeRequestToken(parameters, style, OAuthServer.PORT); String response = message.getHeader("oauth_problem"); Assert.assertEquals(OAuth.Problems.CONSUMER_KEY_UNKNOWN, response); } } } protected OAuthMessage invokeRequestToken( Map<String, String> parameters, ParameterStyle style, int port) throws IOException, URISyntaxException, OAuthException { OAuthMessage message; String uri = HOST + port + TEMPORARY_CREDENTIALS_URL; message = OAuthTestUtils.access(uri, OAuthMessage.POST, parameters, style); return message; } }
public class JaxWsClientProxy extends org.apache.cxf.frontend.ClientProxy implements InvocationHandler, BindingProvider { public static final String THREAD_LOCAL_REQUEST_CONTEXT = "thread.local.request.context"; private static final Logger LOG = LogUtils.getL7dLogger(JaxWsClientProxy.class); private final Binding binding; private final EndpointReferenceBuilder builder; public JaxWsClientProxy(Client c, Binding b) { super(c); this.binding = b; setupEndpointAddressContext(getClient().getEndpoint()); this.builder = new EndpointReferenceBuilder((JaxWsEndpointImpl) getClient().getEndpoint()); } private void setupEndpointAddressContext(Endpoint endpoint) { // NOTE for jms transport the address would be null if (null != endpoint && null != endpoint.getEndpointInfo().getAddress()) { getRequestContext() .put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY, endpoint.getEndpointInfo().getAddress()); } } public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { Endpoint endpoint = getClient().getEndpoint(); String address = endpoint.getEndpointInfo().getAddress(); MethodDispatcher dispatcher = (MethodDispatcher) endpoint.getService().get(MethodDispatcher.class.getName()); Object[] params = args; if (null == params) { params = new Object[0]; } BindingOperationInfo oi = dispatcher.getBindingOperation(method, endpoint); if (oi == null) { // check for method on BindingProvider and Object if (method.getDeclaringClass().equals(BindingProvider.class) || method.getDeclaringClass().equals(Object.class)) { try { return method.invoke(this, params); } catch (InvocationTargetException e) { throw e.fillInStackTrace().getCause(); } } Message msg = new Message("NO_BINDING_OPERATION_INFO", LOG, method.getName()); throw new WebServiceException(msg.toString()); } client.getRequestContext().put(Method.class.getName(), method); boolean isAsync = isAsync(method); Object result = null; try { if (isAsync) { result = invokeAsync(method, oi, params); } else { result = invokeSync(method, oi, params); } } catch (WebServiceException wex) { throw wex.fillInStackTrace(); } catch (Exception ex) { for (Class<?> excls : method.getExceptionTypes()) { if (excls.isInstance(ex)) { throw ex.fillInStackTrace(); } } if (getBinding() instanceof HTTPBinding) { HTTPException exception = new HTTPException(HttpURLConnection.HTTP_INTERNAL_ERROR); exception.initCause(ex); throw exception; } else if (getBinding() instanceof SOAPBinding) { SOAPFault soapFault = createSoapFault((SOAPBinding) getBinding(), ex); if (soapFault == null) { throw new WebServiceException(ex); } SOAPFaultException exception = new SOAPFaultException(soapFault); if (ex instanceof Fault && ex.getCause() != null) { exception.initCause(ex.getCause()); } else { exception.initCause(ex); } throw exception; } else { throw new WebServiceException(ex); } } finally { if (addressChanged(address)) { setupEndpointAddressContext(getClient().getEndpoint()); } } Map<String, Object> respContext = client.getResponseContext(); Map<String, Scope> scopes = CastUtils.cast((Map<?, ?>) respContext.get(WrappedMessageContext.SCOPES)); if (scopes != null) { for (Map.Entry<String, Scope> scope : scopes.entrySet()) { if (scope.getValue() == Scope.HANDLER) { respContext.remove(scope.getKey()); } } } return result; } boolean isAsync(Method m) { return m.getName().endsWith("Async") && (Future.class.equals(m.getReturnType()) || Response.class.equals(m.getReturnType())); } static SOAPFault createSoapFault(SOAPBinding binding, Exception ex) throws SOAPException { SOAPFault soapFault; try { soapFault = binding.getSOAPFactory().createFault(); } catch (Throwable t) { // probably an old version of saaj or something that is not allowing createFault // method to work. Try the saaj 1.2 method of doing this. try { soapFault = binding.getMessageFactory().createMessage().getSOAPBody().addFault(); } catch (Throwable t2) { // still didn't work, we'll just throw what we have return null; } } if (ex instanceof SoapFault) { if (!soapFault.getNamespaceURI().equals(((SoapFault) ex).getFaultCode().getNamespaceURI()) && SOAPConstants.URI_NS_SOAP_1_1_ENVELOPE.equals( ((SoapFault) ex).getFaultCode().getNamespaceURI())) { // change to 1.1 try { soapFault = SOAPFactory.newInstance().createFault(); } catch (Throwable t) { // ignore } } soapFault.setFaultString(((SoapFault) ex).getReason()); soapFault.setFaultCode(((SoapFault) ex).getFaultCode()); soapFault.setFaultActor(((SoapFault) ex).getRole()); Node nd = soapFault.getOwnerDocument().importNode(((SoapFault) ex).getOrCreateDetail(), true); nd = nd.getFirstChild(); soapFault.addDetail(); while (nd != null) { Node next = nd.getNextSibling(); soapFault.getDetail().appendChild(nd); nd = next; } } else { String msg = ex.getMessage(); if (msg != null) { soapFault.setFaultString(msg); } } return soapFault; } private boolean addressChanged(String address) { return !(address == null || getClient().getEndpoint().getEndpointInfo() == null || address.equals(getClient().getEndpoint().getEndpointInfo().getAddress())); } @SuppressWarnings("unchecked") private Object invokeAsync(Method method, BindingOperationInfo oi, Object[] params) throws Exception { client.setExecutor(getClient().getEndpoint().getExecutor()); AsyncHandler<Object> handler; if (params.length > 0 && params[params.length - 1] instanceof AsyncHandler) { handler = (AsyncHandler) params[params.length - 1]; } else { handler = null; } ClientCallback callback = new JaxwsClientCallback(handler); Response<Object> ret = new JaxwsResponseCallback(callback); client.invoke(callback, oi, params); return ret; } public Map<String, Object> getRequestContext() { return new WrappedMessageContext(this.getClient().getRequestContext(), null, Scope.APPLICATION); } public Map<String, Object> getResponseContext() { return new WrappedMessageContext( this.getClient().getResponseContext(), null, Scope.APPLICATION); } public Binding getBinding() { return binding; } public EndpointReference getEndpointReference() { return builder.getEndpointReference(); } public <T extends EndpointReference> T getEndpointReference(Class<T> clazz) { return builder.getEndpointReference(clazz); } }
public class WebSocketVirtualServletResponse implements HttpServletResponse { private static final Logger LOG = LogUtils.getL7dLogger(WebSocketVirtualServletResponse.class); private WebSocketServletHolder webSocketHolder; private Map<String, String> responseHeaders; private ServletOutputStream outputStream; public WebSocketVirtualServletResponse(WebSocketServletHolder websocket) { this.webSocketHolder = websocket; this.responseHeaders = new TreeMap<String, String>(String.CASE_INSENSITIVE_ORDER); this.outputStream = createOutputStream(); } @Override public void flushBuffer() throws IOException { LOG.log(Level.FINE, "flushBuffer()"); outputStream.flush(); } @Override public int getBufferSize() { LOG.log(Level.FINE, "getBufferSize()"); return 0; } @Override public String getCharacterEncoding() { LOG.log(Level.FINE, "getCharacterEncoding()"); return null; } @Override public String getContentType() { LOG.log(Level.FINE, "getContentType()"); return responseHeaders.get("Content-Type"); } @Override public Locale getLocale() { LOG.log(Level.FINE, "getLocale"); return null; } @Override public ServletOutputStream getOutputStream() throws IOException { return outputStream; } @Override public PrintWriter getWriter() throws IOException { LOG.log(Level.FINE, "getWriter()"); return new PrintWriter(getOutputStream()); } @Override public boolean isCommitted() { return false; } @Override public void reset() {} @Override public void resetBuffer() { LOG.log(Level.FINE, "resetBuffer()"); } @Override public void setBufferSize(int size) { if (LOG.isLoggable(Level.FINE)) { LOG.log(Level.FINE, "setBufferSize({0})", size); } } @Override public void setCharacterEncoding(String charset) { // TODO if (LOG.isLoggable(Level.FINE)) { LOG.log(Level.FINE, "setCharacterEncoding({0})", charset); } } @Override public void setContentLength(int len) { if (LOG.isLoggable(Level.FINE)) { LOG.log(Level.FINE, "setContentLength({0})", len); } responseHeaders.put("Content-Length", Integer.toString(len)); } @Override public void setContentType(String type) { if (LOG.isLoggable(Level.FINE)) { LOG.log(Level.FINE, "setContentType({0})", type); } responseHeaders.put("Content-Type", type); } @Override public void setLocale(Locale loc) { if (LOG.isLoggable(Level.FINE)) { LOG.log(Level.FINE, "setLocale({0})", loc); } } @Override public void addCookie(Cookie cookie) { if (LOG.isLoggable(Level.FINE)) { LOG.log(Level.FINE, "addCookie({0})", cookie); } } @Override public void addDateHeader(String name, long date) { // TODO if (LOG.isLoggable(Level.FINE)) { LOG.log(Level.FINE, "addDateHeader({0}, {1})", new Object[] {name, date}); } } @Override public void addHeader(String name, String value) { if (LOG.isLoggable(Level.FINE)) { LOG.log(Level.FINE, "addHeader({0}, {1})", new Object[] {name, value}); } responseHeaders.put(name, value); } @Override public void addIntHeader(String name, int value) { if (LOG.isLoggable(Level.FINE)) { LOG.log(Level.FINE, "addIntHeader({0}, {1})", new Object[] {name, value}); } responseHeaders.put(name, Integer.toString(value)); } @Override public boolean containsHeader(String name) { if (LOG.isLoggable(Level.FINE)) { LOG.log(Level.FINE, "containsHeader({0})", name); } return responseHeaders.containsKey(name); } @Override public String encodeRedirectURL(String url) { if (LOG.isLoggable(Level.FINE)) { LOG.log(Level.FINE, "encodeRedirectURL({0})", url); } return null; } @Override public String encodeRedirectUrl(String url) { if (LOG.isLoggable(Level.FINE)) { LOG.log(Level.FINE, "encodeRedirectUrl({0})", url); } return null; } @Override public String encodeURL(String url) { if (LOG.isLoggable(Level.FINE)) { LOG.log(Level.FINE, "encodeURL({0})", url); } return null; } @Override public String encodeUrl(String url) { if (LOG.isLoggable(Level.FINE)) { LOG.log(Level.FINE, "encodeUrl({0})", url); } return null; } @Override public String getHeader(String name) { if (LOG.isLoggable(Level.FINE)) { LOG.log(Level.FINE, "getHeader({0})", name); } return null; } @Override public Collection<String> getHeaderNames() { LOG.log(Level.FINE, "getHeaderNames()"); return null; } @Override public Collection<String> getHeaders(String name) { if (LOG.isLoggable(Level.FINE)) { LOG.log(Level.FINE, "getHeaders({0})", name); } return null; } @Override public int getStatus() { LOG.log(Level.FINE, "getStatus()"); String v = responseHeaders.get(WebSocketUtils.SC_KEY); return v == null ? 200 : Integer.parseInt(v); } @Override public void sendError(int sc) throws IOException { if (LOG.isLoggable(Level.FINE)) { LOG.log(Level.FINE, "sendError{0}", sc); } responseHeaders.put(WebSocketUtils.SC_KEY, Integer.toString(sc)); byte[] data = WebSocketUtils.buildResponse(responseHeaders, null, 0, 0); webSocketHolder.write(data, 0, data.length); } @Override public void sendError(int sc, String msg) throws IOException { if (LOG.isLoggable(Level.FINE)) { LOG.log(Level.FINE, "sendError({0}, {1})", new Object[] {sc, msg}); } responseHeaders.put(WebSocketUtils.SC_KEY, Integer.toString(sc)); responseHeaders.put(WebSocketUtils.SM_KEY, msg); byte[] data = WebSocketUtils.buildResponse(responseHeaders, null, 0, 0); webSocketHolder.write(data, 0, data.length); } @Override public void sendRedirect(String location) throws IOException { if (LOG.isLoggable(Level.FINE)) { LOG.log(Level.FINE, "sendRedirect({0})", location); } } @Override public void setDateHeader(String name, long date) { // ignore if (LOG.isLoggable(Level.FINE)) { LOG.log(Level.FINE, "setDateHeader({0}, {1})", new Object[] {name, date}); } } @Override public void setHeader(String name, String value) { if (LOG.isLoggable(Level.FINE)) { LOG.log(Level.FINE, "setHeader({0}, {1})", new Object[] {name, value}); } responseHeaders.put(name, value); } @Override public void setIntHeader(String name, int value) { if (LOG.isLoggable(Level.FINE)) { LOG.log(Level.FINE, "setIntHeader({0}, {1})", new Object[] {name, value}); } } @Override public void setStatus(int sc) { if (LOG.isLoggable(Level.FINE)) { LOG.log(Level.FINE, "setStatus({0})", sc); } responseHeaders.put(WebSocketUtils.SC_KEY, Integer.toString(sc)); } @Override public void setStatus(int sc, String sm) { if (LOG.isLoggable(Level.FINE)) { LOG.log(Level.FINE, "setStatus({0}, {1})", new Object[] {sc, sm}); } responseHeaders.put(WebSocketUtils.SC_KEY, Integer.toString(sc)); responseHeaders.put(WebSocketUtils.SM_KEY, sm); } private ServletOutputStream createOutputStream() { // REVISIT // This output buffering is needed as the server side websocket does // not support the fragment transmission mode when sending back a large data. // And this buffering is only used for the response for the initial service innovation. // For the subsequently pushed data to the socket are sent back // unbuffered as individual websocket messages. // the things to consider : // - provide a size limit if we are use this buffering // - add a chunking mode in the cxf websocket's binding. return new ServletOutputStream() { private InternalByteArrayOutputStream buffer = new InternalByteArrayOutputStream(); @Override public void write(int b) throws IOException { byte[] data = new byte[1]; data[0] = (byte) b; write(data, 0, 1); } @Override public void write(byte[] data) throws IOException { write(data, 0, data.length); } @Override public void write(byte[] data, int offset, int length) throws IOException { if (responseHeaders.get(WebSocketUtils.FLUSHED_KEY) == null) { // buffer the data until it gets flushed buffer.write(data, offset, length); } else { // unbuffered write to the socket data = WebSocketUtils.buildResponse(data, offset, length); webSocketHolder.write(data, 0, data.length); } } public void close() throws IOException { if (responseHeaders.get(WebSocketUtils.FLUSHED_KEY) == null) { byte[] data = WebSocketUtils.buildResponse(responseHeaders, buffer.getBytes(), 0, buffer.size()); webSocketHolder.write(data, 0, data.length); responseHeaders.put(WebSocketUtils.FLUSHED_KEY, "true"); } super.close(); } }; } private static class InternalByteArrayOutputStream extends ByteArrayOutputStream { public byte[] getBytes() { return buf; } } }
public final class CorbaObjectReferenceHelper { public static final String WSDLI_NAMESPACE_URI = "http://www.w3.org/2006/01/wsdl-instance"; public static final String ADDRESSING_NAMESPACE_URI = "http://www.w3.org/2005/08/addressing"; public static final String ADDRESSING_WSDL_NAMESPACE_URI = "http://www.w3.org/2006/05/addressing/wsdl"; private static final Logger LOG = LogUtils.getL7dLogger(CorbaObjectReferenceHelper.class); private CorbaObjectReferenceHelper() { // utility class } public static String getWSDLLocation(Definition wsdlDef) { return wsdlDef.getDocumentBaseURI(); } public static QName getServiceName(Binding binding, Definition wsdlDef) { LOG.log(Level.FINE, "Getting service name for an object reference"); Collection<Service> services = CastUtils.cast(wsdlDef.getServices().values()); for (Service serv : services) { Collection<Port> ports = CastUtils.cast(serv.getPorts().values()); for (Port pt : ports) { if (pt.getBinding().equals(binding)) { return serv.getQName(); } } } return null; } public static String getEndpointName(Binding binding, Definition wsdlDef) { LOG.log(Level.FINE, "Getting endpoint name for an object reference"); Collection<Service> services = CastUtils.cast(wsdlDef.getServices().values()); for (Service serv : services) { Collection<Port> ports = CastUtils.cast(serv.getPorts().values()); for (Port pt : ports) { if (pt.getBinding().equals(binding)) { return pt.getName(); } } } return null; } public static Binding getDefaultBinding(Object obj, Definition wsdlDef) { LOG.log(Level.FINEST, "Getting binding for a default object reference"); Collection<Binding> bindings = CastUtils.cast(wsdlDef.getBindings().values()); for (Binding b : bindings) { List<?> extElements = b.getExtensibilityElements(); // Get the list of all extensibility elements for (Iterator<?> extIter = extElements.iterator(); extIter.hasNext(); ) { java.lang.Object element = extIter.next(); // Find a binding type so we can check against its repository ID if (element instanceof BindingType) { BindingType type = (BindingType) element; if (obj._is_a(type.getRepositoryID())) { return b; } } } } return null; } public static EprMetaData getBindingForTypeId(String repId, Definition wsdlDef) { LOG.log( Level.FINE, "RepositoryId " + repId + ", wsdl namespace " + wsdlDef.getTargetNamespace()); EprMetaData ret = new EprMetaData(); Collection<Binding> bindings = CastUtils.cast(wsdlDef.getBindings().values()); for (Binding b : bindings) { List<?> extElements = b.getExtensibilityElements(); // Get the list of all extensibility elements for (Iterator<?> extIter = extElements.iterator(); extIter.hasNext(); ) { java.lang.Object element = extIter.next(); // Find a binding type so we can check against its repository ID if (element instanceof BindingType) { BindingType type = (BindingType) element; if (repId.equals(type.getRepositoryID())) { ret.setCandidateWsdlDef(wsdlDef); ret.setBinding(b); return ret; } } } } if (!ret.isValid()) { // recursivly check imports Iterator<?> importLists = wsdlDef.getImports().values().iterator(); while (importLists.hasNext()) { List<?> imports = (List<?>) importLists.next(); for (java.lang.Object imp : imports) { if (imp instanceof Import) { Definition importDef = ((Import) imp).getDefinition(); LOG.log(Level.INFO, "Following import " + importDef.getDocumentBaseURI()); ret = getBindingForTypeId(repId, importDef); if (ret.isValid()) { return ret; } } } } } return ret; } public static String extractTypeIdFromIOR(String url) { String ret = new String(); byte data[] = DatatypeConverter.parseHexBinary(url.substring(4)); if (data.length > 0) { // parse out type_id from IOR CDR encapsulation boolean bigIndian = !(data[0] > 0); int typeIdStringSize = readIntFromAlignedCDREncaps(data, 4, bigIndian); if (typeIdStringSize > 1) { ret = readStringFromAlignedCDREncaps(data, 8, typeIdStringSize - 1); } } return ret; } private static String readStringFromAlignedCDREncaps(byte[] data, int startIndex, int length) { char[] arr = new char[length]; for (int i = 0; i < length; i++) { arr[i] = (char) (data[startIndex + i] & 0xff); } return new String(arr); } public static int readIntFromAlignedCDREncaps(byte[] data, int index, boolean bigEndian) { if (bigEndian) { int partial = ((data[index] << 24) & 0xff000000) | ((data[index + 1] << 16) & 0x00ff0000); return partial | ((data[index + 2] << 8) & 0x0000ff00) | ((data[index + 3]) & 0x000000ff); } else { int partial = ((data[index]) & 0x000000ff) | ((data[index + 1] << 8) & 0x0000ff00); return partial | ((data[index + 2] << 16) & 0x00ff0000) | ((data[index + 3] << 24) & 0xff000000); } } public static void populateEprInfo(EprMetaData info) { if (!info.isValid()) { return; } Binding match = info.getBinding(); Definition wsdlDef = info.getCandidateWsdlDef(); Collection<Service> services = CastUtils.cast(wsdlDef.getServices().values()); for (Service serv : services) { Collection<Port> ports = CastUtils.cast(serv.getPorts().values()); for (Port pt : ports) { if (pt.getBinding().equals(match)) { info.setPortName(pt.getName()); info.setServiceQName(serv.getQName()); break; } } } if (info.getServiceQName() == null) { Iterator<?> importLists = wsdlDef.getImports().values().iterator(); while (info.getServiceQName() == null && importLists.hasNext()) { List<?> imports = (List<?>) importLists.next(); for (java.lang.Object imp : imports) { if (imp instanceof Import) { Definition importDef = ((Import) imp).getDefinition(); LOG.log(Level.FINE, "following wsdl import " + importDef.getDocumentBaseURI()); info.setCandidateWsdlDef(importDef); populateEprInfo(info); if (info.getServiceQName() != null) { break; } } } } } } }
/** * Logical Handler responsible for aggregating the Message Addressing Properties for outgoing * messages. */ public class MAPAggregatorImpl extends MAPAggregator { private static final Logger LOG = LogUtils.getL7dLogger(MAPAggregator.class); private static final ResourceBundle BUNDLE = LOG.getResourceBundle(); private static final ClientLifeCycleListener DECOUPLED_DEST_CLEANER = new ClientLifeCycleListener() { public void clientCreated(Client client) { // ignore } public void clientDestroyed(Client client) { Destination dest = client .getEndpoint() .getEndpointInfo() .getProperty(DECOUPLED_DESTINATION, Destination.class); if (dest != null) { dest.setMessageObserver(null); dest.shutdown(); } } }; /** Constructor. */ public MAPAggregatorImpl() { messageIdCache = new DefaultMessageIdCache(); } public MAPAggregatorImpl(MAPAggregator mag) { this.addressingRequired = mag.isAddressingRequired(); this.messageIdCache = mag.getMessageIdCache(); if (messageIdCache == null) { messageIdCache = new DefaultMessageIdCache(); } this.usingAddressingAdvisory = mag.isUsingAddressingAdvisory(); this.allowDuplicates = mag.allowDuplicates(); this.addressingResponses = mag.getAddressingResponses(); } /** * Invoked for normal processing of inbound and outbound messages. * * @param message the current message */ public void handleMessage(Message message) { if (!MessageUtils.getContextualBoolean(message, ADDRESSING_DISABLED, false)) { mediate(message, ContextUtils.isFault(message)); } else { // addressing is completely disabled manually, we need to assert the // assertions as the user is in control of those AssertionInfoMap aim = message.get(AssertionInfoMap.class); if (null == aim) { return; } QName[] types = new QName[] { MetadataConstants.ADDRESSING_ASSERTION_QNAME, MetadataConstants.USING_ADDRESSING_2004_QNAME, MetadataConstants.USING_ADDRESSING_2005_QNAME, MetadataConstants.USING_ADDRESSING_2006_QNAME, MetadataConstants.ANON_RESPONSES_ASSERTION_QNAME, MetadataConstants.NON_ANON_RESPONSES_ASSERTION_QNAME, MetadataConstants.ANON_RESPONSES_ASSERTION_QNAME_0705, MetadataConstants.NON_ANON_RESPONSES_ASSERTION_QNAME_0705 }; for (QName type : types) { assertAssertion(aim, type); } } } /** * Invoked when unwinding normal interceptor chain when a fault occurred. * * @param message the current message */ public void handleFault(Message message) { message.put(MAPAggregator.class.getName(), this); } /** * Determine if addressing is being used * * @param message the current message * @pre message is outbound */ private boolean usingAddressing(Message message) { boolean ret = true; if (ContextUtils.isRequestor(message)) { if (hasUsingAddressing(message) || hasAddressingAssertion(message) || hasUsingAddressingAssertion(message)) { return true; } if (!usingAddressingAdvisory || !WSAContextUtils.retrieveUsingAddressing(message)) { ret = false; } } else { ret = getMAPs(message, false, false) != null; } return ret; } /** * Determine if the use of addressing is indicated by the presence of a the usingAddressing * attribute. * * @param message the current message * @pre message is outbound * @pre requestor role */ private boolean hasUsingAddressing(Message message) { boolean ret = false; Endpoint endpoint = message.getExchange().getEndpoint(); if (null != endpoint) { Boolean b = (Boolean) endpoint.get(USING_ADDRESSING); if (null == b) { EndpointInfo endpointInfo = endpoint.getEndpointInfo(); List<ExtensibilityElement> endpointExts = endpointInfo != null ? endpointInfo.getExtensors(ExtensibilityElement.class) : null; List<ExtensibilityElement> bindingExts = endpointInfo != null && endpointInfo.getBinding() != null ? endpointInfo.getBinding().getExtensors(ExtensibilityElement.class) : null; List<ExtensibilityElement> serviceExts = endpointInfo != null && endpointInfo.getService() != null ? endpointInfo.getService().getExtensors(ExtensibilityElement.class) : null; ret = hasUsingAddressing(endpointExts) || hasUsingAddressing(bindingExts) || hasUsingAddressing(serviceExts); b = ret ? Boolean.TRUE : Boolean.FALSE; endpoint.put(USING_ADDRESSING, b); } else { ret = b.booleanValue(); } } return ret; } /** * Determine if the use of addressing is indicated by an Addressing assertion in the alternative * chosen for the current message. * * @param message the current message * @pre message is outbound * @pre requestor role */ private boolean hasAddressingAssertion(Message message) { AssertionInfoMap aim = message.get(AssertionInfoMap.class); if (null == aim) { return false; } return null != aim.get(MetadataConstants.ADDRESSING_ASSERTION_QNAME); } /** * Determine if the use of addressing is indicated by a UsingAddressing in the alternative chosen * for the current message. * * @param message the current message * @pre message is outbound * @pre requestor role */ private boolean hasUsingAddressingAssertion(Message message) { AssertionInfoMap aim = message.get(AssertionInfoMap.class); if (null == aim) { return false; } if (null != aim.get(MetadataConstants.USING_ADDRESSING_2004_QNAME)) { return true; } if (null != aim.get(MetadataConstants.USING_ADDRESSING_2005_QNAME)) { return true; } return null != aim.get(MetadataConstants.USING_ADDRESSING_2006_QNAME); } private WSAddressingFeature getWSAddressingFeature(Message message) { if (message.getExchange() != null && message.getExchange().getEndpoint() != null) { Endpoint endpoint = message.getExchange().getEndpoint(); if (endpoint.getActiveFeatures() != null) { for (Feature feature : endpoint.getActiveFeatures()) { if (feature instanceof WSAddressingFeature) { return (WSAddressingFeature) feature; } } } } return null; } /** * If the isRequestor(message) == true and isAddressRequired() == false Assert all the wsa related * assertion to true * * @param message the current message */ private void assertAddressing(Message message) { AssertionInfoMap aim = message.get(AssertionInfoMap.class); if (null == aim) { return; } QName[] types = new QName[] { MetadataConstants.ADDRESSING_ASSERTION_QNAME, MetadataConstants.USING_ADDRESSING_2004_QNAME, MetadataConstants.USING_ADDRESSING_2005_QNAME, MetadataConstants.USING_ADDRESSING_2006_QNAME }; for (QName type : types) { assertAssertion(aim, type); if (type.equals(MetadataConstants.ADDRESSING_ASSERTION_QNAME)) { assertAssertion(aim, MetadataConstants.ANON_RESPONSES_ASSERTION_QNAME); assertAssertion(aim, MetadataConstants.NON_ANON_RESPONSES_ASSERTION_QNAME); } else if (type.equals(MetadataConstants.ADDRESSING_ASSERTION_QNAME_0705)) { assertAssertion(aim, MetadataConstants.ANON_RESPONSES_ASSERTION_QNAME_0705); assertAssertion(aim, MetadataConstants.NON_ANON_RESPONSES_ASSERTION_QNAME_0705); } } } /** * Asserts all Addressing assertions for the current message, regardless their nested Policies. * * @param message the current message */ private void assertAddressing( Message message, EndpointReferenceType replyTo, EndpointReferenceType faultTo) { AssertionInfoMap aim = message.get(AssertionInfoMap.class); if (null == aim) { return; } if (faultTo == null) { faultTo = replyTo; } boolean anonReply = ContextUtils.isGenericAddress(replyTo); boolean anonFault = ContextUtils.isGenericAddress(faultTo); boolean onlyAnonymous = anonReply && anonFault; boolean hasAnonymous = anonReply || anonFault; QName[] types = new QName[] { MetadataConstants.ADDRESSING_ASSERTION_QNAME, MetadataConstants.USING_ADDRESSING_2004_QNAME, MetadataConstants.USING_ADDRESSING_2005_QNAME, MetadataConstants.USING_ADDRESSING_2006_QNAME }; for (QName type : types) { assertAssertion(aim, type); if (type.equals(MetadataConstants.ADDRESSING_ASSERTION_QNAME)) { if (onlyAnonymous) { assertAssertion(aim, MetadataConstants.ANON_RESPONSES_ASSERTION_QNAME); } else if (!hasAnonymous) { assertAssertion(aim, MetadataConstants.NON_ANON_RESPONSES_ASSERTION_QNAME); } } else if (type.equals(MetadataConstants.ADDRESSING_ASSERTION_QNAME_0705)) { if (onlyAnonymous) { assertAssertion(aim, MetadataConstants.ANON_RESPONSES_ASSERTION_QNAME_0705); } else if (!hasAnonymous) { assertAssertion(aim, MetadataConstants.NON_ANON_RESPONSES_ASSERTION_QNAME_0705); } } } if (!MessageUtils.isRequestor(message) && !MessageUtils.isOutbound(message)) { // need to throw an appropriate fault for these Collection<AssertionInfo> aicNonAnon = aim.getAssertionInfo(MetadataConstants.NON_ANON_RESPONSES_ASSERTION_QNAME); Collection<AssertionInfo> aicNonAnon2 = aim.getAssertionInfo(MetadataConstants.NON_ANON_RESPONSES_ASSERTION_QNAME_0705); Collection<AssertionInfo> aicAnon = aim.getAssertionInfo(MetadataConstants.ANON_RESPONSES_ASSERTION_QNAME); Collection<AssertionInfo> aicAnon2 = aim.getAssertionInfo(MetadataConstants.ANON_RESPONSES_ASSERTION_QNAME_0705); boolean hasAnon = (aicAnon != null && !aicAnon.isEmpty()) || (aicAnon2 != null && !aicAnon2.isEmpty()); boolean hasNonAnon = (aicNonAnon != null && !aicNonAnon.isEmpty()) || (aicNonAnon2 != null && !aicNonAnon2.isEmpty()); if (hasAnonymous && hasNonAnon && !hasAnon) { message.put(FaultMode.class, FaultMode.UNCHECKED_APPLICATION_FAULT); if (isSOAP12(message)) { SoapFault soap12Fault = new SoapFault( "Found anonymous address but non-anonymous required", Soap12.getInstance().getSender()); soap12Fault.addSubCode( new QName(Names.WSA_NAMESPACE_NAME, "OnlyNonAnonymousAddressSupported")); throw soap12Fault; } throw new SoapFault( "Found anonymous address but non-anonymous required", new QName(Names.WSA_NAMESPACE_NAME, "OnlyNonAnonymousAddressSupported")); } else if (!onlyAnonymous && !hasNonAnon && hasAnon) { message.put(FaultMode.class, FaultMode.UNCHECKED_APPLICATION_FAULT); if (isSOAP12(message)) { SoapFault soap12Fault = new SoapFault( "Found non-anonymous address but only anonymous supported", Soap12.getInstance().getSender()); soap12Fault.addSubCode( new QName(Names.WSA_NAMESPACE_NAME, "OnlyAnonymousAddressSupported")); throw soap12Fault; } throw new SoapFault( "Found non-anonymous address but only anonymous supported", new QName(Names.WSA_NAMESPACE_NAME, "OnlyAnonymousAddressSupported")); } } } private void assertAssertion(AssertionInfoMap aim, QName type) { Collection<AssertionInfo> aic = aim.getAssertionInfo(type); for (AssertionInfo ai : aic) { ai.setAsserted(true); } } /** * @param exts list of extension elements * @return true iff the UsingAddressing element is found */ private boolean hasUsingAddressing(List<ExtensibilityElement> exts) { boolean found = false; if (exts != null) { Iterator<ExtensibilityElement> extensionElements = exts.iterator(); while (extensionElements.hasNext() && !found) { ExtensibilityElement ext = extensionElements.next(); found = Names.WSAW_USING_ADDRESSING_QNAME.equals(ext.getElementType()); } } return found; } /** * Mediate message flow. * * @param message the current message * @param isFault true if a fault is being mediated * @return true if processing should continue on dispatch path */ protected boolean mediate(Message message, boolean isFault) { boolean continueProcessing = true; if (ContextUtils.isOutbound(message)) { if (usingAddressing(message)) { // request/response MAPs must be aggregated aggregate(message, isFault); } AddressingProperties theMaps = ContextUtils.retrieveMAPs(message, false, ContextUtils.isOutbound(message)); if (null != theMaps) { if (ContextUtils.isRequestor(message)) { assertAddressing(message, theMaps.getReplyTo(), theMaps.getFaultTo()); } else { checkReplyTo(message, theMaps); } } } else if (!ContextUtils.isRequestor(message)) { // responder validates incoming MAPs AddressingProperties maps = getMAPs(message, false, false); // check responses if (maps != null) { checkAddressingResponses(maps.getReplyTo(), maps.getFaultTo()); assertAddressing(message, maps.getReplyTo(), maps.getFaultTo()); } boolean isOneway = message.getExchange().isOneWay(); if (null == maps && !addressingRequired) { return false; } continueProcessing = validateIncomingMAPs(maps, message); if (maps != null) { AddressingProperties theMaps = ContextUtils.retrieveMAPs(message, false, ContextUtils.isOutbound(message)); if (null != theMaps) { assertAddressing(message, theMaps.getReplyTo(), theMaps.getFaultTo()); } if (isOneway || !ContextUtils.isGenericAddress(maps.getReplyTo())) { InternalContextUtils.rebaseResponse(maps.getReplyTo(), maps, message); } if (!isOneway) { if (ContextUtils.isNoneAddress(maps.getReplyTo())) { LOG.warning("Detected NONE value in ReplyTo WSA header for request-respone MEP"); } else { // ensure the inbound MAPs are available in both the full & fault // response messages (used to determine relatesTo etc.) ContextUtils.propogateReceivedMAPs(maps, message.getExchange()); } } } if (continueProcessing) { // any faults thrown from here on can be correlated with this message message.put(FaultMode.class, FaultMode.LOGICAL_RUNTIME_FAULT); } else { // validation failure => dispatch is aborted, response MAPs // must be aggregated // isFault = true; // aggregate(message, isFault); if (isSOAP12(message)) { SoapFault soap12Fault = new SoapFault( ContextUtils.retrieveMAPFaultReason(message), Soap12.getInstance().getSender()); soap12Fault.setSubCode( new QName(Names.WSA_NAMESPACE_NAME, ContextUtils.retrieveMAPFaultName(message))); throw soap12Fault; } throw new SoapFault( ContextUtils.retrieveMAPFaultReason(message), new QName(Names.WSA_NAMESPACE_NAME, ContextUtils.retrieveMAPFaultName(message))); } } else { AddressingProperties theMaps = ContextUtils.retrieveMAPs(message, false, ContextUtils.isOutbound(message)); if (null != theMaps) { assertAddressing(message, theMaps.getReplyTo(), theMaps.getFaultTo()); } // If the wsa policy is enabled , but the client sets the // WSAddressingFeature.isAddressingRequired to false , we need to assert all WSA assertion to // true if (!ContextUtils.isOutbound(message) && ContextUtils.isRequestor(message) && getWSAddressingFeature(message) != null && !getWSAddressingFeature(message).isAddressingRequired()) { assertAddressing(message); } // CXF-3060 :If wsa policy is not enforced, AddressingProperties map is null and // AddressingFeature.isRequired, requestor checks inbound message and throw exception if (null == theMaps && !ContextUtils.isOutbound(message) && ContextUtils.isRequestor(message) && getWSAddressingFeature(message) != null && getWSAddressingFeature(message).isAddressingRequired()) { boolean missingWsaHeader = false; AssertionInfoMap aim = message.get(AssertionInfoMap.class); if (aim == null || aim.size() == 0) { missingWsaHeader = true; } if (aim != null && aim.size() > 0) { missingWsaHeader = true; QName[] types = new QName[] { MetadataConstants.ADDRESSING_ASSERTION_QNAME, MetadataConstants.USING_ADDRESSING_2004_QNAME, MetadataConstants.USING_ADDRESSING_2005_QNAME, MetadataConstants.USING_ADDRESSING_2006_QNAME }; for (QName type : types) { for (AssertionInfo assertInfo : aim.getAssertionInfo(type)) { if (assertInfo.isAsserted()) { missingWsaHeader = false; } } } } if (missingWsaHeader) { throw new SoapFault( "MISSING_ACTION_MESSAGE", BUNDLE, new QName(Names.WSA_NAMESPACE_NAME, Names.HEADER_REQUIRED_NAME)); } } if (MessageUtils.isPartialResponse(message) && message.getExchange().getOutMessage() != null) { // marked as a partial response, let's see if it really is MessageInfo min = message.get(MessageInfo.class); MessageInfo mout = message.getExchange().getOutMessage().get(MessageInfo.class); if (min != null && mout != null && min.getOperation() == mout.getOperation() && message.getContent(List.class) != null) { // the in and out messages are on the same operation // and we were able to get a response for it. message.remove(Message.PARTIAL_RESPONSE_MESSAGE); } } } return continueProcessing; } private void checkAddressingResponses( EndpointReferenceType replyTo, EndpointReferenceType faultTo) { if (this.addressingResponses == WSAddressingFeature.AddressingResponses.ALL) { return; } boolean passed = false; boolean anonReply = ContextUtils.isGenericAddress(replyTo); boolean anonFault = ContextUtils.isGenericAddress(faultTo); boolean isAnonymous = anonReply && anonFault; if (WSAddressingFeature.AddressingResponses.ANONYMOUS == addressingResponses && isAnonymous) { passed = true; } else if (WSAddressingFeature.AddressingResponses.NON_ANONYMOUS == addressingResponses && (!anonReply && (faultTo.getAddress() != null && !anonFault) || !anonReply && faultTo.getAddress() == null)) { passed = true; } if (!passed) { String reason = BUNDLE.getString("INVALID_ADDRESSING_PROPERTY_MESSAGE"); QName detail = WSAddressingFeature.AddressingResponses.ANONYMOUS == addressingResponses ? Names.ONLY_ANONYMOUS_ADDRESS_SUPPORTED_QNAME : Names.ONLY_NONANONYMOUS_ADDRESS_SUPPORTED_QNAME; throw new SoapFault(reason, detail); } } /** * Perform MAP aggregation. * * @param message the current message * @param isFault true if a fault is being mediated */ private void aggregate(Message message, boolean isFault) { boolean isRequestor = ContextUtils.isRequestor(message); AddressingProperties maps = assembleGeneric(message); addRoleSpecific(maps, message, isRequestor, isFault); // outbound property always used to store MAPs, as this handler // aggregates only when either: // a) message really is outbound // b) message is currently inbound, but we are about to abort dispatch // due to an incoming MAPs validation failure, so the dispatch // will shortly traverse the outbound path ContextUtils.storeMAPs(maps, message, true, isRequestor); } /** * Assemble the generic MAPs (for both requests and responses). * * @param message the current message * @return AddressingProperties containing the generic MAPs */ private AddressingProperties assembleGeneric(Message message) { AddressingProperties maps = getMAPs(message, true, true); // MessageID if (maps.getMessageID() == null) { String messageID = ContextUtils.generateUUID(); maps.setMessageID(ContextUtils.getAttributedURI(messageID)); } // Action if (ContextUtils.hasEmptyAction(maps)) { maps.setAction(InternalContextUtils.getAction(message)); if (ContextUtils.hasEmptyAction(maps) && ContextUtils.isOutbound(message)) { maps.setAction(ContextUtils.getAttributedURI(getActionUri(message, true))); } } return maps; } private String getActionFromInputMessage(final OperationInfo operation) { MessageInfo inputMessage = operation.getInput(); if (inputMessage.getExtensionAttributes() != null) { String inputAction = InternalContextUtils.getAction(inputMessage); if (!StringUtils.isEmpty(inputAction)) { return inputAction; } } return null; } private String getActionFromOutputMessage(final OperationInfo operation) { MessageInfo outputMessage = operation.getOutput(); if (outputMessage != null && outputMessage.getExtensionAttributes() != null) { String outputAction = InternalContextUtils.getAction(outputMessage); if (!StringUtils.isEmpty(outputAction)) { return outputAction; } } return null; } private boolean isSameFault(final FaultInfo faultInfo, String faultName) { if (faultInfo.getName() == null || faultName == null) { return false; } String faultInfoName = faultInfo.getName().getLocalPart(); return faultInfoName.equals(faultName) || faultInfoName.equals(StringUtils.uncapitalize(faultName)); } private String getActionBaseUri(final OperationInfo operation) { String interfaceName = operation.getInterface().getName().getLocalPart(); return addPath(operation.getName().getNamespaceURI(), interfaceName); } private String getActionFromFaultMessage(final OperationInfo operation, final String faultName) { if (operation.getFaults() != null) { for (FaultInfo faultInfo : operation.getFaults()) { if (isSameFault(faultInfo, faultName)) { if (faultInfo.getExtensionAttributes() != null) { String faultAction = InternalContextUtils.getAction(faultInfo); if (!StringUtils.isEmpty(faultAction)) { return faultAction; } } return addPath( addPath( addPath(getActionBaseUri(operation), operation.getName().getLocalPart()), "Fault"), faultInfo.getFaultName().getLocalPart()); } } } return addPath( addPath(addPath(getActionBaseUri(operation), operation.getName().getLocalPart()), "Fault"), faultName); } private String getFaultNameFromMessage(final Message message) { Exception e = message.getContent(Exception.class); Throwable cause = e.getCause(); if (cause == null) { cause = e; } if (e instanceof Fault) { WebFault t = cause.getClass().getAnnotation(WebFault.class); if (t != null) { return t.name(); } } return cause.getClass().getSimpleName(); } protected String getActionUri(Message message, boolean checkMessage) { BindingOperationInfo bop = message.getExchange().getBindingOperationInfo(); if (bop == null || Boolean.TRUE.equals(bop.getProperty("operation.is.synthetic"))) { return null; } OperationInfo op = bop.getOperationInfo(); if (op.isUnwrapped()) { op = ((UnwrappedOperationInfo) op).getWrappedOperation(); } String actionUri = null; if (checkMessage) { actionUri = (String) message.get(ContextUtils.ACTION); if (actionUri == null) { actionUri = (String) message.get(SoapBindingConstants.SOAP_ACTION); } } if (actionUri != null) { return actionUri; } String opNamespace = getActionBaseUri(op); boolean inbound = !ContextUtils.isOutbound(message); boolean requestor = ContextUtils.isRequestor(message); boolean inMsg = requestor ^ inbound; if (ContextUtils.isFault(message)) { String faultName = getFaultNameFromMessage(message); actionUri = getActionFromFaultMessage(op, faultName); } else if (inMsg) { String explicitAction = getActionFromInputMessage(op); if (StringUtils.isEmpty(explicitAction)) { SoapOperationInfo soi = InternalContextUtils.getSoapOperationInfo(bop); explicitAction = soi == null ? null : soi.getAction(); } if (!StringUtils.isEmpty(explicitAction)) { actionUri = explicitAction; } else if (null == op.getInputName()) { actionUri = addPath(opNamespace, op.getName().getLocalPart() + "Request"); } else { actionUri = addPath(opNamespace, op.getInputName()); } } else { String explicitAction = getActionFromOutputMessage(op); if (explicitAction != null) { actionUri = explicitAction; } else if (null == op.getOutputName()) { actionUri = addPath(opNamespace, op.getName().getLocalPart() + "Response"); } else { actionUri = addPath(opNamespace, op.getOutputName()); } } return actionUri; } private String getDelimiter(String uri) { if (uri.startsWith("urn")) { return ":"; } return "/"; } private String addPath(String uri, String path) { StringBuilder buffer = new StringBuilder(); buffer.append(uri); String delimiter = getDelimiter(uri); if (!uri.endsWith(delimiter) && !path.startsWith(delimiter)) { buffer.append(delimiter); } buffer.append(path); return buffer.toString(); } /** * Add MAPs which are specific to the requestor or responder role. * * @param maps the MAPs being assembled * @param message the current message * @param isRequestor true iff the current messaging role is that of requestor * @param isFault true if a fault is being mediated */ private void addRoleSpecific( AddressingProperties maps, Message message, boolean isRequestor, boolean isFault) { if (isRequestor) { Exchange exchange = message.getExchange(); // add request-specific MAPs boolean isOneway = exchange.isOneWay(); boolean isOutbound = ContextUtils.isOutbound(message); // To if (maps.getTo() == null) { Conduit conduit = null; if (isOutbound) { conduit = ContextUtils.getConduit(null, message); } String s = (String) message.get(Message.ENDPOINT_ADDRESS); EndpointReferenceType reference = conduit != null ? conduit.getTarget() : ContextUtils.getNoneEndpointReference(); if (conduit != null && !StringUtils.isEmpty(s) && !reference.getAddress().getValue().equals(s)) { EndpointReferenceType ref = new EndpointReferenceType(); AttributedURIType tp = new AttributedURIType(); tp.setValue(s); ref.setAddress(tp); ref.setMetadata(reference.getMetadata()); ref.setReferenceParameters(reference.getReferenceParameters()); ref.getOtherAttributes().putAll(reference.getOtherAttributes()); reference = ref; } maps.setTo(reference); } // ReplyTo, set if null in MAPs or if set to a generic address // (anonymous or none) that may not be appropriate for the // current invocation EndpointReferenceType replyTo = maps.getReplyTo(); if (ContextUtils.isGenericAddress(replyTo)) { replyTo = getReplyTo(message, replyTo); if (replyTo == null || (isOneway && (replyTo == null || replyTo.getAddress() == null || !Names.WSA_NONE_ADDRESS.equals(replyTo.getAddress().getValue())))) { AttributedURIType address = ContextUtils.getAttributedURI( isOneway ? Names.WSA_NONE_ADDRESS : Names.WSA_ANONYMOUS_ADDRESS); replyTo = ContextUtils.WSA_OBJECT_FACTORY.createEndpointReferenceType(); replyTo.setAddress(address); } maps.setReplyTo(replyTo); } // FaultTo if (maps.getFaultTo() == null) { maps.setFaultTo(maps.getReplyTo()); } else if (maps.getFaultTo().getAddress() == null) { maps.setFaultTo(null); } } else { // add response-specific MAPs AddressingProperties inMAPs = getMAPs(message, false, false); maps.exposeAs(inMAPs.getNamespaceURI()); // To taken from ReplyTo or FaultTo in incoming MAPs (depending // on the fault status of the response) if (isFault && inMAPs.getFaultTo() != null) { maps.setTo(inMAPs.getFaultTo()); } else if (maps.getTo() == null && inMAPs.getReplyTo() != null) { maps.setTo(inMAPs.getReplyTo()); } // RelatesTo taken from MessageID in incoming MAPs if (inMAPs.getMessageID() != null && !Boolean.TRUE.equals(message.get(Message.PARTIAL_RESPONSE_MESSAGE))) { String inMessageID = inMAPs.getMessageID().getValue(); maps.setRelatesTo(ContextUtils.getRelatesTo(inMessageID)); } else { maps.setRelatesTo(ContextUtils.getRelatesTo(Names.WSA_UNSPECIFIED_RELATIONSHIP)); } // fallback fault action if (isFault && maps.getAction() == null) { maps.setAction(ContextUtils.getAttributedURI(Names.WSA_DEFAULT_FAULT_ACTION)); } if (isFault && !ContextUtils.isGenericAddress(inMAPs.getFaultTo())) { Message m = message.getExchange().getInFaultMessage(); if (m == null) { m = message; } InternalContextUtils.rebaseResponse(inMAPs.getFaultTo(), inMAPs, m); Destination destination = InternalContextUtils.createDecoupledDestination(m.getExchange(), inMAPs.getFaultTo()); m.getExchange().setDestination(destination); } } } private EndpointReferenceType getReplyTo(Message message, EndpointReferenceType originalReplyTo) { Exchange exchange = message.getExchange(); Endpoint info = exchange.getEndpoint(); if (info == null) { return originalReplyTo; } synchronized (info) { EndpointInfo ei = info.getEndpointInfo(); Destination dest = ei.getProperty(DECOUPLED_DESTINATION, Destination.class); if (dest == null) { dest = createDecoupledDestination(message); if (dest != null) { info.getEndpointInfo().setProperty(DECOUPLED_DESTINATION, dest); } } if (dest != null) { // if the decoupled endpoint context prop is set and the address is relative, return the // absolute url. final String replyTo = dest.getAddress().getAddress().getValue(); if (replyTo.startsWith("/")) { String debase = (String) message.getContextualProperty(WSAContextUtils.DECOUPLED_ENDPOINT_BASE_PROPERTY); if (debase != null) { return EndpointReferenceUtils.getEndpointReference(debase + replyTo); } } return dest.getAddress(); } } return originalReplyTo; } private Destination createDecoupledDestination(Message message) { String replyToAddress = (String) message.getContextualProperty(WSAContextUtils.REPLYTO_PROPERTY); if (replyToAddress != null) { return setUpDecoupledDestination(message.getExchange().getBus(), replyToAddress, message); } return null; } /** Set up the decoupled Destination if necessary. */ private Destination setUpDecoupledDestination(Bus bus, String replyToAddress, Message message) { EndpointReferenceType reference = EndpointReferenceUtils.getEndpointReference(replyToAddress); if (reference != null) { String decoupledAddress = reference.getAddress().getValue(); LOG.info("creating decoupled endpoint: " + decoupledAddress); try { Destination dest = getDestination(bus, replyToAddress, message); bus.getExtension(ClientLifeCycleManager.class).registerListener(DECOUPLED_DEST_CLEANER); return dest; } catch (Exception e) { // REVISIT move message to localizable Messages.properties LOG.log(Level.WARNING, "decoupled endpoint creation failed: ", e); } } return null; } /** * @param address the address * @return a Destination for the address */ private Destination getDestination(Bus bus, String address, Message message) throws IOException { Destination destination = null; DestinationFactoryManager factoryManager = bus.getExtension(DestinationFactoryManager.class); DestinationFactory factory = factoryManager.getDestinationFactoryForUri(address); if (factory != null) { Endpoint ep = message.getExchange().getEndpoint(); EndpointInfo ei = new EndpointInfo(); ei.setName( new QName( ep.getEndpointInfo().getName().getNamespaceURI(), ep.getEndpointInfo().getName().getLocalPart() + ".decoupled")); ei.setAddress(address); destination = factory.getDestination(ei, bus); Conduit conduit = ContextUtils.getConduit(null, message); if (conduit != null) { MessageObserver ob = ((Observable) conduit).getMessageObserver(); ob = new InterposedMessageObserver(bus, ob); destination.setMessageObserver(ob); } } return destination; } protected static class InterposedMessageObserver implements MessageObserver { Bus bus; MessageObserver observer; public InterposedMessageObserver(Bus b, MessageObserver o) { bus = b; observer = o; } /** * Called for an incoming message. * * @param inMessage */ public void onMessage(Message inMessage) { // disposable exchange, swapped with real Exchange on correlation inMessage.setExchange(new ExchangeImpl()); inMessage.getExchange().put(Bus.class, bus); inMessage.put(Message.DECOUPLED_CHANNEL_MESSAGE, Boolean.TRUE); inMessage.put(Message.RESPONSE_CODE, HttpURLConnection.HTTP_OK); // remove server-specific properties // inMessage.remove(AbstractHTTPDestination.HTTP_REQUEST); // inMessage.remove(AbstractHTTPDestination.HTTP_RESPONSE); inMessage.remove(Message.ASYNC_POST_RESPONSE_DISPATCH); updateResponseCode(inMessage); // cache this inputstream since it's defer to use in case of async try { InputStream in = inMessage.getContent(InputStream.class); if (in != null) { CachedOutputStream cos = new CachedOutputStream(); IOUtils.copy(in, cos); inMessage.setContent(InputStream.class, cos.getInputStream()); } observer.onMessage(inMessage); } catch (IOException e) { e.printStackTrace(); } } private void updateResponseCode(Message message) { Object o = message.get("HTTP.RESPONSE"); if (o != null) { try { o.getClass() .getMethod("setStatus", Integer.TYPE) .invoke(o, HttpURLConnection.HTTP_ACCEPTED); } catch (Throwable t) { // ignore } } } } /** * Get the starting point MAPs (either empty or those set explicitly by the application on the * binding provider request context). * * @param message the current message * @param isProviderContext true if the binding provider request context available to the client * application as opposed to the message context visible to handlers * @param isOutbound true iff the message is outbound * @return AddressingProperties retrieved MAPs */ private AddressingProperties getMAPs( Message message, boolean isProviderContext, boolean isOutbound) { AddressingProperties maps = null; maps = ContextUtils.retrieveMAPs(message, isProviderContext, isOutbound); LOG.log(Level.FINE, "MAPs retrieved from message {0}", maps); if (maps == null && isProviderContext) { maps = new AddressingProperties(); setupNamespace(maps, message); } return maps; } private void setupNamespace(AddressingProperties maps, Message message) { AssertionInfoMap aim = message.get(AssertionInfoMap.class); if (null == aim) { return; } Collection<AssertionInfo> aic = aim.getAssertionInfo(MetadataConstants.USING_ADDRESSING_2004_QNAME); if (aic != null && !aic.isEmpty()) { maps.exposeAs(Names200408.WSA_NAMESPACE_NAME); } } /** * Validate incoming MAPs * * @param maps the incoming MAPs * @param message the current message * @return true if incoming MAPs are valid * @pre inbound message, not requestor */ private boolean validateIncomingMAPs(AddressingProperties maps, Message message) { boolean valid = true; if (maps != null) { // WSAB spec, section 4.2 validation (SOAPAction must match action String sa = SoapActionInInterceptor.getSoapAction(message); String s1 = this.getActionUri(message, false); if (maps.getAction() == null || maps.getAction().getValue() == null) { String reason = BUNDLE.getString("MISSING_ACTION_MESSAGE"); ContextUtils.storeMAPFaultName(Names.HEADER_REQUIRED_NAME, message); ContextUtils.storeMAPFaultReason(reason, message); valid = false; } if (!StringUtils.isEmpty(sa) && valid && !MessageUtils.isTrue(message.get(MAPAggregator.ACTION_VERIFIED))) { if (sa.startsWith("\"")) { sa = sa.substring(1, sa.lastIndexOf('"')); } String action = maps.getAction() == null ? "" : maps.getAction().getValue(); if (!StringUtils.isEmpty(sa) && !sa.equals(action)) { // don't match, must send fault back.... String reason = BUNDLE.getString("INVALID_ADDRESSING_PROPERTY_MESSAGE"); ContextUtils.storeMAPFaultName(Names.ACTION_MISMATCH_NAME, message); ContextUtils.storeMAPFaultReason(reason, message); valid = false; } else if (!StringUtils.isEmpty(s1) && !action.equals(s1) && !action.equals(s1 + "Request") && !s1.equals(action + "Request")) { // if java first, it's likely to have "Request", if wsdl first, // it will depend if the wsdl:input has a name or not. Thus, we'll // check both plain and with the "Request" trailer // doesn't match what's in the wsdl/annotations String reason = BundleUtils.getFormattedString(BUNDLE, "ACTION_NOT_SUPPORTED_MSG", action); ContextUtils.storeMAPFaultName(Names.ACTION_NOT_SUPPORTED_NAME, message); ContextUtils.storeMAPFaultReason(reason, message); valid = false; } } AttributedURIType messageID = maps.getMessageID(); if (!message.getExchange().isOneWay() && (messageID == null || messageID.getValue() == null) && valid) { String reason = BUNDLE.getString("MISSING_ACTION_MESSAGE"); ContextUtils.storeMAPFaultName(Names.HEADER_REQUIRED_NAME, message); ContextUtils.storeMAPFaultReason(reason, message); valid = false; } // Always cache message IDs, even when the message is not valid for some // other reason. if (!allowDuplicates && messageID != null && messageID.getValue() != null && !messageIdCache.checkUniquenessAndCacheId(messageID.getValue())) { LOG.log(Level.WARNING, "DUPLICATE_MESSAGE_ID_MSG", messageID.getValue()); // Only throw the fault if something else has not already marked the // message as invalid. if (valid) { String reason = BUNDLE.getString("DUPLICATE_MESSAGE_ID_MSG"); String l7dReason = MessageFormat.format(reason, messageID.getValue()); ContextUtils.storeMAPFaultName(Names.DUPLICATE_MESSAGE_ID_NAME, message); ContextUtils.storeMAPFaultReason(l7dReason, message); } valid = false; } } else if (usingAddressingAdvisory) { String reason = BUNDLE.getString("MISSING_ACTION_MESSAGE"); ContextUtils.storeMAPFaultName(Names.HEADER_REQUIRED_NAME, message); ContextUtils.storeMAPFaultReason(reason, message); valid = false; } if (Names.INVALID_CARDINALITY_NAME.equals(ContextUtils.retrieveMAPFaultName(message))) { valid = false; } return valid; } /** * Check for NONE ReplyTo value in request-response MEP * * @param message the current message * @param maps the incoming MAPs */ private void checkReplyTo(Message message, AddressingProperties maps) { // if ReplyTo address is none then 202 response status is expected // However returning a fault is more appropriate for request-response MEP if (!message.getExchange().isOneWay() && !MessageUtils.isPartialResponse(message) && ContextUtils.isNoneAddress(maps.getReplyTo())) { String reason = MessageFormat.format( BUNDLE.getString("REPLYTO_NOT_SUPPORTED_MSG"), maps.getReplyTo().getAddress().getValue()); throw new SoapFault(reason, new QName(Names.WSA_NAMESPACE_NAME, Names.WSA_NONE_ADDRESS)); } } private boolean isSOAP12(Message message) { if (message.getExchange().getBinding() instanceof SoapBinding) { SoapBinding binding = (SoapBinding) message.getExchange().getBinding(); if (binding.getSoapVersion() == Soap12.getInstance()) { return true; } } return false; } }
/** * Test client to do websocket calls. * * @see JAXRSClientServerWebSocketTest * <p>we may put this in test-tools so that other systests can use this code. for now keep it * here to experiment jaxrs websocket scenarios. */ class WebSocketTestClient { private static final Logger LOG = LogUtils.getL7dLogger(WebSocketTestClient.class); private List<Object> received; private List<Object> fragments; private CountDownLatch latch; private AsyncHttpClient client; private WebSocket websocket; private String url; public WebSocketTestClient(String url) { this.received = new ArrayList<Object>(); this.fragments = new ArrayList<Object>(); this.latch = new CountDownLatch(1); this.client = new AsyncHttpClient(); this.url = url; } public void connect() throws InterruptedException, ExecutionException, IOException { websocket = client .prepareGet(url) .execute( new WebSocketUpgradeHandler.Builder() .addWebSocketListener(new WsSocketListener()) .build()) .get(); } public void sendTextMessage(String message) { websocket.sendTextMessage(message); } public void sendMessage(byte[] message) { websocket.sendMessage(message); } public boolean await(int secs) throws InterruptedException { return latch.await(secs, TimeUnit.SECONDS); } public void reset(int count) { latch = new CountDownLatch(count); received.clear(); } public List<Object> getReceived() { return received; } public List<Response> getReceivedResponses() { Object[] objs = received.toArray(); List<Response> responses = new ArrayList<Response>(objs.length); for (Object o : objs) { responses.add(new Response(o)); } return responses; } public void close() { websocket.close(); client.close(); } class WsSocketListener implements WebSocketTextListener, WebSocketByteListener { public void onOpen(WebSocket ws) { LOG.info("[ws] opened"); } public void onClose(WebSocket ws) { LOG.info("[ws] closed"); } public void onError(Throwable t) { LOG.info("[ws] error: " + t); } public void onMessage(byte[] message) { received.add(message); LOG.info("[ws] received bytes --> " + makeString(message)); latch.countDown(); } public void onFragment(byte[] fragment, boolean last) { processFragments(fragment, last); } public void onMessage(String message) { received.add(message); LOG.info("[ws] received --> " + message); latch.countDown(); } public void onFragment(String fragment, boolean last) { processFragments(fragment, last); } private void processFragments(Object f, boolean last) { synchronized (fragments) { fragments.add(f); if (last) { if (f instanceof String) { // string StringBuilder sb = new StringBuilder(); for (Iterator<Object> it = fragments.iterator(); it.hasNext(); ) { Object o = it.next(); if (o instanceof String) { sb.append((String) o); it.remove(); } } received.add(sb.toString()); } else { // byte[] ByteArrayOutputStream bao = new ByteArrayOutputStream(); for (Iterator<Object> it = fragments.iterator(); it.hasNext(); ) { Object o = it.next(); if (o instanceof byte[]) { bao.write((byte[]) o, 0, ((byte[]) o).length); it.remove(); } } received.add(bao.toByteArray()); } } } } } private static String makeString(byte[] data) { return data == null ? null : makeString(data, 0, data.length).toString(); } private static StringBuilder makeString(byte[] data, int offset, int length) { if (data.length > 256) { return makeString(data, offset, 256).append("..."); } StringBuilder xbuf = new StringBuilder().append("\nHEX: "); StringBuilder cbuf = new StringBuilder().append("\nASC: "); for (byte b : data) { writeHex(xbuf, 0xff & b); writePrintable(cbuf, 0xff & b); } return xbuf.append(cbuf); } private static void writeHex(StringBuilder buf, int b) { buf.append(Integer.toHexString(0x100 | (0xff & b)).substring(1)).append(' '); } private static void writePrintable(StringBuilder buf, int b) { if (b == 0x0d) { buf.append("\\r"); } else if (b == 0x0a) { buf.append("\\n"); } else if (b == 0x09) { buf.append("\\t"); } else if ((0x80 & b) != 0) { buf.append('.').append(' '); } else { buf.append((char) b).append(' '); } buf.append(' '); } // TODO this is a temporary way to verify the response; we should come up with something better. public static class Response { private Object data; private int pos; private int statusCode; private String contentType; private Object entity; public Response(Object data) { this.data = data; String line; boolean first = true; while ((line = readLine()) != null) { if (first && isStatusCode(line)) { statusCode = Integer.parseInt(line); continue; } else { first = false; } int del = line.indexOf(':'); String h = line.substring(0, del).trim(); String v = line.substring(del + 1).trim(); if ("Content-Type".equalsIgnoreCase(h)) { contentType = v; } } if (data instanceof String) { entity = ((String) data).substring(pos); } else if (data instanceof byte[]) { entity = new byte[((byte[]) data).length - pos]; System.arraycopy((byte[]) data, pos, (byte[]) entity, 0, ((byte[]) entity).length); } } private static boolean isStatusCode(String line) { char c = line.charAt(0); return '0' <= c && c <= '9'; } public int getStatusCode() { return statusCode; } public String getContentType() { return contentType; } @SuppressWarnings("unused") public Object getEntity() { return entity; } public String getTextEntity() { return gettext(entity); } public String toString() { StringBuilder sb = new StringBuilder(); sb.append("Status: ").append(statusCode).append("\r\n"); sb.append("Type: ").append(contentType).append("\r\n"); sb.append("Entity: ").append(gettext(entity)).append("\r\n"); return sb.toString(); } private String readLine() { StringBuilder sb = new StringBuilder(); while (pos < length(data)) { int c = getchar(data, pos++); if (c == '\n') { break; } else if (c == '\r') { continue; } else { sb.append((char) c); } } if (sb.length() == 0) { return null; } return sb.toString(); } private int length(Object o) { return o instanceof char[] ? ((String) o).length() : (o instanceof byte[] ? ((byte[]) o).length : 0); } private int getchar(Object o, int p) { return 0xff & (o instanceof String ? ((String) o).charAt(p) : (o instanceof byte[] ? ((byte[]) o)[p] : -1)); } private String gettext(Object o) { return o instanceof String ? (String) o : (o instanceof byte[] ? new String((byte[]) o) : null); } } }