/*******************************************************************************
* Copyright (c) 2015 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
*
* Contributor:
* Red Hat, Inc. - initial API and implementation
******************************************************************************/
package org.jboss.tools.batch.internal.core.scanner.lib;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.IPath;
/**
* Monitors class path of project and loads seam components of it.
*
* @author Viacheslav Kabanovich
*/
public abstract class AbstractClassPathMonitor implements Libs.LibsListener {
Libs libs;
protected List<String> paths = new ArrayList<String>();
private boolean loaded = false;
protected Map<IPath, String> paths2 = new HashMap<IPath, String>();
boolean libsModified = false;
protected Set<String> processedPaths = new HashSet<String>();
public AbstractClassPathMonitor() {
}
public IProject getProject() {
return getProjectResource();
}
/**
* Initialization of inner model.
*/
public void init() {
if(libs == null && getProject() != null) {
libs = new Libs(getProject());
libs.addListener(this);
libs.init();
}
}
public abstract IProject getProjectResource();
/**
* Returns true if class path was up-to-date.
* Otherwise, updates inner model and disables class loader.
* @return
*/
public boolean update() {
if(libs == null) {
return false;
}
libs.update();
synchronized(this) {
List<String> newPaths = libs.getPaths();
boolean result = libsModified || !loaded;
if(newPaths != null) {
paths = newPaths;
loaded = true;
} else {
paths = new ArrayList<String>();
loaded = false;
}
if(result) {
paths2.clear();
paths2.putAll(libs.getPathsAsMap());
}
libsModified = false;
return result;
}
}
public void pathLoaded(IPath path) {
String p = paths2.get(path);
if(p != null) synchronized (this) {
processedPaths.add(p);
}
}
public boolean hasPath(IPath path) {
return paths2.get(path) != null;
}
public void clean() {
if(libs != null) {
libs.requestForUpdate();
}
paths = new ArrayList<String>();
loaded = false;
if(paths2 != null) paths2.clear();
synchronized (this) {
processedPaths.clear();
}
}
public synchronized void reset() {
processedPaths.clear();
}
protected List<String> syncProcessedPaths() {
ArrayList<String> removed = new ArrayList<String>();
synchronized (this) {
Iterator<String> it = processedPaths.iterator();
while(it.hasNext()) {
String p = it.next();
if(paths.contains(p)) continue;
removed.add(p);
it.remove();
}
}
return removed;
}
protected boolean requestForLoad(String p) {
synchronized (this) {
return processedPaths.add(p);
}
}
public void pathsChanged(List<String> paths) {
synchronized (this) {
libsModified = true;
}
}
public void libraryChanged(String path) {
synchronized (this) {
libsModified = true;
processedPaths.remove(path);
}
}
public void dispose() {
if(libs != null) {
libs.destroy();
libs = null;
}
}
}