View Javadoc

1   /**
2      This file is part of GoldenGate Project (named also GoldenGate or GG).
3   
4      Copyright 2009, Frederic Bregier, and individual contributors by the @author
5      tags. See the COPYRIGHT.txt in the distribution for a full listing of
6      individual contributors.
7   
8      All GoldenGate Project is free software: you can redistribute it and/or 
9      modify it under the terms of the GNU General Public License as published 
10     by the Free Software Foundation, either version 3 of the License, or
11     (at your option) any later version.
12  
13     GoldenGate is distributed in the hope that it will be useful,
14     but WITHOUT ANY WARRANTY; without even the implied warranty of
15     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16     GNU General Public License for more details.
17  
18     You should have received a copy of the GNU General Public License
19     along with GoldenGate .  If not, see <http://www.gnu.org/licenses/>.
20   */
21  package goldengate.common.file;
22  
23  import goldengate.common.command.exception.CommandAbstractException;
24  import goldengate.common.command.exception.Reply501Exception;
25  import goldengate.common.command.exception.Reply530Exception;
26  import goldengate.common.command.exception.Reply550Exception;
27  import goldengate.common.command.exception.Reply553Exception;
28  import goldengate.common.logging.GgInternalLogger;
29  import goldengate.common.logging.GgInternalLoggerFactory;
30  
31  import java.io.File;
32  import java.io.IOException;
33  import java.util.ArrayList;
34  import java.util.List;
35  
36  
37  /**
38   * Abstract Main Implementation of Directory
39   * 
40   * @author Frederic Bregier
41   *
42   */
43  public abstract class AbstractDir implements DirInterface {
44      /**
45       * Internal Logger
46       */
47      private static final GgInternalLogger logger = GgInternalLoggerFactory
48              .getLogger(AbstractDir.class);
49      /**
50       * Current Directory
51       */
52      protected String currentDir = null;
53      /**
54       * SessionInterface
55       */
56      protected SessionInterface session;
57  
58      /**
59       * Opts command for MLSx. (-1) means not supported, 0 supported but not
60       * active, 1 supported and active
61       */
62      protected OptsMLSxInterface optsMLSx;
63      /**
64       * Hack to say Windows or Unix (root like X:\ or /)
65       */
66      protected static Boolean ISUNIX = null;
67      /**
68       * Roots for Windows system
69       */
70      protected static File [] roots = null;
71      /**
72       * Init Windows Support
73       */
74      protected static void initWindowsSupport() {
75          if (ISUNIX == null) {
76              ISUNIX = (!System.getProperty("os.name")
77                      .toLowerCase().startsWith("win"));
78              if (! ISUNIX) {
79                  roots = File.listRoots();
80              }
81          }
82      }
83      /**
84      *
85      * @param file
86      * @return The corresponding Root file
87      */
88      protected File getCorrespondingRoot(File file) {
89         initWindowsSupport();
90         if (ISUNIX) {
91             return new File("/");
92         }
93         String path = file.getAbsolutePath();
94         for (File root : roots) {
95             if (path.startsWith(root.getAbsolutePath())) {
96                 return root;
97             }
98         }
99         // hack !
100        logger.warn("No root found for "+file.getAbsolutePath());
101        return roots[0];
102    }
103     /**
104      * Normalize Path to Internal unique representation
105      *
106      * @param path
107      * @return the normalized path
108      */
109     public static String normalizePath(String path) {
110         return path.replace('\\', SEPARATORCHAR).replace("//", "/");
111     }
112     /**
113     *
114     * @return the SessionInterface
115     */
116    public SessionInterface getSession() {
117        return session;
118    }
119    public String validatePath(String path) throws CommandAbstractException {
120        String extDir;
121        if (isAbsoluteWindows(path)) {
122            extDir = path;
123            File newDir = new File(extDir);
124            return validatePath(newDir);
125        }
126        extDir = consolidatePath(path);
127        // Get the baseDir (mount point)
128        String baseDir = getSession().getAuth().getBaseDirectory();
129        // Get the translated real file path (removing '..')
130        File newDir = new File(baseDir, extDir);
131        return validatePath(newDir);
132    }
133    /**
134     *
135     * @param path
136     * @return True if the given Path is an absolute one under Windows System
137     */
138    public boolean isAbsoluteWindows(String path) {
139        initWindowsSupport();
140        if (!ISUNIX) {
141            File file = new File(path);
142            return file.isAbsolute();
143        }
144        return false;
145    }
146    /**
147     * Consolidate Path as relative or absolute path to an absolute path
148     *
149     * @param path
150     * @return the consolidated path
151     * @throws CommandAbstractException
152     */
153    protected String consolidatePath(String path)
154            throws CommandAbstractException {
155        if (path == null || path.length() == 0) {
156            throw new Reply501Exception("Path must not be empty");
157        }
158        // First check if the path is relative or absolute
159        if (isAbsoluteWindows(path)) {
160            return path;
161        }
162        String extDir = null;
163        if (path.charAt(0) == SEPARATORCHAR) {
164            extDir = path;
165        } else {
166            extDir = currentDir + SEPARATOR + path;
167        }
168        return extDir;
169    }
170    /**
171     * Construct the CanonicalPath without taking into account symbolic link
172     * @param dir
173     * @return the canonicalPath
174     */
175    protected String getCanonicalPath(File dir) {
176        initWindowsSupport();
177        if (ISUNIX) {
178            // resolve it without getting symbolic links
179            StringBuilder builder = new StringBuilder();
180            // Get the path in reverse order from end to start
181            List<String> list = new ArrayList<String>();
182            File newdir = dir;
183            String lastdir = newdir.getName();
184            list.add(lastdir);
185            File parent = newdir.getParentFile();
186            while (parent != null) {
187                newdir = parent;
188                lastdir = newdir.getName();
189                list.add(lastdir);
190                parent = newdir.getParentFile();
191            }
192            // Now filter on '..' or '.'
193            for (int i = list.size()-1; i >= 0; i--) {
194                String curdir = list.get(i);
195                if (curdir.equals(".")) {
196                    list.remove(i);// removes '.'
197                } else if (curdir.equals("..")) {
198                        list.remove(i);// removes '..'
199                        int len = list.size();
200                        if (len > 0 && i < len) {
201                            list.remove(i);// and removes parent dir
202                        }
203                }
204            }
205            if (list.isEmpty()) {
206                return "/";
207            }
208 
209            for (int i = list.size()-1; i >= 0; i--) {
210                builder.append('/');
211                builder.append(list.get(i));
212            }
213            return builder.toString();
214        }
215        //Windows version
216        // no link so just use the default version of canonical Path
217        try {
218            return dir.getCanonicalPath();
219        } catch (IOException e) {
220            return dir.getAbsolutePath();
221        }
222    }
223    /**
224     * Same as validatePath but from a FileInterface
225     *
226     * @param dir
227     * @return the construct and validated path (could be different than the one
228     *         given as argument, example: '..' are removed)
229     * @throws CommandAbstractException
230     */
231    protected String validatePath(File dir) throws CommandAbstractException {
232        String extDir = null;
233        extDir = normalizePath(getCanonicalPath(dir));
234        // Get the relative business path
235        extDir = getSession().getAuth().getRelativePath(extDir);
236        // Check if this business path is valid
237        if (getSession().getAuth().isBusinessPathValid(extDir)) {
238            return extDir;
239        }
240        throw new Reply553Exception("Pathname not allowed");
241    }
242    /**
243     * Finds all files matching a wildcard expression (based on '?', '~' or
244     * '*').
245     *
246     * @param pathWithWildcard
247     *            The wildcard expression with a business path.
248     * @return List of String as relative paths matching the wildcard
249     *         expression. Those files are tested as valid from business point
250     *         of view. If Wildcard support is not active, if the path contains
251     *         any wildcards, it will throw an error.
252     * @throws CommandAbstractException
253     */
254    protected abstract List<String> wildcardFiles(String pathWithWildcard)
255            throws CommandAbstractException;
256    
257    public String getPwd() throws CommandAbstractException {
258        return currentDir;
259    }
260    public boolean changeParentDirectory() throws CommandAbstractException {
261        return changeDirectory("..");
262    }
263    
264    public FileInterface setFile(String path,
265            boolean append) throws CommandAbstractException {
266        checkIdentify();
267        String newpath = consolidatePath(path);
268        List<String> paths = wildcardFiles(newpath);
269        if (paths.size() != 1) {
270            throw new Reply550Exception("File not found: " +
271                    paths.size() + " founds");
272        }
273        String extDir = paths.get(0);
274        return newFile(extDir, append);
275    }
276    
277    public void checkIdentify() throws Reply530Exception {
278        if (!getSession().getAuth().isIdentified()) {
279            throw new Reply530Exception("User not authentified");
280        }
281    }
282    public void clear() {
283        currentDir = null;
284    }
285 
286    public void initAfterIdentification() {
287        currentDir = getSession().getAuth().getBusinessPath();
288    }
289 
290    public OptsMLSxInterface getOptsMLSx() {
291        return optsMLSx;
292    }
293    
294 }