Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: com/flexstor/flexdbserver/services/checkincheckout/CheckInServiceManager.java


1   /*
2    * CheckInServiceManager.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.checkincheckout;
12  
13  import java.util.Date;
14  import java.util.Enumeration;
15  import java.util.Iterator;
16  import java.util.Vector;
17  
18  import com.flexstor.common.constants.ActionPropertiesI;
19  import com.flexstor.common.constants.AssetRolesI;
20  import com.flexstor.common.constants.RsrcForkConstantsI;
21  import com.flexstor.common.constants.ServicesI;
22  import com.flexstor.common.data.ActionData;
23  import com.flexstor.common.data.ActionResult;
24  import com.flexstor.common.data.AssetRecordData;
25  import com.flexstor.common.errorlogger.FlexError;
26  import com.flexstor.common.gateway.CheckOutCheckInGateway;
27  import com.flexstor.common.gateway.exceptions.TransactionFailedException;
28  import com.flexstor.common.io.xfile.FlexXFile;
29  import com.flexstor.common.io.xfile.XFileCopy;
30  import com.flexstor.common.resources.Resources;
31  import com.flexstor.common.services.SrvcNotAvailException;
32  import com.flexstor.common.settings.Settings;
33  import com.flexstor.common.threadmgr.ThreadCallbackI;
34  import com.flexstor.common.util.Diagnostic;
35  import com.flexstor.common.util.FlexDbServerHost;
36  import com.flexstor.common.util.ServerList;
37  import com.flexstor.flexdbserver.services.ServiceManager;
38  import com.flexstor.flexdbserver.services.lowres.LowresConstants;
39  import com.flexstor.flexdbserver.util.PathAnalyzer;
40  import com.flexstor.flexdbserver.util.PathBuilder;
41  
42  /**
43   * CheckInServiceManager provides functionality to control the
44   * sequencial execution of Services during the check-in process
45   */
46  public class CheckInServiceManager
47     extends ServiceManager
48     implements AssetRolesI
49  {
50     // To get the version number from MKS
51     public final static String IDENTIFIER="$Id: CheckInServiceManager.java,v 1.3 2003/08/11 02:22:49 aleric Exp $";
52  
53     /** Record States */
54     private static final int NOT_PROCESSED          = 0;
55     private static final int ORIGINAL_MOVED         = 1;
56     private static final int NEW_VERSION_COPIED     = 2;
57     private static final int LOWRES_UPDATED         = 3;
58     private static final int DEFAULTVIEW_COPIED     = 4;
59     /** Global States */
60     private static final int ASSETS_CHECKED_IN      = 5;
61     private static final int ASSETINFO_REGENERATED  = 6;
62     private static final int DATABASE_UPDATED       = 7;
63     private static final int FILES_ROLLED_BACK      = 8;
64     private static final int TEMPDIR_CLEANED        = 9;
65  
66     protected   String                     sServerName       = "";
67     protected   ActionData               data              = null;
68     protected   Vector                     vRecords          = null;  //records to be processed
69     protected   Vector                     vGoodRecords      = null;  //records successfully processed
70     protected   Vector                     vBadRecords       = null;  //records unsuccessfully processed
71     protected   Vector                     vBadStates        = null;  //state for records unsuccessfully processed
72     protected   boolean                    bContinue         = true;
73     protected   boolean                    bInterrupted      = false;
74     protected   int                        nGlobalState      = NOT_PROCESSED;
75     protected   String                     fileSeparator     = "";
76     protected   String                     sTempDir          = "";
77     protected   CheckOutCheckInGateway   checkInGateway    = null;
78  
79     public CheckInServiceManager( String sIdentifier, ActionData data, ThreadCallbackI caller )
80     {
81        super( data, caller );
82        this.sServerName = sIdentifier;
83        this.data = data;
84  
85        // Get the system dependent file separator
86        fileSeparator = java.io.File.separator;
87  
88        // Create the temp dir
89        sTempDir = Settings.getString( Settings.APP_SERVER_TMP_DIR );
90        if ( ! sTempDir.endsWith(fileSeparator) )
91           sTempDir += fileSeparator;
92  
93        sTempDir += data.getTransId() + fileSeparator;
94     }
95  
96     /**
97      * Main loop for sequencial execution of Services.
98      */
99     public ActionResult execute()
100       throws InterruptedException
101    {
102       vGoodRecords = new Vector();
103       vBadRecords = new Vector();
104       vBadStates = new Vector();
105       AssetRecordData record = null;
106       int nRecordState = NOT_PROCESSED;
107       vRecords = (Vector)(data.getRecords()).clone(); // clone, so we leave the original vector intact.
108       try
109       {
110          // Initialize the checkInGateway
111          checkInGateway = new CheckOutCheckInGateway();
112          checkInGateway.connect();
113 
114          if ( setStatusToInProgress() )
115          {
116             // Do a shallow copy of the vRecords vector so we can remove elements from it
117             // safely during the for loop
118             Vector vRecordsClone = (Vector) vRecords.clone();
119             try
120             {
121                for ( Enumeration e = vRecordsClone.elements(); e.hasMoreElements(); )
122                {
123                   record = (AssetRecordData) e.nextElement();
124                   nRecordState = NOT_PROCESSED;
125                   bContinue = true;
126 
127                   if ( !isInterrupted() )
128                      moveOriginalToVersionsDir( record );
129 
130                   if ( bContinue && !isInterrupted() )
131                   {
132                      nRecordState = ORIGINAL_MOVED;
133                      copyNewVersionIntoOriginal( record );
134                   }
135 
136                   if ( bContinue && !isInterrupted() )
137                   {
138                      nRecordState = NEW_VERSION_COPIED;
139                      updateLowres( record );
140                   }
141 
142                   if ( bContinue && !isInterrupted() )
143                   {
144                      nRecordState = LOWRES_UPDATED;
145                      // While copying the default view (thumbnail) around
146                      // we should still continue with the check in process
147                      // even if the thumbnail process has problems
148                      copyDefaultViewToVersionDir( record );
149                   }
150 
151                   if ( bContinue )
152                      nRecordState = DEFAULTVIEW_COPIED;
153 
154                   if ( bContinue && !isInterrupted() )
155                      vGoodRecords.addElement( record );
156                   else
157                   {
158                      vBadRecords.addElement( record );
159                      vBadStates.addElement( new Integer(nRecordState) );
160                   }
161                   vRecords.removeElement( record );
162                }
163             }
164             catch ( Exception e )
165             {
166                // If any exception is thrown there, we add the current record to the
167                // list of bad ones so we can safely roll it back
168                if ( record != null )
169                {
170                   vBadRecords.addElement( record );
171                   vBadStates.addElement( new Integer(nRecordState) );
172                   vRecords.removeElement( record );
173                }
174             }
175 
176             // If this thread is interrupted, rollback the good records to their original position;
177             // also mark the not-yet-processed record to be rollbacked in the database
178             if ( isInterrupted() )
179             {
180                if ( vGoodRecords.size() > 0 )
181                {
182                   for ( int i = 0; i < vGoodRecords.size(); i++ )
183                   {
184                      vBadRecords.addElement( (AssetRecordData)vGoodRecords.elementAt(i) );
185                      vBadStates.addElement( new Integer(DEFAULTVIEW_COPIED) );
186                   }
187                   vGoodRecords.clear();
188                }
189                if ( vRecords.size() > 0 )
190                {
191                   for ( int i = 0; i < vRecords.size(); i++ )
192                   {
193                      vBadRecords.addElement( (AssetRecordData)vRecords.elementAt(i) );
194                      vBadStates.addElement( new Integer(NOT_PROCESSED) );
195                   }
196                   vRecords.clear();
197                }
198             }
199 
200             if ( vGoodRecords.size() > 0 )
201             {
202                // Before regenerating the assets (if required) lets call the bean so we insert
203                // a new row into the roles tables for the new version assets with the information
204                // for the current assets.
205                checkInAssets( vGoodRecords );
206                nGlobalState = ASSETS_CHECKED_IN;
207 
208                regenerateAssetsInfo( vGoodRecords );
209                if ( !bContinue )
210                {
211                   // If fail, set all records to bad and clear the vRecords vector
212                   for ( int i = 0; i < vGoodRecords.size(); i++ )
213                   {
214                      vBadRecords.addElement( (AssetRecordData) vGoodRecords.elementAt(i) );
215                      vBadStates.addElement( new Integer(ASSETS_CHECKED_IN) );
216                   }
217                   vGoodRecords.removeAllElements();
218                }
219                nGlobalState = ASSETINFO_REGENERATED;
220             }
221          }
222          else // of if ( setStatusToInProgress() )
223          {
224             // If fail, set all records to bad and clear the vRecords vector
225             for ( int i = 0; i < vRecords.size(); i++ )
226             {
227                vBadRecords.addElement( (AssetRecordData) vRecords.elementAt(i) );
228                vBadStates.addElement( new Integer(NOT_PROCESSED) );
229             }
230          }
231 
232          updateDatabase( vGoodRecords, vBadRecords );
233          // Next global state means that we already attempt to update the database,
234          // regardless of the status of the update.
235          nGlobalState = DATABASE_UPDATED;
236       }
237       catch ( TransactionFailedException e ) 
238       {
239          // Set all records in vRecords to bad, if any
240          // Since these records haven't been processed yet, set the state to NOT_PROCESSED
241          for ( int i = 0; i < vRecords.size(); i++ )
242          {
243             vBadRecords.addElement( (AssetRecordData) vRecords.elementAt(i) );
244             vBadStates.addElement( new Integer(NOT_PROCESSED) );
245          }
246          // Set all records in vGoodRecords to bad, if any
247          // Since these records have been fully processed, set the state to DEFAULTVIEW_COPIED
248          // or to ASSETS_CHECKED_IN (in case their version was already created in the database)
249          for ( int i = 0; i < vGoodRecords.size(); i++ )
250          {
251             vBadRecords.addElement( (AssetRecordData) vGoodRecords.elementAt(i) );
252             if ( nGlobalState < ASSETS_CHECKED_IN )
253                vBadStates.addElement( new Integer(DEFAULTVIEW_COPIED) );
254             else
255                vBadStates.addElement( new Integer(ASSETS_CHECKED_IN) );
256          }
257          // 7046=Unable to change database status for this transaction.
258          new FlexError( FlexError.CRITICAL, Resources.get(6232) + " (" + data.getTransId() + ")", IDENTIFIER, 7046 );
259       }
260       finally
261       {
262          // Dispose the checkInGateway
263          checkInGateway.dispose();
264       }
265       
266       // Roll back (in file system) those files that failed to process
267       rollBackFiles( vBadRecords, vBadStates );
268       nGlobalState = FILES_ROLLED_BACK;
269       
270       cleanUpTempDir();
271       nGlobalState = TEMPDIR_CLEANED;
272 
273       // After rolling back and cleanup, if this thread was interrupted, rethrow the exception
274       if ( isInterrupted() )
275          throw new InterruptedException();
276       
277       ActionResult actionResult;
278       if ( vBadRecords.size() > 0 )
279       {
280          actionResult = new ActionResult(false);
281          actionResult.setBadRecords( vBadRecords );
282       }
283       else
284          actionResult = new ActionResult(true);
285       
286       data.setRecords( vGoodRecords );
287       actionResult.setId( data.getTransId() );
288       actionResult.setData( data );
289       return actionResult;
290    }
291 
292    /**
293    * Check if another thread request this thread to be interrupted.
294    */
295    private boolean isInterrupted()
296    {
297       if ( !bInterrupted && abortManager() )
298       {
299          bInterrupted = true;
300          bContinue = false;
301       }
302       return bInterrupted;
303    }
304    
305    protected ActionResult getResultObjectOnAbnormalEnding()
306    {
307       if ( nGlobalState < TEMPDIR_CLEANED )
308       {
309          // Cleanup the temp directory
310          cleanUpTempDir();
311 
312          if ( nGlobalState < FILES_ROLLED_BACK )
313          {
314             // Roll back in file system the records in vBadRecords
315             rollBackFiles( vBadRecords, vBadStates );
316          
317             //If failed abnormally and database has not been updated, lets try to update;
318             // records in vGoodRecords should be updated to check-in, records in vBadRecords
319             // and records in vRecords (not processed yet) should be update to check-out.
320             if ( nGlobalState < DATABASE_UPDATED )
321             {
322                if ( vRecords.size() > 0 )
323                {
324                   for ( int i = 0; i < vRecords.size(); i++ )
325                   {
326                      vBadRecords.addElement( (AssetRecordData) vRecords.elementAt(i) );
327                      if ( nGlobalState < ASSETS_CHECKED_IN )
328                         vBadStates.addElement( new Integer(DEFAULTVIEW_COPIED) );
329                      else
330                         vBadStates.addElement( new Integer(ASSETS_CHECKED_IN) );
331                   }
332                }
333                try
334                {
335                   checkInGateway.connect();
336                   updateDatabase( vGoodRecords, vBadRecords );
337                }
338                catch ( TransactionFailedException rtfe )
339                {
340                   // Roll back all good files; lets set the state for all records
341                   Vector vStates = new Vector( vGoodRecords.size() );
342                   for ( int i = 0; i < vGoodRecords.size(); i++ )
343                      vStates.addElement( new Integer(ASSETS_CHECKED_IN) );
344                   rollBackFiles( vGoodRecords, vStates );
345                }
346                finally
347                {
348                   // Dispose the checkInGateway
349                   checkInGateway.dispose();
350                }
351             }
352          }
353       }
354       ActionResult actionResult = null;
355       if ( vBadRecords.size() > 0 )
356       {
357          actionResult = new ActionResult(false);
358          actionResult.setBadRecords( vBadRecords );
359       }
360       else
361          actionResult = new ActionResult(true);
362       
363       actionResult.setId( data.getTransId() );
364       return actionResult;
365    }
366 
367    /**
368     * Set the status in the database to in-progress
369     */
370    private boolean setStatusToInProgress()
371       throws TransactionFailedException
372    {
373       long[] laBadAssets = checkInGateway.updateToInProcessCheckIn( data );
374       if ( laBadAssets == null )
375          return false;
376 
377       if ( laBadAssets.length > 0 )
378       {
379          // if all records failed, return false
380          if ( laBadAssets.length == vRecords.size() )
381             return false;
382          else
383          {
384             // remove the records that could not be updated
385             AssetRecordData record;
386             for ( int i = 0; i < laBadAssets.length; i++ )
387             {
388                for ( Iterator it = vRecords.iterator(); it.hasNext(); )
389                {
390                   record = (AssetRecordData) it.next();
391                   if ( record.getRecordId() == laBadAssets[i] )
392                   {
393                      vBadRecords.addElement( record );
394                      it.remove();
395                   }
396                }
397             }
398          }
399       }
400       return true;
401    }
402 
403    private void moveOriginalToVersionsDir( AssetRecordData record )
404    {
405       // Set the tempData object used all along this service
406       ActionData tempData = (ActionData)data.clone();
407       tempData.setRecords( null ); // reset records
408       AssetRecordData tempRecord = (AssetRecordData)record.clone();
409       String sNewLocation = tempRecord.getLocation() + ".versions" + fileSeparator + tempRecord.getString( ActionPropertiesI.VERSION_NUMBER_PREVIOUS ) + fileSeparator;
410       tempRecord.setString( ActionPropertiesI.DESTINATION_SERVER, tempRecord.getServer() );
411       tempRecord.setString( ActionPropertiesI.DESTINATION_LOCATION, sNewLocation );
412       // set Keep Resource fork to true so version file maintains its resource fork
413       tempRecord.setBoolean( ActionPropertiesI.KEEP_RESOURCEFORK, new Boolean(true) );
414       // set is MacBinary to false
415       tempRecord.setBoolean( ActionPropertiesI.MACBINARY_FORMAT, new Boolean(false) );
416 
417       tempData.addRecord( tempRecord );
418       executeService( ServicesI.MOVE_SERVICE, tempData );
419 
420       // Set the version server, location and filename
421       record.setString( ActionPropertiesI.VERSION_SERVER, record.getServer() );
422       record.setString( ActionPropertiesI.VERSION_LOCATION, sNewLocation );
423       record.setString( ActionPropertiesI.VERSION_FILENAME, record.getFileName() );
424       record.setLong( ActionPropertiesI.VERSION_FILESIZE, record.getFileSize() );
425    }
426 
427    private void copyNewVersionIntoOriginal( AssetRecordData record )
428    {
429       // Set the tempData object used all along this service
430       ActionData tempData = (ActionData)data.clone();
431       AssetRecordData tempRecord = (AssetRecordData)record.clone();
432 
433       int nAppleTalkVendor = RsrcForkConstantsI.NONE;
434       boolean bIsMacBinary = false;
435       try
436       {
437          nAppleTalkVendor = record.getAppleTalkVendor().intValue();
438          bIsMacBinary = record.isMacBinaryFormat().booleanValue();
439       }
440       catch( NullPointerException npe ) {}
441       
442       String sSourceLocation = record.getString( ActionPropertiesI.SOURCE_LOCATION );
443       if ( sSourceLocation != null && PathAnalyzer.getRemoteFileProtocol(sSourceLocation) != null )
444       {
445          record.setString( ActionPropertiesI.SOURCE_SERVER, PathAnalyzer.getServerName(sSourceLocation) );
446          sSourceLocation = PathAnalyzer.getLocalPath(sSourceLocation);
447          record.setString( ActionPropertiesI.SOURCE_LOCATION, sSourceLocation );
448       }
449 
450       // Get the source location and set this as the input path for the next service
451       String sPath = PathBuilder.constructFilePath( record.getString( ActionPropertiesI.SOURCE_SERVER ), 
452                                                       sSourceLocation, 
453                                                       record.getString( ActionPropertiesI.SOURCE_FILENAME ) );
454 
455       // Determine if the new file is in a server other than the FlexDBServer. If so and ONLY if bIsMacBinary == true,
456       // we will need to copy the file to the temp location of the FlexDBServer and from there split the MacBinary
457       // check if sServer is the same as this server
458       if ( !FlexDbServerHost.isLocalHost( PathAnalyzer.getServerDNS(sPath) ) && bIsMacBinary )
459       {
460          if ( !(new XFileCopy()).copy( sPath, sTempDir + PathAnalyzer.getFileName(sPath) ) )
461          {
462             // 7048=Unable to transfer file from %%1 to FlexDBServer. Check-out failed.
463             new FlexError( FlexError.CRITICAL, Resources.get(6232) + " (" + data.getTransId() + ")", IDENTIFIER, 7048, new String[] { PathAnalyzer.getServerDNS(sPath) } );
464             bContinue = false;
465             return;
466          }
467          else
468          {
469             // Set the new source location to be the temp directory; also set bIsLocationInServer to false
470             // to cleanup temp directory at the end
471             record.setString( ActionPropertiesI.SOURCE_SERVER, FlexDbServerHost.getLocalHostName() );
472             record.setString( ActionPropertiesI.SOURCE_LOCATION, sTempDir );
473             record.setString( ActionPropertiesI.SOURCE_FILENAME, PathAnalyzer.getFileName(sPath) );
474             record.setBoolean( ActionPropertiesI.IS_LOCATION_IN_SERVER, new Boolean(false) );
475             // Update sPath with the new file path
476             sPath = PathBuilder.constructFilePath( record.getString( ActionPropertiesI.SOURCE_SERVER ),
477                                                      record.getString( ActionPropertiesI.SOURCE_LOCATION ),
478                                                      record.getString( ActionPropertiesI.SOURCE_FILENAME ) );
479          }
480       }
481 
482       FlexXFile source = new FlexXFile( sPath );
483 
484       // Get the asset location and format it according to the standard in Flexstor; that is:
485       // No leading slash, but trailing slash
486       String sLocation = PathAnalyzer.getLocalParent( sPath );
487       sLocation = PathBuilder.addFileSeparators( sLocation, false, true );
488       sLocation = PathBuilder.removeFileSeparators( sLocation, true, false );
489 
490       tempRecord.setServer( PathAnalyzer.getServerName( sPath ) );
491       tempRecord.setLocation( sLocation );
492       tempRecord.setFileName( PathAnalyzer.getFileName( sPath ) );
493       record.setLong( ActionPropertiesI.SOURCE_FILESIZE, new Long(source.length()) );
494       tempRecord.setFileSize( record.getLong( ActionPropertiesI.SOURCE_FILESIZE ) );
495 
496       // Now we need to check if this file is a MacBinary or not. If it is then we copy the file
497       // by doing a separteFork; if it is not then we proceed as normal
498       if ( bContinue )
499       {
500          if ( nAppleTalkVendor > RsrcForkConstantsI.NONE && bIsMacBinary )
501          {
502             tempData.setRecords( null ); // reset records
503             tempRecord.setDestinationLocation( PathBuilder.constructPath( record.getServer(), record.getLocation(), true ) );
504             tempData.addRecord( tempRecord );
505             tempData.setInteger( ActionData.RESOURCEFORK_ACTION, new Integer(RsrcForkConstantsI.SEPARATE_FORKS) );
506             executeService( ServicesI.RESOURCEFORK_SERVICE, tempData );
507          }
508          else
509          {
510             tempData.setRecords( null ); // reset records
511             // The destination location will be the original location of the file.
512             tempRecord.setDestinationLocation( PathBuilder.constructPath( record.getServer(), record.getLocation(), true ) );
513             tempRecord.setDestinationFileName( record.getFileName() );
514             tempData.addRecord( tempRecord );
515 
516             executeService( ServicesI.COPY_SERVICE, tempData );
517          }
518          // After this is done we should change the file size of the original record for
519          // the one of the newly created file.
520          record.setFileSize( record.getLong( ActionPropertiesI.SOURCE_FILESIZE ) );
521 
522          // Also get the modification date of the file. Use the file in the temp location.
523          record.setString( ActionPropertiesI.MODIFICATION_DATE, (new Date(source.lastModified())).toString() );
524       }
525    }
526 
527    /**
528     * This method regenerates the lowres file for a highres.
529     * For this, we first query the database to find out if this asset has a lowres child;
530     * if it does, then we call the LowresService to recreate the lowres asset.
531     * NOTE: The service takes as input the highres asset, not the lowres child.
532     */
533    private void updateLowres( AssetRecordData record )
534       throws TransactionFailedException
535    {
536       // Call the bean and find out if there are children to add.
537       ActionData childActionData = checkInGateway.getChildrenByAssetRole( LOWRES, record );
538       Vector vChildRecords = childActionData.getRecords();
539       if ( vChildRecords != null && vChildRecords.size() > 0 )
540       {
541          // There should be only one lowres for this asset; so there should be a single item in the Vector
542          AssetRecordData childRecord = (AssetRecordData)vChildRecords.elementAt(0);
543 
544          // Set the tempData object and add the highres asset to it
545          ActionData tempData = (ActionData)data.clone();
546          tempData.addRecord( record );
547 
548          // Add the child to the AssetRecordData
549          record.addChildRecord( childRecord );
550 
551          // VersionNo needs to be set always, even if we won't keep the lowres version
552          childRecord.setString( ActionPropertiesI.VERSION_NUMBER, record.getString( ActionPropertiesI.VERSION_NUMBER ) );
553 
554          // Now lets find out if we need to keep the lowres for the version asset
555          boolean bKeepLowres = false;
556          try { bKeepLowres = record.getBoolean( ActionPropertiesI.KEEP_LOWRES ).booleanValue(); }
557          catch ( NullPointerException npe ) {}
558          if ( bKeepLowres )
559          {
560             // Set the VersionXXXXX and other info needed in the bean
561             childRecord.setString( ActionPropertiesI.VERSION_SERVER, childRecord.getServer() );
562             childRecord.setString( ActionPropertiesI.VERSION_FILENAME, childRecord.getFileName() );
563             childRecord.setLong( ActionPropertiesI.VERSION_FILESIZE, childRecord.getFileSize() );
564             childRecord.setString( ActionPropertiesI.CHECKIN_DATETIME, record.getString( ActionPropertiesI.CHECKIN_DATETIME ) );
565 
566             String sLocation = childRecord.getLocation();
567             String sNewLocation = sLocation + ".versions" + fileSeparator + record.getString( ActionPropertiesI.VERSION_NUMBER_PREVIOUS )
568                                   + fileSeparator;
569             childRecord.setString( ActionPropertiesI.VERSION_LOCATION, sNewLocation );
570 
571             // Create a new record pointing to the highres in .versions in order to create its lowres
572             AssetRecordData versionRecord = (AssetRecordData)record.clone();
573             versionRecord.setLocation( record.getString( ActionPropertiesI.VERSION_LOCATION ) );
574             tempData.addRecord( versionRecord );
575          }
576 
577          if ( tempData.getRecords() != null && tempData.getRecords().size() > 0 )
578          {
579             tempData.setInteger( "lowres_action", new Integer( LowresConstants.CREATE_LOWRES ) );
580             executeService( ServicesI.LOWRES_SERVICE, tempData );
581          }
582       }
583    }
584 
585    private void copyDefaultViewToVersionDir( AssetRecordData record )
586       throws TransactionFailedException
587    {
588       // Call the bean and find out if there are children to add.
589       AssetRecordData childRecord = (AssetRecordData)checkInGateway.getDefaultViewAsset( record );
590 
591       if ( childRecord != null )
592       {
593          // Set the tempData object used all along this service
594          ActionData tempData = (ActionData)data.clone();
595 
596          // Add the child to the AssetRecordData
597          record.addChildRecord( childRecord );
598          record.setDefaultViewAssetId( new Long(childRecord.getAssetId()) );
599 
600          String sLocation = childRecord.getLocation();
601          String sNewLocation = null;
602          // If location contains the string "defaultthumbnail" do not copy but create
603          // new asset pointing to the same defaultthumbnail.
604          if ( sLocation.indexOf( "defaultthumbnail" ) == -1 )
605          {
606             sNewLocation = sLocation + ".versions" + fileSeparator + record.getString( ActionPropertiesI.VERSION_NUMBER_PREVIOUS ) + fileSeparator;
607             childRecord.setString( ActionPropertiesI.DESTINATION_SERVER, childRecord.getServer() );
608             childRecord.setDestinationLocation( sNewLocation );
609             childRecord.setString( ActionPropertiesI.VERSION_SERVER, childRecord.getServer() );
610             childRecord.setString( ActionPropertiesI.VERSION_LOCATION, sNewLocation );
611             childRecord.setString( ActionPropertiesI.VERSION_FILENAME, childRecord.getFileName() );
612             // set Keep Resource fork to true so lowres version files maintains its resource fork
613             childRecord.setBoolean( ActionPropertiesI.KEEP_RESOURCEFORK, new Boolean(true) );
614             // set is MacBinary to false
615             childRecord.setBoolean( ActionPropertiesI.MACBINARY_FORMAT, new Boolean(false) );
616             tempData.addRecord( childRecord );
617          }
618          else
619          {
620             childRecord.setString( ActionPropertiesI.VERSION_SERVER, childRecord.getServer() );
621             childRecord.setString( ActionPropertiesI.VERSION_LOCATION, childRecord.getLocation() );
622             childRecord.setString( ActionPropertiesI.VERSION_FILENAME, childRecord.getFileName() );
623 
624             // To avoid creating thumbnails in the defaultthumbnail directory, reset the values of server, location and filename
625             childRecord.removeObject( ActionPropertiesI.SERVER );
626             childRecord.removeObject( ActionPropertiesI.LOCATION );
627             childRecord.removeObject( ActionPropertiesI.FILENAME );
628          }
629          // Set the VersionXXXXX and other info needed in the bean
630          childRecord.setString( ActionPropertiesI.VERSION_NUMBER, record.getString( ActionPropertiesI.VERSION_NUMBER ) );
631          childRecord.setLong( ActionPropertiesI.VERSION_FILESIZE, childRecord.getFileSize() );
632          childRecord.setString( ActionPropertiesI.CHECKIN_DATETIME, record.getString( ActionPropertiesI.CHECKIN_DATETIME ) );
633 
634          if ( tempData.getRecords() != null && tempData.getRecords().size() > 0 )
635             executeService( ServicesI.COPY_SERVICE, tempData );
636          // If we were unable to copy the default view (thumbnail) we should still
637          // continue with the check in process.  We don't need to be concerned about
638          // resetting to true a bContinue value that failed elsewhere in the checkIn
639          // process, because the process would not have made it to this method if it
640          // failed elsewhere.
641          if ( bContinue == false )
642          {
643             bContinue = true;
644          }
645       }
646    }
647 
648    private void rollBackFiles( Vector vBadRecords, Vector vBadStates )
649    {
650       if ( vBadRecords.size() > 0 )
651       {
652          Vector vOriginal        = new Vector();
653          Vector vDefaultView     = new Vector();
654          Vector vOriginalLowres  = new Vector(); // holds lowres for original assets
655          Vector vVersionLowres   = new Vector(); // holds lowres for version assets
656          AssetRecordData record = null;
657          for ( int i = 0; i < vBadRecords.size(); i++ )
658          {
659             record = (AssetRecordData) vBadRecords.elementAt(i);
660             // According to the state, add this record to one or more
661             // rollback methods.
662             switch ( ((Integer) vBadStates.elementAt(i)).intValue() )
663             {
664                case ASSETS_CHECKED_IN:
665                case DEFAULTVIEW_COPIED:
666                   rollBackDefaultView( true, vDefaultView, record );
667                case LOWRES_UPDATED:
668                   if ( hasLowres( record ) )
669                      rollBackLowres( true, vOriginalLowres, vVersionLowres, record );
670                case NEW_VERSION_COPIED:
671                case ORIGINAL_MOVED:
672                   rollBackOriginal( true, vOriginal, null, record );
673                   break;
674             }
675          }
676          rollBackDefaultView( false, vDefaultView, null );
677          rollBackLowres( false, vOriginalLowres, vVersionLowres, null );
678          rollBackOriginal( false, vOriginal, vOriginalLowres, null );
679       }
680    }
681    
682    private void rollBackOriginal( boolean bProcessRecord, Vector vRecords, Vector vLowres, AssetRecordData record )
683    {
684       if ( bProcessRecord )
685       {
686          AssetRecordData tempRecord = (AssetRecordData)record.clone();
687          String sNewLocation = tempRecord.getLocation();
688          tempRecord.setString( ActionPropertiesI.DESTINATION_SERVER, tempRecord.getServer() );
689          tempRecord.setDestinationLocation( sNewLocation );
690          // set Keep Resource fork to true so files maintains its resource fork
691          tempRecord.setBoolean( ActionPropertiesI.KEEP_RESOURCEFORK, new Boolean(true) );
692          // set is MacBinary to false
693          tempRecord.setBoolean( ActionPropertiesI.MACBINARY_FORMAT, new Boolean(false) );
694          // Set the version server, location and filename
695          tempRecord.setServer( tempRecord.getString( ActionPropertiesI.VERSION_SERVER ) );
696          tempRecord.setLocation( tempRecord.getString( ActionPropertiesI.VERSION_LOCATION ) );
697          tempRecord.setFileName( tempRecord.getString( ActionPropertiesI.VERSION_FILENAME ) );
698          tempRecord.setFileSize( tempRecord.getLong( ActionPropertiesI.VERSION_FILESIZE ) );
699          vRecords.addElement( tempRecord );
700       }
701       else if ( vRecords.size() > 0 )
702       {
703          // Set the tempData object used all along this service
704          ActionData tempData = (ActionData)data.clone();
705          tempData.setRecords( vRecords ); // Set records
706          executeService( ServicesI.MOVE_SERVICE, tempData );
707 
708          // Find out if we need to update the lowres for these assets
709          if ( vLowres.size() > 0 )
710          {
711             tempData.setRecords( vLowres );
712             tempData.setInteger( "lowres_action", new Integer(LowresConstants.CREATE_LOWRES) );
713             executeService( ServicesI.LOWRES_SERVICE, tempData );
714          }
715       }
716    }
717 
718    private void rollBackLowres( boolean bProcessRecord, Vector vOriginals, Vector vVersions, AssetRecordData record )
719    {
720       if ( bProcessRecord )
721       {
722          vOriginals.addElement( record );
723          // Now lets find out if we need to keep the lowres for the version asset
724          boolean bKeepLowres = false;
725          try { bKeepLowres = record.getBoolean( ActionPropertiesI.KEEP_LOWRES ).booleanValue(); }
726          catch ( NullPointerException npe ) {}
727          if ( bKeepLowres )
728          {
729             // Create a new record pointing to the highres in .versions in order to create its lowres
730             AssetRecordData versionRecord = (AssetRecordData)record.clone();
731             versionRecord.setLocation( record.getString( ActionPropertiesI.VERSION_LOCATION ) );
732             vVersions.addElement( versionRecord );
733          }
734       }
735       else if ( !vOriginals.isEmpty() )
736       {
737          // Set the tempData object used all along this service
738          ActionData tempData = (ActionData)data.clone();
739 
740          // vVersions has elements only if vOriginals has.
741          // Add the elements to vVersions instead of vOriginals, because vOriginals is needed
742          // in rollBackOriginals(...), called after this method.
743          if ( !vVersions.isEmpty() )
744          {
745             for ( int i = 0; i < vOriginals.size(); i++ )
746                vVersions.addElement( vOriginals.elementAt(i) );
747 
748             tempData.setRecords( vVersions );
749          }
750          else
751             tempData.setRecords( vOriginals ); // Set records
752 
753          tempData.setInteger( "lowres_action", new Integer(LowresConstants.DELETE_LOWRES) );
754          executeService( ServicesI.LOWRES_SERVICE, tempData );
755       }
756    }
757 
758    private void rollBackDefaultView( boolean bProcessRecord, Vector vRecords, AssetRecordData record )
759    {
760       if ( bProcessRecord )
761       {
762          AssetRecordData thumbRecord = getDefaultViewRecord(record);
763          if ( thumbRecord != null )
764          {
765             thumbRecord = (AssetRecordData) thumbRecord.clone();
766             thumbRecord.setDestinationLocation( PathBuilder.constructPath( thumbRecord.getServer(), thumbRecord.getLocation(), true ) );
767             // Set the server, location and filename
768             thumbRecord.setServer( thumbRecord.getString( ActionPropertiesI.VERSION_SERVER ) );
769             thumbRecord.setLocation( thumbRecord.getString( ActionPropertiesI.VERSION_LOCATION ) );
770             thumbRecord.setFileName( thumbRecord.getString( ActionPropertiesI.VERSION_FILENAME ) );
771             thumbRecord.setFileSize( thumbRecord.getLong( ActionPropertiesI.VERSION_FILESIZE ) );
772             // set Keep Resource fork to true so lowres files maintains its resource fork
773             thumbRecord.setBoolean( ActionPropertiesI.KEEP_RESOURCEFORK, new Boolean(true) );
774             // set is MacBinary to false
775             thumbRecord.setBoolean( ActionPropertiesI.MACBINARY_FORMAT, new Boolean(false) );
776             vRecords.addElement( thumbRecord );
777          }
778       }
779       else if ( vRecords.size() > 0 )
780       {
781          // Set the tempData object used all along this service
782          ActionData tempData = (ActionData)data.clone();
783          tempData.setRecords( vRecords ); // Set records
784          executeService( ServicesI.MOVE_SERVICE, tempData );
785       }
786    }
787 
788    private void regenerateAssetsInfo( Vector vGoodRecords )
789    {
790       Vector vRegenerateRecords = new Vector();
791       AssetRecordData record = null;
792       for ( int i = 0; i < vGoodRecords.size(); i++ )
793       {
794          record = (AssetRecordData) vGoodRecords.elementAt(i);
795          try
796          {
797             if ( record.getBoolean( ActionPropertiesI.REGENERATE_THUMBNAIL ).booleanValue() == true )
798                vRegenerateRecords.addElement( record );
799          }
800          catch ( NullPointerException npe ) {}
801       }
802       
803       if ( vRegenerateRecords.size() > 0 )
804       {
805          // Set the tempData object used all along this service
806          ActionData tempData = (ActionData)data.clone();
807          tempData.setRecords( vRegenerateRecords );
808          executeService( ServicesI.IMPORT_ACTIONDATA_SERVICE, tempData );
809       }
810    }
811    
812    private void checkInAssets( Vector vGoodRecords )
813       throws TransactionFailedException
814    {
815       ActionData checkInDummyData = (ActionData)data.clone();
816       checkInDummyData.setRecords( vGoodRecords );
817       checkInGateway.checkInAssets( checkInDummyData );
818    }
819    
820    private void updateDatabase( Vector vGoodRecords, Vector vBadRecords )
821       throws TransactionFailedException
822    {
823       if ( vGoodRecords.size() > 0 )
824       {
825          ActionData goodData = (ActionData)data.clone();
826          goodData.setRecords( vGoodRecords );
827          Diagnostic.trace(Diagnostic.APPSERVER_SERVICES, "Doing checkInAsset in the database!!!");
828          try
829          {
830             checkInGateway.updateCheckInStatus( goodData );
831          }
832          catch ( TransactionFailedException rtfe )
833          {
834             // If this fails, add elements of vGoodRecords to vBadRecords so we roll them
835             // back
836             for ( int i = 0; i < vGoodRecords.size(); i++ )
837             {
838                vBadRecords.addElement( (AssetRecordData) vGoodRecords.elementAt(i) );
839                vBadStates.addElement( new Integer(ASSETS_CHECKED_IN) );
840             }
841             vGoodRecords.removeAllElements();
842          }
843       }
844       if ( vBadRecords.size() > 0 )
845       {
846          ActionData badData = (ActionData)data.clone();
847          // If the global state is less than ASSETS_CHECKED_IN, we know that version records were not created
848          // in the database for any of the bad assets and it is safe to call the rollBackInProcessCheckIn with
849          // a 'false' argument.
850          // However if the global state is equal or greater than ASSETS_CHECKED_IN, we need to parse through
851          // the list of bad records to find out which one failed before calling the checkInAssets() (and pass
852          // false in the argument) and for which one we called checkInAssets() (and pass true in the argument)
853          if ( nGlobalState < ASSETS_CHECKED_IN )
854          {
855             badData.setRecords( vBadRecords );
856             Diagnostic.trace(Diagnostic.APPSERVER_SERVICES, "Doing cancelCheckInAssets in the database!!!");
857             checkInGateway.rollbackInProcessCheckIn( badData, false ); // Versions not created
858          }
859          else
860          {
861             Vector vFailedBeforeCheckedIn = new Vector();
862             Vector vFailedAfterCheckedIn = new Vector();
863 
864             int nState;
865             for ( int i = 0; i < vBadStates.size(); i++ )
866             {
867                nState = ((Integer)vBadStates.elementAt(i)).intValue();
868                if ( nState < ASSETS_CHECKED_IN )
869                   vFailedBeforeCheckedIn.addElement( vBadRecords.elementAt(i) );
870                else
871                   vFailedAfterCheckedIn.addElement( vBadRecords.elementAt(i) );
872             }
873 
874             if ( vFailedBeforeCheckedIn.size() > 0 )
875             {
876                badData.setRecords( vFailedBeforeCheckedIn );
877                Diagnostic.trace(Diagnostic.APPSERVER_SERVICES, "Doing cancelCheckInAssets in the database!!!");
878                checkInGateway.rollbackInProcessCheckIn( badData, false );
879             }
880             if ( vFailedAfterCheckedIn.size() > 0 )
881             {
882                badData.setRecords( vFailedAfterCheckedIn );
883                Diagnostic.trace(Diagnostic.APPSERVER_SERVICES, "Doing cancelCheckInAssets in the database!!!");
884                checkInGateway.rollbackInProcessCheckIn( badData, true );
885             }
886          }
887       }
888    }
889    
890    private void cleanUpTempDir()
891    {
892       // Set the tempData object used all along this service
893       ActionData tempData = (ActionData)data.clone();
894       // Remove all files from the /tmp/TransId directory; including the directory if empty
895       tempData.setRecords( null );
896       Vector vRecords = data.getRecords();
897 
898       AssetRecordData tempRecord;
899       for ( int i = 0; i < vRecords.size(); i++ )
900       {
901          tempRecord = (AssetRecordData) vRecords.elementAt(i);
902 
903          boolean bIsLocationInServer = true;
904          try { bIsLocationInServer = tempRecord.getBoolean( ActionPropertiesI.IS_LOCATION_IN_SERVER ).booleanValue(); }
905          catch ( NullPointerException npe ) {}
906          if ( !bIsLocationInServer )
907          {
908             // Location in server is the temp directory; delete files
909             // Get the source location and set this as the input path for the next service
910             tempRecord.setServer( ServerList.getServerName( tempRecord.getString(ActionPropertiesI.SOURCE_SERVER) ) );
911             tempRecord.setLocation( tempRecord.getString(ActionPropertiesI.SOURCE_LOCATION) );
912             tempRecord.setFileName( tempRecord.getString(ActionPropertiesI.SOURCE_FILENAME) );
913             tempRecord.setFileSize( tempRecord.getLong( ActionPropertiesI.SOURCE_FILESIZE ) );
914             tempData.addRecord( tempRecord );
915          }
916       }
917 
918       if ( tempData.getRecords() != null )
919          executeService( ServicesI.DELETE_SERVICE, tempData );
920    }
921    
922    private void executeService( String sServiceName, ActionData data )
923    {
924       try
925       {
926          ActionResult result = doService( sServiceName, data );
927          if ( result == null )
928             bContinue = false;
929          else
930             bContinue = result.isSuccess();
931       }
932       catch( SrvcNotAvailException e )
933       {
934          //6232=Check-In Service
935          new FlexError(FlexError.CRITICAL, Resources.get(6232), IDENTIFIER, e);
936          bContinue = false;
937       }
938    }
939 
940    private AssetRecordData getDefaultViewRecord( AssetRecordData record )
941    {
942       Vector vChildren = record.getChildrenRecords();
943       if ( vChildren != null )
944       {
945          long nDefaultViewAssetId = record.getDefaultViewAssetId().longValue();
946          AssetRecordData child;
947          for ( int i = 0; i < vChildren.size(); i++ )
948          {
949             child = (AssetRecordData)vChildren.elementAt(i);
950             if ( child.getAssetId() == nDefaultViewAssetId )
951                return child;
952          }
953       }
954       return null;
955    }
956 
957    private boolean hasLowres( AssetRecordData record )
958    {
959       Vector vChildren = record.getChildrenRecords();
960       if ( vChildren != null )
961       {
962          for ( int i = 0; i < vChildren.size(); i++ )
963          {
964             Integer nRoleId = ((AssetRecordData)vChildren.elementAt(i)).getRoleId();
965             if ( nRoleId.intValue() == LOWRES )
966                return true;
967          }
968       }
969       return false;
970    }
971 } // end of class