Source Code Cross Referenced for LinkedRemoteFile.java in  » Net » DrFTPD » org » drftpd » remotefile » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Net » DrFTPD » org.drftpd.remotefile 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         * This file is part of DrFTPD, Distributed FTP Daemon.
0003:         *
0004:         * DrFTPD is free software; you can redistribute it and/or modify
0005:         * it under the terms of the GNU General Public License as published by
0006:         * the Free Software Foundation; either version 2 of the License, or
0007:         * (at your option) any later version.
0008:         *
0009:         * DrFTPD is distributed in the hope that it will be useful,
0010:         * but WITHOUT ANY WARRANTY; without even the implied warranty of
0011:         * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
0012:         * GNU General Public License for more details.
0013:         *
0014:         * You should have received a copy of the GNU General Public License
0015:         * along with DrFTPD; if not, write to the Free Software
0016:         * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
0017:         */
0018:        package org.drftpd.remotefile;
0019:
0020:        import java.io.FileNotFoundException;
0021:        import java.io.IOException;
0022:        import java.io.Serializable;
0023:        import java.util.ArrayList;
0024:        import java.util.Collection;
0025:        import java.util.Collections;
0026:        import java.util.Iterator;
0027:        import java.util.List;
0028:        import java.util.Map;
0029:        import java.util.Stack;
0030:        import java.util.StringTokenizer;
0031:
0032:        import net.sf.drftpd.FatalException;
0033:        import net.sf.drftpd.FileExistsException;
0034:        import net.sf.drftpd.NoAvailableSlaveException;
0035:        import net.sf.drftpd.ObjectNotFoundException;
0036:        import net.sf.drftpd.SlaveUnavailableException;
0037:        import net.sf.drftpd.master.config.ConfigInterface;
0038:        import net.sf.drftpd.master.config.FtpConfig;
0039:
0040:        import org.apache.log4j.Level;
0041:        import org.apache.log4j.Logger;
0042:        import org.drftpd.SFVFile;
0043:        import org.drftpd.id3.ID3Tag;
0044:        import org.drftpd.master.ConnectionManager;
0045:        import org.drftpd.master.RemoteSlave;
0046:        import org.drftpd.master.RemoteTransfer;
0047:        import org.drftpd.slave.RemoteIOException;
0048:        import org.drftpd.usermanager.User;
0049:
0050:        import se.mog.io.File;
0051:
0052:        /**
0053:         * Represents the file attributes of a remote file.
0054:         * 
0055:         * @author mog
0056:         * @version $Id: LinkedRemoteFile.java 1541 2006-12-16 17:42:04Z zubov $
0057:         */
0058:
0059:        public class LinkedRemoteFile implements  Serializable, Comparable,
0060:                LinkedRemoteFileInterface {
0061:            private static final Logger logger = Logger
0062:                    .getLogger(LinkedRemoteFile.class.getName());
0063:
0064:            static final long serialVersionUID = 3585958839961835107L;
0065:
0066:            private long _checkSum;
0067:
0068:            // cannot be generic cause CaseInsensitiveHashtable isn't generic
0069:            // it's used by slave when sending commands.
0070:            private CaseInsensitiveHashtable _files;
0071:
0072:            private transient ConfigInterface _ftpConfig;
0073:
0074:            private String _group;
0075:
0076:            // private Random rand = new Random();
0077:            // private String path;
0078:            private long _lastModified;
0079:
0080:            private long _length;
0081:
0082:            private String _link;
0083:
0084:            private String _name;
0085:
0086:            private String _owner;
0087:
0088:            private LinkedRemoteFile _parent;
0089:
0090:            // ///////////////////// SLAVES
0091:            protected List<RemoteSlave> _slaves;
0092:
0093:            private long _xfertime = 0;
0094:
0095:            protected SFVFile _sfvFile;
0096:
0097:            protected ID3Tag mp3tag;
0098:
0099:            /**
0100:             * Creates an empty RemoteFile directory, usually used as an empty root
0101:             * directory that <link>{merge()} </link> can be called on.
0102:             * 
0103:             * Used if no file database exists to start a tree from scratch.
0104:             */
0105:            public LinkedRemoteFile(ConfigInterface ftpConfig) {
0106:                _ftpConfig = ftpConfig;
0107:
0108:                _lastModified = System.currentTimeMillis();
0109:                _length = 0;
0110:                _parent = null;
0111:                _name = "";
0112:                _files = new CaseInsensitiveHashtable();
0113:                _slaves = null;
0114:            }
0115:
0116:            /**
0117:             * Creates a LinkedRemoteFile from file or creates a directory tree
0118:             * representation.
0119:             * 
0120:             * Used by DirectoryRemoteFile. Called by other constructor,
0121:             * ConnectionManager is null if called from Slave.
0122:             * 
0123:             * They all end up here.
0124:             * 
0125:             * @param parent
0126:             *            the parent of this file
0127:             * @param file
0128:             *            file that this RemoteFile object should represent.
0129:             */
0130:            private LinkedRemoteFile(LinkedRemoteFile parent,
0131:                    RemoteFileInterface file, ConfigInterface cfg) {
0132:                this (parent, file, file.getName(), cfg);
0133:            }
0134:
0135:            private LinkedRemoteFile(LinkedRemoteFile parent,
0136:                    RemoteFileInterface file, String name, ConfigInterface cfg) {
0137:                if (!ListUtils.isLegalFileName(name)) {
0138:                    throw new IllegalArgumentException("Illegal filename - "
0139:                            + parent.getPath() + "/" + name);
0140:                }
0141:
0142:                if (!file.isFile() && !file.isDirectory()) {
0143:                    throw new IllegalArgumentException(
0144:                            "File is not a file nor a directory: " + file);
0145:                }
0146:
0147:                if (_length == -1) {
0148:                    throw new IllegalArgumentException("length() == -1 for "
0149:                            + file);
0150:                }
0151:
0152:                _ftpConfig = cfg;
0153:                _lastModified = file.lastModified();
0154:                setOwner(file.getUsername());
0155:                setGroup(file.getGroupname());
0156:                _checkSum = file.getCheckSumCached();
0157:                _parent = parent;
0158:
0159:                if (file.isLink()) {
0160:                    _link = file.getLinkPath();
0161:                }
0162:
0163:                if (parent == null) {
0164:                    _name = "";
0165:                } else {
0166:                    _name = name;
0167:                }
0168:
0169:                if (file.isFile()) {
0170:                    _length = file.length();
0171:                    _xfertime = file.getXfertime();
0172:                    _slaves = Collections
0173:                            .synchronizedList(new ArrayList<RemoteSlave>(file
0174:                                    .getSlaves()));
0175:
0176:                    try {
0177:                        getParentFile().addSize(length());
0178:                    } catch (FileNotFoundException ok) {
0179:                        // thrown if this is the root dir
0180:                    }
0181:                } else if (file.isDirectory()) {
0182:                    // RemoteFileInterface dir[] = file.listFiles();
0183:                    // if (name != "" && dir.length == 0)
0184:                    // throw new FatalException(
0185:                    // "Constructor called with empty dir: " + file);
0186:                    _files = new CaseInsensitiveHashtable(file.getFiles()
0187:                            .size());
0188:
0189:                    Stack<RemoteFileInterface> dirstack = new Stack<RemoteFileInterface>();
0190:
0191:                    // for (int i = 0; i < dir.length; i++) {
0192:                    for (Iterator iter = file.getFiles().iterator(); iter
0193:                            .hasNext();) {
0194:                        RemoteFileInterface file2 = (RemoteFileInterface) iter
0195:                                .next();
0196:
0197:                        // RemoteFileInterface file2 = dir[i];
0198:                        if (file2.isDirectory()) {
0199:                            dirstack.push(file2);
0200:
0201:                            continue;
0202:                        }
0203:
0204:                        // the constructor takes care of addSize()
0205:                        _files.put(file2.getName(), new LinkedRemoteFile(this ,
0206:                                file2, _ftpConfig));
0207:                    }
0208:
0209:                    Iterator i = dirstack.iterator();
0210:
0211:                    while (i.hasNext()) {
0212:                        RemoteFileInterface file2 = (RemoteFileInterface) i
0213:                                .next();
0214:                        String filename = file2.getName();
0215:
0216:                        // the constructor takes care of addSize()
0217:                        _files.put(filename, new LinkedRemoteFile(this , file2,
0218:                                _ftpConfig));
0219:                    }
0220:                } else {
0221:                    throw new RuntimeException();
0222:                }
0223:
0224:                // parent == null if creating root dir
0225:            }
0226:
0227:            /**
0228:             * Creates a root directory (parent == null) that FileRemoteFile or
0229:             * JDOMRemoteFile is merged on.
0230:             * 
0231:             * Also called with null ConnectionManager from slave
0232:             */
0233:            public LinkedRemoteFile(RemoteFileInterface file, FtpConfig cfg)
0234:                    throws IOException {
0235:                this (null, file, cfg);
0236:            }
0237:
0238:            /**
0239:             * Updates lastModified() on this directory, use putFile() to avoid it.
0240:             */
0241:            public LinkedRemoteFile addFile(RemoteFileInterface file) {
0242:                _lastModified = System.currentTimeMillis();
0243:
0244:                return putFile(file);
0245:            }
0246:
0247:            protected void addSize(long size) {
0248:                if (isDirectory()) {
0249:                    synchronized (_files) {
0250:                        _length += size;
0251:                    }
0252:                } else {
0253:                    _length += size;
0254:                }
0255:
0256:                // logger.debug(
0257:                // this +" got " + size + " added, now " + _length,
0258:                // new Throwable());
0259:                try {
0260:                    getParentFile().addSize(size);
0261:                } catch (FileNotFoundException done) {
0262:                }
0263:            }
0264:
0265:            public void addSlave(RemoteSlave slave) {
0266:                if (isDirectory()) { // isDirectory()
0267:                    throw new IllegalStateException(
0268:                            "Cannot addSlave() on a directory");
0269:                }
0270:
0271:                if (slave == null) {
0272:                    throw new NullPointerException();
0273:                }
0274:
0275:                // we get lots of duplicate adds when merging and the slave is already
0276:                // in the file database
0277:                if (_slaves.contains(slave)) {
0278:                    return;
0279:                }
0280:
0281:                _slaves.add(slave);
0282:            }
0283:
0284:            /**
0285:             * @throws ClassCastException
0286:             *             if object is not an instance of RemoteFileInterface.
0287:             * @see java.lang.Comparable#compareTo(java.lang.Object)
0288:             */
0289:            public int compareTo(Object o) {
0290:                return getName().compareTo(((RemoteFileInterface) o).getName());
0291:            }
0292:
0293:            /**
0294:             * Follows links
0295:             */
0296:            public LinkedRemoteFile createDirectories(String path) {
0297:                NonExistingFile nef = lookupNonExistingFile(path);
0298:
0299:                if (nef.exists()) {
0300:                    try {
0301:                        LinkedRemoteFile temp = lookupFile(path);
0302:                        if (temp.isDirectory()) {
0303:                            return temp;
0304:                        }
0305:                        throw new RuntimeException(
0306:                                "Destination directory is already a file");
0307:                    } catch (FileNotFoundException e) {
0308:                        throw new RuntimeException(
0309:                                "createDirectories called on already existing directory that cannot be found");
0310:                    }
0311:                }
0312:
0313:                LinkedRemoteFile dir = nef.getFile();
0314:                StringTokenizer st = new StringTokenizer(nef.getPath(), "/");
0315:
0316:                while (st.hasMoreTokens()) {
0317:                    try {
0318:                        dir = dir.createDirectory(st.nextToken());
0319:                    } catch (FileExistsException e) {
0320:                        throw new RuntimeException(e);
0321:                    }
0322:                }
0323:
0324:                return dir;
0325:            }
0326:
0327:            public LinkedRemoteFile createDirectory(String fileName)
0328:                    throws FileExistsException {
0329:                return createDirectory(null, null, fileName);
0330:            }
0331:
0332:            public LinkedRemoteFile createDirectory(String owner, String group,
0333:                    String fileName) throws FileExistsException {
0334:                // LinkedRemoteFile existingfile = (LinkedRemoteFile)
0335:                // _files.get(fileName);
0336:                // //throws NullPointerException on non-existing directories
0337:                // if (existingfile.isDeleted())
0338:                // existingfile.delete();
0339:                // existingfile = (LinkedRemoteFile) _files.get(fileName);
0340:                if (hasFile(fileName)) {
0341:                    throw new FileExistsException(fileName
0342:                            + " already exists in this directory");
0343:                }
0344:
0345:                LinkedRemoteFile file = addFile(new StaticRemoteFile(null,
0346:                        fileName, owner, group, 0L, System.currentTimeMillis()));
0347:                logger.info("Created directory " + file);
0348:                _lastModified = System.currentTimeMillis();
0349:
0350:                return file;
0351:            }
0352:
0353:            private void setDeletedRecursive() {
0354:                if (isFile()) {
0355:                    _parent = null;
0356:                    _slaves.clear();
0357:                } else if (isDirectory()) {
0358:                    for (RemoteFileInterface victim : new ArrayList<RemoteFileInterface>(
0359:                            getFiles())) {
0360:                        if (victim instanceof  LinkedRemoteFile) {
0361:                            LinkedRemoteFile lrf = (LinkedRemoteFile) victim;
0362:                            lrf.setDeletedRecursive();
0363:                        }
0364:                    }
0365:                    _parent = null;
0366:                    _files.clear();
0367:                }
0368:            }
0369:
0370:            /**
0371:             * Deletes a file or directory, RemoteSlave handles issues with slaves being
0372:             * offline and queued deletes
0373:             * 
0374:             * Trying to lookupFile() or getFile() a deleted file throws
0375:             * FileNotFoundException.
0376:             */
0377:            public void delete() {
0378:                logger.debug("delete(" + getPath() + ")");
0379:
0380:                if (isDirectory()) {
0381:                    // need to use a copy of getFiles() for recursive delete to avoid
0382:                    // ConcurrentModificationErrors
0383:                    long tempLength = length();
0384:                    _length = 0;
0385:                    _ftpConfig.getGlobalContext().getSlaveManager()
0386:                            .deleteOnAllSlaves(this );
0387:                    try {
0388:                        getParentFile().getMap().remove(getName());
0389:
0390:                        // now need to remove size of directory from it's parent
0391:                        getParentFile().addSize(-tempLength);
0392:
0393:                    } catch (FileNotFoundException ex) {
0394:                        logger.log(Level.FATAL,
0395:                                "FileNotFoundException on getParentFile()", ex);
0396:                    }
0397:                    setDeletedRecursive();
0398:                    return;
0399:                }
0400:                if (_link == null) {
0401:                    // this.isFile() = true
0402:                    for (RemoteSlave rslave : new ArrayList<RemoteSlave>(
0403:                            _slaves)) {
0404:                        try {
0405:                            for (RemoteTransfer rtransfer : new ArrayList<RemoteTransfer>(
0406:                                    rslave.getTransfers())) {
0407:                                if (getPath().equalsIgnoreCase(
0408:                                        rtransfer.getPathNull())) {
0409:                                    rtransfer
0410:                                            .abort("File has been deleted on the master");
0411:                                }
0412:                            }
0413:                        } catch (SlaveUnavailableException e) {
0414:                            // nothing to do here, still want to delete it though
0415:                        }
0416:                    }
0417:                    _ftpConfig.getGlobalContext().getSlaveManager()
0418:                            .deleteOnAllSlaves(this );
0419:                    _slaves.clear();
0420:                } else {
0421:                    _link = null;
0422:                }
0423:
0424:                try {
0425:                    if (getParentFile().getMap().remove(getName()) == null) {
0426:                        logger.debug("Unable to remove " + getPath()
0427:                                + " from parent dir, already deleted?");
0428:                    }
0429:
0430:                    getParentFileNull().addSize(-length());
0431:                } catch (FileNotFoundException ex) {
0432:                    logger.log(Level.FATAL,
0433:                            "FileNotFoundException on getParentFile()", ex);
0434:                }
0435:            }
0436:
0437:            public void deleteFromSlave(RemoteSlave rslave) {
0438:                if (!_slaves.contains((rslave)))
0439:                    throw new IllegalArgumentException(
0440:                            "Cannot delete file from " + rslave.getName()
0441:                                    + " as it's not on it");
0442:                rslave.simpleDelete(getPath());
0443:                removeSlave(rslave);
0444:            }
0445:
0446:            public long dirSize() {
0447:                if (_files == null) {
0448:                    throw new IllegalStateException(
0449:                            "Cannot be called on a non-directory");
0450:                }
0451:
0452:                return _files.size();
0453:            }
0454:
0455:            public boolean equals(Object obj) {
0456:                if (obj instanceof  LinkedRemoteFileInterface
0457:                        && ((LinkedRemoteFileInterface) obj).getPath().equals(
0458:                                getPath())) {
0459:                    return true;
0460:                }
0461:
0462:                return false;
0463:            }
0464:
0465:            public Collection<RemoteSlave> getAvailableSlaves()
0466:                    throws NoAvailableSlaveException {
0467:                ArrayList<RemoteSlave> availableSlaves = new ArrayList<RemoteSlave>();
0468:
0469:                for (RemoteSlave rslave : getSlaves()) {
0470:
0471:                    if (!rslave.isAvailable()) {
0472:                        continue;
0473:                    }
0474:
0475:                    availableSlaves.add(rslave);
0476:                }
0477:
0478:                if (availableSlaves.isEmpty()) {
0479:                    throw new NoAvailableSlaveException(getPath()
0480:                            + " has 0 slaves online");
0481:                }
0482:
0483:                return availableSlaves;
0484:            }
0485:
0486:            /**
0487:             * Uses cached checksum if the cached checksum is not 0
0488:             */
0489:            public long getCheckSum() throws NoAvailableSlaveException {
0490:                if ((_checkSum == 0) && (_length != 0)) {
0491:                    _checkSum = getCheckSumFromSlave();
0492:
0493:                    if (_checkSum == 0) {
0494:                        throw new NoAvailableSlaveException(
0495:                                "Could not find a slave to check crc of "
0496:                                        + getPath());
0497:                    }
0498:                }
0499:
0500:                return _checkSum;
0501:            }
0502:
0503:            /**
0504:             * Returns the cached checksum or 0 if no checksum was cached.
0505:             * <p>
0506:             * Use {getCheckSum()} to automatically calculate checksum if no cached
0507:             * checksum is available.
0508:             */
0509:            public long getCheckSumCached() {
0510:                return _checkSum;
0511:            }
0512:
0513:            /**
0514:             * Returns 0 if the checksum cannot be read.
0515:             */
0516:            public long getCheckSumFromSlave() {
0517:                try {
0518:                    for (Iterator iter = getAvailableSlaves().iterator(); iter
0519:                            .hasNext();) {
0520:                        RemoteSlave slave = (RemoteSlave) iter.next();
0521:                        String index = null;
0522:
0523:                        try {
0524:                            index = slave.issueChecksumToSlave(getPath());
0525:                            _checkSum = slave.fetchChecksumFromIndex(index);
0526:                        } catch (RemoteIOException e2) {
0527:                            continue;
0528:                        } catch (SlaveUnavailableException e2) {
0529:                            continue;
0530:                        }
0531:
0532:                        return _checkSum;
0533:                    }
0534:                } catch (NoAvailableSlaveException e) {
0535:                    return 0;
0536:                }
0537:
0538:                return 0;
0539:            }
0540:
0541:            public Collection<LinkedRemoteFileInterface> getDirectories() {
0542:                Collection temp = getFiles();
0543:                ArrayList<LinkedRemoteFileInterface> retlist = new ArrayList<LinkedRemoteFileInterface>();
0544:
0545:                for (Iterator iter = temp.iterator(); iter.hasNext();) {
0546:                    LinkedRemoteFileInterface file = (LinkedRemoteFileInterface) iter
0547:                            .next();
0548:
0549:                    if (file.isDirectory()) {
0550:                        retlist.add(file);
0551:                    }
0552:                }
0553:
0554:                return retlist;
0555:            }
0556:
0557:            /**
0558:             * Returns fileName contained in this directory.
0559:             * 
0560:             * @param fileName
0561:             * @throws FileNotFoundException
0562:             *             if fileName doesn't exist in the files Map
0563:             */
0564:            public LinkedRemoteFileInterface getFile(String fileName)
0565:                    throws FileNotFoundException {
0566:                LinkedRemoteFileInterface file = (LinkedRemoteFileInterface) _files
0567:                        .get(fileName);
0568:
0569:                if (file == null) {
0570:                    throw new FileNotFoundException(
0571:                            "No such file or directory: " + fileName);
0572:                }
0573:
0574:                return file;
0575:            }
0576:
0577:            /**
0578:             * Returns a Collection of all the LinkedRemoteFile objects in this
0579:             * directory, with all .isDeleted() files removed.
0580:             * 
0581:             * <p>
0582:             * <b>NOTE: </b>Since DrFTPD 1.2, the collection returned can no longer be
0583:             * directly modified.
0584:             * 
0585:             * <p>
0586:             * Since this method overrides FileRemoteFile which is part of the classes
0587:             * that keep 1.4 compatibility for the slaves it cannot use generics.
0588:             * </p>
0589:             * 
0590:             * @return a Collection of all the LinkedRemoteFile objects in this
0591:             *         directory.
0592:             */
0593:            public Collection<LinkedRemoteFileInterface> getFiles2() {
0594:                if (_files == null) {
0595:                    throw new IllegalStateException("Isn't a directory");
0596:                }
0597:                return getFilesMap().values();
0598:            }
0599:
0600:            public Collection<RemoteFileInterface> getFiles() {
0601:                if (_files == null) {
0602:                    throw new IllegalStateException("Isn't a directory");
0603:                }
0604:                return getFilesMap().values();
0605:            }
0606:
0607:            /**
0608:             * Returns a map for this directory, having String name as key and
0609:             * LinkedRemoteFile file as value, with all .isDeleted() files removed.
0610:             * 
0611:             * <p>
0612:             * <b>NOTE: </b>Since DrFTPD 1.2, the map returned can no longer be directly
0613:             * modified.
0614:             * 
0615:             * @return map for this directory, having String name as key and
0616:             *         LinkedRemoteFile file as value, with all .isDeleted() files
0617:             *         removed.
0618:             */
0619:            private Map getFilesMap() {
0620:                return Collections.unmodifiableMap(_files);
0621:            }
0622:
0623:            public String getGroupname() {
0624:                if ((_group == null) || _group.equals("")) {
0625:                    return "drftpd";
0626:                }
0627:
0628:                return _group;
0629:            }
0630:
0631:            public LinkedRemoteFile getLink() throws FileNotFoundException {
0632:                return getParentFile().lookupFile(getLinkPath());
0633:            }
0634:
0635:            public String getLinkPath() {
0636:                if (_link == null) {
0637:                    throw new NullPointerException();
0638:                }
0639:
0640:                return _link;
0641:            }
0642:
0643:            /**
0644:             * Returns the underlying Map for this directory.
0645:             * 
0646:             * It is dangerous to modify without knowing what you're doing. Dirsize
0647:             * needs to be taken into account as well as sending approperiate commands
0648:             * to the slaves.
0649:             * 
0650:             * @return the underlying Map for this directory.
0651:             */
0652:            public Map getMap() {
0653:                return _files;
0654:            }
0655:
0656:            public String getName() {
0657:                return _name;
0658:            }
0659:
0660:            public String getParent() throws FileNotFoundException {
0661:                return getParentFile().getPath();
0662:            }
0663:
0664:            public LinkedRemoteFile getParentFile()
0665:                    throws FileNotFoundException {
0666:                if (_parent == null) {
0667:                    throw new FileNotFoundException(
0668:                            "root directory has no parent");
0669:                }
0670:
0671:                return _parent;
0672:            }
0673:
0674:            public LinkedRemoteFile getParentFileNull() {
0675:                return _parent;
0676:            }
0677:
0678:            public String getPath() {
0679:                StringBuffer path = new StringBuffer();
0680:                LinkedRemoteFileInterface parent = this ;
0681:
0682:                while (true) {
0683:                    if (parent.getName().length() == 0) {
0684:                        break;
0685:                    }
0686:
0687:                    path.insert(0, "/" + parent.getName());
0688:
0689:                    try {
0690:                        parent = parent.getParentFile();
0691:
0692:                        // throws FileNotFoundException
0693:                    } catch (FileNotFoundException ex) {
0694:                        break;
0695:                    }
0696:                }
0697:
0698:                if (path.length() == 0) {
0699:                    return "/";
0700:                }
0701:
0702:                return path.toString();
0703:            }
0704:
0705:            public LinkedRemoteFile getRoot() {
0706:                LinkedRemoteFile root = this ;
0707:
0708:                try {
0709:                    while (true)
0710:                        root = root.getParentFile();
0711:                } catch (FileNotFoundException ex) {
0712:                    return root;
0713:                }
0714:            }
0715:
0716:            public synchronized SFVFile getSFVFile() throws IOException,
0717:                    FileNotFoundException, NoAvailableSlaveException,
0718:                    FileStillTransferringException {
0719:
0720:                if (_xfertime == -1L) {
0721:                    throw new FileStillTransferringException();
0722:                }
0723:
0724:                if (_sfvFile == null) {
0725:                    Collection<RemoteSlave> availSlaves = new ArrayList<RemoteSlave>(
0726:                            getAvailableSlaves());
0727:                    for (RemoteSlave rslave : availSlaves) {
0728:                        try {
0729:                            String index = rslave
0730:                                    .issueSFVFileToSlave(getPath());
0731:                            _sfvFile = new SFVFile(rslave
0732:                                    .fetchSFVFileFromIndex(index));
0733:                            _sfvFile.setCompanion(this );
0734:
0735:                            return _sfvFile;
0736:                        } catch (RemoteIOException e) {
0737:                            if (e.getCause() instanceof  FileNotFoundException) {
0738:                                removeSlave(rslave);
0739:                                throw (FileNotFoundException) e.getCause();
0740:                            }
0741:
0742:                            throw (IOException) e.getCause();
0743:                        } catch (SlaveUnavailableException e) {
0744:                            continue;
0745:                        }
0746:                    }
0747:                    throw new NoAvailableSlaveException();
0748:                }
0749:
0750:                if (_sfvFile.size() == 0) {
0751:                    //TODO remove invalidation step, use file locking.
0752:                    _sfvFile = null; // no need to keep a worthless sfv file
0753:                    throw new FileNotFoundException(
0754:                            "sfv file contains no checksum entries");
0755:                }
0756:
0757:                return _sfvFile;
0758:            }
0759:
0760:            public synchronized ID3Tag getID3v1Tag()
0761:                    throws NoAvailableSlaveException, FileNotFoundException,
0762:                    IOException {
0763:                if (mp3tag == null) {
0764:                    logger.info("getID3v1Tag() : (file) " + getPath());
0765:
0766:                    while (true) {
0767:                        RemoteSlave rslave = null;
0768:                        if (isAvailable()) {
0769:                            Iterator<RemoteSlave> iter = getAvailableSlaves()
0770:                                    .iterator();
0771:                            if (!iter.hasNext()) {
0772:                                throw new NoAvailableSlaveException();
0773:                            }
0774:                            rslave = getAvailableSlaves().iterator().next();
0775:                        }
0776:
0777:                        if (rslave == null) {
0778:                            throw new NoAvailableSlaveException(
0779:                                    "no available slave for ID3Tag - "
0780:                                            + getPath());
0781:                        }
0782:
0783:                        try {
0784:                            String index = rslave.issueID3TagToSlave(getPath());
0785:                            mp3tag = rslave.fetchID3TagFromIndex(index);
0786:
0787:                            break;
0788:                        } catch (SlaveUnavailableException e) {
0789:                            continue;
0790:                        } catch (RemoteIOException e) {
0791:                            if (e.getCause() instanceof  FileNotFoundException) {
0792:                                removeSlave(rslave);
0793:                                throw (FileNotFoundException) e.getCause();
0794:                            }
0795:
0796:                            throw (IOException) e.getCause();
0797:                        }
0798:                    }
0799:                } else {
0800:                    logger.info("getID3v1Tag() : (cached) " + getPath());
0801:                }
0802:
0803:                if (mp3tag == null) {
0804:                    throw new IOException("No id3tag found for " + getPath());
0805:                }
0806:
0807:                return mp3tag;
0808:            }
0809:
0810:            /**
0811:             * returns slaves. throws exception if a directory.
0812:             */
0813:            public List<RemoteSlave> getSlaves() {
0814:                if (isDirectory()) {
0815:                    throw new IllegalStateException(
0816:                            "getSlaves() called on a directory: " + getPath());
0817:                }
0818:                return _slaves;
0819:            }
0820:
0821:            public String getUsername() {
0822:                if ((_owner == null) || _owner.equals("")) {
0823:                    return "nobody";
0824:                }
0825:
0826:                return _owner;
0827:            }
0828:
0829:            public long getXferspeed() {
0830:                if (getXfertime() <= 0) {
0831:                    return 0;
0832:                }
0833:
0834:                return (length() / getXfertime());
0835:            }
0836:
0837:            /**
0838:             * @return xfertime in milliseconds
0839:             */
0840:            public long getXfertime() {
0841:                return _xfertime;
0842:            }
0843:
0844:            /**
0845:             * Returns true if this directory contains a file named filename, this is
0846:             * case sensitive.
0847:             * 
0848:             * @param filename
0849:             *            The name of the file
0850:             * @return true if this directory contains a file named filename, this is
0851:             *         case sensitive.
0852:             */
0853:            public boolean hasFile(String filename) {
0854:                return _files.containsKey(filename);
0855:            }
0856:
0857:            public int hashCode() {
0858:                return getName().hashCode();
0859:            }
0860:
0861:            /**
0862:             * Returns true if this file or directory uses slaves that are currently
0863:             * offline.
0864:             * 
0865:             * @return true if this file or directory uses slaves that are currently
0866:             *         offline.
0867:             */
0868:            public boolean hasOfflineSlaves() {
0869:                if (isFile()) {
0870:                    for (Iterator iter = getSlaves().iterator(); iter.hasNext();) {
0871:                        RemoteSlave rslave = (RemoteSlave) iter.next();
0872:
0873:                        if (rslave == null) {
0874:                            throw new NullPointerException();
0875:                        }
0876:
0877:                        if (!rslave.isAvailable()) {
0878:                            return true;
0879:                        }
0880:                    }
0881:                } else if (isDirectory()) {
0882:                    for (Iterator iter = getFiles().iterator(); iter.hasNext();) {
0883:                        if (((LinkedRemoteFileInterface) iter.next())
0884:                                .hasOfflineSlaves()) {
0885:                            return true;
0886:                        }
0887:                    }
0888:                }
0889:
0890:                return false;
0891:            }
0892:
0893:            public boolean hasSlave(RemoteSlave slave) {
0894:                return _slaves.contains(slave);
0895:            }
0896:
0897:            /**
0898:             * Does file have online slaves?
0899:             * 
0900:             * @return Always true for directories
0901:             */
0902:            public boolean isAvailable() {
0903:                if (isDirectory()) {
0904:                    return true;
0905:                }
0906:                if (isLink()) {
0907:                    return true;
0908:                }
0909:
0910:                for (Iterator iter = getSlaves().iterator(); iter.hasNext();) {
0911:                    RemoteSlave rslave = (RemoteSlave) iter.next();
0912:
0913:                    if (rslave == null) {
0914:                        throw new RuntimeException();
0915:                    }
0916:
0917:                    if (rslave.isAvailable()) {
0918:                        return true;
0919:                    }
0920:                }
0921:
0922:                return false;
0923:            }
0924:
0925:            public boolean isDirectory() {
0926:                return (_files != null) && !isLink();
0927:            }
0928:
0929:            /**
0930:             * @return true if directory is empty.
0931:             */
0932:            private boolean isEmpty() {
0933:                if (_files == null) {
0934:                    throw new IllegalStateException("_files is null");
0935:                }
0936:
0937:                return _files.isEmpty();
0938:            }
0939:
0940:            public boolean isFile() {
0941:                return (_files == null) && (_slaves != null) && !isLink();
0942:            }
0943:
0944:            public boolean isLink() {
0945:                return _link != null;
0946:            }
0947:
0948:            public boolean isValid() {
0949:                if (_parent == null)
0950:                    return true;
0951:                try {
0952:                    if (_parent.getFile(getName()) == this  && _parent.isValid())
0953:                        return true;
0954:                    return false;
0955:                } catch (FileNotFoundException e) {
0956:                    return false;
0957:                }
0958:            }
0959:
0960:            public long lastModified() {
0961:                return _lastModified;
0962:            }
0963:
0964:            public long length() {
0965:                // if (isDirectory()) {
0966:                // long length = 0;
0967:                // for (Iterator iter = getFiles().iterator(); iter.hasNext();) {
0968:                // length += ((LinkedRemoteFile) iter.next()).length();
0969:                // }
0970:                // if (_length != 0 && length != _length)
0971:                // logger.warn(
0972:                // "",
0973:                // new Throwable(
0974:                // "Cached checksum missmatch: "
0975:                // + length
0976:                // + " != "
0977:                // + _length
0978:                // + " for "
0979:                // + toString()));
0980:                // _length = length;
0981:                // return length;
0982:                // }
0983:                if (_length < 0) {
0984:                    return 0;
0985:                }
0986:
0987:                return _length;
0988:            }
0989:
0990:            public LinkedRemoteFile lookupFile(String path)
0991:                    throws FileNotFoundException {
0992:                return lookupFile(path, true);
0993:            }
0994:
0995:            public LinkedRemoteFile lookupFile(String path, boolean followLinks)
0996:                    throws FileNotFoundException {
0997:                NonExistingFile ret = lookupNonExistingFile(path, followLinks);
0998:
0999:                if (!ret.exists()) {
1000:                    throw new FileNotFoundException(path + ": File not found");
1001:                }
1002:
1003:                return ret.getFile();
1004:            }
1005:
1006:            public NonExistingFile lookupNonExistingFile(String path) {
1007:                return lookupNonExistingFile(path, true);
1008:            }
1009:
1010:            public NonExistingFile lookupNonExistingFile(String path,
1011:                    boolean followLinks) {
1012:                if (path == null) {
1013:                    throw new IllegalArgumentException("null path not allowed");
1014:                }
1015:
1016:                if (path.equals("")) {
1017:                    return new NonExistingFile(this , null);
1018:                }
1019:
1020:                LinkedRemoteFile currFile = this ;
1021:
1022:                if (path.charAt(0) == '/') {
1023:                    currFile = getRoot();
1024:                }
1025:
1026:                // check for leading ~
1027:                if ((path.length() == 1) && path.equals("~")) {
1028:                    currFile = getRoot();
1029:                    path = "";
1030:                } else if ((path.length() >= 2)
1031:                        && path.substring(0, 2).equals("~/")) {
1032:                    currFile = getRoot();
1033:                    path = path.substring(2);
1034:                }
1035:
1036:                StringTokenizer st = new StringTokenizer(path, "/");
1037:
1038:                while (st.hasMoreTokens()) {
1039:                    String currFileName = st.nextToken();
1040:
1041:                    if (currFileName.equals(".")) {
1042:                        continue;
1043:                    }
1044:
1045:                    if (currFileName.equals("..")) {
1046:                        try {
1047:                            currFile = currFile.getParentFile();
1048:                        } catch (FileNotFoundException ex) {
1049:                        }
1050:
1051:                        continue;
1052:                    }
1053:
1054:                    LinkedRemoteFile nextFile;
1055:
1056:                    try {
1057:                        nextFile = (LinkedRemoteFile) currFile
1058:                                .getFile(currFileName);
1059:
1060:                        if (nextFile.isLink() && followLinks) {
1061:                            currFile = currFile.lookupFile(nextFile
1062:                                    .getLinkPath());
1063:                        } else {
1064:                            currFile = nextFile;
1065:                        }
1066:                    } catch (FileNotFoundException ex) {
1067:                        StringBuffer remaining = new StringBuffer(currFileName);
1068:
1069:                        if (st.hasMoreElements()) {
1070:                            remaining.append('/').append(st.nextToken(""));
1071:                        }
1072:
1073:                        return new NonExistingFile(currFile, remaining
1074:                                .toString());
1075:                    }
1076:                }
1077:
1078:                return new NonExistingFile(currFile, null);
1079:            }
1080:
1081:            /**
1082:             * Returns path for a non-existing file. Performs path normalization and
1083:             * returns an absolute path, follows links
1084:             */
1085:            public String lookupPath(String path) {
1086:                NonExistingFile ret = lookupNonExistingFile(path);
1087:
1088:                if (ret.exists()) {
1089:                    return ret.getFile().getPath();
1090:                }
1091:
1092:                return ret.getFile().getPath() + '/' + ret.getPath();
1093:            }
1094:
1095:            public SFVFile lookupSFVFile() throws IOException,
1096:                    FileNotFoundException, NoAvailableSlaveException,
1097:                    FileStillTransferringException {
1098:                if (!isDirectory()) {
1099:                    throw new IllegalStateException(
1100:                            "lookupSFVFile must be called on a directory");
1101:                }
1102:
1103:                for (Iterator iter = getFiles().iterator(); iter.hasNext();) {
1104:                    LinkedRemoteFileInterface myFile = (LinkedRemoteFileInterface) iter
1105:                            .next();
1106:
1107:                    if (myFile.getName().toLowerCase().endsWith(".sfv")
1108:                            && myFile.isFile()) {
1109:                        return myFile.getSFVFile();
1110:                    }
1111:                }
1112:
1113:                throw new FileNotFoundException("no sfv file in directory");
1114:            }
1115:
1116:            public String lookupMP3File() throws IOException,
1117:                    FileNotFoundException, NoAvailableSlaveException {
1118:                if (!isDirectory()) {
1119:                    throw new IllegalStateException(
1120:                            "lookupMP3File() must be called on a directory");
1121:                }
1122:
1123:                for (Iterator iter = getFiles().iterator(); iter.hasNext();) {
1124:                    LinkedRemoteFileInterface myFile = (LinkedRemoteFileInterface) iter
1125:                            .next();
1126:
1127:                    if (myFile.getName().toLowerCase().endsWith(".mp3")
1128:                            && myFile.isFile()) {
1129:                        return myFile.getPath();
1130:                    }
1131:                }
1132:
1133:                throw new FileNotFoundException("no mp3 file in directory");
1134:            }
1135:
1136:            /**
1137:             * Use addFile() if you want lastModified to be updated.
1138:             */
1139:            public LinkedRemoteFile putFile(RemoteFileInterface file) {
1140:                return putFile(file, file.getName());
1141:            }
1142:
1143:            /**
1144:             * @param torslave
1145:             *            RemoteSlave to replicate to.
1146:             */
1147:
1148:            // public void replicate(final RemoteSlave torslave)
1149:            // throws NoAvailableSlaveException, IOException {
1150:            //
1151:            // final RemoteSlave fromslave = getASlaveForDownload();
1152:            // Transfer fromtransfer = fromslave.getSlave().listen(false);
1153:            // final Transfer totransfer =
1154:            // torslave.getSlave().connect(
1155:            // new InetSocketAddress(
1156:            // fromslave.getInetAddress(),
1157:            // fromtransfer.getLocalPort()),
1158:            // false);
1159:            //
1160:            // Thread t = new Thread(new Runnable() {
1161:            // public void run() {
1162:            // try {
1163:            // totransfer.receiveFile(
1164:            // getParentFile().getPath(),
1165:            // 'I',
1166:            // getName(),
1167:            // 0L);
1168:            // } catch (RemoteException e) {
1169:            // torslave.handleRemoteException(e);
1170:            // logger.warn(EMPTY_STRING, e);
1171:            // } catch (FileNotFoundException e) {
1172:            // throw new FatalException(e);
1173:            // } catch (IOException e) {
1174:            // throw new RuntimeException(e);
1175:            // }
1176:            // }
1177:            // });
1178:            // t.start();
1179:            // fromtransfer.sendFile(getPath(), 'I', 0, false);
1180:            // }
1181:            /**
1182:             * @param toName
1183:             *            name argument to LinkedRemoteFile constructor
1184:             */
1185:            private LinkedRemoteFile putFile(RemoteFileInterface file,
1186:                    String toName) {
1187:                if (_files.containsKey(toName)) {
1188:                    throw new IllegalStateException(getPath() + "/" + toName
1189:                            + " already exists.");
1190:                }
1191:
1192:                // validate
1193:                if (file.isFile()) {
1194:                    if (file.getSlaves() == null) {
1195:                        throw new RuntimeException(file.toString());
1196:                    }
1197:
1198:                    for (Iterator iter = file.getSlaves().iterator(); iter
1199:                            .hasNext();) {
1200:                        if (iter.next() == null) {
1201:                            throw new RuntimeException();
1202:                        }
1203:                    }
1204:                }
1205:
1206:                // the constructor takes care of addSize()
1207:                LinkedRemoteFile linkedfile = new LinkedRemoteFile(this , file,
1208:                        toName, _ftpConfig);
1209:                _files.put(linkedfile.getName(), linkedfile);
1210:
1211:                return linkedfile;
1212:            }
1213:
1214:            /*    */
1215:
1216:            /**
1217:             * Merges mergedir directory onto <code>this</code> directories. If
1218:             * duplicates exist, the slaves are added to this object and the
1219:             * file-attributes of the oldest file (lastModified) are kept.
1220:             */
1221:
1222:            /*
1223:             * public void remerge(LinkedRemoteFile mergedir, RemoteSlave rslave) throws
1224:             * IOException { if (rslave == null) { throw new
1225:             * IllegalArgumentException("slave cannot be null"); }
1226:             * 
1227:             * if (mergedir == null) { throw new IllegalArgumentException("mergedir
1228:             * cannot be null"); }
1229:             * 
1230:             * if (!isDirectory()) { throw new IllegalArgumentException( "merge() called
1231:             * on a non-directory"); }
1232:             * 
1233:             * if (!mergedir.isDirectory()) { throw new
1234:             * IllegalArgumentException("argument is not a directory"); }
1235:             * 
1236:             * synchronized (_files) { // remove all slaves not in mergedir.getFiles() //
1237:             * unmerge() gets called on all files not on slave & all directories for
1238:             * (Iterator i = Collections.unmodifiableCollection( new
1239:             * ArrayList(_files.values())).iterator(); i.hasNext();) { LinkedRemoteFile
1240:             * file = (LinkedRemoteFile) i.next();
1241:             * 
1242:             * synchronized (file) { if (mergedir.hasFile(file.getName())) {
1243:             * LinkedRemoteFile mergefile = (LinkedRemoteFile)
1244:             * mergedir.getFile(file.getName());
1245:             * 
1246:             * if (file.isFile()) { if (file.length() == mergefile.length()) {
1247:             * file.addSlave(rslave); } else { //// conflict //// if (mergefile.length() ==
1248:             * 0) { logger.log(Level.INFO, "Deleting conflicting 0byte " + mergefile + "
1249:             * on " + rslave); rslave.simpleDelete(mergefile.getPath());
1250:             * file.unmergeFile(rslave); } else if ((file.getSlaves().size() == 1) &&
1251:             * (file.length() == 0)) { logger.info("Deleting conflicting 0byte " + file + "
1252:             * on " + rslave);
1253:             * 
1254:             * RemoteSlave rslave2 = (RemoteSlave) file.getSlaves() .iterator() .next();
1255:             * rslave2.simpleDelete(file.getPath()); } else { if
1256:             * (((file.getSlaves().size() == 1) && file.hasSlave(rslave))) { //we're the
1257:             * only slave with the file. file.setLength(mergefile.length());
1258:             * file.setCheckSum(0L); file.setLastModified(mergefile.lastModified()); }
1259:             * else { //// conflict, rename file... //// rslave.simpleRename(getPath() +
1260:             * "/" + mergefile.getName(), getPath(), mergefile.getName() + "." +
1261:             * rslave.getName() + ".conflict"); mergefile._name = mergefile._name + "." +
1262:             * rslave.getName() + ".conflict"; mergefile.addSlave(rslave);
1263:             * _files.put(mergefile.getName(), mergefile); logger.log(Level.WARN, "2 or
1264:             * more slaves contained same file with different sizes, renamed to " +
1265:             * mergefile.getName()); file.unmergeFile(rslave); } } } } else {
1266:             * file.remerge(mergefile, rslave); } // this is done so later new files can
1267:             * be merged without overhead of looking through already merged files
1268:             * mergedir.getMap().remove(mergefile.getName()); } else { // doesn't have
1269:             * file
1270:             * 
1271:             * if (file.isDirectory()) { file.unmergeDir(rslave); } else {
1272:             * file.unmergeFile(rslave); } } } }
1273:             * 
1274:             * for (Iterator iter = mergedir.getFiles().iterator(); iter.hasNext();) {
1275:             * LinkedRemoteFile newfile = (LinkedRemoteFile) iter.next();
1276:             * 
1277:             * try { getFile(newfile.getName());
1278:             * 
1279:             * continue; // local file exists } catch (FileNotFoundException good) { }
1280:             * 
1281:             * recursiveSetRSlaveAndConfig(newfile, _ftpConfig, rslave); newfile._parent =
1282:             * this; // already in _files? _files.put(newfile.getName(), newfile);
1283:             * logger.info(newfile.getPath() + " added from " + rslave.getName()); } } }
1284:             */
1285:
1286:            /**
1287:             * Shorthand for _slaves.remove() that checks if _slaves is empty and calls
1288:             * .delete() if it is.
1289:             */
1290:            public boolean removeSlave(RemoteSlave slave) {
1291:                if (isDirectory()) {
1292:                    throw new IllegalStateException(
1293:                            "Cannot removeSlave() on directory");
1294:                }
1295:
1296:                boolean ret = _slaves.remove(slave);
1297:
1298:                if (_slaves.isEmpty()) {
1299:                    delete();
1300:                }
1301:
1302:                return ret;
1303:            }
1304:
1305:            /**
1306:             * Renames this file
1307:             */
1308:            public void renameTo(String toDirPath, String toName)
1309:                    throws IOException, FileNotFoundException {
1310:                if (toDirPath.charAt(0) != '/') {
1311:                    throw new RuntimeException(
1312:                            "renameTo() must be given an absolute path as argument");
1313:                }
1314:
1315:                if (toName.indexOf('/') != -1) {
1316:                    throw new RuntimeException(
1317:                            "Cannot rename to non-existing directory");
1318:                }
1319:
1320:                if (_ftpConfig == null) {
1321:                    throw new RuntimeException("_ftpConfig is null: " + this );
1322:                }
1323:
1324:                LinkedRemoteFile toDir = lookupFile(toDirPath);
1325:                try {
1326:                    if (toDir.getFile(toName) != null) {
1327:                        throw new FileExistsException(toDirPath
1328:                                + File.separatorChar + toName
1329:                                + " already exists");
1330:                    }
1331:                } catch (FileNotFoundException e) {
1332:                    // this is good
1333:                }
1334:                // throws FileNotFoundException
1335:                {
1336:                    LinkedRemoteFile tmpDir = toDir;
1337:
1338:                    do {
1339:                        if (tmpDir == this ) {
1340:                            throw new IOException(
1341:                                    "Cannot rename into a subdirectory of self");
1342:                        }
1343:                    } while ((tmpDir = tmpDir.getParentFileNull()) != null);
1344:                }
1345:
1346:                /*		existed for old queued operations
1347:                 * 		// slaves are copied here too...
1348:                 LinkedRemoteFile toFile = toDir.putFile(this, toName);
1349:                 */
1350:                _parent._files.remove(getName());
1351:                _parent.addSize(-length());
1352:                if (isDirectory()) {
1353:                    _ftpConfig.getGlobalContext().getSlaveManager()
1354:                            .renameOnAllSlaves(getPath(), toDirPath, toName);
1355:                } else { // isFile()
1356:                    for (Iterator iter = new ArrayList<RemoteSlave>(getSlaves())
1357:                            .iterator(); iter.hasNext();) {
1358:                        RemoteSlave rslave = (RemoteSlave) iter.next();
1359:                        rslave.simpleRename(getPath(), toDirPath, toName);
1360:                    }
1361:                }
1362:                _name = toName;
1363:                _parent = toDir;
1364:                toDir._files.put(getName(), this );
1365:                toDir.addSize(length());
1366:            }
1367:
1368:            public void setCheckSum(long checkSum) {
1369:                _checkSum = checkSum;
1370:            }
1371:
1372:            public void setGroup(String group) {
1373:                _group = (group != null) ? group.intern() : null;
1374:            }
1375:
1376:            public void setLastModified(long lastModified) {
1377:                _lastModified = lastModified;
1378:            }
1379:
1380:            public void setLength(long length) {
1381:                getParentFileNull().addSize(length - _length);
1382:                _length = length;
1383:            }
1384:
1385:            public void setOwner(String owner) {
1386:                _owner = (owner != null) ? owner.intern() : null;
1387:            }
1388:
1389:            public void setXfertime(long xfertime) {
1390:                _xfertime = xfertime;
1391:            }
1392:
1393:            public String toString() {
1394:                StringBuffer ret = new StringBuffer();
1395:                ret.append("LinkedRemoteFile[\"" + this .getName() + "\",");
1396:
1397:                if (isFile()) {
1398:                    ret.append("xfertime:" + _xfertime + ",");
1399:                }
1400:
1401:                if (isLink()) {
1402:                    ret.append("link:" + getLinkPath() + ",");
1403:                }
1404:
1405:                // ret.append(slaves);
1406:                if (_slaves != null) {
1407:                    Iterator i = _slaves.iterator();
1408:
1409:                    // Enumeration e = slaves.elements();
1410:                    ret.append("slaves:[");
1411:
1412:                    // HACK: How can one find out the endpoint without using regexps?
1413:                    // Pattern p = Pattern.compile("endpoint:\\[(.*?):.*?\\]");
1414:                    while (i.hasNext()) {
1415:                        RemoteSlave rslave = (RemoteSlave) i.next();
1416:
1417:                        if (rslave == null) {
1418:                            throw new FatalException(
1419:                                    "There's a null in rslaves");
1420:                        }
1421:
1422:                        ret.append(rslave.getName());
1423:
1424:                        if (!rslave.isAvailable()) {
1425:                            ret.append("-OFFLINE");
1426:                        }
1427:
1428:                        if (i.hasNext()) {
1429:                            ret.append(",");
1430:                        }
1431:                    }
1432:
1433:                    ret.append("]");
1434:                }
1435:
1436:                if (isDirectory()) {
1437:                    ret.append("[directory(" + _files.size() + ")]");
1438:                }
1439:
1440:                ret.append("]");
1441:
1442:                return ret.toString();
1443:            }
1444:
1445:            public synchronized void unmergeDir(RemoteSlave rslave) {
1446:                if (!isDirectory()) {
1447:                    throw new IllegalStateException();
1448:                }
1449:
1450:                for (Iterator i = new ArrayList(_files.values()).iterator(); i
1451:                        .hasNext();) {
1452:                    LinkedRemoteFile file = (LinkedRemoteFile) i.next();
1453:
1454:                    if (file.isDirectory()) {
1455:                        boolean wasEmpty = file.isEmpty();
1456:                        file.unmergeDir(rslave);
1457:
1458:                        // remove empty directories that used to be non-empty
1459:                        if (file.isEmpty() && !wasEmpty) {
1460:                            file.delete();
1461:                        }
1462:                    } else if (file.isFile()) {
1463:                        file.unmergeFile(rslave);
1464:                    } // else isLink(), we don't remove links
1465:                }
1466:            }
1467:
1468:            public void unmergeFile(RemoteSlave rslave) {
1469:                if (!isFile()) {
1470:                    throw new IllegalStateException();
1471:                }
1472:
1473:                if (removeSlave(rslave)) {
1474:                    logger
1475:                            .warn(getPath() + " deleted from "
1476:                                    + rslave.getName());
1477:                }
1478:
1479:                // it's safe to remove it as it has no slaves.
1480:                // removeSlave() takes care of this
1481:                // if (file.getSlaves().size() == 0) {
1482:                // i.remove();
1483:                // getParentFileNull().addSize(-file.length());
1484:                // }
1485:            }
1486:
1487:            public boolean isDeleted() {
1488:                if (isDirectory()) {
1489:                    return (_parent == null && _name.equals(""));
1490:                }
1491:
1492:                return _slaves.isEmpty();
1493:            }
1494:
1495:            public void remerge(CaseInsensitiveHashtable lightRemoteFiles,
1496:                    RemoteSlave rslave) throws IOException {
1497:                if (!isDirectory()) {
1498:                    throw new RuntimeException(getPath()
1499:                            + " is not a directory");
1500:                }
1501:
1502:                for (Iterator iter = new ArrayList<LinkedRemoteFileInterface>(
1503:                        getFiles2()).iterator(); iter.hasNext();) {
1504:                    LinkedRemoteFile lrf = (LinkedRemoteFile) iter.next();
1505:
1506:                    if (lightRemoteFiles.containsKey(lrf.getName())) {
1507:                        LightRemoteFile light = (LightRemoteFile) lightRemoteFiles
1508:                                .remove(lrf.getName());
1509:                        if (light.isDirectory()) {
1510:                            // the directory still exists, we'll deal with it when
1511:                            // the slave sends that directory for remerge
1512:                            continue;
1513:                        }
1514:
1515:                        if (light.length() == lrf.length()) {
1516:                            lrf.addSlave(rslave);
1517:                        } else { // light.length() != lrf.length()
1518:                            if (light.length() == 0) {
1519:                                rslave.simpleDelete(lrf.getPath());
1520:                            } else if (lrf.getSlaves().size() == 1
1521:                                    && lrf.hasSlave(rslave)) {
1522:                                lrf.setLength(light.length());
1523:                                lrf.setCheckSum(0);
1524:                            } else {
1525:                                rslave.simpleRename(lrf.getPath(), lrf
1526:                                        .getParentFile().getPath(), lrf
1527:                                        .getName()
1528:                                        + "." + rslave.getName() + ".conflict");
1529:                                try {
1530:                                    LinkedRemoteFileInterface conflictFile = getFile(light
1531:                                            .getName()
1532:                                            + "."
1533:                                            + rslave.getName()
1534:                                            + ".conflict");
1535:                                    conflictFile.addSlave(rslave);
1536:                                } catch (FileNotFoundException e) {
1537:                                    ArrayList<RemoteSlave> list = new ArrayList<RemoteSlave>();
1538:                                    list.add(rslave);
1539:                                    addFile(new StaticRemoteFile(list, light
1540:                                            .getName()
1541:                                            + "."
1542:                                            + rslave.getName()
1543:                                            + ".conflict", "drftpd", "drftpd",
1544:                                            light.length(), light
1545:                                                    .lastModified()));
1546:                                }
1547:                            }
1548:                        }
1549:                    } else {
1550:                        if (lrf.isLink()) {
1551:                            continue;
1552:                        } else if (lrf.isFile()) {
1553:                            lrf.removeSlave(rslave);
1554:                        } else if (lrf.isDirectory()) {
1555:                            boolean wasEmpty = lrf.isEmpty();
1556:                            lrf.unmergeDir(rslave);
1557:                            if (lrf.isEmpty() && !wasEmpty) {
1558:                                lrf.delete();
1559:                                if (isEmpty()) {
1560:                                    delete();
1561:                                }
1562:                            }
1563:                        }
1564:                    }
1565:                }
1566:
1567:                for (Iterator iter = lightRemoteFiles.values().iterator(); iter
1568:                        .hasNext();) {
1569:                    LightRemoteFile light = (LightRemoteFile) iter.next();
1570:                    if (light.isDirectory()) {
1571:                        // ** new directory **
1572:                        // createDirectory so when remerge is called later with contents
1573:                        // the new directory exists
1574:                        createDirectory(light.getName());
1575:                        // if we set the directory to be old, when files are added, it will update the time correctly
1576:                        getFile(light.getName()).setLastModified(0);
1577:                        logger.debug("adding directory " + light.getName()
1578:                                + " from " + rslave.getName());
1579:                    } else {
1580:                        ArrayList<RemoteSlave> list = new ArrayList<RemoteSlave>();
1581:                        list.add(rslave);
1582:                        logger.debug("adding file " + light.getName()
1583:                                + " from " + rslave.getName());
1584:                        addFile(new StaticRemoteFile(list, light.getName(),
1585:                                "drftpd", "drftpd", light.length(), light
1586:                                        .lastModified()));
1587:                    }
1588:                }
1589:            }
1590:
1591:            public static class NonExistingFile {
1592:                private LinkedRemoteFile _file;
1593:
1594:                private String _path;
1595:
1596:                public NonExistingFile(LinkedRemoteFile file, String path) {
1597:                    _file = file;
1598:                    _path = path;
1599:                }
1600:
1601:                /**
1602:                 * Return true if getPath() returns a null value, i.e. <!-- --> returns
1603:                 * true if the file exists.
1604:                 */
1605:                public boolean exists() {
1606:                    return _path == null;
1607:                }
1608:
1609:                public LinkedRemoteFile getFile() {
1610:                    return _file;
1611:                }
1612:
1613:                public String getPath() {
1614:                    return _path;
1615:                }
1616:
1617:                public String toString() {
1618:                    return "[NonExistingFile:file=" + getFile().getPath()
1619:                            + ",path=" + getPath() + "]";
1620:                }
1621:            }
1622:
1623:            public static LinkedRemoteFile findLatestDir(
1624:                    ConnectionManager conn, LinkedRemoteFileInterface dir,
1625:                    User user, String searchstring)
1626:                    throws ObjectNotFoundException {
1627:                ArrayList<LinkedRemoteFile> dirs = findDirs(conn, dir, user,
1628:                        searchstring);
1629:                if (dirs.size() == 0) {
1630:                    throw new ObjectNotFoundException("dirs has size 0");
1631:                }
1632:                Collections.sort(dirs, new TimeComparator());
1633:                return dirs.get(0);
1634:            }
1635:
1636:            private static ArrayList<LinkedRemoteFile> findDirs(
1637:                    ConnectionManager conn, LinkedRemoteFileInterface dir,
1638:                    User user, String searchstring) {
1639:                ArrayList<LinkedRemoteFile> matchingDirs = new ArrayList<LinkedRemoteFile>();
1640:
1641:                if (!conn.getGlobalContext().getConfig().checkPathPermission(
1642:                        "privpath", user, dir, true)) {
1643:                    logger.debug("privpath: " + dir.getPath());
1644:                    return matchingDirs;
1645:                }
1646:
1647:                for (Iterator<LinkedRemoteFileInterface> iter = dir
1648:                        .getDirectories().iterator(); iter.hasNext();) {
1649:                    LinkedRemoteFileInterface file = iter.next();
1650:                    if (file.isDirectory()) {
1651:                        if (file.getName().toLowerCase().equals(
1652:                                searchstring.toLowerCase())) {
1653:                            logger.info("Found " + file.getPath());
1654:                            // The below cast is a hack, LinkedRemoteFileInterface needs
1655:                            // to be Comparable
1656:                            try {
1657:                                matchingDirs.add((LinkedRemoteFile) file);
1658:                            } catch (ClassCastException e) {
1659:                                // must be testing since LinkedRemoteFile is the only
1660:                                // non-testing class that implements
1661:                                // LinkedRemoteFileInterface
1662:                                continue;
1663:                            }
1664:                        }
1665:                        matchingDirs.addAll(findDirs(conn, file, user,
1666:                                searchstring));
1667:                    }
1668:                }
1669:                return matchingDirs;
1670:            }
1671:
1672:            public List<LinkedRemoteFileInterface> getAllParentFiles() {
1673:                List<LinkedRemoteFileInterface> parents = new ArrayList<LinkedRemoteFileInterface>();
1674:                parents.add(this );
1675:                LinkedRemoteFileInterface parent = this ;
1676:                while (true) {
1677:                    try {
1678:                        parents.add(parent = parent.getParentFile());
1679:                    } catch (FileNotFoundException e) {
1680:                        break;
1681:                    }
1682:                }
1683:                return parents;
1684:            }
1685:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.