/* * Copyright (C) 2003-2010 eXo Platform SAS. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Affero General Public License * as published by the Free Software Foundation; either version 3 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see<http://www.gnu.org/licenses/>. */ package org.exoplatform.platform.organization.injector; import java.io.ByteArrayOutputStream; import java.io.FileInputStream; import java.io.InputStream; import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.util.zip.ZipEntry; import java.util.zip.ZipInputStream; import java.util.zip.ZipOutputStream; import org.exoplatform.commons.utils.ListAccess; import org.exoplatform.container.PortalContainer; import org.exoplatform.container.component.RequestLifeCycle; import org.exoplatform.container.configuration.ConfigurationManager; import org.exoplatform.container.xml.Component; import org.exoplatform.container.xml.ComponentPlugin; import org.exoplatform.container.xml.Configuration; import org.exoplatform.container.xml.ExternalComponentPlugins; import org.exoplatform.services.log.ExoLogger; import org.exoplatform.services.log.Log; import org.exoplatform.services.organization.Group; import org.exoplatform.services.organization.Membership; import org.exoplatform.services.organization.MembershipType; import org.exoplatform.services.organization.OrganizationConfig; import org.exoplatform.services.organization.OrganizationService; import org.exoplatform.services.organization.User; import org.exoplatform.services.organization.UserProfile; import org.exoplatform.services.organization.idm.PicketLinkIDMOrganizationServiceImpl; import org.exoplatform.services.organization.idm.PicketLinkIDMService; import org.exoplatform.services.organization.impl.UserImpl; import org.exoplatform.services.organization.impl.UserProfileImpl; import org.hibernate.Session; import org.hibernate.criterion.Restrictions; import org.picketlink.idm.api.IdentitySession; import org.picketlink.idm.impl.api.PasswordCredential; import org.picketlink.idm.impl.api.session.IdentitySessionImpl; import org.picketlink.idm.impl.model.hibernate.HibernateIdentityObject; import org.picketlink.idm.impl.model.hibernate.HibernateIdentityObjectCredential; import org.picketlink.idm.impl.model.hibernate.HibernateIdentityObjectType; import org.picketlink.idm.impl.repository.RepositoryIdentityStoreSessionImpl; import org.picketlink.idm.spi.store.IdentityStoreInvocationContext; import org.picocontainer.Startable; import com.thoughtworks.xstream.XStream; import com.thoughtworks.xstream.io.xml.XppDriver; public class DataInjectorService implements Startable { private static final String CONFIGURATION_XML_SUFFIX = "-configuration.xml"; private static final Log LOG = ExoLogger.getLogger(DataInjectorService.class); private List<UserImpl> usersData = new ArrayList<UserImpl>(); private List<UserProfileImpl> userProfilesData = new ArrayList<UserProfileImpl>(); private OrganizationService organizationService; private PicketLinkIDMService picketLinkIDMService; private ConfigurationManager configurationManager; private List<DataPlugin> dataPlugins = new ArrayList<DataPlugin>(); public DataInjectorService(OrganizationService organizationService, ConfigurationManager configurationManager) { this.organizationService = organizationService; this.configurationManager = configurationManager; this.picketLinkIDMService = (PicketLinkIDMService) PortalContainer.getInstance().getComponentInstanceOfType( PicketLinkIDMService.class); } @Override public void start() { try { doImport(false); } catch (Exception exception) { LOG.error("Cannot inject Organization Model Data", exception); } } @SuppressWarnings({ "unchecked", "deprecation" }) public void doImport(boolean isArchive) throws Exception { RequestLifeCycle.begin(PortalContainer.getInstance()); try { for (DataPlugin dataPlugin : dataPlugins) { dataPlugin.init(); } if (!isArchive) { for (DataPlugin dataPlugin : dataPlugins) { List<OrganizationConfig.User> users = (List<OrganizationConfig.User>)dataPlugin.getConfig().getUser(); if (users == null || users.isEmpty()) { continue; } for (OrganizationConfig.User injectedUser : users) { String xmlContent = getXMLContent(SerializationUtils.USERS_FOLDER_NAME + injectedUser.getUserName() + SerializationUtils.USER_FILE_SUFFIX); if (xmlContent != null) { XStream xstreamUser_ = new XStream(new XppDriver()); xstreamUser_.alias("user", UserImpl.class); UserImpl userToImport = (UserImpl) xstreamUser_.fromXML(new String(xmlContent)); User user = organizationService.getUserHandler().findUserByName(userToImport.getUserName()); if (userToImport.getLastLoginTime() != null) { user.setLastLoginTime(userToImport.getLastLoginTime()); } if (userToImport.getCreatedDate() != null) { user.setCreatedDate(userToImport.getCreatedDate()); } organizationService.getUserHandler().saveUser(user, false); } xmlContent = getXMLContent(SerializationUtils.PROFILES_FOLDER_NAME + injectedUser.getUserName() + SerializationUtils.PROFILE_FILE_SUFFIX); if (xmlContent != null) { XStream xstreamProfile_ = new XStream(new XppDriver()); xstreamProfile_.alias("user-profile", UserProfileImpl.class); UserProfileImpl userProfile = (UserProfileImpl) xstreamProfile_.fromXML(xmlContent); organizationService.getUserProfileHandler().saveUserProfile(userProfile, false); } } } } else { for (UserImpl importedUser : usersData) { User user = organizationService.getUserHandler().findUserByName(importedUser.getUserName()); if (user != null) { if (importedUser.getLastLoginTime() != null) { user.setLastLoginTime(importedUser.getLastLoginTime()); } if (importedUser.getCreatedDate() != null) { user.setCreatedDate(importedUser.getCreatedDate()); } organizationService.getUserHandler().saveUser(user, false); } else { LOG.warn("user = " + importedUser.getUserName() + " doesn't exist"); } } for (UserProfileImpl userProfile : userProfilesData) { User user = organizationService.getUserHandler().findUserByName(userProfile.getUserName()); if (user != null) { organizationService.getUserProfileHandler().saveUserProfile(userProfile, true); } else { LOG.warn("userProfile = " + userProfile.getUserName() + " doesn't exist"); } } } } finally { RequestLifeCycle.end(); } } @Override public void stop() {} public void addDataPlugin(DataPlugin dataPlugin) { dataPlugins.add(dataPlugin); } public void readDataPlugins(String filePath) throws Exception { dataPlugins.clear(); FileInputStream fin = new FileInputStream(filePath); ZipInputStream zin = new ZipInputStream(fin); ZipEntry ze = null; while ((ze = zin.getNextEntry()) != null) { if (ze.getName().equals("configuration.xml") || ze.getName().contains(CONFIGURATION_XML_SUFFIX)) { ByteArrayOutputStream fout = new ByteArrayOutputStream(); for (int c = zin.read(); c != -1; c = zin.read()) { fout.write(c); } zin.closeEntry(); Configuration tmpConfiguration = SerializationUtils.fromXML(fout.toByteArray(), Configuration.class); Component component = tmpConfiguration.getComponent(DataInjectorService.class.getName()); ExternalComponentPlugins externalComponentPlugins = tmpConfiguration .getExternalComponentPlugins(DataInjectorService.class.getName()); if (component != null && component.getComponentPlugins() != null && !component.getComponentPlugins().isEmpty()) { this.addComponentPlugins(component.getComponentPlugins()); } else if (externalComponentPlugins != null && externalComponentPlugins.getComponentPlugins() != null && !externalComponentPlugins.getComponentPlugins().isEmpty()) { this.addComponentPlugins(externalComponentPlugins.getComponentPlugins()); } } } zin.close(); } private void addComponentPlugins(List<ComponentPlugin> plugins) { if (plugins == null || plugins.isEmpty()) { return; } for (ComponentPlugin plugin : plugins) { try { DataPlugin dataPlugin = PortalContainer.getInstance().createComponent(DataPlugin.class, plugin.getInitParams()); dataPlugin.setName(plugin.getName()); dataPlugin.setDescription(plugin.getDescription()); this.addDataPlugin(dataPlugin); } catch (Exception e) { LOG.error("Failed to instanciate component plugin " + plugin.getName() + ", type=" + plugin.getClass(), e); } } } public void writeOrganizationModelData(ZipOutputStream zos) throws Exception { RequestLifeCycle.begin(PortalContainer.getInstance()); try { Configuration configuration = new Configuration(); Component component = new Component(); component.setType(DataInjectorService.class.getName()); configuration.addComponent(component); {// groups & membershipTypes entry List<OrganizationConfig.Group> groups = getAllGroups(); List<OrganizationConfig.MembershipType> membershipTypes = getAllMembershipTypes(); Configuration organizationServiceConfiguration = SerializationUtils .buildOrganizationServiceConfiguration(SerializationUtils.getOrganizationConfig(groups, membershipTypes, null)); SerializationUtils.addEntry(zos, SerializationUtils.toXML(organizationServiceConfiguration), "OrganizationDataModel/Groups-MembershipTypes-configuration.xml"); configuration.addImport("OrganizationDataModel/Groups-MembershipTypes-configuration.xml"); } {// Write Users ListAccess<User> usersListAccess = organizationService.getUserHandler().findAllUsers(); List<OrganizationConfig.User> orgConfigUsersInSigleFile = new ArrayList<OrganizationConfig.User>(); int i = 0; while (i <= usersListAccess.getSize()) { int length = i + SerializationUtils.MAX_USERS_IN_FILE_PARAM_NAME <= usersListAccess.getSize() ? SerializationUtils.MAX_USERS_IN_FILE_PARAM_NAME : usersListAccess.getSize() - i; User[] users = usersListAccess.load(i, length); for (User user : users) { OrganizationConfig.User orgConfigUser = convertUserToSerializableObject(user); orgConfigUsersInSigleFile.add(orgConfigUser); } Configuration organizationServiceConfiguration = SerializationUtils .buildOrganizationServiceConfiguration(SerializationUtils.getOrganizationConfig(null, null, orgConfigUsersInSigleFile)); SerializationUtils.addEntry(zos, SerializationUtils.toXML(organizationServiceConfiguration), "OrganizationDataModel/Users" + i + CONFIGURATION_XML_SUFFIX); orgConfigUsersInSigleFile.clear(); configuration.addImport("OrganizationDataModel/Users" + i + CONFIGURATION_XML_SUFFIX); i += SerializationUtils.MAX_USERS_IN_FILE_PARAM_NAME; } } SerializationUtils.addEntry(zos, SerializationUtils.toXML(configuration), "configuration.xml"); } finally { RequestLifeCycle.end(); } } public void writeProfiles(ZipOutputStream zos) throws Exception { RequestLifeCycle.begin(PortalContainer.getInstance()); try { ListAccess<User> usersListAccess = organizationService.getUserHandler().findAllUsers(); XStream xstream_ = new XStream(new XppDriver()); int i = 0; while (i <= usersListAccess.getSize()) { int length = i + SerializationUtils.MAX_USERS_IN_FILE_PARAM_NAME <= usersListAccess.getSize() ? SerializationUtils.MAX_USERS_IN_FILE_PARAM_NAME : usersListAccess.getSize() - i; User[] users = usersListAccess.load(i, length); for (User user : users) { UserProfile userProfile = organizationService.getUserProfileHandler().findUserProfileByName(user.getUserName()); if ((userProfile != null) && (userProfile.getUserInfoMap() != null) && !userProfile.getUserInfoMap().isEmpty()) { xstream_.alias("user-profile", userProfile.getClass()); String xml = xstream_.toXML(userProfile); zos.putNextEntry(new ZipEntry(SerializationUtils.PROFILES_FOLDER_NAME + userProfile.getUserName() + SerializationUtils.PROFILE_FILE_SUFFIX)); zos.write(xml.getBytes()); zos.closeEntry(); if (LOG.isDebugEnabled()) { LOG.debug("Adding entry for userProfile: " + userProfile.getUserName()); } } } i += SerializationUtils.MAX_USERS_IN_FILE_PARAM_NAME; } } finally { RequestLifeCycle.end(); } } public void writeUsers(ZipOutputStream zos) throws Exception { RequestLifeCycle.begin(PortalContainer.getInstance()); try { if (LOG.isDebugEnabled()) { LOG.debug("Adding entries for each user, additional fields are missing: LastLoginTime & CreatedDate"); } ListAccess<User> usersListAccess = organizationService.getUserHandler().findAllUsers(); XStream xstream_ = new XStream(new XppDriver()); int i = 0; while (i <= usersListAccess.getSize()) { int length = i + SerializationUtils.MAX_USERS_IN_FILE_PARAM_NAME <= usersListAccess.getSize() ? SerializationUtils.MAX_USERS_IN_FILE_PARAM_NAME : usersListAccess.getSize() - i; User[] users = usersListAccess.load(i, length); for (User user : users) { if (user != null) { xstream_.alias("user", user.getClass()); String xml = xstream_.toXML(user); zos.putNextEntry(new ZipEntry(SerializationUtils.USERS_FOLDER_NAME + user.getUserName() + SerializationUtils.USER_FILE_SUFFIX)); zos.write(xml.getBytes()); zos.closeEntry(); if (LOG.isDebugEnabled()) { LOG.debug("Adding entry for user: " + user.getUserName()); } } } i += SerializationUtils.MAX_USERS_IN_FILE_PARAM_NAME; } } finally { RequestLifeCycle.end(); } } private OrganizationConfig.User convertUserToSerializableObject(User user) throws Exception { OrganizationConfig.User orgConfigUser = new OrganizationConfig.User(); orgConfigUser.setEmail(user.getEmail()); orgConfigUser.setFirstName(user.getFirstName()); orgConfigUser.setLastName(user.getLastName()); if (organizationService instanceof PicketLinkIDMOrganizationServiceImpl) { orgConfigUser.setPassword(readPasswordFromPicketLink(user)); } else { orgConfigUser.setPassword(user.getPassword()); } orgConfigUser.setUserName(user.getUserName()); @SuppressWarnings("unchecked") Collection<Membership> memberships = organizationService.getMembershipHandler().findMembershipsByUser(user.getUserName()); String groups = ""; for (Membership membership : memberships) { groups = new StringBuffer().append(groups).append(membership.getMembershipType()).append(":").append(membership.getGroupId()).append(",").toString(); //NOSONAR groups.substring(0, groups.lastIndexOf(",")); } orgConfigUser.setGroups(groups); return orgConfigUser; } public void readUsersData(String filePath) throws Exception { usersData.clear(); XStream xstreamUser_ = new XStream(new XppDriver()); xstreamUser_.alias("user", UserImpl.class); FileInputStream fin = new FileInputStream(filePath); ZipInputStream zin = new ZipInputStream(fin); ZipEntry ze = null; while ((ze = zin.getNextEntry()) != null) { if (ze.getName().contains("_user.xml")) { ByteArrayOutputStream fout = new ByteArrayOutputStream(); for (int c = zin.read(); c != -1; c = zin.read()) { fout.write(c); } zin.closeEntry(); UserImpl importedUser = (UserImpl) xstreamUser_.fromXML(new String(fout.toByteArray())); usersData.add(importedUser); } } zin.close(); } public void readUserProfilesData(String filePath) throws Exception { userProfilesData.clear(); XStream xstreamProfile_ = new XStream(new XppDriver()); xstreamProfile_.alias("user-profile", UserProfileImpl.class); FileInputStream fin = new FileInputStream(filePath); ZipInputStream zin = new ZipInputStream(fin); ZipEntry ze = null; while ((ze = zin.getNextEntry()) != null) { if (ze.getName().contains("_profile.xml")) { ByteArrayOutputStream fout = new ByteArrayOutputStream(); for (int c = zin.read(); c != -1; c = zin.read()) { fout.write(c); } zin.closeEntry(); UserProfileImpl userProfile = (UserProfileImpl) xstreamProfile_.fromXML(new String(fout.toByteArray())); userProfilesData.add(userProfile); } } zin.close(); } private List<OrganizationConfig.Group> getAllGroups() throws Exception { List<OrganizationConfig.Group> allGroups = new ArrayList<OrganizationConfig.Group>(); try { @SuppressWarnings("unchecked") Collection<Group> groups = organizationService.getGroupHandler().getAllGroups(); for (Group group : groups) { OrganizationConfig.Group orgConfGroup = new OrganizationConfig.Group(); orgConfGroup.setDescription(group.getDescription()); orgConfGroup.setLabel(group.getLabel()); orgConfGroup.setName(group.getGroupName()); orgConfGroup.setParentId(group.getParentId()); allGroups.add(orgConfGroup); } } catch (Exception e) { LOG.error("Error when recovering of all groups ... ", e); return null; } return allGroups; } private List<OrganizationConfig.MembershipType> getAllMembershipTypes() throws Exception { List<OrganizationConfig.MembershipType> allMembershipTypes = new ArrayList<OrganizationConfig.MembershipType>(); try { @SuppressWarnings("unchecked") Collection<MembershipType> membershipTypes = organizationService.getMembershipTypeHandler().findMembershipTypes(); for (MembershipType membershipType : membershipTypes) { OrganizationConfig.MembershipType orgConfMemberShipType = new OrganizationConfig.MembershipType(); orgConfMemberShipType.setDescription(membershipType.getDescription()); orgConfMemberShipType.setType(membershipType.getName()); allMembershipTypes.add(orgConfMemberShipType); } } catch (Exception e) { LOG.error("Error when recovering of all membershipTypes ... ", e); return null; } return allMembershipTypes; } private String getXMLContent(String filePath) { String xmlContent = null; try { InputStream xmlInputStream = configurationManager.getInputStream(filePath); byte[] bytes = new byte[xmlInputStream.available()]; xmlInputStream.read(bytes); xmlContent = new String(bytes); } catch (Exception exception) { LOG.error("file wasn't found ", exception); } return xmlContent; } private String readPasswordFromPicketLink(User user) throws Exception { PicketLinkIDMOrganizationServiceImpl orgService = (PicketLinkIDMOrganizationServiceImpl) organizationService; if (orgService.getConfiguration().isPasswordAsAttribute()) { return user.getPassword(); } else { IdentitySession identitySession = picketLinkIDMService.getIdentitySession(); IdentityStoreInvocationContext identitySessionContext = ((IdentitySessionImpl) identitySession).getSessionContext() .resolveStoreInvocationContext(); Session session = ((Session) ((RepositoryIdentityStoreSessionImpl) identitySessionContext.getIdentityStoreSession()) .getIdentityStoreSession("HibernateStore").getSessionContext()); HibernateIdentityObjectType hibernateIdentityObjectType = (HibernateIdentityObjectType) session .createCriteria(HibernateIdentityObjectType.class).add(Restrictions.eq("name", "USER")).uniqueResult(); HibernateIdentityObject hibernateUserObject = (HibernateIdentityObject) session .createCriteria(HibernateIdentityObject.class).add(Restrictions.eq("name", user.getUserName())) .add(Restrictions.eq("identityType", hibernateIdentityObjectType)).uniqueResult(); HibernateIdentityObjectCredential hibernateCredential = (HibernateIdentityObjectCredential) session .createCriteria(HibernateIdentityObjectCredential.class).createAlias("type", "t") .add(Restrictions.eq("t.name", PasswordCredential.TYPE.getName())) .add(Restrictions.eq("identityObject", hibernateUserObject)).setCacheable(true).uniqueResult(); if (hibernateCredential != null) { return hibernateCredential.getTextValue(); } else { return ""; } } } }