View Javadoc

1   /*
2    * ------------------------------------------------------------------------------
3    * Hermes FTP Server
4    * Copyright (c) 2005-2007 Lars Behnke
5    * ------------------------------------------------------------------------------
6    * 
7    * This file is part of Hermes FTP Server.
8    * 
9    * Hermes FTP Server is free software; you can redistribute it and/or modify
10   * it under the terms of the GNU General Public License as published by
11   * the Free Software Foundation; either version 2 of the License, or
12   * (at your option) any later version.
13   * 
14   * Hermes FTP Server is distributed in the hope that it will be useful,
15   * but WITHOUT ANY WARRANTY; without even the implied warranty of
16   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17   * GNU General Public License for more details.
18   * 
19   * You should have received a copy of the GNU General Public License
20   * along with Hermes FTP Server; if not, write to the Free Software
21   * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
22   * ------------------------------------------------------------------------------
23   */
24  
25  package net.sf.hermesftp.usermanager.impl;
26  
27  import java.io.BufferedReader;
28  import java.io.File;
29  import java.io.FileReader;
30  import java.io.IOException;
31  import java.io.InputStream;
32  import java.io.InputStreamReader;
33  import java.util.List;
34  
35  import net.sf.hermesftp.exception.FtpConfigException;
36  import net.sf.hermesftp.usermanager.model.GroupData;
37  import net.sf.hermesftp.usermanager.model.PermissionData;
38  import net.sf.hermesftp.usermanager.model.UserData;
39  import net.sf.hermesftp.usermanager.model.UserManagerData;
40  
41  import org.apache.commons.logging.Log;
42  import org.apache.commons.logging.LogFactory;
43  import org.dom4j.Document;
44  import org.dom4j.DocumentException;
45  import org.dom4j.Element;
46  import org.dom4j.io.SAXReader;
47  
48  /***
49   * Reads the user management configuration data from a file.
50   * 
51   * @author Lars Behnke
52   */
53  public class XmlFileReader {
54  
55      private static Log          log                          = LogFactory.getLog(XmlFileReader.class);
56  
57      private static final String DEFAULT_HERMESFTP_USERS_FILE = "hermesftp-users.xml";
58  
59      private static final String ATTR_PATH                    = "path";
60  
61      private static final String XPATH_PERMISSIONS            = "permissions/permission";
62  
63      private static final String ATTR_VALUE                   = "value";
64  
65      private static final String ATTR_FLAG                    = "flag";
66  
67      private static final String XPATH_LIMITS                 = "limits/limit";
68  
69      private static final String XPATH_GROUPS                 = "/user-manager/groups/group";
70  
71      private static final String ATTR_NAME                    = "name";
72  
73      private static final String ELEM_GROUP_REF               = "group-ref";
74  
75      private static final String ATTR_DIR                     = "dir";
76  
77      private static final String ATTR_PASSWORD                = "password";
78  
79      private static final String ATTR_FULLNAME                = "fullname";
80  
81      private static final String ATTR_ADMINROLE               = "adminrole";
82  
83      private static final String ATTR_UID                     = "uid";
84  
85      private static final String ELEM_USER                    = "user";
86  
87      private static final String ATTR_DEFAULT_DIR             = "default-dir";
88  
89      private static final String XPATH_USERS                  = "/user-manager/users";
90  
91      private String              filename;
92  
93      /***
94       * Getter method for the java bean <code>filename</code>.
95       * 
96       * @return Returns the value of the java bean <code>filename</code>.
97       */
98      public String getFilename() {
99          if (filename == null || filename.length() == 0) {
100             String ctxDir = System.getProperty("hermes.ctx.dir");
101             File file;
102             if (ctxDir != null) {
103                 file = new File(ctxDir, DEFAULT_HERMESFTP_USERS_FILE);
104             } else {
105                 file = new File(DEFAULT_HERMESFTP_USERS_FILE);
106             }
107             filename = file.getAbsolutePath();
108         }
109         log.info("User configuration file: " + filename);
110         return filename;
111     }
112 
113     /***
114      * Setter method for the java bean <code>filename</code>.
115      * 
116      * @param filename The value of filename to set.
117      */
118     public void setFilename(String filename) {
119         this.filename = filename;
120     }
121 
122     /***
123      * Reads the user management data from a file. If the file was not found the classpath is
124      * searched.
125      * 
126      * @return The user management data.
127      * @throws FtpConfigException Error on reading or processing a configuration file.
128      */
129     public UserManagerData read() throws FtpConfigException {
130         UserManagerData result;
131         File file = null;
132         try {
133             SAXReader reader = new SAXReader();
134             file = new File(getFilename());
135             BufferedReader br;
136             if (file.exists()) {
137                 br = new BufferedReader(new FileReader(file));
138             } else {
139                 InputStream is = getClass().getResourceAsStream("/" + DEFAULT_HERMESFTP_USERS_FILE);
140                 br = new BufferedReader(new InputStreamReader(is));
141             }
142             Document doc = reader.read(br);
143             result = process(doc);
144         } catch (IOException e) {
145             throw new FtpConfigException("Reading " + getFilename() + " failed.");
146         } catch (DocumentException e) {
147             throw new FtpConfigException("Error while processing the configuration file " + file + ".");
148         }
149 
150         return result;
151     }
152 
153     private UserManagerData process(Document doc) {
154         UserManagerData result = new UserManagerData();
155         processUserData(doc, result);
156         processGroupData(doc, result);
157 
158         return result;
159     }
160 
161     @SuppressWarnings("unchecked")
162     private void processUserData(Document doc, UserManagerData umd) {
163         Element usersElement = (Element) doc.selectSingleNode(XPATH_USERS);
164         String defaultDir = usersElement.attributeValue(ATTR_DEFAULT_DIR);
165 
166         List<Element> userElements = usersElement.selectNodes(ELEM_USER);
167         for (Element userElement : userElements) {
168             String uid = userElement.attributeValue(ATTR_UID);
169             String fullName = userElement.attributeValue(ATTR_FULLNAME);
170             String password = userElement.attributeValue(ATTR_PASSWORD);
171             String adminrole = userElement.attributeValue(ATTR_ADMINROLE);
172             String dir = userElement.attributeValue(ATTR_DIR);
173             if (dir == null || dir.length() == 0) {
174                 dir = defaultDir;
175             }
176             UserData userData = new UserData();
177             userData.setFullName(fullName);
178             userData.setUid(uid);
179             userData.setPassword(password);
180             userData.setAdminRole(new Boolean(adminrole).booleanValue());
181             userData.setDir(dir);
182             List<Element> groupRefElements = userElement.selectNodes(ELEM_GROUP_REF);
183             for (Element element : groupRefElements) {
184                 String groupRefName = element.attributeValue(ATTR_NAME);
185                 if (groupRefName != null) {
186                     userData.addGroupName(groupRefName.trim());
187                 }
188             }
189             umd.getUserData().add(userData);
190 
191         }
192     }
193 
194     @SuppressWarnings("unchecked")
195     private void processGroupData(Document doc, UserManagerData umd) {
196         List<Element> groupElements = doc.selectNodes(XPATH_GROUPS);
197         for (Element groupElement : groupElements) {
198             String name = groupElement.attributeValue(ATTR_NAME);
199             GroupData groupData = new GroupData();
200             groupData.setName(name);
201 
202             List<Element> limitElements = groupElement.selectNodes(XPATH_LIMITS);
203             for (Element limitElement : limitElements) {
204                 String limitName = limitElement.attributeValue(ATTR_NAME);
205                 String limitValue = limitElement.attributeValue(ATTR_VALUE);
206                 if (limitName != null && limitValue != null) {
207                     Long limitLong = new Long(limitValue);
208                     groupData.getLimits().put(limitName, limitLong);
209                 }
210             }
211             List<Element> permissionElements = groupElement.selectNodes(XPATH_PERMISSIONS);
212             for (Element permissionElement : permissionElements) {
213                 String path = permissionElement.attributeValue(ATTR_PATH);
214 
215                 /* value attribute is supported for backward compatibility */
216                 String value = permissionElement.attributeValue(ATTR_VALUE);
217                 String flag = permissionElement.attributeValue(ATTR_FLAG);
218                 int permissionValue = getPermissionValue(value, flag);
219                 PermissionData pd = new PermissionData();
220                 pd.setPermission(permissionValue);
221                 pd.setTemplate(path);
222                 groupData.getPermissions().add(pd);
223             }
224             umd.getGroupData().addGroup(groupData);
225         }
226     }
227 
228     /***
229      * Decides on the permission value based on the passed arguments. Value attribute is supported
230      * for backward compatibility
231      * 
232      * @param value The permission value 1=read, 3=read/write.
233      * @param flag The permission flag R=read, RW=read/write.
234      * @return The permission value.
235      */
236     private int getPermissionValue(String value, String flag) {
237         flag = flag == null ? "" : flag.toUpperCase().trim();
238         int permissionValue = 0;
239         if (value != null && value.length() > 0) {
240             permissionValue = Integer.parseInt(value);
241         }
242         if (flag.indexOf('R') >= 0) {
243             permissionValue |= 1;
244         }
245         if (flag.indexOf('W') >= 0) {
246             permissionValue |= 2;
247         }
248         return permissionValue;
249     }
250 
251 }