// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package net.sourceforge.eclipsejetty.launch.configuration;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
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 net.sourceforge.eclipsejetty.JettyPluginUtils;
import net.sourceforge.eclipsejetty.launch.configuration.JettyLaunchDependencyEntry.Kind;
import net.sourceforge.eclipsejetty.launch.configuration.JettyLaunchDependencyEntry.Type;
import net.sourceforge.eclipsejetty.launch.util.JettyLaunchConfigurationAdapter;
import net.sourceforge.eclipsejetty.util.Dependency;
import net.sourceforge.eclipsejetty.util.RegularMatcher;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.jdt.launching.IRuntimeClasspathEntry;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.widgets.Table;
/**
* Holds the list of table entries in the advances configuration tabl
*
* @author Manfred Hantschel
*/
public class JettyLaunchDependencyEntryList
{
private final Map<String, JettyLaunchDependencyEntry> entries;
private final SelectionListener listener;
private int configHash;
public JettyLaunchDependencyEntryList(SelectionListener listener)
{
super();
entries = new HashMap<String, JettyLaunchDependencyEntry>();
this.listener = listener;
}
/**
* @deprecated The regular expression based including/excluding mechanism was replaced by a generic id based one
* with 3.5.1.
*/
@Deprecated
public String createExcludedLibs()
{
StringBuilder result = new StringBuilder();
for (JettyLaunchDependencyEntry entry : getSortedList())
{
if (entry.getType() == Type.ALWAYS_EXCLUDED)
{
if (result.length() > 0)
{
result.append(", "); //$NON-NLS-1$
}
result.append(entry.createMatcher());
}
}
return result.toString();
}
/**
* @deprecated The regular expression based including/excluding mechanism was replaced by a generic id based one
* with 3.5.1.
*/
@Deprecated
public String createIncludedLibs()
{
StringBuilder result = new StringBuilder();
for (JettyLaunchDependencyEntry entry : getSortedList())
{
if (entry.getType() == Type.ALWAYS_INCLUDED)
{
if (result.length() > 0)
{
result.append(", "); //$NON-NLS-1$
}
result.append(entry.createMatcher());
}
}
return result.toString();
}
/**
* Creates a collection of excluded generic ids for storing in the configuration
*
* @return a collection of excluded generic ids
*/
public Collection<String> createExcludedGenericIds()
{
Collection<String> result = new HashSet<String>();
for (JettyLaunchDependencyEntry entry : getSortedList())
{
if (entry.getType() == Type.ALWAYS_EXCLUDED)
{
result.add(entry.getGenericId());
}
}
return result;
}
/**
* Creates a collection of included generic ids for storing in the configuration
*
* @return a collection of included generic ids
*/
public Collection<String> createIncludedGenericIds()
{
Collection<String> result = new HashSet<String>();
for (JettyLaunchDependencyEntry entry : getSortedList())
{
if (entry.getType() == Type.ALWAYS_INCLUDED)
{
result.add(entry.getGenericId());
}
}
return result;
}
/**
* @deprecated The regular expression based global mechanism was replaced by a generic id based one with 3.5.1.
*/
@Deprecated
public String createGlobalLibs()
{
StringBuilder result = new StringBuilder();
for (JettyLaunchDependencyEntry entry : getSortedList())
{
if (entry.isGlobal())
{
if (result.length() > 0)
{
result.append(", "); //$NON-NLS-1$
}
result.append(entry.createMatcher());
}
}
return result.toString();
}
/**
* Creates a collection of global generic ids for storing in the configuration
*
* @return a collection of global generic ids
*/
public Collection<String> createGlobalGenericIds()
{
Collection<String> result = new HashSet<String>();
for (JettyLaunchDependencyEntry entry : getSortedList())
{
if (entry.isGlobal())
{
result.add(entry.getGenericId());
}
}
return result;
}
/**
* Updates/fills the table if necessary
*
* @param adapter the configuration adapter
* @param table the table
* @param dependencies the list of dependencies
* @param includedClasspathEntries all included classpath entries (by default)
* @param globalClasspathEntries all classpath entries marked as being global
* @param updateType true to update the type of the entry
* @param filterPattern the filter pattern for the entries
* @return true if updated
* @throws CoreException on occasion
*/
public boolean update(JettyLaunchConfigurationAdapter adapter, final Table table,
Collection<Dependency> dependencies, Collection<Dependency> includedClasspathEntries,
Collection<Dependency> globalClasspathEntries, boolean updateType, String filterPattern) throws CoreException
{
if (configHash != adapter.getConfiguration().hashCode())
{
clear(table);
configHash = adapter.getConfiguration().hashCode();
}
boolean updated = false;
List<RegularMatcher> excludedLibs = null;
List<RegularMatcher> includedLibs = null;
Set<String> excludedGenericIds = new HashSet<String>();
Set<String> includedGenericIds = new HashSet<String>();
boolean genericIdsSupported = adapter.isGenericIdsSupported();
if (genericIdsSupported)
{
excludedGenericIds.addAll(adapter.getExcludedGenericIds());
includedGenericIds.addAll(adapter.getIncludedGenericIds());
}
else
{
excludedLibs = deprecatedGetExcludedLibs(adapter);
includedLibs = deprecatedGetIncludedLibs(adapter);
}
// mark all as obsolete, will be reactivated later
setObsolete(true);
// create a set of all really included entries
Collection<String> includedEntries = JettyPluginUtils.toLocationCollectionFromScoped(includedClasspathEntries);
// create a set of all global entries
Collection<String> globalEntries = JettyPluginUtils.toLocationCollectionFromScoped(globalClasspathEntries);
// run through all entries and update the state of the entry
for (Dependency dependency : dependencies)
{
String location = JettyPluginUtils.toLocation(dependency);
if (location != null)
{
JettyLaunchDependencyEntry entry = entries.get(location);
if (entry == null)
{
Kind kind;
if (dependency.isProjectDependent())
{
kind = Kind.PROJECT;
}
else
{
switch (dependency.getRuntimeClasspathEntry().getType())
{
case IRuntimeClasspathEntry.PROJECT:
kind = Kind.PROJECT;
break;
case IRuntimeClasspathEntry.ARCHIVE:
case IRuntimeClasspathEntry.CONTAINER:
kind = Kind.JAR;
break;
case IRuntimeClasspathEntry.VARIABLE:
default:
kind = Kind.OTHER;
break;
}
}
entry =
new JettyLaunchDependencyEntry(dependency.getGenericId(), JettyPluginUtils.getPath(location),
JettyPluginUtils.getName(location), kind, Type.DEFAULT);
entries.put(location, entry);
}
if (updateType)
{
if (genericIdsSupported)
{
if (excludedGenericIds.contains(entry.getGenericId()))
{
entry.setType(Type.ALWAYS_EXCLUDED);
}
if (includedGenericIds.contains(entry.getGenericId()))
{
entry.setType(Type.ALWAYS_INCLUDED);
}
}
else
{
if (matches(excludedLibs, location))
{
entry.setType(Type.ALWAYS_EXCLUDED);
}
if (matches(includedLibs, location))
{
entry.setType(Type.ALWAYS_INCLUDED);
}
}
entry.setGlobal(globalEntries.contains(location));
}
entry.setIncluded(includedEntries.contains(location));
entry.setScope(dependency.getScope().key());
entry.setObsolete(false);
}
}
// sort the entries and update the table if entry has changed
final List<JettyLaunchDependencyEntry> list = getSortedList();
int index = 0;
for (JettyLaunchDependencyEntry entry : list)
{
if ((!entry.isObsolete()) && (entry.matches(filterPattern)))
{
updated |= entry.initItem(table, listener, index);
index += 1;
}
else
{
entry.deleteItem(table);
updated |= true;
}
}
table.getDisplay().syncExec(new Runnable()
{
public void run()
{
for (JettyLaunchDependencyEntry entry : list)
{
entry.updateItem(table);
}
}
});
// remove those, that were not hit from the local table
Iterator<Map.Entry<String, JettyLaunchDependencyEntry>> iterator = entries.entrySet().iterator();
while (iterator.hasNext())
{
if (iterator.next().getValue().isObsolete())
{
iterator.remove();
}
}
return updated;
}
@SuppressWarnings("deprecation")
private List<RegularMatcher> deprecatedGetIncludedLibs(JettyLaunchConfigurationAdapter adapter)
throws CoreException
{
return createRegularMatcherList(adapter.getIncludedLibs());
}
@SuppressWarnings("deprecation")
private List<RegularMatcher> deprecatedGetExcludedLibs(JettyLaunchConfigurationAdapter adapter)
throws CoreException
{
return createRegularMatcherList(adapter.getExcludedLibs());
}
/**
* Returns all entries (sorted)
*
* @return all entries
*/
private List<JettyLaunchDependencyEntry> getSortedList()
{
List<JettyLaunchDependencyEntry> list = new ArrayList<JettyLaunchDependencyEntry>(entries.values());
Collections.sort(list);
return list;
}
private List<RegularMatcher> createRegularMatcherList(String libs)
{
List<RegularMatcher> result = new ArrayList<RegularMatcher>();
if ((libs != null) && (libs.trim().length() > 0))
{
for (String lib : JettyPluginUtils.fromCommaSeparatedString(libs))
{
result.add(new RegularMatcher(lib.trim()));
}
}
return result;
}
/**
* @deprecated replaced by the generic id method
*/
@Deprecated
private boolean matches(List<RegularMatcher> list, String location)
{
if (list == null)
{
return false;
}
for (RegularMatcher matcher : list)
{
if (matcher.matches(location))
{
return true;
}
}
return false;
}
/**
* Set all entries as being obsolete and should get deleted on the next update
*
* @param obsolete
*/
private void setObsolete(boolean obsolete)
{
for (JettyLaunchDependencyEntry entry : entries.values())
{
entry.setObsolete(obsolete);
}
}
/**
* Resets all include/exclude definitions of all entries
*/
public void reset()
{
for (JettyLaunchDependencyEntry entry : entries.values())
{
entry.setType(Type.DEFAULT);
}
}
/**
* Clears the table
*
* @param table the table
*/
public void clear(Table table)
{
for (JettyLaunchDependencyEntry entry : entries.values())
{
entry.deleteItem(table);
}
entries.clear();
}
}