/*******************************************************************************
* Copyright (c) 2005,2010 Eclipse Modeling Project.
* 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:
* E.D.Willink - initial API and implementation
*******************************************************************************/
package org.eclipse.ocl.examples.editor.ui.common;
import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import org.eclipse.core.resources.IResourceChangeEvent;
import org.eclipse.core.resources.IResourceChangeListener;
import org.eclipse.core.resources.IResourceDelta;
import org.eclipse.core.runtime.FileLocator;
import org.eclipse.emf.common.notify.Notification;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.ocl.examples.common.label.Label;
import org.eclipse.ocl.examples.common.utils.EcoreUtils;
import org.eclipse.ocl.examples.common.utils.TracingAdapter;
import org.eclipse.ocl.examples.editor.ui.OCLExamplesEditorPlugin;
/**
* ResourceAdapter extends Resource with externally imposed and internally chosen
* read-only attributes..
*/
public abstract class ResourceAdapter extends TracingAdapter
{
public static ResourceAdapter getAdapter(Resource resource, boolean isLocked) {
if (resource == null)
return null;
ResourceAdapter resourceAdapter = EcoreUtils.getAdapter(resource, ResourceAdapter.class);
if (resourceAdapter == null)
resourceAdapter = new ResourceAdapterImpl(resource, isLocked);
else if (resourceAdapter.isLocked() && !isLocked)
resourceAdapter.setLocked(isLocked);
return resourceAdapter;
}
public static ResourceAdapter getAdapter(Resource resource) {
return getAdapter(resource, true);
}
// public static Orphanage getOrphanage(Object model) {
// Resource resource = TreeAccessor.eResource(model);
// ResourceAdapter adapter = getAdapter(resource);
// return adapter != null ? adapter.getOrphanage() : null;
// }
// public static Orphanage getOrphanage(Resource resource) {
// ResourceAdapter adapter = getAdapter(resource);
// return adapter != null ? adapter.getOrphanage() : null;
// }
public static boolean isLocked(Resource resource) {
ResourceAdapter adapter = getAdapter(resource);
return adapter != null ? adapter.isLocked() : false;
}
// public static boolean isLocked(Object model) {
// Resource resource = TreeAccessor.eResource(model);
// ResourceAdapter adapter = getAdapter(resource);
// return adapter != null ? adapter.isLocked() : false;
// }
public static boolean isReadOnly(Resource resource) {
ResourceAdapter adapter = getAdapter(resource);
return adapter != null ? adapter.isReadOnly() : false;
}
// public static boolean isReadOnly(Object model) {
// Resource resource = TreeAccessor.eResource(model);
// ResourceAdapter adapter = getAdapter(resource);
// return adapter != null ? adapter.isReadOnly() : false;
// }
public static boolean isSaveable(Resource resource) {
ResourceAdapter adapter = getAdapter(resource);
return adapter != null ? adapter.isSaveable() : false;
}
public abstract boolean computeIsReadOnly();
public void dispose() {}
// public abstract Orphanage getOrphanage();
public abstract Resource getResource();
public Resource getUnderlyingResource() {
return getResource();
}
@Override
public boolean isAdapterForType(Object type) {
return type == ResourceAdapter.class;
}
public abstract boolean isLocked();
public abstract boolean isReadOnly();
public abstract boolean isSaveable();
public abstract void setLocked(boolean isLocked);
public abstract void setReadOnly(boolean isReadOnly);
@Override
public String toString() {
return getClass().getSimpleName() + "[" + Label.labelFor(getResource()) + "]"
+ (isReadOnly() ? " read-only" : " read-write")
+ (isLocked() ? " locked" : " unlocked");
}
public static class ResourceAdapterImpl
extends ResourceAdapter
implements IResourceChangeListener
{
private final Resource resource;
private URI uri; // may be null for a read-write test resource
private String fileName; // null if not a file
private boolean isReadOnly; // external resource constraint
private boolean isLocked; // internal user preference
// private Orphanage orphanage = null;
protected ResourceAdapterImpl(Resource resource, boolean isLocked) {
// this.listener = this;
this.resource = resource;
resource.eAdapters().add(this);
setURI(resource.getURI()); // Sets isReadOnly
this.isLocked = isReadOnly || isLocked;
// IWorkspace workspace = ResourcesPlugin.getWorkspace();
// workspace.addResourceChangeListener(this, IResourceChangeEvent.POST_CHANGE);
}
@Override
public boolean computeIsReadOnly() {
if (uri == null)
return false;
try {
URL url = new URL(uri.toString());
URL resolvedURL = FileLocator.resolve(url); // FIXME Use URI facilities to avoid loss of platform:
String protocol = resolvedURL.getProtocol();
if ("file".equals(protocol)) {
fileName = resolvedURL.getFile();
File file = new File(fileName);
if (file.canWrite())
return false;
}
} catch (MalformedURLException e) {
} catch (IOException e) {
OCLExamplesEditorPlugin.logError("Failed to access " + uri.toString(), e);
}
return true;
}
@Override
public void dispose() {
// IWorkspace workspace = ResourcesPlugin.getWorkspace();
// workspace.removeResourceChangeListener(this);
}
// @Override
// public Orphanage getOrphanage() {
// if (orphanage == null)
// orphanage = new Orphanage(resource);
// return orphanage;
// }
@Override
public Resource getResource() {
return resource;
}
public URI getURI() {
return uri;
}
@Override
protected void handleNotification(Notification msg) {
super.notifyChanged(msg);
if (EcoreUtils.getFeatureID(msg, resource, Resource.class) == Resource.RESOURCE__ERRORS) {
Object e = msg.getNewValue();
OCLExamplesEditorPlugin.logError("Error in '" + resource.getURI() + "'", e instanceof Throwable ? (Throwable)e : null);
}
}
@Override
public boolean isLocked() {
return isLocked;
}
@Override
public boolean isReadOnly() {
return isReadOnly;
}
@Override
public boolean isSaveable() {
return true;
}
public void resourceChanged(IResourceChangeEvent event) {
IResourceDelta resourceDelta = event.getDelta();
if (resourceDelta != null)
resourceChanged(resourceDelta);
}
public void resourceChanged(IResourceDelta resourceDelta) {
// IPath location = resourceDelta.getFullPath();
// String pathString = "" + location;
// System.out.println("Resource changed : '" + pathString + "' wrt '" + fileName + "'");
for (IResourceDelta childDelta : resourceDelta.getAffectedChildren())
resourceChanged(childDelta);
}
@Override
public void setLocked(boolean setLocked) {
if (setLocked) {
if (resource.isModified()) {
OCLExamplesEditorPlugin.showError("Cannot lock modified resource: " + Label.labelFor(resource), null);
return;
}
}
else {
if (computeIsReadOnly()) {
OCLExamplesEditorPlugin.showError("Cannot unlock read-only resource: " + Label.labelFor(resource), null);
return;
}
}
boolean wasLocked = isLocked;
isLocked = setLocked || isReadOnly;
if (wasLocked != isLocked)
resource.setModified(resource.isModified());
}
@Override
public void setReadOnly(boolean setReadOnly) {
if (setReadOnly) {
if (resource.isModified()) {
OCLExamplesEditorPlugin.showError("Cannot set modified resource read-only: " + Label.labelFor(resource), null);
return;
}
}
else {
if (computeIsReadOnly()) {
OCLExamplesEditorPlugin.showError("Cannot set read-only resource read-write: " + Label.labelFor(resource), null);
return;
}
}
boolean wasReadOnly = isReadOnly;
isReadOnly = setReadOnly;
isLocked = isLocked || isReadOnly;
if (wasReadOnly != isReadOnly)
resource.setModified(resource.isModified());
}
public void setURI(URI uri) {
this.uri = uri;
fileName = null;
isReadOnly = computeIsReadOnly();
setLocked(isLocked || isReadOnly);
}
}
}