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


1   /*
2    * ImageInfoService.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.Enumeration;
14  import java.util.Vector;
15  
16  import com.flexstor.common.data.ActionData;
17  import com.flexstor.common.data.ActionResult;
18  import com.flexstor.common.data.ejb.disguiserecord.AssetRoleData;
19  import com.flexstor.common.data.ejb.disguiserecord.DisguiseAssetRecordData;
20  import com.flexstor.common.data.ejb.disguiserecord.DisguiseRecordData;
21  import com.flexstor.common.data.ejb.disguiserecord.ImageRoleData;
22  import com.flexstor.common.errorlogger.FlexError;
23  import com.flexstor.common.importprocessor.ImportCtlData;
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.ServiceArgumentsI;
28  import com.flexstor.common.settings.Settings;
29  import com.flexstor.common.util.Diagnostic;
30  import com.flexstor.common.util.FlexDbServerHost;
31  import com.flexstor.common.util.ServerList;
32  import com.flexstor.flexdbserver.importprocessor.ConversionOptions;
33  import com.flexstor.flexdbserver.services.Service;
34  import com.flexstor.flexdbserver.services.ServiceContext;
35  import com.flexstor.flexdbserver.services.io.ImportConvert;
36  
37  /**
38   * <P>
39   * AlchemyInfoService <BR>
40   * <BLOCKQUOTE>
41   *    Calls the Alchemy utility to obtain display information about an asset.
42   *     
43   *    Different image convert applications can be plugged into this service. <BR>
44   *    The service requires the following key/value pair lines as output of the command line 
45   *    application being invoked (this is an example): <BR>
46   *    <BLOCKQUOTE>
47   *                Type: JPEG <BR>
48   *                Mode: Truecolour <BR>
49   *                Width: 640 <BR>
50   *                Height: 430 <BR>
51   *                BitsPerPixel: 24 <BR>
52   *                DPIX: 72 <BR>
53   *                DPIY: 72 <BR>
54   *                FileSize: 203189 <BR>
55   *    </BLOCKQUOTE>
56   *    The result must be sent to standard output. <BR>
57   *    The keys do not required to be with the capitalization shown. <BR>
58   *    Make sure a colon is used, not an equal sign. <BR>
59   *    Note that DPIX and DPIY can be substituted with DPCX and DPCY if this values are given in 
60   *    centimeters rather than inches. <BR>
61   *    
62   * </BLOCKQUOTE>
63   * </P>
64   *
65   * Configurable Properties in roletype_services.config <BR>
66   *
67   * <TABLE BORDER="1" CELLPADDING="3" CELLSPACING="3">
68   * <CAPTION ALIGN=TOP>
69   *    <B> In/Out Properties for Assets </B>
70   * </CAPTION>
71   *     <TR>
72   *        <FONT SIZE=+1><B>
73   *        <TH WIDTH="120">Attribute</TH>
74   *                                   <TH WIDTH="30">IN</TH>           <TH WIDTH="30">OUT</TH>          <TH WIDTH="30">Default IN</TH>  <TH WIDTH="30">Default OUT</TH>
75   *        </B></FONT>
76   *     </TR>
77   *     <TR>
78   *        <TH ALIGN=LEFT><FONT SIZE=+1><B>ROLE</B></FONT></TH>
79   *                                   <TD ALIGN=CENTER> &nbsp </TD>    <TD ALIGN=CENTER> &nbsp </TD>    <TD ALIGN=CENTER> ALL </TD>      <TD ALIGN=CENTER> &nbsp </TD>
80   *     </TR>
81   *     <TR><TH> Highres </TH>        <TD ALIGN=CENTER> X </TD>        <TD ALIGN=CENTER> &nbsp </TD>    <TD ALIGN=CENTER> &nbsp </TD>    <TD ALIGN=CENTER> &nbsp </TD></TR>
82   *     <TR><TH> Lowres </TH>         <TD ALIGN=CENTER> X </TD>        <TD ALIGN=CENTER> &nbsp </TD>    <TD ALIGN=CENTER> &nbsp </TD>    <TD ALIGN=CENTER> &nbsp </TD></TR>
83   *     <TR><TH> Thumbnail </TH>      <TD ALIGN=CENTER> X </TD>        <TD ALIGN=CENTER> &nbsp </TD>    <TD ALIGN=CENTER> &nbsp </TD>    <TD ALIGN=CENTER> &nbsp </TD></TR>
84   *     <TR><TH> Layout </TH>         <TD ALIGN=CENTER> X </TD>        <TD ALIGN=CENTER> &nbsp </TD>    <TD ALIGN=CENTER> &nbsp </TD>    <TD ALIGN=CENTER> &nbsp </TD></TR>
85   *     <TR><TH> Video </TH>          <TD ALIGN=CENTER> &nbsp </TD>    <TD ALIGN=CENTER> &nbsp </TD>    <TD ALIGN=CENTER> &nbsp </TD>    <TD ALIGN=CENTER> &nbsp </TD></TR>
86   *     <TR><TH> Audio </TH>          <TD ALIGN=CENTER> &nbsp </TD>    <TD ALIGN=CENTER> &nbsp </TD>    <TD ALIGN=CENTER> &nbsp </TD>    <TD ALIGN=CENTER> &nbsp </TD></TR>
87   *     <TR>
88   *        <TH ALIGN=LEFT><FONT SIZE=+1><B>TYPE</B></FONT></TH>
89   *                                   <TD ALIGN=CENTER> X </TD>        <TD ALIGN=CENTER> &nbsp </TD>    <TD ALIGN=CENTER> ALL </TD>    <TD ALIGN=CENTER> &nbsp </TD></TR>
90   *     </TR>
91   *     <TR>
92   *        <TH ALIGN=LEFT><FONT SIZE=+1><B>FLAG</B></FONT></TH>
93   *     </TR>
94   *     <TR><TH> PARENT </TH>         <TD ALIGN=CENTER> X </TD>        <TD ALIGN=CENTER> &nbsp </TD>    <TD ALIGN=CENTER> X </TD>        <TD ALIGN=CENTER> &nbsp </TD></TR>
95   *     <TR><TH> CHLDREN </TH>        <TD ALIGN=CENTER> X </TD>        <TD ALIGN=CENTER> &nbsp </TD>    <TD ALIGN=CENTER> &nbsp </TD>    <TD ALIGN=CENTER> &nbsp </TD></TR>
96   *     <TR><TH> ALL </TH>            <TD ALIGN=CENTER> X </TD>        <TD ALIGN=CENTER> &nbsp </TD>    <TD ALIGN=CENTER> &nbsp </TD>    <TD ALIGN=CENTER> &nbsp </TD></TR>
97   *     <TR><TH> TEMP_PARENT </TH>    <TD ALIGN=CENTER> X </TD>        <TD ALIGN=CENTER> &nbsp </TD>    <TD ALIGN=CENTER> &nbsp </TD>    <TD ALIGN=CENTER> &nbsp </TD></TR>
98   *     <TR><TH> TEMP_CHILDREN </TH>  <TD ALIGN=CENTER> X </TD>        <TD ALIGN=CENTER> &nbsp </TD>    <TD ALIGN=CENTER> &nbsp </TD>    <TD ALIGN=CENTER> &nbsp </TD></TR>
99   *     <TR><TH> TEMP_ALL </TH>       <TD ALIGN=CENTER> X </TD>        <TD ALIGN=CENTER> &nbsp </TD>    <TD ALIGN=CENTER> &nbsp </TD>    <TD ALIGN=CENTER> &nbsp </TD></TR>
100  * </TABLE>
101  *
102  * <P>
103  *   configfile: Path to configuration file holding alchemy related parameters (optional; defaults
104  *   to the conversion.cfg file for the hot directory). <BR>
105  *   Legal values: Full path to configuration file
106  * </P>
107  *
108  * <P>
109  * Input Data Object <BR>
110  * <BLOCKQUOTE>
111  *    com.flexstor.common.importprocessor.ImportData
112  * </BLOCKQUOTE>
113  * </P>
114  *
115  * <P>
116  * Output Data Object <BR>
117  * <BLOCKQUOTE>
118  *    com.flexstor.common.importprocessor.ImportResult
119  * </BLOCKQUOTE>
120  * </P>
121  * Programmable Properties (passed inside data object) <BR>
122  * <BLOCKQUOTE>
123  *    Global Properties (apply to all assets) <BR>
124  * <BLOCKQUOTE>
125  * <P>
126  *       "intervaltimer_timeout" : 
127  *       A user-specified property in roletype_services.config that defines the timeout period for
128  *       the watch-dog timer that interrupts the Alchemy process if it hangs.
129  *       Data type: int <BR>
130  *       Legal values: time (seconds) <BR>
131  * </P>
132  * </BLOCKQUOTE>
133  * </BLOCKQUOTE>
134  */
135  
136 public class ImageInfoService
137    implements Service
138 {
139    // To get the version number from MKS
140    public final static String IDENTIFIER="$Id: ImageInfoService.java,v 1.6 2003/08/11 02:22:28 aleric Exp $";
141 
142    protected ServiceContext context;
143    protected String fileSeparator;
144    protected int id;
145    
146    private String     sThisService    = "";
147 
148    // Image File Attributes
149    private String sPrimaryFormat     = " ";
150    private String sPrimaryDPIX       = " ";
151    private String sPrimaryDPIY       = " ";
152    private String sPrimaryWidth      = " ";
153    private String sPrimaryHeight     = " ";
154    private String sPrimaryColorDepth = " ";
155    private String sPrimaryColorSpace = " ";
156    private String sPrimaryFileSize   = " ";
157 
158    private ConversionOptions refConversionOptions = null;
159 
160    // "1" = UNIX version, "0" = Windows version
161    private int    nOemAlchemy          = 1;  // default to UNIX
162    private String sTranslator          = "";
163    private String sConfigFile          = "";
164 
165    protected boolean   successful           = true;
166 
167    protected ImportCtlData refCtlData     = null;
168    protected ImportData    refImportData  = null;
169 
170 
171    /**
172     * Calls before the service is initialized (before initData is called) to 
173     * pass information about the environment in which the service is running.
174     * This environment consists of information about the properties set for the
175     * service in one of these files (services.config, roletype_services.config,
176     * or *.ctl), plus methods to access other information such as an instance
177     * of the service broker to invoke other services, the transaction id for
178     * the service, file separator character and local path for the installation
179     * directory and configuration directory.
180     * 
181     * @param context Holds information about the environment in which the service
182     *                is running.
183     */
184    public void setServiceContext( ServiceContext context )
185    {
186       this.context = context;
187       fileSeparator = context.getFileSeparator();
188       id = context.getTransactionId();
189    }
190    
191    /**
192    * A data initialization method called at the beginning of the service.
193    * The input argument, ActionData must be cast into its subclass, ImportData
194    * in order to extract the service specific data from it.
195    */
196    public void initData(ActionData actionData)
197    {
198       if ( (Settings.getString( Settings.SYSTEM_OS )).equals("UNIX") )
199          nOemAlchemy = 1; // tell Convert to use unixExecute()
200       else
201          nOemAlchemy = 0; // tell Convert to use dosExecute()
202 
203 
204       // cast the data object to a convert data wrapper
205       refImportData = (ImportData) actionData;
206 
207 
208       // Get the reference to the .CTL data object
209       refCtlData = refImportData.getCtlDataRef();
210 
211 
212       // Get the config file name defined in the services.config file; if one is not present
213       // use the one listed in the CTL data.
214       sConfigFile = context.getProperty( "configfile" );
215       if ( sConfigFile == null || sConfigFile.equals("") )
216          sConfigFile  = refCtlData.getValuePerKey("CONTROLFILESPATH") + refCtlData.getValuePerKey("CONFIGFILE");
217 
218       //6201=Alchemy Info Service
219       sThisService = Resources.get(6201) + " (" + id + ")";
220    } // initData
221 
222    /**
223    * The start of the Convert Service.
224    */
225    public ActionResult go()
226    {
227       Diagnostic.trace(Diagnostic.APPSERVER_SERVICES, "AlchemyInfoStarting");
228       // Need to read the .cfg conversion file to get all of the parameters
229       // that Alchemy needs to do the conversions
230       // If we could not read the config file return from the convert service.
231       // We already sent the response object back if it was necessary
232       if (!readCfgFile())
233       {
234          ImportResult response = new ImportResult(false);
235          //response.setText(CONVERT);
236          response.setImportData(refImportData);
237 
238          return response;
239       }
240 
241 
242       // Now that we have read in the .cfg file successfully, prepare to
243       // read in the input files and process them with Alchemy.
244       // If successful == false at least one file didn't convert correctly.
245       successful = true;
246 
247       // Get a reference to the DisguiseRecordData so we can get the assets
248       // Also get Role, Type and Flag values from property list (AssetService)
249       DisguiseRecordData refDisguiseRecordData = refImportData.getDisguiseRecordRef();
250       String sRole = context.getProperty(ServiceArgumentsI.ROLE_DATA_SOURCE);
251       String sType = context.getProperty(ServiceArgumentsI.TYPE_DATA_SOURCE);
252       String sFlag = context.getProperty(ServiceArgumentsI.FLAG_DATA_SOURCE);
253       Vector assetRecords =  null;
254 
255       Diagnostic.trace(Diagnostic.APPSERVER_SERVICES, "Role = " + sRole);
256       Diagnostic.trace(Diagnostic.APPSERVER_SERVICES, "Type = " + sType);
257       Diagnostic.trace(Diagnostic.APPSERVER_SERVICES, "Flag = " + sFlag);
258 
259       if(refDisguiseRecordData != null)
260       {
261          if(sRole == null || sType == null || sFlag == null)
262          {
263             successful = false;
264          }
265          else
266          { // Get the assets
267             assetRecords = refDisguiseRecordData.getAssets(sRole, sType, sFlag);
268             if(assetRecords != null)
269             {
270                Enumeration assets = assetRecords.elements();
271 
272                // Processs each asset in each element in ImportData as required
273                while(assets.hasMoreElements())
274                {
275                   DisguiseAssetRecordData anAsset = (DisguiseAssetRecordData)assets.nextElement();
276 
277                   Diagnostic.trace(Diagnostic.APPSERVER_SERVICES, "####### Calling GET INFO for " + sRole);
278                   // Get Info only
279                   if (getInfo(anAsset) == false)
280                   {
281                      // Hard error, quit now
282                      successful = false;
283                      break;
284                   }
285                }
286             }
287             else
288                successful = false;
289          }
290       }
291       else
292         successful = false;
293 
294       // pass back the ImportData
295       ImportResult response = new ImportResult(successful); // turn off default result
296       //response.setText(CONVERT);   // let the caller know what service for email
297       response.setImportData(refImportData);
298 
299       return response;
300    } // go()
301 
302 
303    /**
304    * Get Info
305    */
306    protected boolean getInfo(DisguiseAssetRecordData refSourceAsset)
307    {
308       if(refSourceAsset == null)
309          return false;
310 
311       Diagnostic.trace(Diagnostic.APPSERVER_SERVICES, "ImageConvert: Get Info for: " + refSourceAsset.getFileName());
312 
313       String  server = ServerList.getDNSName( refSourceAsset.getServer() );
314       
315       // Get the paths
316       Diagnostic.trace(Diagnostic.APPSERVER_SERVICES, "Creating the sInputPath...  The location and filename are: " +
317                          refSourceAsset.getLocation() + ", " + refSourceAsset.getFileName());
318       String sInputPath = refSourceAsset.getLocation() + refSourceAsset.getFileName();
319       if ( sInputPath.startsWith(fileSeparator) == false )
320          sInputPath = fileSeparator + sInputPath;
321 
322       // Get The Role Data to get the AssetType
323       AssetRoleData roleData = (AssetRoleData) refSourceAsset.getAssetRole();
324       // If the servername does not match the host name, it means that the file is on another
325       // filesystem and we shouldn't convert it.
326       if ( !FlexDbServerHost.isLocalHost( server ) )
327       {
328          successful = false;
329          //6202=Unable to get info for file: %%1. Server specified in asset record (%%2) does not match FlexDBServer host (%%3)
330          refImportData.addErrorRecord( new FlexError(FlexError.CRITICAL, sThisService, IDENTIFIER, 6202, (new String[] { sInputPath, server, FlexDbServerHost.getLocalHostName() })) );
331          return false;
332       }
333       else
334       {
335          String  sAssetType = null;
336          if(roleData != null)
337          {
338             sAssetType = roleData.getAssetFileType();
339             Diagnostic.trace(Diagnostic.APPSERVER_SERVICES, "sAssetType is: " + sAssetType);
340          }
341          if (sInputPath  != null)
342          {
343             // Set up the conversion options data structure
344             // Setup and process the element
345             if (processElement(sInputPath) == false)
346             {
347                //5519=Unable to convert input file: %%1
348                refImportData.addErrorRecord( new FlexError(FlexError.CRITICAL, sThisService, IDENTIFIER, 5519, (new String[] { sInputPath} )) );
349             }
350          } // if (sInputPath != null)
351          else
352          {
353             successful = false; // at least one file did not convert right
354             //5505=Null input file.
355             refImportData.addErrorRecord( new FlexError(FlexError.CRITICAL, sThisService, IDENTIFIER, 5505) );
356          }
357       } // ServerPath else
358 
359       // Set the file size if it isn't already set
360       if ( refSourceAsset.getFileSize() < 0 )
361          refSourceAsset.setFileSize( stringToLong(sPrimaryFileSize) );
362 
363       // Create the thumbnail asset and role if necessary
364       if ( roleData instanceof ImageRoleData )
365       {
366          ImageRoleData imageRoleData = (ImageRoleData) roleData;
367          Diagnostic.trace(Diagnostic.APPSERVER_SERVICES, "Setting values for " + roleData.getAssetFileType());
368          imageRoleData.setXRes( stringToFloat(sPrimaryDPIX) );
369          imageRoleData.setYRes( stringToFloat(sPrimaryDPIY) );
370          imageRoleData.setWidth( stringToFloat(sPrimaryWidth) );
371          imageRoleData.setHeight( stringToFloat(sPrimaryHeight) );
372          imageRoleData.setColorDepth( stringToFloat(sPrimaryColorDepth) );
373          imageRoleData.setColorSpace( sPrimaryColorSpace );
374 
375          Diagnostic.trace(Diagnostic.APPSERVER_SERVICES, "----> " + imageRoleData.getXRes() + ", " + imageRoleData.getYRes() + ", " + imageRoleData.getWidth()
376                             + ", " + imageRoleData.getHeight() + ", " + imageRoleData.getColorDepth() + ", " + imageRoleData.getColorSpace());
377       }
378       return true;
379    } // getInfo
380 
381    private boolean readCfgFile()
382    {
383       // Need to read the .cfg conversion file to get all of the parameters
384       // that Alchemy needs to do the conversions
385       refConversionOptions = new ConversionOptions(sConfigFile);
386       if ( refConversionOptions.processSection(false) )
387          return true; // we read the file OK so return true
388       else
389       {
390          //5521=Unable to read configuration input file: %%1
391          refImportData.addErrorRecord( new FlexError(FlexError.CRITICAL, sThisService, IDENTIFIER, 5521, (new String[] { sConfigFile })) );
392          return false;
393       }
394    } // readCfgFile()
395 
396 
397    /**
398    *
399    *
400    */
401    public boolean processElement(String sSourcePath)
402    {
403       // Setup translator path first, so if not found can quit now
404       sTranslator = refConversionOptions.getConversionItem("TRANSLATOR", "PATH");
405       if (sTranslator.equals("") == true)
406          return false;
407 
408       String sOptions = "";
409     // Get user-provided conversion options
410     String sUserOptions = refConversionOptions.getConversionItem("info", "OPTION");
411     
412     if ( sUserOptions != null )
413         sOptions = sUserOptions;
414 
415       // Info only
416       String[] saProcess = ImportConvert.createCommand( sTranslator, sSourcePath, null, sOptions );
417       if( getImageInfo(saProcess) == false )
418          return false;
419       return true;
420    } // processElement
421 
422    /**
423    *
424    */
425    protected boolean getImageInfo(String[] saCommandLine)
426    {
427       boolean bResult = true;
428 
429       // Get the user specified value for the watchdog timer interval
430       // Timeout value is specified in seconds
431       String sTimeOut = context.getProperty("intervaltimer_timeout");
432       // If the intervaltimer_timeout property wasn't set, check for the conversion_timeout
433       // property; this is left here for backward compatibility with release 3.0.6.0 
434       if ( sTimeOut == null )
435          sTimeOut = context.getProperty("conversion_timeout");
436             
437       ImportConvert refConvert = new ImportConvert();
438 
439       Diagnostic.trace(Diagnostic.APPSERVER_SERVICES, "Image Info: " + refConvert.toString(saCommandLine));
440       bResult = refConvert.executeConversion(saCommandLine, nOemAlchemy, sTimeOut);
441       if (bResult == true)
442       {
443          sPrimaryFormat     = refConvert.getFormat();
444          sPrimaryDPIX       = refConvert.getDPIX();
445          sPrimaryDPIY       = refConvert.getDPIY();
446          sPrimaryWidth      = refConvert.getWidth();
447          sPrimaryHeight     = refConvert.getHeight();
448          sPrimaryColorDepth = refConvert.getColorDepth();
449          sPrimaryColorSpace = refConvert.getColorMode();
450          sPrimaryFileSize   = refConvert.getFileSize();
451       }
452       return bResult;
453    } // getImageInfo
454 
455     private long stringToLong(String theString)
456     {
457        long returnVal = 0;
458        try{ returnVal = Long.valueOf(theString).longValue(); } catch(NumberFormatException e){};
459        return returnVal;
460     }
461 
462     private float stringToFloat(String theString)
463     {
464        float returnVal = 0;
465        try{ returnVal = Float.valueOf(theString).floatValue();} catch(NumberFormatException e){};
466        return returnVal;
467     }
468 
469    public String getPrimaryFormat()     { return sPrimaryFormat; }
470    public String getPrimaryWidth()      { return sPrimaryWidth;  }
471    public String getPrimaryHeight()     { return sPrimaryHeight; }
472    public String getPrimaryDPIX()       { return sPrimaryDPIX;   }
473    public String getPrimaryDPIY()       { return sPrimaryDPIY;   }
474    public String getPrimaryColorDepth() { return sPrimaryColorDepth; }
475    public String getPrimaryColorSpace() { return sPrimaryColorSpace; }
476    public String getPrimaryFileSize()   { return sPrimaryFileSize; }
477 } // ImageInfoService