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

Quick Search    Search Deep

Source code: com/flexstor/flexdbserver/services/resourcefork/ResourceForkService.java


1   /*
2    * ResourceForkService.java
3    *
4    * Copyright $Date: 2003/08/14 07:17:08 $ 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.resourcefork;
12  
13  import java.util.Enumeration;
14  import java.util.Hashtable;
15  import java.util.Vector;
16  
17  import com.flexstor.common.constants.ActionPropertiesI;
18  import com.flexstor.common.constants.RsrcForkConstantsI;
19  import com.flexstor.common.data.ActionData;
20  import com.flexstor.common.data.ActionResult;
21  import com.flexstor.common.data.AssetRecordData;
22  import com.flexstor.common.errorlogger.FlexError;
23  import com.flexstor.common.io.xfile.FlexXFile;
24  import com.flexstor.common.resources.Resources;
25  import com.flexstor.common.settings.Settings;
26  import com.flexstor.common.util.Diagnostic;
27  import com.flexstor.common.util.ServerList;
28  import com.flexstor.flexdbserver.services.Service;
29  import com.flexstor.flexdbserver.services.ServiceContext;
30  import com.flexstor.flexdbserver.services.resourcefork.dave.DaveResourceFork;
31  import com.flexstor.flexdbserver.services.resourcefork.helios.HeliosResourceFork;
32  import com.flexstor.flexdbserver.services.resourcefork.ipt.IPTResourceFork;
33  import com.flexstor.flexdbserver.services.resourcefork.none.NoneResourceFork;
34  import com.flexstor.flexdbserver.services.resourcefork.xinet.XinetResourceFork;
35  import com.flexstor.flexdbserver.util.PathAnalyzer;
36  import com.flexstor.flexdbserver.util.PathBuilder;
37  
38  /**
39   * <P>
40   * ResourceForkService <BR>
41   * <BLOCKQUOTE>
42   *    Converts Macintosh files stored in either UNIX or NT file systems to MacBinary format
43   *    and vice versa. This service supports files stored using the following AppleTalk vendors
44   *    and software: Helios, IPT, Xinet, and DAVE.
45   * </BLOCKQUOTE>
46   * </P>
47   *
48   * <P>
49   * Configurable Properties in services.config <BR>
50   * <BLOCKQUOTE>
51   *    NTVolumes: Specifies Windows NTFS volumes where assets reside. These volumes need to
52   *    be mapped to the server running the FLEXSTOR.db application server; the mount point should be named after
53   *    the volume name assigned in NT. More than one volume is accepted (optional; only required
54   *    if files reside in NT volume and AppleTalk Vendor is DAVE). <BR>
55   *    Legal values: A comma or space delimited list of NT volumes
56   * </P>
57   * <P>
58   *    NTHost: The IP address of the NT host where files are located (optional; only required if files
59   *    reside in NT volume and AppleTalk vendor is DAVE). <BR>
60   *    Legal values: Valid IP address <BR>
61   * </P>
62   * <P>
63   *    NTPort: Port number where Remote Asset Server is running in NT machine (optional; only
64   *    required if files reside in NT volume and AppleTalk Vendor is DAVE; defaults to 1099). <BR>
65   *    Legal values: Valid port number <BR>
66   * </P>
67   * <P>
68   *    appletalk_installpath: Installation directory for AppleTalk software (required for Helios,
69   *    IPT, and Xinet). <BR>
70   *    Legal values: Full path <BR>
71   * </P>
72   * <P>
73   *    appletalk_converterpath: Path to conversion utilities (required for Helios and Xinet). <BR>
74   *    Legal values: Full path (not including name of utilities) <BR>
75   * </BLOCKQUOTE>
76   * </P>
77   *
78   * <P>
79   * Input Data Object <BR>
80   * <BLOCKQUOTE>
81   *    com.flexstor.common.data.ActionData
82   * </BLOCKQUOTE>
83   * </P>
84   *
85   * <P>
86   * Output Data Object <BR>
87   * <BLOCKQUOTE>
88   *    com.flexstor.common.data.ActionResult
89   * </BLOCKQUOTE>
90   * </P>
91   *
92   * <P>
93   * Programmable Properties (passed inside data object) <BR>
94   * <BLOCKQUOTE>
95   *    Global Properties (apply to all assets) <BR>
96   * <BLOCKQUOTE>
97   *       RsrcForkAction: The action to be performed by this ResourceForkService. <BR>
98   *       Data type: Integer <BR>
99   *       Legal values: COMBINE_FORKS, COPY_FORKS, MOVE_FORKS, SEPARATE_FORKS, DELETE_FORKS
100  *       defined in com.flexstor.common.constants.RsrcForkConstantsI <BR>
101  * </P>
102  * <P>
103  *       DestinationLocation: Location where output files will be placed. This property
104  *       will only be used if DestinationLocation is not defined as a specific property. <BR>
105  *       Data type: String <BR>
106  *       Legal values: Full path to destination directory <BR>
107  * </P>
108  * <P>
109  *       DeleteDirectory: Attempts to delete original directory after action is performed.
110  *       Directory will be deleted only if DeleteOriginal is set to true and no more files
111  *       remained inside directory (optional; defaults to false). <BR>
112  *       Data type: Boolean <BR>
113  *       Legal values: true or false <BR>
114  * </P>
115  * <P>
116  *       DeleteOriginal: Delete original file after action is performed (optional; defaults to false). <BR>
117  *       Data type: Boolean <BR>
118  *       Legal values: true or false <BR>
119  * </P>
120  * <P>
121  *       AddToAssetsInProcess: By default, if an action is going to place files in the original
122  *       hot directories, the ResourceForkService adds the files to the ASSET_INPROCESS table so
123  *       they don't get imported. If a previous service or process is doing so already, this option
124  *       can be disabled from the ResourceForkService (defaults to true). <BR>
125  *       Data type: Boolean <BR>
126  *       Legal values: true or false <BR>
127  * </BLOCKQUOTE>
128  * </P>
129  * <P>
130  *   Specific Properties (apply to each individual asset) <BR>
131  * <BLOCKQUOTE>
132  *       DestinationLocation: Location where the record will be placed; if not specified it
133  *       will use the DestinationLocation property defined in the Global section (if defined);
134  *       otherwise, the action will fail. <BR>
135  *       Data type: String <BR>
136  *       Legal values: Full path to destination directory <BR>
137  * </BLOCKQUOTE>
138  * </BLOCKQUOTE>
139  * </P>
140  */
141 public class ResourceForkService
142    implements Service, RsrcForkConstantsI, ActionPropertiesI
143 {
144    // To get the version number from MKS
145    public final static String IDENTIFIER="$Id: ResourceForkService.java,v 1.6 2003/08/14 07:17:08 dcardozo Exp $";
146 
147    public static final String FORK = "MacBinary Converter";
148    
149    private ActionData    forkData                = null;
150    private Vector          vRecords                = new Vector();
151    private Vector          vBadRecords             = new Vector();
152    private String          sAppServer              = null;
153    private String          sThisService            = "";
154    private String          sDefaultDestination     = null;
155    private int             nAction                 = -1;
156    private int             nServerAppleTalkVendor  = RsrcForkConstantsI.NONE;
157    private Hashtable       htProperties            = null;
158    // This variables are used in case we have non-appletalk vendor assets in a
159    // Appletalk vendor machine
160    private ResourceFork  noneResourceFork;
161    private ResourceFork  tempResourceFork;
162    private boolean bUsingNoneRsrc;
163    protected  ServiceContext     context;
164    protected  int                  id = -1;
165    protected  String               fileSeparator;
166 
167    /**
168     * Calls before the service is initialized (before initData is called) to 
169     * pass information about the environment in which the service is running.
170     * This environment consists of information about the properties set for the
171     * service in one of these files (services.config, roletype_services.config,
172     * or *.ctl), plus methods to access other information such as an instance
173     * of the service broker to invoke other services, the transaction id for
174     * the service, file separator character and local path for the installation
175     * directory and configuration directory.
176     * 
177     * @param context Holds information about the environment in which the service
178     *                is running.
179     */
180    public void setServiceContext( ServiceContext context )
181    {
182       this.context = context;
183       id = context.getTransactionId();
184       fileSeparator = context.getFileSeparator();
185    }
186    
187    public void initData(ActionData actionData)
188    {
189       forkData = actionData;
190       vRecords = forkData.getRecords();
191 
192       sAppServer = Settings.getString( Settings.APP_SERVER_HOST );
193 
194       htProperties = context.getProperties();
195       // Load the following key-value pairs into the Hashtable of properties to make them
196       // available for the XXXXResourceFork classes
197       try { nAction = forkData.getInteger( RESOURCEFORK_ACTION ).intValue(); }
198       catch ( NullPointerException npe ) { /* Uses default set in definitions */ }
199       finally{ htProperties.put( RESOURCEFORK_ACTION, new Integer( nAction ) ); }
200 
201       boolean bDeleteDir = false;
202       Boolean bBoolean = forkData.getBoolean( DELETE_DIRECTORY );
203       // If bBoolean is not, use default value set in definition
204       if ( bBoolean != null )
205          bDeleteDir = bBoolean.booleanValue();
206 
207       htProperties.put( DELETE_DIRECTORY, new Boolean( bDeleteDir ) );
208 
209       boolean bDeleteOriginal = false;
210       bBoolean = forkData.getBoolean( DELETE_ORIGINAL );
211       // If bBoolean is not, use default value set in definition
212       if ( bBoolean != null )
213          bDeleteOriginal = bBoolean.booleanValue();
214 
215       htProperties.put( DELETE_ORIGINAL, new Boolean( bDeleteOriginal ) );
216 
217       boolean bAddToAssetsInProcess = true;
218       bBoolean = forkData.getBoolean( ADD_TO_ASSETS_INPROCESS );
219       // If bBoolean is not, use default value set in definition
220       if ( bBoolean != null )
221          bAddToAssetsInProcess = bBoolean.booleanValue();
222       htProperties.put( ADD_TO_ASSETS_INPROCESS, new Boolean( bAddToAssetsInProcess ) );
223 
224       // If a destination is not set per asset, this will be used.
225       sDefaultDestination = forkData.getString( ActionPropertiesI.DESTINATION_LOCATION );
226       if ( sDefaultDestination != null && sDefaultDestination.endsWith( fileSeparator ) == false )
227          sDefaultDestination += fileSeparator;
228    }
229 
230    public ActionResult go()
231    {
232       // check taht we have an action to perform
233       if ( nAction == -1 )
234       {
235          //6295=No Action Specified for service.
236          new FlexError(FlexError.CRITICAL, sThisService, IDENTIFIER, 6295);
237          // send the response object to the calling class
238          return createBadResultObject();
239       }
240 
241       ResourceFork resourceFork = getResourceForkInstance();
242       if ( resourceFork == null )
243       {
244          //6912=An invalid AppleShare/OPI product has been specified; %%1 failed..
245          new FlexError(FlexError.CRITICAL, sThisService, IDENTIFIER, Resources.get(6912, sThisService));
246          // send the response object to the calling class
247          return createBadResultObject();
248       }
249 
250       if ( resourceFork.converterExists() == false)
251       {
252          //5538=No MacBinary converter found; check that converter path is properly set in services.config. Process failed.
253          new FlexError(FlexError.CRITICAL, sThisService, IDENTIFIER, 5538 );
254          // send the response object to the calling class
255          return createBadResultObject();
256       }
257 
258       // Do a shallow clone so we can safely remove items from vRecord.
259       Vector vRecordCounter = (Vector)vRecords.clone();
260       AssetRecordData record;
261       FlexXFile xFile, xTargetDir = null;
262       for (Enumeration e = vRecordCounter.elements();  e.hasMoreElements(); )
263       {
264          record = (AssetRecordData) e.nextElement();
265          int nRecordAppleTalkVendor = record.getAppleTalkVendor().intValue();
266          xFile = new FlexXFile( PathBuilder.constructFilePath( record ) );
267          
268          if ( nRecordAppleTalkVendor == nServerAppleTalkVendor )
269          {
270             if ( bUsingNoneRsrc )
271             {
272                resourceFork = tempResourceFork;
273                bUsingNoneRsrc = false;
274             }
275          }
276          else if ( nRecordAppleTalkVendor == NONE )
277          {
278             if ( !bUsingNoneRsrc )
279             {
280                if ( noneResourceFork == null )
281                   noneResourceFork = (ResourceFork) new NoneResourceFork( id, sThisService, htProperties );
282 
283                tempResourceFork = resourceFork;
284                resourceFork = noneResourceFork;
285                bUsingNoneRsrc = true;
286             }
287          }
288          else
289          {
290             vBadRecords.addElement( record );
291             vRecords.removeElement( record );
292             //6296=%%1 cannot be processed. AppleShare/OPI Vendor for this file doesn't match
293             // AppleShare/OPI Vendor installed in server.
294             new FlexError(FlexError.CRITICAL, sThisService, IDENTIFIER, 6296, new String[] { xFile.getAbsolutePath() } );
295             continue;
296          }
297          
298          if ( nAction != DELETE_FORKS )
299          {
300             String sTargetDir = record.getDestinationLocation();
301             // If a destination location is not specified, check for the default destination; is one is
302             // specified, use it; otherwise, if the action is COMBINE_FORKS or SEPARATE_FORKS use the
303             // source location as the destination; for other actions, fail.
304             if ( (sTargetDir == null) || sTargetDir.equals("") )
305             {
306                if ( sDefaultDestination != null )
307                   sTargetDir = sDefaultDestination;
308                else if ( nAction == COMBINE_FORKS || nAction == SEPARATE_FORKS )
309                   sTargetDir = record.getLocation();
310                else //if ( nAction == COPY_FORKS || nAction == MOVE_FORKS )
311                {
312                   //6936=Destination directory not specified. Cannot proceed with file %%1.
313                   new FlexError(FlexError.CRITICAL, sThisService, IDENTIFIER, 6936, new String[] { fileSeparator + record.getLocation() + record.getFileName()} );
314                   vBadRecords.addElement( record );
315                   vRecords.removeElement( record );
316                   continue;
317                }
318             }
319             sTargetDir = PathBuilder.constructPath( sAppServer, sTargetDir, true );
320 
321             Diagnostic.trace(Diagnostic.APPSERVER_SERVICES, "Target Dir for MacBinary " + sTargetDir);
322             xTargetDir = new FlexXFile( sTargetDir );
323          }
324 
325          boolean bActionResult = false;
326          if ( nAction == DELETE_FORKS )
327          {
328             bActionResult = resourceFork.deleteForks( xFile );
329          }
330          else
331          {
332             if( resourceFork.isDirCreated(xTargetDir) )
333             {
334                if ( resourceFork.checkForDiskSpace( xFile, xTargetDir, nAction ) )
335                {
336                   String sFixFileName, sTargetDir;
337                   record.setString( "OriginalServer", record.getServer() );
338                   record.setString( "OriginalLocation", record.getLocation() );
339                   record.setString( "OriginalFileName", record.getFileName() );
340 
341                   switch ( nAction )
342                   {
343                      case COMBINE_FORKS:
344                         Diagnostic.trace(Diagnostic.APPSERVER_SERVICES, 10, "ResourceForkService: Combining Forks" );
345                         bActionResult = resourceFork.combineForks( xFile, xTargetDir );
346                         // each individual record will need to be updated with the correct filename
347                         // and the correct path. If NoneResourceFork was used the file name doesn't
348                         // need the .bin extension
349                         if ( resourceFork instanceof NoneResourceFork )
350                            sFixFileName= record.getFileName();
351                         else
352                            sFixFileName = new String( record.getFileName() + RsrcForkConstantsI.MACBINARY_EXT );
353                         
354                         record.setFileName( sFixFileName );
355                         // Make sure path does not contain a leading slash but contains a trailing slash
356                         sTargetDir = xTargetDir.getLocalPath();
357                         sTargetDir = PathBuilder.removeFileSeparators( sTargetDir, true, false );
358                         sTargetDir = PathBuilder.addFileSeparators( sTargetDir, false, true );
359                         record.setLocation( sTargetDir );
360                         break;
361                      case SEPARATE_FORKS:
362                         Diagnostic.trace(Diagnostic.APPSERVER_SERVICES, 10, "ResourceForkService: Separating Forks" );
363                         bActionResult = resourceFork.separateForks( xFile, xTargetDir );
364                         // each individual record will need to be updated with the correct filename
365                         // and the correct path.If NoneResourceFork was used the file name doesn't
366                         // have the .bin extension
367                         sFixFileName = record.getFileName();
368                         if ( !(resourceFork instanceof NoneResourceFork) )
369                            sFixFileName = sFixFileName.substring( 0, sFixFileName.lastIndexOf(RsrcForkConstantsI.MACBINARY_EXT) );
370       
371                         record.setFileName( sFixFileName );
372                         // Make sure path does not contain a leading slash but contains a trailing slash
373                         sTargetDir = xTargetDir.getLocalPath();
374                         sTargetDir = PathBuilder.removeFileSeparators( sTargetDir, true, false );
375                         sTargetDir = PathBuilder.addFileSeparators( sTargetDir, false, true );
376                         record.setLocation( sTargetDir );
377                         break;
378                      case COPY_FORKS:
379                         bActionResult = resourceFork.copyForks( xFile, xTargetDir );
380                         break;
381                      case MOVE_FORKS:
382                         bActionResult = resourceFork.moveForks( xFile, xTargetDir );
383                         break;
384                   }
385                }
386                else
387                {
388                   //6294=There is not enough disk space in %%1 to perform this service on asset %%2.
389                   new FlexError(FlexError.CRITICAL, sThisService, IDENTIFIER, 6294, new String[] { xTargetDir.getPath(), PathBuilder.constructFilePath(record) } );
390                   bActionResult = false;
391                }
392             }
393             else
394             {
395                //5537=Destination %%1 not found; MacBinary converted failed.
396                new FlexError(FlexError.CRITICAL, sThisService, IDENTIFIER, 5537, new String[] { xTargetDir.getLocalPath() });
397                bActionResult = false;
398             }
399          }
400 
401          // we only want to set the result record to [whatever].bin if it was successful
402          // and it was not trying to separate the forks.
403          if ( bActionResult && (nAction != SEPARATE_FORKS) )
404          {
405             String sOutFile = resourceFork.getOutFile();
406             if ( sOutFile.equals("") == false )
407             {
408                String sServer = PathAnalyzer.getServerName(sOutFile);
409                String sLocalParent = PathAnalyzer.getLocalParent(sOutFile);
410                sLocalParent = PathBuilder.addFileSeparators( sLocalParent, false, true );
411                sLocalParent = PathBuilder.removeFileSeparators( sLocalParent, true, false );
412                String sFileName = PathAnalyzer.getFileName(sOutFile);
413 
414                record.setString( ActionPropertiesI.DESTINATION_SERVER, sServer );
415                record.setString( ActionPropertiesI.DESTINATION_LOCATION, sLocalParent );
416                record.setString( ActionPropertiesI.DESTINATION_FILENAME, sFileName );
417             }
418          }
419          else if ( !bActionResult )
420          {
421             vBadRecords.addElement( record );
422             vRecords.removeElement( record );
423          }
424       } // end of for (int i...
425 
426       // If any temporary directory was created, delete it
427       resourceFork.deleteTempDir();
428 
429       ActionResult result;
430       // if there is not a good file, or at least one bad file
431       if (vBadRecords.size() > 0)
432       {
433          result = new ActionResult(false); // failures occurred
434          result.setBadRecords(vBadRecords); // return the bad records
435       }
436       else
437       {
438          result = new ActionResult(true);
439       }
440 
441       // we do not need to copy the vRecords back into the forkData ActionData object
442       // because we have been changing it as we go along.
443       
444       result.setString( ActionPropertiesI.MESSAGE_STRING, FORK );
445       result.setData(forkData);
446       result.setId( id );
447       // send the response object to the calling class
448       return result;
449    }
450 
451    private ResourceFork getResourceForkInstance()
452    {
453       ResourceFork resourceFork = null;
454 
455       nServerAppleTalkVendor = ServerList.getAppleTalkVendor( sAppServer );
456 
457       switch( nServerAppleTalkVendor )
458       {
459          case DAVE:
460             //6747=Dave Resource Fork Service
461             sThisService = Resources.get(6747) + " (" + id + ")";
462             Diagnostic.trace(Diagnostic.APPSERVER_SERVICES, "It is a DAVE Fork Service");
463             resourceFork = (ResourceFork) new DaveResourceFork( id, sThisService, htProperties );
464             break;
465          case HELIOS:
466             //5540=Helios Resource Fork Service
467             sThisService = Resources.get(5540) + " (" + id + ")";
468             Diagnostic.trace(Diagnostic.APPSERVER_SERVICES, "It is a HELIOS Fork Service");
469             resourceFork = (ResourceFork) new HeliosResourceFork( id, sThisService, htProperties );
470             break;
471          case IPT:
472             //5541=IPT Resource Fork Service
473             sThisService = Resources.get(5541) + " (" + id + ")";
474             Diagnostic.trace(Diagnostic.APPSERVER_SERVICES, "It is a IPT Fork Service");
475             resourceFork = (ResourceFork) new IPTResourceFork( id, sThisService, htProperties );
476             break;
477          case XINET:
478             //5542=Xinet Resource Fork Service
479             sThisService = Resources.get(5542) + " (" + id + ")";
480             Diagnostic.trace(Diagnostic.APPSERVER_SERVICES, "It is a XINET Fork Service");
481             resourceFork = (ResourceFork) new XinetResourceFork( id, sThisService, htProperties );
482             break;
483          default:
484             //7082=None Resource Fork Service
485             sThisService = Resources.get(7082) + " (" + id + ")";
486             Diagnostic.trace(Diagnostic.APPSERVER_SERVICES, "It is a NONE Fork Service");
487             resourceFork = (ResourceFork) new NoneResourceFork( id, sThisService, htProperties );
488             break;
489       }
490       return resourceFork;
491    }
492 
493    private ActionResult createBadResultObject()
494    {
495       // Copy all the records to the Vector containing all bad records; and delete
496       // the list of records from ActionData.
497       vBadRecords = (Vector) vRecords.clone();
498       vRecords.removeAllElements();
499 
500       ActionResult result = new ActionResult(false); // failures occurred
501       result.setBadRecords(vBadRecords); // return the bad records
502       result.setString( ActionPropertiesI.MESSAGE_STRING, FORK );
503       result.setData(forkData);
504       return result;
505    }
506 }
507 
508 
509 
510