001 /** 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017 package org.apache.camel.component.restlet; 018 019 import java.io.PrintWriter; 020 import java.io.StringWriter; 021 import java.util.Map; 022 023 import javax.xml.transform.dom.DOMSource; 024 025 import org.apache.camel.Exchange; 026 import org.apache.camel.Message; 027 import org.apache.camel.RuntimeCamelException; 028 import org.apache.camel.converter.jaxp.StringSource; 029 import org.apache.camel.spi.HeaderFilterStrategy; 030 import org.apache.camel.spi.HeaderFilterStrategyAware; 031 import org.apache.commons.logging.Log; 032 import org.apache.commons.logging.LogFactory; 033 import org.restlet.data.ChallengeResponse; 034 import org.restlet.data.ChallengeScheme; 035 import org.restlet.data.CharacterSet; 036 import org.restlet.data.Form; 037 import org.restlet.data.MediaType; 038 import org.restlet.data.Request; 039 import org.restlet.data.Response; 040 import org.restlet.data.Status; 041 042 /** 043 * Default Restlet binding implementation 044 * 045 * @version $Revision: 799086 $ 046 */ 047 public class DefaultRestletBinding implements RestletBinding, HeaderFilterStrategyAware { 048 private static final Log LOG = LogFactory.getLog(DefaultRestletBinding.class); 049 private HeaderFilterStrategy headerFilterStrategy; 050 051 public void populateExchangeFromRestletRequest(Request request, Exchange exchange) throws Exception { 052 Message inMessage = exchange.getIn(); 053 054 // extract headers from restlet 055 for (Map.Entry<String, Object> entry : request.getAttributes().entrySet()) { 056 if (!headerFilterStrategy.applyFilterToExternalHeaders(entry.getKey(), entry.getValue(), exchange)) { 057 inMessage.setHeader(entry.getKey(), entry.getValue()); 058 if (LOG.isDebugEnabled()) { 059 LOG.debug("Populate exchange from Restlet request header: " 060 + entry.getKey() + " value: " + entry.getValue()); 061 } 062 } 063 } 064 065 // copy query string to header 066 String query = request.getResourceRef().getQuery(); 067 if (query != null) { 068 inMessage.setHeader(Exchange.HTTP_QUERY, query); 069 } 070 071 // copy URI to header 072 inMessage.setHeader(Exchange.HTTP_URI, request.getResourceRef().getIdentifier(true)); 073 074 // copy HTTP method to header 075 inMessage.setHeader(Exchange.HTTP_METHOD, request.getMethod().toString()); 076 077 if (!request.isEntityAvailable()) { 078 return; 079 } 080 081 Form form = new Form(request.getEntity()); 082 for (Map.Entry<String, String> entry : form.getValuesMap().entrySet()) { 083 // extract body added to the form as the key which has null value 084 if (entry.getValue() == null) { 085 inMessage.setBody(entry.getKey()); 086 if (LOG.isDebugEnabled()) { 087 LOG.debug("Populate exchange from Restlet request body: " + entry.getValue()); 088 } 089 } else { 090 if (!headerFilterStrategy.applyFilterToExternalHeaders(entry.getKey(), entry.getValue(), exchange)) { 091 inMessage.setHeader(entry.getKey(), entry.getValue()); 092 if (LOG.isDebugEnabled()) { 093 LOG.debug("Populate exchange from Restlet request user header: " 094 + entry.getKey() + " value: " + entry.getValue()); 095 } 096 } 097 } 098 } 099 } 100 101 public void populateRestletRequestFromExchange(Request request, Exchange exchange) { 102 request.setReferrerRef("camel-restlet"); 103 String body = exchange.getIn().getBody(String.class); 104 Form form = new Form(); 105 // add the body as the key in the form with null value 106 form.add(body, null); 107 108 if (LOG.isDebugEnabled()) { 109 LOG.debug("Populate Restlet request from exchange body: " + body); 110 } 111 112 // login and password are filtered by header filter strategy 113 String login = exchange.getIn().getHeader(RestletConstants.RESTLET_LOGIN, String.class); 114 String password = exchange.getIn().getHeader(RestletConstants.RESTLET_PASSWORD, String.class); 115 116 if (login != null && password != null) { 117 ChallengeResponse authentication = new ChallengeResponse(ChallengeScheme.HTTP_BASIC, login, password); 118 request.setChallengeResponse(authentication); 119 if (LOG.isDebugEnabled()) { 120 LOG.debug("Basic HTTP Authentication has been applied"); 121 } 122 } 123 124 for (Map.Entry<String, Object> entry : exchange.getIn().getHeaders().entrySet()) { 125 if (!headerFilterStrategy.applyFilterToCamelHeaders(entry.getKey(), entry.getValue(), exchange)) { 126 if (entry.getKey().startsWith("org.restlet.")) { 127 // put the org.restlet headers in attributes 128 request.getAttributes().put(entry.getKey(), entry.getValue()); 129 } else { 130 // put the user stuff in the form 131 form.add(entry.getKey(), entry.getValue().toString()); 132 } 133 if (LOG.isDebugEnabled()) { 134 LOG.debug("Populate Restlet request from exchange header: " 135 + entry.getKey() + " value: " + entry.getValue()); 136 } 137 } 138 } 139 140 request.setEntity(form.getWebRepresentation()); 141 } 142 143 public void populateRestletResponseFromExchange(Exchange exchange, Response response) { 144 145 Message out; 146 if (exchange.isFailed()) { 147 // 500 for internal server error which can be overridden by response code in header 148 response.setStatus(Status.valueOf(500)); 149 if (exchange.hasOut() && exchange.getOut().isFault()) { 150 out = exchange.getOut(); 151 } else { 152 // print exception as message and stacktrace 153 Exception t = exchange.getException(); 154 StringWriter sw = new StringWriter(); 155 PrintWriter pw = new PrintWriter(sw); 156 t.printStackTrace(pw); 157 response.setEntity(sw.toString(), MediaType.TEXT_PLAIN); 158 return; 159 } 160 } else { 161 out = exchange.getOut(); 162 } 163 164 // get content type 165 MediaType mediaType = out.getHeader(Exchange.CONTENT_TYPE, MediaType.class); 166 if (mediaType == null) { 167 Object body = out.getBody(); 168 mediaType = MediaType.TEXT_PLAIN; 169 if (body instanceof String) { 170 mediaType = MediaType.TEXT_PLAIN; 171 } else if (body instanceof StringSource || body instanceof DOMSource) { 172 mediaType = MediaType.TEXT_XML; 173 } 174 } 175 176 // get response code 177 Integer responseCode = out.getHeader(Exchange.HTTP_RESPONSE_CODE, Integer.class); 178 if (responseCode != null) { 179 response.setStatus(Status.valueOf(responseCode)); 180 } 181 182 for (Map.Entry<String, Object> entry : out.getHeaders().entrySet()) { 183 if (!headerFilterStrategy.applyFilterToCamelHeaders(entry.getKey(), entry.getValue(), exchange)) { 184 response.getAttributes().put(entry.getKey(), entry.getValue()); 185 if (LOG.isDebugEnabled()) { 186 LOG.debug("Populate Restlet response from exchange header: " 187 + entry.getKey() + " value: " + entry.getValue()); 188 } 189 } 190 } 191 192 String text = out.getBody(String.class); 193 if (LOG.isDebugEnabled()) { 194 LOG.debug("Populate Restlet response from exchange body: " + text); 195 } 196 response.setEntity(text, mediaType); 197 198 if (exchange.getProperty(Exchange.CHARSET_NAME) != null) { 199 response.getEntity().setCharacterSet(CharacterSet.valueOf(exchange.getProperty(Exchange.CHARSET_NAME, 200 String.class))); 201 } 202 } 203 204 public void populateExchangeFromRestletResponse(Exchange exchange, Response response) throws Exception { 205 206 for (Map.Entry<String, Object> entry : response.getAttributes().entrySet()) { 207 if (!headerFilterStrategy.applyFilterToExternalHeaders(entry.getKey(), entry.getValue(), exchange)) { 208 exchange.getOut().setHeader(entry.getKey(), entry.getValue()); 209 if (LOG.isDebugEnabled()) { 210 LOG.debug("Populate exchange from Restlet response header: " 211 + entry.getKey() + " value: " + entry.getValue()); 212 } 213 } 214 } 215 216 String text = response.getEntity().getText(); 217 if (LOG.isDebugEnabled()) { 218 LOG.debug("Populate exchange from Restlet response: " + text); 219 } 220 221 if (exchange.getPattern().isOutCapable()) { 222 exchange.getOut().setBody(text); 223 } else { 224 throw new RuntimeCamelException("Exchange is incapable of receiving response: " + exchange + " with pattern: " + exchange.getPattern()); 225 } 226 } 227 228 public HeaderFilterStrategy getHeaderFilterStrategy() { 229 return headerFilterStrategy; 230 } 231 232 public void setHeaderFilterStrategy(HeaderFilterStrategy strategy) { 233 headerFilterStrategy = strategy; 234 } 235 }