blob: f09e822d30e9cdceef1df2bf99f52fb729651385 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License") + you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.openmeetings.backup;
import static org.apache.commons.transaction.util.FileHelper.copyRec;
import static org.apache.openmeetings.db.entity.user.PrivateMessage.INBOX_FOLDER_ID;
import static org.apache.openmeetings.db.entity.user.PrivateMessage.SENT_FOLDER_ID;
import static org.apache.openmeetings.db.entity.user.PrivateMessage.TRASH_FOLDER_ID;
import static org.apache.openmeetings.db.util.UserHelper.getMinLoginLength;
import static org.apache.openmeetings.util.OmFileHelper.getStreamsHibernateDir;
import static org.apache.openmeetings.util.OmFileHelper.getUploadDir;
import static org.apache.openmeetings.util.OmFileHelper.getUploadProfilesUserDir;
import static org.apache.openmeetings.util.OmFileHelper.getUploadRoomDir;
import static org.apache.openmeetings.util.OmFileHelper.profilesPrefix;
import static org.apache.openmeetings.util.OpenmeetingsVariables.CONFIG_CRYPT_KEY;
import static org.apache.openmeetings.util.OpenmeetingsVariables.webAppRootKey;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.StringReader;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.apache.commons.transaction.util.FileHelper;
import org.apache.openmeetings.db.dao.basic.ChatDao;
import org.apache.openmeetings.db.dao.basic.ConfigurationDao;
import org.apache.openmeetings.db.dao.calendar.AppointmentCategoryDao;
import org.apache.openmeetings.db.dao.calendar.AppointmentDao;
import org.apache.openmeetings.db.dao.calendar.AppointmentReminderTypDao;
import org.apache.openmeetings.db.dao.calendar.MeetingMemberDao;
import org.apache.openmeetings.db.dao.file.FileExplorerItemDao;
import org.apache.openmeetings.db.dao.record.FlvRecordingDao;
import org.apache.openmeetings.db.dao.room.PollDao;
import org.apache.openmeetings.db.dao.room.RoomDao;
import org.apache.openmeetings.db.dao.room.RoomOrganisationDao;
import org.apache.openmeetings.db.dao.room.RoomTypeDao;
import org.apache.openmeetings.db.dao.server.LdapConfigDao;
import org.apache.openmeetings.db.dao.server.OAuth2Dao;
import org.apache.openmeetings.db.dao.server.ServerDao;
import org.apache.openmeetings.db.dao.user.OrganisationDao;
import org.apache.openmeetings.db.dao.user.PrivateMessageFolderDao;
import org.apache.openmeetings.db.dao.user.PrivateMessagesDao;
import org.apache.openmeetings.db.dao.user.StateDao;
import org.apache.openmeetings.db.dao.user.UserContactsDao;
import org.apache.openmeetings.db.dao.user.UserDao;
import org.apache.openmeetings.db.entity.basic.ChatMessage;
import org.apache.openmeetings.db.entity.basic.Configuration;
import org.apache.openmeetings.db.entity.calendar.Appointment;
import org.apache.openmeetings.db.entity.calendar.AppointmentCategory;
import org.apache.openmeetings.db.entity.calendar.AppointmentReminderTyps;
import org.apache.openmeetings.db.entity.calendar.MeetingMember;
import org.apache.openmeetings.db.entity.file.FileExplorerItem;
import org.apache.openmeetings.db.entity.record.FlvRecording;
import org.apache.openmeetings.db.entity.record.FlvRecordingMetaData;
import org.apache.openmeetings.db.entity.room.PollType;
import org.apache.openmeetings.db.entity.room.Room;
import org.apache.openmeetings.db.entity.room.RoomModerator;
import org.apache.openmeetings.db.entity.room.RoomOrganisation;
import org.apache.openmeetings.db.entity.room.RoomPoll;
import org.apache.openmeetings.db.entity.room.RoomPollAnswers;
import org.apache.openmeetings.db.entity.room.RoomType;
import org.apache.openmeetings.db.entity.server.LdapConfig;
import org.apache.openmeetings.db.entity.server.OAuthServer;
import org.apache.openmeetings.db.entity.server.Server;
import org.apache.openmeetings.db.entity.user.Address;
import org.apache.openmeetings.db.entity.user.Organisation;
import org.apache.openmeetings.db.entity.user.PrivateMessage;
import org.apache.openmeetings.db.entity.user.PrivateMessageFolder;
import org.apache.openmeetings.db.entity.user.State;
import org.apache.openmeetings.db.entity.user.User;
import org.apache.openmeetings.db.entity.user.User.Right;
import org.apache.openmeetings.db.entity.user.User.Type;
import org.apache.openmeetings.db.entity.user.UserContact;
import org.apache.openmeetings.db.util.TimezoneUtil;
import org.apache.openmeetings.util.CalendarPatterns;
import org.apache.openmeetings.util.OmFileHelper;
import org.apache.openmeetings.util.crypt.MD5Implementation;
import org.apache.wicket.util.string.Strings;
import org.red5.logging.Red5LoggerFactory;
import org.simpleframework.xml.Serializer;
import org.simpleframework.xml.convert.Registry;
import org.simpleframework.xml.convert.RegistryStrategy;
import org.simpleframework.xml.core.Persister;
import org.simpleframework.xml.strategy.Strategy;
import org.simpleframework.xml.stream.InputNode;
import org.simpleframework.xml.stream.NodeBuilder;
import org.simpleframework.xml.transform.RegistryMatcher;
import org.slf4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;
public class BackupImport {
private static final Logger log = Red5LoggerFactory.getLogger(BackupImport.class, webAppRootKey);
@Autowired
private AppointmentDao appointmentDao;
@Autowired
private StateDao statemanagement;
@Autowired
private OrganisationDao orgDao;
@Autowired
private RoomDao roomDao;
@Autowired
private AppointmentCategoryDao appointmentCategoryDaoImpl;
@Autowired
private AppointmentReminderTypDao appointmentReminderTypDaoImpl;
@Autowired
private UserDao usersDao;
@Autowired
private FlvRecordingDao flvRecordingDao;
@Autowired
private PrivateMessageFolderDao privateMessageFolderDao;
@Autowired
private PrivateMessagesDao privateMessagesDao;
@Autowired
private MeetingMemberDao meetingMemberDao;
@Autowired
private LdapConfigDao ldapConfigDao;
@Autowired
private FileExplorerItemDao fileExplorerItemDao;
@Autowired
private UserContactsDao userContactsDao;
@Autowired
private PollDao pollManager;
@Autowired
private ConfigurationDao configurationDao;
@Autowired
private TimezoneUtil tzUtil;
@Autowired
private ChatDao chatDao;
@Autowired
private ServerDao serverDao;
@Autowired
private OAuth2Dao auth2Dao;
@Autowired
private OrganisationDao organisationDao;
@Autowired
private RoomTypeDao roomTypeDao;
@Autowired
private RoomOrganisationDao roomOrganisationDao;
private final Map<Long, Long> usersMap = new HashMap<Long, Long>();
private final Map<Long, Long> organisationsMap = new HashMap<Long, Long>();
private final Map<Long, Long> appointmentsMap = new HashMap<Long, Long>();
private final Map<Long, Long> roomsMap = new HashMap<Long, Long>();
private final Map<Long, Long> messageFoldersMap = new HashMap<Long, Long>();
private final Map<Long, Long> userContactsMap = new HashMap<Long, Long>();
private final Map<String, Integer> userEmailMap = new HashMap<String, Integer>();
private enum Maps {
USERS, ORGANISATIONS, APPOINTMENTS, ROOMS, MESSAGEFOLDERS, USERCONTACTS
};
public void performImport(InputStream is) throws Exception {
File working_dir = OmFileHelper.getUploadImportDir();
if (!working_dir.exists()) {
working_dir.mkdir();
}
usersMap.clear();
organisationsMap.clear();
appointmentsMap.clear();
roomsMap.clear();
messageFoldersMap.clear();
userContactsMap.clear();
userEmailMap.clear();
messageFoldersMap.put(INBOX_FOLDER_ID, INBOX_FOLDER_ID);
messageFoldersMap.put(SENT_FOLDER_ID, SENT_FOLDER_ID);
messageFoldersMap.put(TRASH_FOLDER_ID, TRASH_FOLDER_ID);
File f = OmFileHelper.getNewDir(working_dir, "import_" + CalendarPatterns.getTimeForStreamId(new Date()));
log.debug("##### WRITE FILE TO: " + f);
ZipInputStream zipinputstream = new ZipInputStream(is);
ZipEntry zipentry = zipinputstream.getNextEntry();
while (zipentry != null) {
String fName = zipentry.getName();
if (File.pathSeparatorChar != '\\' && fName.indexOf('\\') > -1) {
fName = fName.replace('\\', '/');
}
// for each entry to be extracted
File fentry = new File(f, fName);
File dir = fentry.isDirectory() ? fentry : fentry.getParentFile();
dir.mkdirs();
if (fentry.isDirectory()) {
zipentry = zipinputstream.getNextEntry();
continue;
}
FileHelper.copy(zipinputstream, fentry);
zipinputstream.closeEntry();
zipentry = zipinputstream.getNextEntry();
}
zipinputstream.close();
/*
* ##################### Import Configs
*/
{
Registry registry = new Registry();
Strategy strategy = new RegistryStrategy(registry);
RegistryMatcher matcher = new RegistryMatcher(); //TODO need to be removed in the later versions
Serializer serializer = new Persister(strategy, matcher);
matcher.bind(Long.class, LongTransform.class);
registry.bind(Date.class, DateConverter.class);
registry.bind(User.class, new UserConverter(usersDao, usersMap));
List<Configuration> list = readList(serializer, f, "configs.xml", "configs", Configuration.class, true);
for (Configuration c : list) {
if (c.getConf_key() == null || c.isDeleted()) {
continue;
}
Configuration cfg = configurationDao.forceGet(c.getConf_key());
if (cfg != null && !cfg.isDeleted()) {
log.warn("Non deleted configuration with same key is found! old value: {}, new value: {}", cfg.getConf_value(), c.getConf_value());
}
c.setConfiguration_id(cfg == null ? null : cfg.getConfiguration_id());
if (c.getUser() != null && c.getUser().getUser_id() == null) {
c.setUser(null);
}
if (CONFIG_CRYPT_KEY.equals(c.getConf_key())) {
try {
Class.forName(c.getConf_value());
} catch (ClassNotFoundException e) {
c.setConf_value(MD5Implementation.class.getCanonicalName());
}
}
configurationDao.update(c, null);
}
}
log.info("Configs import complete, starting organization import");
/*
* ##################### Import Organizations
*/
Serializer simpleSerializer = new Persister();
{
List<Organisation> list = readList(simpleSerializer, f, "organizations.xml", "organisations", Organisation.class);
for (Organisation o : list) {
long oldId = o.getOrganisation_id();
o.setOrganisation_id(null);
o = organisationDao.update(o, null);
organisationsMap.put(oldId, o.getOrganisation_id());
}
}
log.info("Organizations import complete, starting user import");
/*
* ##################### Import Users
*/
{
String jNameTimeZone = configurationDao.getConfValue("default.timezone", String.class, "Europe/Berlin");
List<User> list = readUserList(f, "users.xml", "users");
int minLoginLength = getMinLoginLength(configurationDao);
for (User u : list) {
if (u.getLogin() == null) {
continue;
}
if (u.getType() == Type.contact && u.getLogin().length() < minLoginLength) {
u.setLogin(UUID.randomUUID().toString());
}
//FIXME: OPENMEETINGS-750
//Convert old Backups with OmTimeZone to new schema
String tz = u.getTimeZoneId();
if (tz == null) {
u.setTimeZoneId(jNameTimeZone);
u.setForceTimeZoneCheck(true);
} else {
u.setForceTimeZoneCheck(false);
}
u.setStarttime(new Date());
long userId = u.getUser_id();
u.setUser_id(null);
if (u.getSipUser() != null && u.getSipUser().getId() != 0) {
u.getSipUser().setId(0);
}
if (!Strings.isEmpty(u.getExternalUserType())) {
u.setType(Type.external);
}
usersDao.update(u, -1L);
usersMap.put(userId, u.getUser_id());
}
}
log.info("Users import complete, starting room import");
/*
* ##################### Import Rooms
*/
{
Registry registry = new Registry();
Strategy strategy = new RegistryStrategy(registry);
RegistryMatcher matcher = new RegistryMatcher(); //TODO need to be removed in the later versions
Serializer serializer = new Persister(strategy, matcher);
matcher.bind(Long.class, LongTransform.class);
matcher.bind(Integer.class, IntegerTransform.class);
registry.bind(User.class, new UserConverter(usersDao, usersMap));
registry.bind(RoomType.class, new RoomTypeConverter(roomTypeDao));
List<Room> list = readList(serializer, f, "rooms.xml", "rooms", Room.class);
for (Room r : list) {
Long roomId = r.getRooms_id();
// We need to reset ids as openJPA reject to store them otherwise
r.setRooms_id(null);
if (r.getModerators() != null) {
for (Iterator<RoomModerator> i = r.getModerators().iterator(); i.hasNext();) {
RoomModerator rm = i.next();
if (rm.getUser().getUser_id() == null) {
i.remove();
}
}
}
r = roomDao.update(r, null);
roomsMap.put(roomId, r.getRooms_id());
}
}
log.info("Room import complete, starting room organizations import");
/*
* ##################### Import Room Organisations
*/
{
Registry registry = new Registry();
Strategy strategy = new RegistryStrategy(registry);
Serializer serializer = new Persister(strategy);
registry.bind(Organisation.class, new OrganisationConverter(orgDao, organisationsMap));
registry.bind(Room.class, new RoomConverter(roomDao, roomsMap));
List<RoomOrganisation> list = readList(serializer, f, "rooms_organisation.xml", "room_organisations", RoomOrganisation.class);
for (RoomOrganisation ro : list) {
if (!ro.getDeleted() && ro.getRoom() != null && ro.getRoom().getRooms_id() != null && ro.getOrganisation() != null && ro.getOrganisation().getOrganisation_id() != null) {
// We need to reset this as openJPA reject to store them otherwise
ro.setRooms_organisation_id(null);
roomOrganisationDao.update(ro, null);
}
}
}
log.info("Room organizations import complete, starting chat messages import");
/*
* ##################### Import Chat messages
*/
{
Registry registry = new Registry();
Strategy strategy = new RegistryStrategy(registry);
Serializer serializer = new Persister(strategy);
registry.bind(User.class, new UserConverter(usersDao, usersMap));
registry.bind(Room.class, new RoomConverter(roomDao, roomsMap));
registry.bind(Date.class, DateConverter.class);
List<ChatMessage> list = readList(serializer, f, "chat_messages.xml", "chat_messages", ChatMessage.class, true);
for (ChatMessage m : list) {
chatDao.update(m);
}
}
log.info("Chat messages import complete, starting appointement import");
/*
* ##################### Import Appointements
*/
{
Registry registry = new Registry();
Strategy strategy = new RegistryStrategy(registry);
Serializer serializer = new Persister(strategy);
registry.bind(AppointmentCategory.class, new AppointmentCategoryConverter(appointmentCategoryDaoImpl));
registry.bind(User.class, new UserConverter(usersDao, usersMap));
registry.bind(AppointmentReminderTyps.class, new AppointmentReminderTypeConverter(appointmentReminderTypDaoImpl));
registry.bind(Room.class, new RoomConverter(roomDao, roomsMap));
registry.bind(Date.class, DateConverter.class);
List<Appointment> list = readList(serializer, f, "appointements.xml", "appointments", Appointment.class);
log.debug(list.size() + " Appointments found in backup");
for (Appointment a : list) {
Long appId = a.getId();
// We need to reset this as openJPA reject to store them otherwise
a.setId(null);
if (a.getOwner() != null && a.getOwner().getUser_id() == null) {
a.setOwner(null);
}
if (a.getRoom() != null && a.getRoom().getRooms_id() == null) {
a.setRoom(null);
}
a = appointmentDao.update(a, null, false);
appointmentsMap.put(appId, a.getId());
}
}
log.info("Appointement import complete, starting meeting members import");
/*
* ##################### Import MeetingMembers
*
* Reminder Invitations will be NOT send!
*/
{
List<MeetingMember> list = readMeetingMemberList(f, "meetingmembers.xml", "meetingmembers");
for (MeetingMember ma : list) {
meetingMemberDao.update(ma);
}
}
log.info("Meeting members import complete, starting ldap config import");
/*
* ##################### Import LDAP Configs
*/
{
List<LdapConfig> list = readList(simpleSerializer, f, "ldapconfigs.xml", "ldapconfigs", LdapConfig.class, true);
for (LdapConfig c : list) {
if (!"local DB [internal]".equals(c.getName())) {
ldapConfigDao.addLdapConfigByObject(c);
}
}
}
log.info("Ldap config import complete, starting cluster servers import");
/*
* ##################### Cluster servers
*/
{
List<Server> list = readList(simpleSerializer, f, "servers.xml", "servers", Server.class, true);
for (Server s : list) {
serverDao.update(s, null);
}
}
log.info("Cluster servers import complete, starting OAuth2 servers import");
/*
* ##################### OAuth2 servers
*/
{
List<OAuthServer> list = readList(simpleSerializer, f, "oauth2servers.xml", "oauth2servers", OAuthServer.class, true);
for (OAuthServer s : list) {
auth2Dao.update(s, null);
}
}
log.info("OAuth2 servers import complete, starting recordings import");
/*
* ##################### Import Recordings
*/
{
Registry registry = new Registry();
Strategy strategy = new RegistryStrategy(registry);
RegistryMatcher matcher = new RegistryMatcher(); //TODO need to be removed in the later versions
Serializer serializer = new Persister(strategy, matcher);
matcher.bind(Long.class, LongTransform.class);
matcher.bind(Integer.class, IntegerTransform.class);
registry.bind(Date.class, DateConverter.class);
List<FlvRecording> list = readList(serializer, f, "flvRecordings.xml", "flvrecordings", FlvRecording.class, true);
for (FlvRecording fr : list) {
fr.setFlvRecordingId(0);
if (fr.getRoom_id() != null) {
fr.setRoom_id(roomsMap.get(fr.getRoom_id()));
}
if (fr.getOwnerId() != null) {
fr.setOwnerId(usersMap.get(fr.getOwnerId()));
}
if (fr.getFlvRecordingMetaData() != null) {
for (FlvRecordingMetaData meta : fr.getFlvRecordingMetaData()) {
meta.setFlvRecordingMetaDataId(0);
meta.setFlvRecording(fr);
}
}
flvRecordingDao.update(fr);
}
}
log.info("FLVrecording import complete, starting private message folder import");
/*
* ##################### Import Private Message Folders
*/
{
List<PrivateMessageFolder> list = readList(simpleSerializer, f, "privateMessageFolder.xml"
, "privatemessagefolders", PrivateMessageFolder.class, true);
for (PrivateMessageFolder p : list) {
Long folderId = p.getPrivateMessageFolderId();
PrivateMessageFolder storedFolder = privateMessageFolderDao.get(folderId);
if (storedFolder == null) {
p.setPrivateMessageFolderId(0);
Long newFolderId = privateMessageFolderDao.addPrivateMessageFolderObj(p);
messageFoldersMap.put(folderId, newFolderId);
}
}
}
log.info("Private message folder import complete, starting user contacts import");
/*
* ##################### Import User Contacts
*/
{
Registry registry = new Registry();
Strategy strategy = new RegistryStrategy(registry);
Serializer serializer = new Persister(strategy);
registry.bind(User.class, new UserConverter(usersDao, usersMap));
List<UserContact> list = readList(serializer, f, "userContacts.xml", "usercontacts", UserContact.class, true);
for (UserContact uc : list) {
Long ucId = uc.getUserContactId();
UserContact storedUC = userContactsDao.get(ucId);
if (storedUC == null && uc.getContact() != null && uc.getContact().getUser_id() != null) {
uc.setUserContactId(0);
if (uc.getOwner() != null && uc.getOwner().getUser_id() == null) {
uc.setOwner(null);
}
Long newId = userContactsDao.addUserContactObj(uc);
userContactsMap.put(ucId, newId);
}
}
}
log.info("Usercontact import complete, starting private messages item import");
/*
* ##################### Import Private Messages
*/
{
Registry registry = new Registry();
Strategy strategy = new RegistryStrategy(registry);
Serializer serializer = new Persister(strategy);
registry.bind(User.class, new UserConverter(usersDao, usersMap));
registry.bind(Room.class, new RoomConverter(roomDao, roomsMap));
registry.bind(Date.class, DateConverter.class);
List<PrivateMessage> list = readList(serializer, f, "privateMessages.xml", "privatemessages", PrivateMessage.class, true);
boolean oldBackup = true;
for (PrivateMessage p : list) {
if (p.getFolderId() < 0) {
oldBackup = false;
break;
}
}
for (PrivateMessage p : list) {
p.setId(0);
p.setFolderId(getNewId(p.getFolderId(), Maps.MESSAGEFOLDERS));
p.setUserContactId(getNewId(p.getUserContactId(), Maps.USERCONTACTS));
if (p.getRoom() != null && p.getRoom().getRooms_id() == null) {
p.setRoom(null);
}
if (p.getTo() != null && p.getTo().getUser_id() == null) {
p.setTo(null);
}
if (p.getFrom() != null && p.getFrom().getUser_id() == null) {
p.setFrom(null);
}
if (p.getOwner() != null && p.getOwner().getUser_id() == null) {
p.setOwner(null);
}
if (oldBackup && p.getOwner() != null && p.getOwner().getUser_id() != null
&& p.getFrom() != null && p.getFrom().getUser_id() != null
&& p.getOwner().getUser_id() == p.getFrom().getUser_id())
{
p.setFolderId(SENT_FOLDER_ID);
}
privateMessagesDao.update(p, null);
}
}
log.info("Private message import complete, starting file explorer item import");
/*
* ##################### Import File-Explorer Items
*/
{
Registry registry = new Registry();
Strategy strategy = new RegistryStrategy(registry);
RegistryMatcher matcher = new RegistryMatcher(); //TODO need to be removed in the later versions
Serializer serializer = new Persister(strategy, matcher);
matcher.bind(Long.class, LongTransform.class);
matcher.bind(Integer.class, IntegerTransform.class);
registry.bind(Date.class, DateConverter.class);
List<FileExplorerItem> list = readList(serializer, f, "fileExplorerItems.xml", "fileExplorerItems", FileExplorerItem.class, true);
for (FileExplorerItem file : list) {
// We need to reset this as openJPA reject to store them otherwise
file.setFileExplorerItemId(0);
Long roomId = file.getRoom_id();
file.setRoom_id(roomsMap.containsKey(roomId) ? roomsMap.get(roomId) : null);
if (file.getOwnerId() != null) {
file.setOwnerId(usersMap.get(file.getOwnerId()));
}
fileExplorerItemDao.addFileExplorerItem(file);
}
}
log.info("File explorer item import complete, starting file poll import");
/*
* ##################### Import Room Polls
*/
{
Registry registry = new Registry();
Strategy strategy = new RegistryStrategy(registry);
RegistryMatcher matcher = new RegistryMatcher(); //TODO need to be removed in the later versions
Serializer serializer = new Persister(strategy, matcher);
matcher.bind(Integer.class, IntegerTransform.class);
registry.bind(User.class, new UserConverter(usersDao, usersMap));
registry.bind(Room.class, new RoomConverter(roomDao, roomsMap));
registry.bind(PollType.class, new PollTypeConverter(pollManager));
registry.bind(Date.class, DateConverter.class);
List<RoomPoll> list = readList(serializer, f, "roompolls.xml", "roompolls", RoomPoll.class, true);
for (RoomPoll rp : list) {
if (rp.getRoom() == null || rp.getRoom().getRooms_id() == null) {
//room was deleted
continue;
}
if (rp.getCreatedBy() == null || rp.getCreatedBy().getUser_id() == null) {
rp.setCreatedBy(null);
}
for (RoomPollAnswers rpa : rp.getRoomPollAnswerList()) {
if (rpa.getVotedUser() == null || rpa.getVotedUser().getUser_id() == null) {
rpa.setVotedUser(null);
}
}
pollManager.savePollBackup(rp);
}
}
log.info("Poll import complete, starting copy of files and folders");
/*
* ##################### Import real files and folders
*/
importFolders(f);
log.info("File explorer item import complete, clearing temp files");
FileHelper.removeRec(f);
}
private <T> List<T> readList(Serializer ser, File baseDir, String fileName, String listNodeName, Class<T> clazz) throws Exception {
return readList(ser, baseDir, fileName, listNodeName, clazz, false);
}
private <T> List<T> readList(Serializer ser, File baseDir, String fileName, String listNodeName, Class<T> clazz, boolean notThow) throws Exception {
List<T> list = new ArrayList<T>();
File xml = new File(baseDir, fileName);
if (!xml.exists()) {
final String msg = fileName + " missing";
if (notThow) {
log.debug(msg);
} else {
throw new Exception(msg);
}
} else {
InputNode root = NodeBuilder.read(new FileInputStream(xml));
InputNode listNode = root.getNext();
if (listNodeName.equals(listNode.getName())) {
InputNode item = listNode.getNext();
while (item != null) {
T o = ser.read(clazz, item, false);
list.add(o);
item = listNode.getNext();
}
}
}
return list;
}
private Node getNode(Node doc, String name) {
NodeList nl = doc.getChildNodes();
for (int i = 0; i < nl.getLength(); ++i) {
Node node = nl.item(i);
if (node.getNodeType() == Node.ELEMENT_NODE && name.equals(node.getNodeName())) {
return node;
}
}
return null;
}
public List<User> readUserList(InputStream xml, String listNodeName) throws Exception {
return readUserList(new InputSource(xml), listNodeName);
}
public List<User> readUserList(File baseDir, String fileName, String listNodeName) throws Exception {
File xml = new File(baseDir, fileName);
if (!xml.exists()) {
throw new Exception(fileName + " missing");
}
return readUserList(new InputSource(xml.toURI().toASCIIString()), listNodeName);
}
//FIXME (need to be removed in later versions) HACK to add external attendees previously stored in MeetingMember structure
private List<MeetingMember> readMeetingMemberList(File baseDir, String filename, String listNodeName) throws Exception {
Registry registry = new Registry();
Strategy strategy = new RegistryStrategy(registry);
Serializer ser = new Persister(strategy);
registry.bind(User.class, new UserConverter(usersDao, usersMap));
registry.bind(Appointment.class, new AppointmentConverter(appointmentDao, appointmentsMap));
File xml = new File(baseDir, filename);
if (!xml.exists()) {
throw new Exception(filename + " missing");
}
DocumentBuilder dBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
Document doc = dBuilder.parse(new InputSource(xml.toURI().toASCIIString()));
StringWriter sw = new StringWriter();
Transformer xformer = TransformerFactory.newInstance().newTransformer();
xformer.transform(new DOMSource(doc), new StreamResult(sw));
List<MeetingMember> list = new ArrayList<MeetingMember>();
InputNode root = NodeBuilder.read(new StringReader(sw.toString()));
InputNode root1 = NodeBuilder.read(new StringReader(sw.toString())); //HACK to handle external attendee's firstname, lastname, email
InputNode listNode = root.getNext();
InputNode listNode1 = root1.getNext(); //HACK to handle external attendee's firstname, lastname, email
if (listNodeName.equals(listNode.getName())) {
InputNode item = listNode.getNext();
InputNode item1 = listNode1.getNext(); //HACK to handle external attendee's firstname, lastname, email
while (item != null) {
MeetingMember mm = ser.read(MeetingMember.class, item, false);
boolean needToSkip1 = true;
if (mm.getUser() == null) {
mm.setUser(new User());
}
if (mm.getUser().getUser_id() == null) {
//HACK to handle external attendee's firstname, lastname, email
boolean contactValid = false;
do {
if (Type.contact == mm.getUser().getType() && "firstname".equals(item1.getName())) {
mm.getUser().setFirstname(item1.getValue());
}
if (Type.contact == mm.getUser().getType() && "lastname".equals(item1.getName())) {
mm.getUser().setLastname(item1.getValue());
}
if ("email".equals(item1.getName())) {
String email = item1.getValue();
if (mm.getAppointment() != null && mm.getAppointment().getOwner() != null) {
mm.setUser(usersDao.getContact(email, mm.getAppointment().getOwner()));
}
contactValid = true;
}
item1 = listNode1.getNext(); //HACK to handle old om_time_zone
} while (item1 != null && !"meetingmember".equals(item1.getName()));
if (!contactValid) {
mm = null;
}
needToSkip1 = false;
}
if (needToSkip1) {
do {
item1 = listNode1.getNext(); //HACK to handle Address inside user
} while (item1 != null && !"meetingmember".equals(item1.getName()));
}
item = listNode.getNext();
if (mm != null && !mm.isDeleted() && mm.getUser() != null && mm.getAppointment() != null && mm.getAppointment().getId() != null) {
mm.setId(null);
list.add(mm);
}
}
}
return list;
}
//FIXME (need to be removed in later versions) HACK to fix 2 deleted nodes in users.xml and inline Adresses and sipData
private List<User> readUserList(InputSource xml, String listNodeName) throws Exception {
Registry registry = new Registry();
Strategy strategy = new RegistryStrategy(registry);
Serializer ser = new Persister(strategy);
registry.bind(Organisation.class, new OrganisationConverter(orgDao, organisationsMap));
registry.bind(State.class, new StateConverter(statemanagement));
registry.bind(Date.class, DateConverter.class);
DocumentBuilder dBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
Document doc = dBuilder.parse(xml);
NodeList nl = getNode(getNode(doc, "root"), listNodeName).getChildNodes();
userEmailMap.clear();
//add existence email from database
List<User> users = usersDao.getAllUsers();
for (User u : users){
if (u.getAdresses() == null || u.getAdresses().getEmail() == null || Type.user != u.getType()) {
continue;
}
userEmailMap.put(u.getAdresses().getEmail(), -1);
}
// one of the old OM version created 2 nodes "deleted" this code block handles this
for (int i = 0; i < nl.getLength(); ++i) {
Node user = nl.item(i);
NodeList nl1 = user.getChildNodes();
boolean deletedFound = false;
for (int j = 0; j < nl1.getLength(); ++j) {
Node node = nl1.item(j);
if (node.getNodeType() == Node.ELEMENT_NODE && "deleted".equals(node.getNodeName())) {
if (deletedFound) {
user.removeChild(node);
break;
}
deletedFound = true;
}
}
}
StringWriter sw = new StringWriter();
Transformer xformer = TransformerFactory.newInstance().newTransformer();
xformer.transform(new DOMSource(doc), new StreamResult(sw));
List<User> list = new ArrayList<User>();
InputNode root = NodeBuilder.read(new StringReader(sw.toString()));
InputNode root1 = NodeBuilder.read(new StringReader(sw.toString())); //HACK to handle Address inside user
InputNode root2 = NodeBuilder.read(new StringReader(sw.toString())); //HACK to handle old om_time_zone, level_id, status
InputNode listNode = root.getNext();
InputNode listNode1 = root1.getNext(); //HACK to handle Address inside user
InputNode listNode2 = root2.getNext(); //HACK to handle old om_time_zone
if (listNodeName.equals(listNode.getName())) {
InputNode item = listNode.getNext();
InputNode item1 = listNode1.getNext(); //HACK to handle Address inside user
InputNode item2 = listNode2.getNext(); //HACK to handle old om_time_zone, level_id, status
while (item != null) {
User u = ser.read(User.class, item, false);
boolean needToSkip1 = true;
//HACK to handle Address inside user
if (u.getAdresses() == null) {
Address a = ser.read(Address.class, item1, false);
u.setAdresses(a);
needToSkip1 = false;
}
if (needToSkip1) {
do {
item1 = listNode1.getNext(); //HACK to handle Address inside user
} while (item1 != null && !"user".equals(item1.getName()));
}
String level_id = null, status = null;
do {
if (u.getTimeZoneId() == null && "omTimeZone".equals(item2.getName())) {
String jName = item2.getValue();
u.setTimeZoneId(jName == null ? null : tzUtil.getTimezoneByInternalJName(jName).getID());
}
if ("level_id".equals(item2.getName())) {
level_id = item2.getValue();
}
if ("status".equals(item2.getName())) {
status = item2.getValue();
}
item2 = listNode2.getNext(); //HACK to handle old om_time_zone, level_id, status
} while (item2 != null && !"user".equals(item2.getName()));
if (u.getRights().isEmpty()) {
u.getRights().add(Right.Room);
if ("1".equals(status)) {
u.getRights().add(Right.Dashboard);
u.getRights().add(Right.Login);
}
if ("3".equals(level_id)) {
u.getRights().add(Right.Admin);
u.getRights().add(Right.Soap);
}
if ("4".equals(level_id)) {
u.getRights().add(Right.Soap);
}
}
// check that email is unique
if (u.getAdresses() != null && u.getAdresses().getEmail() != null && Type.user == u.getType()) {
if (userEmailMap.containsKey(u.getAdresses().getEmail())) {
log.warn("Email is duplicated for user " + u.toString());
String updateEmail = "modified_by_import_<" + list.size() + ">" + u.getAdresses().getEmail();
u.getAdresses().setEmail(updateEmail);
}
userEmailMap.put(u.getAdresses().getEmail(), userEmailMap.size());
}
list.add(u);
item = listNode.getNext();
}
}
return list;
}
private Long getProfileId(File f) {
String n = f.getName();
if (n.indexOf(profilesPrefix) > -1) {
return importLongType(n.substring(profilesPrefix.length()));
}
return null;
}
private void importFolders(File importBaseDir) throws IOException {
// Now check the room files and import them
File roomFilesFolder = new File(importBaseDir, "roomFiles");
File uploadDir = getUploadDir();
log.debug("roomFilesFolder PATH " + roomFilesFolder.getCanonicalPath());
if (roomFilesFolder.exists()) {
for (File file : roomFilesFolder.listFiles()) {
if (file.isDirectory()) {
String fName = file.getName();
if ("profiles".equals(fName)) {
// profile should correspond to the new user id
for (File profile : file.listFiles()) {
Long oldId = getProfileId(profile);
Long id = oldId != null ? getNewId(oldId, Maps.USERS) : null;
if (id != null) {
copyRec(profile, getUploadProfilesUserDir(id));
}
}
continue;
} else {
// check if folder is room folder, store it under new id if necessary
Long oldId = importLongType(fName);
Long id = oldId != null ? getNewId(oldId, Maps.ROOMS) : null;
if (id != null) {
copyRec(file, getUploadRoomDir(id.toString()));
continue;
}
}
copyRec(file, new File(uploadDir, fName));
}
}
}
// Now check the recordings and import them
File sourceDirRec = new File(importBaseDir, "recordingFiles");
log.debug("sourceDirRec PATH " + sourceDirRec.getCanonicalPath());
if (sourceDirRec.exists()) {
copyRec(sourceDirRec, getStreamsHibernateDir());
}
}
private Long importLongType(String value) {
Long val = null;
try {
val = Long.valueOf(value);
} catch (Exception e) {
// no-op
}
return val;
}
private Long getNewId(Long oldId, Maps map) {
Long newId = oldId;
switch (map) {
case USERS:
if (usersMap.containsKey(oldId)) {
newId = usersMap.get(oldId);
}
break;
case ORGANISATIONS:
if (organisationsMap.containsKey(oldId)) {
newId = organisationsMap.get(oldId);
}
break;
case APPOINTMENTS:
if (appointmentsMap.containsKey(oldId)) {
newId = appointmentsMap.get(oldId);
}
break;
case ROOMS:
if (roomsMap.containsKey(oldId)) {
newId = roomsMap.get(oldId);
}
break;
case MESSAGEFOLDERS:
if (messageFoldersMap.containsKey(oldId)) {
newId = messageFoldersMap.get(oldId);
}
break;
case USERCONTACTS:
if (userContactsMap.containsKey(oldId)) {
newId = userContactsMap.get(oldId);
}
break;
default:
break;
}
return newId;
}
}