From 32d17447a258188b2d534bcb0bf65a659ba7b7d0 Mon Sep 17 00:00:00 2001 From: mcentner Date: Fri, 29 Aug 2008 12:11:34 +0000 Subject: Initial import. git-svn-id: https://joinup.ec.europa.eu/svn/mocca/trunk@1 8a26b1a7-26f0-462f-b9ef-d0e30c41f5a4 --- .../gv/egiz/bku/binding/HTTPBindingProcessor.java | 820 +++++++++++++++++++++ 1 file changed, 820 insertions(+) create mode 100644 bkucommon/src/main/java/at/gv/egiz/bku/binding/HTTPBindingProcessor.java (limited to 'bkucommon/src/main/java/at/gv/egiz/bku/binding/HTTPBindingProcessor.java') diff --git a/bkucommon/src/main/java/at/gv/egiz/bku/binding/HTTPBindingProcessor.java b/bkucommon/src/main/java/at/gv/egiz/bku/binding/HTTPBindingProcessor.java new file mode 100644 index 00000000..b79f7d55 --- /dev/null +++ b/bkucommon/src/main/java/at/gv/egiz/bku/binding/HTTPBindingProcessor.java @@ -0,0 +1,820 @@ +/* +* Copyright 2008 Federal Chancellery Austria and +* Graz University of Technology +* +* Licensed 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 at.gv.egiz.bku.binding; + +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.OutputStream; +import java.io.OutputStreamWriter; +import java.io.Reader; +import java.security.cert.X509Certificate; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Locale; +import java.util.Map; + +import javax.net.ssl.SSLHandshakeException; +import javax.xml.transform.Transformer; +import javax.xml.transform.TransformerException; +import javax.xml.transform.TransformerFactory; +import javax.xml.transform.URIResolver; +import javax.xml.transform.stream.StreamResult; +import javax.xml.transform.stream.StreamSource; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import at.gv.egiz.bku.slcommands.SLCommand; +import at.gv.egiz.bku.slcommands.SLCommandContext; +import at.gv.egiz.bku.slcommands.SLCommandFactory; +import at.gv.egiz.bku.slcommands.SLCommandInvoker; +import at.gv.egiz.bku.slcommands.SLResult; +import at.gv.egiz.bku.slcommands.SLSourceContext; +import at.gv.egiz.bku.slcommands.SLTargetContext; +import at.gv.egiz.bku.slcommands.impl.ErrorResultImpl; +import at.gv.egiz.bku.slexceptions.SLBindingException; +import at.gv.egiz.bku.slexceptions.SLCanceledException; +import at.gv.egiz.bku.slexceptions.SLException; +import at.gv.egiz.bku.slexceptions.SLRuntimeException; +import at.gv.egiz.bku.utils.StreamUtil; +import at.gv.egiz.bku.utils.binding.Protocol; +import at.gv.egiz.bku.utils.urldereferencer.FormDataURLSupplier; +import at.gv.egiz.bku.utils.urldereferencer.SimpleFormDataContextImpl; +import at.gv.egiz.bku.utils.urldereferencer.StreamData; +import at.gv.egiz.bku.utils.urldereferencer.URIResolverAdapter; +import at.gv.egiz.bku.utils.urldereferencer.URLDereferencer; +import at.gv.egiz.bku.utils.urldereferencer.URLDereferencerContext; +import at.gv.egiz.stal.QuitRequest; +import at.gv.egiz.stal.STALRequest; + +/** + * Class performing the HTTP binding as defined by the CCE specification. + * Currently a huge monolithic class. + * @TODO refactor + */ +@SuppressWarnings("unchecked") +public class HTTPBindingProcessor extends AbstractBindingProcessor implements + FormDataURLSupplier { + + private static Log log = LogFactory.getLog(HTTPBindingProcessor.class); + + private static enum State { + INIT, PROCESS, DATAURL, TRANSFORM, FINISHED + }; + + public final static Collection XML_REQ_TRANSFER_ENCODING = Arrays + .asList(new String[] { "binary" }); + + /** + * Defines the maximum number of dataurl connects that are allowed within a + * single SL Request processing. + */ + protected static int MAX_DATAURL_HOPS = 10; + + protected static String XML_MIME_TYPE = "text/xml"; + protected static String BINARY_MIME_TYPE = "application/octet-stream"; + + /** + * If null everything is ok and the result is taken from the command invoker. + */ + protected SLException bindingProcessorError; + protected SLCommandInvoker commandInvoker; + protected DataUrlResponse dataUrlResponse; + protected Map headerMap = Collections.EMPTY_MAP; + protected SLCommand slCommand; + protected Map formParameterMap = new HashMap(); + protected SLSourceContext srcContex = new SLSourceContext(); + protected SLTargetContext targetContext = new SLTargetContext(); + protected Protocol protocol; + protected State currentState = State.INIT; + protected Transformer transformer = null; + protected String resultContentType = null; + protected SLResult slResult = null; + protected int responseCode = 200; + protected Map responseHeaders = Collections.EMPTY_MAP; + protected Locale locale = Locale.getDefault(); + + /** + * + * @param id + * may be null. In this case a new session id will be created. + * @param cmdInvoker + * must not be null; + */ + public HTTPBindingProcessor(String id, SLCommandInvoker cmdInvoker, + Protocol protocol) { + super(id); + if ((protocol != Protocol.HTTP) && (protocol != Protocol.HTTPS)) { + throw new SLRuntimeException("Protocol not supported: " + protocol); + } + if (cmdInvoker == null) { + throw new NullPointerException("Commandinvoker cannot be set to null"); + } + commandInvoker = cmdInvoker; + this.protocol = protocol; + srcContex.setSourceProtocol(protocol); + srcContex.setSourceIsDataURL(false); + } + + //---------------------------------------------------------------------------- + // ----------- BEGIN CONVENIENCE METHODS ----------- + + protected void sendSTALQuit() { + log.info("Sending QUIT command to STAL"); + List quit = new ArrayList(1); + quit.add(new QuitRequest()); + getSTAL().handleRequest(quit); + } + + protected String getFormParameterAsString(String formParameterName) { + FormParameter fp = formParameterMap.get(formParameterName); + return getFormParameterAsString(fp); + } + + protected String getFormParameterAsString(FormParameter fp) { + if (fp == null) { + return null; + } + try { + return StreamUtil.asString(fp.getFormParameterValue(), HttpUtil + .getCharset(fp.getFormParameterContentType(), true)); + } catch (IOException e) { + return null; + } + } + + protected String getDataUrl() { + return getFormParameterAsString(FixedFormParameters.DATAURL); + } + + protected String getStyleSheetUrl() { + return getFormParameterAsString(FixedFormParameters.STYLESHEETURL); + } + + protected List getFormParameters(String parameterNamePostfix) { + List resultList = new ArrayList(); + for (Iterator fpi = formParameterMap.keySet().iterator(); fpi + .hasNext();) { + String paramName = fpi.next(); + if (paramName.endsWith(parameterNamePostfix)) { + resultList.add(formParameterMap.get(paramName)); + } + } + return resultList; + } + + protected List getTransferHeaders() { + return getFormParameters("__"); + } + + protected List getTransferForms() { + List resultList = new ArrayList(); + for (Iterator fpi = formParameterMap.keySet().iterator(); fpi + .hasNext();) { + String paramName = fpi.next(); + if ((paramName.endsWith("_")) && (!paramName.endsWith("__"))) { + resultList.add(formParameterMap.get(paramName)); + } + } + return resultList; + } + + protected void closeDataUrlConnection() { + log.debug("Closing data url input stream"); + if (dataUrlResponse == null) { + return; + } + InputStream is = dataUrlResponse.getStream(); + if (is != null) { + try { + is.close(); + } catch (IOException e) { + log.info("Error closing input stream to dataurl server:" + e); + } + } + } + + //---------------------------------------------------------------------------- + // ----------- END CONVENIENCE METHODS ----------- + + //---------------------------------------------------------------------------- + // -- BEGIN Methods that handle the http binding activities as defined in the + // activity diagram -- + + protected void init() { + log.info("Starting Bindingprocessor in Thread: " + + Thread.currentThread().getId()); + if (bindingProcessorError != null) { + log.debug("Detected binding processor error, sending quit command"); + // sendSTALQuit(); + currentState = State.FINISHED; + } else if (slCommand == null) { + log.error("SLCommand not set (consumeRequest not called ??)"); + bindingProcessorError = new SLException(2000); + // sendSTALQuit(); + currentState = State.FINISHED; + } else { + currentState = State.PROCESS; + } + } + + protected void processRequest() { + log.debug("Entered State: " + State.PROCESS); + log.debug("Processing command: " + slCommand); + commandInvoker.setCommand(slCommand); + responseCode = 200; + responseHeaders = Collections.EMPTY_MAP; + try { + commandInvoker.invoke(srcContex); + } catch (SLCanceledException e) { + log.info("Caught exception: " + e); + bindingProcessorError = e; + currentState = State.TRANSFORM; + } + dataUrlResponse = null; + if (getDataUrl() != null) { + log.debug("Data Url set to: " + getDataUrl()); + currentState = State.DATAURL; + } else { + log.debug("No data url set"); + currentState = State.TRANSFORM; + } + } + + protected void handleDataUrl() { + log.debug("Entered State: " + State.DATAURL); + try { + DataUrl dataUrl = new DataUrl(getDataUrl()); + DataUrlConnection conn = dataUrl.openConnection(); + + // set transfer headers + for (FormParameter fp : getTransferHeaders()) { + String paramString = getFormParameterAsString(fp); + if (paramString == null) { + log.error("Got empty transfer header, ignoring this"); + } else { + String[] keyVal = paramString.split(":", 2); + String key = keyVal[0]; + String val = null; + if (keyVal.length == 2) { + val = keyVal[1]; + } + val = val.trim(); + log.debug("Setting header " + key + " to value " + val); + conn.setHTTPHeader(key, val); + } + } + + // set transfer form parameters + for (FormParameter fp : getTransferForms()) { + String contentTransferEncoding = null; + String contentType = fp.getFormParameterContentType(); + String charSet = HttpUtil.getCharset(contentType, false); + if (charSet != null) { + contentType = contentType.substring(0, contentType + .lastIndexOf(HttpUtil.SEPERATOR[0])); + } + for (Iterator header = fp.getHeaderNames(); header.hasNext();) { + if (HttpUtil.CONTENT_TRANSFER_ENCODING + .equalsIgnoreCase(header.next())) { + contentTransferEncoding = getFormParameterAsString(fp); + } + } + log.debug("Setting form: " + fp.getFormParameterName() + + " contentType: " + contentType + " charset: " + charSet + + " contentTransferEncoding: " + contentTransferEncoding); + conn.setHTTPFormParameter(fp.getFormParameterName(), fp + .getFormParameterValue(), contentType, charSet, + contentTransferEncoding); + } + + // connect + conn.connect(); + // fetch and set SL result + targetContext.setTargetIsDataURL(true); + targetContext.setTargetCertificate(conn.getServerCertificate()); + targetContext.setTargetProtocol(conn.getProtocol()); + SLResult result = commandInvoker.getResult(targetContext); + + // transfer result + conn.transmit(result); + + // process Dataurl response + dataUrlResponse = conn.getResponse(); + log.debug("Received data url response code: " + + dataUrlResponse.getResponseCode()); + protocol = Protocol.fromString(conn.getProtocol()); + + switch (dataUrlResponse.getResponseCode()) { + case 200: + String contentType = dataUrlResponse.getContentType(); + log.debug("Got dataurl response content type: " + contentType); + if (contentType != null) { + if ((contentType.startsWith(HttpUtil.APPLICATION_URL_ENCODED)) + || (contentType.startsWith(HttpUtil.MULTIPART_FOTMDATA))) { + log.debug("Detected SL Request in dataurl response"); + // process headers and request + setHTTPHeaders(dataUrlResponse.getResponseHeaders()); + consumeRequestStream(dataUrlResponse.getStream()); + closeDataUrlConnection(); + srcContex.setSourceCertificate(conn.getServerCertificate()); + srcContex.setSourceIsDataURL(true); + srcContex + .setSourceProtocol(Protocol.fromString(conn.getProtocol())); + currentState = State.PROCESS; + } else if (((contentType.startsWith(HttpUtil.TXT_HTML)) + || (contentType.startsWith(HttpUtil.TXT_PLAIN)) || (contentType + .startsWith(HttpUtil.TXT_XML))) + && (dataUrlResponse.isHttpResponseXMLOK())) { + log.info("Dataurl response matches with content type: " + + contentType); + currentState = State.TRANSFORM; + + } else if ((contentType.startsWith(HttpUtil.TXT_XML)) + && (!dataUrlResponse.isHttpResponseXMLOK())) { + log + .debug("Detected text/xml dataurl response with content != "); + headerMap.put(HttpUtil.HTTP_HEADER_CONTENT_TYPE, contentType); + assignXMLRequest(dataUrlResponse.getStream(), HttpUtil.getCharset( + contentType, true)); + closeDataUrlConnection(); + srcContex.setSourceCertificate(conn.getServerCertificate()); + srcContex.setSourceIsDataURL(true); + srcContex + .setSourceProtocol(Protocol.fromString(conn.getProtocol())); + currentState = State.PROCESS; + // just to be complete, actually not used + srcContex.setSourceHTTPReferer(dataUrlResponse.getResponseHeaders() + .get(HttpUtil.HTTP_HEADER_REFERER)); + } else { + resultContentType = contentType; + responseHeaders = dataUrlResponse.getResponseHeaders(); + responseCode = dataUrlResponse.getResponseCode(); + currentState = State.FINISHED; + } + } else { + log.debug("Content type not set in dataurl response"); + closeDataUrlConnection(); + throw new SLBindingException(2007); + } + + break; + case 307: + contentType = dataUrlResponse.getContentType(); + if ((contentType != null) && (contentType.startsWith(HttpUtil.TXT_XML))) { + log.debug("Received dataurl response code 307 with XML content"); + String location = dataUrlResponse.getResponseHeaders().get( + HttpUtil.HTTP_HEADER_LOCATION); + if (location == null) { + log + .error("Did not get a location header for a 307 data url response"); + throw new SLBindingException(2003); + } + // consumeRequestStream(dataUrlResponse.getStream()); + FormParameterStore fp = new FormParameterStore(); + fp.init(location.getBytes(HttpUtil.DEFAULT_CHARSET), + FixedFormParameters.DATAURL, null, null); + formParameterMap.put(FixedFormParameters.DATAURL, fp); + headerMap.put(HttpUtil.HTTP_HEADER_CONTENT_TYPE, contentType); + assignXMLRequest(dataUrlResponse.getStream(), HttpUtil.getCharset( + dataUrlResponse.getContentType(), true)); + closeDataUrlConnection(); + srcContex.setSourceCertificate(conn.getServerCertificate()); + srcContex.setSourceIsDataURL(true); + srcContex.setSourceProtocol(Protocol.fromString(conn.getProtocol())); + currentState = State.PROCESS; + // just to be complete, actually not used + srcContex.setSourceHTTPReferer(dataUrlResponse.getResponseHeaders() + .get(HttpUtil.HTTP_HEADER_REFERER)); + + } else { + log.debug("Received dataurl response code 307 non XML content: " + + dataUrlResponse.getContentType()); + resultContentType = dataUrlResponse.getContentType(); + currentState = State.FINISHED; + } + responseHeaders = dataUrlResponse.getResponseHeaders(); + responseCode = dataUrlResponse.getResponseCode(); + break; + + case 301: + case 302: + case 303: + responseHeaders = dataUrlResponse.getResponseHeaders(); + responseCode = dataUrlResponse.getResponseCode(); + resultContentType = dataUrlResponse.getContentType(); + currentState = State.FINISHED; + break; + + default: + // issue error + log.info("Unexpected response code from dataurl server: " + + dataUrlResponse.getResponseCode()); + throw new SLBindingException(2007); + } + + } catch (SLException slx) { + bindingProcessorError = slx; + log.error("Error during dataurl communication"); + resultContentType = HttpUtil.TXT_XML; + currentState = State.TRANSFORM; + } catch (SSLHandshakeException hx) { + bindingProcessorError = new SLException(2010); + log.info("Error during dataurl communication", hx); + resultContentType = HttpUtil.TXT_XML; + currentState = State.TRANSFORM; + } catch (IOException e) { + bindingProcessorError = new SLBindingException(2001); + log.error("Error while data url handling", e); + resultContentType = HttpUtil.TXT_XML; + currentState = State.TRANSFORM; + return; + } + } + + protected void transformResult() { + log.debug("Entered State: " + State.TRANSFORM); + if (bindingProcessorError != null) { + resultContentType = HttpUtil.TXT_XML; + } else if (dataUrlResponse != null) { + resultContentType = dataUrlResponse.getContentType(); + } else { + targetContext.setTargetIsDataURL(false); + targetContext.setTargetProtocol(protocol.toString()); + try { + slResult = commandInvoker.getResult(targetContext); + resultContentType = slResult.getMimeType(); + log + .debug("Successfully got SLResult from commandinvoker, setting mimetype to: " + + resultContentType); + } catch (SLCanceledException e) { + log.info("Cannot get result from invoker:", e); + bindingProcessorError = new SLException(6002); + resultContentType = HttpUtil.TXT_XML; + } + } + transformer = getTransformer(getStyleSheetUrl()); + if (transformer != null) { + log.debug("Output transformation required"); + resultContentType = transformer.getOutputProperty("media-type"); + log.debug("Got media type from stylesheet: " + resultContentType); + if (resultContentType == null) { + log.debug("Setting to default text/xml result conent type"); + resultContentType = "text/xml"; + } + log.debug("Deferring sytylesheet processing"); + } + currentState = State.FINISHED; + } + + protected void finished() { + log.debug("Entered State: " + State.FINISHED); + if (bindingProcessorError != null) { + log.debug("Binding processor error, sending quit command"); + resultContentType = HttpUtil.TXT_XML; + } + sendSTALQuit(); + log.info("Terminating Bindingprocessor; Thread: " + + Thread.currentThread().getId()); + } + + // -- END Methods that handle the http binding activities as defined in the + // activity diagram -- + //---------------------------------------------------------------------------- + + /** + * Sets the headers of the SL Request. IMPORTANT: make sure to set all headers + * before invoking {@link #consumeRequestStream(InputStream)} + * + * @param aHeaderMap + * if null all header will be cleared. + */ + public void setHTTPHeaders(Map aHeaderMap) { + headerMap = new HashMap(); + // ensure lowercase keys + if (aHeaderMap != null) { + for (String s : aHeaderMap.keySet()) { + if (s != null) { + headerMap.put(s.toLowerCase(), aHeaderMap.get(s)); + if (s.equalsIgnoreCase(HttpUtil.HTTP_HEADER_REFERER)) { + String referer = aHeaderMap.get(s); + log.debug("Got referer header: " + referer); + srcContex.setSourceHTTPReferer(referer); + } + } + } + } + } + + public void setSourceCertificate(X509Certificate aCert) { + srcContex.setSourceCertificate(aCert); + } + + /** + * The HTTPBindingProcessor does not handle redirect URLs. It only provides + * the parameter. + * + * @return null if redirect url is not set. + */ + public String getRedirectURL() { + return getFormParameterAsString(FixedFormParameters.REDIRECTURL); + } + + public String getFormDataContentType(String aParameterName) { + FormParameter fp = formParameterMap.get(aParameterName); + if (fp != null) { + return fp.getFormParameterContentType(); + } + return null; + } + + public InputStream getFormData(String aParameterName) { + FormParameter fp = formParameterMap.get(aParameterName); + if (fp != null) { + return fp.getFormParameterValue(); + } + return null; + } + + protected void assignXMLRequest(InputStream is, String charset) + throws IOException, SLException { + Reader r = new InputStreamReader(is, charset); + StreamSource source = new StreamSource(r); + SLCommandContext commandCtx = new SLCommandContext(); + commandCtx.setSTAL(getSTAL()); + commandCtx.setURLDereferencerContext(new SimpleFormDataContextImpl(this)); + slCommand = SLCommandFactory.getInstance().createSLCommand(source, + commandCtx); + log.debug("Created new command: " + slCommand); + } + + @Override + public void run() { + boolean done = false; + int hopcounter = 0; + if (bindingProcessorError != null) { + currentState = State.FINISHED; + } + try { + while (!done) { + try { + switch (currentState) { + case INIT: + init(); + break; + case PROCESS: + processRequest(); + break; + case DATAURL: + handleDataUrl(); + if (++hopcounter > MAX_DATAURL_HOPS) { + log.error("Maximum number of dataurl hops reached"); + bindingProcessorError = new SLBindingException(2000); + currentState = State.FINISHED; + } + break; + case TRANSFORM: + transformResult(); + break; + case FINISHED: + done = true; + finished(); + break; + } + } catch (RuntimeException rte) { + throw rte; + } catch (Exception t) { + log.error("Caught unexpected exception", t); + responseCode = 200; + resultContentType = HttpUtil.TXT_XML; + responseHeaders = Collections.EMPTY_MAP; + bindingProcessorError = new SLException(2000); + currentState = State.FINISHED; + } + } + } catch (Throwable t) { + log.error("Caught unexpected exception", t); + responseCode = 200; + resultContentType = HttpUtil.TXT_XML; + responseHeaders = Collections.EMPTY_MAP; + bindingProcessorError = new SLException(2000); + currentState = State.FINISHED; + } + log.debug("Terminated http binding processor"); + } + + @Override + public void consumeRequestStream(InputStream is) { + try { + log.debug("Start consuming request stream"); + formParameterMap.clear(); + String cl = headerMap + .get(HttpUtil.HTTP_HEADER_CONTENT_TYPE.toLowerCase()); + if (cl == null) { + log.info("No content type set in http header"); + throw new SLBindingException(2006); + } + InputDecoder id = InputDecoderFactory.getDecoder(cl, is); + id.setContentType(cl); + if (id == null) { + log.error("Cannot get inputdecoder for is"); + throw new SLException(2006); + } + for (Iterator fpi = id.getFormParameterIterator(); fpi + .hasNext();) { + FormParameter fp = fpi.next(); + log.debug("Got request parameter with name: " + + fp.getFormParameterName()); + if (fp.getFormParameterName().equals(FixedFormParameters.XMLREQUEST)) { + log.debug("Creating XML Request"); + for (Iterator headerIterator = fp.getHeaderNames(); headerIterator + .hasNext();) { + String headerName = headerIterator.next(); + if (HttpUtil.CONTENT_TRANSFER_ENCODING.equalsIgnoreCase(headerName)) { + String transferEncoding = fp.getHeaderValue(headerName); + log.debug("Got transfer encoding for xmlrequest: " + + transferEncoding); + if (XML_REQ_TRANSFER_ENCODING.contains(transferEncoding)) { + log.debug("Supported transfer encoding: " + transferEncoding); + } else { + log + .error("Transferencoding not supported: " + + transferEncoding); + throw new SLBindingException(2005); + } + } + } + String charset = HttpUtil.getCharset(cl, true); + assignXMLRequest(fp.getFormParameterValue(), charset); + } else { + FormParameterStore fps = new FormParameterStore(); + fps.init(fp); + if (!fps.isEmpty()) { + log.debug("Setting from parameter: " + fps.getFormParameterName()); + formParameterMap.put(fps.getFormParameterName(), fps); + } + } + } + if (slCommand == null) { + throw new SLBindingException(2004); + } + if (is.read() != -1) { + log.error("Request input stream not completely read"); + // consume rest of stream, should never occur + throw new SLRuntimeException( + "request input stream not consumed till end"); + } + } catch (SLException slx) { + log.info("Error while consuming input stream " + slx); + bindingProcessorError = slx; + } catch (Throwable t) { + log.info("Error while consuming input stream " + t, t); + bindingProcessorError = new SLException(2000); + } finally { + try { + while (is.read() != -1) + ; + } catch (IOException e) { + log.error(e); + } + } + } + + @Override + public String getResultContentType() { + return resultContentType; + } + + protected Transformer getTransformer(String styleSheetURL) { + if (styleSheetURL == null) { + log.debug("Stylesheet URL not set"); + return null; + } + try { + URLDereferencerContext urlCtx = new SimpleFormDataContextImpl(this); + URIResolver resolver = new URIResolverAdapter(URLDereferencer + .getInstance(), urlCtx); + TransformerFactory factory = TransformerFactory.newInstance(); + StreamData sd = URLDereferencer.getInstance().dereference(styleSheetURL, + urlCtx); + Transformer t = factory.newTransformer(new StreamSource(sd.getStream())); + t.setURIResolver(resolver); + return t; + } catch (Exception ex) { + log.info("Cannot instantiate transformer", ex); + bindingProcessorError = new SLException(2002); + return null; + } + } + + protected void handleBindingProcessorError(OutputStream os, String encoding, + Transformer transformer) throws IOException { + log.debug("Writing error as result"); + ErrorResultImpl error = new ErrorResultImpl(bindingProcessorError); + try { + error.writeTo(new StreamResult(new OutputStreamWriter(os, encoding)), + transformer); + } catch (TransformerException e) { + log.fatal("Cannot write error result to stream", e); + } + } + + @Override + public void writeResultTo(OutputStream os, String encoding) + throws IOException { + if (encoding == null) { + encoding = HttpUtil.DEFAULT_CHARSET; + } + if (bindingProcessorError != null) { + log.debug("Detected error in binding processor, writing error as result"); + handleBindingProcessorError(os, encoding, transformer); + return; + } else if (dataUrlResponse != null) { + log.debug("Writing data url response as result"); + String charEnc = HttpUtil.getCharset(dataUrlResponse.getContentType(), + true); + InputStreamReader isr = new InputStreamReader( + dataUrlResponse.getStream(), charEnc); + OutputStreamWriter osw = new OutputStreamWriter(os, encoding); + if (transformer == null) { + StreamUtil.copyStream(isr, osw); + } else { + try { + transformer.transform(new StreamSource(isr), new StreamResult(osw)); + } catch (TransformerException e) { + log.fatal("Exception occured during result transformation", e); + // bindingProcessorError = new SLException(2008); + // handleBindingProcessorError(os, encoding, null); + return; + } + } + osw.flush(); + isr.close(); + } else if (slResult == null) { + // result not yet assigned -> must be a cancel + bindingProcessorError = new SLException(6001); + handleBindingProcessorError(os, encoding, transformer); + return; + } else { + log.debug("Getting result from invoker"); + OutputStreamWriter osw = new OutputStreamWriter(os, encoding); + try { + slResult.writeTo(new StreamResult(osw), transformer); + } catch (TransformerException e) { + log.fatal("Cannot write result to stream", e); + // bindingProcessorError = new SLException(2008); + // handleBindingProcessorError(os, encoding, transformer); + } + osw.flush(); + } + } + + /** + * The response code from the dataurl server or 200 if no dataurl server + * created the result + * + * @return + */ + public int getResponseCode() { + return responseCode; + } + + /** + * All headers from the data url server in case of a direct forward from the + * dataurl server. + * + * @return + */ + public Map getResponseHeaders() { + return responseHeaders; + } + + @Override + public void setLocale(Locale locale) { + if (locale == null) { + throw new NullPointerException("Locale must not be set to null"); + } + this.locale = locale; + } + +} \ No newline at end of file -- cgit v1.2.3 From e0f2c64ad6360e2ecec983cb5e0a60f812672106 Mon Sep 17 00:00:00 2001 From: wbauer Date: Thu, 4 Sep 2008 14:56:54 +0000 Subject: finished access controller, accessed it from command invoker and configured everything within onlinebku git-svn-id: https://joinup.ec.europa.eu/svn/mocca/trunk@14 8a26b1a7-26f0-462f-b9ef-d0e30c41f5a4 --- .../gv/egiz/bku/binding/HTTPBindingProcessor.java | 1634 ++++++++++---------- 1 file changed, 816 insertions(+), 818 deletions(-) (limited to 'bkucommon/src/main/java/at/gv/egiz/bku/binding/HTTPBindingProcessor.java') diff --git a/bkucommon/src/main/java/at/gv/egiz/bku/binding/HTTPBindingProcessor.java b/bkucommon/src/main/java/at/gv/egiz/bku/binding/HTTPBindingProcessor.java index b79f7d55..19f22126 100644 --- a/bkucommon/src/main/java/at/gv/egiz/bku/binding/HTTPBindingProcessor.java +++ b/bkucommon/src/main/java/at/gv/egiz/bku/binding/HTTPBindingProcessor.java @@ -1,820 +1,818 @@ /* -* Copyright 2008 Federal Chancellery Austria and -* Graz University of Technology -* -* Licensed 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 at.gv.egiz.bku.binding; - -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.io.OutputStream; -import java.io.OutputStreamWriter; -import java.io.Reader; -import java.security.cert.X509Certificate; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Locale; -import java.util.Map; - -import javax.net.ssl.SSLHandshakeException; -import javax.xml.transform.Transformer; -import javax.xml.transform.TransformerException; -import javax.xml.transform.TransformerFactory; -import javax.xml.transform.URIResolver; -import javax.xml.transform.stream.StreamResult; -import javax.xml.transform.stream.StreamSource; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -import at.gv.egiz.bku.slcommands.SLCommand; -import at.gv.egiz.bku.slcommands.SLCommandContext; -import at.gv.egiz.bku.slcommands.SLCommandFactory; -import at.gv.egiz.bku.slcommands.SLCommandInvoker; -import at.gv.egiz.bku.slcommands.SLResult; -import at.gv.egiz.bku.slcommands.SLSourceContext; -import at.gv.egiz.bku.slcommands.SLTargetContext; -import at.gv.egiz.bku.slcommands.impl.ErrorResultImpl; -import at.gv.egiz.bku.slexceptions.SLBindingException; -import at.gv.egiz.bku.slexceptions.SLCanceledException; -import at.gv.egiz.bku.slexceptions.SLException; -import at.gv.egiz.bku.slexceptions.SLRuntimeException; -import at.gv.egiz.bku.utils.StreamUtil; -import at.gv.egiz.bku.utils.binding.Protocol; -import at.gv.egiz.bku.utils.urldereferencer.FormDataURLSupplier; -import at.gv.egiz.bku.utils.urldereferencer.SimpleFormDataContextImpl; -import at.gv.egiz.bku.utils.urldereferencer.StreamData; -import at.gv.egiz.bku.utils.urldereferencer.URIResolverAdapter; -import at.gv.egiz.bku.utils.urldereferencer.URLDereferencer; -import at.gv.egiz.bku.utils.urldereferencer.URLDereferencerContext; -import at.gv.egiz.stal.QuitRequest; -import at.gv.egiz.stal.STALRequest; - -/** - * Class performing the HTTP binding as defined by the CCE specification. - * Currently a huge monolithic class. - * @TODO refactor - */ -@SuppressWarnings("unchecked") -public class HTTPBindingProcessor extends AbstractBindingProcessor implements - FormDataURLSupplier { - - private static Log log = LogFactory.getLog(HTTPBindingProcessor.class); - - private static enum State { - INIT, PROCESS, DATAURL, TRANSFORM, FINISHED - }; - - public final static Collection XML_REQ_TRANSFER_ENCODING = Arrays - .asList(new String[] { "binary" }); - - /** - * Defines the maximum number of dataurl connects that are allowed within a - * single SL Request processing. - */ - protected static int MAX_DATAURL_HOPS = 10; - - protected static String XML_MIME_TYPE = "text/xml"; - protected static String BINARY_MIME_TYPE = "application/octet-stream"; - - /** - * If null everything is ok and the result is taken from the command invoker. - */ - protected SLException bindingProcessorError; - protected SLCommandInvoker commandInvoker; - protected DataUrlResponse dataUrlResponse; - protected Map headerMap = Collections.EMPTY_MAP; - protected SLCommand slCommand; - protected Map formParameterMap = new HashMap(); - protected SLSourceContext srcContex = new SLSourceContext(); - protected SLTargetContext targetContext = new SLTargetContext(); - protected Protocol protocol; - protected State currentState = State.INIT; - protected Transformer transformer = null; - protected String resultContentType = null; - protected SLResult slResult = null; - protected int responseCode = 200; - protected Map responseHeaders = Collections.EMPTY_MAP; - protected Locale locale = Locale.getDefault(); - - /** - * - * @param id - * may be null. In this case a new session id will be created. - * @param cmdInvoker - * must not be null; - */ - public HTTPBindingProcessor(String id, SLCommandInvoker cmdInvoker, - Protocol protocol) { - super(id); - if ((protocol != Protocol.HTTP) && (protocol != Protocol.HTTPS)) { - throw new SLRuntimeException("Protocol not supported: " + protocol); - } - if (cmdInvoker == null) { - throw new NullPointerException("Commandinvoker cannot be set to null"); - } - commandInvoker = cmdInvoker; - this.protocol = protocol; - srcContex.setSourceProtocol(protocol); - srcContex.setSourceIsDataURL(false); - } - - //---------------------------------------------------------------------------- - // ----------- BEGIN CONVENIENCE METHODS ----------- - - protected void sendSTALQuit() { - log.info("Sending QUIT command to STAL"); - List quit = new ArrayList(1); - quit.add(new QuitRequest()); - getSTAL().handleRequest(quit); - } - - protected String getFormParameterAsString(String formParameterName) { - FormParameter fp = formParameterMap.get(formParameterName); - return getFormParameterAsString(fp); - } - - protected String getFormParameterAsString(FormParameter fp) { - if (fp == null) { - return null; - } - try { - return StreamUtil.asString(fp.getFormParameterValue(), HttpUtil - .getCharset(fp.getFormParameterContentType(), true)); - } catch (IOException e) { - return null; - } - } - - protected String getDataUrl() { - return getFormParameterAsString(FixedFormParameters.DATAURL); - } - - protected String getStyleSheetUrl() { - return getFormParameterAsString(FixedFormParameters.STYLESHEETURL); - } - - protected List getFormParameters(String parameterNamePostfix) { - List resultList = new ArrayList(); - for (Iterator fpi = formParameterMap.keySet().iterator(); fpi - .hasNext();) { - String paramName = fpi.next(); - if (paramName.endsWith(parameterNamePostfix)) { - resultList.add(formParameterMap.get(paramName)); - } - } - return resultList; - } - - protected List getTransferHeaders() { - return getFormParameters("__"); - } - - protected List getTransferForms() { - List resultList = new ArrayList(); - for (Iterator fpi = formParameterMap.keySet().iterator(); fpi - .hasNext();) { - String paramName = fpi.next(); - if ((paramName.endsWith("_")) && (!paramName.endsWith("__"))) { - resultList.add(formParameterMap.get(paramName)); - } - } - return resultList; - } - - protected void closeDataUrlConnection() { - log.debug("Closing data url input stream"); - if (dataUrlResponse == null) { - return; - } - InputStream is = dataUrlResponse.getStream(); - if (is != null) { - try { - is.close(); - } catch (IOException e) { - log.info("Error closing input stream to dataurl server:" + e); - } - } - } - - //---------------------------------------------------------------------------- - // ----------- END CONVENIENCE METHODS ----------- - - //---------------------------------------------------------------------------- - // -- BEGIN Methods that handle the http binding activities as defined in the - // activity diagram -- - - protected void init() { - log.info("Starting Bindingprocessor in Thread: " - + Thread.currentThread().getId()); - if (bindingProcessorError != null) { - log.debug("Detected binding processor error, sending quit command"); - // sendSTALQuit(); - currentState = State.FINISHED; - } else if (slCommand == null) { - log.error("SLCommand not set (consumeRequest not called ??)"); - bindingProcessorError = new SLException(2000); - // sendSTALQuit(); - currentState = State.FINISHED; - } else { - currentState = State.PROCESS; - } - } - - protected void processRequest() { - log.debug("Entered State: " + State.PROCESS); - log.debug("Processing command: " + slCommand); - commandInvoker.setCommand(slCommand); - responseCode = 200; - responseHeaders = Collections.EMPTY_MAP; - try { - commandInvoker.invoke(srcContex); - } catch (SLCanceledException e) { - log.info("Caught exception: " + e); - bindingProcessorError = e; - currentState = State.TRANSFORM; - } - dataUrlResponse = null; - if (getDataUrl() != null) { - log.debug("Data Url set to: " + getDataUrl()); - currentState = State.DATAURL; - } else { - log.debug("No data url set"); - currentState = State.TRANSFORM; - } - } - - protected void handleDataUrl() { - log.debug("Entered State: " + State.DATAURL); - try { - DataUrl dataUrl = new DataUrl(getDataUrl()); - DataUrlConnection conn = dataUrl.openConnection(); - - // set transfer headers - for (FormParameter fp : getTransferHeaders()) { - String paramString = getFormParameterAsString(fp); - if (paramString == null) { - log.error("Got empty transfer header, ignoring this"); - } else { - String[] keyVal = paramString.split(":", 2); - String key = keyVal[0]; - String val = null; - if (keyVal.length == 2) { - val = keyVal[1]; - } - val = val.trim(); - log.debug("Setting header " + key + " to value " + val); - conn.setHTTPHeader(key, val); - } - } - - // set transfer form parameters - for (FormParameter fp : getTransferForms()) { - String contentTransferEncoding = null; - String contentType = fp.getFormParameterContentType(); - String charSet = HttpUtil.getCharset(contentType, false); - if (charSet != null) { - contentType = contentType.substring(0, contentType - .lastIndexOf(HttpUtil.SEPERATOR[0])); - } - for (Iterator header = fp.getHeaderNames(); header.hasNext();) { - if (HttpUtil.CONTENT_TRANSFER_ENCODING - .equalsIgnoreCase(header.next())) { - contentTransferEncoding = getFormParameterAsString(fp); - } - } - log.debug("Setting form: " + fp.getFormParameterName() - + " contentType: " + contentType + " charset: " + charSet - + " contentTransferEncoding: " + contentTransferEncoding); - conn.setHTTPFormParameter(fp.getFormParameterName(), fp - .getFormParameterValue(), contentType, charSet, - contentTransferEncoding); - } - - // connect - conn.connect(); - // fetch and set SL result - targetContext.setTargetIsDataURL(true); - targetContext.setTargetCertificate(conn.getServerCertificate()); - targetContext.setTargetProtocol(conn.getProtocol()); - SLResult result = commandInvoker.getResult(targetContext); - - // transfer result - conn.transmit(result); - - // process Dataurl response - dataUrlResponse = conn.getResponse(); - log.debug("Received data url response code: " - + dataUrlResponse.getResponseCode()); - protocol = Protocol.fromString(conn.getProtocol()); - - switch (dataUrlResponse.getResponseCode()) { - case 200: - String contentType = dataUrlResponse.getContentType(); - log.debug("Got dataurl response content type: " + contentType); - if (contentType != null) { - if ((contentType.startsWith(HttpUtil.APPLICATION_URL_ENCODED)) - || (contentType.startsWith(HttpUtil.MULTIPART_FOTMDATA))) { - log.debug("Detected SL Request in dataurl response"); - // process headers and request - setHTTPHeaders(dataUrlResponse.getResponseHeaders()); - consumeRequestStream(dataUrlResponse.getStream()); - closeDataUrlConnection(); - srcContex.setSourceCertificate(conn.getServerCertificate()); - srcContex.setSourceIsDataURL(true); - srcContex - .setSourceProtocol(Protocol.fromString(conn.getProtocol())); - currentState = State.PROCESS; - } else if (((contentType.startsWith(HttpUtil.TXT_HTML)) - || (contentType.startsWith(HttpUtil.TXT_PLAIN)) || (contentType - .startsWith(HttpUtil.TXT_XML))) - && (dataUrlResponse.isHttpResponseXMLOK())) { - log.info("Dataurl response matches with content type: " - + contentType); - currentState = State.TRANSFORM; - - } else if ((contentType.startsWith(HttpUtil.TXT_XML)) - && (!dataUrlResponse.isHttpResponseXMLOK())) { - log - .debug("Detected text/xml dataurl response with content != "); - headerMap.put(HttpUtil.HTTP_HEADER_CONTENT_TYPE, contentType); - assignXMLRequest(dataUrlResponse.getStream(), HttpUtil.getCharset( - contentType, true)); - closeDataUrlConnection(); - srcContex.setSourceCertificate(conn.getServerCertificate()); - srcContex.setSourceIsDataURL(true); - srcContex - .setSourceProtocol(Protocol.fromString(conn.getProtocol())); - currentState = State.PROCESS; - // just to be complete, actually not used - srcContex.setSourceHTTPReferer(dataUrlResponse.getResponseHeaders() - .get(HttpUtil.HTTP_HEADER_REFERER)); - } else { - resultContentType = contentType; - responseHeaders = dataUrlResponse.getResponseHeaders(); - responseCode = dataUrlResponse.getResponseCode(); - currentState = State.FINISHED; - } - } else { - log.debug("Content type not set in dataurl response"); - closeDataUrlConnection(); - throw new SLBindingException(2007); - } - - break; - case 307: - contentType = dataUrlResponse.getContentType(); - if ((contentType != null) && (contentType.startsWith(HttpUtil.TXT_XML))) { - log.debug("Received dataurl response code 307 with XML content"); - String location = dataUrlResponse.getResponseHeaders().get( - HttpUtil.HTTP_HEADER_LOCATION); - if (location == null) { - log - .error("Did not get a location header for a 307 data url response"); - throw new SLBindingException(2003); - } - // consumeRequestStream(dataUrlResponse.getStream()); - FormParameterStore fp = new FormParameterStore(); - fp.init(location.getBytes(HttpUtil.DEFAULT_CHARSET), - FixedFormParameters.DATAURL, null, null); - formParameterMap.put(FixedFormParameters.DATAURL, fp); - headerMap.put(HttpUtil.HTTP_HEADER_CONTENT_TYPE, contentType); - assignXMLRequest(dataUrlResponse.getStream(), HttpUtil.getCharset( - dataUrlResponse.getContentType(), true)); - closeDataUrlConnection(); - srcContex.setSourceCertificate(conn.getServerCertificate()); - srcContex.setSourceIsDataURL(true); - srcContex.setSourceProtocol(Protocol.fromString(conn.getProtocol())); - currentState = State.PROCESS; - // just to be complete, actually not used - srcContex.setSourceHTTPReferer(dataUrlResponse.getResponseHeaders() - .get(HttpUtil.HTTP_HEADER_REFERER)); - - } else { - log.debug("Received dataurl response code 307 non XML content: " - + dataUrlResponse.getContentType()); - resultContentType = dataUrlResponse.getContentType(); - currentState = State.FINISHED; - } - responseHeaders = dataUrlResponse.getResponseHeaders(); - responseCode = dataUrlResponse.getResponseCode(); - break; - - case 301: - case 302: - case 303: - responseHeaders = dataUrlResponse.getResponseHeaders(); - responseCode = dataUrlResponse.getResponseCode(); - resultContentType = dataUrlResponse.getContentType(); - currentState = State.FINISHED; - break; - - default: - // issue error - log.info("Unexpected response code from dataurl server: " - + dataUrlResponse.getResponseCode()); - throw new SLBindingException(2007); - } - - } catch (SLException slx) { - bindingProcessorError = slx; - log.error("Error during dataurl communication"); - resultContentType = HttpUtil.TXT_XML; - currentState = State.TRANSFORM; - } catch (SSLHandshakeException hx) { - bindingProcessorError = new SLException(2010); - log.info("Error during dataurl communication", hx); - resultContentType = HttpUtil.TXT_XML; - currentState = State.TRANSFORM; - } catch (IOException e) { - bindingProcessorError = new SLBindingException(2001); - log.error("Error while data url handling", e); - resultContentType = HttpUtil.TXT_XML; - currentState = State.TRANSFORM; - return; - } - } - - protected void transformResult() { - log.debug("Entered State: " + State.TRANSFORM); - if (bindingProcessorError != null) { - resultContentType = HttpUtil.TXT_XML; - } else if (dataUrlResponse != null) { - resultContentType = dataUrlResponse.getContentType(); - } else { - targetContext.setTargetIsDataURL(false); - targetContext.setTargetProtocol(protocol.toString()); - try { - slResult = commandInvoker.getResult(targetContext); - resultContentType = slResult.getMimeType(); - log - .debug("Successfully got SLResult from commandinvoker, setting mimetype to: " - + resultContentType); - } catch (SLCanceledException e) { - log.info("Cannot get result from invoker:", e); - bindingProcessorError = new SLException(6002); - resultContentType = HttpUtil.TXT_XML; - } - } - transformer = getTransformer(getStyleSheetUrl()); - if (transformer != null) { - log.debug("Output transformation required"); - resultContentType = transformer.getOutputProperty("media-type"); - log.debug("Got media type from stylesheet: " + resultContentType); - if (resultContentType == null) { - log.debug("Setting to default text/xml result conent type"); - resultContentType = "text/xml"; - } - log.debug("Deferring sytylesheet processing"); - } - currentState = State.FINISHED; - } - - protected void finished() { - log.debug("Entered State: " + State.FINISHED); - if (bindingProcessorError != null) { - log.debug("Binding processor error, sending quit command"); - resultContentType = HttpUtil.TXT_XML; - } - sendSTALQuit(); - log.info("Terminating Bindingprocessor; Thread: " - + Thread.currentThread().getId()); - } - - // -- END Methods that handle the http binding activities as defined in the - // activity diagram -- - //---------------------------------------------------------------------------- - - /** - * Sets the headers of the SL Request. IMPORTANT: make sure to set all headers - * before invoking {@link #consumeRequestStream(InputStream)} - * - * @param aHeaderMap - * if null all header will be cleared. - */ - public void setHTTPHeaders(Map aHeaderMap) { - headerMap = new HashMap(); - // ensure lowercase keys - if (aHeaderMap != null) { - for (String s : aHeaderMap.keySet()) { - if (s != null) { - headerMap.put(s.toLowerCase(), aHeaderMap.get(s)); - if (s.equalsIgnoreCase(HttpUtil.HTTP_HEADER_REFERER)) { - String referer = aHeaderMap.get(s); - log.debug("Got referer header: " + referer); - srcContex.setSourceHTTPReferer(referer); - } - } - } - } - } - - public void setSourceCertificate(X509Certificate aCert) { - srcContex.setSourceCertificate(aCert); - } - - /** - * The HTTPBindingProcessor does not handle redirect URLs. It only provides - * the parameter. - * - * @return null if redirect url is not set. - */ - public String getRedirectURL() { - return getFormParameterAsString(FixedFormParameters.REDIRECTURL); - } - - public String getFormDataContentType(String aParameterName) { - FormParameter fp = formParameterMap.get(aParameterName); - if (fp != null) { - return fp.getFormParameterContentType(); - } - return null; - } - - public InputStream getFormData(String aParameterName) { - FormParameter fp = formParameterMap.get(aParameterName); - if (fp != null) { - return fp.getFormParameterValue(); - } - return null; - } - - protected void assignXMLRequest(InputStream is, String charset) - throws IOException, SLException { - Reader r = new InputStreamReader(is, charset); - StreamSource source = new StreamSource(r); - SLCommandContext commandCtx = new SLCommandContext(); - commandCtx.setSTAL(getSTAL()); - commandCtx.setURLDereferencerContext(new SimpleFormDataContextImpl(this)); - slCommand = SLCommandFactory.getInstance().createSLCommand(source, - commandCtx); - log.debug("Created new command: " + slCommand); - } - - @Override - public void run() { - boolean done = false; - int hopcounter = 0; - if (bindingProcessorError != null) { - currentState = State.FINISHED; - } - try { - while (!done) { - try { - switch (currentState) { - case INIT: - init(); - break; - case PROCESS: - processRequest(); - break; - case DATAURL: - handleDataUrl(); - if (++hopcounter > MAX_DATAURL_HOPS) { - log.error("Maximum number of dataurl hops reached"); - bindingProcessorError = new SLBindingException(2000); - currentState = State.FINISHED; - } - break; - case TRANSFORM: - transformResult(); - break; - case FINISHED: - done = true; - finished(); - break; - } - } catch (RuntimeException rte) { - throw rte; - } catch (Exception t) { - log.error("Caught unexpected exception", t); - responseCode = 200; - resultContentType = HttpUtil.TXT_XML; - responseHeaders = Collections.EMPTY_MAP; - bindingProcessorError = new SLException(2000); - currentState = State.FINISHED; - } - } - } catch (Throwable t) { - log.error("Caught unexpected exception", t); - responseCode = 200; - resultContentType = HttpUtil.TXT_XML; - responseHeaders = Collections.EMPTY_MAP; - bindingProcessorError = new SLException(2000); - currentState = State.FINISHED; - } - log.debug("Terminated http binding processor"); - } - - @Override - public void consumeRequestStream(InputStream is) { - try { - log.debug("Start consuming request stream"); - formParameterMap.clear(); - String cl = headerMap - .get(HttpUtil.HTTP_HEADER_CONTENT_TYPE.toLowerCase()); - if (cl == null) { - log.info("No content type set in http header"); - throw new SLBindingException(2006); - } - InputDecoder id = InputDecoderFactory.getDecoder(cl, is); - id.setContentType(cl); - if (id == null) { - log.error("Cannot get inputdecoder for is"); - throw new SLException(2006); - } - for (Iterator fpi = id.getFormParameterIterator(); fpi - .hasNext();) { - FormParameter fp = fpi.next(); - log.debug("Got request parameter with name: " - + fp.getFormParameterName()); - if (fp.getFormParameterName().equals(FixedFormParameters.XMLREQUEST)) { - log.debug("Creating XML Request"); - for (Iterator headerIterator = fp.getHeaderNames(); headerIterator - .hasNext();) { - String headerName = headerIterator.next(); - if (HttpUtil.CONTENT_TRANSFER_ENCODING.equalsIgnoreCase(headerName)) { - String transferEncoding = fp.getHeaderValue(headerName); - log.debug("Got transfer encoding for xmlrequest: " - + transferEncoding); - if (XML_REQ_TRANSFER_ENCODING.contains(transferEncoding)) { - log.debug("Supported transfer encoding: " + transferEncoding); - } else { - log - .error("Transferencoding not supported: " - + transferEncoding); - throw new SLBindingException(2005); - } - } - } - String charset = HttpUtil.getCharset(cl, true); - assignXMLRequest(fp.getFormParameterValue(), charset); - } else { - FormParameterStore fps = new FormParameterStore(); - fps.init(fp); - if (!fps.isEmpty()) { - log.debug("Setting from parameter: " + fps.getFormParameterName()); - formParameterMap.put(fps.getFormParameterName(), fps); - } - } - } - if (slCommand == null) { - throw new SLBindingException(2004); - } - if (is.read() != -1) { - log.error("Request input stream not completely read"); - // consume rest of stream, should never occur - throw new SLRuntimeException( - "request input stream not consumed till end"); - } - } catch (SLException slx) { - log.info("Error while consuming input stream " + slx); - bindingProcessorError = slx; - } catch (Throwable t) { - log.info("Error while consuming input stream " + t, t); - bindingProcessorError = new SLException(2000); - } finally { - try { - while (is.read() != -1) - ; - } catch (IOException e) { - log.error(e); - } - } - } - - @Override - public String getResultContentType() { - return resultContentType; - } - - protected Transformer getTransformer(String styleSheetURL) { - if (styleSheetURL == null) { - log.debug("Stylesheet URL not set"); - return null; - } - try { - URLDereferencerContext urlCtx = new SimpleFormDataContextImpl(this); - URIResolver resolver = new URIResolverAdapter(URLDereferencer - .getInstance(), urlCtx); - TransformerFactory factory = TransformerFactory.newInstance(); - StreamData sd = URLDereferencer.getInstance().dereference(styleSheetURL, - urlCtx); - Transformer t = factory.newTransformer(new StreamSource(sd.getStream())); - t.setURIResolver(resolver); - return t; - } catch (Exception ex) { - log.info("Cannot instantiate transformer", ex); - bindingProcessorError = new SLException(2002); - return null; - } - } - - protected void handleBindingProcessorError(OutputStream os, String encoding, - Transformer transformer) throws IOException { - log.debug("Writing error as result"); - ErrorResultImpl error = new ErrorResultImpl(bindingProcessorError); - try { - error.writeTo(new StreamResult(new OutputStreamWriter(os, encoding)), - transformer); - } catch (TransformerException e) { - log.fatal("Cannot write error result to stream", e); - } - } - - @Override - public void writeResultTo(OutputStream os, String encoding) - throws IOException { - if (encoding == null) { - encoding = HttpUtil.DEFAULT_CHARSET; - } - if (bindingProcessorError != null) { - log.debug("Detected error in binding processor, writing error as result"); - handleBindingProcessorError(os, encoding, transformer); - return; - } else if (dataUrlResponse != null) { - log.debug("Writing data url response as result"); - String charEnc = HttpUtil.getCharset(dataUrlResponse.getContentType(), - true); - InputStreamReader isr = new InputStreamReader( - dataUrlResponse.getStream(), charEnc); - OutputStreamWriter osw = new OutputStreamWriter(os, encoding); - if (transformer == null) { - StreamUtil.copyStream(isr, osw); - } else { - try { - transformer.transform(new StreamSource(isr), new StreamResult(osw)); - } catch (TransformerException e) { - log.fatal("Exception occured during result transformation", e); - // bindingProcessorError = new SLException(2008); - // handleBindingProcessorError(os, encoding, null); - return; - } - } - osw.flush(); - isr.close(); - } else if (slResult == null) { - // result not yet assigned -> must be a cancel - bindingProcessorError = new SLException(6001); - handleBindingProcessorError(os, encoding, transformer); - return; - } else { - log.debug("Getting result from invoker"); - OutputStreamWriter osw = new OutputStreamWriter(os, encoding); - try { - slResult.writeTo(new StreamResult(osw), transformer); - } catch (TransformerException e) { - log.fatal("Cannot write result to stream", e); - // bindingProcessorError = new SLException(2008); - // handleBindingProcessorError(os, encoding, transformer); - } - osw.flush(); - } - } - - /** - * The response code from the dataurl server or 200 if no dataurl server - * created the result - * - * @return - */ - public int getResponseCode() { - return responseCode; - } - - /** - * All headers from the data url server in case of a direct forward from the - * dataurl server. - * - * @return - */ - public Map getResponseHeaders() { - return responseHeaders; - } - - @Override - public void setLocale(Locale locale) { - if (locale == null) { - throw new NullPointerException("Locale must not be set to null"); - } - this.locale = locale; - } - + * Copyright 2008 Federal Chancellery Austria and + * Graz University of Technology + * + * Licensed 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 at.gv.egiz.bku.binding; + +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.OutputStream; +import java.io.OutputStreamWriter; +import java.io.Reader; +import java.net.URL; +import java.security.cert.X509Certificate; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Locale; +import java.util.Map; + +import javax.net.ssl.SSLHandshakeException; +import javax.xml.transform.Transformer; +import javax.xml.transform.TransformerException; +import javax.xml.transform.TransformerFactory; +import javax.xml.transform.URIResolver; +import javax.xml.transform.stream.StreamResult; +import javax.xml.transform.stream.StreamSource; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import at.gv.egiz.bku.slcommands.SLCommand; +import at.gv.egiz.bku.slcommands.SLCommandContext; +import at.gv.egiz.bku.slcommands.SLCommandFactory; +import at.gv.egiz.bku.slcommands.SLCommandInvoker; +import at.gv.egiz.bku.slcommands.SLResult; +import at.gv.egiz.bku.slcommands.SLSourceContext; +import at.gv.egiz.bku.slcommands.SLTargetContext; +import at.gv.egiz.bku.slcommands.impl.ErrorResultImpl; +import at.gv.egiz.bku.slexceptions.SLBindingException; +import at.gv.egiz.bku.slexceptions.SLException; +import at.gv.egiz.bku.slexceptions.SLRuntimeException; +import at.gv.egiz.bku.utils.StreamUtil; +import at.gv.egiz.bku.utils.binding.Protocol; +import at.gv.egiz.bku.utils.urldereferencer.FormDataURLSupplier; +import at.gv.egiz.bku.utils.urldereferencer.SimpleFormDataContextImpl; +import at.gv.egiz.bku.utils.urldereferencer.StreamData; +import at.gv.egiz.bku.utils.urldereferencer.URIResolverAdapter; +import at.gv.egiz.bku.utils.urldereferencer.URLDereferencer; +import at.gv.egiz.bku.utils.urldereferencer.URLDereferencerContext; +import at.gv.egiz.stal.QuitRequest; +import at.gv.egiz.stal.STALRequest; + +/** + * Class performing the HTTP binding as defined by the CCE specification. + * Currently a huge monolithic class. + * + * @TODO refactor + */ +@SuppressWarnings("unchecked") +public class HTTPBindingProcessor extends AbstractBindingProcessor implements + FormDataURLSupplier { + + private static Log log = LogFactory.getLog(HTTPBindingProcessor.class); + + private static enum State { + INIT, PROCESS, DATAURL, TRANSFORM, FINISHED + }; + + public final static Collection XML_REQ_TRANSFER_ENCODING = Arrays + .asList(new String[] { "binary" }); + + /** + * Defines the maximum number of dataurl connects that are allowed within a + * single SL Request processing. + */ + protected static int MAX_DATAURL_HOPS = 10; + + protected static String XML_MIME_TYPE = "text/xml"; + protected static String BINARY_MIME_TYPE = "application/octet-stream"; + + /** + * If null everything is ok and the result is taken from the command invoker. + */ + protected SLException bindingProcessorError; + protected SLCommandInvoker commandInvoker; + protected DataUrlResponse dataUrlResponse; + protected Map headerMap = Collections.EMPTY_MAP; + protected SLCommand slCommand; + protected Map formParameterMap = new HashMap(); + protected SLSourceContext srcContex = new SLSourceContext(); + protected SLTargetContext targetContext = new SLTargetContext(); + protected URL srcUrl; + protected State currentState = State.INIT; + protected Transformer transformer = null; + protected String resultContentType = null; + protected SLResult slResult = null; + protected int responseCode = 200; + protected Map responseHeaders = Collections.EMPTY_MAP; + protected Locale locale = Locale.getDefault(); + + /** + * + * @param id + * may be null. In this case a new session id will be created. + * @param cmdInvoker + * must not be null; + */ + public HTTPBindingProcessor(String id, SLCommandInvoker cmdInvoker, URL source) { + super(id); + this.srcUrl = source; + Protocol protocol = Protocol.fromString(source.getProtocol()); + if ((protocol != Protocol.HTTP) && (protocol != Protocol.HTTPS)) { + throw new SLRuntimeException("Protocol not supported: " + protocol); + } + if (cmdInvoker == null) { + throw new NullPointerException("Commandinvoker cannot be set to null"); + } + commandInvoker = cmdInvoker; + srcContex.setSourceUrl(source); + srcContex.setSourceIsDataURL(false); + } + + //---------------------------------------------------------------------------- + // ----------- BEGIN CONVENIENCE METHODS ----------- + + protected void sendSTALQuit() { + log.info("Sending QUIT command to STAL"); + List quit = new ArrayList(1); + quit.add(new QuitRequest()); + getSTAL().handleRequest(quit); + } + + protected String getFormParameterAsString(String formParameterName) { + FormParameter fp = formParameterMap.get(formParameterName); + return getFormParameterAsString(fp); + } + + protected String getFormParameterAsString(FormParameter fp) { + if (fp == null) { + return null; + } + try { + return StreamUtil.asString(fp.getFormParameterValue(), HttpUtil + .getCharset(fp.getFormParameterContentType(), true)); + } catch (IOException e) { + return null; + } + } + + protected String getDataUrl() { + return getFormParameterAsString(FixedFormParameters.DATAURL); + } + + protected String getStyleSheetUrl() { + return getFormParameterAsString(FixedFormParameters.STYLESHEETURL); + } + + protected List getFormParameters(String parameterNamePostfix) { + List resultList = new ArrayList(); + for (Iterator fpi = formParameterMap.keySet().iterator(); fpi + .hasNext();) { + String paramName = fpi.next(); + if (paramName.endsWith(parameterNamePostfix)) { + resultList.add(formParameterMap.get(paramName)); + } + } + return resultList; + } + + protected List getTransferHeaders() { + return getFormParameters("__"); + } + + protected List getTransferForms() { + List resultList = new ArrayList(); + for (Iterator fpi = formParameterMap.keySet().iterator(); fpi + .hasNext();) { + String paramName = fpi.next(); + if ((paramName.endsWith("_")) && (!paramName.endsWith("__"))) { + resultList.add(formParameterMap.get(paramName)); + } + } + return resultList; + } + + protected void closeDataUrlConnection() { + log.debug("Closing data url input stream"); + if (dataUrlResponse == null) { + return; + } + InputStream is = dataUrlResponse.getStream(); + if (is != null) { + try { + is.close(); + } catch (IOException e) { + log.info("Error closing input stream to dataurl server:" + e); + } + } + } + + //---------------------------------------------------------------------------- + // ----------- END CONVENIENCE METHODS ----------- + + //---------------------------------------------------------------------------- + // -- BEGIN Methods that handle the http binding activities as defined in the + // activity diagram -- + + protected void init() { + log.info("Starting Bindingprocessor in Thread: " + + Thread.currentThread().getId()); + if (bindingProcessorError != null) { + log.debug("Detected binding processor error, sending quit command"); + // sendSTALQuit(); + currentState = State.FINISHED; + } else if (slCommand == null) { + log.error("SLCommand not set (consumeRequest not called ??)"); + bindingProcessorError = new SLException(2000); + // sendSTALQuit(); + currentState = State.FINISHED; + } else { + currentState = State.PROCESS; + } + } + + protected void processRequest() { + log.debug("Entered State: " + State.PROCESS); + log.debug("Processing command: " + slCommand); + commandInvoker.setCommand(slCommand); + responseCode = 200; + responseHeaders = Collections.EMPTY_MAP; + try { + commandInvoker.invoke(srcContex); + } catch (SLException e) { + log.info("Caught exception: " + e); + bindingProcessorError = e; + currentState = State.TRANSFORM; + } + dataUrlResponse = null; + if (getDataUrl() != null) { + log.debug("Data Url set to: " + getDataUrl()); + currentState = State.DATAURL; + } else { + log.debug("No data url set"); + currentState = State.TRANSFORM; + } + } + + protected void handleDataUrl() { + log.debug("Entered State: " + State.DATAURL); + try { + DataUrl dataUrl = new DataUrl(getDataUrl()); + DataUrlConnection conn = dataUrl.openConnection(); + + // set transfer headers + for (FormParameter fp : getTransferHeaders()) { + String paramString = getFormParameterAsString(fp); + if (paramString == null) { + log.error("Got empty transfer header, ignoring this"); + } else { + String[] keyVal = paramString.split(":", 2); + String key = keyVal[0]; + String val = null; + if (keyVal.length == 2) { + val = keyVal[1]; + } + val = val.trim(); + log.debug("Setting header " + key + " to value " + val); + conn.setHTTPHeader(key, val); + } + } + + // set transfer form parameters + for (FormParameter fp : getTransferForms()) { + String contentTransferEncoding = null; + String contentType = fp.getFormParameterContentType(); + String charSet = HttpUtil.getCharset(contentType, false); + if (charSet != null) { + contentType = contentType.substring(0, contentType + .lastIndexOf(HttpUtil.SEPERATOR[0])); + } + for (Iterator header = fp.getHeaderNames(); header.hasNext();) { + if (HttpUtil.CONTENT_TRANSFER_ENCODING + .equalsIgnoreCase(header.next())) { + contentTransferEncoding = getFormParameterAsString(fp); + } + } + log.debug("Setting form: " + fp.getFormParameterName() + + " contentType: " + contentType + " charset: " + charSet + + " contentTransferEncoding: " + contentTransferEncoding); + conn.setHTTPFormParameter(fp.getFormParameterName(), fp + .getFormParameterValue(), contentType, charSet, + contentTransferEncoding); + } + + // connect + conn.connect(); + // fetch and set SL result + targetContext.setTargetIsDataURL(true); + targetContext.setTargetCertificate(conn.getServerCertificate()); + targetContext.setTargetUrl(conn.getUrl()); + SLResult result = commandInvoker.getResult(targetContext); + + // transfer result + conn.transmit(result); + + // process Dataurl response + dataUrlResponse = conn.getResponse(); + log.debug("Received data url response code: " + + dataUrlResponse.getResponseCode()); + + switch (dataUrlResponse.getResponseCode()) { + case 200: + String contentType = dataUrlResponse.getContentType(); + log.debug("Got dataurl response content type: " + contentType); + if (contentType != null) { + if ((contentType.startsWith(HttpUtil.APPLICATION_URL_ENCODED)) + || (contentType.startsWith(HttpUtil.MULTIPART_FOTMDATA))) { + log.debug("Detected SL Request in dataurl response"); + // process headers and request + setHTTPHeaders(dataUrlResponse.getResponseHeaders()); + consumeRequestStream(dataUrlResponse.getStream()); + closeDataUrlConnection(); + srcContex.setSourceCertificate(conn.getServerCertificate()); + srcContex.setSourceIsDataURL(true); + srcContex.setSourceUrl(conn.getUrl()); + currentState = State.PROCESS; + } else if (((contentType.startsWith(HttpUtil.TXT_HTML)) + || (contentType.startsWith(HttpUtil.TXT_PLAIN)) || (contentType + .startsWith(HttpUtil.TXT_XML))) + && (dataUrlResponse.isHttpResponseXMLOK())) { + log.info("Dataurl response matches with content type: " + + contentType); + currentState = State.TRANSFORM; + + } else if ((contentType.startsWith(HttpUtil.TXT_XML)) + && (!dataUrlResponse.isHttpResponseXMLOK())) { + log + .debug("Detected text/xml dataurl response with content != "); + headerMap.put(HttpUtil.HTTP_HEADER_CONTENT_TYPE, contentType); + assignXMLRequest(dataUrlResponse.getStream(), HttpUtil.getCharset( + contentType, true)); + closeDataUrlConnection(); + srcContex.setSourceCertificate(conn.getServerCertificate()); + srcContex.setSourceIsDataURL(true); + srcContex.setSourceUrl(conn.getUrl()); + currentState = State.PROCESS; + // just to be complete, actually not used + srcContex.setSourceHTTPReferer(dataUrlResponse.getResponseHeaders() + .get(HttpUtil.HTTP_HEADER_REFERER)); + } else { + resultContentType = contentType; + responseHeaders = dataUrlResponse.getResponseHeaders(); + responseCode = dataUrlResponse.getResponseCode(); + currentState = State.FINISHED; + } + } else { + log.debug("Content type not set in dataurl response"); + closeDataUrlConnection(); + throw new SLBindingException(2007); + } + + break; + case 307: + contentType = dataUrlResponse.getContentType(); + if ((contentType != null) && (contentType.startsWith(HttpUtil.TXT_XML))) { + log.debug("Received dataurl response code 307 with XML content"); + String location = dataUrlResponse.getResponseHeaders().get( + HttpUtil.HTTP_HEADER_LOCATION); + if (location == null) { + log + .error("Did not get a location header for a 307 data url response"); + throw new SLBindingException(2003); + } + // consumeRequestStream(dataUrlResponse.getStream()); + FormParameterStore fp = new FormParameterStore(); + fp.init(location.getBytes(HttpUtil.DEFAULT_CHARSET), + FixedFormParameters.DATAURL, null, null); + formParameterMap.put(FixedFormParameters.DATAURL, fp); + headerMap.put(HttpUtil.HTTP_HEADER_CONTENT_TYPE, contentType); + assignXMLRequest(dataUrlResponse.getStream(), HttpUtil.getCharset( + dataUrlResponse.getContentType(), true)); + closeDataUrlConnection(); + srcContex.setSourceCertificate(conn.getServerCertificate()); + srcContex.setSourceIsDataURL(true); + srcContex.setSourceUrl(conn.getUrl()); + currentState = State.PROCESS; + // just to be complete, actually not used + srcContex.setSourceHTTPReferer(dataUrlResponse.getResponseHeaders() + .get(HttpUtil.HTTP_HEADER_REFERER)); + + } else { + log.debug("Received dataurl response code 307 non XML content: " + + dataUrlResponse.getContentType()); + resultContentType = dataUrlResponse.getContentType(); + currentState = State.FINISHED; + } + responseHeaders = dataUrlResponse.getResponseHeaders(); + responseCode = dataUrlResponse.getResponseCode(); + break; + + case 301: + case 302: + case 303: + responseHeaders = dataUrlResponse.getResponseHeaders(); + responseCode = dataUrlResponse.getResponseCode(); + resultContentType = dataUrlResponse.getContentType(); + currentState = State.FINISHED; + break; + + default: + // issue error + log.info("Unexpected response code from dataurl server: " + + dataUrlResponse.getResponseCode()); + throw new SLBindingException(2007); + } + + } catch (SLException slx) { + bindingProcessorError = slx; + log.error("Error during dataurl communication"); + resultContentType = HttpUtil.TXT_XML; + currentState = State.TRANSFORM; + } catch (SSLHandshakeException hx) { + bindingProcessorError = new SLException(2010); + log.info("Error during dataurl communication", hx); + resultContentType = HttpUtil.TXT_XML; + currentState = State.TRANSFORM; + } catch (IOException e) { + bindingProcessorError = new SLBindingException(2001); + log.error("Error while data url handling", e); + resultContentType = HttpUtil.TXT_XML; + currentState = State.TRANSFORM; + return; + } + } + + protected void transformResult() { + log.debug("Entered State: " + State.TRANSFORM); + if (bindingProcessorError != null) { + resultContentType = HttpUtil.TXT_XML; + } else if (dataUrlResponse != null) { + resultContentType = dataUrlResponse.getContentType(); + } else { + targetContext.setTargetIsDataURL(false); + targetContext.setTargetUrl(srcUrl); + try { + slResult = commandInvoker.getResult(targetContext); + resultContentType = slResult.getMimeType(); + log + .debug("Successfully got SLResult from commandinvoker, setting mimetype to: " + + resultContentType); + } catch (SLException e) { + log.info("Cannot get result from invoker:", e); + bindingProcessorError = new SLException(6002); + resultContentType = HttpUtil.TXT_XML; + } + } + transformer = getTransformer(getStyleSheetUrl()); + if (transformer != null) { + log.debug("Output transformation required"); + resultContentType = transformer.getOutputProperty("media-type"); + log.debug("Got media type from stylesheet: " + resultContentType); + if (resultContentType == null) { + log.debug("Setting to default text/xml result conent type"); + resultContentType = "text/xml"; + } + log.debug("Deferring sytylesheet processing"); + } + currentState = State.FINISHED; + } + + protected void finished() { + log.debug("Entered State: " + State.FINISHED); + if (bindingProcessorError != null) { + log.debug("Binding processor error, sending quit command"); + resultContentType = HttpUtil.TXT_XML; + } + sendSTALQuit(); + log.info("Terminating Bindingprocessor; Thread: " + + Thread.currentThread().getId()); + } + + // -- END Methods that handle the http binding activities as defined in the + // activity diagram -- + //---------------------------------------------------------------------------- + + /** + * Sets the headers of the SL Request. IMPORTANT: make sure to set all headers + * before invoking {@link #consumeRequestStream(InputStream)} + * + * @param aHeaderMap + * if null all header will be cleared. + */ + public void setHTTPHeaders(Map aHeaderMap) { + headerMap = new HashMap(); + // ensure lowercase keys + if (aHeaderMap != null) { + for (String s : aHeaderMap.keySet()) { + if (s != null) { + headerMap.put(s.toLowerCase(), aHeaderMap.get(s)); + if (s.equalsIgnoreCase(HttpUtil.HTTP_HEADER_REFERER)) { + String referer = aHeaderMap.get(s); + log.debug("Got referer header: " + referer); + srcContex.setSourceHTTPReferer(referer); + } + } + } + } + } + + public void setSourceCertificate(X509Certificate aCert) { + srcContex.setSourceCertificate(aCert); + } + + /** + * The HTTPBindingProcessor does not handle redirect URLs. It only provides + * the parameter. + * + * @return null if redirect url is not set. + */ + public String getRedirectURL() { + return getFormParameterAsString(FixedFormParameters.REDIRECTURL); + } + + public String getFormDataContentType(String aParameterName) { + FormParameter fp = formParameterMap.get(aParameterName); + if (fp != null) { + return fp.getFormParameterContentType(); + } + return null; + } + + public InputStream getFormData(String aParameterName) { + FormParameter fp = formParameterMap.get(aParameterName); + if (fp != null) { + return fp.getFormParameterValue(); + } + return null; + } + + protected void assignXMLRequest(InputStream is, String charset) + throws IOException, SLException { + Reader r = new InputStreamReader(is, charset); + StreamSource source = new StreamSource(r); + SLCommandContext commandCtx = new SLCommandContext(); + commandCtx.setSTAL(getSTAL()); + commandCtx.setURLDereferencerContext(new SimpleFormDataContextImpl(this)); + slCommand = SLCommandFactory.getInstance().createSLCommand(source, + commandCtx); + log.debug("Created new command: " + slCommand); + } + + @Override + public void run() { + boolean done = false; + int hopcounter = 0; + if (bindingProcessorError != null) { + currentState = State.FINISHED; + } + try { + while (!done) { + try { + switch (currentState) { + case INIT: + init(); + break; + case PROCESS: + processRequest(); + break; + case DATAURL: + handleDataUrl(); + if (++hopcounter > MAX_DATAURL_HOPS) { + log.error("Maximum number of dataurl hops reached"); + bindingProcessorError = new SLBindingException(2000); + currentState = State.FINISHED; + } + break; + case TRANSFORM: + transformResult(); + break; + case FINISHED: + done = true; + finished(); + break; + } + } catch (RuntimeException rte) { + throw rte; + } catch (Exception t) { + log.error("Caught unexpected exception", t); + responseCode = 200; + resultContentType = HttpUtil.TXT_XML; + responseHeaders = Collections.EMPTY_MAP; + bindingProcessorError = new SLException(2000); + currentState = State.FINISHED; + } + } + } catch (Throwable t) { + log.error("Caught unexpected exception", t); + responseCode = 200; + resultContentType = HttpUtil.TXT_XML; + responseHeaders = Collections.EMPTY_MAP; + bindingProcessorError = new SLException(2000); + currentState = State.FINISHED; + } + log.debug("Terminated http binding processor"); + } + + @Override + public void consumeRequestStream(InputStream is) { + try { + log.debug("Start consuming request stream"); + formParameterMap.clear(); + String cl = headerMap + .get(HttpUtil.HTTP_HEADER_CONTENT_TYPE.toLowerCase()); + if (cl == null) { + log.info("No content type set in http header"); + throw new SLBindingException(2006); + } + InputDecoder id = InputDecoderFactory.getDecoder(cl, is); + id.setContentType(cl); + if (id == null) { + log.error("Cannot get inputdecoder for is"); + throw new SLException(2006); + } + for (Iterator fpi = id.getFormParameterIterator(); fpi + .hasNext();) { + FormParameter fp = fpi.next(); + log.debug("Got request parameter with name: " + + fp.getFormParameterName()); + if (fp.getFormParameterName().equals(FixedFormParameters.XMLREQUEST)) { + log.debug("Creating XML Request"); + for (Iterator headerIterator = fp.getHeaderNames(); headerIterator + .hasNext();) { + String headerName = headerIterator.next(); + if (HttpUtil.CONTENT_TRANSFER_ENCODING.equalsIgnoreCase(headerName)) { + String transferEncoding = fp.getHeaderValue(headerName); + log.debug("Got transfer encoding for xmlrequest: " + + transferEncoding); + if (XML_REQ_TRANSFER_ENCODING.contains(transferEncoding)) { + log.debug("Supported transfer encoding: " + transferEncoding); + } else { + log + .error("Transferencoding not supported: " + + transferEncoding); + throw new SLBindingException(2005); + } + } + } + String charset = HttpUtil.getCharset(cl, true); + assignXMLRequest(fp.getFormParameterValue(), charset); + } else { + FormParameterStore fps = new FormParameterStore(); + fps.init(fp); + if (!fps.isEmpty()) { + log.debug("Setting from parameter: " + fps.getFormParameterName()); + formParameterMap.put(fps.getFormParameterName(), fps); + } + } + } + if (slCommand == null) { + throw new SLBindingException(2004); + } + if (is.read() != -1) { + log.error("Request input stream not completely read"); + // consume rest of stream, should never occur + throw new SLRuntimeException( + "request input stream not consumed till end"); + } + } catch (SLException slx) { + log.info("Error while consuming input stream " + slx); + bindingProcessorError = slx; + } catch (Throwable t) { + log.info("Error while consuming input stream " + t, t); + bindingProcessorError = new SLException(2000); + } finally { + try { + while (is.read() != -1) + ; + } catch (IOException e) { + log.error(e); + } + } + } + + @Override + public String getResultContentType() { + return resultContentType; + } + + protected Transformer getTransformer(String styleSheetURL) { + if (styleSheetURL == null) { + log.debug("Stylesheet URL not set"); + return null; + } + try { + URLDereferencerContext urlCtx = new SimpleFormDataContextImpl(this); + URIResolver resolver = new URIResolverAdapter(URLDereferencer + .getInstance(), urlCtx); + TransformerFactory factory = TransformerFactory.newInstance(); + StreamData sd = URLDereferencer.getInstance().dereference(styleSheetURL, + urlCtx); + Transformer t = factory.newTransformer(new StreamSource(sd.getStream())); + t.setURIResolver(resolver); + return t; + } catch (Exception ex) { + log.info("Cannot instantiate transformer", ex); + bindingProcessorError = new SLException(2002); + return null; + } + } + + protected void handleBindingProcessorError(OutputStream os, String encoding, + Transformer transformer) throws IOException { + log.debug("Writing error as result"); + ErrorResultImpl error = new ErrorResultImpl(bindingProcessorError); + try { + error.writeTo(new StreamResult(new OutputStreamWriter(os, encoding)), + transformer); + } catch (TransformerException e) { + log.fatal("Cannot write error result to stream", e); + } + } + + @Override + public void writeResultTo(OutputStream os, String encoding) + throws IOException { + if (encoding == null) { + encoding = HttpUtil.DEFAULT_CHARSET; + } + if (bindingProcessorError != null) { + log.debug("Detected error in binding processor, writing error as result"); + handleBindingProcessorError(os, encoding, transformer); + return; + } else if (dataUrlResponse != null) { + log.debug("Writing data url response as result"); + String charEnc = HttpUtil.getCharset(dataUrlResponse.getContentType(), + true); + InputStreamReader isr = new InputStreamReader( + dataUrlResponse.getStream(), charEnc); + OutputStreamWriter osw = new OutputStreamWriter(os, encoding); + if (transformer == null) { + StreamUtil.copyStream(isr, osw); + } else { + try { + transformer.transform(new StreamSource(isr), new StreamResult(osw)); + } catch (TransformerException e) { + log.fatal("Exception occured during result transformation", e); + // bindingProcessorError = new SLException(2008); + // handleBindingProcessorError(os, encoding, null); + return; + } + } + osw.flush(); + isr.close(); + } else if (slResult == null) { + // result not yet assigned -> must be a cancel + bindingProcessorError = new SLException(6001); + handleBindingProcessorError(os, encoding, transformer); + return; + } else { + log.debug("Getting result from invoker"); + OutputStreamWriter osw = new OutputStreamWriter(os, encoding); + try { + slResult.writeTo(new StreamResult(osw), transformer); + } catch (TransformerException e) { + log.fatal("Cannot write result to stream", e); + // bindingProcessorError = new SLException(2008); + // handleBindingProcessorError(os, encoding, transformer); + } + osw.flush(); + } + } + + /** + * The response code from the dataurl server or 200 if no dataurl server + * created the result + * + * @return + */ + public int getResponseCode() { + return responseCode; + } + + /** + * All headers from the data url server in case of a direct forward from the + * dataurl server. + * + * @return + */ + public Map getResponseHeaders() { + return responseHeaders; + } + + @Override + public void setLocale(Locale locale) { + if (locale == null) { + throw new NullPointerException("Locale must not be set to null"); + } + this.locale = locale; + } + } \ No newline at end of file -- cgit v1.2.3 From 3edfbe631f24d73324bc4dd0d182ca7737c4d5b5 Mon Sep 17 00:00:00 2001 From: mcentner Date: Wed, 24 Sep 2008 13:56:53 +0000 Subject: Improved SLResult marshalling. git-svn-id: https://joinup.ec.europa.eu/svn/mocca/trunk@66 8a26b1a7-26f0-462f-b9ef-d0e30c41f5a4 --- .../gv/egiz/bku/binding/HTTPBindingProcessor.java | 40 ++++++++-------------- 1 file changed, 15 insertions(+), 25 deletions(-) (limited to 'bkucommon/src/main/java/at/gv/egiz/bku/binding/HTTPBindingProcessor.java') diff --git a/bkucommon/src/main/java/at/gv/egiz/bku/binding/HTTPBindingProcessor.java b/bkucommon/src/main/java/at/gv/egiz/bku/binding/HTTPBindingProcessor.java index 19f22126..8f72c3ee 100644 --- a/bkucommon/src/main/java/at/gv/egiz/bku/binding/HTTPBindingProcessor.java +++ b/bkucommon/src/main/java/at/gv/egiz/bku/binding/HTTPBindingProcessor.java @@ -35,6 +35,7 @@ import java.util.Locale; import java.util.Map; import javax.net.ssl.SSLHandshakeException; +import javax.xml.transform.Templates; import javax.xml.transform.Transformer; import javax.xml.transform.TransformerException; import javax.xml.transform.TransformerFactory; @@ -108,7 +109,7 @@ public class HTTPBindingProcessor extends AbstractBindingProcessor implements protected SLTargetContext targetContext = new SLTargetContext(); protected URL srcUrl; protected State currentState = State.INIT; - protected Transformer transformer = null; + protected Templates templates = null; protected String resultContentType = null; protected SLResult slResult = null; protected int responseCode = 200; @@ -471,10 +472,10 @@ public class HTTPBindingProcessor extends AbstractBindingProcessor implements resultContentType = HttpUtil.TXT_XML; } } - transformer = getTransformer(getStyleSheetUrl()); - if (transformer != null) { + templates = getTemplates(getStyleSheetUrl()); + if (templates != null) { log.debug("Output transformation required"); - resultContentType = transformer.getOutputProperty("media-type"); + resultContentType = templates.getOutputProperties().getProperty("media-type"); log.debug("Got media type from stylesheet: " + resultContentType); if (resultContentType == null) { log.debug("Setting to default text/xml result conent type"); @@ -703,7 +704,7 @@ public class HTTPBindingProcessor extends AbstractBindingProcessor implements return resultContentType; } - protected Transformer getTransformer(String styleSheetURL) { + protected Templates getTemplates(String styleSheetURL) { if (styleSheetURL == null) { log.debug("Stylesheet URL not set"); return null; @@ -713,11 +714,10 @@ public class HTTPBindingProcessor extends AbstractBindingProcessor implements URIResolver resolver = new URIResolverAdapter(URLDereferencer .getInstance(), urlCtx); TransformerFactory factory = TransformerFactory.newInstance(); + factory.setURIResolver(resolver); StreamData sd = URLDereferencer.getInstance().dereference(styleSheetURL, urlCtx); - Transformer t = factory.newTransformer(new StreamSource(sd.getStream())); - t.setURIResolver(resolver); - return t; + return factory.newTemplates(new StreamSource(sd.getStream())); } catch (Exception ex) { log.info("Cannot instantiate transformer", ex); bindingProcessorError = new SLException(2002); @@ -726,15 +726,10 @@ public class HTTPBindingProcessor extends AbstractBindingProcessor implements } protected void handleBindingProcessorError(OutputStream os, String encoding, - Transformer transformer) throws IOException { + Templates templates) throws IOException { log.debug("Writing error as result"); ErrorResultImpl error = new ErrorResultImpl(bindingProcessorError); - try { - error.writeTo(new StreamResult(new OutputStreamWriter(os, encoding)), - transformer); - } catch (TransformerException e) { - log.fatal("Cannot write error result to stream", e); - } + error.writeTo(new StreamResult(new OutputStreamWriter(os, encoding)), templates); } @Override @@ -745,7 +740,7 @@ public class HTTPBindingProcessor extends AbstractBindingProcessor implements } if (bindingProcessorError != null) { log.debug("Detected error in binding processor, writing error as result"); - handleBindingProcessorError(os, encoding, transformer); + handleBindingProcessorError(os, encoding, templates); return; } else if (dataUrlResponse != null) { log.debug("Writing data url response as result"); @@ -754,10 +749,11 @@ public class HTTPBindingProcessor extends AbstractBindingProcessor implements InputStreamReader isr = new InputStreamReader( dataUrlResponse.getStream(), charEnc); OutputStreamWriter osw = new OutputStreamWriter(os, encoding); - if (transformer == null) { + if (templates == null) { StreamUtil.copyStream(isr, osw); } else { try { + Transformer transformer = templates.newTransformer(); transformer.transform(new StreamSource(isr), new StreamResult(osw)); } catch (TransformerException e) { log.fatal("Exception occured during result transformation", e); @@ -771,18 +767,12 @@ public class HTTPBindingProcessor extends AbstractBindingProcessor implements } else if (slResult == null) { // result not yet assigned -> must be a cancel bindingProcessorError = new SLException(6001); - handleBindingProcessorError(os, encoding, transformer); + handleBindingProcessorError(os, encoding, templates); return; } else { log.debug("Getting result from invoker"); OutputStreamWriter osw = new OutputStreamWriter(os, encoding); - try { - slResult.writeTo(new StreamResult(osw), transformer); - } catch (TransformerException e) { - log.fatal("Cannot write result to stream", e); - // bindingProcessorError = new SLException(2008); - // handleBindingProcessorError(os, encoding, transformer); - } + slResult.writeTo(new StreamResult(osw), templates); osw.flush(); } } -- cgit v1.2.3 From e21dd5249d5fa19c5619847922cf8cdea95e3145 Mon Sep 17 00:00:00 2001 From: wbauer Date: Thu, 25 Sep 2008 07:29:47 +0000 Subject: improved robustness of http binding processor git-svn-id: https://joinup.ec.europa.eu/svn/mocca/trunk@70 8a26b1a7-26f0-462f-b9ef-d0e30c41f5a4 --- .../main/java/at/gv/egiz/bku/binding/HTTPBindingProcessor.java | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'bkucommon/src/main/java/at/gv/egiz/bku/binding/HTTPBindingProcessor.java') diff --git a/bkucommon/src/main/java/at/gv/egiz/bku/binding/HTTPBindingProcessor.java b/bkucommon/src/main/java/at/gv/egiz/bku/binding/HTTPBindingProcessor.java index 8f72c3ee..5e44e82b 100644 --- a/bkucommon/src/main/java/at/gv/egiz/bku/binding/HTTPBindingProcessor.java +++ b/bkucommon/src/main/java/at/gv/egiz/bku/binding/HTTPBindingProcessor.java @@ -115,6 +115,7 @@ public class HTTPBindingProcessor extends AbstractBindingProcessor implements protected int responseCode = 200; protected Map responseHeaders = Collections.EMPTY_MAP; protected Locale locale = Locale.getDefault(); + protected boolean finished = false; /** * @@ -246,6 +247,7 @@ public class HTTPBindingProcessor extends AbstractBindingProcessor implements commandInvoker.setCommand(slCommand); responseCode = 200; responseHeaders = Collections.EMPTY_MAP; + dataUrlResponse = null; try { commandInvoker.invoke(srcContex); } catch (SLException e) { @@ -253,7 +255,6 @@ public class HTTPBindingProcessor extends AbstractBindingProcessor implements bindingProcessorError = e; currentState = State.TRANSFORM; } - dataUrlResponse = null; if (getDataUrl() != null) { log.debug("Data Url set to: " + getDataUrl()); currentState = State.DATAURL; @@ -495,6 +496,7 @@ public class HTTPBindingProcessor extends AbstractBindingProcessor implements sendSTALQuit(); log.info("Terminating Bindingprocessor; Thread: " + Thread.currentThread().getId()); + finished = true; } // -- END Methods that handle the http binding activities as defined in the @@ -620,6 +622,7 @@ public class HTTPBindingProcessor extends AbstractBindingProcessor implements currentState = State.FINISHED; } log.debug("Terminated http binding processor"); + finished = true; } @Override @@ -805,4 +808,8 @@ public class HTTPBindingProcessor extends AbstractBindingProcessor implements this.locale = locale; } + @Override + public boolean isFinished() { + return finished; + } } \ No newline at end of file -- cgit v1.2.3 From c2ae3db1bc6dcb8ba3eb3461c05e293917c004ca Mon Sep 17 00:00:00 2001 From: mcentner Date: Thu, 30 Oct 2008 10:33:29 +0000 Subject: Updated SMCC to use exclusive access and to throw exceptions upon locked or not activated cards. Improved locale support in the security layer request and response processing. Fixed issue in STAL which prevented the use of RSA-SHA1 signatures. Added additional parameters to the applet test pages. git-svn-id: https://joinup.ec.europa.eu/svn/mocca/trunk@128 8a26b1a7-26f0-462f-b9ef-d0e30c41f5a4 --- .../src/main/java/at/gv/egiz/bku/binding/HTTPBindingProcessor.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'bkucommon/src/main/java/at/gv/egiz/bku/binding/HTTPBindingProcessor.java') diff --git a/bkucommon/src/main/java/at/gv/egiz/bku/binding/HTTPBindingProcessor.java b/bkucommon/src/main/java/at/gv/egiz/bku/binding/HTTPBindingProcessor.java index 5e44e82b..4a22874c 100644 --- a/bkucommon/src/main/java/at/gv/egiz/bku/binding/HTTPBindingProcessor.java +++ b/bkucommon/src/main/java/at/gv/egiz/bku/binding/HTTPBindingProcessor.java @@ -564,6 +564,7 @@ public class HTTPBindingProcessor extends AbstractBindingProcessor implements SLCommandContext commandCtx = new SLCommandContext(); commandCtx.setSTAL(getSTAL()); commandCtx.setURLDereferencerContext(new SimpleFormDataContextImpl(this)); + commandCtx.setLocale(locale); slCommand = SLCommandFactory.getInstance().createSLCommand(source, commandCtx); log.debug("Created new command: " + slCommand); @@ -731,7 +732,7 @@ public class HTTPBindingProcessor extends AbstractBindingProcessor implements protected void handleBindingProcessorError(OutputStream os, String encoding, Templates templates) throws IOException { log.debug("Writing error as result"); - ErrorResultImpl error = new ErrorResultImpl(bindingProcessorError); + ErrorResultImpl error = new ErrorResultImpl(bindingProcessorError, locale); error.writeTo(new StreamResult(new OutputStreamWriter(os, encoding)), templates); } -- cgit v1.2.3 From d379980f1c64bcf174c9706ff5aa746314a6666f Mon Sep 17 00:00:00 2001 From: clemenso Date: Thu, 27 Nov 2008 15:21:37 +0000 Subject: typo git-svn-id: https://joinup.ec.europa.eu/svn/mocca/trunk@220 8a26b1a7-26f0-462f-b9ef-d0e30c41f5a4 --- .../gv/egiz/bku/binding/HTTPBindingProcessor.java | 58 +++++++++++----------- 1 file changed, 29 insertions(+), 29 deletions(-) (limited to 'bkucommon/src/main/java/at/gv/egiz/bku/binding/HTTPBindingProcessor.java') diff --git a/bkucommon/src/main/java/at/gv/egiz/bku/binding/HTTPBindingProcessor.java b/bkucommon/src/main/java/at/gv/egiz/bku/binding/HTTPBindingProcessor.java index 4a22874c..98b5b775 100644 --- a/bkucommon/src/main/java/at/gv/egiz/bku/binding/HTTPBindingProcessor.java +++ b/bkucommon/src/main/java/at/gv/egiz/bku/binding/HTTPBindingProcessor.java @@ -139,8 +139,8 @@ public class HTTPBindingProcessor extends AbstractBindingProcessor implements srcContex.setSourceIsDataURL(false); } - //---------------------------------------------------------------------------- - // ----------- BEGIN CONVENIENCE METHODS ----------- + //---------------------------------------------------------------------------- + // ----------- BEGIN CONVENIENCE METHODS ----------- protected void sendSTALQuit() { log.info("Sending QUIT command to STAL"); @@ -217,24 +217,24 @@ public class HTTPBindingProcessor extends AbstractBindingProcessor implements } } - //---------------------------------------------------------------------------- - // ----------- END CONVENIENCE METHODS ----------- + //---------------------------------------------------------------------------- + // ----------- END CONVENIENCE METHODS ----------- - //---------------------------------------------------------------------------- - // -- BEGIN Methods that handle the http binding activities as defined in the - // activity diagram -- + //---------------------------------------------------------------------------- + // -- BEGIN Methods that handle the http binding activities as defined in the + // activity diagram -- protected void init() { log.info("Starting Bindingprocessor in Thread: " + Thread.currentThread().getId()); if (bindingProcessorError != null) { log.debug("Detected binding processor error, sending quit command"); - // sendSTALQuit(); + // sendSTALQuit(); currentState = State.FINISHED; } else if (slCommand == null) { log.error("SLCommand not set (consumeRequest not called ??)"); bindingProcessorError = new SLException(2000); - // sendSTALQuit(); + // sendSTALQuit(); currentState = State.FINISHED; } else { currentState = State.PROCESS; @@ -270,7 +270,7 @@ public class HTTPBindingProcessor extends AbstractBindingProcessor implements DataUrl dataUrl = new DataUrl(getDataUrl()); DataUrlConnection conn = dataUrl.openConnection(); - // set transfer headers + // set transfer headers for (FormParameter fp : getTransferHeaders()) { String paramString = getFormParameterAsString(fp); if (paramString == null) { @@ -288,7 +288,7 @@ public class HTTPBindingProcessor extends AbstractBindingProcessor implements } } - // set transfer form parameters + // set transfer form parameters for (FormParameter fp : getTransferForms()) { String contentTransferEncoding = null; String contentType = fp.getFormParameterContentType(); @@ -311,18 +311,18 @@ public class HTTPBindingProcessor extends AbstractBindingProcessor implements contentTransferEncoding); } - // connect + // connect conn.connect(); - // fetch and set SL result + // fetch and set SL result targetContext.setTargetIsDataURL(true); targetContext.setTargetCertificate(conn.getServerCertificate()); targetContext.setTargetUrl(conn.getUrl()); SLResult result = commandInvoker.getResult(targetContext); - // transfer result + // transfer result conn.transmit(result); - // process Dataurl response + // process Dataurl response dataUrlResponse = conn.getResponse(); log.debug("Received data url response code: " + dataUrlResponse.getResponseCode()); @@ -335,7 +335,7 @@ public class HTTPBindingProcessor extends AbstractBindingProcessor implements if ((contentType.startsWith(HttpUtil.APPLICATION_URL_ENCODED)) || (contentType.startsWith(HttpUtil.MULTIPART_FOTMDATA))) { log.debug("Detected SL Request in dataurl response"); - // process headers and request + // process headers and request setHTTPHeaders(dataUrlResponse.getResponseHeaders()); consumeRequestStream(dataUrlResponse.getStream()); closeDataUrlConnection(); @@ -363,7 +363,7 @@ public class HTTPBindingProcessor extends AbstractBindingProcessor implements srcContex.setSourceIsDataURL(true); srcContex.setSourceUrl(conn.getUrl()); currentState = State.PROCESS; - // just to be complete, actually not used + // just to be complete, actually not used srcContex.setSourceHTTPReferer(dataUrlResponse.getResponseHeaders() .get(HttpUtil.HTTP_HEADER_REFERER)); } else { @@ -390,7 +390,7 @@ public class HTTPBindingProcessor extends AbstractBindingProcessor implements .error("Did not get a location header for a 307 data url response"); throw new SLBindingException(2003); } - // consumeRequestStream(dataUrlResponse.getStream()); + // consumeRequestStream(dataUrlResponse.getStream()); FormParameterStore fp = new FormParameterStore(); fp.init(location.getBytes(HttpUtil.DEFAULT_CHARSET), FixedFormParameters.DATAURL, null, null); @@ -403,7 +403,7 @@ public class HTTPBindingProcessor extends AbstractBindingProcessor implements srcContex.setSourceIsDataURL(true); srcContex.setSourceUrl(conn.getUrl()); currentState = State.PROCESS; - // just to be complete, actually not used + // just to be complete, actually not used srcContex.setSourceHTTPReferer(dataUrlResponse.getResponseHeaders() .get(HttpUtil.HTTP_HEADER_REFERER)); @@ -427,7 +427,7 @@ public class HTTPBindingProcessor extends AbstractBindingProcessor implements break; default: - // issue error + // issue error log.info("Unexpected response code from dataurl server: " + dataUrlResponse.getResponseCode()); throw new SLBindingException(2007); @@ -499,9 +499,9 @@ public class HTTPBindingProcessor extends AbstractBindingProcessor implements finished = true; } - // -- END Methods that handle the http binding activities as defined in the - // activity diagram -- - //---------------------------------------------------------------------------- + // -- END Methods that handle the http binding activities as defined in the + // activity diagram -- + //---------------------------------------------------------------------------- /** * Sets the headers of the SL Request. IMPORTANT: make sure to set all headers @@ -512,7 +512,7 @@ public class HTTPBindingProcessor extends AbstractBindingProcessor implements */ public void setHTTPHeaders(Map aHeaderMap) { headerMap = new HashMap(); - // ensure lowercase keys + // ensure lowercase keys if (aHeaderMap != null) { for (String s : aHeaderMap.keySet()) { if (s != null) { @@ -673,7 +673,7 @@ public class HTTPBindingProcessor extends AbstractBindingProcessor implements FormParameterStore fps = new FormParameterStore(); fps.init(fp); if (!fps.isEmpty()) { - log.debug("Setting from parameter: " + fps.getFormParameterName()); + log.debug("Setting form parameter: " + fps.getFormParameterName()); formParameterMap.put(fps.getFormParameterName(), fps); } } @@ -683,7 +683,7 @@ public class HTTPBindingProcessor extends AbstractBindingProcessor implements } if (is.read() != -1) { log.error("Request input stream not completely read"); - // consume rest of stream, should never occur + // consume rest of stream, should never occur throw new SLRuntimeException( "request input stream not consumed till end"); } @@ -761,15 +761,15 @@ public class HTTPBindingProcessor extends AbstractBindingProcessor implements transformer.transform(new StreamSource(isr), new StreamResult(osw)); } catch (TransformerException e) { log.fatal("Exception occured during result transformation", e); - // bindingProcessorError = new SLException(2008); - // handleBindingProcessorError(os, encoding, null); + // bindingProcessorError = new SLException(2008); + // handleBindingProcessorError(os, encoding, null); return; } } osw.flush(); isr.close(); } else if (slResult == null) { - // result not yet assigned -> must be a cancel + // result not yet assigned -> must be a cancel bindingProcessorError = new SLException(6001); handleBindingProcessorError(os, encoding, templates); return; -- cgit v1.2.3 From 90f7f3ea1674e7cd5ead84247ca881ca101ba72a Mon Sep 17 00:00:00 2001 From: clemenso Date: Wed, 11 Feb 2009 20:03:29 +0000 Subject: div. changes for A-Trust Activation Support (User-Agent header, GetStatusRequest, ...) git-svn-id: https://joinup.ec.europa.eu/svn/mocca/trunk@296 8a26b1a7-26f0-462f-b9ef-d0e30c41f5a4 --- .../src/main/java/at/gv/egiz/bku/binding/HTTPBindingProcessor.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'bkucommon/src/main/java/at/gv/egiz/bku/binding/HTTPBindingProcessor.java') diff --git a/bkucommon/src/main/java/at/gv/egiz/bku/binding/HTTPBindingProcessor.java b/bkucommon/src/main/java/at/gv/egiz/bku/binding/HTTPBindingProcessor.java index 98b5b775..43f42331 100644 --- a/bkucommon/src/main/java/at/gv/egiz/bku/binding/HTTPBindingProcessor.java +++ b/bkucommon/src/main/java/at/gv/egiz/bku/binding/HTTPBindingProcessor.java @@ -91,7 +91,7 @@ public class HTTPBindingProcessor extends AbstractBindingProcessor implements * Defines the maximum number of dataurl connects that are allowed within a * single SL Request processing. */ - protected static int MAX_DATAURL_HOPS = 10; + protected static int MAX_DATAURL_HOPS = 50; protected static String XML_MIME_TYPE = "text/xml"; protected static String BINARY_MIME_TYPE = "application/octet-stream"; -- cgit v1.2.3 From 2882e14d19cfa58ea382083434210aaf0cfea3e3 Mon Sep 17 00:00:00 2001 From: wbauer Date: Fri, 13 Mar 2009 07:49:49 +0000 Subject: Fixed Bug#405 and added according test case Fixed Bug#402 Added Feature#403 git-svn-id: https://joinup.ec.europa.eu/svn/mocca/trunk@320 8a26b1a7-26f0-462f-b9ef-d0e30c41f5a4 --- .../src/main/java/at/gv/egiz/bku/binding/HTTPBindingProcessor.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'bkucommon/src/main/java/at/gv/egiz/bku/binding/HTTPBindingProcessor.java') diff --git a/bkucommon/src/main/java/at/gv/egiz/bku/binding/HTTPBindingProcessor.java b/bkucommon/src/main/java/at/gv/egiz/bku/binding/HTTPBindingProcessor.java index 43f42331..d0b2dac1 100644 --- a/bkucommon/src/main/java/at/gv/egiz/bku/binding/HTTPBindingProcessor.java +++ b/bkucommon/src/main/java/at/gv/egiz/bku/binding/HTTPBindingProcessor.java @@ -672,10 +672,10 @@ public class HTTPBindingProcessor extends AbstractBindingProcessor implements } else { FormParameterStore fps = new FormParameterStore(); fps.init(fp); - if (!fps.isEmpty()) { + //if (!fps.isEmpty()) { log.debug("Setting form parameter: " + fps.getFormParameterName()); formParameterMap.put(fps.getFormParameterName(), fps); - } + //} } } if (slCommand == null) { -- cgit v1.2.3 From 1ad095128a98137e2b4c904814722be4ec43eebd Mon Sep 17 00:00:00 2001 From: wbauer Date: Mon, 30 Mar 2009 13:42:39 +0000 Subject: fixed bug#410 git-svn-id: https://joinup.ec.europa.eu/svn/mocca/trunk@324 8a26b1a7-26f0-462f-b9ef-d0e30c41f5a4 --- .../src/main/java/at/gv/egiz/bku/binding/HTTPBindingProcessor.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'bkucommon/src/main/java/at/gv/egiz/bku/binding/HTTPBindingProcessor.java') diff --git a/bkucommon/src/main/java/at/gv/egiz/bku/binding/HTTPBindingProcessor.java b/bkucommon/src/main/java/at/gv/egiz/bku/binding/HTTPBindingProcessor.java index d0b2dac1..97b5b859 100644 --- a/bkucommon/src/main/java/at/gv/egiz/bku/binding/HTTPBindingProcessor.java +++ b/bkucommon/src/main/java/at/gv/egiz/bku/binding/HTTPBindingProcessor.java @@ -281,8 +281,11 @@ public class HTTPBindingProcessor extends AbstractBindingProcessor implements String val = null; if (keyVal.length == 2) { val = keyVal[1]; + val = val.trim(); + } else { + log.error("Invalid transfer header encoding: "+paramString); + throw new SLBindingException(2005); } - val = val.trim(); log.debug("Setting header " + key + " to value " + val); conn.setHTTPHeader(key, val); } -- cgit v1.2.3 From c09207ae05e1d0bf4398f05834d79aa301e867d5 Mon Sep 17 00:00:00 2001 From: clemenso Date: Thu, 25 Jun 2009 11:54:21 +0000 Subject: MAX_DATAURL_HOPS = 80 (a-trust workflows) git-svn-id: https://joinup.ec.europa.eu/svn/mocca/trunk@371 8a26b1a7-26f0-462f-b9ef-d0e30c41f5a4 --- .../src/main/java/at/gv/egiz/bku/binding/HTTPBindingProcessor.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'bkucommon/src/main/java/at/gv/egiz/bku/binding/HTTPBindingProcessor.java') diff --git a/bkucommon/src/main/java/at/gv/egiz/bku/binding/HTTPBindingProcessor.java b/bkucommon/src/main/java/at/gv/egiz/bku/binding/HTTPBindingProcessor.java index 97b5b859..832b1770 100644 --- a/bkucommon/src/main/java/at/gv/egiz/bku/binding/HTTPBindingProcessor.java +++ b/bkucommon/src/main/java/at/gv/egiz/bku/binding/HTTPBindingProcessor.java @@ -91,7 +91,7 @@ public class HTTPBindingProcessor extends AbstractBindingProcessor implements * Defines the maximum number of dataurl connects that are allowed within a * single SL Request processing. */ - protected static int MAX_DATAURL_HOPS = 50; + protected static int MAX_DATAURL_HOPS = 80; protected static String XML_MIME_TYPE = "text/xml"; protected static String BINARY_MIME_TYPE = "application/octet-stream"; -- cgit v1.2.3 From b16d733781a2f7d2a56f562be7f06090f724a02a Mon Sep 17 00:00:00 2001 From: clemenso Date: Thu, 13 Aug 2009 09:32:12 +0000 Subject: minor changes (log) git-svn-id: https://joinup.ec.europa.eu/svn/mocca/trunk@428 8a26b1a7-26f0-462f-b9ef-d0e30c41f5a4 --- .../main/java/at/gv/egiz/bku/binding/HTTPBindingProcessor.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'bkucommon/src/main/java/at/gv/egiz/bku/binding/HTTPBindingProcessor.java') diff --git a/bkucommon/src/main/java/at/gv/egiz/bku/binding/HTTPBindingProcessor.java b/bkucommon/src/main/java/at/gv/egiz/bku/binding/HTTPBindingProcessor.java index 832b1770..cb11a3e6 100644 --- a/bkucommon/src/main/java/at/gv/egiz/bku/binding/HTTPBindingProcessor.java +++ b/bkucommon/src/main/java/at/gv/egiz/bku/binding/HTTPBindingProcessor.java @@ -347,8 +347,8 @@ public class HTTPBindingProcessor extends AbstractBindingProcessor implements srcContex.setSourceUrl(conn.getUrl()); currentState = State.PROCESS; } else if (((contentType.startsWith(HttpUtil.TXT_HTML)) - || (contentType.startsWith(HttpUtil.TXT_PLAIN)) || (contentType - .startsWith(HttpUtil.TXT_XML))) + || (contentType.startsWith(HttpUtil.TXT_PLAIN)) + || (contentType.startsWith(HttpUtil.TXT_XML))) && (dataUrlResponse.isHttpResponseXMLOK())) { log.info("Dataurl response matches with content type: " + contentType); @@ -568,10 +568,10 @@ public class HTTPBindingProcessor extends AbstractBindingProcessor implements commandCtx.setSTAL(getSTAL()); commandCtx.setURLDereferencerContext(new SimpleFormDataContextImpl(this)); commandCtx.setLocale(locale); - slCommand = SLCommandFactory.getInstance().createSLCommand(source, + slCommand = SLCommandFactory.getInstance().createSLCommand(source, commandCtx); log.debug("Created new command: " + slCommand); - } + } @Override public void run() { -- cgit v1.2.3 From c1a8ed191e57b6c068d9a2733cca40dd4c209b9f Mon Sep 17 00:00:00 2001 From: clemenso Date: Fri, 14 Aug 2009 11:14:32 +0000 Subject: [#354] HTTPBindingProcessor: MAX_DATAURL_HOPS not configurable git-svn-id: https://joinup.ec.europa.eu/svn/mocca/trunk@436 8a26b1a7-26f0-462f-b9ef-d0e30c41f5a4 --- .../main/java/at/gv/egiz/bku/binding/HTTPBindingProcessor.java | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) (limited to 'bkucommon/src/main/java/at/gv/egiz/bku/binding/HTTPBindingProcessor.java') diff --git a/bkucommon/src/main/java/at/gv/egiz/bku/binding/HTTPBindingProcessor.java b/bkucommon/src/main/java/at/gv/egiz/bku/binding/HTTPBindingProcessor.java index cb11a3e6..ef603fc7 100644 --- a/bkucommon/src/main/java/at/gv/egiz/bku/binding/HTTPBindingProcessor.java +++ b/bkucommon/src/main/java/at/gv/egiz/bku/binding/HTTPBindingProcessor.java @@ -87,12 +87,6 @@ public class HTTPBindingProcessor extends AbstractBindingProcessor implements public final static Collection XML_REQ_TRANSFER_ENCODING = Arrays .asList(new String[] { "binary" }); - /** - * Defines the maximum number of dataurl connects that are allowed within a - * single SL Request processing. - */ - protected static int MAX_DATAURL_HOPS = 80; - protected static String XML_MIME_TYPE = "text/xml"; protected static String BINARY_MIME_TYPE = "application/octet-stream"; @@ -592,7 +586,7 @@ public class HTTPBindingProcessor extends AbstractBindingProcessor implements break; case DATAURL: handleDataUrl(); - if (++hopcounter > MAX_DATAURL_HOPS) { + if (++hopcounter > config.getMaxDataUrlHops()) { log.error("Maximum number of dataurl hops reached"); bindingProcessorError = new SLBindingException(2000); currentState = State.FINISHED; -- cgit v1.2.3 From bd070e82c276afb8c1c3a9ddc3b5712783760881 Mon Sep 17 00:00:00 2001 From: mcentner Date: Tue, 29 Sep 2009 17:36:06 +0000 Subject: Logging issues fixed: - Added possibility to configure logging of BKUWebstart. Logging is now configured from log4j configuration deployed with BKUWebstart in a first step. In a second step the webstart launcher looks for a log4j configuration file in the user's mooca configuration directory and updates the log4j configuration. - Logging of IAIK PKI properly initialized. IAIK PKI does not mess with the log4j configuration any longer. - Changed log4j accordingly (an appender is now needed as IAIK PKI does not reconfigure log4j any longer). Added css-stylesheet to ErrorResponses issued by the BKU to improve the presentation to the user. Changed dependencies of BKUWebStart (see Issue#469 https://egovlabs.gv.at/tracker/index.php?func=detail&aid=469&group_id=13&atid=134). DataURLConnection now uses the request encoding of SL < 1.2. application/x-www-form-urlencoded is now used as default encoding method. multipart/form-data is used only if transfer parameters are present in the request that require a Content-Type parameter. This can only be set with multipart/form-data. This is not in conformance with SL 1.2, however it should improve compatibility with applications. Therefore, removed the ability to configure the DataURLConnection implementation class. DataURLConnection now uses a streaming implementation for encoding of application/x-www-form-urlencoded requests. XWWWFormUrlImputDecoder now uses a streaming implementation for decoding of application/x-www-form-urlencoded requests. Fixed Bug in SLResultPart that caused a binary response to be provided as parameter "XMLResponse" in a multipart/form-data encoded request to DataURL. SLCommandFactory now supports unmarshalling of SL < 1.2 requests in order issue meaningful error messages. Therefore, the marshaling context for response marshaling had to be separated from the marshaling context for requests in order to avoid the marshaling of SL < 1.2 namespace prefixes in SL 1.2 responses. Target attribute in QualifiedProperties is now marshaled. (see Issue#470 https://egovlabs.gv.at/tracker/index.php?func=detail&aid=470&group_id=13&atid=134) Reporting of XML validation errors improved. git-svn-id: https://joinup.ec.europa.eu/svn/mocca/trunk@510 8a26b1a7-26f0-462f-b9ef-d0e30c41f5a4 --- .../gv/egiz/bku/binding/HTTPBindingProcessor.java | 29 ++++++++++++++++++---- 1 file changed, 24 insertions(+), 5 deletions(-) (limited to 'bkucommon/src/main/java/at/gv/egiz/bku/binding/HTTPBindingProcessor.java') diff --git a/bkucommon/src/main/java/at/gv/egiz/bku/binding/HTTPBindingProcessor.java b/bkucommon/src/main/java/at/gv/egiz/bku/binding/HTTPBindingProcessor.java index ef603fc7..a1c4d5fc 100644 --- a/bkucommon/src/main/java/at/gv/egiz/bku/binding/HTTPBindingProcessor.java +++ b/bkucommon/src/main/java/at/gv/egiz/bku/binding/HTTPBindingProcessor.java @@ -22,6 +22,7 @@ import java.io.InputStreamReader; import java.io.OutputStream; import java.io.OutputStreamWriter; import java.io.Reader; +import java.io.Writer; import java.net.URL; import java.security.cert.X509Certificate; import java.util.ArrayList; @@ -46,6 +47,7 @@ import javax.xml.transform.stream.StreamSource; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import at.gv.egiz.bku.slcommands.ErrorResult; import at.gv.egiz.bku.slcommands.SLCommand; import at.gv.egiz.bku.slcommands.SLCommandContext; import at.gv.egiz.bku.slcommands.SLCommandFactory; @@ -635,7 +637,6 @@ public class HTTPBindingProcessor extends AbstractBindingProcessor implements throw new SLBindingException(2006); } InputDecoder id = InputDecoderFactory.getDecoder(cl, is); - id.setContentType(cl); if (id == null) { log.error("Cannot get inputdecoder for is"); throw new SLException(2006); @@ -730,9 +731,20 @@ public class HTTPBindingProcessor extends AbstractBindingProcessor implements Templates templates) throws IOException { log.debug("Writing error as result"); ErrorResultImpl error = new ErrorResultImpl(bindingProcessorError, locale); - error.writeTo(new StreamResult(new OutputStreamWriter(os, encoding)), templates); + Writer writer = writeXMLDeclarationAndProcessingInstruction(os, encoding); + error.writeTo(new StreamResult(writer), templates, true); } + protected Writer writeXMLDeclarationAndProcessingInstruction(OutputStream os, String encoding) throws IOException { + if (encoding == null) { + encoding = HttpUtil.DEFAULT_CHARSET; + } + OutputStreamWriter writer = new OutputStreamWriter(os, encoding); + writer.write("\n"); + writer.write("\n"); + return writer; + } + @Override public void writeResultTo(OutputStream os, String encoding) throws IOException { @@ -772,9 +784,16 @@ public class HTTPBindingProcessor extends AbstractBindingProcessor implements return; } else { log.debug("Getting result from invoker"); - OutputStreamWriter osw = new OutputStreamWriter(os, encoding); - slResult.writeTo(new StreamResult(osw), templates); - osw.flush(); + boolean fragment = false; + Writer writer; + if (slResult instanceof ErrorResult) { + writer = writeXMLDeclarationAndProcessingInstruction(os, encoding); + fragment = true; + } else { + writer = new OutputStreamWriter(os, encoding); + } + slResult.writeTo(new StreamResult(writer), templates, fragment); + writer.flush(); } } -- cgit v1.2.3 From 650732adaff82503b19a41b6c53d4299be9a1533 Mon Sep 17 00:00:00 2001 From: mcentner Date: Thu, 19 Nov 2009 13:37:10 +0000 Subject: Gracefully read the input stream. git-svn-id: https://joinup.ec.europa.eu/svn/mocca/trunk@552 8a26b1a7-26f0-462f-b9ef-d0e30c41f5a4 --- .../gv/egiz/bku/binding/HTTPBindingProcessor.java | 29 +++++++++++++++------- 1 file changed, 20 insertions(+), 9 deletions(-) (limited to 'bkucommon/src/main/java/at/gv/egiz/bku/binding/HTTPBindingProcessor.java') diff --git a/bkucommon/src/main/java/at/gv/egiz/bku/binding/HTTPBindingProcessor.java b/bkucommon/src/main/java/at/gv/egiz/bku/binding/HTTPBindingProcessor.java index a1c4d5fc..b1906666 100644 --- a/bkucommon/src/main/java/at/gv/egiz/bku/binding/HTTPBindingProcessor.java +++ b/bkucommon/src/main/java/at/gv/egiz/bku/binding/HTTPBindingProcessor.java @@ -16,6 +16,8 @@ */ package at.gv.egiz.bku.binding; +import iaik.utils.Base64InputStream; + import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; @@ -551,7 +553,20 @@ public class HTTPBindingProcessor extends AbstractBindingProcessor implements public InputStream getFormData(String aParameterName) { FormParameter fp = formParameterMap.get(aParameterName); if (fp != null) { - return fp.getFormParameterValue(); + final String enc = fp.getHeaderValue("Content-Transfer-Encoding"); + if (enc == null || "binary".equals(enc)) { + return fp.getFormParameterValue(); + } else if ("base64".equals(enc)) { + return new Base64InputStream(fp.getFormParameterValue()); + } else { + return new InputStream() { + @Override + public int read() throws IOException { + throw new IOException("Content-Transfer-Encoding : " + enc + + " is not supported."); + } + }; + } } return null; } @@ -679,12 +694,6 @@ public class HTTPBindingProcessor extends AbstractBindingProcessor implements if (slCommand == null) { throw new SLBindingException(2004); } - if (is.read() != -1) { - log.error("Request input stream not completely read"); - // consume rest of stream, should never occur - throw new SLRuntimeException( - "request input stream not consumed till end"); - } } catch (SLException slx) { log.info("Error while consuming input stream " + slx); bindingProcessorError = slx; @@ -693,8 +702,10 @@ public class HTTPBindingProcessor extends AbstractBindingProcessor implements bindingProcessorError = new SLException(2000); } finally { try { - while (is.read() != -1) - ; + if (is.read() != -1) { + log.warn("Request input stream not completely read."); + while (is.read() != -1); + } } catch (IOException e) { log.error(e); } -- cgit v1.2.3 From 5af9b75dccc1b52d1382fe0f2df30affd509f5b9 Mon Sep 17 00:00:00 2001 From: clemenso Date: Tue, 24 Nov 2009 18:48:00 +0000 Subject: Filenames derived from reference URI git-svn-id: https://joinup.ec.europa.eu/svn/mocca/trunk@553 8a26b1a7-26f0-462f-b9ef-d0e30c41f5a4 --- bkucommon/src/main/java/at/gv/egiz/bku/binding/HTTPBindingProcessor.java | 1 + 1 file changed, 1 insertion(+) (limited to 'bkucommon/src/main/java/at/gv/egiz/bku/binding/HTTPBindingProcessor.java') diff --git a/bkucommon/src/main/java/at/gv/egiz/bku/binding/HTTPBindingProcessor.java b/bkucommon/src/main/java/at/gv/egiz/bku/binding/HTTPBindingProcessor.java index b1906666..e39addb5 100644 --- a/bkucommon/src/main/java/at/gv/egiz/bku/binding/HTTPBindingProcessor.java +++ b/bkucommon/src/main/java/at/gv/egiz/bku/binding/HTTPBindingProcessor.java @@ -339,6 +339,7 @@ public class HTTPBindingProcessor extends AbstractBindingProcessor implements // process headers and request setHTTPHeaders(dataUrlResponse.getResponseHeaders()); consumeRequestStream(dataUrlResponse.getStream()); + //TODO check for bindingProcessorError closeDataUrlConnection(); srcContex.setSourceCertificate(conn.getServerCertificate()); srcContex.setSourceIsDataURL(true); -- cgit v1.2.3