Source code: com/flexstor/flexdbserver/services/asset/ImportCopyService.java
1 /*
2 * ImportCopyService.java
3 *
4 * Copyright $Date: 2003/08/11 02:22:29 $ 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.asset;
12
13 import java.util.Vector;
14
15 import com.flexstor.common.constants.AssetRolesI;
16 import com.flexstor.common.data.ActionData;
17 import com.flexstor.common.data.ActionResult;
18 import com.flexstor.common.data.ejb.disguiserecord.AssetRoleData;
19 import com.flexstor.common.data.ejb.disguiserecord.DisguiseAssetRecordData;
20 import com.flexstor.common.data.ejb.disguiserecord.DisguiseRecordData;
21 import com.flexstor.common.errorlogger.FlexError;
22 import com.flexstor.common.importprocessor.ImportCtlData;
23 import com.flexstor.common.importprocessor.ImportData;
24 import com.flexstor.common.importprocessor.ImportResult;
25 import com.flexstor.common.io.xfile.FlexXFile;
26 import com.flexstor.common.io.xfile.XFileCopy;
27 import com.flexstor.common.resources.Resources;
28 import com.flexstor.common.services.ServiceArgumentsI;
29 import com.flexstor.common.settings.Settings;
30 import com.flexstor.common.util.ServerList;
31 import com.flexstor.flexdbserver.services.Service;
32 import com.flexstor.flexdbserver.services.ServiceContext;
33 import com.flexstor.flexdbserver.util.PathAnalyzer;
34 import com.flexstor.flexdbserver.util.PathBuilder;
35
36 /**
37 * <P>
38 * ImportCopyService <BR>
39 * <BLOCKQUOTE>
40 * Provides functionality to copy files during the import process.
41 * </BLOCKQUOTE>
42 * </P>
43 *
44 * Configurable Properties in roletype_services.config <BR>
45 *
46 * <TABLE BORDER="1" CELLPADDING="3" CELLSPACING="3">
47 * <CAPTION ALIGN=TOP>
48 * <B> In/Out Properties for Assets </B>
49 * </CAPTION>
50 * <TR>
51 * <FONT SIZE=+1><B>
52 * <TH WIDTH="120">Attribute</TH>
53 * <TH WIDTH="30">IN</TH> <TH WIDTH="30">OUT</TH> <TH WIDTH="30">Default IN</TH> <TH WIDTH="30">Default OUT</TH>
54 * </B></FONT>
55 * </TR>
56 * <TR>
57 * <TH ALIGN=LEFT><FONT SIZE=+1><B>ROLE</B></FONT></TH>
58 * <TD ALIGN=CENTER>   </TD> <TD ALIGN=CENTER>   </TD> <TD ALIGN=CENTER> ALL </TD> <TD ALIGN=CENTER> ALL </TD>
59 * </TR>
60 * <TR><TH> Highres </TH> <TD ALIGN=CENTER> X </TD> <TD ALIGN=CENTER> X </TD> <TD ALIGN=CENTER>   </TD> <TD ALIGN=CENTER>   </TD></TR>
61 * <TR><TH> Lowres </TH> <TD ALIGN=CENTER> X </TD> <TD ALIGN=CENTER> X </TD> <TD ALIGN=CENTER>   </TD> <TD ALIGN=CENTER>   </TD></TR>
62 * <TR><TH> Thumbnail </TH> <TD ALIGN=CENTER> X </TD> <TD ALIGN=CENTER> X </TD> <TD ALIGN=CENTER>   </TD> <TD ALIGN=CENTER>   </TD></TR>
63 * <TR><TH> Layout </TH> <TD ALIGN=CENTER> X </TD> <TD ALIGN=CENTER> X </TD> <TD ALIGN=CENTER>   </TD> <TD ALIGN=CENTER>   </TD></TR>
64 * <TR><TH> Video </TH> <TD ALIGN=CENTER> X </TD> <TD ALIGN=CENTER> X </TD> <TD ALIGN=CENTER>   </TD> <TD ALIGN=CENTER>   </TD></TR>
65 * <TR><TH> Audio </TH> <TD ALIGN=CENTER> X </TD> <TD ALIGN=CENTER> X </TD> <TD ALIGN=CENTER>   </TD> <TD ALIGN=CENTER>   </TD></TR>
66 * <TR>
67 * <TH ALIGN=LEFT><FONT SIZE=+1><B>TYPE</B></FONT></TH>
68 * <TD ALIGN=CENTER> X </TD> <TD ALIGN=CENTER> X </TD> <TD ALIGN=CENTER> ALL </TD> <TD ALIGN=CENTER> ALL </TD></TR>
69 * </TR>
70 * <TR>
71 * <TH ALIGN=LEFT><FONT SIZE=+1><B>FLAG</B></FONT></TH>
72 * </TR>
73 * <TR><TH> PARENT </TH> <TD ALIGN=CENTER> X </TD> <TD ALIGN=CENTER> X </TD> <TD ALIGN=CENTER> X </TD> <TD ALIGN=CENTER> X </TD></TR>
74 * <TR><TH> CHLDREN </TH> <TD ALIGN=CENTER> X </TD> <TD ALIGN=CENTER> X </TD> <TD ALIGN=CENTER>   </TD> <TD ALIGN=CENTER>   </TD></TR>
75 * <TR><TH> ALL </TH> <TD ALIGN=CENTER> X </TD> <TD ALIGN=CENTER> X </TD> <TD ALIGN=CENTER>   </TD> <TD ALIGN=CENTER>   </TD></TR>
76 * <TR><TH> TEMP_PARENT </TH> <TD ALIGN=CENTER> X </TD> <TD ALIGN=CENTER> X </TD> <TD ALIGN=CENTER>   </TD> <TD ALIGN=CENTER>   </TD></TR>
77 * <TR><TH> TEMP_CHILDREN </TH> <TD ALIGN=CENTER> X </TD> <TD ALIGN=CENTER> X </TD> <TD ALIGN=CENTER>   </TD> <TD ALIGN=CENTER>   </TD></TR>
78 * <TR><TH> TEMP_ALL </TH> <TD ALIGN=CENTER> X </TD> <TD ALIGN=CENTER> X </TD> <TD ALIGN=CENTER>   </TD> <TD ALIGN=CENTER>   </TD></TR>
79 * </TABLE>
80 *
81 * <P>
82 * copyflat: Indicates if the source file must be copied into the destination location,
83 * duplicating the source path under the destination. For instance, if set to true, then
84 * the file /path/to/file will be copied in /dest/ as /dest/path/to/file; otherwise, it
85 * will be copied as /dest/file (optional; defaults to true). <BR>
86 * Legal values: true or false <BR>
87 * </P>
88 * <P>
89 * destination: Path where files will be copied. If ImportCopyService is specified as a
90 * preservice in the input control (*.ctl) file and this property is not declared, it will default to
91 * either the lowcopybase or highcopybase property (depending on role) in the input control file.
92 * If ImportCopyService is not defined as a preservice, this property must be declared. <BR>
93 * Legal values: Full path <BR>
94 * </BLOCKQUOTE>
95 * </P>
96 *
97 * <P>
98 * Input Data Object <BR>
99 * <BLOCKQUOTE>
100 * com.flexstor.common.importprocessor.ImportData
101 * </BLOCKQUOTE>
102 * </P>
103 *
104 * <P>
105 * Output Data Object <BR>
106 * <BLOCKQUOTE>
107 * com.flexstor.common.importprocessor.ImportResult
108 * </BLOCKQUOTE>
109 * </P>
110 */
111 public class ImportCopyService
112 implements Service
113 {
114 public static final String IDENTIFIER = "$Id: ImportCopyService.java,v 1.4 2003/08/11 02:22:29 aleric Exp $";
115
116 protected ImportData refImportData = null;
117 protected ImportCtlData refCtlData = null;
118
119 protected ServiceContext context;
120 protected int id = -1;
121 protected String fileSeparator;
122 private String sThisService = "";
123 private String sServer = null;
124 private boolean bFromPreservice = false;
125 private boolean bInputOutputSame = false; // If the Input and Output Assets are the same,
126 // (role, type, flag out == role, type, flag in)
127 // we do thing differently in storeNewLocation()
128 // method.
129
130 /**
131 * Calls before the service is initialized (before initData is called) to
132 * pass information about the environment in which the service is running.
133 * This environment consists of information about the properties set for the
134 * service in one of these files (services.config, roletype_services.config,
135 * or *.ctl), plus methods to access other information such as an instance
136 * of the service broker to invoke other services, the transaction id for
137 * the service, file separator character and local path for the installation
138 * directory and configuration directory.
139 *
140 * @param context Holds information about the environment in which the service
141 * is running.
142 */
143 public void setServiceContext( ServiceContext context )
144 {
145 this.context = context;
146 id = context.getTransactionId();
147 fileSeparator = context.getFileSeparator();
148 }
149
150 /**
151 * A data initialization method called at the beginning of the service.
152 * The input argument, ActionData must be cast into its subclass, ImportData
153 * in order to extract the CopyService specific data from it.
154 */
155 public void initData(ActionData actionData)
156 {
157 //5526=Import Copy Service
158 sThisService = Resources.get(5526) + " (" + id + ")";
159
160 refImportData = (ImportData) actionData;
161
162 // Get the ctl data object
163 refCtlData = refImportData.getCtlDataRef();
164 // Get the FlexDBServer host
165 sServer = Settings.getString( Settings.APP_SERVER_HOST );
166 // Determine if this service was called from a list of preservices
167 String sProcess = context.getProperty( ServiceArgumentsI.PROCESS );
168 if ( sProcess.equals( "Import " + AssetServiceManager.PRESERVICES ) )
169 bFromPreservice = true;
170 }
171
172 /**
173 * The start of the Copy Service.
174 */
175 public ActionResult go()
176 {
177 ImportResult result = new ImportResult(true);
178
179 if (refImportData != null)
180 {
181 //get ROLE values
182 String role_in = context.getProperty(ServiceArgumentsI.ROLE_DATA_SOURCE);
183 String role_out = context.getProperty(ServiceArgumentsI.ROLE_DATA_DESTINATION);
184
185 // get the TYPE values
186 String type_in = context.getProperty(ServiceArgumentsI.TYPE_DATA_SOURCE);
187 String type_out = context.getProperty(ServiceArgumentsI.TYPE_DATA_DESTINATION);
188
189 //get FLAG values
190 String flag_in = context.getProperty(ServiceArgumentsI.FLAG_DATA_SOURCE);
191 String flag_out = context.getProperty(ServiceArgumentsI.FLAG_DATA_DESTINATION);
192
193 System.out.println( "arguments: " + role_in + ", " + role_out + ", " + type_in + ", " + type_out + ", " + flag_in + ", " + flag_out );
194
195 //downcast to a ImportData object and get the DisguiseRecord
196 DisguiseRecordData disguiseData = refImportData.getDisguiseRecordRef();
197
198 // get the list of in and out assets and set the full_text_path field
199 Vector vInAssets = disguiseData.getAssets( role_in, type_in, flag_in );
200 // If the input assets are the same as the output assets, don't call the disguiseData.getAssets()
201 // method; just copy the Vector
202 Vector vOutAssets;
203 if ( role_out.equals(role_in) && type_out.equals(type_in) && flag_out.equals(flag_in) )
204 {
205 bInputOutputSame = true;
206 vOutAssets = vInAssets;
207 }
208 else
209 vOutAssets = disguiseData.getAssets( role_out, type_out, flag_out );
210
211 if ( vInAssets != null && vInAssets.size() > 0 )
212 {
213 DisguiseAssetRecordData assetIn, assetOut;
214 XFileCopy copyRef = new XFileCopy();
215 String sFileName, sInputPath, sOutputPath;
216
217 for ( int i = 0; i < vInAssets.size(); i++ )
218 {
219 assetIn = (DisguiseAssetRecordData) vInAssets.elementAt(i);
220 try
221 {
222 assetOut = (DisguiseAssetRecordData) vOutAssets.elementAt(i);
223 }
224 catch ( ArrayIndexOutOfBoundsException aioobe )
225 {
226 System.out.println( "Creating new assetOut" );
227 // If role and type are default, use the ones in the assetIn
228 int nRoleOutId = -1;
229 if ( role_out.equals( ServiceArgumentsI.DEFAULT_ROLE ) )
230 nRoleOutId = assetIn.getAssetRoleId();
231 else
232 nRoleOutId = getRoleId( role_out );
233 if ( type_out.equals( ServiceArgumentsI.DEFAULT_TYPE ) )
234 type_out = assetIn.getAssetFileType();
235
236 assetOut = new DisguiseAssetRecordData();
237 AssetRoleData role = new AssetRoleData();
238 role.setAssetRoleId( nRoleOutId );
239 role.setAssetFileType( type_out );
240 if ( flag_out.equals( "TEMP" ) )
241 role.setTempRole( true );
242 assetOut.setAssetRole( role );
243 assetIn.addChildAsset( assetOut );
244 }
245
246 sFileName = assetIn.getFileName();
247 sInputPath = PathBuilder.constructFilePath( assetIn.getServer(), assetIn.getLocation(), sFileName );
248 sOutputPath = createOutputPath( sInputPath, assetIn.getAssetRoleId() );
249 if ( sOutputPath != null )
250 {
251 if ( copyRef.copy( sInputPath, sOutputPath + sFileName ) )
252 storeNewLocation( sOutputPath, assetOut, assetIn );
253 else
254 disguiseData.deleteAsset( assetIn );
255 }
256 else
257 {
258 // This else could be reached only in the first iteration of the for loop,
259 // after that it will never get here because the base destination was found
260 // in createOutputPath().
261 //6518=Destination directory not specified. Cannot proceed.
262 refImportData.addErrorRecord( new FlexError(FlexError.CRITICAL, sThisService, IDENTIFIER, 6518 ) );
263 result.setSuccess(false);
264 break;
265 }
266 }
267 // If this is a preservice, in ImportCtlData replace the HIGHFILELISTBASE with
268 // the HIGHCOPYBASE so in next services we use it as the base path ( specially for alchemy )
269 if ( bFromPreservice )
270 {
271 refCtlData.removeItem( "HIGHFILELISTBASE", refCtlData.getValuePerKey("HIGHFILELISTBASE") );
272 refCtlData.addValuePerKey( "HIGHFILELISTBASE" , refCtlData.getValuePerKey("HIGHCOPYBASE") );
273 }
274 }
275 else
276 {
277 //6290=Could not find assets of the following role, type and flag: %%1 %%2 %%3
278 refImportData.addErrorRecord( new FlexError(FlexError.CRITICAL, sThisService, IDENTIFIER, 6290, new String[] { role_in, type_in, flag_in } ) );
279 result.setSuccess(false);
280 }
281 }
282 else
283 {
284 //6291=Cannot operate on an empty data object
285 refImportData.addErrorRecord( new FlexError(FlexError.CRITICAL, sThisService, IDENTIFIER, 6291 ) );
286 result.setSuccess(false);
287 }
288 result.setImportData(refImportData);
289 return result;
290 } // go()
291
292 private String createOutputPath( String sInputPath, int nRoleId )
293 {
294 boolean bCopyFlat = true;
295 String sCopyFlat = (String) context.getProperty("copyflat");
296 if ( sCopyFlat != null )
297 bCopyFlat = (Boolean.valueOf(sCopyFlat)).booleanValue();
298
299 // Try to get the destination set in the service properties (configuration files)
300 String sBaseDestination = context.getProperty("destination");
301 if ( sBaseDestination != null && sBaseDestination.equals("") == false )
302 {
303 // Don't add the test for bCopyFlat in the above if statement!!!
304 // If !bCopyFlat it would be wrong to go to the next else if...
305 if ( bCopyFlat )
306 {
307 if ( PathAnalyzer.getRemoteFileProtocol(sBaseDestination) == null )
308 sBaseDestination = PathBuilder.constructPath( sServer, sBaseDestination, true );
309 return sBaseDestination;
310 }
311 }
312 else if ( bFromPreservice ) // If from preservice and not destination set, use the copy base properties
313 {
314 if ( nRoleId == AssetRolesI.LOWRES )
315 sBaseDestination = refCtlData.getValuePerKey("LOWCOPYBASE");
316 else
317 sBaseDestination = refCtlData.getValuePerKey("HIGHCOPYBASE");
318 }
319
320 // Lets check once more if sBaseDestination is null; if it is then exit
321 if ( sBaseDestination != null && sBaseDestination.equals("") == false )
322 {
323 if ( PathAnalyzer.getRemoteFileProtocol(sBaseDestination) == null )
324 sBaseDestination = PathBuilder.constructPath( sServer, sBaseDestination, true );
325 }
326 else
327 return null;
328
329 String sBaseOriginal;
330 if ( nRoleId == AssetRolesI.LOWRES )
331 sBaseOriginal = refCtlData.getValuePerKey("LOWFILELISTBASE");
332 else
333 sBaseOriginal = refCtlData.getValuePerKey("HIGHFILELISTBASE");
334
335 if ( PathAnalyzer.getRemoteFileProtocol(sBaseOriginal) == null )
336 sBaseOriginal = PathBuilder.constructPath( sServer, sBaseOriginal, true );
337
338 System.out.println("BaseDestination is: " + sBaseDestination);
339 System.out.println("Copying flat: " + bCopyFlat );
340 return buildCompositeDir( sInputPath, sBaseDestination, sBaseOriginal );
341 }
342
343 /**
344 * Build up the directory from the element & root paths specified.
345 * @param sLocation The element path.
346 * @param sRootPath The root path.
347 */
348 protected String buildCompositeDir(String sLocation, String sRootPath, String sListBasePath)
349 {
350 String sOutputPath = sRootPath;
351
352 // Find the base path in the user specified input file path
353 if (sLocation.startsWith(sListBasePath))
354 sOutputPath += sLocation.substring( sListBasePath.length() );
355 else
356 sOutputPath += sLocation;
357
358 return sOutputPath;
359 } // buildCompositeDir
360
361 private int getRoleId( String sRole )
362 {
363 // Get the proper Role Id
364 if ( sRole.equalsIgnoreCase("LOWRES") )
365 return AssetRolesI.LOWRES;
366 else if ( sRole.equalsIgnoreCase("THUMBNAIL") )
367 return AssetRolesI.THUMBNAIL;
368 else if ( sRole.equalsIgnoreCase("LAYOUT") )
369 return AssetRolesI.LAYOUT;
370 else if ( sRole.equalsIgnoreCase("AUDIO") )
371 return AssetRolesI.AUDIO;
372 else if ( sRole.equalsIgnoreCase("VIDEO") )
373 return AssetRolesI.VIDEO;
374 else if ( sRole.equalsIgnoreCase("ALL") )
375 return -1;
376 else
377 return AssetRolesI.HIGHRES; // HIGHRES is the default
378 }
379
380 private void storeNewLocation( String sOutputPath, DisguiseAssetRecordData assetOut, DisguiseAssetRecordData assetIn )
381 {
382 // This method will store the new location (the destination) as the new location of
383 // the asset only if the service was run as a pre-service (which indicates that we
384 // want the copy of the asset to be managed in FLEXSTOR.db). Then the old location
385 // will be set in the copy_source values for later update of the ASSETS_COPY_SOURCE
386 // in the DBUpdate Service.
387 // If the service was not run as a pre-service and the Output Asset is the same as the
388 // Input Asset, we don't want to rename it; doing so will result in FLEXSTOR.db managing
389 // the copy of the asset instead of the original.
390 if ( bFromPreservice )
391 {
392 System.out.println( "Setting copy source values..." );
393 assetOut.setCopySource( true );
394 assetOut.setCopySourceServer( assetOut.getServer() );
395 assetOut.setCopySourceLocation( assetOut.getLocation() );
396 assetOut.setCopySourceFileName( assetOut.getFileName() );
397 }
398
399 if ( bFromPreservice || !bInputOutputSame )
400 {
401 if ( sOutputPath.startsWith( "nfs" ) )
402 {
403 FlexXFile xOutputPath = new FlexXFile( sOutputPath );
404 assetOut.setServer( ServerList.getServerName( xOutputPath.getServer() ) );
405 assetOut.setLocation( xOutputPath.getLocalPath() + fileSeparator );
406 assetOut.setFileName( assetIn.getFileName() );
407 }
408 else
409 {
410 assetOut.setServer( assetIn.getServer() );
411 assetOut.setLocation( sOutputPath );
412 assetOut.setFileName( assetIn.getFileName() );
413 }
414 }
415 }
416 }