blob: 0b2e92014702778f5e3b6f8397e711164db801be [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2007 Cisco Systems, Inc.
* 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. Dillon (Cisco Systems, Inc.) - reformat for Code Open-Sourcing
*******************************************************************************/
package org.eclipse.tigerstripe.workbench.internal.api.impl;
import java.io.File;
import java.io.StringReader;
import java.net.URI;
import java.util.ArrayList;
import java.util.Collection;
import org.apache.commons.lang.StringUtils;
import org.eclipse.core.resources.IContainer;
import org.eclipse.core.resources.IMarker;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IWorkspaceRoot;
import org.eclipse.core.resources.IWorkspaceRunnable;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.ISafeRunnable;
import org.eclipse.core.runtime.ListenerList;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.SafeRunner;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.tigerstripe.workbench.TigerstripeException;
import org.eclipse.tigerstripe.workbench.WorkingCopyException;
import org.eclipse.tigerstripe.workbench.generation.IM1Generator;
import org.eclipse.tigerstripe.workbench.generation.IM1RunConfig;
import org.eclipse.tigerstripe.workbench.internal.BasePlugin;
import org.eclipse.tigerstripe.workbench.internal.api.contract.segment.IFacetReference;
import org.eclipse.tigerstripe.workbench.internal.api.contract.useCase.IUseCaseReference;
import org.eclipse.tigerstripe.workbench.internal.api.project.IImportCheckpoint;
import org.eclipse.tigerstripe.workbench.internal.api.project.INameProvider;
import org.eclipse.tigerstripe.workbench.internal.contract.segment.FacetReference;
import org.eclipse.tigerstripe.workbench.internal.contract.useCase.UseCaseReference;
import org.eclipse.tigerstripe.workbench.internal.core.TigerstripeRuntime;
import org.eclipse.tigerstripe.workbench.internal.core.generation.M1Generator;
import org.eclipse.tigerstripe.workbench.internal.core.model.ArtifactManager;
import org.eclipse.tigerstripe.workbench.internal.core.model.ArtifactManagerImpl;
import org.eclipse.tigerstripe.workbench.internal.core.model.importing.AbstractImportCheckpointHelper;
import org.eclipse.tigerstripe.workbench.internal.core.project.Dependency;
import org.eclipse.tigerstripe.workbench.internal.core.project.InternalTigerstripeProject;
import org.eclipse.tigerstripe.workbench.internal.core.project.ModelReferenceInternal;
import org.eclipse.tigerstripe.workbench.internal.core.project.ProjectDetails;
import org.eclipse.tigerstripe.workbench.model.deprecated_.IArtifactManagerSession;
import org.eclipse.tigerstripe.workbench.project.IDependency;
import org.eclipse.tigerstripe.workbench.project.IModelReference;
import org.eclipse.tigerstripe.workbench.project.IPluginConfig;
import org.eclipse.tigerstripe.workbench.project.IProjectDependencyChangeListener;
import org.eclipse.tigerstripe.workbench.project.IProjectDependencyDelta;
import org.eclipse.tigerstripe.workbench.project.IProjectDetails;
import org.eclipse.tigerstripe.workbench.project.ITigerstripeModelProject;
import org.eclipse.tigerstripe.workbench.project.ITigerstripeModelProjectInternal;
public abstract class TigerstripeProjectHandle extends
BaseTigerstripeModelProject implements ITigerstripeModelProjectInternal {
private ListenerList projectChangeListeners = new ListenerList();
private INameProvider nameProvider;
private ArtifactManager manager;
private boolean dependenciesCacheNeedsRefresh = false;
public static final String DESCRIPTOR_FILENAME = ITigerstripeConstants.PROJECT_DESCRIPTOR;
private boolean wasDisposed = false;
public String getDescriptorFilename() {
return DESCRIPTOR_FILENAME;
}
private InternalTigerstripeProject tsProject;
public TigerstripeProjectHandle(URI projectContainerURI) {
super(TigerstripeRuntime.getDefaultInstance(),projectContainerURI);
}
@Override
protected IM1Generator getGenerator(ITigerstripeModelProject project,IM1RunConfig config) {
return new M1Generator(this, config);
}
public void setProjectDetails(IProjectDetails projectDetails)
throws WorkingCopyException, TigerstripeException {
assertSet();
getTSProject().setProjectDetails((ProjectDetails) projectDetails);
}
public INameProvider getNameProvider() {
if (nameProvider == null) {
nameProvider = new NameProviderImpl(this);
}
return nameProvider;
}
public String getBaseRepository() throws TigerstripeException {
if (getTSProject() != null)
return getTSProject().getBaseRepository();
throw new TigerstripeException("Invalid project handle.");
}
public synchronized IArtifactManagerSession getArtifactManagerSession()
throws TigerstripeException {
if (artifactMgrSession == null) {
if (manager == null) {
ArtifactManagerImpl impl = new ArtifactManagerImpl(getTSProject());
impl.registerListeners();
manager = impl;
}
setArtifactManagerSession(new ArtifactManagerSessionImpl(manager));
}
return artifactMgrSession;
}
public boolean wasDisposed() {
if (isWorkingCopy()) {
return super.wasDisposed() && wasDisposed;
}
return wasDisposed;
}
protected void setTSProject(InternalTigerstripeProject tsProject) {
this.tsProject = tsProject;
}
public InternalTigerstripeProject getTSProject() throws TigerstripeException {
if (tsProject == null) {
// try and create a project for the URI
File baseDir = new File(this.getProjectContainerURI());
if (baseDir.isDirectory()) {
tsProject = new InternalTigerstripeProject(baseDir, this);
} else
throw new TigerstripeException("Invalid project "
+ baseDir.toString());
}
tsProject.reload(false);
return this.tsProject;
}
@Override
public boolean exists() {
boolean result = false;
// check that a descriptor can be found and that it is valid
if (findProjectDescriptor()) {
try {
getTSProject();
result = true;
} catch (TigerstripeException e) {
result = false;
}
}
return result;
}
public void addPluginConfig(IPluginConfig ref) throws TigerstripeException {
assertSet();
getTSProject().addPluginConfig(ref);
}
public void removePluginConfig(IPluginConfig ref)
throws TigerstripeException {
assertSet();
getTSProject().removePluginConfig(ref);
}
public IDependency makeDependency(String relativePath)
throws TigerstripeException {
return new Dependency(runtime, getTSProject(), relativePath);
}
public void addDependency(IDependency dependency, IProgressMonitor monitor)
throws TigerstripeException {
assertSet();
dependenciesCacheNeedsRefresh = true;
getTSProject().addDependency(dependency);
ProjectDependencyChangeDelta delta = new ProjectDependencyChangeDelta(
this, IProjectDependencyDelta.PROJECT_DEPENDENCY_ADDED, dependency);
broadcastProjectDependencyChange(delta);
}
public void addDependencies(IDependency[] dependencies,
IProgressMonitor monitor) throws WorkingCopyException,
TigerstripeException {
assertSet();
dependenciesCacheNeedsRefresh = true;
getTSProject().addDependencies(dependencies);
for (IDependency dep : dependencies) {
ProjectDependencyChangeDelta delta = new ProjectDependencyChangeDelta(
this, IProjectDependencyDelta.PROJECT_DEPENDENCY_ADDED,
dep);
broadcastProjectDependencyChange(delta);
}
}
public void removeDependency(IDependency dependency,
IProgressMonitor monitor) throws WorkingCopyException,
TigerstripeException {
assertSet();
dependenciesCacheNeedsRefresh = true;
getTSProject().removeDependency(dependency);
ProjectDependencyChangeDelta delta = new ProjectDependencyChangeDelta(
this, IProjectDependencyDelta.PROJECT_DEPENDENCY_REMOVED, dependency);
broadcastProjectDependencyChange(delta);
}
public void removeDependencies(IDependency[] dependencies,
IProgressMonitor monitor) throws WorkingCopyException,
TigerstripeException {
assertSet();
dependenciesCacheNeedsRefresh = true;
getTSProject().removeDependencies(dependencies);
for (IDependency dep : dependencies) {
ProjectDependencyChangeDelta delta = new ProjectDependencyChangeDelta(
this, IProjectDependencyDelta.PROJECT_DEPENDENCY_REMOVED,
dep);
broadcastProjectDependencyChange(delta);
}
}
public void removeModelReference(String modelRefId)
throws TigerstripeException {
assertSet();
dependenciesCacheNeedsRefresh = true;
IModelReference modelRef = clearReference(modelRefId);
// This could happen if reference was not loaded, simply create a dummy
// instance to pass to the base project, otherwise it won't be removed
// correctly.
if (modelRef == null) {
modelRef = new ModelReferenceInternal(modelRefId);
}
getTSProject().removeModelReference(modelRef);
ProjectDependencyChangeDelta delta = new ProjectDependencyChangeDelta(
this, IProjectDependencyDelta.PROJECT_REFERENCE_REMOVED,
modelRef);
broadcastProjectDependencyChange(delta);
}
public void removeModelReferences(String[] modelRefs)
throws TigerstripeException {
for (String modelId : modelRefs) {
removeModelReference(modelId);
}
}
public IModelReference addModelReference(String modelId)
throws TigerstripeException {
assertSet();
dependenciesCacheNeedsRefresh = true;
IModelReference modelRef = makeReference(modelId);
modelRef.setEnabled(true);
getTSProject().addModelReference(modelRef);
if (modelRef.isResolved()) {
ProjectDependencyChangeDelta delta = new ProjectDependencyChangeDelta(
this, IProjectDependencyDelta.PROJECT_REFERENCE_ADDED,
modelRef);
broadcastProjectDependencyChange(delta);
}
return modelRef;
}
public IModelReference[] addModelReferences(String[] modelRefIds)
throws TigerstripeException {
Collection<IModelReference> modelRefs = new ArrayList<>();
for (String modelId : modelRefIds) {
modelRefs.add(addModelReference(modelId));
}
return modelRefs.stream().toArray(IModelReference[]::new);
}
public void setAdvancedProperty(String property, String value)
throws TigerstripeException {
assertSet();
getTSProject().setAdvancedProperty(property, value);
}
public boolean requiresDescriptorUpgrade() throws TigerstripeException {
return getTSProject().requiresDescriptorUpgrade();
}
/**
* Returns the IImportCheckpoint for this project
*
*/
public IImportCheckpoint getImportCheckpoint() throws TigerstripeException {
AbstractImportCheckpointHelper cpHelper = new AbstractImportCheckpointHelper(
this);
IImportCheckpoint result = cpHelper.readCheckpoint();
return result;
}
public IArtifactManagerSession getIArtifactManagerSession()
throws TigerstripeException {
return getArtifactManagerSession();
}
public void doSave() throws TigerstripeException {
try {
InternalTigerstripeProject project = getTSProject();
if (project != null) {
project.doSave(null);
project.clearDirty();
return;
}
} catch (TigerstripeException e) {
if (tsProject != null) {
// This means we are saving on an empty directory, and the
// descriptor needs to be created now
tsProject.doSave(null);
return;
}
}
throw new TigerstripeException("Invalid project, cannot save.");
}
public IFacetReference makeFacetReference(URI facetURI)
throws TigerstripeException {
return new FacetReference(facetURI, this);
}
public IFacetReference makeFacetReference(String projectRelativePath)
throws TigerstripeException {
return new FacetReference(projectRelativePath,
getTSProject());
}
public IUseCaseReference makeIUseCaseReference(URI useCaseURI)
throws TigerstripeException {
return new UseCaseReference(useCaseURI, this);
}
public void addFacetReference(IFacetReference facetRef)
throws TigerstripeException {
assertSet();
getTSProject().addFacetReference(facetRef);
}
public void removeFacetReference(IFacetReference facetRef)
throws TigerstripeException {
assertSet();
getTSProject().removeFacetReference(facetRef);
}
public ITigerstripeModelProject[] getIReferencedProjects()
throws TigerstripeException {
return getReferencedProjects();
}
// ==========================================================================
// ====
// WorkingCopy stuff
@Override
public void doCommit(IProgressMonitor monitor) throws TigerstripeException {
TigerstripeProjectHandle original = (TigerstripeProjectHandle) getOriginal();
original.reloadFrom(getTSProject(), dependenciesCacheNeedsRefresh,
monitor);
original.doSave();
try {
original.getIProject().refreshLocal(1, monitor);
} catch (CoreException e) {
throw new TigerstripeException("Error saving descriptor", e);
}
getTSProject().clearDirty();
dependenciesCacheNeedsRefresh = false;
}
// ========================================
// Project dependency change listeners stuff
public void addProjectDependencyChangeListener(
IProjectDependencyChangeListener listener) {
if (isWorkingCopy()) {
TigerstripeProjectHandle original = (TigerstripeProjectHandle) getOriginal();
original.addProjectDependencyChangeListener(listener);
} else {
projectChangeListeners.add(listener);
}
}
public void removeProjectDependencyChangeListener(
IProjectDependencyChangeListener listener) {
if (isWorkingCopy()) {
TigerstripeProjectHandle original = (TigerstripeProjectHandle) getOriginal();
if (original != null) {
original.removeProjectDependencyChangeListener(listener);
}
} else {
projectChangeListeners.remove(listener);
}
}
public void broadcastProjectDependencyChange(
final IProjectDependencyDelta delta) {
if (isWorkingCopy()) {
TigerstripeProjectHandle original = (TigerstripeProjectHandle) getOriginal();
original.broadcastProjectDependencyChange(delta);
} else {
Object[] objects = projectChangeListeners.getListeners();
for (Object obj : objects) {
final IProjectDependencyChangeListener listener = (IProjectDependencyChangeListener) obj;
SafeRunner.run(new ISafeRunnable() {
public void handleException(Throwable exception) {
BasePlugin.log(exception);
}
public void run() throws Exception {
listener.projectDependenciesChanged(delta);
}
});
}
}
}
public void reloadFrom(InternalTigerstripeProject descriptor,
boolean dependenciesCacheNeedsRefresh, IProgressMonitor monitor)
throws TigerstripeException {
StringReader reader = new StringReader(descriptor.asText());
getTSProject().reloadFrom(reader);
if (dependenciesCacheNeedsRefresh) {
// Rebuild the cache if dependencies were added
((ArtifactManagerSessionImpl) getArtifactManagerSession())
.getArtifactManager().updateDependenciesContentCache(
monitor);
}
}
/*
* (non-Javadoc)
*
* @see
* org.eclipse.tigerstripe.workbench.project.ITigerstripeModelProject#getModelId
* ()
*/
public String getModelId() throws TigerstripeException {
return StringUtils.defaultIfEmpty(getProjectDetails().getModelId(), getName());
}
/*
* (non-Javadoc)
*
* @see
* org.eclipse.tigerstripe.workbench.project.ITigerstripeModelProject#setModelId
* (java.lang.String)
*/
public void setModelId(String modelId) throws WorkingCopyException,
TigerstripeException {
IProjectDetails details = getProjectDetails();
details.setModelId(modelId);
setProjectDetails(details);
}
@Override
public void dispose() {
super.dispose();
if (manager != null) {
manager.dispose();
}
if (tsProject != null) {
tsProject.dispose();
}
wasDisposed = true;
}
// NM: Marks the cache as dirty so it'll refresh it next time
public void markCacheAsDirty() {
dependenciesCacheNeedsRefresh = true;
}
public boolean containsErrors() {
IProject project = (IProject) this.getAdapter(IProject.class);
try {
IMarker[] markers = project.findMarkers(IMarker.PROBLEM, true,
IResource.DEPTH_INFINITE);
for (int i = 0; i < markers.length; i++) {
if (IMarker.SEVERITY_ERROR == markers[i].getAttribute(
IMarker.SEVERITY, IMarker.SEVERITY_INFO)) {
return true;
}
}
} catch (CoreException e) {
BasePlugin.log(e);
}
return false;
}
public Object getAdapter(@SuppressWarnings("rawtypes") Class adapter) {
if (adapter == IProject.class) {
try {
return getIProject();
} catch (TigerstripeException e) {
return null;
}
} else if (adapter == IJavaProject.class) {
try {
IProject project = getIProject();
// Note that this will be null for the PhantomProject
if (project != null) {
return JavaCore.create(project);
}
} catch (TigerstripeException e) {
return null;
}
}
return null;
}
private IProject getIProject()
throws TigerstripeException {
IContainer container = getIContainer();
if (container instanceof IProject) {
return (IProject) container;
}
/**
* Project also can be child folder in other project. In this case this
* container will be IFolder instead of IProject
*/
if (container != null) {
IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
for (IProject project : root.getProjects()) {
if (project.getLocation().equals(container.getLocation())) {
return project;
}
}
}
throw new TigerstripeException("Can't resolve " + this.getLocation()
+ " as Eclipse IProject");
}
private IContainer container;
// Introduced as a result of Bugzilla 319896
private IContainer getIContainer() {
if (container == null) {
IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
File file = new File(this.getLocation().toOSString());
IPath path = new Path(file.getAbsolutePath());
container = root.getContainerForLocation(path);
}
return container;
}
public void delete(final boolean force, IProgressMonitor monitor)
throws TigerstripeException {
if (monitor == null)
monitor = new NullProgressMonitor();
final IProject project = (IProject) getAdapter(IProject.class);
if (project != null) {
try {
ResourcesPlugin.getWorkspace().run(new IWorkspaceRunnable() {
@Override
public void run(IProgressMonitor monitor)
throws CoreException {
project.delete(force, monitor);
}
}, project, IResource.NONE, monitor);
} catch (CoreException e) {
throw new TigerstripeException("An error occured while trying to delete project:" + e.getMessage(), e);
}
}
}
@Override
public IPath getFullPath() {
String name = getName();
if (name == null) {
return null;
}
IResource member = ResourcesPlugin.getWorkspace().getRoot()
.findMember(name);
if (member == null) {
return null;
}
return member.getFullPath();
}
@Override
protected IModelReference newRef(String modelId) {
return new ModelReferenceInternal(getRuntime(), this, modelId);
}
}