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

Quick Search    Search Deep

Source code: com/flexstor/flexdbserver/services/asset/ImportAssetService.java


1   /*
2    * ImportAssetService.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.Enumeration;
14  import java.util.Hashtable;
15  import java.util.Vector;
16  
17  import com.flexstor.common.data.ActionData;
18  import com.flexstor.common.data.ActionResult;
19  import com.flexstor.common.data.ejb.disguiserecord.DisguiseAssetRecordData;
20  import com.flexstor.common.data.ejb.disguiserecord.DisguiseBucketRecordData;
21  import com.flexstor.common.data.ejb.disguiserecord.DisguiseRecordData;
22  import com.flexstor.common.errorlogger.FlexError;
23  import com.flexstor.common.importprocessor.ImportData;
24  import com.flexstor.common.importprocessor.ImportResult;
25  import com.flexstor.common.importprocessor.ResultListener;
26  import com.flexstor.common.resources.Resources;
27  import com.flexstor.common.services.ServiceBrokerI;
28  import com.flexstor.common.services.ServiceListenerI;
29  import com.flexstor.common.threadmgr.ThreadCallbackI;
30  import com.flexstor.common.threadmgr.ThreadConsumerI;
31  import com.flexstor.common.util.Diagnostic;
32  import com.flexstor.flexdbserver.importprocessor.ImportProcessor;
33  import com.flexstor.flexdbserver.services.Service;
34  import com.flexstor.flexdbserver.services.ServiceContext;
35  import com.flexstor.flexdbserver.services.ServiceManager;
36  import com.flexstor.flexdbserver.transactionmanager.TransMngImport;
37  
38  /**
39   * <P>
40   * ImportAssetService <BR>
41   * <BLOCKQUOTE>
42   *    Manages the entire process of importing assets into the database. This service reads from the
43   *    input control (*.ctl) file a list of services to be performed against all assets (preservices, for example
44   *    assigning roles and types to each asset); then it divides the assets in groups by role and type
45   *    and performs the set of services specified for each group in the roletype_services.config file. Finally,
46   *    if specified in the roletype_services.config file, it will import the assets into the database.
47   * </BLOCKQUOTE>
48   * </P>
49   *
50   * <P>
51   * Input Data Object <BR>
52   * <BLOCKQUOTE>
53   *    com.flexstor.common.importprocessor.ImportData
54   * </BLOCKQUOTE>
55   * </P>
56   *
57   * <P>
58   * Output Data Object <BR>
59   * <BLOCKQUOTE>
60   *    com.flexstor.common.importprocessor.ImportResult
61   * </BLOCKQUOTE>
62   * </P>
63   */
64  public class ImportAssetService
65     implements Service, ThreadCallbackI
66  {
67     // To get the version number from MKS
68     public final static String IDENTIFIER="$Id: ImportAssetService.java,v 1.4 2003/08/11 02:22:29 aleric Exp $";
69  
70     private ServiceBrokerI   serviceBroker;
71     private int                id                      = -1;
72     private String             sThisService            = "";
73     private ImportData       importData              = null;
74     private ImportData       subImportDataReturned   = null;
75     private int                nManagerRunning         = 0;
76     private ServiceListenerI listener                = null; // The listener of this service
77     private String             sServiceType            = ""; //Valid values: PreService, PostService or Service
78     private String             sSubTransId             = ""; //The Transaction id for this sub transaction
79     private boolean            bContinue               = true;
80  
81     /**
82      * Calls before the service is initialized (before initData is called) to 
83      * pass information about the environment in which the service is running.
84      * This environment consists of information about the properties set for the
85      * service in one of these files (services.config, roletype_services.config,
86      * or *.ctl), plus methods to access other information such as an instance
87      * of the service broker to invoke other services, the transaction id for
88      * the service, file separator character and local path for the installation
89      * directory and configuration directory.
90      * 
91      * @param context Holds information about the environment in which the service
92      *                is running.
93      */
94     public void setServiceContext( ServiceContext context )
95     {
96        serviceBroker = context.getServiceBroker();
97        id = context.getTransactionId();
98     }
99     
100    /**
101    * A data initialization method called at the beginning of the service.
102    * The input argument, ActionData must be cast into its subclass, ImportData
103    * in order to extract the AssetService specific data.
104    **/
105    public void initData(ActionData actionData)
106    {
107       importData = (ImportData) actionData;
108       listener = importData.getServiceListener();
109       sSubTransId = importData.getTransID();
110       //5560=Import Asset Service
111       sThisService = Resources.get(5560) + " (" + sSubTransId + ")";
112    }
113 
114    /**
115    * The start of the Asset Service.
116    **/
117    public synchronized ActionResult go()
118    {
119       boolean bLockHotDir = false;
120       String sHotDirToLock = "";
121 
122       // This code will be enclosed in a try/finally block to ensure that
123       // when a hot directory is locked, no matter what, it will be released
124       try
125       {
126          // Check if it is necessary to lock the hot directory
127          // Retrieve the LockHotdir property from the *ctl file
128          bLockHotDir = (new Boolean(importData.getCtlDataRef().getValuePerKey("LOCKHOTDIR"))).booleanValue();
129          if ( bLockHotDir )
130          {
131             // Retrieve the base path of the hot directory to be locked
132             sHotDirToLock = importData.getCtlDataRef().getValuePerKey("TOP");
133             ImportProcessor.lockHotDir(sHotDirToLock);
134          }
135 
136          TransMngImport tmImport = new TransMngImport( id );
137 
138          // Run Pre-Services
139          // Start an instance of the Asset Service Manager in a different thread and waits
140          // for it to finish; if something wrong happens, abort the Import Asset Service
141          try
142          {
143             sServiceType = AssetServiceManager.PRESERVICES;
144             (new AssetServiceManager(sServiceType, importData, this)).startManager();
145             this.wait();
146             
147             // Replace the original import data object with the one updated by the pre-services
148             importData = subImportDataReturned;
149          }
150          catch (InterruptedException ie)
151          {
152             // Remove the assets from the ASSETS_INPROCESS table and remove this persisted
153             // transaction from TransList.per
154             tmImport.setTransactionCompletedState();
155             new FlexError(FlexError.CRITICAL, sThisService, IDENTIFIER, ie);
156             notifyListener();
157             return new ImportResult(false);
158          }
159          catch (AssetServiceManagerException rasme)
160          {
161             // Remove the assets from the ASSETS_INPROCESS table and remove this persisted
162             // transaction from TransList.per
163             tmImport.setTransactionCompletedState();
164             new FlexError(FlexError.CRITICAL, sThisService, IDENTIFIER, rasme);
165             notifyListener();
166             return new ImportResult(false);
167          }
168 
169          // After all preservices are completed, create subsets of ImportData per each file type
170          Hashtable hImportDataSubSet = null;
171          if ( bContinue )
172             hImportDataSubSet = createImportDataSubSets();
173 
174          if (hImportDataSubSet != null)
175          {
176             // Set sServiceType to "Service" to indicate that the updateImportData() method
177             // must be performed.
178             sServiceType = "Service";
179             // Set the counter of manager running to zero; as it could be modified by the
180             // preservices
181             nManagerRunning = 0;
182 
183             // Create one thread per ImportDataSubSet and start a Remote Asset Service Manager
184             // synchronized to protect integrity of hImportDataSubSet and to make sure we start
185             //all the threads before getting any response back from observables.
186             for (Enumeration e = hImportDataSubSet.keys(); e.hasMoreElements(); )
187             {
188                String sType = (String) e.nextElement();
189                ImportData importDataSubSet = (ImportData) hImportDataSubSet.get(sType);
190                // Create a new transaction manager for this object and set the state to
191                // IMPORT_INPROCESS_TABLE_UPDATE_STATE for rollback purposes. Assets were already
192                // added to the ASSETS_INPROCESS table by the import processor.
193                int nSubTransId = serviceBroker.getUniqueNo();
194                if ( nSubTransId != -1 )
195                {
196                   importDataSubSet.setTransId( nSubTransId );
197                   try
198                   {
199                      tmImport.addSubTransaction(nSubTransId, importDataSubSet );
200                      (new AssetServiceManager(sType, importDataSubSet, this)).startManager();
201                   }
202                   catch ( AssetServiceManagerException rasme )
203                   {
204                      // Remove the assets from the ASSETS_INPROCESS table and remove this persisted
205                      // transaction from TransList.per
206                      tmImport.removeSubTransaction( nSubTransId );
207                      new FlexError(FlexError.CRITICAL, sThisService, IDENTIFIER, rasme);
208                      notifyListener();
209                      return new ImportResult(false);
210                   }
211                   nManagerRunning++;
212                }
213             }
214          }
215 
216          // while there are services still running, just wait until be notified of an update;
217          // if all services are done, exit loop and exit Asset Service
218          while (nManagerRunning > 0 )
219          {
220             try
221             {
222                this.wait();
223                if ( subImportDataReturned != null )
224                   tmImport.removeSubTransaction( subImportDataReturned.getTransId() );
225             }
226             catch (InterruptedException ie)
227             {
228                // Remove the assets from the ASSETS_INPROCESS table and remove this persisted
229                // transaction from TransList.per
230                tmImport.setTransactionCompletedState();
231                notifyListener();
232                return new ImportResult(false);
233             }
234          }
235 
236          // Run Post-Services
237          // Start an instance of the Asset Service Manager in a different thread and waits
238          // for it to finish; if something wrong happens, abort the Import Asset Service
239          /*
240          *  NOTE: Postservices are not supported at this moment.
241          *
242          * Before enabling this code we have to make sure that the importData variable
243          * holds all assets as modified by services in roletype_services.config.
244          * 
245          if ( importData != null )
246          {
247             try
248             {
249                sServiceType = AssetServiceManager.POSTSERVICES;
250                sNewThreadName = sThreadName + nThreadCounter++;
251                ThreadManager.requestService( new AssetServiceManager(sServiceType, importData), this, null );
252                this.wait();
253             }
254             catch (InterruptedException ie)
255             {
256                // Remove the assets from the ASSETS_INPROCESS table and remove this persisted
257                // transaction from TransList.per
258                tmImport.setTransactionCompletedState();
259                notifyListener();
260                return new ImportResult(false);
261             }
262             catch (AssetServiceManagerException rasme)
263             {
264                // Remove the assets from the ASSETS_INPROCESS table and remove this persisted
265                // transaction from TransList.per
266                tmImport.setTransactionCompletedState();
267                new FlexError(FlexError.CRITICAL, sThisService, IDENTIFIER, rasme);
268                notifyListener();
269                return new ImportResult(false);
270             }
271          }
272          */
273 
274          // Remove any asset left in ASSETS_INPROCESS table and remove this persisted
275          // transaction from TransList.per
276          tmImport.setTransactionCompletedState();
277 
278          notifyListener();
279          return new ImportResult(bContinue);
280       }
281       finally
282       {
283          // Unlock hot directory
284          if ( bLockHotDir )
285             ImportProcessor.unlockHotDir(sHotDirToLock);
286       }
287    }
288 
289    /**
290    * create all subsets of ImportData (one per file type) and return
291    * them in a hashtable.
292    * key = file type; value = ImportData sub set
293    **/
294    private Hashtable createImportDataSubSets()
295    {
296       String[] saType = importData.getTypesFoundRef().getTypes();
297       Hashtable hSubSet = null;
298       if (saType != null && saType.length > 0)
299       {
300          hSubSet = new Hashtable(saType.length);
301 
302          for (int i = 0; i < saType.length; i++)
303          {
304             ImportData importDataSubSet = (ImportData) importData.clone();
305             int indexOfPeriod = saType[i].indexOf(".");
306             String sRole;
307             String sType;
308             if ( indexOfPeriod != -1 )
309             {
310                sRole = saType[i].substring( 0, indexOfPeriod );
311                sType = saType[i].substring( indexOfPeriod + 1 );
312             }
313             else
314             {
315                // Log error; saType[i] doesn't contain a valid role.type String.
316                Vector vAssets = importDataSubSet.getDisguiseRecordRef().getAssets( "ALL", saType[i], "PARENT" );
317                if ( vAssets != null && vAssets.size() > 0 )
318                {
319                   DisguiseAssetRecordData asset;
320                   Vector vBadAssets = new Vector();
321                   for ( int k = 0; k < vAssets.size(); k++ )
322                   {
323                      asset = (DisguiseAssetRecordData) vAssets.elementAt(k);
324                      if ( asset.getAssetRoleId() == 0 )
325                         vBadAssets.addElement( asset.getServer() + ":/" + asset.getLocation() + asset.getFileName() );
326                   }
327                   if ( vBadAssets.size() > 0 )
328                   {
329                      // 6968=%%1 is not a valid role.type. The following assets will not be imported:
330                      StringBuffer sbError = new StringBuffer( Resources.get(6968, saType[i]) + "\r\n" );
331                      for ( int j = 0; j < vBadAssets.size(); j++ )
332                         sbError.append( "    " + (String)vBadAssets.elementAt(j) + "\r\n" );
333 
334                      new FlexError(FlexError.CRITICAL, sThisService, IDENTIFIER, sbError.toString());
335                   }
336                }
337                continue;
338             }
339 
340             DisguiseRecordData disguiseRecorDataSubSet = importDataSubSet.getDisguiseRecordRef();
341             DisguiseBucketRecordData[] buckets = disguiseRecorDataSubSet.getBuckets();
342             if ( buckets != null )
343             {
344                Vector vBucketsToUse = new Vector();
345                for ( int j = 0; j < buckets.length; j++ )
346                {
347                   if ( !(buckets[j].removePrimaryAssetsNotInRoleType( sRole, sType )) )
348                      vBucketsToUse.addElement( buckets[j] );
349                }
350                if ( vBucketsToUse.size() > 0 )
351                {
352                   DisguiseBucketRecordData[] arrayOfBucketsToUse = new DisguiseBucketRecordData[ vBucketsToUse.size() ];
353                   vBucketsToUse.copyInto( arrayOfBucketsToUse );
354                   disguiseRecorDataSubSet.setBucket( arrayOfBucketsToUse );
355                   hSubSet.put(saType[i], importDataSubSet);
356                }
357             }
358          }
359       }
360       return hSubSet;
361    }
362 
363    /**
364    * update the ImportData after the set of services are executed for
365    * a ImportData sub set.
366    **/
367    private synchronized void notify(ImportResult importResult)
368    {
369       if ( importResult == null )
370       {
371          subImportDataReturned = null;
372          bContinue = false;
373       }
374       else if ( importResult.isSuccess() ) // true
375       {
376          subImportDataReturned = importResult.getImportData();
377          bContinue = true;
378       }
379       else // false
380       {
381          subImportDataReturned = importResult.getImportData();
382          bContinue = false;
383       }
384       nManagerRunning--;
385       this.notifyAll();
386    }
387 
388    /**
389     * Called when a thread task is about to begin.
390     * @param consumer the instance that this task will run against.
391     * @param obj      the user defined parameter for this task.
392     */
393    public void threadTaskStart ( ThreadConsumerI consumer, Object obj ) {}
394 
395    /**
396     * Called when a thread task has just finished.
397     * @param consumer the instance that this task will run against.
398     * @param obj      the user defined parameter for this task.
399     */
400    public void threadTaskEnd ( ThreadConsumerI consumer, Object obj )
401    {
402       notify( (ImportResult)(((ServiceManager)consumer).getResult()) );
403    }
404 
405   private void notifyListener()
406   {
407      // If a listener is up, notify it that this service is done
408      if ( listener != null )
409      {
410         Diagnostic.trace(Diagnostic.APPSERVER_SERVICES, "ImportAssetService done; sending acknowledge to import processor for Id: " + sSubTransId + "!!!");
411         ResultListener.getInstance().serviceDone(sSubTransId);
412      }
413   }
414 }