    001// Copyright 2009, 2012 The Apache Software Foundation
    002//
    003// Licensed under the Apache License, Version 2.0 (the "License");
    004// you may not use this file except in compliance with the License.
    005// You may obtain a copy of the License at
    006//
    007//     http://www.apache.org/licenses/LICENSE-2.0
    008//
    009// Unless required by applicable law or agreed to in writing, software
    010// distributed under the License is distributed on an "AS IS" BASIS,
    011// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    012// See the License for the specific language governing permissions and
    013// limitations under the License.
    014
    015package org.apache.tapestry5.internal.services;
    016
    017import org.apache.tapestry5.internal.util.Base64OutputStream;
    018import org.apache.tapestry5.internal.util.MacOutputStream;
    019import org.apache.tapestry5.internal.util.TeeOutputStream;
    020import org.apache.tapestry5.services.ClientDataSink;
    021import org.apache.tapestry5.services.URLEncoder;
    022
    023import java.io.BufferedOutputStream;
    024import java.io.IOException;
    025import java.io.ObjectOutputStream;
    026import java.io.OutputStream;
    027import java.security.Key;
    028import java.util.zip.GZIPOutputStream;
    029
    030public class ClientDataSinkImpl implements ClientDataSink
    031{
    032    private final Base64OutputStream base64OutputStream;
    033
    034    private final ObjectOutputStream objectOutputStream;
    035
    036    private final URLEncoder urlEncoder;
    037
    038    private boolean closed;
    039
    040    private final MacOutputStream macOutputStream;
    041
    042    public ClientDataSinkImpl(URLEncoder urlEncoder, Key hmacKey) throws IOException
    043    {
    044        this.urlEncoder = urlEncoder;
    045
    046        base64OutputStream = new Base64OutputStream();
    047        macOutputStream =  MacOutputStream.streamFor(hmacKey);
    048
    049        final BufferedOutputStream pipeline = new BufferedOutputStream(new GZIPOutputStream(
    050                new TeeOutputStream(macOutputStream, base64OutputStream)));
    051
    052        OutputStream guard = new OutputStream()
    053        {
    054            @Override
    055            public void write(int b) throws IOException
    056            {
    057                pipeline.write(b);
    058            }
    059
    060            @Override
    061            public void close() throws IOException
    062            {
    063                closed = true;
    064
    065                pipeline.close();
    066            }
    067
    068            @Override
    069            public void flush() throws IOException
    070            {
    071                pipeline.flush();
    072            }
    073
    074            @Override
    075            public void write(byte[] b) throws IOException
    076            {
    077                pipeline.write(b);
    078            }
    079
    080            @Override
    081            public void write(byte[] b, int off, int len) throws IOException
    082            {
    083                pipeline.write(b, off, len);
    084            }
    085        };
    086
    087
    088        objectOutputStream = new ObjectOutputStream(guard);
    089    }
    090
    091    public ObjectOutputStream getObjectOutputStream()
    092    {
    093        return objectOutputStream;
    094    }
    095
    096    public String getClientData()
    097    {
    098        if (!closed)
    099        {
    100            try
    101            {
    102                objectOutputStream.close();
    103            } catch (IOException ex)
    104            {
    105                // Ignore.
    106            }
    107        }
    108
    109        return macOutputStream.getResult() + ":" + base64OutputStream.toBase64();
    110    }
    111
    112    public String getEncodedClientData()
    113    {
    114        return urlEncoder.encode(getClientData());
    115    }
    116}