/*
* Copyright 2016 Ryan Graham
*
* Licensed 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.jivesoftware.openfire.plugin;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.StringWriter;
import java.util.List;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.lang.StringEscapeUtils;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.XMLWriter;
import org.jivesoftware.openfire.container.Plugin;
import org.jivesoftware.openfire.container.PluginManager;
import org.jivesoftware.openfire.user.UserManager;
import org.jivesoftware.openfire.user.UserProvider;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* The user import/export plugin provides a way to import and export Openfire
* user data via the Admin Console. The user data consists of username,
* name, email address, password and roster list (aka "buddy list"). This plugin also
* can aid in the migration of users from other Jabber/XMPP based systems to Jive
* Openfire.
*
* @author <a href="mailto:ryan@version2software.com">Ryan Graham</a>
*/
public class ImportExportPlugin implements Plugin {
private static final Logger Log = LoggerFactory.getLogger(ImportExportPlugin.class);
private UserProvider provider;
public ImportExportPlugin() {
provider = UserManager.getUserProvider();
}
public void initializePlugin(PluginManager manager, File pluginDirectory) {
}
public void destroyPlugin() {
provider = null;
}
/**
* Convenience method that returns true if this UserProvider is read-only.
*
* @return true if the user provider is read-only.
*/
public boolean isUserProviderReadOnly() {
return provider.isReadOnly();
}
/**
* Converts the user data that is to be exported to a byte[]. If a read-only
* user store is being used a user's password will be the same as their username.
*
* @return a byte[] of the user data.
* @throws IOException if there's a problem writing to the XMLWriter.
*/
public byte[] exportUsersToByteArray(boolean xep227Support) throws IOException {
ByteArrayOutputStream out = new ByteArrayOutputStream();
XMLWriter writer = new XMLWriter(out, OutputFormat.createPrettyPrint());
writer.write(exportUsers(xep227Support));
return out.toByteArray();
}
/**
* Converts the exported user data to a String. If a read-only
* user store is being used a user's password will be the same as their username.
*
* @return a formatted String representation of the user data.
* @throws IOException if there's a problem writing to the XMLWriter.
*/
public String exportUsersToString(boolean xep227Support) throws IOException {
StringWriter stringWriter = new StringWriter();
XMLWriter writer = null;
try {
writer = new XMLWriter(stringWriter, OutputFormat.createPrettyPrint());
writer.write(exportUsers(xep227Support));
} catch (IOException ioe) {
Log.error(ioe.getMessage(), ioe);
throw ioe;
} finally {
if (writer != null) {
writer.close();
}
}
return StringEscapeUtils.escapeHtml(stringWriter.toString());
}
/**
* Returns a list of usernames that were unable to be imported or whose rosters could not imported. Users are not able to be
* imported for the following reasons:
* <li>Their username is not properly formatted.
* <li>If a read-only user data store is being used and the user could not be found.
* <li>If a writeable user data store is being used and the user already exists.
*
* @param file a FileItem containing the user data to be imported.
* @param previousDomain a String an optional parameter that if supplied will replace the user roster entries domain names to
* server name of current Openfire installation.
* @return True if FileItem matches the openfire user schema.
* @throws IOException if there is a problem reading the FileItem.
* @throws DocumentException if an error occurs during parsing.
*/
public List<String> importUserData(FileItem file, String previousDomain, boolean xep227Support) throws DocumentException, IOException {
InExporter exporter = XMLImportExportFactory.getExportInstance(xep227Support);
return exporter.importUsers(file.getInputStream(), previousDomain,isUserProviderReadOnly());
}
/**
* Returns whether or not the supplied FileItem matches the openfire user schema
*
* @param file a FileItem to be validated.
* @return True if FileItem matches the openfire user schema.
*/
public boolean validateImportFile(FileItem usersFile, boolean xep227Support) {
try {
InExporter exporter = XMLImportExportFactory.getExportInstance(xep227Support);
return exporter.validate(usersFile.getInputStream());
}
catch (Exception e) {
Log.error(e.getMessage(), e);
return false;
}
}
private Document exportUsers(boolean xep227Support) {
InExporter exporter = XMLImportExportFactory.getExportInstance(xep227Support);
return exporter.exportUsers();
}
}