/*
** Apollo - Test Skeleton Toolkit for Web Start/JNLP
** Copyright (c) 2001, 2002, 2003 by Gerald Bauer
**
** This program is free software.
**
** You may redistribute it and/or modify it under the terms of the GNU
** General Public License as published by the Free Software Foundation.
** Version 2 of the license should be included with this distribution in
** the file LICENSE, as well as License.html. If the license is not
** included with this distribution, you may find a copy at the FSF web
** site at 'www.gnu.org' or 'www.fsf.org', or you may write to the
** Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139 USA.
**
** THIS SOFTWARE IS PROVIDED AS-IS WITHOUT WARRANTY OF ANY KIND,
** NOT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY. THE AUTHOR
** OF THIS SOFTWARE, ASSUMES _NO_ RESPONSIBILITY FOR ANY
** CONSEQUENCE RESULTING FROM THE USE, MODIFICATION, OR
** REDISTRIBUTION OF THIS SOFTWARE.
**
*/

package apollo;

import java.io.*;
import java.net.*;
import java.util.*;

public class MuffinStoreHandler
{
   private static MuffinStoreHandler _handler;

   private BasicService _basicService;
   private URL _codebase;
   private PersistenceService _persistenceService;

   public MuffinStoreHandler()
   {
      _basicService = ServiceManager.lookupBasicService();
      _persistenceService = ServiceManager.lookupPersistenceService();

      _codebase = _basicService.getCodeBase();
   }

   public void setTag( URL url, int tag ) throws MalformedURLException, IOException
   {
      _persistenceService.setTag( url, tag );
   }

   public static MuffinStoreHandler getHandler()
   {
      if( _handler == null )
         _handler = new MuffinStoreHandler();
      return _handler;
   }

   public FileContents get( URL url ) throws MalformedURLException, FileNotFoundException, IOException
   {
      return _persistenceService.get( url );
   }

   public FileContents get( String name ) throws MalformedURLException, FileNotFoundException, IOException
   {
      return _persistenceService.get( new URL( getCodeBase(), name ) );
   }

   public URL getCodeBase()
   {
      return _codebase;
   }

   public String[] getNames() throws MalformedURLException, IOException
   {
      return _persistenceService.getNames( getCodeBase() );
   }

   public String[] getNames( URL url ) throws MalformedURLException, IOException
   {
      return _persistenceService.getNames( url );
   }

   public String[] getNames( String name ) throws MalformedURLException, IOException
   {
      return _persistenceService.getNames( new URL( getCodeBase(), name ) );
   }

   public int getTag( URL url ) throws MalformedURLException, IOException
   {
      return _persistenceService.getTag( url );
   }

   /**
    *  return empty string for directory urls (that is, urls ending with a
    *  slash) e.g. http://www.host.org/path/path/ --> empty string return file
    *  name (that is, last path entry) for all other urls e.g.
    *  http://www.host.org/path/path/filename --> filename
    */
   private String getUrlFileName( URL url )
   {
      String path = url.getPath();

      if( path.endsWith( "/" ) )
         // it's a directory; no file name available
         return "";

      String name = "";
      int index = path.lastIndexOf( '/' );
      if( index != -1 )
         name = path.substring( index + 1 );

      return name;
   }

   public long create( URL url, long maxSize ) throws MalformedURLException, IOException
   {
      return _persistenceService.create( url, maxSize );
   }

   public long create( String name, long maxSize ) throws MalformedURLException, IOException
   {
      return _persistenceService.create( new URL( getCodeBase(), name ), maxSize );
   }

   public void delete( URL url ) throws MalformedURLException, IOException
   {
      _persistenceService.delete( url );
   }

   public void delete( String name ) throws MalformedURLException, IOException
   {
      _persistenceService.delete( new URL( getCodeBase(), name ) );
   }

   public boolean exists( URL url ) throws MalformedURLException, IOException
   {
      String names[] = getNames( url );

      // todo: throw URLException for URLs ending with a slash

      // get filename only (no directory path)
      String key = getUrlFileName( url );

      for( int i = 0; i < names.length; i++ )
         if( names[i].equals( key ) )
            return true;

      return false;
   }

   public boolean exists( String name ) throws MalformedURLException, IOException
   {
      return exists( new URL( getCodeBase(), name ) );
   }

   public Properties loadProperties( String name ) throws MalformedURLException, FileNotFoundException, IOException
   {
      // todo: should I check if the muffin exists first and return an empty property table
      //   instead of throwing a FileNotFoundException?

      FileContents contents = get( name );

      Properties props = new Properties();
      InputStream in = contents.getInputStream();
      props.load( in );
      in.close();

      return props;
   }

   public String loadText( String name ) throws MalformedURLException, FileNotFoundException, IOException
   {
      // todo: should I check if the muffin exists first and return an empty or default value
      //   instead of throwing a FileNotFoundException?

      FileContents contents = get( name );

      StringBuffer text = new StringBuffer();

      InputStreamReader in = new InputStreamReader( contents.getInputStream() );
      char buffer[] = new char[4096];
      int bytes_read;
      while( ( bytes_read = in.read( buffer ) ) != -1 )
         text.append( new String( buffer, 0, bytes_read ) );
      in.close();

      return text.toString();
   }

   public void saveProperties( String name, Properties props ) throws MalformedURLException, FileNotFoundException, IOException
   {
      saveProperties( name, props, 2056 );
   }

   public void saveProperties( String name, Properties props, long maxSize ) throws MalformedURLException, FileNotFoundException, IOException
   {
      URL muffinUrl = new URL( getCodeBase(), name );
      if( !exists( muffinUrl ) )
         create( muffinUrl, maxSize );

      FileContents contents = get( muffinUrl );

      OutputStream out = contents.getOutputStream( true );
      /*
       *  overwrite:=true
       */
      props.store( out, new Date().toString() );
      out.flush();
      out.close();
   }

   public void saveText( String name, String text ) throws MalformedURLException, FileNotFoundException, IOException
   {
      saveText( name, text, 2056 );
   }

   public void saveText( String name, String text, long maxSize ) throws MalformedURLException, FileNotFoundException, IOException
   {
      URL muffinUrl = new URL( getCodeBase(), name );
      if( !exists( muffinUrl ) )
         create( muffinUrl, maxSize );

      FileContents contents = get( muffinUrl );

      OutputStreamWriter out = new OutputStreamWriter( contents.getOutputStream( true ) );
      /*
       *  overwrite:=true
       */
      out.write( text );
      out.flush();
      out.close();
   }
}