blob: c7b8904bb3d7c6b199b4f344a47fcbdb29007a4e [file] [log] [blame]
//------------------------------------------------------------------------------
// Copyright (c) 2005, 2006 IBM Corporation and others.
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// which accompanies this distribution, and is available at
// http://www.eclipse.org/legal/epl-v10.html
//
// Contributors:
// IBM Corporation - initial implementation
//------------------------------------------------------------------------------
package org.eclipse.epf.importing.services;
import java.io.File;
import java.io.FileFilter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import org.apache.tools.ant.Project;
import org.apache.tools.ant.taskdefs.Copy;
import org.apache.tools.ant.types.FileSet;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.epf.common.serviceability.MsgDialog;
import org.eclipse.epf.common.utils.FileUtil;
import org.eclipse.epf.common.utils.XMLUtil;
import org.eclipse.epf.export.services.LibraryDocument;
import org.eclipse.epf.importing.ImportPlugin;
import org.eclipse.epf.importing.ImportResources;
import org.eclipse.epf.library.LibraryService;
import org.eclipse.epf.library.LibraryServiceUtil;
import org.eclipse.epf.library.services.LibraryProcessor;
import org.eclipse.epf.library.services.SafeUpdateController;
import org.eclipse.epf.library.util.ResourceHelper;
import org.eclipse.epf.persistence.refresh.RefreshJob;
import org.eclipse.epf.uma.MethodConfiguration;
import org.eclipse.epf.uma.MethodLibrary;
import org.eclipse.epf.uma.MethodPlugin;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
/**
* Imports a method plug-in into the current library.
*
* @author Jinhua Xi
* @since 1.0
*/
public class PluginImportingService {
private PluginImportData data;
LibraryDocument importingLibDoc;
// flag to indicate the file cheout status
IStatus fileCheckedOutStatus = null;
public PluginImportingService(PluginImportData data) {
this.data = data;
}
/**
* Validates the plug-in against the current library, collects all the
* informations including plug-in info, configuation info and error info.
* Call this method, then call getError(), getPlugins(), getConfigs().
*/
public void validate(IProgressMonitor monitor) {
try {
if (monitor != null) {
monitor.setTaskName(ImportResources
.getString("Import.PluginImportingService.MSG0")); //$NON-NLS-1$
}
if (this.data == null) {
return;
}
this.data.clear();
// Prepare the lib files.
File importingLibPath = new File(data.llData.getParentFolder()
+ File.separator + LibraryDocument.exportFile);
if (!importingLibPath.exists()) {
data
.getErrorInfo()
.addError(
ImportResources
.getString(
"Import.PluginImportingService.MSG1", importingLibPath.toString())); //$NON-NLS-1$
return;
}
importingLibDoc = new LibraryDocument(importingLibPath);
scanLibraryFile(importingLibDoc);
} catch (Exception ex) {
ex.printStackTrace();
}
}
public void performImport(IProgressMonitor monitor) throws Exception {
// need to disable the workspace refreshing
boolean refresh = RefreshJob.getInstance().isEnabled();
try {
if (refresh) {
// disable resource refreshing during import
//
RefreshJob.getInstance().setEnabled(false);
}
__doImport(monitor);
} finally {
if (refresh) {
// re-enable resource refreshing
//
RefreshJob.getInstance().setEnabled(true);
}
}
}
private void __doImport(IProgressMonitor monitor) {
try {
if (monitor != null) {
monitor.setTaskName(ImportResources
.getString("Import.PluginImportingService.MSG3")); //$NON-NLS-1$
}
List unlockedPlugins = unlockPlugins();
// To import the plug-ins, we need to do the following:
// 1. Delete the plug-ins in the current library if user specify
// remove
// 2. Copy the selected plugin files to the destination
// 3. Update the library.xmi
// 4. Reload the library
File libFile = new File(LibraryService.getInstance()
.getCurrentMethodLibrary().eResource().getURI()
.toFileString());
LibraryDocument targetLibDoc = new LibraryDocument(libFile);
// // Remove existing entries.
// removeExistingEntries(targetLibDoc);
// Import entries and copy files.
if (importEntries(targetLibDoc)) {
// Save the updated library file.
targetLibDoc.save();
// Replace the guid of the old MethodLibrary with the new one.
fixLibraryGuid(libFile.getParentFile(), importingLibDoc
.getLibraryGuid(), targetLibDoc.getLibraryGuid());
// Reopen the library.
LibraryProcessor.getInstance().openLibrary(
libFile.getAbsolutePath());
// finally, re-lock the unlocked plugins and save the library
// again
if (unlockedPlugins.size() > 0) {
lockUnlockedPlugins(unlockedPlugins);
LibraryService.getInstance().saveCurrentMethodLibrary();
}
}
// re-open library and fresh the workspace
MethodLibrary library = LibraryService.getInstance()
.reopenCurrentMethodLibrary();
} catch (Exception e) {
ImportPlugin.getDefault().getLogger().logError(e);
}
}
private List unlockPlugins() {
List pluginIds = new ArrayList();
PluginImportData.PluginInfo info;
for (Iterator it = data.getPlugins().iterator(); it.hasNext();) {
info = (PluginImportData.PluginInfo) it.next();
if ((info.existingPlugin != null) && info.selected) {
if (info.existingPlugin.getUserChangeable().booleanValue() == false) {
info.existingPlugin.setUserChangeable(new Boolean(true));
pluginIds.add(info.existingPlugin.getGuid());
}
}
}
return pluginIds;
}
private void lockUnlockedPlugins(List unlockedPlugins) {
List plugins = LibraryService.getInstance().getCurrentMethodLibrary()
.getMethodPlugins();
for (Iterator it = plugins.iterator(); it.hasNext();) {
MethodPlugin plugin = (MethodPlugin) it.next();
if (unlockedPlugins.contains(plugin.getGuid())) {
plugin.setUserChangeable(new Boolean(false));
}
}
}
private boolean importEntries(LibraryDocument targetLibDoc) {
// 1. Find the entries to be removed.
List importList = new ArrayList();
List newList = new ArrayList();
PluginImportData.PluginInfo info;
for (Iterator it = data.getPlugins().iterator(); it.hasNext();) {
info = (PluginImportData.PluginInfo) it.next();
if (info.selected) {
if (info.existingPlugin == null) {
newList.add(info.guid);
}
importList.add(info.guid);
}
}
PluginImportData.ConfiguarationInfo cinfo;
for (Iterator it = data.getConfigs().iterator(); it.hasNext();) {
cinfo = (PluginImportData.ConfiguarationInfo) it.next();
if (cinfo.selected) {
if (cinfo.existingConfig == null) {
newList.add(cinfo.guid);
}
importList.add(cinfo.guid);
}
}
// 2. Iterate the docuemnt and add the new entries.
importLibEntries(targetLibDoc, newList);
return copyFiles(targetLibDoc, importList, newList);
}
private void importLibEntries(LibraryDocument targetLibDoc, List newList) {
if (newList == null || newList.size() == 0) {
return;
}
// Add plug-ins.
NodeList nodes = importingLibDoc.getPlugins();
for (int i = 0; i < nodes.getLength(); i++) {
Element node = (Element) nodes.item(i);
String guid = LibraryDocument.getGuid(node);
if (newList.contains(guid)) {
targetLibDoc.addPlugin(node);
}
}
// Add configurations.
nodes = importingLibDoc.getConfigurations();
for (int i = 0; i < nodes.getLength(); i++) {
Element node = (Element) nodes.item(i);
String guid = LibraryDocument.getGuid(node);
if (newList.contains(guid)) {
targetLibDoc.addConfiguration(node);
}
}
// add resource entries
nodes = importingLibDoc.getResourceDescriptors();
for (int i = 0; i < nodes.getLength(); i++) {
Element node = (Element) nodes.item(i);
String guid = node.getAttribute(LibraryDocument.ATTR_id);
String uri = node.getAttribute(LibraryDocument.ATTR_uri);
if (newList.contains(guid)) {
targetLibDoc.addResource(node);
}
}
// Add the resource sub managers.
nodes = importingLibDoc.getResourceSubManagers();
for (int i = 0; i < nodes.getLength(); i++) {
Element node = (Element) nodes.item(i);
String guid = LibraryDocument.getSubManagerBaseGuid(node
.getAttribute(LibraryDocument.ATTR_href));
if (newList.contains(guid)) {
targetLibDoc.addResource(node);
}
}
}
private boolean copyFiles(LibraryDocument targetLibDoc, List importList,
List newList) {
for (Iterator it = importList.iterator(); it.hasNext();) {
String guid = (String) it.next();
String src_uri = importingLibDoc.getResourceUri(guid);
String target_uri;
if (src_uri == null || src_uri.length() == 0) {
continue;
}
if (newList.contains(guid)) {
target_uri = src_uri;
} else {
target_uri = targetLibDoc.getResourceUri(guid); // the resource
// might be
// renamed
}
// Check the plugin.xmi file. If it exists, copy the folder to
// the destination directory.
final File src_file = importingLibDoc.getFileFromUri(src_uri);
if (src_file.exists()) {
final File target_file = targetLibDoc
.getFileFromUri(target_uri);
// if it's a configuration, only copy the file,
// if it's a plugin, copy the whole directory
if (data.getPluginInfo(guid) != null) {
if (target_file.exists()) {
SafeUpdateController.syncExec(new Runnable() {
public void run() {
DirCopy copy = new DirCopy(src_file
.getParentFile(), target_file
.getParentFile());
fileCheckedOutStatus = copy.execute();
}
});
} else {
copyDir(src_file.getParentFile(), target_file
.getParentFile());
}
} else if (data.getConfigInfo(guid) != null) {
final List files = new ArrayList();
if (target_file.exists()) {
files.add(target_file.getAbsolutePath());
SafeUpdateController.syncExec(new Runnable() {
public void run() {
fileCheckedOutStatus = FileModifyChecker
.checkModify(files);
}
});
}
if (fileCheckedOutStatus == null
|| fileCheckedOutStatus.isOK()) {
ResourceHelper.copyFile(src_file, target_file);
}
}
if ((fileCheckedOutStatus != null)
&& !fileCheckedOutStatus.isOK()) {
// log error
SafeUpdateController.syncExec(new Runnable() {
public void run() {
String title = ImportResources
.getString("Import.importPluginsWizard.title"); //$NON-NLS-1$
String msg = ImportResources
.getString("Import.importPluginsWizard.ERR_Import_plugin"); //$NON-NLS-1$
new MsgDialog(ImportPlugin.getDefault())
.displayError(title, msg,
fileCheckedOutStatus);
}
});
return false;
}
}
}
return true;
}
public static void copyDir(File fromDir, File toDir) {
Copy cp = new Copy();
cp.setOverwrite(true);
FileSet set = new FileSet();
set.setDir(fromDir);
cp.addFileset(set);
cp.setTodir(toDir);
cp.setProject(new Project());
cp.execute();
}
// /**
// * remove the plugin entry from the library document
// *
// * @param document
// * LibraryDocument
// * @param guid
// * String guid of the plugin
// */
// private void removeExistingEntries(LibraryDocument document) {
// // 1. Find the entries to be removed.
// List removeList = new ArrayList();
// PluginImportData.PluginInfo info;
// for (Iterator it = data.getPlugins().iterator(); it.hasNext();) {
// info = (PluginImportData.PluginInfo) it.next();
// if ((info.existingPlugin != null) && info.selected) {
// removeList.add(info.guid);
// }
// }
//
// PluginImportData.ConfiguarationInfo cinfo;
// for (Iterator it = data.getConfigs().iterator(); it.hasNext();) {
// cinfo = (PluginImportData.ConfiguarationInfo) it.next();
// if ((cinfo.existingConfig != null) && cinfo.selected) {
// removeList.add(cinfo.guid);
// }
// }
//
// // 2. Iterate the docuemnt and remove the entries.
// document.removePlugins(removeList);
// document.removeConfigurations(removeList);
// document.removeResourceEntries(removeList);
// }
public String validateSelection() {
data.getErrorInfo().clear();
// Iterate the new plugins, make sure the base is included
// either as an importing plugin, or is in the current library
// get the method plugins in the current library.
MethodLibrary library = LibraryService.getInstance()
.getCurrentMethodLibrary();
List plugins = (library == null) ? new ArrayList() : library
.getMethodPlugins();
List pluginids = new ArrayList();
for (Iterator it = plugins.iterator(); it.hasNext();) {
pluginids.add(((MethodPlugin) it.next()).getGuid());
}
// The base plug-ins MUST be either a selected one or an existing one
// otherwise, can't import
List basePlugins = new ArrayList();
List newPlugins = new ArrayList();
for (Iterator it = data.getPlugins().iterator(); it.hasNext();) {
PluginImportData.PluginInfo info = (PluginImportData.PluginInfo) it
.next();
if (info.selected && (info.existingPlugin == null)) {
newPlugins.add(info.guid);
for (Iterator itb = info.usedPlugins.iterator(); itb.hasNext();) {
Object base = itb.next();
if (!basePlugins.contains(base)) {
basePlugins.add(base);
}
}
}
}
if (newPlugins.size() > 0) {
for (Iterator it = basePlugins.iterator(); it.hasNext();) {
String guid = (String) it.next();
String uri = (String) data.basePluginUrlMap.get(guid);
if (!newPlugins.contains(guid) && !pluginids.contains(guid)) {
String message;
if (uri != null && uri.length() > 0) {
message = ImportResources.getString(
"Import.PluginImportingService.MSG5", uri); //$NON-NLS-1$
} else {
message = ImportResources
.getString("Import.PluginImportingService.MSG6"); //$NON-NLS-1$
}
data.getErrorInfo().addError(message);
if (uri == null || uri.length() == 0) {
break;
}
}
}
}
return data.getErrorInfo().getError();
}
private void scanLibraryFile(LibraryDocument document) {
visitLibTag(document);
visitResourceTag(document);
data.validatePlugins();
// Check base plug-in dependencies.
for (Iterator it = data.getPlugins().iterator(); it.hasNext();) {
PluginImportData.PluginInfo info = (PluginImportData.PluginInfo) it
.next();
if (info.existingPlugin == null) {
for (Iterator itbase = info.usedPlugins.iterator(); itbase
.hasNext();) {
String guid = (String) itbase.next();
if (!data.basePluginUrlMap.containsKey(guid)) {
data.basePluginUrlMap.put(guid, ""); //$NON-NLS-1$
}
}
}
}
}
private void visitLibTag(LibraryDocument document) {
// Reload the element mapping.
NodeList nodes = document.getPlugins();
for (int i = 0; i < nodes.getLength(); i++) {
Element node = (Element) nodes.item(i);
PluginImportData.PluginInfo pi = data.new PluginInfo();
pi.guid = document.getGuid(node);
data.getPlugins().add(pi);
// Check with the current library, get the related information.
loadExistingPluginInfo(pi);
}
// Remove the unneeded configurations.
nodes = document.getConfigurations();
for (int i = 0; i < nodes.getLength(); i++) {
Element node = (Element) nodes.item(i);
PluginImportData.ConfiguarationInfo ci = data.new ConfiguarationInfo();
ci.guid = document.getGuid(node);
ci.name = node.getAttribute("name"); //$NON-NLS-1$
data.getConfigs().add(ci);
// Check with the current library, get the related information.
loadExistingConfigInfo(ci);
}
}
private void visitResourceTag(LibraryDocument document) {
NodeList nodes = document.getResourceDescriptors();
for (int i = 0; i < nodes.getLength(); i++) {
Element node = (Element) nodes.item(i);
String guid = node.getAttribute(LibraryDocument.ATTR_id);
String uri = node.getAttribute(LibraryDocument.ATTR_uri);
// Load the plugin.xmi file for detail information.
File file = document.getFileFromUri(uri);
PluginImportData.PluginInfo pi = data.getPluginInfo(guid);
if (pi != null) {
if (file.exists()) {
loadPluginInfo(file, pi);
} else {
// Remove the plug-in info entry since thias is not
// a valid plug-in to import.
data.removePluginInfo(guid);
}
} else {
// if not plugin, might be a configuration
PluginImportData.ConfiguarationInfo ci = data
.getConfigInfo(guid);
if (ci != null) {
if (file.exists()) {
loadConfigInfo(file, ci);
}
}
}
}
}
protected void loadConfigInfo(File source,
PluginImportData.ConfiguarationInfo info) {
try {
Document document = XMLUtil.loadXml(source);
Element root = document.getDocumentElement();
Element configTag = null;
if (root.getTagName().equals(
"org.eclipse.epf.uma:MethodConfiguration")) //$NON-NLS-1$
{
configTag = root;
} else {
NodeList nodes = root
.getElementsByTagName("org.eclipse.epf.uma:MethodConfiguration"); //$NON-NLS-1$
if (nodes.getLength() > 0) {
configTag = (Element) nodes.item(0);
}
}
if (configTag != null) {
info.name = configTag.getAttribute("name"); //$NON-NLS-1$
}
} catch (Exception e) {
ImportPlugin.getDefault().getLogger().logError(e);
}
}
protected void loadPluginInfo(File source, PluginImportData.PluginInfo info) {
try {
Document document = XMLUtil.loadXml(source);
Element root = document.getDocumentElement();
Element pluginTag = null;
if (root.getTagName().equals("org.eclipse.epf.uma:MethodPlugin")) //$NON-NLS-1$
{
pluginTag = root;
} else {
NodeList nodes = root
.getElementsByTagName("org.eclipse.epf.uma:MethodPlugin"); //$NON-NLS-1$
if (nodes.getLength() > 0) {
pluginTag = (Element) nodes.item(0);
}
}
if (pluginTag != null) {
info.name = pluginTag.getAttribute("name"); //$NON-NLS-1$
info.version = LibraryDocument.getChildValue(pluginTag,
"version"); //$NON-NLS-1$
info.brief_desc = LibraryDocument.getChildValue(pluginTag,
"briefDescription"); //$NON-NLS-1$
info.authors = LibraryDocument.getChildValue(pluginTag,
"authors"); //$NON-NLS-1$
info.changeDate = LibraryDocument.getChildValue(pluginTag,
"changeDate"); //$NON-NLS-1$
info.url = source.toString();
// Get the base plug-ins.
NodeList nodes = pluginTag.getElementsByTagName("bases"); //$NON-NLS-1$
for (int i = 0; i < nodes.getLength(); i++) {
Element node = (Element) nodes.item(i);
String guid = node.getAttribute(LibraryDocument.ATTR_href);
int indx = guid.indexOf("#"); //$NON-NLS-1$
if (indx > 0) {
guid = guid.substring(indx + 1);
} else {
indx = guid.indexOf("uma://"); //$NON-NLS-1$
if (indx >= 0) {
guid = guid.substring(indx + 6);
}
}
info.usedPlugins.add(guid);
}
}
} catch (Exception e) {
ImportPlugin.getDefault().getLogger().logError(e);
}
}
private void loadExistingPluginInfo(PluginImportData.PluginInfo info) {
MethodLibrary library = LibraryService.getInstance()
.getCurrentMethodLibrary();
List plugins = (library == null) ? new ArrayList() : library
.getMethodPlugins();
for (Iterator it = plugins.iterator(); it.hasNext();) {
MethodPlugin plugin = (MethodPlugin) it.next();
if (plugin.getGuid().equals(info.guid)) {
info.existingPlugin = plugin;
}
}
}
private void loadExistingConfigInfo(PluginImportData.ConfiguarationInfo info) {
MethodConfiguration[] configs = LibraryServiceUtil
.getMethodConfigurations(LibraryService.getInstance()
.getCurrentMethodLibrary());
if (configs == null || configs.length == 0) {
return;
}
for (int i = 0; i < configs.length; i++) {
MethodConfiguration config = configs[i];
if (config.getGuid().equals(info.guid)) {
info.existingConfig = config;
}
}
}
/**
* Replaces the guid of the old method library with the new one.
* <p>
* Search for the following files: library.xmi, plugin.xmi, model.xmi.
*/
private void fixLibraryGuid(File path, String oldGuid, String newGuid) {
if (!path.isDirectory()) {
return;
}
File[] files = path.listFiles(new FileFilter() {
public boolean accept(File f) {
if (f.isDirectory()) {
return true;
}
String name = f.getName();
return name.equals("library.xmi") || name.equals("plugin.xmi") || name.equals("model.xmi"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
}
});
if (files == null || files.length == 0) {
return;
}
for (int i = 0; i < files.length; i++) {
if (files[i].isDirectory()) {
fixLibraryGuid(files[i], oldGuid, newGuid);
} else {
// Read in the file, update it and save the file.
try {
String source = FileUtil.readFile(files[i],
FileUtil.ENCODING_UTF_8).toString();
if (source.indexOf(oldGuid) >= 0) {
// TODO: This is a regexp repalcement, is it safe?
source = source.replaceAll(oldGuid, newGuid);
FileUtil.writeUTF8File(files[i].getAbsolutePath(),
source);
}
} catch (IOException e) {
ImportPlugin.getDefault().getLogger().logError(e);
}
}
}
}
}