KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > alfresco > filesys > server > smb > repo > ContentIOControlHandler


1 /*
2  * Copyright (C) 2006 Alfresco, Inc.
3  *
4  * Licensed under the Mozilla Public License version 1.1
5  * with a permitted attribution clause. You may obtain a
6  * copy of the License at
7  *
8  * http://www.alfresco.org/legal/license.txt
9  *
10  * Unless required by applicable law or agreed to in writing,
11  * software distributed under the License is distributed on an
12  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
13  * either express or implied. See the License for the specific
14  * language governing permissions and limitations under the
15  * License.
16  */

17 package org.alfresco.filesys.server.smb.repo;
18
19 import java.io.FileNotFoundException JavaDoc;
20
21 import org.alfresco.filesys.server.SrvSession;
22 import org.alfresco.filesys.server.filesys.DiskDeviceContext;
23 import org.alfresco.filesys.server.filesys.FileName;
24 import org.alfresco.filesys.server.filesys.IOControlNotImplementedException;
25 import org.alfresco.filesys.server.filesys.NetworkFile;
26 import org.alfresco.filesys.server.filesys.NotifyChange;
27 import org.alfresco.filesys.server.filesys.TreeConnection;
28 import org.alfresco.filesys.smb.NTIOCtl;
29 import org.alfresco.filesys.smb.SMBException;
30 import org.alfresco.filesys.smb.SMBStatus;
31 import org.alfresco.filesys.smb.server.repo.CifsHelper;
32 import org.alfresco.filesys.smb.server.repo.ContentDiskDriver;
33 import org.alfresco.filesys.smb.server.repo.IOControlHandler;
34 import org.alfresco.filesys.util.DataBuffer;
35 import org.alfresco.model.ContentModel;
36 import org.alfresco.service.cmr.coci.CheckOutCheckInService;
37 import org.alfresco.service.cmr.lock.LockType;
38 import org.alfresco.service.cmr.repository.ContentData;
39 import org.alfresco.service.cmr.repository.NodeRef;
40 import org.alfresco.service.cmr.repository.NodeService;
41 import org.alfresco.service.transaction.TransactionService;
42 import org.apache.commons.logging.Log;
43 import org.apache.commons.logging.LogFactory;
44
45 /**
46  * Content Disk Driver I/O Control Handler Class
47  *
48  * <p>Provides the custom I/O control code handling used by the CIFS client interface application.
49  *
50  * @author gkspencer
51  */

52 public class ContentIOControlHandler implements IOControlHandler
53 {
54     // Logging
55

56     private static final Log logger = LogFactory.getLog(ContentIOControlHandler.class);
57     
58     // Services and helpers
59

60     private CifsHelper cifsHelper;
61     private TransactionService transactionService;
62     private NodeService nodeService;
63     private CheckOutCheckInService checkInOutService;
64     
65     private ContentDiskDriver contentDriver;
66     
67     /**
68      * Default constructor
69      */

70     public ContentIOControlHandler()
71     {
72     }
73     
74     /**
75      * Initalize the I/O control handler
76      *
77      * @param contentDriver ContentDiskDriver
78      * @param cifsHelper CifsHelper
79      * @param transService TransactionService
80      * @param nodeService NodeService
81      * @param cociService CheckOutCheckInService
82      */

83     public void initialize( ContentDiskDriver contentDriver, CifsHelper cifsHelper,
84         TransactionService transService, NodeService nodeService, CheckOutCheckInService cociService)
85     {
86         this.contentDriver = contentDriver;
87         this.cifsHelper = cifsHelper;
88         this.transactionService = transService;
89         this.nodeService = nodeService;
90         this.checkInOutService = cociService;
91     }
92
93     /**
94      * Process a filesystem I/O control request
95      *
96      * @param sess Server session
97      * @param tree Tree connection.
98      * @param ctrlCode I/O control code
99      * @param fid File id
100      * @param dataBuf I/O control specific input data
101      * @param isFSCtrl true if this is a filesystem control, or false for a device control
102      * @param filter if bit0 is set indicates that the control applies to the share root handle
103      * @return DataBuffer
104      * @exception IOControlNotImplementedException
105      * @exception SMBException
106      */

107     public DataBuffer processIOControl(SrvSession sess, TreeConnection tree, int ctrlCode, int fid, DataBuffer dataBuf,
108             boolean isFSCtrl, int filter)
109         throws IOControlNotImplementedException, SMBException
110     {
111         // Validate the file id
112

113         NetworkFile netFile = tree.findFile(fid);
114         if ( netFile == null || netFile.isDirectory() == false)
115             throw new SMBException(SMBStatus.NTErr, SMBStatus.NTInvalidParameter);
116         
117         // Split the control code
118

119         int devType = NTIOCtl.getDeviceType(ctrlCode);
120         int ioFunc = NTIOCtl.getFunctionCode(ctrlCode);
121         
122         if ( devType != NTIOCtl.DeviceFileSystem || dataBuf == null)
123             throw new IOControlNotImplementedException();
124         
125         // Check if the request has a valid signature for an Alfresco CIFS server I/O control
126

127         if ( dataBuf.getLength() < IOControl.Signature.length())
128             throw new IOControlNotImplementedException("Bad request length");
129         
130         String JavaDoc sig = dataBuf.getString(IOControl.Signature.length(), false);
131         
132         if ( sig == null || sig.compareTo(IOControl.Signature) != 0)
133             throw new IOControlNotImplementedException("Bad request signature");
134         
135         // Get the node for the parent folder, make sure it is a folder
136

137         NodeRef folderNode = null;
138         
139         try
140         {
141             folderNode = contentDriver.getNodeForPath(tree, netFile.getFullName());
142             
143             if ( cifsHelper.isDirectory( folderNode) == false)
144                 folderNode = null;
145         }
146         catch ( FileNotFoundException JavaDoc ex)
147         {
148             folderNode = null;
149         }
150
151         // If the folder node is not valid return an error
152

153         if ( folderNode == null)
154             throw new SMBException(SMBStatus.NTErr, SMBStatus.NTAccessDenied);
155         
156         // Debug
157

158         if ( logger.isInfoEnabled()) {
159             logger.info("IO control func=0x" + Integer.toHexString(ioFunc) + ", fid=" + fid + ", buffer=" + dataBuf);
160             logger.info(" Folder nodeRef=" + folderNode);
161         }
162
163         // Check if the I/O control code is one of our custom codes
164

165         DataBuffer retBuffer = null;
166         
167         switch ( ioFunc)
168         {
169         // Probe to check if this is an Alfresco CIFS server
170

171         case IOControl.CmdProbe:
172             
173             // Return a buffer with the signature
174

175             retBuffer = new DataBuffer(IOControl.Signature.length());
176             retBuffer.putFixedString(IOControl.Signature, IOControl.Signature.length());
177             retBuffer.putInt(IOControl.StsSuccess);
178             break;
179             
180         // Get file information for a file within the current folder
181

182         case IOControl.CmdFileStatus:
183
184             // Process the file status request
185

186             retBuffer = procIOFileStatus( sess, tree, dataBuf, folderNode);
187             break;
188             
189         // Check-in file request
190

191         case IOControl.CmdCheckIn:
192             
193             // Process the check-in request
194

195             retBuffer = procIOCheckIn( sess, tree, dataBuf, folderNode, netFile);
196             break;
197             
198         // Check-out file request
199

200         case IOControl.CmdCheckOut:
201             
202             // Process the check-out request
203

204             retBuffer = procIOCheckOut( sess, tree, dataBuf, folderNode, netFile);
205             break;
206             
207         // Unknown I/O control code
208

209         default:
210             throw new IOControlNotImplementedException();
211         }
212         
213         // Return the reply buffer, may be null
214

215         return retBuffer;
216     }
217     
218     /**
219      * Process the file status I/O request
220      *
221      * @param sess Server session
222      * @param tree Tree connection
223      * @param reqBuf Request buffer
224      * @param folderNode NodeRef of parent folder
225      * @return DataBuffer
226      */

227     private final DataBuffer procIOFileStatus( SrvSession sess, TreeConnection tree, DataBuffer reqBuf, NodeRef folderNode)
228     {
229         // Start a transaction
230

231         sess.beginTransaction( transactionService, true);
232         
233         // Get the file name from the request
234

235         String JavaDoc fName = reqBuf.getString( true);
236         logger.info(" File status, fname=" + fName);
237
238         // Create a response buffer
239

240         DataBuffer respBuf = new DataBuffer(256);
241         respBuf.putFixedString(IOControl.Signature, IOControl.Signature.length());
242         
243         // Get the node for the file/folder
244

245         NodeRef childNode = null;
246         
247         try
248         {
249             childNode = cifsHelper.getNodeRef( folderNode, fName);
250         }
251         catch (FileNotFoundException JavaDoc ex)
252         {
253         }
254
255         // Check if the file/folder was found
256

257         if ( childNode == null)
258         {
259             // Return an error response
260

261             respBuf.putInt(IOControl.StsFileNotFound);
262             return respBuf;
263         }
264
265         // Check if this is a file or folder node
266

267         if ( cifsHelper.isDirectory( childNode))
268         {
269             // Only return the status and node type for folders
270

271             respBuf.putInt(IOControl.StsSuccess);
272             respBuf.putInt(IOControl.TypeFolder);
273         }
274         else
275         {
276             // Indicate that this is a file node
277

278             respBuf.putInt(IOControl.StsSuccess);
279             respBuf.putInt(IOControl.TypeFile);
280
281             // Check if this file is a working copy
282

283             if ( nodeService.hasAspect( childNode, ContentModel.ASPECT_WORKING_COPY))
284             {
285                 // Indicate that this is a working copy
286

287                 respBuf.putInt(IOControl.True);
288                 
289                 // Get the owner username and file it was copied from
290

291                 String JavaDoc owner = (String JavaDoc) nodeService.getProperty( childNode, ContentModel.PROP_WORKING_COPY_OWNER);
292                 String JavaDoc copiedFrom = null;
293                 
294                 if ( nodeService.hasAspect( childNode, ContentModel.ASPECT_COPIEDFROM))
295                 {
296                     // Get the path of the file the working copy was generated from
297

298                     NodeRef fromNode = (NodeRef) nodeService.getProperty( childNode, ContentModel.PROP_COPY_REFERENCE);
299                     if ( fromNode != null)
300                         copiedFrom = (String JavaDoc) nodeService.getProperty( fromNode, ContentModel.PROP_NAME);
301                 }
302                 
303                 // Pack the owner and copied from values
304

305                 respBuf.putString(owner != null ? owner : "", true, true);
306                 respBuf.putString(copiedFrom != null ? copiedFrom : "", true, true);
307             }
308             else
309             {
310                 // Not a working copy
311

312                 respBuf.putInt(IOControl.False);
313             }
314             
315             // Check the lock status of the file
316

317             if ( nodeService.hasAspect( childNode, ContentModel.ASPECT_LOCKABLE))
318             {
319                 // Get the lock type and owner
320

321                 String JavaDoc lockTypeStr = (String JavaDoc) nodeService.getProperty( childNode, ContentModel.PROP_LOCK_TYPE);
322                 String JavaDoc lockOwner = null;
323                 
324                 if ( lockTypeStr != null)
325                     lockOwner = (String JavaDoc) nodeService.getProperty( childNode, ContentModel.PROP_LOCK_OWNER);
326                 
327                 // Pack the lock type, and owner if there is a lock on the file
328

329                 if ( lockTypeStr == null)
330                     respBuf.putInt(IOControl.LockNone);
331                 else
332                 {
333                     LockType lockType = LockType.valueOf( lockTypeStr);
334                     
335                     respBuf.putInt(lockType == LockType.READ_ONLY_LOCK ? IOControl.LockRead : IOControl.LockWrite);
336                     respBuf.putString(lockOwner != null ? lockOwner : "", true, true);
337                 }
338             }
339             else
340             {
341                 // File is not lockable
342

343                 respBuf.putInt(IOControl.LockNone);
344             }
345             
346             // Get the content data details for the file
347

348             ContentData contentData = (ContentData) nodeService.getProperty( childNode, ContentModel.PROP_CONTENT);
349             
350             if ( contentData != null)
351             {
352                 // Get the content mime-type
353

354                 String JavaDoc mimeType = contentData.getMimetype();
355                 
356                 // Pack the content length and mime-type
357

358                 respBuf.putInt( IOControl.True);
359                 respBuf.putLong( contentData.getSize());
360                 respBuf.putString( mimeType != null ? mimeType : "", true, true);
361             }
362             else
363             {
364                 // File does not have any content
365

366                 respBuf.putInt( IOControl.False);
367             }
368         }
369         
370         // Return the response
371

372         return respBuf;
373     }
374     
375     /**
376      * Process the check in I/O request
377      *
378      * @param sess Server session
379      * @param tree Tree connection
380      * @param reqBuf Request buffer
381      * @param folderNode NodeRef of parent folder
382      * @param netFile NetworkFile for the folder
383      * @return DataBuffer
384      */

385     private final DataBuffer procIOCheckIn( SrvSession sess, TreeConnection tree, DataBuffer reqBuf, NodeRef folderNode,
386             NetworkFile netFile)
387     {
388         // Start a transaction
389

390         sess.beginTransaction( transactionService, false);
391         
392         // Get the file name from the request
393

394         String JavaDoc fName = reqBuf.getString( true);
395         boolean keepCheckedOut = reqBuf.getInt() == IOControl.True ? true : false;
396         
397         logger.info(" CheckIn, fname=" + fName + ", keepCheckedOut=" + keepCheckedOut);
398
399         // Create a response buffer
400

401         DataBuffer respBuf = new DataBuffer(256);
402         respBuf.putFixedString(IOControl.Signature, IOControl.Signature.length());
403         
404         // Get the node for the file/folder
405

406         NodeRef childNode = null;
407         
408         try
409         {
410             childNode = cifsHelper.getNodeRef( folderNode, fName);
411         }
412         catch (FileNotFoundException JavaDoc ex)
413         {
414         }
415
416         // Check if the file/folder was found
417

418         if ( childNode == null)
419         {
420             // Return an error response
421

422             respBuf.putInt(IOControl.StsFileNotFound);
423             return respBuf;
424         }
425
426         // Check if this is a file or folder node
427

428         if ( cifsHelper.isDirectory( childNode))
429         {
430             // Return an error status, attempt to check in a folder
431

432             respBuf.putInt(IOControl.StsBadParameter);
433         }
434         else
435         {
436             // Check if this file is a working copy
437

438             if ( nodeService.hasAspect( childNode, ContentModel.ASPECT_WORKING_COPY))
439             {
440                 try
441                 {
442                     // Check in the file
443

444                     checkInOutService.checkin( childNode, null, null, keepCheckedOut);
445
446                     // Check in was successful
447

448                     respBuf.putInt( IOControl.StsSuccess);
449                     
450                     // Check if there are any file/directory change notify requests active
451

452                     DiskDeviceContext diskCtx = (DiskDeviceContext) tree.getContext();
453                     if (diskCtx.hasChangeHandler()) {
454                         
455                         // Build the relative path to the checked in file
456

457                         String JavaDoc fileName = FileName.buildPath( netFile.getFullName(), null, fName, FileName.DOS_SEPERATOR);
458                         
459                         // Queue a file deleted change notification
460

461                         diskCtx.getChangeHandler().notifyFileChanged(NotifyChange.ActionRemoved, fileName);
462                     }
463                 }
464                 catch (Exception JavaDoc ex)
465                 {
466                     // Return an error status and message
467

468                     respBuf.setPosition( IOControl.Signature.length());
469                     respBuf.putInt(IOControl.StsError);
470                     respBuf.putString( ex.getMessage(), true, true);
471                 }
472             }
473             else
474             {
475                 // Not a working copy
476

477                 respBuf.putInt(IOControl.StsNotWorkingCopy);
478             }
479         }
480         
481         // Return the response
482

483         return respBuf;
484     }
485
486     /**
487      * Process the check out I/O request
488      *
489      * @param sess Server session
490      * @param tree Tree connection
491      * @param reqBuf Request buffer
492      * @param folderNode NodeRef of parent folder
493      * @param netFile NetworkFile for the folder
494      * @return DataBuffer
495      */

496     private final DataBuffer procIOCheckOut( SrvSession sess, TreeConnection tree, DataBuffer reqBuf, NodeRef folderNode,
497             NetworkFile netFile)
498     {
499         // Start a transaction
500

501         sess.beginTransaction( transactionService, false);
502         
503         // Get the file name from the request
504

505         String JavaDoc fName = reqBuf.getString( true);
506         
507         logger.info(" CheckOut, fname=" + fName);
508
509         // Create a response buffer
510

511         DataBuffer respBuf = new DataBuffer(256);
512         respBuf.putFixedString(IOControl.Signature, IOControl.Signature.length());
513         
514         // Get the node for the file/folder
515

516         NodeRef childNode = null;
517         
518         try
519         {
520             childNode = cifsHelper.getNodeRef( folderNode, fName);
521         }
522         catch (FileNotFoundException JavaDoc ex)
523         {
524         }
525
526         // Check if the file/folder was found
527

528         if ( childNode == null)
529         {
530             // Return an error response
531

532             respBuf.putInt(IOControl.StsFileNotFound);
533             return respBuf;
534         }
535
536         // Check if this is a file or folder node
537

538         if ( cifsHelper.isDirectory( childNode))
539         {
540             // Return an error status, attempt to check in a folder
541

542             respBuf.putInt(IOControl.StsBadParameter);
543         }
544         else
545         {
546             try
547             {
548                 // Check out the file
549

550                 NodeRef workingCopyNode = checkInOutService.checkout( childNode);
551
552                 // Get the working copy file name
553

554                 String JavaDoc workingCopyName = (String JavaDoc) nodeService.getProperty( workingCopyNode, ContentModel.PROP_NAME);
555                 
556                 // Check out was successful, pack the working copy name
557

558                 respBuf.putInt( IOControl.StsSuccess);
559                 respBuf.putString( workingCopyName, true, true);
560                 
561                 // Check if there are any file/directory change notify requests active
562

563                 DiskDeviceContext diskCtx = (DiskDeviceContext) tree.getContext();
564                 if (diskCtx.hasChangeHandler()) {
565                     
566                     // Build the relative path to the checked in file
567

568                     String JavaDoc fileName = FileName.buildPath( netFile.getFullName(), null, workingCopyName, FileName.DOS_SEPERATOR);
569                     
570                     // Queue a file added change notification
571

572                     diskCtx.getChangeHandler().notifyFileChanged(NotifyChange.ActionAdded, fileName);
573                 }
574             }
575             catch (Exception JavaDoc ex)
576             {
577                 // Return an error status and message
578

579                 respBuf.setPosition( IOControl.Signature.length());
580                 respBuf.putInt(IOControl.StsError);
581                 respBuf.putString( ex.getMessage(), true, true);
582             }
583         }
584         
585         // Return the response
586

587         return respBuf;
588     }
589 }
590
Popular Tags