blob: 5a3eee8fa5eecf9d4e7b63fba9013e79bda55515 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2010 BSI Business Systems Integration AG.
* 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:
* BSI Business Systems Integration AG - initial API and implementation
******************************************************************************/
package org.eclipse.scout.sdk.rap.var;
import java.util.HashSet;
import java.util.Queue;
import java.util.Set;
import java.util.concurrent.ConcurrentLinkedQueue;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IResourceChangeEvent;
import org.eclipse.core.resources.IResourceChangeListener;
import org.eclipse.core.resources.IResourceDelta;
import org.eclipse.core.resources.IResourceDeltaVisitor;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.ISchedulingRule;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.core.variables.IValueVariable;
import org.eclipse.core.variables.IValueVariableListener;
import org.eclipse.core.variables.VariablesPlugin;
import org.eclipse.scout.commons.CompareUtility;
import org.eclipse.scout.commons.EventListenerList;
import org.eclipse.scout.commons.StringUtility;
import org.eclipse.scout.sdk.rap.ScoutSdkRap;
import org.eclipse.scout.sdk.util.resources.ResourceUtility;
/**
* <h3>{@link RapTargetVariable}</h3> ...
*
* @author Matthias Villiger
* @since 3.9.0 14.01.2013
*/
public final class RapTargetVariable {
public final static String RAP_TARGET_KEY = "scout_rap_target";
public final static String RESOURCE_CHANGE_JOB_FAMILY = "ScoutRapTargetResourceCheckFamily";
public final static P_JobRule JOB_RULE = new P_JobRule();
private final static RapTargetVariable INSTANCE = new RapTargetVariable();
private final EventListenerList m_listeners;
private final P_TargetFileListener m_targetFileListener;
private final P_ResourceChangeEventHandlerJob m_resourceChangeJob;
private final Queue<IResourceChangeEvent> m_resourceChangeEventsToHandle;
private final IValueVariable m_scoutRapTargetVariable;
private final IRapTargetVariableListener m_valueChangeListener;
private final IValueVariableListener m_variableListener;
private String m_oldVal;
private RapTargetVariable() {
m_listeners = new EventListenerList();
m_scoutRapTargetVariable = VariablesPlugin.getDefault().getStringVariableManager().getValueVariable(RAP_TARGET_KEY);
m_oldVal = null;
m_resourceChangeEventsToHandle = new ConcurrentLinkedQueue<IResourceChangeEvent>();
m_resourceChangeJob = new P_ResourceChangeEventHandlerJob();
m_targetFileListener = new P_TargetFileListener();
m_valueChangeListener = new RapTargetVariableListenerAdapter() {
@Override
public void valueChanged(String oldVal, String newVal) {
refreshResourceListener();
}
};
m_variableListener = new P_VariableListener();
}
private void refreshResourceListener() {
if (!StringUtility.hasText(getValue())) {
// no value: register listener that waits for target files using the variable
ResourcesPlugin.getWorkspace().addResourceChangeListener(m_targetFileListener, IResourceChangeEvent.POST_CHANGE | IResourceChangeEvent.PRE_REFRESH);
}
else {
// variable has a value: no need to listen anymore: remove
ResourcesPlugin.getWorkspace().removeResourceChangeListener(m_targetFileListener);
}
}
public void start() {
addListener(m_valueChangeListener);
VariablesPlugin.getDefault().getStringVariableManager().addValueVariableListener(m_variableListener);
refreshResourceListener();
}
public void stop() {
removeListener(m_valueChangeListener);
VariablesPlugin.getDefault().getStringVariableManager().removeValueVariableListener(m_variableListener);
ResourcesPlugin.getWorkspace().removeResourceChangeListener(m_targetFileListener);
}
public void addListener(IRapTargetVariableListener listener) {
m_listeners.add(IRapTargetVariableListener.class, listener);
}
public void removeListener(IRapTargetVariableListener listener) {
m_listeners.remove(IRapTargetVariableListener.class, listener);
}
private void fireValueChanged(String oldVal, String newVal) {
for (IRapTargetVariableListener listener : m_listeners.getListeners(IRapTargetVariableListener.class)) {
try {
listener.valueChanged(oldVal, newVal);
}
catch (Exception e) {
ScoutSdkRap.logWarning("RAP Target Variable Listener could not be completed.", e);
}
}
}
private void fireEmptyVariableInUse(IFile targetFile) {
for (IRapTargetVariableListener listener : m_listeners.getListeners(IRapTargetVariableListener.class)) {
try {
listener.emptyVariableInUse(targetFile);
}
catch (Exception e) {
ScoutSdkRap.logWarning("RAP Target Variable Listener could not be completed.", e);
}
}
}
/**
* Sets a new value for the scout_rap_target variable.<br>
* The new value is directly propagated to the environment variable.
*
* @param val
* The new value
*/
public void setValue(String val) {
setValue(val, false);
}
void initialize(String val) {
setValue(val, true);
}
private synchronized void setValue(String val, boolean isInitialSet) {
String oldVal = isInitialSet ? null : m_scoutRapTargetVariable.getValue(); // not possible to call getValue() when we are initializing
String newVal = StringUtility.hasText(val) ? val.trim() : null;
if (CompareUtility.notEquals(oldVal, newVal)) {
m_scoutRapTargetVariable.setValue(newVal);
}
}
/**
* gets the current value of the scout_rap_target variable
*
* @return
*/
public synchronized String getValue() {
return m_scoutRapTargetVariable.getValue();
}
public static RapTargetVariable get() {
return INSTANCE;
}
public static final class P_JobRule implements ISchedulingRule {
private P_JobRule() {
}
@Override
public boolean contains(ISchedulingRule rule) {
return rule == JOB_RULE;
}
@Override
public boolean isConflicting(ISchedulingRule rule) {
return rule == JOB_RULE;
}
}
private final class P_ResourceChangeEventHandlerJob extends Job {
private P_ResourceChangeEventHandlerJob() {
super("Check for Scout rap target variable");
setSystem(true);
setUser(false);
setRule(JOB_RULE);
}
private boolean isScoutRapTargetVarPresent(IFile r) throws CoreException {
String s = ResourceUtility.getContent(r);
return s.contains(RAP_TARGET_KEY);
}
@Override
public boolean belongsTo(Object family) {
return RESOURCE_CHANGE_JOB_FAMILY.equals(family);
}
private void collectTargetFiles(IResourceDelta d, final Set<IFile> res) throws CoreException {
if (d == null) {
return;
}
try {
d.accept(new IResourceDeltaVisitor() {
@Override
public boolean visit(IResourceDelta delta) throws CoreException {
IResource resource = delta.getResource();
if (ResourceUtility.exists(resource) && resource.getType() == IResource.FILE && resource.getName().toLowerCase().endsWith(".target")) {
res.add((IFile) resource);
return false;
}
return true;
}
});
}
catch (CoreException e) {
ScoutSdkRap.logError("Could not check for .target files that use the scout rap target variable.", e);
}
}
@Override
protected IStatus run(IProgressMonitor monitor) {
IResourceChangeEvent event;
while ((event = m_resourceChangeEventsToHandle.poll()) != null) {
if (!StringUtility.hasText(getValue())) {
try {
HashSet<IFile> collector = new HashSet<IFile>();
collectTargetFiles(event.getDelta(), collector);
if (!collector.isEmpty()) {
for (IFile f : collector) {
try {
if (isScoutRapTargetVarPresent(f)) {
fireEmptyVariableInUse(f);
break;
}
}
catch (CoreException e) {
ScoutSdkRap.logWarning(e);
}
}
}
}
catch (CoreException e) {
ScoutSdkRap.logWarning(e);
}
}
}
return Status.OK_STATUS;
}
}
private final class P_TargetFileListener implements IResourceChangeListener {
@Override
public void resourceChanged(IResourceChangeEvent event) {
m_resourceChangeEventsToHandle.offer(event);
m_resourceChangeJob.schedule();
}
}
private final class P_VariableListener implements IValueVariableListener {
@Override
public void variablesRemoved(IValueVariable[] variables) {
}
@Override
public void variablesChanged(IValueVariable[] variables) {
for (IValueVariable var : variables) {
if (RAP_TARGET_KEY.equals(var.getName())) {
String newVal = var.getValue();
fireValueChanged(m_oldVal, newVal);
m_oldVal = newVal;
}
}
}
@Override
public void variablesAdded(IValueVariable[] variables) {
}
}
}