/*******************************************************************************
* 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.filesystems.impl;
import java.io.File;
import java.io.IOException;
import java.util.*;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.CoreException;
import org.w3c.dom.*;
import org.jboss.tools.common.meta.XAttribute;
import org.jboss.tools.common.meta.XModelEntity;
import org.jboss.tools.common.model.*;
import org.jboss.tools.common.model.filesystems.FileSystemsHelper;
import org.jboss.tools.common.model.loaders.*;
import org.jboss.tools.common.model.loaders.impl.*;
import org.jboss.tools.common.model.plugin.ModelPlugin;
import org.jboss.tools.common.model.project.IAutoLoad;
import org.jboss.tools.common.model.project.IModelNature;
import org.jboss.tools.common.model.util.*;
import org.jboss.tools.common.model.project.WatcherLoader;
public class FileSystemsLoader extends URLRootLoader {
public static String IS_ADDED_TO_CLASSPATH = "isAddedToClassPath"; //$NON-NLS-1$
FileSystemsLoaderUtil fsutil = new FileSystemsLoaderUtil();
public FileSystemsLoader() {}
protected XModelObjectLoaderUtil util() {
return fsutil;
}
public boolean save(XModelObject object) {
if(!fsutil.isModified(object)) return true;
if(object.getModel().getProperties().get(XModelConstants.AUTOLOAD) != null) {
return true;
}
String s = getEclipseFileName(object, false);
boolean b = (s == null) ? super.save(object.copy(1)) :
saveEclipse(object.copy(1));
if(((FileSystemsImpl)object).requestSave()) return true;
XModelObject[] cs = object.getChildren();
for (int i = 0; i < cs.length; i++) {
XObjectLoader loader = XModelObjectLoaderUtil.getObjectLoader(cs[i]);
if(loader != null) b &= loader.save(cs[i]);
}
return b;
}
public boolean update(XModelObject object) throws XModelException {
boolean b = true;
IAutoLoad auto = (IAutoLoad)object.getModel().getProperties().get(XModelConstants.AUTOLOAD);
if(auto != null) {
auto.update(object.getModel());
}
XModelObject[] cs = object.getChildren();
for (int i = 0; i < cs.length; i++) {
XObjectLoader loader = XModelObjectLoaderUtil.getObjectLoader(cs[i]);
if(loader != null) b &= loader.update(cs[i]);
}
updateClassPath(object);
((FileSystemsImpl)object).updateOverlapped();
return b;
}
public void updateClassPath(XModelObject object) {
updateLibs(object);
removeMissingJarSystems(object);
updateSrcs(object);
}
public void load(XModelObject object) {
if(EclipseResourceUtil.isProjectFragment(object.getModel())) return;
IAutoLoad auto = (IAutoLoad)object.getModel().getProperties().get(XModelConstants.AUTOLOAD);
if(auto != null) {
auto.load(object.getModel());
updateLibs(object);
_updateSrcs(object);
((FileSystemsImpl)object).updateOverlapped();
return;
}
String f = getEclipseFileName(object, true);
if(f == null) super.load(object);
else util().load(new File(f), object);
XModelObject[] os = object.getChildren();
for (int i = 0; i < os.length; i++) {
String s = os[i].getAttributeValue(XModelObjectConstants.ATTR_NAME_LOCATION);
if(s == null || !s.startsWith(XModelConstants.WORKSPACE_OLD_REF)) continue;
s = XModelConstants.WORKSPACE_REF + s.substring(XModelConstants.WORKSPACE_OLD_REF.length());
os[i].setAttributeValue(XModelObjectConstants.ATTR_NAME_LOCATION, s);
}
removeMissingJarSystems(object);
}
void removeMissingJarSystems(XModelObject object) {
XModelObject[] os = object.getChildren("FileSystemJar"); //$NON-NLS-1$
for (int i = 0; i < os.length; i++) {
JarSystemImpl jar = (JarSystemImpl)os[i];
String location = jar.getLocation();
if(location != null && !new File(location).isFile()) {
jar.removeFromParent();
object.setModified(true);
}
}
}
public String fileroot(XModelObject object) {
return XModelConstants.getWorkspace(object.getModel()) + XModelObjectConstants.SEPARATOR;
}
protected String fileName(XModelObject object) {
return "workspace.pex"; //$NON-NLS-1$
}
public void saveTo(File f, XModelObject object) {
XModelObject o = object.copy(1);
XModelObject[] cs = o.getChildren();
for (XModelObject c: cs) {
if(c.getModelEntity().getName().equals("FileSystemJar")) { //$NON-NLS-1$
o.removeChild(c);
}
if(!c.getAttributeValue(XModelObjectConstants.ATTR_NAME_LOCATION).startsWith("%")) { //$NON-NLS-1$
o.removeChild(c);
}
}
util().save(f, o);
}
private boolean saveEclipse(XModelObject object) {
String f = getEclipseFileName(object, false);
boolean b = f != null && util().save(new File(f), object);
if(b) {
IFile file = EclipseResourceUtil.getFile(f);
if(file != null) {
try {
file.refreshLocal(0, null);
} catch (CoreException e) {
// ignore
}
}
}
return b;
}
private String getEclipseFileName(XModelObject object, boolean load) {
String project = object.getModel().getProperties().getProperty(IModelNature.ECLIPSE_PROJECT);
if(project == null) return null;
String fn = project + XModelObjectConstants.SEPARATOR + IModelNature.PROJECT_FILE;
if(!load || new File(fn).exists()) return fn;
return null;
}
List<String> paths = null;
private void updateLibs(XModelObject object) {
if(WatcherLoader.isLocked(object.getModel())) {
return;
}
IProject project = EclipseResourceUtil.getProject(object);
if(project == null) return;
XModelObject lib = validateLib(object);
// if(lib == null) {
// return;
// }
Libs libs = FileSystemsHelper.getLibs(object);
if(libs != null) libs.update();
}
private XModelObject validateLib(XModelObject object) {
XModelObject lib = object.getChildByPath("lib"); //$NON-NLS-1$
if(lib == null) {
XModelObject wi = object.getChildByPath("WEB-INF"); //$NON-NLS-1$
if(wi == null) return null;
XModelObject lb = wi.getChildByPath("lib"); //$NON-NLS-1$
if(lb == null) return null;
lib = wi.getModel().createModelObject(XModelObjectConstants.ENT_FILE_SYSTEM_FOLDER, null);
lib.setAttributeValue(XModelObjectConstants.ATTR_NAME, "lib"); //$NON-NLS-1$
lib.setAttributeValue(XModelObjectConstants.ATTR_NAME_LOCATION, wi.getAttributeValue(XModelObjectConstants.ATTR_NAME_LOCATION) + "/lib"); //$NON-NLS-1$
object.addChild(lib);
object.setModified(true);
}
return lib;
}
public void updateSrcs(XModelObject object) {
IAutoLoad auto = (IAutoLoad)object.getModel().getProperties().get(XModelConstants.AUTOLOAD);
if(auto == null && WatcherLoader.isLocked(object.getModel())) {
return;
}
_updateSrcs(object);
}
private static void _updateSrcs(XModelObject object) {
IProject p = EclipseResourceUtil.getProject(object);
if(p == null || !p.isAccessible()) return;
String[] srcs = EclipseResourceUtil.getJavaProjectSrcLocations(p);
Set<String> paths = new HashSet<String>();
for (int i = 0; i < srcs.length; i++) {
String path = EclipseResourceUtil.getRelativeLocation(object.getModel(), srcs[i]);
if(path == null) continue;
paths.add(path);
}
XModelObject[] cs = object.getChildren(XModelObjectConstants.ENT_FILE_SYSTEM_FOLDER);
for (int i = 0; i < cs.length; i++) {
if(cs[i].getAttributeValue(XModelObjectConstants.ATTR_NAME).startsWith("src")) { //$NON-NLS-1$
String loc = cs[i].getAttributeValue(XModelObjectConstants.ATTR_NAME_LOCATION);
if(!paths.contains(loc)) {
object.removeChild(cs[i]);
} else {
paths.remove(loc);
}
}
}
for (String path : paths) {
String n = getNextSrcName(object);
Properties properties = new Properties();
properties.setProperty(XModelObjectConstants.ATTR_NAME_LOCATION, path);
properties.setProperty(XModelObjectConstants.ATTR_NAME, n);
FileSystemImpl s = (FileSystemImpl)object.getModel().createModelObject(XModelObjectConstants.ENT_FILE_SYSTEM_FOLDER, properties);
object.addChild(s);
}
}
private static String getNextSrcName(XModelObject object) {
if(object.getChildByPath("src") == null) return "src"; //$NON-NLS-1$ //$NON-NLS-2$
int i = 1;
while(true) {
String s = "src-" + i; //$NON-NLS-1$
if(object.getChildByPath(s) == null) return s;
i++;
}
}
}
class FileSystemsLoaderUtil extends XModelObjectLoaderUtil {
boolean isFileSystems(String nodeName) {
return "FILESYSTEMS".equals(nodeName) || "file-systems".equals(nodeName); //$NON-NLS-1$ //$NON-NLS-2$
}
protected Set<String> getAllowedChildren(XModelEntity entity) {
Set<String> children = super.getAllowedChildren(entity);
if(isFileSystems(entity.getXMLSubPath())) {
children.add("WEB"); //$NON-NLS-1$
children.add("web"); //$NON-NLS-1$
}
return children;
}
protected Set<String> getAllowedAttributes(XModelEntity entity) {
Set<String> attributes = super.getAllowedAttributes(entity);
if(isFileSystems(entity.getXMLSubPath())) {
attributes.add("WORKSPACE_HOME"); //$NON-NLS-1$
attributes.add("workspace-home"); //$NON-NLS-1$
}
return attributes;
}
public boolean saveChildren(Element element, XModelObject o) {
if("FileSystemJar".equals(o.getModelEntity().getName())) { //$NON-NLS-1$
return true;
}
boolean b = super.saveChildren(element, o);
if(b && isFileSystems(element.getNodeName())) {
saveWorkspaceHomeAttr(element, o);
XModelObject w = getWeb(o);
if(w != null) save(element, w);
}
return b;
}
public void loadChildren(Element element, XModelObject o) {
super.loadChildren(element, o);
if(isFileSystems(element.getNodeName())) {
Element e = XMLUtil.getUniqueChild(element, "web"); //$NON-NLS-1$
if(e == null) e = XMLUtil.getUniqueChild(element, "WEB"); //$NON-NLS-1$
XModelObject w = getWeb(o);
if(w != null && e != null) load(e, w);
}
}
boolean isModified(XModelObject object) {
if(object.isModified()) return true;
XModelObject w = getWeb(object);
return w != null && w.isModified();
}
private XModelObject getWeb(XModelObject object) {
return object.getModel().getByPath("Web"); //$NON-NLS-1$
}
private void saveWorkspaceHomeAttr(Element element, XModelObject o) {
Properties p = o.getModel().getProperties();
String project = p.getProperty(IModelNature.ECLIPSE_PROJECT);
String workspace = p.getProperty(XModelConstants.WORKSPACE);
if(project == null) return;
String relative = workspace.startsWith(project + XModelObjectConstants.SEPARATOR) ?
"." + workspace.substring(project.length()) : workspace; //$NON-NLS-1$
element.setAttribute("workspace-home", relative); //$NON-NLS-1$
}
static Map<String,String> oldAttributes = new HashMap<String, String>();
static {
oldAttributes.put("application-name", "APPLICATION_NAME"); //$NON-NLS-1$ //$NON-NLS-2$
oldAttributes.put("workspace-home", "WORKSPACE_HOME"); //$NON-NLS-1$ //$NON-NLS-2$
oldAttributes.put("info", "INFO"); //$NON-NLS-1$ //$NON-NLS-2$
oldAttributes.put(XModelObjectConstants.ATTR_NAME_LOCATION, "LOCATION"); //$NON-NLS-1$
oldAttributes.put("model-path", "MODEL_PATH"); //$NON-NLS-1$ //$NON-NLS-2$
oldAttributes.put("root", "ROOT"); //$NON-NLS-1$ //$NON-NLS-2$
oldAttributes.put("web-root", "root"); //$NON-NLS-1$ //$NON-NLS-2$
oldAttributes.put("src", "SRC"); //$NON-NLS-1$ //$NON-NLS-2$
}
public String getAttribute(Element element, String xmlname, XAttribute attr) {
if(element == null || xmlname == null) return null;
if(!element.hasAttribute(xmlname)) {
String oldAttribute = xmlname;
while(oldAttribute != null) {
oldAttribute = oldAttributes.get(oldAttribute);
if(oldAttribute != null && element.hasAttribute(oldAttribute)) {
xmlname = oldAttribute;
break;
}
}
}
return super.getAttribute(element, xmlname, attr);
}
}