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    }