001    /*
002     * Copyright (c) 2007-2015 Concurrent, Inc. All Rights Reserved.
003     *
004     * Project and contact information: http://www.cascading.org/
005     *
006     * This file is part of the Cascading project.
007     *
008     * Licensed under the Apache License, Version 2.0 (the "License");
009     * you may not use this file except in compliance with the License.
010     * 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, software
015     * distributed under the License is distributed on an "AS IS" BASIS,
016     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
017     * See the License for the specific language governing permissions and
018     * limitations under the License.
019     */
020    
021    package cascading.tap.local.io;
022    
023    import java.io.File;
024    import java.io.FileNotFoundException;
025    import java.io.FileOutputStream;
026    
027    import cascading.tap.Tap;
028    import cascading.tap.TapException;
029    
030    /**
031     *
032     */
033    public class TapFileOutputStream extends FileOutputStream
034      {
035      public TapFileOutputStream( String path, boolean append ) throws FileNotFoundException
036        {
037        super( prepare( null, path ), append );
038        }
039    
040      public TapFileOutputStream( Tap parent, String path, boolean update ) throws FileNotFoundException
041        {
042        super( prepare( parent, path ), update );
043        }
044    
045      private static String prepare( Tap parent, String path )
046        {
047        File file;
048    
049        if( parent == null )
050          file = new File( path );
051        else
052          file = new File( parent.getIdentifier(), path );
053    
054        // ignore the output. will catch the failure downstream if any.
055        // not ignoring the output causes race conditions with other systems writing to the same directory.
056        File parentFile = file.getAbsoluteFile().getParentFile();
057    
058        if( parentFile != null && parentFile.exists() && parentFile.isFile() )
059          throw new TapException( "cannot create parent directory, it already exists as a file: " + parentFile.getAbsolutePath() );
060    
061        // don't test for success, just fighting a race condition otherwise
062        // will get caught downstream
063        if( parentFile != null )
064          parentFile.mkdirs();
065    
066        return file.getAbsolutePath();
067        }
068      }