Source code: com/flexstor/flexdbserver/services/checkincheckout/CheckOutServiceManager.java
1 /*
2 * CheckOutServiceManager.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.Vector;
14
15 import com.flexstor.common.constants.ActionPropertiesI;
16 import com.flexstor.common.constants.RsrcForkConstantsI;
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.AssetRecordData;
21 import com.flexstor.common.errorlogger.FlexError;
22 import com.flexstor.common.resources.Resources;
23 import com.flexstor.common.services.SrvcNotAvailException;
24 import com.flexstor.common.settings.Settings;
25 import com.flexstor.common.threadmgr.ThreadCallbackI;
26 import com.flexstor.common.util.FlexDbServerHost;
27 import com.flexstor.common.util.StringUtil;
28 import com.flexstor.flexdbserver.services.ServiceManager;
29 import com.flexstor.flexdbserver.util.PathAnalyzer;
30 import com.flexstor.flexdbserver.util.PathBuilder;
31
32 /**
33 * CheckOutServiceManager provides functionality to control the
34 * sequencial execution of Services during the check-in process
35 */
36 public class CheckOutServiceManager
37 extends ServiceManager
38 {
39 // To get the version number from MKS
40 public final static String IDENTIFIER="$Id: CheckOutServiceManager.java,v 1.3 2003/08/11 02:22:49 aleric Exp $";
41
42 protected String sServerName = "";
43 protected ActionData data = null;
44 protected Vector vRecords = null; //records to be processed
45 protected Vector vGoodRecords = new Vector(); //records successfully processed
46 protected Vector vBadRecords = new Vector(); //records unsuccessfully processed
47 protected String sSourcePath = null;
48 protected String sSourceServer = null;
49 protected String sSourceLocation = null;
50 protected boolean bIsLocationInServer = true;
51 protected boolean bIsLocInFlexDBServer = true;
52 protected boolean bKeepResourceFork = true;
53 protected boolean bIsMacBinaryFormat = false;
54 protected boolean bIsMacBinaryInTemp = false;
55 protected boolean bRunRemote = false;
56 protected String fileSeparator = "";
57 protected String sTempDir = "";
58 protected ActionData tempDataCopy = null;
59 protected ActionData tempDataRsrc = null;
60
61 public CheckOutServiceManager( String sIdentifier, ActionData data, ThreadCallbackI caller )
62 {
63 super( data, caller );
64 this.sServerName = sIdentifier;
65 this.data = data;
66 vRecords = data.getRecords();
67
68 // Here we should check if the server is the same as the AppServer where we are running;
69 // if it is, then instantiate local services; otherwise, use server name to instantiate
70 // services remotely.
71 /*String sDNSServer = ServerList.getDNSName( sServerName );
72 String sAppServerHost = Settings.getString( Settings.APP_SERVER_HOST );
73
74 if ( sDNSServer.equals( sAppServerHost ) == false )
75 bRunRemote = true;*/
76
77 // Get the system dependent file separator
78 fileSeparator = java.io.File.separator;
79 // Set the temporary directory to {FlexDBServer temp dir}/{trans_id}/
80 sTempDir = Settings.getString( Settings.APP_SERVER_TMP_DIR );
81 if ( !sTempDir.endsWith( fileSeparator ) )
82 sTempDir += fileSeparator;
83 sTempDir += data.getTransId() + fileSeparator;
84 }
85
86 /**
87 * Main loop for sequencial execution of Services.
88 */
89 public ActionResult execute()
90 throws InterruptedException
91 {
92 // Get the source location for files
93 // This is the location to move the files to
94 sSourceServer = data.getString( ActionPropertiesI.SOURCE_SERVER );
95
96 sSourceLocation = data.getString( ActionPropertiesI.SOURCE_LOCATION );
97 // If the SOURCE_LOCATION property holds a URL, then extract the server name and
98 // add it to the SOURCE_SERVER property
99 if ( sSourceLocation != null && PathAnalyzer.getRemoteFileProtocol(sSourceLocation) != null )
100 {
101 sSourceServer = PathAnalyzer.getServerName(sSourceLocation);
102 sSourceLocation = PathAnalyzer.getLocalPath(sSourceLocation);
103 data.setString( ActionPropertiesI.SOURCE_SERVER, sSourceServer );
104 data.setString( ActionPropertiesI.SOURCE_LOCATION, sSourceLocation );
105 }
106
107 sSourcePath = PathBuilder.constructPath( sSourceServer, sSourceLocation , true );
108
109 // If the source path is null then this is a remote server instance so
110 // move the files to the temp directory. They will be moved from there by the
111 // post processing on the originating server.
112 if (sSourcePath == null)
113 {
114 sSourceServer = FlexDbServerHost.getLocalHostName();
115 sSourceLocation = sTempDir;
116 sSourcePath = PathBuilder.constructPath( sSourceServer, sSourceLocation, true );
117 }
118
119 try
120 {
121 bIsLocationInServer = data.getBoolean( ActionPropertiesI.IS_LOCATION_IN_SERVER ).booleanValue();
122 bKeepResourceFork = data.getBoolean( ActionPropertiesI.KEEP_RESOURCEFORK ).booleanValue();
123 bIsMacBinaryFormat = data.getBoolean( ActionPropertiesI.MACBINARY_FORMAT ).booleanValue();
124 }
125 catch( NullPointerException npe ) {}
126
127 if ( sSourcePath != null )
128 {
129 // If bIsLocationInServer == true, determine if location is in the FlexDBServer or somewhere else
130 if ( bIsLocationInServer && !PathAnalyzer.isPathLocal( sSourcePath ) )
131 bIsLocInFlexDBServer = false;
132 else
133 sSourceServer = FlexDbServerHost.getLocalHostName();
134
135 AssetRecordData record;
136 // Prepare object in case we need to do a plain copy or resource fork copy
137 tempDataCopy = (ActionData) data.clone();
138 tempDataRsrc = (ActionData) data.clone();
139 tempDataCopy.setRecords( null );
140 tempDataRsrc.setRecords( null );
141
142 for ( int i = 0; i < vRecords.size(); i++ )
143 {
144 record = (AssetRecordData)vRecords.elementAt(i);
145 int nAppleTalkVendor = record.getAppleTalkVendor().intValue();
146
147 if ( !bIsLocationInServer )
148 {
149 // Destination is in client machine
150 record.setString( ActionPropertiesI.DESTINATION_SERVER, sSourceServer );
151 record.setString( ActionPropertiesI.DESTINATION_LOCATION, sSourceLocation );
152 // Reset DESTINATION_FILENAME to null. If the the restore service is called
153 // beforehands; it set this value with the *.bin extension
154 record.removeObject( ActionPropertiesI.DESTINATION_FILENAME );
155 if ( nAppleTalkVendor > RsrcForkConstantsI.NONE && bKeepResourceFork )
156 {
157 // Preserve resource fork (assume MacBinary will be created)
158 // Create MacBinary in temp location specified by client
159 tempDataRsrc.addRecord( record );
160 bIsMacBinaryFormat = true;
161 }
162 else
163 {
164 // Do not preserve resource fork
165 // Copy data fork in temp location specified by client
166 tempDataCopy.addRecord( record );
167 }
168 }
169 else if ( bIsLocInFlexDBServer )
170 {
171 // Destination is in FlexDBServer
172 record.setString( ActionPropertiesI.DESTINATION_SERVER, sSourceServer );
173 record.setString( ActionPropertiesI.DESTINATION_LOCATION, sSourceLocation );
174 // Reset DESTINATION_FILENAME to null. If the the restore service is called
175 // beforehands; it set this value with the *.bin extension
176 record.removeObject( ActionPropertiesI.DESTINATION_FILENAME );
177 if ( nAppleTalkVendor > RsrcForkConstantsI.NONE && bKeepResourceFork && bIsMacBinaryFormat )
178 {
179 // Create MacBinary in destination
180 tempDataRsrc.addRecord( record );
181 }
182 else
183 {
184 if ( nAppleTalkVendor > RsrcForkConstantsI.NONE && bKeepResourceFork )
185 // copy both data+rsrc fork
186 tempDataRsrc.addRecord( record );
187 else
188 // copy service will copy data fork only
189 tempDataCopy.addRecord( record );
190 }
191 }
192 else
193 {
194 // Destination is in another server
195 if ( nAppleTalkVendor > RsrcForkConstantsI.NONE && bKeepResourceFork )
196 {
197 // Preserve resource fork (assume MacBinary will be created)
198 // Create MacBinary in FlexDBServer's temp location
199 // NFS copy file to server
200 record.setDestinationLocation( sTempDir ); // Set the destination location to be the temp directory
201 tempDataRsrc.addRecord( record );
202 bIsMacBinaryFormat = true;
203 bIsMacBinaryInTemp = true;
204 }
205 else
206 {
207 // Do not preserve resource fork
208 // NFS copy data fork to server
209 record.setString( ActionPropertiesI.DESTINATION_SERVER, sSourceServer );
210 record.setString( ActionPropertiesI.DESTINATION_LOCATION, sSourceLocation );
211 // Reset DESTINATION_FILENAME to null. If the the restore service is called
212 // beforehands; it set this value with the *.bin extension
213 record.removeObject( ActionPropertiesI.DESTINATION_FILENAME );
214 tempDataCopy.addRecord( record );
215 }
216 }
217 }
218
219 // Before executing a service, we should check if an interrupt request has been
220 // placed, and if so, throw an InterruptedException to abort this operation
221 if ( abortManager() )
222 throw new InterruptedException();
223
224 // Execute resource fork service first, if the resource fork service fails to create the
225 // MacBinary for the files, then add them to the tempDataCopy to copy just the data forks
226 if ( tempDataRsrc.getRecords() != null )
227 RsrcForkCopy();
228
229 if ( tempDataCopy.getRecords() != null )
230 doRegularCopy();
231
232 updateURLs();
233 }
234 else
235 {
236 //6233=Check-Out Service
237 //6746=Check-Out Location is invalid; cannot proceed. ( %%1 )
238 new FlexError(FlexError.CRITICAL, Resources.get(6233), IDENTIFIER, 6746);
239 vBadRecords = vRecords;
240 }
241
242 ActionResult actionResult;
243 if ( vBadRecords.size() > 0 )
244 {
245 actionResult = new ActionResult(false);
246 actionResult.setBadRecords( vBadRecords );
247 }
248 else
249 actionResult = new ActionResult(true);
250
251 data.setRecords( vGoodRecords ); // Set vRecords with updated list
252 actionResult.setData( data );
253 actionResult.setId( data.getTransId() );
254
255 return actionResult;
256 }
257
258 /**
259 * Method updateURLs will process each record and update the URL_STRING for each,
260 * adding the filename to the URL_STRING base that was given to us by the client.
261 */
262 private void updateURLs()
263 {
264 for ( int i = 0; i < vGoodRecords.size(); i++ )
265 {
266 AssetRecordData record = (AssetRecordData)vGoodRecords.elementAt(i);
267 String sURL = record.getString( ActionPropertiesI.URL_STRING );
268 if ( sURL.endsWith("/") )
269 {
270 sURL = sURL + record.getFileName();
271 }
272 else
273 {
274 sURL = sURL + "/" + record.getFileName();
275 }
276 record.setString( ActionPropertiesI.URL_STRING, StringUtil.encodeURLString( sURL ) );
277 }
278 }
279
280 protected ActionResult getResultObjectOnAbnormalEnding()
281 {
282 // If vRecords contains records (not processed yet) set to bad
283 if ( vRecords.size() > 0 )
284 {
285 for ( int i = 0; i < vRecords.size(); i++ )
286 vBadRecords.addElement( (AssetRecordData)vRecords.elementAt(i) );
287 }
288
289 ActionResult actionResult = null;
290 if ( vBadRecords.size() > 0 )
291 {
292 actionResult = new ActionResult(false);
293 actionResult.setBadRecords( vBadRecords );
294 }
295 else
296 actionResult = new ActionResult(true);
297
298 actionResult.setId( data.getTransId() );
299 return actionResult;
300 }
301
302 private void RsrcForkCopy()
303 {
304 if ( bIsMacBinaryFormat )
305 tempDataRsrc.setInteger( ActionData.RESOURCEFORK_ACTION, new Integer(RsrcForkConstantsI.COMBINE_FORKS) );
306 else
307 tempDataRsrc.setInteger( ActionData.RESOURCEFORK_ACTION, new Integer(RsrcForkConstantsI.COPY_FORKS) );
308
309 ActionResult result = executeService( ServicesI.RESOURCEFORK_SERVICE, tempDataRsrc );
310 Vector vBad = null;
311 if ( result == null )
312 vBad = tempDataRsrc.getRecords();
313 else
314 {
315 vBad = result.getBadRecords();
316 vGoodRecords = result.getGoodRecords();
317 if ( vGoodRecords != null && vGoodRecords.size() > 0 )
318 {
319 AssetRecordData record;
320 for ( int i = 0; i < vGoodRecords.size(); i++ )
321 {
322 record = (AssetRecordData) vGoodRecords.elementAt(i);
323 // Remove from original Vector to indicate it has been processed
324 vRecords.removeElement( record );
325
326 if ( bIsMacBinaryInTemp )
327 {
328 record.setLocation( sTempDir );
329 record.setString( ActionPropertiesI.DESTINATION_SERVER, sSourceServer );
330 record.setString( ActionPropertiesI.DESTINATION_LOCATION, sSourceLocation );
331 // Reset DESTINATION_FILENAME to null. If the the restore service is called
332 // beforehands; it set this value with the *.bin extension
333 record.removeObject( ActionPropertiesI.DESTINATION_FILENAME );
334
335 // If the resource fork service was requested to create a MacBinary in the temp location,
336 // now copy the MacBinary (or data fork if service failed) to the destination location
337 record.setBoolean( ActionPropertiesI.KEEP_RESOURCEFORK, new Boolean(false) );
338 tempDataCopy.addRecord( record );
339 }
340 }
341 }
342 }
343 // If the resource fork service fails for all or some assets, add them to the copy service to copy the
344 // data fork only.
345 if ( vBad != null )
346 {
347 AssetRecordData record;
348 for ( int i = 0; i < vBad.size(); i++ )
349 {
350 record = (AssetRecordData)vBad.elementAt(i);
351 record.setBoolean( ActionPropertiesI.KEEP_RESOURCEFORK, new Boolean(false) );
352 record.setBoolean( ActionPropertiesI.MACBINARY_FORMAT, new Boolean(false) );
353 // If we were supposed to put the MacBinary in temp; update the destination location to the one assigned
354 // by the client, not the temp dir
355 if ( bIsMacBinaryInTemp )
356 {
357 record.setString( ActionPropertiesI.DESTINATION_SERVER, sSourceServer );
358 record.setString( ActionPropertiesI.DESTINATION_LOCATION, sSourceLocation );
359 // Reset DESTINATION_FILENAME to null. If the the restore service is called
360 // beforehands; it set this value with the *.bin extension
361 record.removeObject( ActionPropertiesI.DESTINATION_FILENAME );
362 }
363 tempDataCopy.addRecord( record );
364 }
365 }
366 }
367
368 private void doRegularCopy()
369 {
370 ActionResult result = executeService( ServicesI.COPY_SERVICE, tempDataCopy );
371
372 Vector vBad = new Vector();
373 Vector vGood = new Vector();
374
375 if ( result != null )
376 {
377 vBad = result.getBadRecords();
378 vGood = result.getGoodRecords();
379 }
380 else
381 vBad = tempDataCopy.getRecords();
382
383 if ( vBad != null && vBad.size() > 0 )
384 {
385 AssetRecordData badRecord;
386 for ( int i = 0; i < vBad.size(); i++ )
387 {
388 badRecord = (AssetRecordData)vBad.elementAt(i);
389 vBadRecords.addElement( badRecord );
390 vRecords.removeElement( badRecord );
391 }
392 }
393 if ( vGood != null && vGood.size() > 0 )
394 {
395 // check that vGoodRecords isn't null and initialize if it is
396 if ( vGoodRecords == null )
397 vGoodRecords = new Vector();
398
399 AssetRecordData goodRecord;
400 for ( int i = 0; i < vGood.size(); i++ )
401 {
402 goodRecord = (AssetRecordData)vGood.elementAt(i);
403 vGoodRecords.addElement( goodRecord );
404 vRecords.removeElement( goodRecord );
405 }
406 }
407 }
408
409 private ActionResult executeService( String sServiceName, ActionData data )
410 {
411 if ( bRunRemote )
412 sServiceName = sServiceName + "_" + sServerName;
413
414 try
415 {
416 return doService( sServiceName, data );
417 }
418 catch( SrvcNotAvailException e )
419 {
420 //6233=Check-Out Service
421 new FlexError(FlexError.CRITICAL, Resources.get(6233), IDENTIFIER, e);
422 return null;
423 }
424 }
425 }