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/DBUpdateService.java


1   /*
2    * DBUpdateService.java
3    *
4    * Copyright $Date: 2003/08/11 02:22:28 $ 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.Iterator;
14  import java.util.StringTokenizer;
15  import java.util.Vector;
16  
17  import com.flexstor.common.constants.ServicesI;
18  import com.flexstor.common.data.ActionData;
19  import com.flexstor.common.data.ActionResult;
20  import com.flexstor.common.data.ejb.disguiserecord.DisguiseRecordData;
21  import com.flexstor.common.errorlogger.FlexError;
22  import com.flexstor.common.gateway.ImportRecordGateway;
23  import com.flexstor.common.gateway.exceptions.TransactionFailedException;
24  import com.flexstor.common.importprocessor.ImportData;
25  import com.flexstor.common.importprocessor.ImportResult;
26  import com.flexstor.common.resources.Resources;
27  import com.flexstor.common.services.ServiceBrokerI;
28  import com.flexstor.common.services.SrvcNotAvailException;
29  import com.flexstor.flexdbserver.services.Service;
30  import com.flexstor.flexdbserver.services.ServiceContext;
31  import com.flexstor.flexdbserver.translog.TransactionImport;
32  
33  /**
34   * <P>
35   * DBUpdateService <BR>
36   * <BLOCKQUOTE>
37   *    Inserts or updates asset information in the database, creating the bucket structure if necessary.
38   *    The service first calls the DefaultViewService to assign a default displayable asset for each one
39   *    (if an asset has a default view already assigned, this service will not assign a new one). <BR>
40   *
41   *    This service is usually called during imports (from hot directories, from GUIs and html uploads)
42   *    and also when regenerating the thumbnail of an asset being checked in. Because of this, the DBUpdate
43   *    Service can handle the insert and updates of buckets, elements and assets. <BR>
44   *    The DB Update service delegates all the database operations to the DisguiseRecordPersist bean. <BR>
45   *    To determine whether an asset needs to be updated or inserted, the bean first looks if the asset
46   *    has a record id set in the data object; if it does, an update of such asset is performed, otherwise
47   *    an insert is done. <BR>
48   *    For buckets and elements the first step is to retrieve from the database its record id based on the
49   *    meta data set in the data object (NOTE: this operation is performed once outside the DB Update
50   *    Service- by the Import Processor -and later checked again by the DB Update Service). Later the
51   *    DisguiseRecordPersist bean will check if a record id has been set for the bucket or element in the
52   *    data object; if true it will use it to query the database and make sure it is already a row in the
53   *    table (a record id could be set by some other process without updating the database). If the record
54   *    id is already in the database an update is performed. In cases where the data object does not contain
55   *    a record id or when the record id in the data object does not exits in the bucket or element table,
56   *    an insert is performed. <BR>
57   *    Updates are performed for buckets and elements only if meta data is available. <BR>
58   *
59   *    NOTE: During a hot directory import to a bucket that already exists in the database, the
60   *    DisguiseRecordPersist bean updates the row in the database with meta data that is already set. This
61   *    is done because the import processor adds the sub-directories name as fields in the buckets' data object;
62   *    later the DisguiseRecordPersist bean checks if there is at least a field in the data object, and if so,
63   *    uses it to update the bucket. <BR>
64   * </BLOCKQUOTE>
65   * </P>
66   *
67   * Configurable Properties in roletype_services.config <BR>
68   *
69   * <P>
70   *   explicit_rollback_segment: If enabled, will explicitly allocate a dedicated rollback segment in the
71   *   database for this transaction (optional; defaults to false). <BR>
72   *   Legal values: true or false
73   * </P>
74   * <P>
75   * Input Data Object <BR>
76   * <BLOCKQUOTE>
77   *    com.flexstor.common.importprocessor.ImportData
78   * </BLOCKQUOTE>
79   * </P>
80   *
81   * <P>
82   * Output Data Object <BR>
83   * <BLOCKQUOTE>
84   *    com.flexstor.common.importprocessor.ImportResult
85   * </BLOCKQUOTE>
86   * </P>
87   *
88   * <P>
89   * Programmable Properties (passed inside data object) <BR>
90   * <BLOCKQUOTE>
91   *    Global Properties (apply to all assets) <BR>
92   * <BLOCKQUOTE>
93   *       bUpdateAssets: Signals whether the assets are for inserting or updating. Set in
94   *       ImportData.setUpdate( boolean value ) (defaults to false). <BR>
95   *       Data type: boolean <BR>
96   *       Legal values: true or false <BR>
97   * </BLOCKQUOTE>
98   * </BLOCKQUOTE>
99   * </P>
100  */
101 public class DBUpdateService
102    implements Service
103 {
104   public static final String IDENTIFIER = "$Id: DBUpdateService.java,v 1.4 2003/08/11 02:22:28 aleric Exp $";
105 
106   protected ImportData   data           = null;
107   
108   private   String           sThisService   = ""; 
109   protected   ServiceContext context;
110   protected   ServiceBrokerI serviceBroker;
111   protected   int               id = -1;
112 
113    public DBUpdateService()
114    {
115       super();
116    }
117 
118    /**
119     * Calls before the service is initialized (before initData is called) to 
120     * pass information about the environment in which the service is running.
121     * This environment consists of information about the properties set for the
122     * service in one of these files (services.config, roletype_services.config,
123     * or *.ctl), plus methods to access other information such as an instance
124     * of the service broker to invoke other services, the transaction id for
125     * the service, file separator character and local path for the installation
126     * directory and configuration directory.
127     * 
128     * @param context Holds information about the environment in which the service
129     *                is running.
130     */
131    public void setServiceContext( ServiceContext context )
132    {
133       this.context = context;
134       this.serviceBroker = context.getServiceBroker();
135    }
136    
137    /**
138     * Data initialization method called at the beginning of the service.
139     *
140     * @param ActionData is the super class of the ImportData wrapper object
141     *        which contains DisguiseRecords, which again contains more
142     *        DisguiseBucketRecord(s) and/or ElementRecord(s).  Finally
143     *         there are DisguiseAssetRecord(s) that is useful to extract
144     *         information for the preparation of DBUpdateService.
145     */
146    public void initData( ActionData actionData )
147    {
148       data = (ImportData)actionData;
149 
150       //6318=Database Update Service
151       sThisService = Resources.get(6318) + " (" + id + ")";
152    }
153 
154    /**
155     * Start of the  DBUpdateService.
156     *
157     * @return a Result object with the DBUpdate process results.
158     */
159    public ActionResult go()
160    {
161       // Check for assets; if no assets in data object, don't call the DefaultViewService,
162       // we are importing empty buckets
163       Vector vAssets = data.getDisguiseRecordRef().getPrimaryAssets();
164 
165       if ( vAssets != null && vAssets.size() > 0 )
166       {
167          ImportResult result = setDefaultViewAssets();
168          if ( result == null || !result.isSuccess() )
169             return new ImportResult(false);
170          else
171             data = result.getImportData();
172       }
173 
174       // Now do the import and return result
175       return importAssets();
176    }
177 
178    private ImportResult setDefaultViewAssets()
179    {
180       try
181       {
182          data.setServiceName( ServicesI.DEFAULTVIEW_SERVICE );
183          return ( ImportResult) serviceBroker.invokeImmediately(data);
184       }
185       catch( SrvcNotAvailException e )
186       {
187          data.addErrorRecord( new FlexError(FlexError.CRITICAL, sThisService, IDENTIFIER, e) );
188          return new ImportResult( false );
189       }
190    }
191 
192    private ImportResult importAssets()
193    {
194       DisguiseRecordData disguiseData = data.getDisguiseRecordRef();
195 
196       ImportRecordGateway importGateway = null;
197       try
198       {
199          importGateway = new ImportRecordGateway();
200          importGateway.connect();
201 
202          boolean bContinue = true;
203          // If this is an insert, first check for the existence of buckets, then do the insert
204          // and finaly do the transaction logging; otherwise just do an insertRecord to update
205          // the database; since during update all buckets already exist in the database.
206          boolean bInsert = !data.isUpdate();
207          if ( bInsert )
208          {
209             disguiseData = importGateway.checkForExisting(disguiseData);
210             Vector vErrors = disguiseData.getErrors();
211             if ( vErrors != null && vErrors.size() > 0 )
212             {
213                // The elements of the Vector are Strings of the following format:
214                //    1000,%%1,%%2,%%3
215                // where the first item is the resource id and the next, if any, are arguments 
216                // to be included in the resource
217                int nResourceId = -1;
218                String[] saArgs = null;
219                for ( Iterator i = vErrors.iterator(); i.hasNext(); )
220                {
221                   StringTokenizer st = new StringTokenizer( (String)i.next(), "," );
222                   nResourceId = Integer.parseInt( st.nextToken() );
223                   if ( st.hasMoreTokens() )
224                   {
225                      saArgs = new String[ st.countTokens() ]; // Remove resource id
226                      int j = 0;
227                      while ( st.hasMoreTokens() )
228                         saArgs[j++] = st.nextToken();
229                   }
230                }
231                data.addErrorRecord( new FlexError(FlexError.CRITICAL, sThisService, IDENTIFIER, nResourceId, saArgs ) );
232 
233                // Fail if there are not buckets to import
234                if ( disguiseData.getBucketsAsVector() == null || disguiseData.getBucketsAsVector().size() == 0 )
235                   bContinue = false;
236             }
237          }
238          
239          if ( bContinue )
240          {
241             // Lets find out if we need to explicitly allocate a rollback segment
242             String sAllocRollBackSgmnt = context.getProperty( "explicit_rollback_segment" );
243             if ( sAllocRollBackSgmnt != null && sAllocRollBackSgmnt.equalsIgnoreCase("true") )
244                disguiseData.setAllocateRollBackSegment(true);
245             else
246                disguiseData.setAllocateRollBackSegment(false);
247    
248             disguiseData = importGateway.insertRecord(disguiseData);
249             // Save back to the Import Data
250             data.setDisguiseRecordRef(disguiseData);
251    
252             if ( bInsert )
253                (new TransactionImport( data )).log();
254          }
255          
256          ImportResult result = new ImportResult(bContinue);
257          result.setImportData(data);
258          return result;
259       }
260       catch(TransactionFailedException rtfe)
261       {
262          return new ImportResult(false);
263       }
264       finally
265       {
266          if ( importGateway != null )
267             importGateway.dispose();
268       }
269    }
270 } // public class DBUpdateService