001package org.apache.maven.wagon;
002
003/*
004 * Licensed to the Apache Software Foundation (ASF) under one
005 * or more contributor license agreements.  See the NOTICE file
006 * distributed with this work for additional information
007 * regarding copyright ownership.  The ASF licenses this file
008 * to you under the Apache License, Version 2.0 (the
009 * "License"); you may not use this file except in compliance
010 * with the License.  You may obtain a copy of the License at
011 *
012 *   http://www.apache.org/licenses/LICENSE-2.0
013 *
014 * Unless required by applicable law or agreed to in writing,
015 * software distributed under the License is distributed on an
016 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
017 * KIND, either express or implied.  See the License for the
018 * specific language governing permissions and limitations
019 * under the License.
020 */
021
022import java.io.File;
023import java.io.IOException;
024import java.io.InputStream;
025import java.io.OutputStream;
026
027import org.apache.maven.wagon.authorization.AuthorizationException;
028import org.apache.maven.wagon.events.TransferEvent;
029import org.apache.maven.wagon.resource.Resource;
030
031/**
032 * Base class for wagon which provide stream based API.
033 *
034 * @author <a href="mailto:michal@codehaus.org">Michal Maczka</a>
035 *
036 */
037public abstract class StreamWagon
038    extends AbstractWagon
039    implements StreamingWagon
040{
041    // ----------------------------------------------------------------------
042    //
043    // ----------------------------------------------------------------------
044
045    public abstract void fillInputData( InputData inputData )
046        throws TransferFailedException, ResourceDoesNotExistException, AuthorizationException;
047
048    public abstract void fillOutputData( OutputData outputData )
049        throws TransferFailedException;
050
051    public abstract void closeConnection()
052        throws ConnectionException;
053
054    // ----------------------------------------------------------------------
055    //
056    // ----------------------------------------------------------------------
057
058    public void get( String resourceName, File destination )
059        throws TransferFailedException, ResourceDoesNotExistException, AuthorizationException
060    {
061        getIfNewer( resourceName, destination, 0 );
062    }
063
064    protected void checkInputStream( InputStream is, Resource resource )
065        throws TransferFailedException
066    {
067        if ( is == null )
068        {
069            TransferFailedException e =
070                new TransferFailedException( getRepository().getUrl()
071                    + " - Could not open input stream for resource: '" + resource + "'" );
072            fireTransferError( resource, e, TransferEvent.REQUEST_GET );
073            throw e;
074        }
075    }
076
077    public boolean getIfNewer( String resourceName, File destination, long timestamp )
078        throws TransferFailedException, ResourceDoesNotExistException, AuthorizationException
079    {
080        boolean retValue = false;
081
082        Resource resource = new Resource( resourceName );
083
084        fireGetInitiated( resource, destination );
085
086        resource.setLastModified( timestamp );
087        
088        InputStream is = getInputStream( resource );
089
090        // always get if timestamp is 0 (ie, target doesn't exist), otherwise only if older than the remote file
091        if ( timestamp == 0 || timestamp < resource.getLastModified() )
092        {
093            retValue = true;
094
095            checkInputStream( is, resource );
096
097            getTransfer( resource, destination, is );
098        }
099        else
100        {
101            try
102            {
103                if ( is != null )
104                {
105                    is.close();
106                }
107            }
108            catch ( final IOException e )
109            {
110                throw new TransferFailedException( "Failure transferring " + resourceName, e );
111            }
112        }
113
114        return retValue;
115    }
116
117    protected InputStream getInputStream( Resource resource )
118        throws TransferFailedException, ResourceDoesNotExistException, AuthorizationException
119    {
120        InputData inputData = new InputData();
121
122        inputData.setResource( resource );
123
124        try
125        {
126            fillInputData( inputData );
127        }
128        catch ( TransferFailedException e )
129        {
130            fireTransferError( resource, e, TransferEvent.REQUEST_GET );
131            cleanupGetTransfer( resource );
132            throw e;
133        }
134        catch ( ResourceDoesNotExistException e )
135        {
136            fireTransferError( resource, e, TransferEvent.REQUEST_GET );
137            cleanupGetTransfer( resource );
138            throw e;
139        }
140        catch ( AuthorizationException e )
141        {
142            fireTransferError( resource, e, TransferEvent.REQUEST_GET );
143            cleanupGetTransfer( resource );
144            throw e;
145        }
146        finally
147        {
148            if ( inputData.getInputStream() == null )
149            {
150                cleanupGetTransfer( resource );
151            }
152        }
153
154        return inputData.getInputStream();
155    }
156
157    // source doesn't exist exception
158    public void put( File source, String resourceName )
159        throws TransferFailedException, ResourceDoesNotExistException, AuthorizationException
160    {
161        Resource resource = new Resource( resourceName );
162
163        firePutInitiated( resource, source );
164
165        resource.setContentLength( source.length() );
166
167        resource.setLastModified( source.lastModified() );
168
169        OutputStream os = getOutputStream( resource );
170
171        checkOutputStream( resource, os );
172
173        putTransfer( resource, source, os, true );
174    }
175
176    protected void checkOutputStream( Resource resource, OutputStream os )
177        throws TransferFailedException
178    {
179        if ( os == null )
180        {
181            TransferFailedException e =
182                new TransferFailedException( getRepository().getUrl()
183                    + " - Could not open output stream for resource: '" + resource + "'" );
184            fireTransferError( resource, e, TransferEvent.REQUEST_PUT );
185            throw e;
186        }
187    }
188
189    protected OutputStream getOutputStream( Resource resource )
190        throws TransferFailedException
191    {
192        OutputData outputData = new OutputData();
193
194        outputData.setResource( resource );
195
196        try
197        {
198            fillOutputData( outputData );
199        }
200        catch ( TransferFailedException e )
201        {
202            fireTransferError( resource, e, TransferEvent.REQUEST_PUT );
203
204            throw e;
205        }
206        finally
207        {
208            if ( outputData.getOutputStream() == null )
209            {
210                cleanupPutTransfer( resource );
211            }
212        }
213
214        return outputData.getOutputStream();
215    }
216
217    public boolean getIfNewerToStream( String resourceName, OutputStream stream, long timestamp )
218        throws ResourceDoesNotExistException, TransferFailedException, AuthorizationException
219    {
220        boolean retValue = false;
221
222        Resource resource = new Resource( resourceName );
223
224        fireGetInitiated( resource, null );
225
226        InputStream is = getInputStream( resource );
227
228        // always get if timestamp is 0 (ie, target doesn't exist), otherwise only if older than the remote file
229        if ( timestamp == 0 || timestamp < resource.getLastModified() )
230        {
231            retValue = true;
232
233            checkInputStream( is, resource );
234
235            fireGetStarted( resource, null );
236
237            getTransfer( resource, stream, is, true, Integer.MAX_VALUE );
238
239            fireGetCompleted( resource, null );
240        }
241        else
242        {
243            try
244            {
245                if ( is != null )
246                {
247                    is.close();
248                }
249            }
250            catch ( final IOException e )
251            {
252                throw new TransferFailedException( "Failure transferring " + resourceName, e );
253            }
254        }
255        
256        return retValue;
257    }
258
259    public void getToStream( String resourceName, OutputStream stream )
260        throws ResourceDoesNotExistException, TransferFailedException, AuthorizationException
261    {
262        getIfNewerToStream( resourceName, stream, 0 );
263    }
264
265    public void putFromStream( InputStream stream, String destination )
266        throws TransferFailedException, ResourceDoesNotExistException, AuthorizationException
267    {
268        Resource resource = new Resource( destination );
269
270        firePutInitiated( resource, null );
271
272        putFromStream( stream, resource );
273    }
274
275    public void putFromStream( InputStream stream, String destination, long contentLength, long lastModified )
276        throws TransferFailedException, ResourceDoesNotExistException, AuthorizationException
277    {
278        Resource resource = new Resource( destination );
279
280        firePutInitiated( resource, null );
281
282        resource.setContentLength( contentLength );
283
284        resource.setLastModified( lastModified );
285
286        putFromStream( stream, resource );
287    }
288
289    protected void putFromStream( InputStream stream, Resource resource )
290        throws TransferFailedException, AuthorizationException, ResourceDoesNotExistException
291    {
292        OutputStream os = getOutputStream( resource );
293
294        checkOutputStream( resource, os );
295
296        firePutStarted( resource, null );
297
298        putTransfer( resource, stream, os, true );
299
300        firePutCompleted( resource, null );
301    }
302}