001 package echopoint.tucana;
002
003 import echopoint.tucana.event.DownloadFailEvent;
004 import echopoint.tucana.event.DownloadFinishEvent;
005 import echopoint.tucana.event.DownloadStartEvent;
006 import static nextapp.echo.webcontainer.ClientProperties.BROWSER_INTERNET_EXPLORER;
007 import nextapp.echo.webcontainer.Connection;
008 import nextapp.echo.webcontainer.ContentType;
009 import nextapp.echo.webcontainer.Service;
010 import nextapp.echo.webcontainer.UserInstance;
011 import nextapp.echo.webcontainer.WebContainerServlet;
012
013 import javax.servlet.http.HttpServletResponse;
014 import java.io.IOException;
015 import java.io.OutputStream;
016
017 /**
018 * Services requests to download files.
019 *
020 * @author Echo File Transfer Library
021 * @version $Id: DownloadService.java 116 2009-02-19 00:23:08Z sptrakesh $
022 */
023 public class DownloadService implements Service
024 {
025 static final String SERVICE_ID = "echopoint.tucana.DownloadService";
026
027 private static final String HTTPS = "https";
028
029 private static final String PARAMETER_DOWNLOAD_UID = "duid";
030
031 private static final String[] URL_PARAMETERS = new String[]{ PARAMETER_DOWNLOAD_UID };
032
033 private static final DownloadService INSTANCE = new DownloadService();
034
035 /** Installs the service in the registry. */
036 public static void install()
037 {
038 WebContainerServlet.getServiceRegistry().add( INSTANCE );
039 }
040
041 /** Don't instantiate externally */
042 private DownloadService() {}
043
044 /**
045 * Creates a URI from which to download the file.
046 *
047 * @param userInstance the user instance of the user downloading.
048 * @param downloadId the id of the download command.
049 * @return the download URI.
050 */
051 public String createUri( UserInstance userInstance, String downloadId )
052 {
053 return userInstance.getServiceUri(
054 this, URL_PARAMETERS, new String[]{ downloadId } );
055 }
056
057 /** Returns the service id. */
058 public String getId()
059 {
060 return SERVICE_ID;
061 }
062
063 /** Returns the service version. */
064 public int getVersion()
065 {
066 return DO_NOT_CACHE;
067 }
068
069 /**
070 * Handles a service request.
071 *
072 * @param conn the connection.
073 */
074 public void service( Connection conn ) throws IOException
075 {
076 final UserInstance userInstance = conn.getUserInstance();
077 if ( userInstance == null )
078 {
079 serviceBadRequest( conn, "No container available." );
080 return;
081 }
082
083 final String downloadId =
084 conn.getRequest().getParameter( PARAMETER_DOWNLOAD_UID );
085 if ( downloadId == null )
086 {
087 serviceBadRequest( conn, "Download UID not specified." );
088 return;
089 }
090
091 final DownloadCommand download =
092 DownloadCommandPeer.getAndRemoveDownload( downloadId );
093 if ( download == null )
094 {
095 serviceBadRequest( conn, "Download UID is not valid." );
096 return;
097 }
098
099 service( conn, download );
100 }
101
102 /**
103 * Internal processing to handle the download request.
104 *
105 * @param conn the connection.
106 * @param download the download command.
107 * @throws IOException If errors are encountered while writing to the output
108 * stream of the connection.
109 */
110 private void service( Connection conn, DownloadCommand download )
111 throws IOException
112 {
113 final OutputStream out = conn.getOutputStream();
114 final DownloadProvider provider = download.getProvider();
115 final HttpServletResponse response = conn.getResponse();
116
117 if ( provider.getFileName() == null )
118 {
119 response.setHeader(
120 "Content-Disposition", provider.getContentDisposition() );
121 }
122 else
123 {
124 response.setHeader( "Content-Disposition",
125 provider.getContentDisposition() +
126 "; filename=\"" + provider.getFileName() + "\"" );
127 }
128
129 if ( provider.getSize() > 0 )
130 {
131 response.setHeader( "Content-Length", String.valueOf( provider.getSize() ) );
132 }
133
134 final String contentType = provider.getContentType();
135 if ( contentType == null )
136 {
137 response.setContentType( "application/octet-stream" );
138 }
139 else
140 {
141 response.setContentType( provider.getContentType() );
142 }
143
144 try
145 {
146 download.notifyCallback( new DownloadStartEvent( download, provider ) );
147
148 // Fix for IE and https connections
149 if ( HTTPS.equals( conn.getRequest().getScheme() ) &&
150 conn.getUserInstance().getClientProperties().getBoolean( BROWSER_INTERNET_EXPLORER ) )
151 {
152 response.setHeader( "Cache-Control", "" );
153 response.setHeader( "Pragma", "" );
154 }
155
156 provider.writeFile( out );
157 download.notifyCallback( new DownloadFinishEvent( download, provider ) );
158 }
159 catch ( Exception e )
160 {
161 download.notifyCallback( new DownloadFailEvent( download, provider, e ) );
162 }
163 }
164
165 /**
166 * Sets the response status indicating that a bad request was made to this
167 * service.
168 *
169 * @param conn the connection.
170 * @param message the error message.
171 */
172 private void serviceBadRequest( Connection conn, String message )
173 {
174 conn.getResponse().setStatus( HttpServletResponse.SC_BAD_REQUEST );
175 conn.setContentType( ContentType.TEXT_PLAIN );
176 conn.getWriter().write( message );
177 }
178
179 /**
180 * Returns an instance for public use.
181 *
182 * @return an instance for public use.
183 */
184 public static DownloadService getInstance()
185 {
186 return INSTANCE;
187 }
188 }