Source code: com/flexstor/flexdbserver/services/download/DownloadService.java
1 /*
2 * DownloadService.java
3 *
4 * Copyright $Date: 2003/08/11 02:22:49 $ FLEXSTOR.net Inc.
5 *
6 * This work is licensed for use and distribution under license terms found at
7 * http://www.flexstor.org/license.html
8 *
9 */
10
11 package com.flexstor.flexdbserver.services.download;
12
13 import java.util.Vector;
14
15 import com.flexstor.common.constants.ActionPropertiesI;
16 import com.flexstor.common.constants.ServicesI;
17 import com.flexstor.common.data.ActionData;
18 import com.flexstor.common.data.ActionResult;
19 import com.flexstor.common.data.AssetRecordData;
20 import com.flexstor.common.errorlogger.FlexError;
21 import com.flexstor.common.resources.Resources;
22 import com.flexstor.common.services.ServiceBrokerI;
23 import com.flexstor.common.services.SrvcNotAvailException;
24 import com.flexstor.common.settings.Settings;
25 import com.flexstor.common.util.StringUtil;
26 import com.flexstor.flexdbserver.services.Service;
27 import com.flexstor.flexdbserver.services.ServiceContext;
28 import com.flexstor.flexdbserver.transactionmanager.TransMngDownload;
29 import com.flexstor.flexdbserver.util.PathAnalyzer;
30
31
32 /**
33 * <P>
34 * DownloadService <BR>
35 * <BLOCKQUOTE>
36 * This service copies the requested assets to a temporary location from where they can be downloaded using a browser.
37 * </BLOCKQUOTE>
38 * </P>
39 *
40 * Configurable Properties in roletype_services.config <BR>
41 *
42 * <TABLE BORDER="1" CELLPADDING="3" CELLSPACING="3">
43 * <CAPTION ALIGN=TOP>
44 * <B> In/Out Properties for Assets </B>
45 * </CAPTION>
46 * <TR>
47 * <FONT SIZE=+1><B>
48 * <TH WIDTH="120">Attribute</TH>
49 * <TH WIDTH="30">IN</TH> <TH WIDTH="30">OUT</TH> <TH WIDTH="30">Default IN</TH> <TH WIDTH="30">Default OUT</TH>
50 * </B></FONT>
51 * </TR>
52 * <TR>
53 * <TH ALIGN=LEFT><FONT SIZE=+1><B>ROLE</B></FONT></TH>
54 * <TD ALIGN=CENTER>   </TD> <TD ALIGN=CENTER>   </TD> <TD ALIGN=CENTER> ALL </TD> <TD ALIGN=CENTER> ALL </TD>
55 * </TR>
56 * <TR><TH> Highres </TH> <TD ALIGN=CENTER> X </TD> <TD ALIGN=CENTER> X </TD> <TD ALIGN=CENTER>   </TD> <TD ALIGN=CENTER>   </TD></TR>
57 * <TR><TH> Lowres </TH> <TD ALIGN=CENTER> X </TD> <TD ALIGN=CENTER> X </TD> <TD ALIGN=CENTER>   </TD> <TD ALIGN=CENTER>   </TD></TR>
58 * <TR><TH> Thumbnail </TH> <TD ALIGN=CENTER> X </TD> <TD ALIGN=CENTER> X </TD> <TD ALIGN=CENTER>   </TD> <TD ALIGN=CENTER> X </TD></TR>
59 * <TR><TH> Layout </TH> <TD ALIGN=CENTER> X </TD> <TD ALIGN=CENTER> X </TD> <TD ALIGN=CENTER>   </TD> <TD ALIGN=CENTER>   </TD></TR>
60 * <TR><TH> Video </TH> <TD ALIGN=CENTER> X </TD> <TD ALIGN=CENTER> X </TD> <TD ALIGN=CENTER>   </TD> <TD ALIGN=CENTER>   </TD></TR>
61 * <TR><TH> Audio </TH> <TD ALIGN=CENTER> X </TD> <TD ALIGN=CENTER> X </TD> <TD ALIGN=CENTER>   </TD> <TD ALIGN=CENTER>   </TD></TR>
62 * <TR>
63 * <TH ALIGN=LEFT><FONT SIZE=+1><B>TYPE</B></FONT></TH>
64 * <TD ALIGN=CENTER> X </TD> <TD ALIGN=CENTER> X </TD> <TD ALIGN=CENTER> ALL </TD> <TD ALIGN=CENTER>   </TD></TR>
65 * </TR>
66 * <TR>
67 * <TH ALIGN=LEFT><FONT SIZE=+1><B>FLAG</B></FONT></TH>
68 * </TR>
69 * <TR><TH> PARENT </TH> <TD ALIGN=CENTER> X </TD> <TD ALIGN=CENTER> X </TD> <TD ALIGN=CENTER>   </TD> <TD ALIGN=CENTER>   </TD></TR>
70 * <TR><TH> CHLDREN </TH> <TD ALIGN=CENTER> X </TD> <TD ALIGN=CENTER> X </TD> <TD ALIGN=CENTER>   </TD> <TD ALIGN=CENTER> X </TD></TR>
71 * <TR><TH> ALL </TH> <TD ALIGN=CENTER> X </TD> <TD ALIGN=CENTER> X </TD> <TD ALIGN=CENTER>   </TD> <TD ALIGN=CENTER>   </TD></TR>
72 * <TR><TH> TEMP_PARENT </TH> <TD ALIGN=CENTER> X </TD> <TD ALIGN=CENTER> X </TD> <TD ALIGN=CENTER>   </TD> <TD ALIGN=CENTER>   </TD></TR>
73 * <TR><TH> TEMP_CHILDREN </TH> <TD ALIGN=CENTER> X </TD> <TD ALIGN=CENTER> X </TD> <TD ALIGN=CENTER>   </TD> <TD ALIGN=CENTER>   </TD></TR>
74 * <TR><TH> TEMP_ALL </TH> <TD ALIGN=CENTER> X </TD> <TD ALIGN=CENTER> X </TD> <TD ALIGN=CENTER>   </TD> <TD ALIGN=CENTER>   </TD></TR>
75 * </TABLE>
76 *
77 * Configurable Properties in flexstorweb.properties <BR>
78 * <BLOCKQUOTE>
79 * <P>
80 * flexstor.download.baseURL: The http URL corresponding to the baseDir where the assets are copied <BR>
81 * Legal values: URL path (including the server name or IP address)
82 * </BLOCKQUOTE>
83 * </P>
84 *
85 * <P>
86 * Input Data Object <BR>
87 * <BLOCKQUOTE>
88 * com.flexstor.common.data.ActionData
89 * </BLOCKQUOTE>
90 * </P>
91 *
92 * <P>
93 * Output Data Object <BR>
94 * <BLOCKQUOTE>
95 * com.flexstor.common.data.ActionResult
96 * </BLOCKQUOTE>
97 * </P>
98 *
99 * Programmable Properties (passed inside data object) <BR>
100 * <BLOCKQUOTE>
101 * Global Properties (apply to all assets) <BR>
102 * <BLOCKQUOTE>
103 * <P>
104 * "DestinationServer": (ActionPropertiesI.DESTINATION_SERVER)
105 * Specifies the destination server where the new file will be placed.
106 * Set in ActionData . <BR>
107 * Data type: String <BR>
108 * Legal values: Valid server name (Fully qualified name or server name only) <BR>
109 * </P>
110 * <P>
111 * "DestinationLocation": (ActionPropertiesI.DESTINATION_LOCATION)
112 * Specifies the destination path where the new file will be placed.
113 * Set in ActionData . <BR>
114 * Data type: String <BR>
115 * Legal values: Valid path string <BR>
116 * </P>
117 * <P>
118 * "EmailMessage": (ActionPropertiesI.EMAIL_MESSAGE)
119 * Specifies the email message body.
120 * Set in ActionData . <BR>
121 * Data type: String <BR>
122 * Legal values: <BR>
123 * </P>
124 * <P>
125 * "EmailSubject": (ActionPropertiesI.EMAIL_SUBJECT)
126 * Specifies the email message subject.
127 * Set in ActionData . <BR>
128 * Data type: String <BR>
129 * Legal values: <BR>
130 * </P>
131 * <P>
132 * "SendServiceType": (ActionPropertiesI.SEND_SERVICE_TYPE)
133 * Send service type selection.
134 * Set in ActionData <BR>
135 * Data type: Integer <BR>
136 * Legal values: <ServicesI.MIME, ServicesI.FTP, ServicesI.COPY><BR>
137 * </P>
138 * <P>
139 * "KeepResourceFork": (ActionPropertiesI.KEEP_RESOURCE_FORK)
140 * If true, handle resource fork.
141 * Set in ActionData (defaults to false). <BR>
142 * Data type: Boolean <BR>
143 * Legal values: <true, false><BR>
144 * </P>
145 */
146 public class DownloadService
147 implements Service
148 {
149 public String IDENTIFIER = "$Id: DownloadService.java,v 1.5 2003/08/11 02:22:49 aleric Exp $";
150
151
152 protected String sThisService = null;
153 protected String sDestinationLocation;
154 protected String sAppServer;
155 protected String sService = "";
156 protected boolean bAbortService = false;
157 protected ActionData emailData;
158 protected ActionData actionData;
159
160 private ServiceBrokerI serviceBroker;
161 private String fileSeparator;
162 private int id = -1;
163
164 /**
165 * Calls before the service is initialized (before initData is called) to
166 * pass information about the environment in which the service is running.
167 * This environment consists of information about the properties set for the
168 * service in one of these files (services.config, roletype_services.config,
169 * or *.ctl), plus methods to access other information such as an instance
170 * of the service broker to invoke other services, the transaction id for
171 * the service, file separator character and local path for the installation
172 * directory and configuration directory.
173 *
174 * @param context Holds information about the environment in which the service
175 * is running.
176 */
177 public void setServiceContext( ServiceContext context )
178 {
179 id = context.getTransactionId();
180 fileSeparator = context.getFileSeparator();
181 serviceBroker = context.getServiceBroker();
182 }
183
184 /**
185 *Method to initialize the data used by this service. Extracts the email data if any and also sets the destination
186 *@param action The ActionData object containing the request
187 */
188 public void initData( ActionData action )
189 {
190 this.actionData = action;
191 emailData = (ActionData)actionData.getObject( ActionPropertiesI.CONFIRMATION_DATA ); //extract the email data if any
192 //6814=Download Service
193 sThisService = Resources.get(6814) + " (" + id + ")";
194
195 //set the detination as baseDir + trasactionId
196 // The only time these values could be null (during normal processing) is when the doPreProcessing(...) method of a
197 // distributed download service has been called.
198 String sBaseDir = actionData.getString(ActionPropertiesI.DESTINATION_LOCATION);
199
200 if ( sBaseDir != null )
201 {
202 sDestinationLocation = sBaseDir + fileSeparator + String.valueOf(actionData.getTransId()) + fileSeparator;
203
204 // If the DESTINATION_LOCATION property holds a URL, then extract the server name and
205 // add it to the DESTINATION_SERVER property
206 if ( sDestinationLocation != null && PathAnalyzer.getRemoteFileProtocol(sDestinationLocation) != null )
207 {
208 actionData.setString( ActionPropertiesI.DESTINATION_SERVER, PathAnalyzer.getServerName(sDestinationLocation) );
209 actionData.setString( ActionPropertiesI.DESTINATION_LOCATION, PathAnalyzer.getLocalPath(sDestinationLocation) );
210 }
211 else
212 actionData.setString( ActionPropertiesI.DESTINATION_LOCATION, sDestinationLocation );
213
214 sAppServer = Settings.getString( Settings.APP_SERVER_HOST );
215 }
216 } // init
217
218 /**
219 *Method which implements the download service by calling the copy service followed by an email service if necessary
220 *@return Result
221 */
222 public ActionResult go()
223 {
224 // Run the Send Service
225 // Remove emailData from actionData so we don't get email confirmation from the Send Service
226 actionData.removeObject( ActionPropertiesI.CONFIRMATION_DATA );
227 actionData.setInteger(ActionPropertiesI.SEND_SERVICE_TYPE, new Integer(ServicesI.COPY));
228 ActionResult actionResult = executeService( actionData, ServicesI.SEND_SERVICE );
229 bAbortService = !actionResult.isSuccess();
230
231 // The getDownloadURL(...) sets the URL_STRING in every record which must be returned to the JSP client to
232 // be displayed. Also store the array of urls in a variable; this will be used to populate the body of an
233 // email confirmation, if requested.
234 String url[] = getDownloadURL(actionData);
235 //Set the email message depending on the result of the copy service
236 if ( emailData != null )
237 {
238 if( !bAbortService )
239 {
240 String message = null;
241
242 if ( emailData.getString(ActionPropertiesI.EMAIL_SUBJECT) == null )
243 //set the email subject to successful
244 emailData.setString(ActionPropertiesI.EMAIL_SUBJECT, Resources.get(6815, "successful") );
245
246 //add email message from resource file
247 if ( emailData.getString(ActionPropertiesI.EMAIL_MESSAGE) != null )
248 message = emailData.getString(ActionPropertiesI.EMAIL_MESSAGE) + "\n\n" + Resources.get(6816) + "\n";
249 else
250 message = "\n" + Resources.get(6816) + "\n";
251
252 //add the URLs to the message
253 for( int i = 0; i < url.length; i++)
254 message = message + url[i] + "\n";
255
256 emailData.setString(ActionPropertiesI.EMAIL_MESSAGE, message);
257 }
258 else
259 {
260 //set the email subject to unsuccessful
261 emailData.setString(ActionPropertiesI.EMAIL_SUBJECT, Resources.get(6815,"unsuccessful") );
262
263 //set the unsuccessful meassage from the resource file with the transaction id
264 emailData.setString(ActionPropertiesI.EMAIL_MESSAGE, Resources.get( 6817, String.valueOf( actionData.getTransId() ) ));
265 }
266
267 executeService(emailData,ServicesI.EMAIL_SERVICE); //call the email service
268 }
269
270 //Set the transaction state depending on the send result
271 if (!bAbortService)
272 {
273 (new TransMngDownload( actionData.getTransId(),actionData )).setTransactionCompletedState(true);
274 }
275
276 // Setup the result object. Use the result object directly from the SEND service.
277 actionResult.setId( actionData.getTransId() );
278 return actionResult;
279 }
280
281 /**Convinient method to get the URL's
282 @return Array of Download URLs
283 */
284 protected String[] getDownloadURL( ActionData data )
285 {
286 Vector records = data.getRecords();
287 AssetRecordData record;
288 int size;
289 size = data.getNumberOfRecords();
290 if( size == 0 )
291 {
292 return new String[0];
293 }
294
295 String url[] = new String[size];
296 String baseURL = data.getString( "baseURL" );
297 String transId = String.valueOf( data.getTransId() );
298
299 for( int i = 0; i < size; i++ )
300 {
301 record = (AssetRecordData)records.elementAt(i);
302 String fName = record.getFileName();
303 int k = fName.lastIndexOf("/") + 1;
304 fName = fName.substring(k);
305 url[i] = StringUtil.encodeURLString(baseURL + "/" + transId + "/" + fName);
306 record.setString( ActionPropertiesI.URL_STRING, url[i] );
307 }
308 return url;
309 }
310
311 /**
312 Method to execute the service as given in the parameter
313 *@param actionData Object containing service details
314 */
315 protected ActionResult executeService(ActionData actionData, String serviceName)
316 {
317 ActionResult result = null;
318 actionData.setTransId(id);
319 sService = serviceName;
320
321 try
322 {
323 actionData.setServiceName(serviceName);
324 result = (ActionResult) serviceBroker.invokeImmediately(actionData);
325 }
326 catch(SrvcNotAvailException rsnae)
327 {
328 new FlexError(FlexError.CRITICAL, sThisService, IDENTIFIER, rsnae);
329 result = new ActionResult(false);
330 }
331 catch (Exception e)
332 {
333 new FlexError(FlexError.CRITICAL, sThisService, IDENTIFIER, e);
334 result = new ActionResult(false);
335 }
336
337 return result;
338 }
339 } // DownloadService