001 /*
002 *
003 * $Revision: 13085 $ $Date: 2008-02-06 18:27:24 +0100 (Mi, 06 Feb 2008) $
004 *
005 * This file is part of *** M y C o R e ***
006 * See http://www.mycore.de/ for details.
007 *
008 * This program is free software; you can use it, redistribute it
009 * and / or modify it under the terms of the GNU General Public License
010 * (GPL) as published by the Free Software Foundation; either version 2
011 * of the License or (at your option) any later version.
012 *
013 * This program is distributed in the hope that it will be useful, but
014 * WITHOUT ANY WARRANTY; without even the implied warranty of
015 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
016 * GNU General Public License for more details.
017 *
018 * You should have received a copy of the GNU General Public License
019 * along with this program, in a file called gpl.txt or license.txt.
020 * If not, write to the Free Software Foundation Inc.,
021 * 59 Temple Place - Suite 330, Boston, MA 02111-1307 USA
022 */
023
024 package org.mycore.services.migration;
025
026 import java.io.File;
027 import java.io.FileInputStream;
028 import java.io.FileNotFoundException;
029 import java.io.FileOutputStream;
030 import java.io.IOException;
031 import java.io.OutputStreamWriter;
032 import java.sql.Connection;
033 import java.sql.SQLException;
034 import java.sql.Statement;
035 import java.util.List;
036 import java.util.Properties;
037
038 import org.apache.log4j.Logger;
039 import org.hibernate.Session;
040 import org.jdom.Comment;
041 import org.jdom.Document;
042 import org.jdom.Element;
043 import org.jdom.input.SAXBuilder;
044 import org.jdom.output.XMLOutputter;
045 import org.jdom.xpath.XPath;
046
047 import org.mycore.backend.hibernate.MCRHIBConnection;
048 import org.mycore.common.MCRConfiguration;
049 import org.mycore.user.MCRGroup;
050 import org.mycore.user.MCRUserMgr;
051
052 /**
053 * Update of User Management to comply with new MyCoRe 2.0
054 *
055 * Therefore we first checkout all users and groups, drop the concerning tables
056 * and check all users and groups back in. Before check-in the new user tables
057 * will be automatically created by Hibernate which takes care of new primary
058 * key and foreign key constraints.
059 *
060 *
061 * @author Robert Stephan
062 */
063 class MCRUserMigrationHelper {
064
065 private static Logger LOGGER = Logger.getLogger(MCRUserMigrationHelper.class.getName());
066
067 static File getUserFile() {
068 return new File(getBaseDirectory(), "user-data.xml");
069 }
070
071 static File getGroupFile() {
072 return new File(getBaseDirectory(), "group-data.xml");
073 }
074
075 private static File getBaseDirectory() {
076 Properties props = (Properties) (MCRConfiguration.instance().getProperties());
077 String workingDir = props.getProperty("MCR.BaseDirectory", null);
078 if (workingDir == null) {
079 workingDir = System.getProperty("java.io.tmpdir");
080 }
081
082 File dir = new File(workingDir, "user-migration");
083 dir.mkdirs();
084 return dir;
085 }
086
087 @SuppressWarnings("all")
088 static final void dropTables() throws SQLException {
089 try {
090 Connection con = MCRHIBConnection.instance().getSession().connection();
091 Statement stmt = con.createStatement();
092 stmt.executeUpdate("DROP TABLE MCRGROUPMEMBERS");
093 stmt.executeUpdate("DROP TABLE MCRGROUPADMINS");
094 stmt.executeUpdate("DROP TABLE MCRUSERS");
095 stmt.executeUpdate("DROP TABLE MCRGROUPS");
096 stmt.close();
097 con.commit();
098
099 } catch (SQLException e) {
100 LOGGER.debug("Failed to drop table", e);
101 throw e;
102 }
103 Session session = MCRHIBConnection.instance().getSession();
104 session.clear();
105 }
106
107 static final void deleteTempFiles() {
108 try {
109 File groupFile = getGroupFile();
110 if (groupFile.getAbsolutePath().endsWith(".xml")) {
111 File f1org = new File(groupFile.getAbsolutePath() + ".org.xml");
112 f1org.delete();
113 }
114 groupFile.delete();
115
116 File userFile = getUserFile();
117 if (userFile.getAbsolutePath().endsWith(".xml")) {
118 File f1org = new File(userFile.getAbsolutePath() + ".org.xml");
119 f1org.delete();
120 }
121 userFile.delete();
122
123 File baseDir = getBaseDirectory();
124 baseDir.delete();
125
126 } catch (Exception e) {
127 LOGGER.debug("Failed to cleanup temp files", e);
128 }
129 }
130
131 /*
132 * We have to delete all group member information, since we create the
133 * groups before the users we also delete all groups - allready created by
134 * "init superuser"
135 */
136 static void cleanupGroupFile() throws Exception {
137 StringBuffer useradmins = new StringBuffer();
138 StringBuffer groupadmins = new StringBuffer();
139 try {
140 final File groupFile = getGroupFile();
141 copyFile(groupFile, new File(groupFile.getAbsolutePath() + ".org.xml"));
142 SAXBuilder sb = new SAXBuilder();
143 Document doc = sb.build(groupFile);
144 // delete group.members
145 XPath x = XPath.newInstance("//group.members");
146 List list = x.selectNodes(doc);
147 for (Object o : list) {
148 Element e = (Element) o;
149 e.removeContent();
150 }
151
152 // remove empty admins.userID and admins.groupID
153 x = XPath.newInstance("//admins.userID");
154 list = x.selectNodes(doc);
155 for (Object o : list) {
156 Element e = (Element) o;
157 if (useradmins.length() > 0)
158 useradmins.append(";");
159 useradmins.append(e.getParentElement().getParentElement().getAttributeValue("ID"));
160 useradmins.append("=");
161 useradmins.append(e.getText());
162
163 e.detach();
164 }
165
166 x = XPath.newInstance("//admins.groupID");
167 list = x.selectNodes(doc);
168 for (Object o : list) {
169 Element e = (Element) o;
170 if (groupadmins.length() > 0)
171 groupadmins.append(";");
172 groupadmins.append(e.getParentElement().getParentElement().getAttributeValue("ID"));
173 groupadmins.append("=");
174 groupadmins.append(e.getText());
175
176 e.detach();
177 }
178
179 // deltete existing Groups
180 x = XPath.newInstance("//group");
181 list = x.selectNodes(doc);
182 for (Object o : list) {
183 Element e = (Element) o;
184 if (MCRUserMgr.instance().existGroup(e.getAttributeValue("ID"))) {
185 e.getParent().removeContent(e);
186 }
187 }
188 doc.addContent(new Comment(useradmins.toString() + "|" + groupadmins.toString()));
189 XMLOutputter xmlOut = new XMLOutputter();
190 xmlOut.output(doc, new OutputStreamWriter(new FileOutputStream(groupFile), "utf-8"));
191 } catch (Exception e) {
192 LOGGER.debug("Error in user migration while modifying group members", e);
193 throw e;
194 }
195 }
196
197 /*
198 * We have to delete all users - allready created by "init superuser"
199 */
200 static void cleanupUserFile() {
201 try {
202 final File userFile = getUserFile();
203 copyFile(userFile, new File(userFile.getAbsolutePath() + ".org.xml"));
204 SAXBuilder sb = new SAXBuilder();
205 Document doc = sb.build(userFile);
206
207 // deltete existing Users
208 XPath x = XPath.newInstance("//user");
209 List list = x.selectNodes(doc);
210 for (Object o : list) {
211 Element e = (Element) o;
212 if (MCRUserMgr.instance().existUser(e.getAttributeValue("ID"))) {
213 e.getParent().removeContent(e);
214 }
215 }
216 XMLOutputter xmlOut = new XMLOutputter();
217 xmlOut.output(doc, new OutputStreamWriter(new FileOutputStream(userFile), "utf-8"));
218 } catch (Exception e) {
219 LOGGER.debug("Error in user migration while modifying group members", e);
220 }
221 }
222
223 static void updateAdmins() {
224 SAXBuilder sb = new SAXBuilder();
225 MCRUserMgr mgr = MCRUserMgr.instance();
226 try {
227 Document doc = sb.build(getGroupFile());
228 for (Object o : doc.getContent()) {
229 LOGGER.info(o.getClass().getCanonicalName());
230 if (o instanceof Comment) {
231 LOGGER.info("Found Comment");
232 String s = ((Comment) o).getText();
233 String[] sa = s.split("\\|");
234 String users = sa[0];
235 String groups = "";
236 if (sa.length > 1)
237 groups = sa[1];
238 String[] userA = users.split(";");
239 String[] groupA = groups.split(";");
240 for (String x : userA) {
241 final String[] groupAdmin = x.split("=");
242 if (groupAdmin.length > 1) {
243 String id = groupAdmin[0];
244 String value = groupAdmin[1];
245 MCRGroup mcrGroup = mgr.retrieveGroup(id);
246 mcrGroup.addAdminUserID(value);
247 mgr.updateGroup(mcrGroup);
248 LOGGER.info("Adding user '" + value + "' to admins of group '" + id + "'.");
249 }
250 }
251 for (String x : groupA) {
252 final String[] groupAdmin = x.split("=");
253 if (groupAdmin.length > 1) {
254 String id = groupAdmin[0];
255 String value = groupAdmin[1];
256 MCRGroup mcrGroup = mgr.retrieveGroup(id);
257 mcrGroup.addAdminGroupID(value);
258 mgr.updateGroup(mcrGroup);
259 LOGGER.info("Adding group '" + value + "' to admins of group '" + id + "'.");
260 }
261 }
262 }
263
264 }
265
266 } catch (Exception e) {
267 LOGGER.warn("Error in user migration while updateing group admin information", e);
268 }
269 }
270
271 // just for debugging
272 private static void copyFile(File fromFile, File toFile) {
273 FileInputStream from = null;
274 FileOutputStream to = null;
275 try {
276 from = new FileInputStream(fromFile);
277 to = new FileOutputStream(toFile);
278 byte[] buffer = new byte[4096];
279 int bytesRead;
280
281 while ((bytesRead = from.read(buffer)) != -1)
282 to.write(buffer, 0, bytesRead); // write
283 } catch (FileNotFoundException e) {
284 e.printStackTrace();
285 } catch (IOException e) {
286 e.printStackTrace();
287 }
288
289 finally {
290 if (from != null)
291 try {
292 from.close();
293 } catch (IOException e) {
294 ;
295 }
296 if (to != null)
297 try {
298 to.close();
299 } catch (IOException e) {
300 ;
301 }
302 }
303 }
304
305 }