/*******************************************************************************
* Copyright (c) 2007 Exadel, Inc. and Red Hat, Inc.
* Distributed under license by Red Hat, Inc. All rights reserved.
* This program is 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:
* Exadel, Inc. and Red Hat, Inc. - initial API and implementation
******************************************************************************/
package org.jboss.tools.common.model.options.impl;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.net.URL;
import java.net.URLConnection;
import java.text.MessageFormat;
import org.w3c.dom.*;
import org.eclipse.core.runtime.Platform;
import org.jboss.tools.common.model.*;
import org.jboss.tools.common.model.options.*;
import org.jboss.tools.common.model.plugin.ModelPlugin;
import org.jboss.tools.common.model.util.*;
import org.jboss.tools.common.xml.XMLUtilities;
import org.osgi.framework.Bundle;
public class XStudioDataLoaderImpl implements SharableConstants {
private SharableElement studio = null;
public static class PreferencesFileException extends XModelException {
private static final long serialVersionUID = 1L;
String file;
String xmlError;
public PreferencesFileException(String file, String xmlError) {
super("Preferences file " + file + " has errors: " + xmlError);
this.file = file;
this.xmlError = xmlError;
}
public String getFile() {
return file;
}
public String getXMLError() {
return xmlError;
}
}
private XStudioLoaderPeer peer = XStudioLoaderPeer.instance();
public XStudioDataLoaderImpl() {}
public void load(XModelObject _studio) {
peer.init(_studio);
studio = (SharableElement)_studio;
peer.setIsLoadingOn(true);
studio.setScope(PROJECT);
new SharableLoaderImpl().loadSystemSharable(studio);
XStudioContribution[] cs = XStudioContributions.getContributions();
for (int i = 0; i < cs.length; i++) {
load(LIST[0], cs[i]);
}
boolean e = false;
for (int i = 1; i < LIST.length; i++) {
File[] fs = peer.getFilesForScope(LIST[i]);
for (int j = 0; j < fs.length; j++) e = load(LIST[i], fs[j]);
}
mergeGeneralToProject((SharableElementImpl)studio, !e);
peer.setIsLoadingOn(false);
_studio.setModified(false);
File f = peer.getProjectPreferencesFile();
if(f != null && f.exists()) {
PreferenceImportExport.getInstance().apply(f);
}
}
private boolean load(String scopename, File file) {
if(file.isFile()) {
try {
check(new FileReader(file), file.toString());
} catch (IOException e) {
ModelPlugin.getDefault().logError(e);
return false;
}
}
Element element = XMLUtil.getElement(file.getAbsolutePath());
return load(scopename, element);
}
private boolean load(String scopename, XStudioContribution c) {
check(new InputStreamReader(c.getInputStream()), c.resource);
Element element = XMLUtil.getElement(c.getInputStream());
return load(scopename, element);
}
private void check(Reader r, String file) {
String[] errors = XMLUtil.getXMLErrors(r, false);
if(errors != null && errors.length > 0) {
PreferencesFileException exc = new PreferencesFileException(file, errors[0]);
ModelPlugin.getDefault().logError(exc.getMessage(), exc);
}
}
private boolean load(String scopename, Element element) {
if(element == null) return false;
SharableLoaderImpl loader = new SharableLoaderImpl();
loader.loadSharable(element, studio, scopename);
return true;
}
public boolean save(XModelObject _studio) {
if(!_studio.isModified()) return true;
peer.init(_studio);
studio = (SharableElement)_studio;
for (int i = 0; i < LIST.length; i++) {
if(i == 1) saveProject();
}
_studio.setModified(false);
return true;
}
private void saveProject() {
File[] fs = peer.getFilesForScope(PROJECT);
boolean isPaletteModified = studio.getChildByPath("Palette").isModified() || studio.getChildByPath("Icons").isModified(); //$NON-NLS-1$ //$NON-NLS-2$
boolean isPreferencesModified = studio.getChildByPath(OPTIONS).isModified();
if(!fs[0].exists() || isPaletteModified) savePalette(fs[0]);
if(!fs[1].exists() || isPreferencesModified) savePreferences(fs[1]);
}
private void savePalette(File f) {
if(handleReadOnly(studio, PROJECT, f) != 0) return;
save(studio, PROJECT, f, new String[]{"Palette", "XStudioIcons"});
studio.getChildByPath("Palette").setModified(false); //$NON-NLS-1$
studio.getChildByPath("Icons").setModified(false); //$NON-NLS-1$
}
private void savePreferences(File f) {
if(handleReadOnly(studio, LIST[1], f) != 0) return;
save(studio, PROJECT, f, new String[]{OPTIONS});
studio.getChildByPath(OPTIONS).setModified(false);
}
private void save(SharableElement q, String scopename, File f, String[] names) {
if(f.exists() && (!f.isFile() || !f.canWrite())) return;
try {
if(!f.exists()) f.createNewFile();
} catch (IOException e1) {
ModelPlugin.getPluginLog().logError("XStudioDataLoaderImpl:save:Cannot create file:" + e1.getMessage()); //$NON-NLS-1$
return;
}
Element e = XMLUtil.createDocumentElement("dummyroot"); //$NON-NLS-1$
new SharableLoaderImpl().saveSharable(e, q, scopename);
NodeList x = e.getElementsByTagName(XSTUDIO);
if(x == null || x.getLength() == 0) return;
Element xs = (Element)x.item(0);
check(xs.getChildNodes(), names);
removeMobilePalette(xs);
try {
XModelObjectLoaderUtil.serialize(xs, f.getAbsolutePath());
} catch (IOException e2) {
ModelPlugin.getPluginLog().logError(e2);
}
}
private void check(NodeList l, String[] names) {
Node[] ns = new Node[l.getLength()];
for (int i = 0; i < ns.length; i++) ns[i] = l.item(i);
for (int i = 0; i < ns.length; i++) check(ns[i], names);
}
private void check(Node n, String[] names) {
if(n.getNodeType() != Node.ELEMENT_NODE) return;
for (int i = 0; i < names.length; i++)
if(names[i].equals(n.getNodeName())) return;
n.getParentNode().removeChild(n);
}
private void removeMobilePalette(Element xs) {
Element p = XMLUtilities.getUniqueChild(xs, SharableConstants.PALETTE_ROOT);
if(p != null) {
NodeList nl = p.getChildNodes();
for (int i = 0; i < nl.getLength(); i++) {
Node n = nl.item(i);
if(n instanceof Element && SharableConstants.MOBILE_PALETTE_ROOT.equals(((Element)n).getAttribute(XModelObjectConstants.XML_ATTR_NAME))) {
p.removeChild(n);
break;
}
}
}
}
private void mergeGeneralToProject(SharableElementImpl object, boolean merge_all) {
object.merge(GENERAL, PROJECT, merge_all);
}
private int handleReadOnly(XModelObject o, String scope, File f) {
if(!PROJECT.equals(scope)) return 1;
int i = 0;
while(i == 0 && f.exists() && !f.canWrite())
i = o.getModel().getService().showDialog("Question",
getReadOnlyMessage(f), new String[]{"Retry", "Discard"}, null,
org.jboss.tools.common.model.ServiceDialog.QUESTION);
return i;
}
private String getReadOnlyMessage(File f) {
return MessageFormat
.format(
"File {0} is read-only.\nPlease make it writable to allow for saving options.",
f.getAbsolutePath());
}
private InputStream readGeneral() {
try {
Bundle b = Platform.getBundle(ModelPlugin.PLUGIN_ID);
URL u = b.getResource("meta/options_general.xml"); //$NON-NLS-1$
URLConnection c = u.openConnection();
return c.getInputStream();
} catch (IOException e) {
ModelPlugin.getPluginLog().logError(e);
return null;
}
}
}