X-Git-Url: https://gerrit.simantics.org/r/gitweb?p=simantics%2Fplatform.git;a=blobdiff_plain;f=bundles%2Forg.simantics.project%2Fsrc%2Forg%2Fsimantics%2Fproject%2Fimpl%2FProject.java;fp=bundles%2Forg.simantics.project%2Fsrc%2Forg%2Fsimantics%2Fproject%2Fimpl%2FProject.java;h=7d507bbb2e37970088e14a329ab2f1d3c7267209;hp=d6929de34f2fbe5254fd2d5f9e03cb13aecdbb1b;hb=0ae2b770234dfc3cbb18bd38f324125cf0faca07;hpb=24e2b34260f219f0d1644ca7a138894980e25b14 diff --git a/bundles/org.simantics.project/src/org/simantics/project/impl/Project.java b/bundles/org.simantics.project/src/org/simantics/project/impl/Project.java index d6929de34..7d507bbb2 100644 --- a/bundles/org.simantics.project/src/org/simantics/project/impl/Project.java +++ b/bundles/org.simantics.project/src/org/simantics/project/impl/Project.java @@ -1,364 +1,364 @@ -/******************************************************************************* - * Copyright (c) 2007, 2010 Association for Decentralized Information Management - * in Industry THTH ry. - * 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: - * VTT Technical Research Centre of Finland - initial API and implementation - *******************************************************************************/ -package org.simantics.project.impl; - -import java.lang.reflect.Method; -import java.util.Arrays; -import java.util.LinkedList; -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.concurrent.locks.Lock; -import java.util.concurrent.locks.ReentrantLock; - -import org.simantics.db.RequestProcessor; -import org.simantics.db.Resource; -import org.simantics.db.Session; -import org.simantics.db.WriteOnlyGraph; -import org.simantics.db.common.processor.MergingGraphRequestProcessor; -import org.simantics.db.common.request.WriteOnlyRequest; -import org.simantics.db.exception.CancelTransactionException; -import org.simantics.db.exception.DatabaseException; -import org.simantics.project.IProject; -import org.simantics.project.exception.ProjectException; -import org.simantics.project.features.IProjectFeature; -import org.simantics.utils.datastructures.disposable.DisposeState; -import org.simantics.utils.datastructures.disposable.IDisposeListener; -import org.simantics.utils.datastructures.hints.HintContext; -import org.simantics.utils.threads.IThreadWorkQueue; -import org.simantics.utils.threads.SyncListenerList; - - -/** - * @author Tuukka Lehtonen - */ -public class Project extends HintContext implements IProject { - - private static IProjectFeature[] NONE = {}; - - //private static final String TAG_PROJECTS = "projects"; - - private IProjectFeature[] features = NONE; - private final LinkedList featureSet = new LinkedList(); - private final LinkedList inactiveFeatures = new LinkedList(); - private final LinkedList activeFeatures = new LinkedList(); - - private final Lock lock = new ReentrantLock(); - private final AtomicBoolean active = new AtomicBoolean(false); - - protected Session session; - protected Resource resource; - - public Project(Session session, Resource resource) { - if (session == null) - throw new NullPointerException("null session"); - if (resource == null) - throw new NullPointerException("null resource"); - - this.session = session; - this.resource = resource; - //System.out.println("NEW PROJECT [" + resource.getResourceId() + "] (" + System.identityHashCode(this) + ")"); - } - - public void doDispose() { - //System.out.println("DISPOSE: " + this + " (" + System.identityHashCode(this) + ")"); - lock.lock(); - try { - deactivate(); - - featureSet.clear(); - features = NONE; - } catch (ProjectException e1) { - // TODO: do something more sensible than print the possible exception! - e1.printStackTrace(); - } finally { - lock.unlock(); - } - } - - @Override - public IProjectFeature[] getFeatures() { - assertNotDisposed(); - - // Defensive copy. - IProjectFeature[] features = this.features; - return Arrays.copyOf(features, features.length); - } - - public void addFeature(IProjectFeature feature) { - assertNotDisposed(); - lock.lock(); - try { - if (!featureSet.contains(feature)) { - featureSet.add(feature); - inactiveFeatures.add(feature); - features = featureSet.toArray(new IProjectFeature[featureSet.size()]); - } - } finally { - lock.unlock(); - } - } - - @Override - public void activate() throws ProjectException { - if (isDisposed()) - throw new IllegalStateException("project is disposed, cannot activate " + this + " (" + System.identityHashCode(this) + ")"); - - lock.lock(); - try { - if (active.get() == true) - return; - - while (!inactiveFeatures.isEmpty()) { - IProjectFeature feature = inactiveFeatures.getFirst(); - boolean success = false; - try { - feature.setProjectElement(this); - feature.configure(); - - inactiveFeatures.removeFirst(); - activeFeatures.addLast(feature); - - success = true; - } finally { - if (!success) - feature.setProjectElement(null); - } - } - - try { - transactionBarrier(); - } finally { - active.set(true); - } - } finally { - lock.unlock(); - } - } - - @Override - public void deactivate() throws ProjectException { - if (isDisposed()) - throw new IllegalStateException("project is disposed, cannot deactivate " + this + " (" + System.identityHashCode(this) + ")"); - - lock.lock(); - try { - if (active.get() == false) - return; - - while (!activeFeatures.isEmpty()) { - IProjectFeature feature = activeFeatures.getLast(); - boolean success = false; - try { - feature.deconfigure(); - - activeFeatures.removeLast(); - inactiveFeatures.addFirst(feature); - - success = true; - } finally { - if (success) - feature.setProjectElement(null); - } - } - - try { - transactionBarrier(); - } finally { - active.set(false); - } - } finally { - lock.unlock(); - } - } - - private void transactionBarrier() throws ProjectException { - // IMPORTANT: ensure that all database requests have been - // completed before returning from deactivation. - try { - session.syncRequest(new WriteOnlyRequest() { - @Override - public void perform(WriteOnlyGraph graph) throws DatabaseException { - throw new CancelTransactionException("barrier"); - } - }); - } catch (CancelTransactionException e) { - } catch (DatabaseException e) { - throw new ProjectException(e); - } - } - - @Override - public String toString() { - return getClass().getSimpleName() + " [resource=" + get().getResourceId() + "]"; - } - - @Override - public int hashCode() { - return get().hashCode(); - } - - @Override - public boolean equals(Object obj) { - if (this == obj) - return true; - if (!(obj instanceof Project)) - return false; - final Project other = (Project) obj; - - // Need to make sure that the resources are from the same session. - if (!session.equals(other.session)) - return false; - - Resource r1 = get(); - Resource r2 = other.get(); - if (r1 == null) { - if (r2 != null) - return false; - } else if (!r1.equals(r2)) - return false; - - return true; - } - - @Override - public Session getSession() { - return session; - } - - @Override - public Resource get() { - return resource; - } - - public RequestProcessor getGraphRequestProcessor() { - MergingGraphRequestProcessor mgrp = session.peekService(MergingGraphRequestProcessor.class); - return mgrp != null ? mgrp : session; - } - - // IDisposable implementation (copied from AbstractDisposable) - - SyncListenerList disposeListeners = null; - - private volatile DisposeState disposeStatus = DisposeState.Alive; - - protected void assertNotDisposed() { - if (isDisposed()) - throw new IllegalStateException(this + " is disposed"); - } - - @Override - public DisposeState getDisposeState() { - return disposeStatus; - } - - @Override - public boolean isDisposed() { - return disposeStatus == DisposeState.Disposed; - } - - public boolean isAlive() { - return disposeStatus == DisposeState.Alive; - } - - @Override - public void dispose() { - try { - lock.lock(); - try { - if (disposeStatus == DisposeState.Disposing) - return; - assertNotDisposed(); - disposeStatus = DisposeState.Disposing; - } finally { - lock.unlock(); - } - - try { - fireDisposed(); - } finally { - doDispose(); - } - } finally { - disposeStatus = DisposeState.Disposed; - } - } - - /** - * Disposes if not disposed - */ - @Override - public void safeDispose() { - try { - lock.lock(); - try { - if (disposeStatus != DisposeState.Alive) - return; - disposeStatus = DisposeState.Disposing; - } finally { - lock.unlock(); - } - - try { - fireDisposed(); - } finally { - doDispose(); - } - } finally { - disposeStatus = DisposeState.Disposed; - } - } - - protected boolean hasDisposeListeners() { - return disposeListeners!=null && !disposeListeners.isEmpty(); - } - - private final static Method onDisposed = SyncListenerList.getMethod(IDisposeListener.class, "onDisposed"); - - private void fireDisposed() { - if (disposeListeners==null) return; - disposeListeners.fireEventSync(onDisposed, this); - } - - @SuppressWarnings("unused") - private void fireDisposedAsync() { - if (disposeListeners==null) return; - disposeListeners.fireEventAsync(onDisposed, this); - } - - @Override - public void addDisposeListener(IDisposeListener listener) { - lazyGetListenerList().add(listener); - } - - @Override - public void addDisposeListener(IDisposeListener listener, IThreadWorkQueue thread) { - lazyGetListenerList().add(thread, listener); - } - - @Override - public void removeDisposeListener(IDisposeListener listener) { - if (disposeListeners==null) return; - disposeListeners.remove(listener); - } - - @Override - public void removeDisposeListener(IDisposeListener listener, IThreadWorkQueue thread) { - if (disposeListeners==null) return; - disposeListeners.remove(thread, listener); - } - - private synchronized SyncListenerList lazyGetListenerList() { - if (disposeListeners==null) - disposeListeners = new SyncListenerList(IDisposeListener.class); - return disposeListeners; - } - -} +/******************************************************************************* + * Copyright (c) 2007, 2010 Association for Decentralized Information Management + * in Industry THTH ry. + * 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: + * VTT Technical Research Centre of Finland - initial API and implementation + *******************************************************************************/ +package org.simantics.project.impl; + +import java.lang.reflect.Method; +import java.util.Arrays; +import java.util.LinkedList; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantLock; + +import org.simantics.db.RequestProcessor; +import org.simantics.db.Resource; +import org.simantics.db.Session; +import org.simantics.db.WriteOnlyGraph; +import org.simantics.db.common.processor.MergingGraphRequestProcessor; +import org.simantics.db.common.request.WriteOnlyRequest; +import org.simantics.db.exception.CancelTransactionException; +import org.simantics.db.exception.DatabaseException; +import org.simantics.project.IProject; +import org.simantics.project.exception.ProjectException; +import org.simantics.project.features.IProjectFeature; +import org.simantics.utils.datastructures.disposable.DisposeState; +import org.simantics.utils.datastructures.disposable.IDisposeListener; +import org.simantics.utils.datastructures.hints.HintContext; +import org.simantics.utils.threads.IThreadWorkQueue; +import org.simantics.utils.threads.SyncListenerList; + + +/** + * @author Tuukka Lehtonen + */ +public class Project extends HintContext implements IProject { + + private static IProjectFeature[] NONE = {}; + + //private static final String TAG_PROJECTS = "projects"; + + private IProjectFeature[] features = NONE; + private final LinkedList featureSet = new LinkedList(); + private final LinkedList inactiveFeatures = new LinkedList(); + private final LinkedList activeFeatures = new LinkedList(); + + private final Lock lock = new ReentrantLock(); + private final AtomicBoolean active = new AtomicBoolean(false); + + protected Session session; + protected Resource resource; + + public Project(Session session, Resource resource) { + if (session == null) + throw new NullPointerException("null session"); + if (resource == null) + throw new NullPointerException("null resource"); + + this.session = session; + this.resource = resource; + //System.out.println("NEW PROJECT [" + resource.getResourceId() + "] (" + System.identityHashCode(this) + ")"); + } + + public void doDispose() { + //System.out.println("DISPOSE: " + this + " (" + System.identityHashCode(this) + ")"); + lock.lock(); + try { + deactivate(); + + featureSet.clear(); + features = NONE; + } catch (ProjectException e1) { + // TODO: do something more sensible than print the possible exception! + e1.printStackTrace(); + } finally { + lock.unlock(); + } + } + + @Override + public IProjectFeature[] getFeatures() { + assertNotDisposed(); + + // Defensive copy. + IProjectFeature[] features = this.features; + return Arrays.copyOf(features, features.length); + } + + public void addFeature(IProjectFeature feature) { + assertNotDisposed(); + lock.lock(); + try { + if (!featureSet.contains(feature)) { + featureSet.add(feature); + inactiveFeatures.add(feature); + features = featureSet.toArray(new IProjectFeature[featureSet.size()]); + } + } finally { + lock.unlock(); + } + } + + @Override + public void activate() throws ProjectException { + if (isDisposed()) + throw new IllegalStateException("project is disposed, cannot activate " + this + " (" + System.identityHashCode(this) + ")"); + + lock.lock(); + try { + if (active.get() == true) + return; + + while (!inactiveFeatures.isEmpty()) { + IProjectFeature feature = inactiveFeatures.getFirst(); + boolean success = false; + try { + feature.setProjectElement(this); + feature.configure(); + + inactiveFeatures.removeFirst(); + activeFeatures.addLast(feature); + + success = true; + } finally { + if (!success) + feature.setProjectElement(null); + } + } + + try { + transactionBarrier(); + } finally { + active.set(true); + } + } finally { + lock.unlock(); + } + } + + @Override + public void deactivate() throws ProjectException { + if (isDisposed()) + throw new IllegalStateException("project is disposed, cannot deactivate " + this + " (" + System.identityHashCode(this) + ")"); + + lock.lock(); + try { + if (active.get() == false) + return; + + while (!activeFeatures.isEmpty()) { + IProjectFeature feature = activeFeatures.getLast(); + boolean success = false; + try { + feature.deconfigure(); + + activeFeatures.removeLast(); + inactiveFeatures.addFirst(feature); + + success = true; + } finally { + if (success) + feature.setProjectElement(null); + } + } + + try { + transactionBarrier(); + } finally { + active.set(false); + } + } finally { + lock.unlock(); + } + } + + private void transactionBarrier() throws ProjectException { + // IMPORTANT: ensure that all database requests have been + // completed before returning from deactivation. + try { + session.syncRequest(new WriteOnlyRequest() { + @Override + public void perform(WriteOnlyGraph graph) throws DatabaseException { + throw new CancelTransactionException("barrier"); + } + }); + } catch (CancelTransactionException e) { + } catch (DatabaseException e) { + throw new ProjectException(e); + } + } + + @Override + public String toString() { + return getClass().getSimpleName() + " [resource=" + get().getResourceId() + "]"; + } + + @Override + public int hashCode() { + return get().hashCode(); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (!(obj instanceof Project)) + return false; + final Project other = (Project) obj; + + // Need to make sure that the resources are from the same session. + if (!session.equals(other.session)) + return false; + + Resource r1 = get(); + Resource r2 = other.get(); + if (r1 == null) { + if (r2 != null) + return false; + } else if (!r1.equals(r2)) + return false; + + return true; + } + + @Override + public Session getSession() { + return session; + } + + @Override + public Resource get() { + return resource; + } + + public RequestProcessor getGraphRequestProcessor() { + MergingGraphRequestProcessor mgrp = session.peekService(MergingGraphRequestProcessor.class); + return mgrp != null ? mgrp : session; + } + + // IDisposable implementation (copied from AbstractDisposable) + + SyncListenerList disposeListeners = null; + + private volatile DisposeState disposeStatus = DisposeState.Alive; + + protected void assertNotDisposed() { + if (isDisposed()) + throw new IllegalStateException(this + " is disposed"); + } + + @Override + public DisposeState getDisposeState() { + return disposeStatus; + } + + @Override + public boolean isDisposed() { + return disposeStatus == DisposeState.Disposed; + } + + public boolean isAlive() { + return disposeStatus == DisposeState.Alive; + } + + @Override + public void dispose() { + try { + lock.lock(); + try { + if (disposeStatus == DisposeState.Disposing) + return; + assertNotDisposed(); + disposeStatus = DisposeState.Disposing; + } finally { + lock.unlock(); + } + + try { + fireDisposed(); + } finally { + doDispose(); + } + } finally { + disposeStatus = DisposeState.Disposed; + } + } + + /** + * Disposes if not disposed + */ + @Override + public void safeDispose() { + try { + lock.lock(); + try { + if (disposeStatus != DisposeState.Alive) + return; + disposeStatus = DisposeState.Disposing; + } finally { + lock.unlock(); + } + + try { + fireDisposed(); + } finally { + doDispose(); + } + } finally { + disposeStatus = DisposeState.Disposed; + } + } + + protected boolean hasDisposeListeners() { + return disposeListeners!=null && !disposeListeners.isEmpty(); + } + + private final static Method onDisposed = SyncListenerList.getMethod(IDisposeListener.class, "onDisposed"); + + private void fireDisposed() { + if (disposeListeners==null) return; + disposeListeners.fireEventSync(onDisposed, this); + } + + @SuppressWarnings("unused") + private void fireDisposedAsync() { + if (disposeListeners==null) return; + disposeListeners.fireEventAsync(onDisposed, this); + } + + @Override + public void addDisposeListener(IDisposeListener listener) { + lazyGetListenerList().add(listener); + } + + @Override + public void addDisposeListener(IDisposeListener listener, IThreadWorkQueue thread) { + lazyGetListenerList().add(thread, listener); + } + + @Override + public void removeDisposeListener(IDisposeListener listener) { + if (disposeListeners==null) return; + disposeListeners.remove(listener); + } + + @Override + public void removeDisposeListener(IDisposeListener listener, IThreadWorkQueue thread) { + if (disposeListeners==null) return; + disposeListeners.remove(thread, listener); + } + + private synchronized SyncListenerList lazyGetListenerList() { + if (disposeListeners==null) + disposeListeners = new SyncListenerList(IDisposeListener.class); + return disposeListeners; + } + +}