/* * Copyright (c) 1990-2012 kopiLeft Development SARL, Bizerte, Tunisia * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License version 2.1 as published by the Free Software Foundation. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * $Id$ */ package org.kopi.ebics.client; import java.io.IOException; import java.io.OutputStream; import java.util.Date; import org.kopi.ebics.exception.EbicsException; import org.kopi.ebics.interfaces.ContentFactory; import org.kopi.ebics.io.ByteArrayContentFactory; import org.kopi.ebics.io.Joiner; import org.kopi.ebics.messages.Messages; import org.kopi.ebics.session.EbicsSession; import org.kopi.ebics.session.OrderType; import org.kopi.ebics.utils.Constants; import org.kopi.ebics.utils.Utils; import org.kopi.ebics.xml.DInitializationRequestElement; import org.kopi.ebics.xml.DInitializationResponseElement; import org.kopi.ebics.xml.DTransferRequestElement; import org.kopi.ebics.xml.DTransferResponseElement; import org.kopi.ebics.xml.DefaultEbicsRootElement; import org.kopi.ebics.xml.InitializationResponseElement; import org.kopi.ebics.xml.ReceiptRequestElement; import org.kopi.ebics.xml.ReceiptResponseElement; import org.kopi.ebics.xml.TransferResponseElement; import org.kopi.ebics.xml.UInitializationRequestElement; import org.kopi.ebics.xml.UTransferRequestElement; /** * Handling of file transfers. * Files can be transferred to and fetched from the bank. * Every transfer may be performed in a recoverable way. * For convenience and performance reasons there are also * methods that do the whole transfer in one method call. * To use the recoverable transfer mode, you may set a working * directory for temporarily created files. * * <p> EBICS specification 2.4.2 - 6.2 Encryption at application level * * <p>In the event of an upload transaction, a random symmetrical key is generated in the * customer system that is used exclusively within the framework of this transaction both for * encryption of the ES’s and for encryption of the order data. This key is encrypted * asymmetrically with the financial institution’s public encryption key and is transmitted by the * customer system to the bank system during the initialization phase of the transaction. * * <p>Analogously, in the case of a download transaction a random symmetrical key is generated * in the bank system that is used for encryption of the order data that is to be downloaded and * for encryption of the bank-technical signature that has been provided by the financial * institution. This key is asymmetrically encrypted and is transmitted by the bank system to the * customer system during the initialization phase of the transaction. The asymmetrical * encryption takes place with the technical subscriber’s public encryption key if the * transaction’s EBICS messages are sent by a technical subscriber. Otherwise the * asymmetrical encryption takes place with the public encryption key of the non-technical * subscriber, i.e. the submitter of the order. * * @author Hachani * */ public class FileTransfer { /** * Constructs a new FileTransfer session * @param session the user session */ public FileTransfer(EbicsSession session) { this.session = session; } /** * Initiates a file transfer to the bank. * @param content The bytes you want to send. * @param orderType As which order type * @throws IOException * @throws EbicsException */ public void sendFile(byte[] content, OrderType orderType) throws IOException, EbicsException { HttpRequestSender sender; UInitializationRequestElement initializer; InitializationResponseElement response; int httpCode; TransferState state; sender = new HttpRequestSender(session); initializer = new UInitializationRequestElement(session, orderType, content); initializer.build(); initializer.validate(); session.getConfiguration().getTraceManager().trace(initializer.getUserSignature()); session.getConfiguration().getTraceManager().trace(initializer); httpCode = sender.send(new ByteArrayContentFactory(initializer.prettyPrint())); Utils.checkHttpCode(httpCode); response = new InitializationResponseElement(sender.getResponseBody(), orderType, DefaultEbicsRootElement.generateName(orderType)); response.build(); session.getConfiguration().getTraceManager().trace(response); response.report(); state = new TransferState(initializer.getSegmentNumber(), response.getTransactionId()); while(state.hasNext()) { int segmentNumber; segmentNumber = state.next(); sendFile(initializer.getContent(segmentNumber), segmentNumber, state.isLastSegment(), state.getTransactionId(), orderType); } } /** * Sends a segment to the ebics bank server. * @param factory the content factory that contain the segment data. * @param segmentNumber the segment number * @param lastSegment is it the last segment? * @param transactionId the transaction Id * @param orderType the order type * @throws IOException * @throws EbicsException */ public void sendFile(ContentFactory factory, int segmentNumber, boolean lastSegment, byte[] transactionId, OrderType orderType) throws IOException, EbicsException { UTransferRequestElement uploader; HttpRequestSender sender; TransferResponseElement response; int httpCode; session.getConfiguration().getLogger().info(Messages.getString("upload.segment", Constants.APPLICATION_BUNDLE_NAME, segmentNumber)); uploader = new UTransferRequestElement(session, orderType, segmentNumber, lastSegment, transactionId, factory); sender = new HttpRequestSender(session); uploader.build(); uploader.validate(); session.getConfiguration().getTraceManager().trace(uploader); httpCode = sender.send(new ByteArrayContentFactory(uploader.prettyPrint())); Utils.checkHttpCode(httpCode); response = new TransferResponseElement(sender.getResponseBody(), DefaultEbicsRootElement.generateName(orderType)); response.build(); session.getConfiguration().getTraceManager().trace(response); response.report(); } /** * Fetches a file of the given order type from the bank. * You may give an optional start and end date. * This type of transfer will run until everything is processed. * No transaction recovery is possible. * @param orderType type of file to fetch * @param start optional begin of fetch term * @param end optional end of fetch term * @param dest where to put the data * @throws IOException communication error * @throws EbicsException server generated error */ public void fetchFile(OrderType orderType, Date start, Date end, OutputStream dest) throws IOException, EbicsException { HttpRequestSender sender; DInitializationRequestElement initializer; DInitializationResponseElement response; ReceiptRequestElement receipt; ReceiptResponseElement receiptResponse; int httpCode; TransferState state; Joiner joiner; sender = new HttpRequestSender(session); initializer = new DInitializationRequestElement(session, orderType, start, end); initializer.build(); initializer.validate(); session.getConfiguration().getTraceManager().trace(initializer); httpCode = sender.send(new ByteArrayContentFactory(initializer.prettyPrint())); Utils.checkHttpCode(httpCode); response = new DInitializationResponseElement(sender.getResponseBody(), orderType, DefaultEbicsRootElement.generateName(orderType)); response.build(); session.getConfiguration().getTraceManager().trace(response); response.report(); state = new TransferState(response.getSegmentsNumber(), response.getTransactionId()); state.setSegmentNumber(response.getSegmentNumber()); joiner = new Joiner(session.getUser()); joiner.append(response.getOrderData()); while(state.hasNext()) { int segmentNumber; segmentNumber = state.next(); fetchFile(orderType, segmentNumber, state.isLastSegment(), state.getTransactionId(), joiner); } joiner.writeTo(dest, response.getTransactionKey()); receipt = new ReceiptRequestElement(session, state.getTransactionId(), DefaultEbicsRootElement.generateName(orderType)); receipt.build(); receipt.validate(); session.getConfiguration().getTraceManager().trace(receipt); httpCode = sender.send(new ByteArrayContentFactory(receipt.prettyPrint())); Utils.checkHttpCode(httpCode); receiptResponse = new ReceiptResponseElement(sender.getResponseBody(), DefaultEbicsRootElement.generateName(orderType)); receiptResponse.build(); session.getConfiguration().getTraceManager().trace(receiptResponse); receiptResponse.report(); } /** * Fetches a given portion of a file. * @param orderType the order type * @param segmentNumber the segment number * @param lastSegment is it the last segment? * @param transactionId the transaction ID * @param joiner the portions joiner * @throws IOException communication error * @throws EbicsException server generated error */ public void fetchFile(OrderType orderType, int segmentNumber, boolean lastSegment, byte[] transactionId, Joiner joiner) throws IOException, EbicsException { DTransferRequestElement downloader; HttpRequestSender sender; DTransferResponseElement response; int httpCode; sender = new HttpRequestSender(session); downloader = new DTransferRequestElement(session, orderType, segmentNumber, lastSegment, transactionId); downloader.build(); downloader.validate(); session.getConfiguration().getTraceManager().trace(downloader); httpCode = sender.send(new ByteArrayContentFactory(downloader.prettyPrint())); Utils.checkHttpCode(httpCode); response = new DTransferResponseElement(sender.getResponseBody(), orderType, DefaultEbicsRootElement.generateName(orderType)); response.build(); session.getConfiguration().getTraceManager().trace(response); response.report(); joiner.append(response.getOrderData()); } // -------------------------------------------------------------------- // DATA MEMBERS // -------------------------------------------------------------------- private EbicsSession session; }