    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
    015    package org.apache.tapestry5.internal.services;
    016
    017    import org.apache.tapestry5.internal.util.Base64OutputStream;
    018    import org.apache.tapestry5.internal.util.MacOutputStream;
    019    import org.apache.tapestry5.internal.util.TeeOutputStream;
    020    import org.apache.tapestry5.services.ClientDataSink;
    021    import org.apache.tapestry5.services.URLEncoder;
    022
    023    import java.io.BufferedOutputStream;
    024    import java.io.IOException;
    025    import java.io.ObjectOutputStream;
    026    import java.io.OutputStream;
    027    import java.security.Key;
    028    import java.util.zip.GZIPOutputStream;
    029
    030    public 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    }