diff options
Diffstat (limited to 'branches/sca-java-1.x/modules/binding-http-runtime/src/main')
4 files changed, 704 insertions, 525 deletions
diff --git a/branches/sca-java-1.x/modules/binding-http-runtime/src/main/java/org/apache/tuscany/sca/binding/http/provider/HTTPBindingListenerServlet.java b/branches/sca-java-1.x/modules/binding-http-runtime/src/main/java/org/apache/tuscany/sca/binding/http/provider/HTTPBindingListenerServlet.java index 41be041621..12f1143e3a 100644 --- a/branches/sca-java-1.x/modules/binding-http-runtime/src/main/java/org/apache/tuscany/sca/binding/http/provider/HTTPBindingListenerServlet.java +++ b/branches/sca-java-1.x/modules/binding-http-runtime/src/main/java/org/apache/tuscany/sca/binding/http/provider/HTTPBindingListenerServlet.java @@ -1,516 +1,516 @@ -/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package org.apache.tuscany.sca.binding.http.provider;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.net.URLDecoder;
-import java.text.ParseException;
-import java.util.List;
-
-import javax.servlet.ServletException;
-import javax.servlet.ServletResponse;
-import javax.servlet.http.HttpServlet;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import javax.xml.namespace.QName;
-
-import org.apache.tuscany.sca.assembly.Binding;
-import org.apache.tuscany.sca.binding.http.HTTPCacheContext;
-import org.apache.tuscany.sca.binding.http.util.HTTPHeadersParser;
-import org.apache.tuscany.sca.invocation.Invoker;
-import org.apache.tuscany.sca.invocation.Message;
-import org.apache.tuscany.sca.invocation.MessageFactory;
-import org.apache.tuscany.sca.policy.Intent;
-import org.apache.tuscany.sca.policy.PolicySet;
-import org.apache.tuscany.sca.policy.PolicySetAttachPoint;
-import org.apache.tuscany.sca.policy.authentication.basic.BasicAuthenticationPolicy;
-
-/**
- * Servlet responsible for dispatching HTTP requests to the
- * target component implementation.
- *
- * @version $Rev$ $Date$
- */
-public class HTTPBindingListenerServlet extends HttpServlet {
- private static final long serialVersionUID = 2865466417329430610L;
-
- private static final QName AUTEHTICATION_INTENT = new QName("http://www.osoa.org/xmlns/sca/1.0","authentication");
-
- transient private Binding binding;
-
- transient private boolean requiresAuthentication = false;
- transient private BasicAuthenticationPolicy basicAuthenticationPolicy = null;
-
- private MessageFactory messageFactory;
- private Invoker getInvoker;
- private Invoker conditionalGetInvoker;
- private Invoker putInvoker;
- private Invoker conditionalPutInvoker;
- private Invoker postInvoker;
- private Invoker conditionalPostInvoker;
- private Invoker deleteInvoker;
- private Invoker conditionalDeleteInvoker;
-
- /**
- * Constructs a new HTTPServiceListenerServlet.
- */
- public HTTPBindingListenerServlet(Binding binding, MessageFactory messageFactory) {
- this.binding = binding;
- this.messageFactory = messageFactory;
-
-
- // find out which policies are active
- if (binding instanceof PolicySetAttachPoint) {
- List<Intent> intents = ((PolicySetAttachPoint)binding).getRequiredIntents();
- for(Intent intent : intents) {
- if(intent.getName().equals(AUTEHTICATION_INTENT)) {
- requiresAuthentication = true;
- }
- }
-
-
- List<PolicySet> policySets = ((PolicySetAttachPoint)binding).getApplicablePolicySets();
- for (PolicySet ps : policySets) {
- for (Object p : ps.getPolicies()) {
- if (BasicAuthenticationPolicy.class.isInstance(p)) {
- basicAuthenticationPolicy = (BasicAuthenticationPolicy)p;
- } else {
- // etc. check for other types of policy being present
- }
- }
- }
- }
- }
-
-
- @Override
- protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
-
- if(requiresAuthentication) {
- if(! hasAuthorization(request, response)) {
- response.setHeader("WWW-Authenticate", "BASIC realm=\"Tuscany\"");
- response.sendError(HttpServletResponse.SC_UNAUTHORIZED);
- }
- }
-
- super.service(request, response);
- }
-
- @Override
- protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
- // Get the request path
- String path = URLDecoder.decode(request.getRequestURI().substring(request.getServletPath().length()), "UTF-8");
- if (path.length() ==0) {
- // Redirect to a URL ending with / to make relative hrefs work
- // relative to the served resource.
- response.sendRedirect(request.getRequestURL().append('/').toString());
- return;
- }
-
- // Invoke the get operation on the service implementation
- Message requestMessage = messageFactory.createMessage();
-
- //store http headers to message
- requestMessage.getHeaders().addAll(HTTPHeadersParser.getHeaders(request));
-
- String id = path.substring(1);
-
- Message responseMessage = null;
- HTTPCacheContext cacheContext = null;
- try {
- cacheContext = HTTPCacheContext.getCacheContextFromRequest(request);
- } catch (ParseException e) {
- }
-
- // Route message based on availability of cache info and cache methods
- if (( cacheContext != null ) && (cacheContext.isEnabled()) && (conditionalGetInvoker != null )) {
- requestMessage.setBody(new Object[] {id, cacheContext});
- responseMessage = conditionalGetInvoker.invoke(requestMessage);
- } else {
- requestMessage.setBody(new Object[] {id});
- responseMessage = getInvoker.invoke(requestMessage);
- }
- if (responseMessage.isFault()) {
- Object body = responseMessage.getBody();
-
- int index = -1;
- if ( -1 < (index = body.getClass().getName().indexOf( "NotModifiedException")) ) {
- if ( index > -1 )
- response.sendError( HttpServletResponse.SC_NOT_MODIFIED, body.toString().substring( index ));
- else
- response.sendError( HttpServletResponse.SC_NOT_MODIFIED );
- return;
- } else if ( -1 < (index = body.getClass().getName().indexOf( "PreconditionFailedException")) ) {
- if ( index > -1 )
- response.sendError( HttpServletResponse.SC_PRECONDITION_FAILED, body.toString().substring( index ));
- else
- response.sendError( HttpServletResponse.SC_PRECONDITION_FAILED );
- return;
- }
-
- throw new ServletException((Throwable)responseMessage.getBody());
- }
-
- // Write the response from the service implementation to the response
- // output stream
- InputStream is = (InputStream)responseMessage.getBody();
- OutputStream os = response.getOutputStream();
- byte[] buffer = new byte[2048];
- for (;;) {
- int n = is.read(buffer);
- if (n <= 0)
- break;
- os.write(buffer, 0, n);
- }
- os.flush();
- os.close();
- }
-
- @Override
- protected void doDelete(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
- // Get the request path
- String path = URLDecoder.decode(request.getRequestURI().substring(request.getServletPath().length()), "UTF-8");
- if (path.length() ==0) {
- // Redirect to a URL ending with / to make relative hrefs work
- // relative to the served resource.
- response.sendRedirect(request.getRequestURL().append('/').toString());
- return;
- }
-
- // Invoke the get operation on the service implementation
- Message requestMessage = messageFactory.createMessage();
- String id = path.substring(1);
-
- Message responseMessage = null;
- HTTPCacheContext cacheContext = null;
- try {
- cacheContext = HTTPCacheContext.getCacheContextFromRequest(request);
- } catch (ParseException e) {
- }
-
- // Route message based on availability of cache info and cache methods
- if (( cacheContext != null ) && (cacheContext.isEnabled()) && (conditionalDeleteInvoker != null )) {
- requestMessage.setBody(new Object[] {id, cacheContext});
- responseMessage = conditionalDeleteInvoker.invoke(requestMessage);
- } else {
- requestMessage.setBody(new Object[] {id});
- responseMessage = deleteInvoker.invoke(requestMessage);
- }
- if (responseMessage.isFault()) {
- Object body = responseMessage.getBody();
-
- int index = -1;
- if ( -1 < (index = body.getClass().getName().indexOf( "NotModifiedException")) ) {
- if ( index > -1 )
- response.sendError( HttpServletResponse.SC_NOT_MODIFIED, body.toString().substring( index ));
- else
- response.sendError( HttpServletResponse.SC_NOT_MODIFIED );
- return;
- } else if ( -1 < (index = body.getClass().getName().indexOf( "PreconditionFailedException")) ) {
- if ( index > -1 )
- response.sendError( HttpServletResponse.SC_PRECONDITION_FAILED, body.toString().substring( index ));
- else
- response.sendError( HttpServletResponse.SC_PRECONDITION_FAILED );
- return;
- }
-
- throw new ServletException((Throwable)responseMessage.getBody());
- }
-
- // Write the response from the service implementation to the response
- // output stream
- InputStream is = (InputStream)responseMessage.getBody();
- OutputStream os = response.getOutputStream();
- byte[] buffer = new byte[2048];
- for (;;) {
- int n = is.read(buffer);
- if (n <= 0)
- break;
- os.write(buffer, 0, n);
- }
- os.flush();
- os.close();
- }
-
- @Override
- protected void doPut(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
- // Get the request path
- String path = URLDecoder.decode(request.getRequestURI().substring(request.getServletPath().length()), "UTF-8");
- if (path.length() ==0) {
- // Redirect to a URL ending with / to make relative hrefs work
- // relative to the served resource.
- response.sendRedirect(request.getRequestURL().append('/').toString());
- return;
- }
-
- // Invoke the get operation on the service implementation
- Message requestMessage = messageFactory.createMessage();
- String id = path.substring(1);
-
- Message responseMessage = null;
- HTTPCacheContext cacheContext = null;
- try {
- cacheContext = HTTPCacheContext.getCacheContextFromRequest(request);
- } catch (ParseException e) {
- }
-
- // Route message based on availability of cache info and cache methods
- if (( cacheContext != null ) && (cacheContext.isEnabled()) && (conditionalPutInvoker != null )) {
- requestMessage.setBody(new Object[] {id, cacheContext});
- responseMessage = conditionalPutInvoker.invoke(requestMessage);
- } else {
- requestMessage.setBody(new Object[] {id});
- responseMessage = putInvoker.invoke(requestMessage);
- }
- if (responseMessage.isFault()) {
- Object body = responseMessage.getBody();
-
- int index = -1;
- if ( -1 < (index = body.getClass().getName().indexOf( "NotModifiedException")) ) {
- if ( index > -1 )
- response.sendError( HttpServletResponse.SC_NOT_MODIFIED, body.toString().substring( index ));
- else
- response.sendError( HttpServletResponse.SC_NOT_MODIFIED );
- return;
- } else if ( -1 < (index = body.getClass().getName().indexOf( "PreconditionFailedException")) ) {
- if ( index > -1 )
- response.sendError( HttpServletResponse.SC_PRECONDITION_FAILED, body.toString().substring( index ));
- else
- response.sendError( HttpServletResponse.SC_PRECONDITION_FAILED );
- return;
- }
-
- throw new ServletException((Throwable)responseMessage.getBody());
- }
-
- // Write the response from the service implementation to the response
- // output stream
- InputStream is = (InputStream)responseMessage.getBody();
- OutputStream os = response.getOutputStream();
- byte[] buffer = new byte[2048];
- for (;;) {
- int n = is.read(buffer);
- if (n <= 0)
- break;
- os.write(buffer, 0, n);
- }
- os.flush();
- os.close();
- }
-
- @Override
- protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
- // Get the request path
- String path = URLDecoder.decode(request.getRequestURI().substring(request.getServletPath().length()), "UTF-8");
- if (path.length() ==0) {
- // Redirect to a URL ending with / to make relative hrefs work
- // relative to the served resource.
- response.sendRedirect(request.getRequestURL().append('/').toString());
- return;
- }
-
- // Invoke the get operation on the service implementation
- Message requestMessage = messageFactory.createMessage();
- // String id = path.substring(1);
-
- Message responseMessage = null;
- HTTPCacheContext cacheContext = null;
- try {
- cacheContext = HTTPCacheContext.getCacheContextFromRequest(request);
- } catch (ParseException e) {
- }
-
- // Route message based on availability of cache info and cache methods
- if (( cacheContext != null ) && (cacheContext.isEnabled()) && (conditionalPostInvoker != null )) {
- requestMessage.setBody(new Object[] {cacheContext});
- responseMessage = conditionalPostInvoker.invoke(requestMessage);
- } else {
- requestMessage.setBody(new Object[] {});
- responseMessage = postInvoker.invoke(requestMessage);
- }
- if (responseMessage.isFault()) {
- Object body = responseMessage.getBody();
-
- int index = -1;
- if ( -1 < (index = body.getClass().getName().indexOf( "NotModifiedException")) ) {
- if ( index > -1 )
- response.sendError( HttpServletResponse.SC_NOT_MODIFIED, body.toString().substring( index ));
- else
- response.sendError( HttpServletResponse.SC_NOT_MODIFIED );
- return;
- } else if ( -1 < (index = body.getClass().getName().indexOf( "PreconditionFailedException")) ) {
- if ( index > -1 )
- response.sendError( HttpServletResponse.SC_PRECONDITION_FAILED, body.toString().substring( index ));
- else
- response.sendError( HttpServletResponse.SC_PRECONDITION_FAILED );
- return;
- }
-
- throw new ServletException((Throwable)responseMessage.getBody());
- }
-
-
- // Test if the ETag and LastModified are returned as a cache context.
- Object body = responseMessage.getBody();
- if ( body.getClass() == HTTPCacheContext.class ) {
- // Transfer to header if so.
- HTTPCacheContext cc = (HTTPCacheContext)responseMessage.getBody();
- if (( cc != null ) && ( cc.isEnabled() )) {
- String eTag = cc.getETag();
- if ( eTag != null )
- response.setHeader( "ETag", cc.getETag() );
- String lastModified = cc.getLastModified();
- if ( lastModified != null)
- response.setHeader( "LastModified", cc.getLastModified() );
- }
- }
- }
-
- /**
- * @return the getInvoker
- */
- public Invoker getGetInvoker() {
- return getInvoker;
- }
-
- /**
- * @param getInvoker the getInvoker to set
- */
- public void setGetInvoker(Invoker getInvoker) {
- this.getInvoker = getInvoker;
- }
-
- /**
- * @return the conditionalGetInvoker
- */
- public Invoker getConditionalGetInvoker() {
- return conditionalGetInvoker;
- }
-
- /**
- * @param conditionalGetInvoker the conditionalGetInvoker to set
- */
- public void setConditionalGetInvoker(Invoker conditionalGetInvoker) {
- this.conditionalGetInvoker = conditionalGetInvoker;
- }
-
- /**
- * @return the putInvoker
- */
- public Invoker getPutInvoker() {
- return putInvoker;
- }
-
- /**
- * @param putInvoker the putInvoker to set
- */
- public void setPutInvoker(Invoker putInvoker) {
- this.putInvoker = putInvoker;
- }
-
- /**
- * @return the conditionalPutInvoker
- */
- public Invoker getConditionalPutInvoker() {
- return conditionalPutInvoker;
- }
-
- /**
- * @param conditionalPutInvoker the conditionalPutInvoker to set
- */
- public void setConditionalPutInvoker(Invoker conditionalPutInvoker) {
- this.conditionalPutInvoker = conditionalPutInvoker;
- }
-
- /**
- * @return the postInvoker
- */
- public Invoker getPostInvoker() {
- return postInvoker;
- }
-
- /**
- * @param postInvoker the postInvoker to set
- */
- public void setPostInvoker(Invoker postInvoker) {
- this.postInvoker = postInvoker;
- }
-
- /**
- * @return the conditionalPostInvoker
- */
- public Invoker getConditionalPostInvoker() {
- return conditionalPostInvoker;
- }
-
- /**
- * @param conditionalPostInvoker the conditionalPostInvoker to set
- */
- public void setConditionalPostInvoker(Invoker conditionalPostInvoker) {
- this.conditionalPostInvoker = conditionalPostInvoker;
- }
-
- /**
- * @return the deleteInvoker
- */
- public Invoker getDeleteInvoker() {
- return deleteInvoker;
- }
-
- /**
- * @param deleteInvoker the deleteInvoker to set
- */
- public void setDeleteInvoker(Invoker deleteInvoker) {
- this.deleteInvoker = deleteInvoker;
- }
-
- /**
- * @return the conditionalDeleteInvoker
- */
- public Invoker getConditionalDeleteInvoker() {
- return conditionalDeleteInvoker;
- }
-
- /**
- * @param conditionalDeleteInvoker the conditionalDeleteInvoker to set
- */
- public void setConditionalDeleteInvoker(Invoker conditionalDeleteInvoker) {
- this.conditionalDeleteInvoker = conditionalDeleteInvoker;
- }
-
-
- /**
- * Utility Methods related to Policy
- */
-
-
- private boolean hasAuthorization(HttpServletRequest request, ServletResponse response) {
- boolean result = false;
- if(request.getHeader("Authorization") != null) {
- result = true;
- }
-
- return result;
- }
-
-
-}
+/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.binding.http.provider; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.URLDecoder; +import java.text.ParseException; +import java.util.List; + +import javax.servlet.ServletException; +import javax.servlet.ServletResponse; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.xml.namespace.QName; + +import org.apache.tuscany.sca.assembly.Binding; +import org.apache.tuscany.sca.binding.http.HTTPCacheContext; +import org.apache.tuscany.sca.binding.http.util.HTTPHeadersParser; +import org.apache.tuscany.sca.invocation.Invoker; +import org.apache.tuscany.sca.invocation.Message; +import org.apache.tuscany.sca.invocation.MessageFactory; +import org.apache.tuscany.sca.policy.Intent; +import org.apache.tuscany.sca.policy.PolicySet; +import org.apache.tuscany.sca.policy.PolicySetAttachPoint; +import org.apache.tuscany.sca.policy.authentication.basic.BasicAuthenticationPolicy; + +/** + * Servlet responsible for dispatching HTTP requests to the + * target component implementation. + * + * @version $Rev$ $Date$ + */ +public class HTTPBindingListenerServlet extends HttpServlet { + private static final long serialVersionUID = 2865466417329430610L; + + private static final QName AUTEHTICATION_INTENT = new QName("http://www.osoa.org/xmlns/sca/1.0","authentication"); + + transient private Binding binding; + + transient private boolean requiresAuthentication = false; + transient private BasicAuthenticationPolicy basicAuthenticationPolicy = null; + + private MessageFactory messageFactory; + private Invoker getInvoker; + private Invoker conditionalGetInvoker; + private Invoker putInvoker; + private Invoker conditionalPutInvoker; + private Invoker postInvoker; + private Invoker conditionalPostInvoker; + private Invoker deleteInvoker; + private Invoker conditionalDeleteInvoker; + + /** + * Constructs a new HTTPServiceListenerServlet. + */ + public HTTPBindingListenerServlet(Binding binding, MessageFactory messageFactory) { + this.binding = binding; + this.messageFactory = messageFactory; + + + // find out which policies are active + if (binding instanceof PolicySetAttachPoint) { + List<Intent> intents = ((PolicySetAttachPoint)binding).getRequiredIntents(); + for(Intent intent : intents) { + if(intent.getName().equals(AUTEHTICATION_INTENT)) { + requiresAuthentication = true; + } + } + + + List<PolicySet> policySets = ((PolicySetAttachPoint)binding).getApplicablePolicySets(); + for (PolicySet ps : policySets) { + for (Object p : ps.getPolicies()) { + if (BasicAuthenticationPolicy.class.isInstance(p)) { + basicAuthenticationPolicy = (BasicAuthenticationPolicy)p; + } else { + // etc. check for other types of policy being present + } + } + } + } + } + + + @Override + protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { + + if(requiresAuthentication) { + if(! hasAuthorization(request, response)) { + response.setHeader("WWW-Authenticate", "BASIC realm=\"Tuscany\""); + response.sendError(HttpServletResponse.SC_UNAUTHORIZED); + } + } + + super.service(request, response); + } + + @Override + protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { + // Get the request path + String path = URLDecoder.decode(request.getRequestURI().substring(request.getServletPath().length()), "UTF-8"); + if (path.length() ==0) { + // Redirect to a URL ending with / to make relative hrefs work + // relative to the served resource. + response.sendRedirect(request.getRequestURL().append('/').toString()); + return; + } + + // Invoke the get operation on the service implementation + Message requestMessage = messageFactory.createMessage(); + + //store http headers to message + requestMessage.getHeaders().addAll(HTTPHeadersParser.getHeaders(request)); + + String id = path.substring(1); + + Message responseMessage = null; + HTTPCacheContext cacheContext = null; + try { + cacheContext = HTTPCacheContext.getCacheContextFromRequest(request); + } catch (ParseException e) { + } + + // Route message based on availability of cache info and cache methods + if (( cacheContext != null ) && (cacheContext.isEnabled()) && (conditionalGetInvoker != null )) { + requestMessage.setBody(new Object[] {id, cacheContext}); + responseMessage = conditionalGetInvoker.invoke(requestMessage); + } else { + requestMessage.setBody(new Object[] {id}); + responseMessage = getInvoker.invoke(requestMessage); + } + if (responseMessage.isFault()) { + Object body = responseMessage.getBody(); + + int index = -1; + if ( -1 < (index = body.getClass().getName().indexOf( "NotModifiedException")) ) { + if ( index > -1 ) + response.sendError( HttpServletResponse.SC_NOT_MODIFIED, body.toString().substring( index )); + else + response.sendError( HttpServletResponse.SC_NOT_MODIFIED ); + return; + } else if ( -1 < (index = body.getClass().getName().indexOf( "PreconditionFailedException")) ) { + if ( index > -1 ) + response.sendError( HttpServletResponse.SC_PRECONDITION_FAILED, body.toString().substring( index )); + else + response.sendError( HttpServletResponse.SC_PRECONDITION_FAILED ); + return; + } + + throw new ServletException((Throwable)responseMessage.getBody()); + } + + // Write the response from the service implementation to the response + // output stream + InputStream is = (InputStream)responseMessage.getBody(); + OutputStream os = response.getOutputStream(); + byte[] buffer = new byte[2048]; + for (;;) { + int n = is.read(buffer); + if (n <= 0) + break; + os.write(buffer, 0, n); + } + os.flush(); + os.close(); + } + + @Override + protected void doDelete(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { + // Get the request path + String path = URLDecoder.decode(request.getRequestURI().substring(request.getServletPath().length()), "UTF-8"); + if (path.length() ==0) { + // Redirect to a URL ending with / to make relative hrefs work + // relative to the served resource. + response.sendRedirect(request.getRequestURL().append('/').toString()); + return; + } + + // Invoke the get operation on the service implementation + Message requestMessage = messageFactory.createMessage(); + String id = path.substring(1); + + Message responseMessage = null; + HTTPCacheContext cacheContext = null; + try { + cacheContext = HTTPCacheContext.getCacheContextFromRequest(request); + } catch (ParseException e) { + } + + // Route message based on availability of cache info and cache methods + if (( cacheContext != null ) && (cacheContext.isEnabled()) && (conditionalDeleteInvoker != null )) { + requestMessage.setBody(new Object[] {id, cacheContext}); + responseMessage = conditionalDeleteInvoker.invoke(requestMessage); + } else { + requestMessage.setBody(new Object[] {id}); + responseMessage = deleteInvoker.invoke(requestMessage); + } + if (responseMessage.isFault()) { + Object body = responseMessage.getBody(); + + int index = -1; + if ( -1 < (index = body.getClass().getName().indexOf( "NotModifiedException")) ) { + if ( index > -1 ) + response.sendError( HttpServletResponse.SC_NOT_MODIFIED, body.toString().substring( index )); + else + response.sendError( HttpServletResponse.SC_NOT_MODIFIED ); + return; + } else if ( -1 < (index = body.getClass().getName().indexOf( "PreconditionFailedException")) ) { + if ( index > -1 ) + response.sendError( HttpServletResponse.SC_PRECONDITION_FAILED, body.toString().substring( index )); + else + response.sendError( HttpServletResponse.SC_PRECONDITION_FAILED ); + return; + } + + throw new ServletException((Throwable)responseMessage.getBody()); + } + + // Write the response from the service implementation to the response + // output stream + InputStream is = (InputStream)responseMessage.getBody(); + OutputStream os = response.getOutputStream(); + byte[] buffer = new byte[2048]; + for (;;) { + int n = is.read(buffer); + if (n <= 0) + break; + os.write(buffer, 0, n); + } + os.flush(); + os.close(); + } + + @Override + protected void doPut(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { + // Get the request path + String path = URLDecoder.decode(request.getRequestURI().substring(request.getServletPath().length()), "UTF-8"); + if (path.length() ==0) { + // Redirect to a URL ending with / to make relative hrefs work + // relative to the served resource. + response.sendRedirect(request.getRequestURL().append('/').toString()); + return; + } + + // Invoke the get operation on the service implementation + Message requestMessage = messageFactory.createMessage(); + String id = path.substring(1); + + Message responseMessage = null; + HTTPCacheContext cacheContext = null; + try { + cacheContext = HTTPCacheContext.getCacheContextFromRequest(request); + } catch (ParseException e) { + } + + // Route message based on availability of cache info and cache methods + if (( cacheContext != null ) && (cacheContext.isEnabled()) && (conditionalPutInvoker != null )) { + requestMessage.setBody(new Object[] {id, cacheContext}); + responseMessage = conditionalPutInvoker.invoke(requestMessage); + } else { + requestMessage.setBody(new Object[] {id}); + responseMessage = putInvoker.invoke(requestMessage); + } + if (responseMessage.isFault()) { + Object body = responseMessage.getBody(); + + int index = -1; + if ( -1 < (index = body.getClass().getName().indexOf( "NotModifiedException")) ) { + if ( index > -1 ) + response.sendError( HttpServletResponse.SC_NOT_MODIFIED, body.toString().substring( index )); + else + response.sendError( HttpServletResponse.SC_NOT_MODIFIED ); + return; + } else if ( -1 < (index = body.getClass().getName().indexOf( "PreconditionFailedException")) ) { + if ( index > -1 ) + response.sendError( HttpServletResponse.SC_PRECONDITION_FAILED, body.toString().substring( index )); + else + response.sendError( HttpServletResponse.SC_PRECONDITION_FAILED ); + return; + } + + throw new ServletException((Throwable)responseMessage.getBody()); + } + + // Write the response from the service implementation to the response + // output stream + InputStream is = (InputStream)responseMessage.getBody(); + OutputStream os = response.getOutputStream(); + byte[] buffer = new byte[2048]; + for (;;) { + int n = is.read(buffer); + if (n <= 0) + break; + os.write(buffer, 0, n); + } + os.flush(); + os.close(); + } + + @Override + protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { + // Get the request path + String path = URLDecoder.decode(request.getRequestURI().substring(request.getServletPath().length()), "UTF-8"); + if (path.length() ==0) { + // Redirect to a URL ending with / to make relative hrefs work + // relative to the served resource. + response.sendRedirect(request.getRequestURL().append('/').toString()); + return; + } + + // Invoke the get operation on the service implementation + Message requestMessage = messageFactory.createMessage(); + // String id = path.substring(1); + + Message responseMessage = null; + HTTPCacheContext cacheContext = null; + try { + cacheContext = HTTPCacheContext.getCacheContextFromRequest(request); + } catch (ParseException e) { + } + + // Route message based on availability of cache info and cache methods + if (( cacheContext != null ) && (cacheContext.isEnabled()) && (conditionalPostInvoker != null )) { + requestMessage.setBody(new Object[] {cacheContext}); + responseMessage = conditionalPostInvoker.invoke(requestMessage); + } else { + requestMessage.setBody(new Object[] {}); + responseMessage = postInvoker.invoke(requestMessage); + } + if (responseMessage.isFault()) { + Object body = responseMessage.getBody(); + + int index = -1; + if ( -1 < (index = body.getClass().getName().indexOf( "NotModifiedException")) ) { + if ( index > -1 ) + response.sendError( HttpServletResponse.SC_NOT_MODIFIED, body.toString().substring( index )); + else + response.sendError( HttpServletResponse.SC_NOT_MODIFIED ); + return; + } else if ( -1 < (index = body.getClass().getName().indexOf( "PreconditionFailedException")) ) { + if ( index > -1 ) + response.sendError( HttpServletResponse.SC_PRECONDITION_FAILED, body.toString().substring( index )); + else + response.sendError( HttpServletResponse.SC_PRECONDITION_FAILED ); + return; + } + + throw new ServletException((Throwable)responseMessage.getBody()); + } + + + // Test if the ETag and LastModified are returned as a cache context. + Object body = responseMessage.getBody(); + if ( body.getClass() == HTTPCacheContext.class ) { + // Transfer to header if so. + HTTPCacheContext cc = (HTTPCacheContext)responseMessage.getBody(); + if (( cc != null ) && ( cc.isEnabled() )) { + String eTag = cc.getETag(); + if ( eTag != null ) + response.setHeader( "ETag", cc.getETag() ); + String lastModified = cc.getLastModified(); + if ( lastModified != null) + response.setHeader( "LastModified", cc.getLastModified() ); + } + } + } + + /** + * @return the getInvoker + */ + public Invoker getGetInvoker() { + return getInvoker; + } + + /** + * @param getInvoker the getInvoker to set + */ + public void setGetInvoker(Invoker getInvoker) { + this.getInvoker = getInvoker; + } + + /** + * @return the conditionalGetInvoker + */ + public Invoker getConditionalGetInvoker() { + return conditionalGetInvoker; + } + + /** + * @param conditionalGetInvoker the conditionalGetInvoker to set + */ + public void setConditionalGetInvoker(Invoker conditionalGetInvoker) { + this.conditionalGetInvoker = conditionalGetInvoker; + } + + /** + * @return the putInvoker + */ + public Invoker getPutInvoker() { + return putInvoker; + } + + /** + * @param putInvoker the putInvoker to set + */ + public void setPutInvoker(Invoker putInvoker) { + this.putInvoker = putInvoker; + } + + /** + * @return the conditionalPutInvoker + */ + public Invoker getConditionalPutInvoker() { + return conditionalPutInvoker; + } + + /** + * @param conditionalPutInvoker the conditionalPutInvoker to set + */ + public void setConditionalPutInvoker(Invoker conditionalPutInvoker) { + this.conditionalPutInvoker = conditionalPutInvoker; + } + + /** + * @return the postInvoker + */ + public Invoker getPostInvoker() { + return postInvoker; + } + + /** + * @param postInvoker the postInvoker to set + */ + public void setPostInvoker(Invoker postInvoker) { + this.postInvoker = postInvoker; + } + + /** + * @return the conditionalPostInvoker + */ + public Invoker getConditionalPostInvoker() { + return conditionalPostInvoker; + } + + /** + * @param conditionalPostInvoker the conditionalPostInvoker to set + */ + public void setConditionalPostInvoker(Invoker conditionalPostInvoker) { + this.conditionalPostInvoker = conditionalPostInvoker; + } + + /** + * @return the deleteInvoker + */ + public Invoker getDeleteInvoker() { + return deleteInvoker; + } + + /** + * @param deleteInvoker the deleteInvoker to set + */ + public void setDeleteInvoker(Invoker deleteInvoker) { + this.deleteInvoker = deleteInvoker; + } + + /** + * @return the conditionalDeleteInvoker + */ + public Invoker getConditionalDeleteInvoker() { + return conditionalDeleteInvoker; + } + + /** + * @param conditionalDeleteInvoker the conditionalDeleteInvoker to set + */ + public void setConditionalDeleteInvoker(Invoker conditionalDeleteInvoker) { + this.conditionalDeleteInvoker = conditionalDeleteInvoker; + } + + + /** + * Utility Methods related to Policy + */ + + + private boolean hasAuthorization(HttpServletRequest request, ServletResponse response) { + boolean result = false; + if(request.getHeader("Authorization") != null) { + result = true; + } + + return result; + } + + +} diff --git a/branches/sca-java-1.x/modules/binding-http-runtime/src/main/java/org/apache/tuscany/sca/binding/http/provider/HTTPBindingProviderFactory.java b/branches/sca-java-1.x/modules/binding-http-runtime/src/main/java/org/apache/tuscany/sca/binding/http/provider/HTTPBindingProviderFactory.java index fccd10f3cd..768636d478 100644 --- a/branches/sca-java-1.x/modules/binding-http-runtime/src/main/java/org/apache/tuscany/sca/binding/http/provider/HTTPBindingProviderFactory.java +++ b/branches/sca-java-1.x/modules/binding-http-runtime/src/main/java/org/apache/tuscany/sca/binding/http/provider/HTTPBindingProviderFactory.java @@ -39,11 +39,12 @@ import org.apache.tuscany.sca.runtime.RuntimeComponentService; * @version $Rev$ $Date$ */ public class HTTPBindingProviderFactory implements BindingProviderFactory<HTTPBinding> { - + private ExtensionPointRegistry extensionPoints; private MessageFactory messageFactory; private ServletHost servletHost; public HTTPBindingProviderFactory(ExtensionPointRegistry extensionPoints) { + this.extensionPoints = extensionPoints; ServletHostExtensionPoint servletHosts = extensionPoints.getExtensionPoint(ServletHostExtensionPoint.class); this.servletHost = servletHosts.getServletHosts().get(0); ModelFactoryExtensionPoint modelFactories = extensionPoints.getExtensionPoint(ModelFactoryExtensionPoint.class); @@ -55,7 +56,7 @@ public class HTTPBindingProviderFactory implements BindingProviderFactory<HTTPBi } public ServiceBindingProvider createServiceBindingProvider(RuntimeComponent component, RuntimeComponentService service, HTTPBinding binding) { - return new HTTPServiceBindingProvider(component, service, binding, messageFactory, servletHost); + return new HTTPServiceBindingProvider(component, service, binding, extensionPoints, messageFactory, servletHost); } public Class<HTTPBinding> getModelType() { diff --git a/branches/sca-java-1.x/modules/binding-http-runtime/src/main/java/org/apache/tuscany/sca/binding/http/provider/HTTPRRBListenerServlet.java b/branches/sca-java-1.x/modules/binding-http-runtime/src/main/java/org/apache/tuscany/sca/binding/http/provider/HTTPRRBListenerServlet.java new file mode 100644 index 0000000000..605e2c6211 --- /dev/null +++ b/branches/sca-java-1.x/modules/binding-http-runtime/src/main/java/org/apache/tuscany/sca/binding/http/provider/HTTPRRBListenerServlet.java @@ -0,0 +1,102 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.binding.http.provider; + +import java.io.BufferedReader; +import java.io.CharArrayWriter; +import java.io.IOException; +import java.io.InputStreamReader; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.tuscany.sca.assembly.Binding; +import org.apache.tuscany.sca.binding.http.HTTPBindingContext; +import org.apache.tuscany.sca.invocation.Invoker; +import org.apache.tuscany.sca.invocation.Message; +import org.apache.tuscany.sca.invocation.MessageFactory; + +public class HTTPRRBListenerServlet extends HttpServlet { + + private static final long serialVersionUID = 6688524143716091739L; + + transient private Binding binding; + transient private Invoker bindingInvoker; + transient private MessageFactory messageFactory; + + /** + * Constructs a new HTTPServiceListenerServlet. + */ + public HTTPRRBListenerServlet(Binding binding, Invoker bindingInvoker, MessageFactory messageFactory) { + this.binding = binding; + this.bindingInvoker = bindingInvoker; + this.messageFactory = messageFactory; + } + + public void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { + + // Decode using the charset in the request if it exists otherwise + // use UTF-8 as this is what all browser implementations use. + // The JSON-RPC-Java JavaScript client is ASCII clean so it + // although here we can correctly handle data from other clients + // that do not escape non ASCII data + String charset = request.getCharacterEncoding(); + if (charset == null) { + charset = "UTF-8"; + } + BufferedReader in = new BufferedReader(new InputStreamReader(request.getInputStream(), charset)); + + // Read the request + CharArrayWriter data = new CharArrayWriter(); + char[] buf = new char[4096]; + int ret; + while ((ret = in.read(buf, 0, 4096)) != -1) { + data.write(buf, 0, ret); + } + + HTTPBindingContext bindingContext = new HTTPBindingContext(); + bindingContext.setHttpRequest(request); + bindingContext.setHttpResponse(response); + + // Dispatch the service interaction to the service invoker + Message requestMessage = messageFactory.createMessage(); + requestMessage.setBindingContext(bindingContext); + requestMessage.setBody(new Object[]{data}); + + Message responseMessage = bindingInvoker.invoke(requestMessage); + + // return response to client + if (responseMessage.isFault()) { + // Turn a fault into an exception + //throw new ServletException((Throwable)responseMessage.getBody()); + Throwable e = (Throwable)responseMessage.getBody(); + response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, e.toString()); + } else { + byte[] bout; + bout = responseMessage.<Object>getBody().toString().getBytes("UTF-8"); + response.getOutputStream().write(bout); + response.getOutputStream().flush(); + response.getOutputStream().close(); + } + } + +} diff --git a/branches/sca-java-1.x/modules/binding-http-runtime/src/main/java/org/apache/tuscany/sca/binding/http/provider/HTTPServiceBindingProvider.java b/branches/sca-java-1.x/modules/binding-http-runtime/src/main/java/org/apache/tuscany/sca/binding/http/provider/HTTPServiceBindingProvider.java index 6e01ac5f9f..3a3428268c 100644 --- a/branches/sca-java-1.x/modules/binding-http-runtime/src/main/java/org/apache/tuscany/sca/binding/http/provider/HTTPServiceBindingProvider.java +++ b/branches/sca-java-1.x/modules/binding-http-runtime/src/main/java/org/apache/tuscany/sca/binding/http/provider/HTTPServiceBindingProvider.java @@ -25,6 +25,7 @@ import javax.servlet.Servlet; import javax.xml.namespace.QName; import org.apache.tuscany.sca.binding.http.HTTPBinding; +import org.apache.tuscany.sca.core.ExtensionPointRegistry; import org.apache.tuscany.sca.host.http.SecurityContext; import org.apache.tuscany.sca.host.http.ServletHost; import org.apache.tuscany.sca.interfacedef.InterfaceContract; @@ -32,12 +33,18 @@ import org.apache.tuscany.sca.interfacedef.Operation; import org.apache.tuscany.sca.invocation.InvocationChain; import org.apache.tuscany.sca.invocation.Invoker; import org.apache.tuscany.sca.invocation.MessageFactory; +import org.apache.tuscany.sca.invocation.Phase; import org.apache.tuscany.sca.policy.Intent; import org.apache.tuscany.sca.policy.PolicySet; import org.apache.tuscany.sca.policy.PolicySetAttachPoint; import org.apache.tuscany.sca.policy.authentication.AuthenticationConfigurationPolicy; import org.apache.tuscany.sca.policy.confidentiality.ConfidentialityPolicy; -import org.apache.tuscany.sca.provider.ServiceBindingProvider; +import org.apache.tuscany.sca.provider.OperationSelectorProvider; +import org.apache.tuscany.sca.provider.OperationSelectorProviderFactory; +import org.apache.tuscany.sca.provider.ProviderFactoryExtensionPoint; +import org.apache.tuscany.sca.provider.ServiceBindingProviderRRB; +import org.apache.tuscany.sca.provider.WireFormatProvider; +import org.apache.tuscany.sca.provider.WireFormatProviderFactory; import org.apache.tuscany.sca.runtime.RuntimeComponent; import org.apache.tuscany.sca.runtime.RuntimeComponentService; import org.apache.tuscany.sca.runtime.RuntimeWire; @@ -47,27 +54,74 @@ import org.apache.tuscany.sca.runtime.RuntimeWire; * * @version $Rev$ $Date$ */ -public class HTTPServiceBindingProvider implements ServiceBindingProvider { +public class HTTPServiceBindingProvider implements ServiceBindingProviderRRB { private static final QName AUTEHTICATION_INTENT = new QName("http://www.osoa.org/xmlns/sca/1.0","authentication"); private static final QName CONFIDENTIALITY_INTENT = new QName("http://www.osoa.org/xmlns/sca/1.0","confidentiality"); + private ExtensionPointRegistry extensionPoints; + + private RuntimeComponent component; private RuntimeComponentService service; + private InterfaceContract serviceContract; private HTTPBinding binding; private MessageFactory messageFactory; + private OperationSelectorProvider osProvider; + private WireFormatProvider wfProvider; + private ServletHost servletHost; private String servletMapping; private HTTPBindingListenerServlet bindingListenerServlet; public HTTPServiceBindingProvider(RuntimeComponent component, - RuntimeComponentService service, - HTTPBinding binding, - MessageFactory messageFactory, - ServletHost servletHost) { + RuntimeComponentService service, + HTTPBinding binding, + ExtensionPointRegistry extensionPoints, + MessageFactory messageFactory, + ServletHost servletHost) { + this.component = component; this.service = service; + this.binding = binding; + this.extensionPoints = extensionPoints; this.messageFactory = messageFactory; this.servletHost = servletHost; + + // retrieve operation selector and wire format service providers + + ProviderFactoryExtensionPoint providerFactories = extensionPoints.getExtensionPoint(ProviderFactoryExtensionPoint.class); + + + if (binding.getOperationSelector() != null) { + // Configure the interceptors for operation selection + OperationSelectorProviderFactory osProviderFactory = (OperationSelectorProviderFactory) providerFactories.getProviderFactory(binding.getOperationSelector().getClass()); + if (osProviderFactory != null) { + this.osProvider = osProviderFactory.createServiceOperationSelectorProvider(component, service, binding); + } + } + + if (binding.getRequestWireFormat() != null && binding.getResponseWireFormat() != null) { + // Configure the interceptors for wire format + WireFormatProviderFactory wfProviderFactory = (WireFormatProviderFactory) providerFactories.getProviderFactory(binding.getRequestWireFormat().getClass()); + if (wfProviderFactory != null) { + this.wfProvider = wfProviderFactory.createServiceWireFormatProvider(component, service, binding); + } + } + + + + //clone the service contract to avoid databinding issues + try { + this.serviceContract = (InterfaceContract) service.getInterfaceContract().clone(); + + // configure data binding + if (this.wfProvider != null) { + wfProvider.configureWireFormatInterfaceContract(service.getInterfaceContract()); + } + } catch(CloneNotSupportedException e) { + this.serviceContract = service.getInterfaceContract(); + } + } public void start() { @@ -115,6 +169,10 @@ public class HTTPServiceBindingProvider implements ServiceBindingProvider { Invoker serviceInvoker = invocationChain.getHeadInvoker(); servlet = new HTTPServiceListenerServlet(binding, serviceInvoker, messageFactory); break; + } else if (binding.getOperationSelector() != null || binding.getRequestWireFormat() != null) { + Invoker bindingInvoker = wire.getBindingInvocationChain().getHeadInvoker(); + servlet = new HTTPRRBListenerServlet(binding, bindingInvoker, messageFactory); + break; } } if (servlet == null) { @@ -179,11 +237,29 @@ public class HTTPServiceBindingProvider implements ServiceBindingProvider { } public InterfaceContract getBindingInterfaceContract() { - return null; + return service.getInterfaceContract(); } public boolean supportsOneWayInvocation() { return false; } + + /** + * Add specific http interceptor to invocation chain + * @param runtimeWire + */ + public void configureBindingChain(RuntimeWire runtimeWire) { + + InvocationChain bindingChain = runtimeWire.getBindingInvocationChain(); + + if(osProvider != null) { + bindingChain.addInterceptor(Phase.SERVICE_BINDING_OPERATION_SELECTOR, osProvider.createInterceptor()); + } + + if (wfProvider != null) { + bindingChain.addInterceptor(Phase.SERVICE_BINDING_WIREFORMAT, wfProvider.createInterceptor()); + } + + } } |