[Yanel-dev] Many fixes for the Split Path Topic: Final Patch !

Balz Schreier balz.schreier at gmail.com
Fri Oct 29 23:55:02 CEST 2010


Skipped content of type multipart/alternative-------------- next part -----=
---------
Index: src/impl/java/org/wyona/yarep/impl/repo/vfs/VirtualFileSystemNode.ja=
va
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- src/impl/java/org/wyona/yarep/impl/repo/vfs/VirtualFileSystemNode.java	=
(revision 54229)
+++ src/impl/java/org/wyona/yarep/impl/repo/vfs/VirtualFileSystemNode.java	=
(working copy)
@@ -11,23 +11,17 @@
 import java.io.InputStream;
 import java.io.OutputStream;
 import java.io.PrintWriter;
+import java.util.ArrayList;
 import java.util.Arrays;
-import java.util.Calendar;
 import java.util.Date;
 import java.util.HashMap;
 import java.util.Iterator;
 import java.util.LinkedHashMap;
+import java.util.List;
 =

+import org.apache.commons.io.FileUtils;
 import org.apache.commons.io.IOUtils;
-import org.apache.commons.io.FileUtils;
 import org.apache.log4j.Logger;
-
-import org.apache.lucene.document.Document;
-import org.apache.lucene.document.Field;
-import org.apache.lucene.document.Field.Index;
-import org.apache.lucene.document.Field.Store;
-import org.apache.lucene.index.IndexWriter;
-
 import org.wyona.yarep.core.NoSuchRevisionException;
 import org.wyona.yarep.core.Node;
 import org.wyona.yarep.core.NodeStateException;
@@ -39,6 +33,7 @@
 import org.wyona.yarep.core.Revision;
 import org.wyona.yarep.core.UID;
 import org.wyona.yarep.core.attributes.VersionableV1;
+import org.wyona.yarep.core.impl.vfs.SplitPathConfig;
 import org.wyona.yarep.impl.AbstractNode;
 import org.wyona.yarep.impl.DefaultProperty;
 =

@@ -99,10 +94,15 @@
     protected void init() throws RepositoryException {
         =

         this.contentDir =3D getRepository().getContentDir();
-        this.contentFile =3D new File(this.contentDir, getRepository().spl=
itPath(this.uuid));
+        if (getRepository().getSplitPathConfig() =3D=3D null) {
+            throw new RepositoryException("Repository does not have a spli=
t path config instance! Make sure that Repository.init() is called before y=
ou use it!");
+        }
+        String maybeSplitPath =3D SplitPathConfig.splitPathIfRequired(this=
.uuid, getRepository().getSplitPathConfig());
+        this.contentFile =3D new File(this.contentDir, maybeSplitPath);
+        log.debug("New Node gets created: "+contentFile.getAbsolutePath());
         this.backupContentFile =3D new File(this.contentDir, this.uuid);
         =

-        String metauuid =3D getRepository().splitPath(uuid + META_DIR_SUFF=
IX);
+        String metauuid =3D SplitPathConfig.splitPathIfRequired(uuid + MET=
A_DIR_SUFFIX, getRepository().getSplitPathConfig());
         if (getRepository().getMetaDir() !=3D null) {
             this.metaDir =3D new File(getRepository().getMetaDir(), metauu=
id);
             this.backupMetaDir =3D new File(getRepository().getMetaDir(), =
uuid + META_DIR_SUFFIX);
@@ -242,10 +242,81 @@
     public Node[] getNodes() throws RepositoryException {
         Path[] childPaths;
         if (getRepository().isSplitPathEnabled()) {
-            // TODO: Unsplit paths
-            log.warn("TODO: Unsplit paths...");
-            childPaths =3D getRepository().getMap().getChildren(new Path(t=
his.path));
+            =

+            File startingDirectory =3D new File(contentDir + path);
+            log.warn("startingDirectory=3D "+startingDirectory);
+            if (!startingDirectory.exists()) {
+                log.warn("No such file or directory: " + startingDirectory=
);
+                childPaths =3D new Path[0];
+            }
+            if (startingDirectory.isFile()) {
+                log.warn("Can not get children form a file! : " + starting=
Directory);
+                childPaths =3D new Path[0];
+            }
+            =

+            // only if the current path belongs to a "include" path for th=
e split paths, we search ALL children, otherwise just the direct children
+            log.warn("Checking whether this path is include: "+path);
+            if (!SplitPathConfig.isIncludePath(path, getRepository().getSp=
litPathConfig())) {
+                childPaths =3D getRepository().getMap().getChildren(new Pa=
th(path));
+                =

+            } else {
+                List<File> allChildren =3D getAllFiles(startingDirectory);=
 // get all children from the location "this.path"
+                log.debug("Number of children: " + allChildren.size() + " =
(" + startingDirectory + ")");
+                List<Path> validChildrenPaths =3D new ArrayList<Path>();
+                String fileSepForRegEx =3D File.separator;
+                if (fileSepForRegEx.equals("\\")) {
+                    fileSepForRegEx =3D "\\\\"; // this is a double backsl=
ash, used for the regex later
+                }
+                =

+                for (File child: allChildren) {
+                    String childFullPath =3D child.getAbsolutePath().repla=
ceAll(fileSepForRegEx, "/"); // whatever the file separator was, yarep uses=
 "/"
+                    log.debug("startingDirectory=3D "+startingDirectory);
+                    log.debug("child =3D "+child.getAbsolutePath());
+                    if (childFullPath.startsWith(contentDir.getAbsolutePat=
h())) {
+                        String pathAndNode =3D childFullPath.substring(con=
tentDir.getAbsolutePath().length()); // =3D starts with this.path, e.g. "/p=
ath/node"
+                        log.debug("1. pathAndNode =3D "+pathAndNode);
+                        String unsplitPathAndNode =3D SplitPathConfig.unsp=
litPathIfRequired(pathAndNode, getRepository().getSplitPathConfig());
+                        String unsplitNode =3D unsplitPathAndNode.substrin=
g(path.length()); // we remove the path (prefix) from e.g. "/path/node.xml"=
 -> "/node.xml"
+                        log.debug("2. unsplitNode =3D "+unsplitNode);
+                        boolean ignore =3D ((org.wyona.yarep.impl.VFileSys=
temMapImpl) getRepository().getMap()).ignorePath(unsplitNode);
+                        if (!ignore) {
+                            String newPath =3D null;
+                            if (path.equals(File.separator)) {
+                                newPath =3D unsplitNode;
+                                if (!newPath.startsWith("/")) {
+                                    newPath =3D "/" + newPath;
+                                }
+                                log.debug("path was File separator. newPat=
h =3D "+newPath);
+                                =

+                            } else if (path.toString().endsWith(File.separ=
ator) || path.toString().endsWith("/")) {
+                                newPath =3D path.substring(0,path.length()=
-1);
+                                if (!unsplitNode.startsWith("/")) {
+                                    unsplitNode =3D "/" + unsplitNode;
+                                }
+                                newPath =3D path + unsplitNode;
+                                log.debug("path ended with a /. newPath =
=3D "+newPath.toString());
+                            } else {
+                                // NOTE: Do not use File.separator here, b=
ecause it's the repository path and not the Operating System's File System =
path
+                                if (!unsplitNode.startsWith("/")) {
+                                    unsplitNode =3D "/" + unsplitNode;
+                                }
+                                newPath =3D path + unsplitNode;
+                                log.debug("path does not end with a /. new=
Path =3D "+newPath.toString());
+                            }
+                            validChildrenPaths.add(new Path(newPath));
+                            log.warn("getNodes('"+path+"'): ADDED: "+unspl=
itNode);
+                       } else {
+                           log.warn("getNodes('"+path+"'): IGNORED: "+unsp=
litNode);
+                       }
+                     } else {
+                        log.error("Something is wrong: children are not wi=
thin parents!");
+                    }
+                }
+                childPaths =3D validChildrenPaths.toArray(new Path[validCh=
ildrenPaths.size()]);            =

+            } // end if-else: include or not
+
         } else {
+            // split path is not enabled
             childPaths =3D getRepository().getMap().getChildren(new Path(t=
his.path));
         }
         =

@@ -255,8 +326,30 @@
         }
         return childNodes;
     }
-    =

+
     /**
+     * =

+     * @param dir
+     * @return List of Files (directories are NOT in the list!)
+     */
+    private List<File> getAllFiles(File dir) {
+        List<File> result =3D new ArrayList<File>();
+        if (dir.isDirectory()) {
+            File[] filesAndDirsArray =3D dir.listFiles();
+            List<File> filesAndDirs =3D Arrays.asList(filesAndDirsArray);
+            for (File file : filesAndDirs) {
+                if (file.isFile()) {
+                    result.add(file);
+                } else {
+                    List<File> deeperList =3D getAllFiles(file);
+                    result.addAll(deeperList);
+                }
+            }
+        }
+        return result;
+    }
+
+    /**
      * @see org.wyona.yarep.core.Node#addNode(java.lang.String, int)
      */
     public Node addNode(String name, int type) throws RepositoryException {
@@ -264,11 +357,16 @@
         if (getPath().endsWith("/")) {
             newPath =3D getPath() + name;
         }
+        // in case the new node referenced by "name" is added to ROOT ("/"=
) we have to delete a potential / at the beginning:
+        if (newPath.startsWith("//")) {
+            newPath =3D newPath.substring(1);
+        }
         log.debug("adding node: " + newPath);
         if (this.repository.existsNode(newPath)) {
             throw new RepositoryException("Node exists already: " + newPat=
h);
         }
-        UID uid =3D getRepository().getMap().create(new Path(getRepository=
().splitPath(newPath)), type);
+        String maybeSplitPath =3D SplitPathConfig.splitPathIfRequired(newP=
ath, getRepository().getSplitPathConfig());
+        UID uid =3D getRepository().getMap().create(new Path(maybeSplitPat=
h), type);
         // create file:
         File file =3D new File(this.contentDir, uid.toString());
         try {
Index: src/impl/java/org/wyona/yarep/impl/repo/vfs/VirtualFileSystemReposit=
ory.java
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- src/impl/java/org/wyona/yarep/impl/repo/vfs/VirtualFileSystemRepository=
.java	(revision 54229)
+++ src/impl/java/org/wyona/yarep/impl/repo/vfs/VirtualFileSystemRepository=
.java	(working copy)
@@ -14,9 +14,6 @@
 import org.apache.avalon.framework.configuration.DefaultConfigurationBuild=
er;
 import org.apache.commons.io.IOUtils;
 import org.apache.log4j.Logger;
-import org.apache.lucene.analysis.Analyzer;
-import org.apache.lucene.index.IndexWriter;
-
 import org.wyona.commons.io.FileUtil;
 import org.wyona.yarep.core.Map;
 import org.wyona.yarep.core.NoSuchNodeException;
@@ -27,6 +24,7 @@
 import org.wyona.yarep.core.Revision;
 import org.wyona.yarep.core.Storage;
 import org.wyona.yarep.core.UID;
+import org.wyona.yarep.core.impl.vfs.SplitPathConfig;
 import org.wyona.yarep.core.search.Indexer;
 import org.wyona.yarep.core.search.SearchException;
 import org.wyona.yarep.core.search.Searcher;
@@ -115,11 +113,7 @@
 =

     // Configuration parameters of the <splitpath ...> element
     private boolean splitPathEnabled =3D false;
-    private int splitparts =3D 0;
-    private int splitlength =3D 0;
-    private String DEFAULT_DUMMY_SEPARATOR_VALUE =3D "-";
-    private String dummySeparator =3D DEFAULT_DUMMY_SEPARATOR_VALUE;
-    private String[] includepaths =3D {};
+    private SplitPathConfig splitPathConfig =3D new SplitPathConfig();
     =

     /**
      *
@@ -136,7 +130,7 @@
     }
 =

     /**
-     * Read respectively load repository configuration
+     * Load repository configuration
      */
     public void readConfiguration(File configFile) throws RepositoryExcept=
ion {
         this.configFile =3D configFile;
@@ -213,23 +207,22 @@
             Configuration splitConfig =3D config.getChild("splitpath", fal=
se);
             if (splitConfig !=3D null) {
                 splitPathEnabled =3D true;
-                String depth =3D splitConfig.getAttribute("depth", "0");
-                splitparts =3D Integer.parseInt(depth);
+                splitPathConfig.setSplitparts(Integer.parseInt(splitConfig=
.getAttribute("depth", "0")));
+                splitPathConfig.setSplitlength(Integer.parseInt(splitConfi=
g.getAttribute("length", "0")));
 =

-                String length;
-                length =3D splitConfig.getAttribute("length", "0");
-                splitlength =3D Integer.parseInt(length);
-
-                dummySeparator =3D splitConfig.getAttribute("escape", DEFA=
ULT_DUMMY_SEPARATOR_VALUE);
-
-                int c =3D splitConfig.getChildren("include").length;
-                int i =3D 0;
-                if (c > 0) {
-                    includepaths =3D new String[c];
+                int numberOfIncludePaths =3D splitConfig.getChildren("incl=
ude").length;
+                if (numberOfIncludePaths > 0) {
+                    String[] includepaths =3D new String[numberOfIncludePa=
ths];
+                    int i =3D 0;
                     for (Configuration include : splitConfig.getChildren("=
include")) {
                         includepaths[i++] =3D include.getAttribute("path");
                     }
+                    splitPathConfig.setIncludepaths(includepaths);
                 }
+                // NOTE: This repository uses the VFileSystemMapImpl: But =
we do not tell the map about the splitting.
+                //       Splitting is known to this repository and the nod=
e only.
+                // ((org.wyona.yarep.impl.VFileSystemMapImpl) map).setSpli=
tPathConfig(splitPathConfig);
+                // ((org.wyona.yarep.impl.VFileSystemMapImpl) map).setSpli=
tPathEnabled(true);
             } =

         } catch (Exception e) {
             log.error(e.toString());
@@ -291,12 +284,7 @@
         return delete(path);
     }
 =

-
-    /**
-     * @see org.wyona.yarep.core.Repository#exists(org.wyona.yarep.core.Pa=
th)
-     */
     public boolean exists(Path path) throws RepositoryException {
-        log.warn("DEPRECATED");
         return existsNode(path.toString());
     }
 =

@@ -401,7 +389,8 @@
             path =3D path.substring(0, path.length() - 1);
         }
         if (splitPathEnabled) {
-            return map.exists(new Path(splitPath(path))) || map.exists(new=
 Path(path)); // INFO: The OR is because of backwards compatibility in case=
 that a node exists with an unsplitted path, because it has not been migrat=
ed yet (which can happen if it has only been read so far, but never written=
 since introducing the split path configuration)
+            String maybeSplit =3D SplitPathConfig.splitPathIfRequired(path=
, splitPathConfig);
+            return map.exists(new Path(maybeSplit)) || map.exists(new Path=
(path));
         } else {
             return map.exists(new Path(path));
         }
@@ -416,7 +405,8 @@
             path =3D path.substring(0, path.length() - 1);
         }
 =

-        if ((splitPathEnabled && map.exists(new Path(splitPath(path)))) ||=
 map.exists(new Path(path))) {
+        String maybeSplit =3D SplitPathConfig.splitPathIfRequired(path, sp=
litPathConfig);
+        if ((splitPathEnabled && map.exists(new Path(maybeSplit))) || map.=
exists(new Path(path))) {
             String uuid =3D new UID(path).toString();
             return new VirtualFileSystemNode(this, path, uuid);
         } else {
@@ -609,98 +599,20 @@
         return true;
     }
 =

-    /**
-     * Splits a String such that the result can be used as a repo path for=
 a tree-like repo structure.
-     *
-     * This method splits off n strings (where n =3D parts) of length part=
length, e.g. if
-     * splitPath("ec2c0c02-1d7d-4a21-8a39-68f9f72dea09", 3, 4) is called, =
then:
-     * in:  ec2c0c02-1d7d-4a21-8a39-68f9f72dea09, 3, 4
-     * out: ec2c/0c02/-1d7/d-4a21-8a39-68f9f72dea09
-     *
-     * If the strings length is shorter than parts * partslength, then as =
many
-     * parts as possible are split, e.g.
-     * in:  foobar, 2, 5
-     * out: fooba/r
-     * in:  lorem, 3, 10
-     * out: lorem
-     *
-     * An example with "/" characters:
-     * in:  /foobar/lorem/ipsum.txt, parts =3D 3, lenght =3D 3
-     * out: /foo/bar/-lo/rem/ipsum.txt
-     *
-     * @param uuid
-     * @return split uuid
-     */
-    String splitPath(String path) {
-        // NOTE: uuid should be a full yarep path, so we can safely remove
-        // the leading slash
-        =

-        // check if the given path matches any of the include values
-        // in the configuration
-        boolean include =3D false;
-        String base =3D "";
-        for (String s : includepaths) {
-            if (path.startsWith(s)) {
-                include =3D true;
-                base =3D s;
-                break;
-            }
-        }
+    public SplitPathConfig getSplitPathConfig() {
+        return splitPathConfig;
+    }
 =

-        // return the path unchanged if it doesn't match
-        // any of the include values
-        if (!include) {
-            return path;
-        }
-        =

-        // remove the leading base string, will be added again later
-        path =3D path.substring(base.length(), path.length());
-
-        // replace "/" characters where needed
-        if (path.length() <=3D splitparts * splitlength) {
-            path =3D path.replaceAll("/", dummySeparator);
-        } else {
-            path =3D String.format("%s%s",
-                    path.substring(0, splitparts * splitlength).replaceAll=
("/", dummySeparator),
-                    path.substring(splitparts * splitlength));
-        }
-
-        // now do the actual splitting
-        int len =3D path.length();
-        int pos =3D 0;
-        String out =3D "";
-
-        int partc =3D 0;
-        int w;
-        while (len > 0 && partc < splitparts) {
-            partc++;
-            if (len < splitlength) {
-                w =3D len;
-            } else {
-                w =3D splitlength;
-            }
-            out +=3D path.substring(pos, pos + w);
-            pos +=3D w;
-            len -=3D w;
-
-            if (len > 0) {
-                out +=3D "/";
-            }
-        }
-
-        // append remainder
-        if (len > 0) {
-            out +=3D path.substring(pos, pos + len);
-        }
-
-        // finally, add the leading zero again and return the new path
-        return base + out;
+    public void setSplitPathConfig(SplitPathConfig splitPathConfig) {
+        this.splitPathConfig =3D splitPathConfig;
     }
 =

-    /**
-     * Check whether split path is enabled and make this available to clas=
ses within this package
-     */
-    boolean isSplitPathEnabled() {
+    public boolean isSplitPathEnabled() {
         return splitPathEnabled;
     }
+
+    public void setSplitPathEnabled(boolean splitPathEnabled) {
+        this.splitPathEnabled =3D splitPathEnabled;
+    }
+
 }
Index: src/impl/java/org/wyona/yarep/impl/VFileSystemMapImpl.java
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- src/impl/java/org/wyona/yarep/impl/VFileSystemMapImpl.java	(revision 54=
229)
+++ src/impl/java/org/wyona/yarep/impl/VFileSystemMapImpl.java	(working cop=
y)
@@ -1,23 +1,22 @@
 package org.wyona.yarep.impl;
 =

+import java.io.File;
+import java.io.FilenameFilter;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
 import org.apache.avalon.framework.configuration.Configuration;
-
+import org.apache.log4j.Category;
 import org.wyona.commons.io.FileUtil;
 import org.wyona.yarep.core.Map;
 import org.wyona.yarep.core.Path;
 import org.wyona.yarep.core.RepositoryException;
 import org.wyona.yarep.core.UID;
+import org.wyona.yarep.core.impl.vfs.SplitPathConfig;
 =

-import java.io.File;
-import java.io.FileReader;
-import java.io.FileWriter;
-import java.io.BufferedReader;
-import java.io.FilenameFilter;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-import org.apache.log4j.Category;
-
 /**
  *
  */
@@ -29,7 +28,11 @@
     protected Pattern[] ignorePatterns;
     protected ChildrenFilter childrenFilter =3D new ChildrenFilter();
     =

+    // Configuration parameters of the <splitpath ...> element
+    private boolean splitPathEnabled =3D false;
+    private SplitPathConfig splitPathConfig =3D new SplitPathConfig();
 =

+
     /**
      *
      */
@@ -41,6 +44,27 @@
                 Configuration[] ignoreElements =3D mapConfig.getChildren("=
ignore");
                 setIgnorePatterns(ignoreElements);
             }
+            // Read the <splitpath> configuration
+            log.debug("Reading Split Path Configuation");
+            Configuration splitConfig =3D mapConfig.getChild("splitpath", =
false);
+            if (splitConfig !=3D null) {
+                splitPathConfig.setSplitparts(Integer.parseInt(splitConfig=
.getAttribute("depth", "0")));
+                splitPathConfig.setSplitlength(Integer.parseInt(splitConfi=
g.getAttribute("length", "0")));
+                splitPathConfig.setEscapeChar(splitConfig.getAttribute("es=
cape", "-"));
+
+                int numberOfIncludePaths =3D splitConfig.getChildren("incl=
ude").length;
+                int i =3D 0;
+                if (numberOfIncludePaths > 0) {
+                    String[] includepaths =3D new String[numberOfIncludePa=
ths];
+                    for (Configuration include : splitConfig.getChildren("=
include")) {
+                        includepaths[i++] =3D include.getAttribute("path");
+                    }
+                    splitPathConfig.setIncludepaths(includepaths);
+                }
+                log.debug("Split Path Configuration DONE");
+                splitPathEnabled =3D true;
+            } =

+            =

         } catch(Exception e) {
             log.error(e);
             throw new RepositoryException("Could not read map configuratio=
n: " =

@@ -66,15 +90,14 @@
     =

     /**
      * Test if path should be ignored
+     * @return true returns true if the path can be ignored
      */
-    protected boolean ignorePath(String path) {
+    public boolean ignorePath(String path) {
         if (ignorePatterns !=3D null) {
             for (int i=3D0; i<this.ignorePatterns.length; i++) {
                 Matcher matcher =3D this.ignorePatterns[i].matcher(path); =

                 if (matcher.matches()) {
-                    if (log.isDebugEnabled()) {
-                        log.debug(path + " matched ignore pattern " + igno=
rePatterns[i].pattern());
-                    }
+                    log.debug(path + " matched ignore pattern " + ignorePa=
tterns[i].pattern());
                     return true;
                 }
             }
@@ -89,7 +112,14 @@
      *
      */
     public boolean isResource(Path path) throws RepositoryException {
-        File file =3D new File(pathsDir + path.toString());
+        File file =3D null;
+        if (splitPathEnabled) {
+            String maybeSplitedPath =3D SplitPathConfig.splitPathIfRequire=
d(path.toString(), this.splitPathConfig);
+            file =3D new File(pathsDir + maybeSplitedPath);
+        }
+        if (file =3D=3D null || !file.exists()) {
+            file =3D new File(pathsDir + path.toString());
+        }
         return file.isFile();
     }
 =

@@ -97,14 +127,21 @@
      *
      */
     public boolean exists(Path path) throws RepositoryException {
-        File file =3D new File(pathsDir + path.toString());
-        // TODO: Get name of repository for debugging ...
-        //log.debug("File: " + file);
-        return file.exists() && !ignorePath(file.getPath());
+        File file =3D null;
+        if (splitPathEnabled) {
+            String maybeSplitedPath =3D SplitPathConfig.splitPathIfRequire=
d(path.toString(), this.splitPathConfig);
+            file =3D new File(pathsDir + maybeSplitedPath);
+        }
+        if (file =3D=3D null || !file.exists()) {
+            file =3D new File(pathsDir + path.toString());
+        }
+        boolean result =3D file.exists() && !ignorePath(file.getPath());
+        log.debug("file.exists()=3D"+result+": File: "+file.getPath());
+        return result;
     }
 =

     /**
-     *
+     * Calling this method has no effect anymore because delete is done in=
 the storage impl!
      */
     public boolean delete(Path path) throws RepositoryException {
         // don't do anything because if we delete the file here, the delete
@@ -118,41 +155,124 @@
      *
      */
     public boolean isCollection(Path path) throws RepositoryException {
-        File file =3D new File(pathsDir + path.toString());
+        File file =3D null;
+        if (splitPathEnabled) {
+            String maybeSplitedPath =3D SplitPathConfig.splitPathIfRequire=
d(path.toString(), this.splitPathConfig);
+            file =3D new File(pathsDir + maybeSplitedPath);
+        }
+        if (file =3D=3D null || !file.exists()) {
+            file =3D new File(pathsDir + path.toString());
+        }
         return file.isDirectory();
     }
 =

     /**
-     * Get children
+     * Get children, the path of the children includes the path of the par=
ent!
      */
     public Path[] getChildren(Path path) throws RepositoryException {
-        File file =3D new File(pathsDir + path.toString());
-        if (!file.exists()) {
-            log.warn("No such file or directory: " + file);
-            return new Path[0];
-        }
+        // Note: path is always NOT splited, because the caller of this me=
thod does not know anything about it
+        log.debug("path =3D "+path.toString());
+        if (splitPathEnabled) {
+            File startingDirectory =3D new File(pathsDir + path.toString()=
);
+            if (!startingDirectory.exists()) {
+                log.warn("No such file or directory: " + startingDirectory=
);
+                return new Path[0];
+            }
+            if (startingDirectory.isFile()) {
+                log.warn("Can not get children form a file! : " + starting=
Directory);
+                return new Path[0];
+            }
+            =

+            List<File> allChildren =3D getAllFiles(startingDirectory);
+            log.debug("Number of children: " + allChildren.size() + " (" +=
 startingDirectory + ")");
+            List<Path> validChildrenPaths =3D new ArrayList<Path>();
+            String fileSepForRegEx =3D File.separator;
+            if (fileSepForRegEx.equals("\\")) {
+                fileSepForRegEx =3D "\\\\"; // this is a double backslash,=
 used for the regex later
+            }
+            =

+            for (File child: allChildren) {
+                String unsplitPath =3D child.getAbsolutePath().replaceAll(=
fileSepForRegEx, "/"); // whatever the file separator was, yarep uses "/"
+                log.debug("startingDirectory=3D "+startingDirectory);
+                log.debug("child =3D "+child.getAbsolutePath());
+                if (unsplitPath.startsWith(startingDirectory.getAbsolutePa=
th())) {
+                    unsplitPath =3D unsplitPath.substring(startingDirector=
y.getAbsolutePath().length());
+                    log.debug("1. path to unsplit =3D "+unsplitPath);
+                    unsplitPath =3D SplitPathConfig.unsplitPathIfRequired(=
unsplitPath, splitPathConfig);
+                    log.debug("2. unsplitPath =3D "+unsplitPath);
+                    Path newPath =3D null;
+                    if (!ignorePath(unsplitPath)) {
+                        if (path.toString().endsWith(File.separator)) {
+                            newPath =3D new Path(path + unsplitPath);
+                            log.debug("3a. Added "+newPath.toString());
+                        } else {
+                            // NOTE: Do not use File.separator here, becau=
se it's the repository path and not the Operating System's File System path
+                            newPath =3D new Path(path + "/" + unsplitPath);
+                            log.debug("3b. Added "+newPath.toString());
+                        }
+                        validChildrenPaths.add(newPath);
+                   } else {
+                       log.debug("ignored: "+child.getAbsolutePath());
+                   }
+                 } else {
+                    log.error("Something is wrong: children are not within=
 parents!");
+                }
+            }
+            Path[] childrenArray =3D validChildrenPaths.toArray(new Path[v=
alidChildrenPaths.size()]);
+            return childrenArray;
+            =

+        } else {
+            File file =3D new File(pathsDir + path.toString());
+            if (!file.exists()) {
+                log.warn("No such file or directory: " + file);
+                return new Path[0];
+            }
 =

-        String[] filenames =3D file.list(this.childrenFilter);
+            String[] filenames =3D file.list(this.childrenFilter);
 =

-	// NOTE: This situation should only occur if one is trying to get childre=
n for a file than a directory! One might want to consider to test first wit=
h isResource() or isCollection().
-        if (filenames =3D=3D null) {
-            log.warn("No children: " + path + " (" + file + ")");
-            return new Path[0];
-        }
+        // NOTE: This situation should only occur if one is trying to get =
children for a file than a directory! One might want to consider to test fi=
rst with isResource() or isCollection().
+            if (filenames =3D=3D null) {
+                log.warn("No children: " + path + " (" + file + ")");
+                return new Path[0];
+            }
 =

-        log.debug("Number of children: " + filenames.length + " (" + file =
+ ")");
-        Path[] children =3D new Path[filenames.length];
-        for (int i =3D 0;i < children.length; i++) {
-            if (path.toString().endsWith(File.separator)) {
-                children[i] =3D new Path(path + filenames[i]);
-            } else {
-                // NOTE: Do not use File.separator here, because it's the =
repository path and not the Operating System File System path
-                children[i] =3D new Path(path + "/" + filenames[i]);
+            log.debug("Number of children: " + filenames.length + " (" + f=
ile + ")");
+            Path[] children =3D new Path[filenames.length];
+            for (int i =3D 0;i < children.length; i++) {
+                if (path.toString().endsWith(File.separator)) {
+                    children[i] =3D new Path(path + filenames[i]);
+                } else {
+                    // NOTE: Do not use File.separator here, because it's =
the repository path and not the Operating System File System path
+                    children[i] =3D new Path(path + "/" + filenames[i]);
+                }
+                log.debug("Child: " + children[i]);
             }
-            log.debug("Child: " + children[i]);
+            return children;
+            =

         }
-        return children;
     }
+    =

+    /**
+     * =

+     * @param dir
+     * @return List of Files (directories are NOT in the list!)
+     */
+    private List<File> getAllFiles(File dir) {
+        List<File> result =3D new ArrayList<File>();
+        if (dir.isDirectory()) {
+            File[] filesAndDirsArray =3D dir.listFiles();
+            List<File> filesAndDirs =3D Arrays.asList(filesAndDirsArray);
+            for (File file : filesAndDirs) {
+                if (file.isFile()) {
+                    result.add(file);
+                } else {
+                    List<File> deeperList =3D getAllFiles(file);
+                    result.addAll(deeperList);
+                }
+            }
+        }
+        return result;
+    }
 =

     /**
      * Get UID
@@ -163,11 +283,14 @@
     }
 =

     /**
-     * Create UID
+     * Create UID:
      */
     public synchronized UID create(Path path, int type) throws RepositoryE=
xception {
+        log.debug("pathsDir =3D "+pathsDir.getAbsolutePath());
+        log.debug("path =3D "+path);
+        log.debug("path parent =3D "+path.getParent());
         // TODO: Check if leading slash should be removed ...
-        File parent =3D new File(pathsDir + File.separator + path.getParen=
t().toString());
+        File parent =3D new File(pathsDir + File.separator + path.getParen=
t().toString()); // e.g. access-control/users
         if (!parent.exists()) {
             log.warn("Directory will be created: " + parent);
             parent.mkdirs();
@@ -176,9 +299,35 @@
             new File(parent, path.getName()).mkdir();
         } else {
             try {
-                if(!new File(parent, path.getName()).createNewFile()) log.=
warn("File has not been created: " + new File(parent, path.getName()));
+                if (splitPathEnabled) {
+                    // splitted e.g: ab/cd/4.xml
+                    String maybeSplitedPath =3D SplitPathConfig.splitPathI=
fRequired(path.toString(), this.splitPathConfig);
+                    log.debug("maybeSplited =3D "+maybeSplitedPath);
+                    String newParent =3D pathsDir.getAbsolutePath();
+                    if (maybeSplitedPath.contains("/")) {
+                        // newparent for splitted above would be pathsDir/=
ab/cd
+                        newParent =3D newParent + maybeSplitedPath.substri=
ng(0,maybeSplitedPath.lastIndexOf("/")+1);
+                    }
+                    String newFileName =3D new File(maybeSplitedPath).getN=
ame();
+                    log.debug("new parent =3D "+newParent);
+                    log.debug("new file name =3D "+newFileName);
+                    File newFilePath =3D new File(newParent , newFileName);
+                    new File(newParent).mkdirs();
+                    log.debug("new parent exists: "+new File(newParent).ex=
ists());
+                    boolean created =3D newFilePath.createNewFile();
+                    log.debug("new file exists: "+newFilePath.exists());
+                    log.debug("new file is directory: "+newFilePath.isDire=
ctory());
+                    if (!created)  {
+                        log.debug("Maybe file has not been created: " + ne=
wFilePath.getAbsolutePath()); // On Mac OSX 10.6, the file gets created eve=
n in this case
+                    }
+                    =

+                } else {
+                    if(!new File(parent, path.getName()).createNewFile()) =
log.debug("File has not been created: " + new File(parent, path.getName()));
+                }
+
+                =

             } catch (Exception e) {
-                log.error(e.getMessage(), e);
+                log.error("Could not create new file!! Exception: "+e.getM=
essage(), e);
             }
         }
         =

@@ -186,7 +335,7 @@
     }
 =

     /**
-     *
+     * An exception gets thrown if you call this method because symbolic l=
inks are not implemented for virtual file systems!
      */
     public void addSymbolicLink(Path path, UID uid) throws RepositoryExcep=
tion {
         throw new RepositoryException("Symbolic links not implemented for =
virtual file system!");
@@ -199,6 +348,9 @@
         public ChildrenFilter() {
         }
         =

+        /**
+         * @param dir is ignored in this implementation
+         */
         public boolean accept(File dir, String name) {
             =

             if (VFileSystemMapImpl.this.ignorePath(name)) {
@@ -224,4 +376,20 @@
             ignorePatterns =3D null; // see ignorePath(String)
         }
     }
+
+    public SplitPathConfig getSplitPathConfig() {
+        return splitPathConfig;
+    }
+
+    public void setSplitPathConfig(SplitPathConfig splitPathConfig) {
+        this.splitPathConfig =3D splitPathConfig;
+    }
+
+    public boolean isSplitPathEnabled() {
+        return splitPathEnabled;
+    }
+
+    public void setSplitPathEnabled(boolean splitPathEnabled) {
+        this.splitPathEnabled =3D splitPathEnabled;
+    }
 }
Index: src/impl/java/org/wyona/yarep/core/impl/vfs/VFileSystemStorage.java
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- src/impl/java/org/wyona/yarep/core/impl/vfs/VFileSystemStorage.java	(re=
vision 54229)
+++ src/impl/java/org/wyona/yarep/core/impl/vfs/VFileSystemStorage.java	(wo=
rking copy)
@@ -1,12 +1,5 @@
 package org.wyona.yarep.core.impl.vfs;
 =

-import org.wyona.commons.io.FileUtil;
-import org.wyona.yarep.core.NoSuchNodeException;
-import org.wyona.yarep.core.Path;
-import org.wyona.yarep.core.RepositoryException;
-import org.wyona.yarep.core.Storage;
-import org.wyona.yarep.core.UID;
-
 import java.io.File;
 import java.io.InputStream;
 import java.io.OutputStream;
@@ -15,6 +8,12 @@
 =

 import org.apache.avalon.framework.configuration.Configuration;
 import org.apache.log4j.Category;
+import org.wyona.commons.io.FileUtil;
+import org.wyona.yarep.core.NoSuchNodeException;
+import org.wyona.yarep.core.Path;
+import org.wyona.yarep.core.RepositoryException;
+import org.wyona.yarep.core.Storage;
+import org.wyona.yarep.core.UID;
 =

 /**
  *
@@ -27,6 +26,12 @@
     private String alternative =3D null;
     private String dirListingMimeType =3D "application/xml";
 =

+    // Configuration parameters of the <splitpath ...> element
+    private SplitPathConfig splitPathConfig =3D new SplitPathConfig();
+    private boolean splitPathEnabled =3D false;
+    =

+    =

+
     /**
      * Read VFS Storage configuration
      */
@@ -50,6 +55,28 @@
                 dirListingMimeType =3D directoryConfig.getAttribute("mime-=
type", "application/xml");
                 log.debug("Mime type of directory listing: " + dirListingM=
imeType);
             }
+
+            // Read the <splitpath> configuration
+            log.debug("Reading Split Path Configuation");
+            Configuration splitConfig =3D storageConfig.getChild("splitpat=
h", false);
+            if (splitConfig !=3D null) {
+                splitPathEnabled =3D true;
+                splitPathConfig.setSplitparts(Integer.parseInt(splitConfig=
.getAttribute("depth", "0")));
+                splitPathConfig.setSplitlength(Integer.parseInt(splitConfi=
g.getAttribute("length", "0")));
+                splitPathConfig.setEscapeChar(splitConfig.getAttribute("es=
cape", "-"));
+
+                int numberOfIncludePaths =3D splitConfig.getChildren("incl=
ude").length;
+                int i =3D 0;
+                if (numberOfIncludePaths > 0) {
+                    String[] includepaths =3D new String[numberOfIncludePa=
ths];
+                    for (Configuration include : splitConfig.getChildren("=
include")) {
+                        includepaths[i++] =3D include.getAttribute("path");
+                    }
+                    splitPathConfig.setIncludepaths(includepaths);
+                }
+                log.debug("Split Path Configuration DONE");
+            } =

+            =

         } catch (Exception e) {
             log.error(e);
             throw new RepositoryException(e.getMessage(), e);
@@ -60,57 +87,117 @@
      *
      */
     public Writer getWriter(UID uid, Path path) {
-        return new VFileSystemRepositoryWriter(uid, path, contentDir);
+        // TODO We pass null as uid argument because the class anyway does=
 not need it at this moment. =

+        // If in future this class is going to process the uid argument to=
o, the splitpathConfig object can be passed to it
+        String maybeSplitedPath =3D SplitPathConfig.splitPathIfRequired(pa=
th.toString(), this.splitPathConfig);
+        Path newPath =3D new Path(maybeSplitedPath);
+        Writer writer =3D null;
+        try {
+            writer =3D new VFileSystemRepositoryWriter(null, newPath, cont=
entDir);
+        } catch (Exception e) {
+        }
+        if (writer =3D=3D null) {
+            writer =3D new VFileSystemRepositoryWriter(null, path, content=
Dir);
+        }
+        return writer;
     }
 =

     /**
-     *
+     * @param uid is ignored in this implementation!
      */
     public OutputStream getOutputStream(UID uid, Path path) throws Reposit=
oryException {
-        return new VFileSystemRepositoryOutputStream(uid, path, contentDir=
);
+        // TODO We pass null as uid argument because the class anyway does=
 not need it at this moment. =

+        // If in future this class is going to process the uid argument to=
o, the splitpathConfig object can be passed to it
+        String maybeSplitedPath =3D SplitPathConfig.splitPathIfRequired(pa=
th.toString(), this.splitPathConfig);
+        Path newPath =3D new Path(maybeSplitedPath);
+        OutputStream out =3D null;
+        try {
+            out =3D new VFileSystemRepositoryOutputStream(null, newPath, c=
ontentDir);
+        } catch (Exception e) {
+        }
+        if (out =3D=3D null) {
+            out =3D new VFileSystemRepositoryOutputStream(null, path, cont=
entDir);
+        }
+        return out;
     }
 =

     /**
      *
      */
     public Reader getReader(UID uid, Path path) throws NoSuchNodeException=
 {
-        return new VFileSystemRepositoryReader(uid, path, contentDir);
+        // TODO We pass null as uid argument because the class anyway does=
 not need it at this moment. =

+        // If in future this class is going to process the uid argument to=
o, the splitpathConfig object can be passed to it
+        String maybeSplitedPath =3D SplitPathConfig.splitPathIfRequired(pa=
th.toString(), this.splitPathConfig);
+        Path newPath =3D new Path(maybeSplitedPath);
+        Reader reader =3D null;
+        try {
+            reader =3D new VFileSystemRepositoryReader(null, newPath, cont=
entDir);
+        } catch (Exception e) {
+        }
+        if (reader =3D=3D null) {
+            reader =3D new VFileSystemRepositoryReader(null, path, content=
Dir);
+        }
+        return reader;
     }
 =

     /**
-     *
+     * @param uid is ignored in this implementation!
      */
     public InputStream getInputStream(UID uid, Path path) throws Repositor=
yException {
-        return new VFileSystemRepositoryInputStream(uid, path, contentDir,=
 alternative, dirListingMimeType);
+        // TODO: if uid is processed by VFileSystemRepositoryInputStream, =
the splitPathConfig must be passed to it too. =

+        String maybeSplitedPath =3D SplitPathConfig.splitPathIfRequired(pa=
th.toString(), this.splitPathConfig);
+        Path newPath =3D new Path(maybeSplitedPath);
+        InputStream in =3D null;
+        try {
+            in =3D new VFileSystemRepositoryInputStream(null, newPath, con=
tentDir, alternative, dirListingMimeType);
+        } catch (Exception e) {
+        }
+        if (in =3D=3D null) {
+            in =3D new VFileSystemRepositoryInputStream(null, path, conten=
tDir, alternative, dirListingMimeType);
+        }
+        return in;
     }
 =

     /**
-     *
+     * @param path is currently ignored!!
      */
     public long getLastModified(UID uid, Path path) throws RepositoryExcep=
tion {
-        File file =3D new File(contentDir.getAbsolutePath() + File.separat=
or + uid.toString());
+        String maybeSplitedPath =3D SplitPathConfig.splitPathIfRequired(ui=
d.toString(), this.splitPathConfig);
+        File file =3D new File(contentDir.getAbsolutePath() + File.separat=
or + maybeSplitedPath);
+        if (!file.exists()) {
+            file =3D new File(contentDir.getAbsolutePath() + File.separato=
r + uid.toString());
+        }
         return file.lastModified(); =

     }
     =

     /**
+     * @param path is currently not used!
      * @return Size of file in bytes
      */
     public long getSize(UID uid, Path path) throws RepositoryException {
-    	File file =3D new File(contentDir.getAbsolutePath() + File.separator =
+ uid.toString());
-    	return file.length(); =

+        String maybeSplitedPath =3D SplitPathConfig.splitPathIfRequired(ui=
d.toString(), this.splitPathConfig);
+        File file =3D new File(contentDir.getAbsolutePath() + File.separat=
or + maybeSplitedPath);
+        if (!file.exists()) {
+            file =3D new File(contentDir.getAbsolutePath() + File.separato=
r + uid.toString());
+        }
+        return file.length(); =

     }
 =

     /**
-     *
+     * @param path is currently not used!
      */
     public boolean delete(UID uid, Path path) throws RepositoryException {
-        File file =3D new File(contentDir.getAbsolutePath() + File.separat=
or + uid.toString());
+        String maybeSplitedPath =3D SplitPathConfig.splitPathIfRequired(ui=
d.toString(), this.splitPathConfig);
+        File file =3D new File(contentDir.getAbsolutePath() + File.separat=
or + maybeSplitedPath.toString());
+        if (!file.exists()) {
+            file =3D new File(contentDir.getAbsolutePath() + File.separato=
r + uid.toString());
+        }
         log.debug("Try to delete: " + file);
         return file.delete();
     }
     =

     /**
-     * =

+     * Not implemented at this moment
      */
     public String[] getRevisions(UID uid, Path path) throws RepositoryExce=
ption {
         log.warn("Versioning not implemented yet");
@@ -118,16 +205,32 @@
     }
 =

     /**
-     *
+     * Checks the existence via uid first and then via path parameter
      */
     public boolean exists(UID uid, Path path) {
+        boolean exists =3D false;
         if (uid !=3D null) {
-            return new File(contentDir.getAbsolutePath() + File.separator =
+ uid.toString()).exists();
+            if (splitPathEnabled) {
+                File normalFile =3D new File(contentDir.getAbsolutePath() =
+ File.separator + uid.toString());
+                File splitFile =3D new File(contentDir.getAbsolutePath() +=
 File.separator + SplitPathConfig.splitPathIfRequired(uid.toString(), this.=
splitPathConfig));
+                exists =3D normalFile.exists() || splitFile.exists();
+            } else {
+                exists =3D new File(contentDir.getAbsolutePath() + File.se=
parator + uid.toString()).exists();
+            }
+
         } else if (path !=3D null) {
             log.warn("No UUID specified, hence check path: " + path + " (C=
ontent dir: " + contentDir + ")");
-            return new File(contentDir.getAbsolutePath() + File.separator =
+ path.toString()).exists();
-        } else {
-            return false;
-        }
+            if (splitPathEnabled) {
+                File normalFile =3D new File(contentDir.getAbsolutePath() =
+ File.separator + path.toString());
+                File splitFile =3D new File(contentDir.getAbsolutePath() +=
 File.separator + SplitPathConfig.splitPathIfRequired(path.toString(), this=
.splitPathConfig));
+                exists =3D normalFile.exists() || splitFile.exists();
+            } else {
+                exists =3D new File(contentDir.getAbsolutePath() + File.se=
parator + path.toString()).exists();
+            }
+
+        } =

+        return exists;
     }
+    =

+
 }


More information about the Yanel-development mailing list