/******************************************************************************* * 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.core.resources; import java.io.File; import java.io.IOException; import java.lang.reflect.Field; import java.net.URI; import org.eclipse.core.resources.*; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.Path; import org.eclipse.jdt.core.IJarEntryResource; import org.eclipse.jdt.core.IJavaProject; import org.eclipse.jdt.core.IPackageFragment; import org.eclipse.jdt.core.IPackageFragmentRoot; import org.eclipse.jdt.internal.ui.javaeditor.JarEntryEditorInput; import org.eclipse.jface.resource.ImageDescriptor; import org.eclipse.ui.*; import org.eclipse.ui.editors.text.ILocationProvider; import org.eclipse.ui.internal.part.NullEditorInput; import org.eclipse.ui.part.FileEditorInput; import org.jboss.tools.common.model.XModel; import org.jboss.tools.common.model.XModelObject; import org.jboss.tools.common.model.XModelObjectConstants; import org.jboss.tools.common.model.filesystems.FileSystemsHelper; import org.jboss.tools.common.model.filesystems.impl.*; import org.jboss.tools.common.model.plugin.ModelPlugin; import org.jboss.tools.common.model.project.IModelNature; import org.jboss.tools.common.model.util.*; import org.jboss.tools.common.model.ui.ModelUIPlugin; import org.jboss.tools.common.model.ui.editor.*; public class XModelObjectEditorInput extends FileEditorInput implements IModelObjectEditorInput { private XModelObject object; private XModelObjectCache cache; private XModelObjectEditorInput(XModelObject object) { super(getFileByObject(object)); this.object = object; cache = new XModelObjectCache(object); } /** * Returns true if XModelObject corresponding to the file is replaced. * * @return */ public boolean updateXModelObject() { IFile file = getFile(); XModelObject o = EclipseResourceUtil.createObjectForResource(file); if(o != null && o != object) { object = o; cache = new XModelObjectCache(object); return true; } return false; } private static XModelObject getMainObject(XModelObject object) { if(object instanceof FileAnyAuxiliaryImpl) { XModelObject main = ((FileAnyAuxiliaryImpl)object).getMainObject(); if(main != null) object = main; } return object; } public static IModelObjectEditorInput createInstance(XModelObject object) { object = getMainObject(object); IFile f = getFileByObject(object); if(f == null && object instanceof FileAnyImpl) { XModelObject p = object.getParent(); if(p instanceof FolderImpl) { String path = ((FileAnyImpl)object).getAbsolutePath(); if(path != null) { return new ModelObjectLocationEditorInput(object, new Path(path)); } } return new ModelObjectStorageEditorInput(object); } return (f == null) ? null : new XModelObjectEditorInput(object); } public XModelObject getXModelObject() { XModelObject o = cache.getObject(); if(o != null) object = o; return o; } public boolean exists() { IFile f = getFile(); return f != null && f.exists(); } public ImageDescriptor getImageDescriptor() { return null; } public String getName() { return object.getPresentationString(); } public String getToolTipText() { IFile f = (IFile)EclipseResourceUtil.getResource(object); if(f != null && f.exists()) return f.getFullPath().makeRelative().toString(); return object.getPresentationString(); } public Object getAdapter(Class adapter) { if(adapter == XModelObject.class) return getXModelObject(); Object result = null; if (IFile.class.isAssignableFrom(adapter)) { result = EclipseResourceUtil.getResource(object); if (result != null && !adapter.isAssignableFrom(result.getClass())) result = null; } else { result = super.getAdapter(adapter); } return result; } public boolean equals(Object o) { getXModelObject(); if (this == o) return true; if (o instanceof FileEditorInput) { if(getFile() == null) return false; FileEditorInput other = (FileEditorInput)o; IFile f1 = getFile(); IFile f2 = other.getFile(); if(f1 == null || f2 == null) return f1 == f2; if(f1.equals(f2)) return true; IPath loc1 = f1.getLocation(); IPath loc2 = f2.getLocation(); if(loc1 == null || loc2 == null) return loc1 == loc2; return loc1.equals(loc2); } if(o instanceof XModelObjectEditorInput) { return object.equals(((XModelObjectEditorInput)o).getXModelObject()); } return false; } public IStorage getStorage() { return getFile(); } public IFile getFile() { return super.getFile(); } public boolean isFileChanged() { XModelObject o = getXModelObject(); IFile f1 = super.getFile(); if (o == null || o.getPath() == null) return false; IFile f2 = getFileByObject(o); return !f1.equals(f2); } public void synchronize() { XModelObject o = getXModelObject(); IFile f1 = super.getFile(); if (o == null || o.getPath() == null) return; IFile f2 = getFileByObject(o); if(!f1.equals(f2) && f2 != null) hackSetFile(f2); } private void hackSetFile(IFile f) { try { Field field = FileEditorInput.class.getDeclaredField("file"); //$NON-NLS-1$ field.setAccessible(true); field.set(this, f); } catch (NoSuchFieldException e) { ModelUIPlugin.getPluginLog().logError(e); } catch (IllegalArgumentException e) { ModelUIPlugin.getPluginLog().logError(e); } catch (IllegalAccessException e) { ModelUIPlugin.getPluginLog().logError(e); } } private static IFile getFileByObject(XModelObject object) { return (IFile)EclipseResourceUtil.getResource(object); } public static IEditorInput checkInput(IEditorInput input) { if(input instanceof IModelObjectEditorInput) return input; if(input instanceof ILocationProvider) return convertExternalInput((ILocationProvider)input); if(input instanceof IFileEditorInput) return convertFileInput((IFileEditorInput)input); if(input instanceof IStorageEditorInput) return convertStorageEditorInput((IStorageEditorInput)input); if(input instanceof IURIEditorInput) { URI uri = ((IURIEditorInput)input).getURI(); String f = uri.getPath(); XModelObject o = EclipseResourceUtil.createObjectForLocation(f); return (o == null || o.getFileType() != XModelObject.FILE) ? (IEditorInput)input : new ModelObjectLocationEditorInput(getMainObject(o), new Path(f)); } return input; } private static IEditorInput convertFileInput(IFileEditorInput input) { IFileEditorInput fi = (IFileEditorInput)input; IFile f = fi.getFile(); if(f != null && !f.isSynchronized(IResource.DEPTH_INFINITE)) { try { f.refreshLocal(IResource.DEPTH_INFINITE, null); } catch (CoreException e) { //ignore } } XModelObject o = EclipseResourceUtil.getObjectByResource(f); if(o == null) { o = EclipseResourceUtil.createObjectForResource(f); } return (o == null || o.getFileType() != XModelObject.FILE) ? input : new XModelObjectEditorInput(getMainObject(o)); } private static IEditorInput convertExternalInput(ILocationProvider input) { XModelObject o = EclipseResourceUtil.createObjectForLocation(input.getPath(input).toString()); return (o == null || o.getFileType() != XModelObject.FILE) ? (IEditorInput)input : new ModelObjectLocationEditorInput(getMainObject(o), input.getPath(input)); } private static IEditorInput convertStorageEditorInput(IStorageEditorInput input) { if(input instanceof JarEntryEditorInput) { IProject project = null; JarEntryEditorInput j = (JarEntryEditorInput)input; if(j.getStorage() instanceof IJarEntryResource) { IJarEntryResource file = (IJarEntryResource)j.getStorage(); String jarFile = file.getPackageFragmentRoot().getPath().toString(); if(file.getPackageFragmentRoot().getResource() != null) { jarFile = file.getPackageFragmentRoot().getResource().getLocation().toString(); } String entry = file.getName(); IJarEntryResource r = file; while(r != null && r.getParent() instanceof IJarEntryResource) { r = (IJarEntryResource)r.getParent(); entry = r.getName() + "/" + entry; } if(r != null && r.getParent() instanceof IPackageFragment) { IPackageFragment pf = (IPackageFragment)r.getParent(); IJavaProject jp = pf.getJavaProject(); if(jp != null) project = jp.getProject(); while(pf != null) { String p = pf.getElementName(); entry = p + "/" + entry; if(pf.getParent() instanceof IPackageFragment) { pf = (IPackageFragment)pf.getParent(); } else { pf = null; } } } else if(r != null && r.getPackageFragmentRoot() != null) { IPackageFragmentRoot root = r.getPackageFragmentRoot(); if(root.getJavaProject() != null) { project = root.getJavaProject().getProject(); } } IEditorInput result = createJarEntryEditorInput(project, jarFile, entry); if(result != null) return result; } } String[] entryInfo = parseJarEntryFileInput(input); if(entryInfo == null) return input; String jarFile = entryInfo[0]; String entry = entryInfo[1]; IEditorInput result = createJarEntryEditorInput(null, jarFile, entry); return (result == null || result instanceof NullEditorInput) ? input : result; } public static String[] parseJarEntryFileInput(IStorageEditorInput input) { IStorage storage = null; try { storage = input.getStorage(); } catch (CoreException e) { // ignore } return storage == null ? null : parseJarEntryFile(storage); } public static String[] parseJarEntryFile(IStorage storage) { if(storage == null) return null; String s = storage.toString(); if(!s.startsWith("JarEntryFile[")) return null; //$NON-NLS-1$ s = s.substring("JarEntryFile[".length()); //$NON-NLS-1$ int i = s.indexOf("::"); //$NON-NLS-1$ if(i < 0) return null; String jarFile = s.substring(0, i); String entry = storage.getFullPath().toString(); return new String[]{jarFile, entry}; } public static XModelObject getJarEntryObject(IProject p, String jarFile, String entry) { File jf = new File(jarFile); try { jf = new File(new File(jarFile).getCanonicalPath()); } catch (IOException e) { ModelPlugin.getDefault().logError(e); } if(p == null) { IFile f = EclipseResourceUtil.getFile(jarFile); if(f == null) return null; p = f.getProject(); } if(p == null) return null; IModelNature n = EclipseResourceUtil.getModelNature(p); XModel model = null; if(n != null) { model = n.getModel(); } else { XModelObject o = EclipseResourceUtil.createObjectForResource(p); if(o != null) model = o.getModel(); } if(model == null) return null; XModelObject[] fs = FileSystemsHelper.getFileSystems(model).getChildren(); for (XModelObject s: fs) { String loc = Paths.expand(s.get(XModelObjectConstants.ATTR_NAME_LOCATION), model.getProperties()); if(new File(loc).equals(jf)) { XModelObject result = s.getChildByPath(entry); if(result == null && entry != null) { int q = entry.indexOf('/'); int d = entry.indexOf('.'); if(q > d && d >= 0) { String entry1 = entry.substring(0, q).replace('.', '/') + entry.substring(q); result = s.getChildByPath(entry1); } } if(result != null) return result; } } return (n == null) ? null : n.getModel().getByPath("/" + entry); //$NON-NLS-1$ } public static IEditorInput createJarEntryEditorInput(IProject project, String jarFile, final String entry) { XModelObject o = getJarEntryObject(project, jarFile, entry); if(o != null) return new ModelObjectJarEntryEditorInput(o, jarFile, entry); return XModelObjectEditorInputFactory.createNullEditorInput(entry); } public String getFactoryId() { return XModelObjectEditorInputFactory.getFactoryId(); } public void saveState(IMemento memento) { XModelObjectEditorInputFactory.saveState(memento, this); } public void revalidate() { IFile f = getFile(); if(f == null || f.equals(super.getFile())) return; try { Field field = FileEditorInput.class.getDeclaredField("file"); //$NON-NLS-1$ field.setAccessible(true); field.set(this, f); } catch (NoSuchFieldException e) { ModelUIPlugin.getPluginLog().logError(e); } catch (IllegalArgumentException e) { ModelUIPlugin.getPluginLog().logError(e); } catch (IllegalAccessException e) { ModelUIPlugin.getPluginLog().logError(e); } } }