You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@felix.apache.org by ri...@apache.org on 2009/07/13 15:26:06 UTC

svn commit: r793581 [13/23] - in /felix/trunk/sigil: ./ bld-ivy/ bld-ivy/example/ bld-ivy/example/dependence/ bld-ivy/example/dependence/dependee/ bld-ivy/example/dependence/dependee/src/ bld-ivy/example/dependence/dependee/src/standalone/ bld-ivy/exam...

Added: felix/trunk/sigil/org.cauldron.sigil.core/src/org/cauldron/sigil/internal/model/repository/RepositoryConfiguration.java
URL: http://svn.apache.org/viewvc/felix/trunk/sigil/org.cauldron.sigil.core/src/org/cauldron/sigil/internal/model/repository/RepositoryConfiguration.java?rev=793581&view=auto
==============================================================================
--- felix/trunk/sigil/org.cauldron.sigil.core/src/org/cauldron/sigil/internal/model/repository/RepositoryConfiguration.java (added)
+++ felix/trunk/sigil/org.cauldron.sigil.core/src/org/cauldron/sigil/internal/model/repository/RepositoryConfiguration.java Mon Jul 13 13:25:46 2009
@@ -0,0 +1,395 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.cauldron.sigil.internal.model.repository;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
+
+import org.cauldron.sigil.SigilCore;
+import org.cauldron.sigil.model.repository.IRepositoryConfiguration;
+import org.cauldron.sigil.model.repository.IRepositoryModel;
+import org.cauldron.sigil.model.repository.IRepositorySet;
+import org.cauldron.sigil.model.repository.IRepositoryType;
+import org.cauldron.sigil.model.repository.RepositorySet;
+import org.cauldron.sigil.preferences.PrefsUtils;
+import org.cauldron.sigil.repository.IBundleRepository;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IConfigurationElement;
+import org.eclipse.core.runtime.IExtension;
+import org.eclipse.core.runtime.IExtensionPoint;
+import org.eclipse.core.runtime.IExtensionRegistry;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.jface.preference.PreferenceStore;
+import org.eclipse.swt.graphics.Image;
+import org.osgi.framework.Bundle;
+
+public class RepositoryConfiguration implements IRepositoryConfiguration {
+	
+	private static final String REPOSITORY = "repository.";
+	private static final String REPOSITORY_SET = REPOSITORY + "set.";
+	private static final String REPOSITORY_SETS = REPOSITORY + "sets";
+	private static final String REPOSITORY_TIMESTAMP = REPOSITORY + "timestamp";
+	private static final String INSTANCES = ".instances";
+	private static final String NAME = ".name";
+	private static final String LOC = ".loc";
+	private static final String TIMESTAMP = ".timestamp";
+	
+	public static final String REPOSITORY_DEFAULT_SET = REPOSITORY + "default.set";
+
+	/* (non-Javadoc)
+	 * @see org.cauldron.sigil.repository.management.IRepositoryManagement#loadRepositories()
+	 */
+	public List<IRepositoryModel> loadRepositories() {
+		IPreferenceStore prefs = SigilCore.getDefault().getPreferenceStore();
+		
+		ArrayList<IRepositoryModel> repositories = new ArrayList<IRepositoryModel>();
+
+		for ( RepositoryType type : loadRepositoryTypes() ) {
+			String typeID = type.getId();
+			
+			if ( type.isDynamic() ) {	
+				String instances = prefs.getString( REPOSITORY + typeID + INSTANCES );
+				if ( instances.trim().length() > 0 ) {
+					for( String instance : instances.split(",") ) {
+						String key = REPOSITORY + typeID + "." + instance;
+						repositories.add( loadRepository(instance, key, type, prefs) );
+					}
+				}
+			}
+			else {
+				String key = REPOSITORY + typeID;
+				repositories.add( loadRepository(typeID, key, type, prefs) );
+			}
+			
+		}
+		
+		return repositories;
+	}
+	
+	public IRepositoryModel findRepository(String id) {
+		for (IRepositoryModel model : loadRepositories()) {
+			if ( model.getId().equals( id ) ) {
+				return model;
+			}
+		}
+		return null;
+	}
+	
+	/* (non-Javadoc)
+	 * @see org.cauldron.sigil.repository.management.IRepositoryManagement#saveRepositories(java.util.List)
+	 */
+	public void saveRepositories(List<IRepositoryModel> repositories) throws CoreException {
+		IPreferenceStore prefs = getPreferences();
+		
+		HashMap<IRepositoryType, List<IRepositoryModel>> mapped = new HashMap<IRepositoryType, List<IRepositoryModel>>(repositories.size());
+		
+		saveRepositoryPreferences(repositories, mapped);
+		createNewEntries(mapped, prefs);
+		deleteOldEntries(repositories,prefs);
+		// time stamp is used as a signal to the manager
+		// to update its view of the stored repositories
+		timeStamp(prefs);
+	}
+
+	/* (non-Javadoc)
+	 * @see org.cauldron.sigil.repository.management.IRepositoryManagement#loadRepositoryTypes()
+	 */
+	public List<RepositoryType> loadRepositoryTypes() {
+		List<RepositoryType> repositories = new ArrayList<RepositoryType>();
+		
+		IExtensionRegistry registry = Platform.getExtensionRegistry();
+		
+		IExtensionPoint p = registry.getExtensionPoint(SigilCore.REPOSITORY_PROVIDER_EXTENSION_POINT_ID);
+		
+		for ( IExtension e : p.getExtensions() ) {
+			for ( IConfigurationElement c : e.getConfigurationElements() ) {
+				String id = c.getAttribute("id");
+				String type = c.getAttribute("type");
+				boolean dynamic = Boolean.valueOf( c.getAttribute("dynamic") ); 
+				String icon = c.getAttribute("icon");
+				Image image = (icon == null || icon.trim().length() == 0) ? null : loadImage(e, icon);
+				repositories.add( new RepositoryType(id, type, dynamic, image ) );
+			}
+		}
+		
+		return repositories;
+	}
+
+	/* (non-Javadoc)
+	 * @see org.cauldron.sigil.repository.management.IRepositoryManagement#newRepositoryElement(org.cauldron.sigil.repository.management.RepositoryType)
+	 */
+	public IRepositoryModel newRepositoryElement(IRepositoryType type) {
+		String id = UUID.randomUUID().toString();
+		PreferenceStore prefs = new PreferenceStore();
+		RepositoryModel element = new RepositoryModel(id, "", type, prefs);
+		prefs.setFilename(makeFileName(element));
+		prefs.setValue("id", id);
+		return element;
+	}
+	
+	public IRepositorySet getDefaultRepositorySet() {
+		//int level = findLevel( key + LEVEL, type, prefs );
+		ArrayList<IRepositoryModel> reps = new ArrayList<IRepositoryModel>();
+		for ( String s : PrefsUtils.stringToArray(getPreferences().getString( REPOSITORY_DEFAULT_SET)) ) {
+			reps.add( findRepository(s) );
+		}
+		return new RepositorySet( reps );
+	}
+
+	public IRepositorySet getRepositorySet(String name) {
+		String key = REPOSITORY_SET + name;
+		if ( getPreferences().contains(key) ) {
+			ArrayList<IRepositoryModel> reps = new ArrayList<IRepositoryModel>();
+			for ( String s : PrefsUtils.stringToArray(getPreferences().getString( key )) ) {
+				reps.add( findRepository(s) );
+			}
+			return new RepositorySet( reps );
+		}
+		else {
+			return null;
+		}
+	}
+
+	public Map<String, IRepositorySet> loadRepositorySets() {
+		IPreferenceStore store = getPreferences();
+		
+		HashMap<String, IRepositorySet> sets = new HashMap<String, IRepositorySet>();
+		
+		for ( String name : PrefsUtils.stringToArray(store.getString(REPOSITORY_SETS))) {
+			String key = REPOSITORY_SET + name;
+			ArrayList<IRepositoryModel> reps = new ArrayList<IRepositoryModel>();
+			for ( String s : PrefsUtils.stringToArray(getPreferences().getString( key )) ) {
+				reps.add( findRepository(s) );
+			}
+			sets.put( name, new RepositorySet( reps ) );
+		}
+		
+		return sets;
+	}
+
+	public void saveRepositorySets(Map<String, IRepositorySet> sets) {
+		IPreferenceStore store = getPreferences();
+
+		ArrayList<String> names = new ArrayList<String>();
+		
+		for ( Map.Entry<String, IRepositorySet> set : sets.entrySet() ) {
+			String name = set.getKey();
+			String key = REPOSITORY_SET + name;
+			ArrayList<String> ids = new ArrayList<String>();
+			for ( IRepositoryModel m : set.getValue().getRepositories() ) {
+				ids.add( m.getId() );
+			}
+			store.setValue(key, PrefsUtils.listToString(ids) );
+			names.add( name );
+		}
+		
+		for ( String name : PrefsUtils.stringToArray(store.getString(REPOSITORY_SETS))) {
+			if ( !names.contains(name) ) {
+				String key = REPOSITORY_SET + name;
+				store.setToDefault(key);
+			}
+		}
+		
+		store.setValue(REPOSITORY_SETS, PrefsUtils.listToString(names) );
+		timeStamp(store);
+	}
+			
+	public void setDefaultRepositorySet(IRepositorySet defaultSet) {
+		ArrayList<String> ids = new ArrayList<String>();
+		for ( IRepositoryModel m : defaultSet.getRepositories() ) {
+			ids.add( m.getId() );
+		}
+		IPreferenceStore prefs = getPreferences();
+		prefs.setValue( REPOSITORY_DEFAULT_SET, PrefsUtils.listToString( ids ) );
+		timeStamp(prefs);
+	}
+
+	private void timeStamp(IPreferenceStore prefs) {
+		prefs.setValue( REPOSITORY_TIMESTAMP, System.currentTimeMillis() );
+	}
+
+	private IPreferenceStore getPreferences() {
+		return SigilCore.getDefault().getPreferenceStore();
+	}
+
+	private void deleteOldEntries(List<IRepositoryModel> repositories, IPreferenceStore prefs) {
+		for ( IRepositoryModel e : loadRepositories() ) {
+			if ( !repositories.contains(e) ) {
+				new File( makeFileName(e) ).delete();
+				String key = makeKey(e);
+				prefs.setToDefault( key + LOC );
+				prefs.setToDefault( key + NAME );
+			}
+		}
+		
+		for ( IRepositoryType type : loadRepositoryTypes() ) {
+			boolean found = false;
+			for ( IRepositoryModel e : repositories ) {
+				if ( e.getType().equals( type ) ) {
+					found = true;
+					break;
+				}
+			}
+			
+			if ( !found ) {
+				prefs.setToDefault( REPOSITORY + type.getId() + INSTANCES );
+			}
+		}
+	}
+
+	private static void createNewEntries(HashMap<IRepositoryType, List<IRepositoryModel>> mapped, IPreferenceStore prefs) {
+		for ( Map.Entry<IRepositoryType, List<IRepositoryModel>> entry : mapped.entrySet() ) {
+			IRepositoryType type = entry.getKey();
+			if ( type.isDynamic() ) {
+				StringBuffer buf = new StringBuffer();
+				
+				for ( IRepositoryModel element : entry.getValue() ) {
+					if ( buf.length() > 0 ) {
+						buf.append( "," );
+					}
+					buf.append( element.getId() );
+					saveRepository(element, prefs);
+				}
+				
+				prefs.setValue( REPOSITORY + type.getId() + INSTANCES, buf.toString() );
+			}
+			else {
+				IRepositoryModel element = entry.getValue().get(0);
+				saveRepository(element, prefs);
+			}
+		}
+	}
+
+	private static void saveRepositoryPreferences(List<IRepositoryModel> repositories,
+			HashMap<IRepositoryType, List<IRepositoryModel>> mapped) throws CoreException {
+		for( IRepositoryModel rep : repositories ) {
+			try {
+				createDir( makeFileName(rep));
+				rep.getPreferences().save();
+				List<IRepositoryModel> list = mapped.get( rep.getType() );
+				if ( list == null ) {
+					list = new ArrayList<IRepositoryModel>(1);
+					mapped.put( rep.getType(), list );
+				}
+				list.add( rep );
+			} catch (IOException e) {
+				throw SigilCore.newCoreException("Failed to save repository preferences", e);
+			}
+		}
+	}
+
+	private static void createDir(String fileName) {
+		File file = new File( fileName );
+		file.getParentFile().mkdirs();
+	}
+
+	private static void saveRepository(IRepositoryModel element, IPreferenceStore prefs) {
+		String key = makeKey(element);
+		prefs.setValue( key + LOC, makeFileName(element) );
+		if ( element.getType().isDynamic() ) {
+			prefs.setValue( key + NAME, element.getName() );
+		}
+		prefs.setValue( key + TIMESTAMP, now() );
+	}
+
+	private static long now() {
+		return System.currentTimeMillis();
+	}
+
+	private static String makeKey(IRepositoryModel element) {
+		IRepositoryType type = element.getType();
+		
+		String key = REPOSITORY + type.getId(); 
+		if ( type.isDynamic() )
+			key = key + "." + element.getId();
+		
+		return key;
+	}
+
+	private static String makeFileName(IRepositoryModel element) {
+		IPath path = SigilCore.getDefault().getStateLocation();
+		path = path.append( "repository" );
+		path = path.append( element.getType().getId() );
+		path = path.append( element.getId() );
+		return path.toOSString();
+	}
+
+	private static RepositoryModel loadRepository(String id, String key, RepositoryType type, IPreferenceStore prefs) {
+		String name = type.isDynamic() ? prefs.getString( key + NAME ) : type.getType();
+		
+		PreferenceStore repPrefs = new PreferenceStore();		
+		RepositoryModel element = new RepositoryModel( id, name, type, repPrefs );
+		
+		String loc = prefs.getString( key + LOC );
+		
+		if ( loc == null || loc.trim().length() == 0 ) {
+			loc = makeFileName(element);
+		}
+		
+		repPrefs.setFilename(loc);
+		
+		if ( new File( loc ).exists() ) {
+			try {
+				repPrefs.load();
+			} catch (IOException e) {
+				SigilCore.error("Failed to load properties for repository " + key, e );
+			}
+		}
+		
+		repPrefs.setValue( "id", id );
+		
+		return element;
+	}
+
+	@SuppressWarnings("unchecked")
+	private static Image loadImage(IExtension ext, String icon) {
+		int i = icon.lastIndexOf( "/" );
+		String path = i == -1 ? "/" : icon.substring(0, i);
+		String name = i == -1 ? icon : icon.substring(i+1);
+		
+		Bundle b = Platform.getBundle(ext.getContributor().getName());
+		
+		Enumeration<URL> en = b.findEntries(path, name, false);
+		Image image = null;
+		
+		if ( en.hasMoreElements() ) {
+			try {
+				image = SigilCore.loadImage(en.nextElement());
+			} catch (IOException e) {
+				SigilCore.error( "Failed to load image", e );
+			}
+		}
+		else {
+			SigilCore.error("No such image " + icon + " in bundle " + b.getSymbolicName() );
+		}
+		
+		return image;
+	}
+
+}

Added: felix/trunk/sigil/org.cauldron.sigil.core/src/org/cauldron/sigil/internal/model/repository/RepositoryModel.java
URL: http://svn.apache.org/viewvc/felix/trunk/sigil/org.cauldron.sigil.core/src/org/cauldron/sigil/internal/model/repository/RepositoryModel.java?rev=793581&view=auto
==============================================================================
--- felix/trunk/sigil/org.cauldron.sigil.core/src/org/cauldron/sigil/internal/model/repository/RepositoryModel.java (added)
+++ felix/trunk/sigil/org.cauldron.sigil.core/src/org/cauldron/sigil/internal/model/repository/RepositoryModel.java Mon Jul 13 13:25:46 2009
@@ -0,0 +1,96 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.cauldron.sigil.internal.model.repository;
+
+import org.cauldron.sigil.model.repository.IRepositoryModel;
+import org.cauldron.sigil.model.repository.IRepositoryType;
+import org.eclipse.jface.preference.PreferenceStore;
+
+public class RepositoryModel implements IRepositoryModel {
+	private String id;
+	
+	private String name;
+	
+	private IRepositoryType type;
+	
+	private PreferenceStore preferences;
+		
+	public RepositoryModel(String id, String name, IRepositoryType type, PreferenceStore preferences) {
+		this.id = id;
+		this.name = name;
+		this.type = type;
+		this.preferences = preferences;
+	}
+	
+	/* (non-Javadoc)
+	 * @see org.cauldron.sigil.ui.preferences.repository.IRepositoryModel#getPreferences()
+	 */
+	public PreferenceStore getPreferences() {
+		return preferences;
+	}
+
+	/* (non-Javadoc)
+	 * @see org.cauldron.sigil.ui.preferences.repository.IRepositoryModel#getType()
+	 */
+	public IRepositoryType getType() {
+		return type;
+	}
+
+	/* (non-Javadoc)
+	 * @see org.cauldron.sigil.ui.preferences.repository.IRepositoryModel#getId()
+	 */
+	public String getId() {
+		return id;
+	}
+
+	/* (non-Javadoc)
+	 * @see org.cauldron.sigil.ui.preferences.repository.IRepositoryModel#getName()
+	 */
+	public String getName() {
+		return name;
+	}
+	
+	/* (non-Javadoc)
+	 * @see org.cauldron.sigil.ui.wizard.repository.IRepositoryModel#setName(java.lang.String)
+	 */
+	public void setName(String name) {
+		this.name = name;
+	}
+
+	@Override
+	public boolean equals(Object obj) {
+		try {
+			RepositoryModel e = (RepositoryModel) obj;
+			return id.equals(e.id);
+		}
+		catch (ClassCastException e) {
+			return false;
+		}
+	}
+
+	@Override
+	public int hashCode() {
+		return id.hashCode();
+	}
+	
+	public String toString() {
+		return type.getId() + ":" + id + ":" + name;
+	}
+}
\ No newline at end of file

Added: felix/trunk/sigil/org.cauldron.sigil.core/src/org/cauldron/sigil/internal/model/repository/RepositoryType.java
URL: http://svn.apache.org/viewvc/felix/trunk/sigil/org.cauldron.sigil.core/src/org/cauldron/sigil/internal/model/repository/RepositoryType.java?rev=793581&view=auto
==============================================================================
--- felix/trunk/sigil/org.cauldron.sigil.core/src/org/cauldron/sigil/internal/model/repository/RepositoryType.java (added)
+++ felix/trunk/sigil/org.cauldron.sigil.core/src/org/cauldron/sigil/internal/model/repository/RepositoryType.java Mon Jul 13 13:25:46 2009
@@ -0,0 +1,87 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.cauldron.sigil.internal.model.repository;
+
+import org.cauldron.sigil.model.repository.IRepositoryType;
+import org.eclipse.swt.graphics.Image;
+
+public class RepositoryType implements IRepositoryType {
+	private String type;
+	private String id;
+	private Image icon;
+	private boolean dynamic;
+	
+	public RepositoryType(String id, String type, boolean dynamic,
+			Image icon) {
+		this.id = id;
+		this.type = type;
+		this.dynamic = dynamic;
+		this.icon = icon;
+	}
+
+	/* (non-Javadoc)
+	 * @see org.cauldron.sigil.ui.preferences.repository.IRepositoryType#getType()
+	 */
+	public String getType() {
+		return type;
+	}
+
+	/* (non-Javadoc)
+	 * @see org.cauldron.sigil.ui.preferences.repository.IRepositoryType#getId()
+	 */
+	public String getId() {
+		return id;
+	}
+
+	/* (non-Javadoc)
+	 * @see org.cauldron.sigil.ui.preferences.repository.IRepositoryType#getIcon()
+	 */
+	public Image getIcon() {
+		return icon;
+	}
+
+	/* (non-Javadoc)
+	 * @see org.cauldron.sigil.ui.preferences.repository.IRepositoryType#isDynamic()
+	 */
+	public boolean isDynamic() {
+		return dynamic;
+	}
+
+	@Override
+	public boolean equals(Object obj) {
+		try {
+			RepositoryType t = (RepositoryType) obj;
+			return t.id.equals( id );
+		}
+		catch (ClassCastException e) {
+			return false;
+		}
+	}
+
+	@Override
+	public int hashCode() {
+		return id.hashCode();
+	}
+
+	@Override
+	public String toString() {
+		return type;
+	}
+}

Added: felix/trunk/sigil/org.cauldron.sigil.core/src/org/cauldron/sigil/internal/repository/eclipse/GlobalRepositoryManager.java
URL: http://svn.apache.org/viewvc/felix/trunk/sigil/org.cauldron.sigil.core/src/org/cauldron/sigil/internal/repository/eclipse/GlobalRepositoryManager.java?rev=793581&view=auto
==============================================================================
--- felix/trunk/sigil/org.cauldron.sigil.core/src/org/cauldron/sigil/internal/repository/eclipse/GlobalRepositoryManager.java (added)
+++ felix/trunk/sigil/org.cauldron.sigil.core/src/org/cauldron/sigil/internal/repository/eclipse/GlobalRepositoryManager.java Mon Jul 13 13:25:46 2009
@@ -0,0 +1,42 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.cauldron.sigil.internal.repository.eclipse;
+
+import java.util.List;
+
+import org.cauldron.sigil.SigilCore;
+import org.cauldron.sigil.internal.repository.eclipse.SigilRepositoryManager;
+import org.cauldron.sigil.model.repository.IRepositoryModel;
+import org.cauldron.sigil.repository.IRepositoryManager;
+
+public class GlobalRepositoryManager extends SigilRepositoryManager implements
+		IRepositoryManager {
+
+	public GlobalRepositoryManager() {
+		super(null);
+	}
+
+	@Override
+	protected IRepositoryModel[] findRepositories() {
+		List<IRepositoryModel> repos = SigilCore.getRepositoryConfiguration().loadRepositories();
+		return repos.toArray( new IRepositoryModel[repos.size()]);
+	}
+
+}

Added: felix/trunk/sigil/org.cauldron.sigil.core/src/org/cauldron/sigil/internal/repository/eclipse/OSGiInstallRepository.java
URL: http://svn.apache.org/viewvc/felix/trunk/sigil/org.cauldron.sigil.core/src/org/cauldron/sigil/internal/repository/eclipse/OSGiInstallRepository.java?rev=793581&view=auto
==============================================================================
--- felix/trunk/sigil/org.cauldron.sigil.core/src/org/cauldron/sigil/internal/repository/eclipse/OSGiInstallRepository.java (added)
+++ felix/trunk/sigil/org.cauldron.sigil.core/src/org/cauldron/sigil/internal/repository/eclipse/OSGiInstallRepository.java Mon Jul 13 13:25:46 2009
@@ -0,0 +1,135 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.cauldron.sigil.internal.repository.eclipse;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.jar.JarFile;
+import java.util.jar.Manifest;
+
+import org.cauldron.bld.core.BldCore;
+import org.cauldron.sigil.SigilCore;
+import org.cauldron.sigil.install.IOSGiInstall;
+import org.cauldron.sigil.model.ModelElementFactory;
+import org.cauldron.sigil.model.ModelElementFactoryException;
+import org.cauldron.sigil.model.eclipse.ISigilBundle;
+import org.cauldron.sigil.model.osgi.IBundleModelElement;
+import org.cauldron.sigil.repository.AbstractBundleRepository;
+import org.cauldron.sigil.repository.IRepositoryVisitor;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.Path;
+
+public class OSGiInstallRepository extends AbstractBundleRepository {
+	
+	private Map<String,List<ISigilBundle>> bundles;
+	
+	public OSGiInstallRepository(String id) {
+		super(id);
+	}
+	
+	public void refresh() {
+		synchronized( this ) {
+			bundles = null;
+		}
+		
+		notifyChange();		
+	}
+	
+	@Override
+	public void accept(IRepositoryVisitor visitor, int options) {
+		IOSGiInstall install = SigilCore.getInstallManager().getDefaultInstall();
+
+		if ( install != null ) {
+			List<ISigilBundle> found = null;
+
+			synchronized( this ) {
+				found = bundles == null ? null : bundles.get( install.getId() );
+			}
+
+			if ( found == null )  {
+				found = new ArrayList<ISigilBundle>();
+				IPath source = install.getType().getSourceLocation();
+				
+				for ( IPath p : install.getType().getDefaultBundleLocations() ) {
+					loadBundle( p, found, source );
+				}
+
+				synchronized( this ) {
+					bundles = new HashMap<String, List<ISigilBundle>>();
+					bundles.put( install.getId(), found );
+				}
+			}
+
+			for ( ISigilBundle b : found ) {
+				if ( !visitor.visit(b) ) {
+					break;
+				}
+			}
+		}
+	}
+
+	private void loadBundle(IPath p, List<ISigilBundle> bundles, IPath source) {
+		File f = p.toFile();
+		JarFile jar = null;
+		try {
+			jar = new JarFile(f);
+			ISigilBundle bundle = buildBundle(jar.getManifest(), f );
+			if ( bundle != null ) {
+				bundle.setLocation(p);
+				bundle.setSourcePathLocation( source );
+				bundle.setSourceRootPath( new Path( "src" ) );
+				bundles.add( bundle );
+			}
+		} catch (IOException e) {
+			BldCore.error( "Failed to read jar file " + f, e );
+		} catch (ModelElementFactoryException e) {
+			BldCore.error( "Failed to build bundle " + f , e );
+		} catch (RuntimeException e) {
+			BldCore.error( "Failed to build bundle " + f , e );
+		}
+		finally {
+			if ( jar != null ) {
+				try {
+					jar.close();
+				} catch (IOException e) {
+					BldCore.error( "Failed to close jar file", e );
+				}
+			}
+		}
+	}
+
+	private ISigilBundle buildBundle(Manifest manifest, File f) {
+		IBundleModelElement info = buildBundleModelElement( manifest );
+
+		ISigilBundle bundle = null;
+
+		if ( info != null ) {
+			bundle = ModelElementFactory.getInstance().newModelElement( ISigilBundle.class );
+			bundle.addChild(info);
+			bundle.setLocation( new Path( f.getAbsolutePath() ) );
+		}
+
+		return bundle;
+	}
+}

Added: felix/trunk/sigil/org.cauldron.sigil.core/src/org/cauldron/sigil/internal/repository/eclipse/OSGiInstallRepositoryProvider.java
URL: http://svn.apache.org/viewvc/felix/trunk/sigil/org.cauldron.sigil.core/src/org/cauldron/sigil/internal/repository/eclipse/OSGiInstallRepositoryProvider.java?rev=793581&view=auto
==============================================================================
--- felix/trunk/sigil/org.cauldron.sigil.core/src/org/cauldron/sigil/internal/repository/eclipse/OSGiInstallRepositoryProvider.java (added)
+++ felix/trunk/sigil/org.cauldron.sigil.core/src/org/cauldron/sigil/internal/repository/eclipse/OSGiInstallRepositoryProvider.java Mon Jul 13 13:25:46 2009
@@ -0,0 +1,31 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.cauldron.sigil.internal.repository.eclipse;
+
+import java.util.Properties;
+
+import org.cauldron.sigil.repository.IBundleRepository;
+import org.cauldron.sigil.repository.IRepositoryProvider;
+
+public class OSGiInstallRepositoryProvider implements IRepositoryProvider {
+	public IBundleRepository createRepository(String id, Properties preferences) {
+		return new OSGiInstallRepository(id);
+	}
+}

Added: felix/trunk/sigil/org.cauldron.sigil.core/src/org/cauldron/sigil/internal/repository/eclipse/SigilRepositoryManager.java
URL: http://svn.apache.org/viewvc/felix/trunk/sigil/org.cauldron.sigil.core/src/org/cauldron/sigil/internal/repository/eclipse/SigilRepositoryManager.java?rev=793581&view=auto
==============================================================================
--- felix/trunk/sigil/org.cauldron.sigil.core/src/org/cauldron/sigil/internal/repository/eclipse/SigilRepositoryManager.java (added)
+++ felix/trunk/sigil/org.cauldron.sigil.core/src/org/cauldron/sigil/internal/repository/eclipse/SigilRepositoryManager.java Mon Jul 13 13:25:46 2009
@@ -0,0 +1,192 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.cauldron.sigil.internal.repository.eclipse;
+
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Properties;
+
+import org.cauldron.sigil.SigilCore;
+import org.cauldron.sigil.model.repository.IRepositoryModel;
+import org.cauldron.sigil.model.repository.IRepositorySet;
+import org.cauldron.sigil.model.repository.IRepositoryType;
+import org.cauldron.sigil.repository.AbstractRepositoryManager;
+import org.cauldron.sigil.repository.IBundleRepository;
+import org.cauldron.sigil.repository.IRepositoryManager;
+import org.cauldron.sigil.repository.IRepositoryProvider;
+import org.cauldron.sigil.repository.RepositoryException;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IConfigurationElement;
+import org.eclipse.core.runtime.IExtension;
+import org.eclipse.core.runtime.IExtensionPoint;
+import org.eclipse.core.runtime.IExtensionRegistry;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.jface.util.IPropertyChangeListener;
+import org.eclipse.jface.util.PropertyChangeEvent;
+
+public class SigilRepositoryManager extends AbstractRepositoryManager implements IRepositoryManager, IPropertyChangeListener {
+	
+	private final String repositorySet;
+	
+	private HashMap<String, RepositoryCache> cachedRepositories = new HashMap<String, RepositoryCache>();
+	
+	class RepositoryCache {
+		private final Properties pref;
+		private final IBundleRepository repo;
+
+		RepositoryCache(Properties pref, IBundleRepository repo) {
+			this.pref = pref;
+			this.repo = repo;
+		}
+	}
+	
+	public SigilRepositoryManager(String repositorySet) {
+		this.repositorySet = repositorySet;
+	}
+	
+	@Override
+	public void initialise() {
+		super.initialise();
+		SigilCore.getDefault().getPreferenceStore().addPropertyChangeListener(this);
+	}
+	
+	public void destroy() {
+		IPreferenceStore prefs = SigilCore.getDefault().getPreferenceStore();
+		if ( prefs != null ) {
+			prefs.removePropertyChangeListener(this);
+		}
+	}
+		
+	@Override
+	protected void loadRepositories() {
+		IPreferenceStore prefs = SigilCore.getDefault().getPreferenceStore();
+		
+		ArrayList<IBundleRepository> repos = new ArrayList<IBundleRepository>();
+		HashSet<String> ids = new HashSet<String>();
+		
+		for ( IRepositoryModel repo : findRepositories() ) {
+			try {
+				IRepositoryProvider provider = findProvider( repo.getType() );
+				String id = repo.getId();
+				IBundleRepository repoImpl = null;
+				if ( repo.getType().isDynamic() ) {
+					String instance = "repository." + repo.getType().getId() + "." + id; 
+					String loc = prefs.getString( instance + ".loc" );
+					Properties pref = loadPreferences(loc);
+					repoImpl = loadRepository(id, pref, provider);
+				}
+				else {
+					repoImpl = loadRepository(id, null, provider);
+				}
+				
+				repos.add( repoImpl );
+				ids.add( id );
+			} catch (Exception e) {
+				SigilCore.error( "Failed to load repository for " + repo, e);
+			}
+		}
+
+		setRepositories(repos.toArray( new IBundleRepository[repos.size()] ) );
+		
+		for ( Iterator<String> i = cachedRepositories.keySet().iterator(); i.hasNext(); ) {
+			if ( !ids.contains(i.next()) ) {
+				i.remove();
+			}
+		}
+	}
+
+	private IRepositoryProvider findProvider(IRepositoryType repositoryType) throws CoreException {
+		String id = repositoryType.getId();
+		
+		IExtensionRegistry registry = Platform.getExtensionRegistry();
+		IExtensionPoint p = registry.getExtensionPoint(SigilCore.REPOSITORY_PROVIDER_EXTENSION_POINT_ID);
+		
+		for ( IExtension e : p.getExtensions() ) {
+			for ( IConfigurationElement c : e.getConfigurationElements() ) {
+				if ( id.equals( c.getAttribute("id") ) ) {
+					IRepositoryProvider provider = (IRepositoryProvider) c.createExecutableExtension("class");
+					return provider;
+				}
+			}
+		}
+
+		return null;
+	}
+
+	protected IRepositoryModel[] findRepositories() {
+		if ( repositorySet == null ) {
+			return SigilCore.getRepositoryConfiguration().getDefaultRepositorySet().getRepositories();
+		}
+		else {
+			IRepositorySet set = SigilCore.getRepositoryConfiguration().getRepositorySet(repositorySet);
+			return set.getRepositories();
+		}	
+	}
+
+	private IBundleRepository loadRepository(String id, Properties pref, IRepositoryProvider provider) throws RepositoryException {
+		try {
+			if ( pref == null ) {
+				pref = new Properties();
+			}
+
+			RepositoryCache cache = cachedRepositories.get(id);
+			
+			if ( cache == null || !cache.pref.equals(pref) ) {
+				IBundleRepository repo = provider.createRepository(id, pref);
+				cache = new RepositoryCache(pref, repo);
+				cachedRepositories.put( id, cache );
+			}
+			
+			return cache.repo;
+		} catch (RuntimeException e) {
+			throw new RepositoryException( "Failed to build repositories", e);
+		}		
+	}
+
+	private Properties loadPreferences(String loc) throws FileNotFoundException, IOException {
+		FileInputStream in = null;
+		try {
+			Properties pref = new Properties();
+			pref.load(new FileInputStream(loc));
+			return pref;
+		}
+		finally {
+			if ( in != null ) {
+				try {
+					in.close();
+				} catch (IOException e) {
+					SigilCore.error( "Failed to close file", e );
+				}
+			}
+		}
+	}
+	
+	public void propertyChange(PropertyChangeEvent event) {
+		if ( event.getProperty().equals( "repository.timestamp" ) ) {
+			loadRepositories();
+		}
+	}	
+}

Added: felix/trunk/sigil/org.cauldron.sigil.core/src/org/cauldron/sigil/internal/repository/eclipse/WorkspaceRepository.java
URL: http://svn.apache.org/viewvc/felix/trunk/sigil/org.cauldron.sigil.core/src/org/cauldron/sigil/internal/repository/eclipse/WorkspaceRepository.java?rev=793581&view=auto
==============================================================================
--- felix/trunk/sigil/org.cauldron.sigil.core/src/org/cauldron/sigil/internal/repository/eclipse/WorkspaceRepository.java (added)
+++ felix/trunk/sigil/org.cauldron.sigil.core/src/org/cauldron/sigil/internal/repository/eclipse/WorkspaceRepository.java Mon Jul 13 13:25:46 2009
@@ -0,0 +1,126 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.cauldron.sigil.internal.repository.eclipse;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.cauldron.sigil.SigilCore;
+import org.cauldron.sigil.model.eclipse.ISigilBundle;
+import org.cauldron.sigil.model.project.ISigilProjectModel;
+import org.cauldron.sigil.repository.AbstractBundleRepository;
+import org.cauldron.sigil.repository.IRepositoryVisitor;
+import org.eclipse.core.resources.IProject;
+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.IWorkspaceRoot;
+import org.eclipse.core.runtime.CoreException;
+
+public class WorkspaceRepository extends AbstractBundleRepository implements IResourceChangeListener {
+	
+	private static final int UPDATE_MASK = IResourceDelta.CONTENT | IResourceDelta.DESCRIPTION | IResourceDelta.OPEN;
+	private ISigilBundle[] bundles;
+	
+	public WorkspaceRepository(String id) {
+		super(id);
+	}
+
+	@Override
+	public void accept(IRepositoryVisitor visitor, int options) {
+		synchronized( this ) {
+			if ( bundles == null ) {
+				List<ISigilProjectModel> models = SigilCore.getRoot().getProjects();
+				ArrayList<ISigilBundle> tmp = new ArrayList<ISigilBundle>(models.size());
+				for ( ISigilProjectModel n : models ) {
+					ISigilBundle b = n.getBundle();
+					tmp.add(b);
+				}
+				bundles = tmp.toArray( new ISigilBundle[tmp.size()] );
+			}
+		}
+		
+		for ( ISigilBundle b : bundles ) {
+			visitor.visit(b);
+		}
+	}
+	
+	public void refresh() {
+		synchronized(this) {
+			bundles = null;
+		}
+	}
+	
+	@Override
+	protected void notifyChange() {
+		refresh();
+		super.notifyChange();
+	}
+
+	public void resourceChanged(IResourceChangeEvent event) {
+		try {
+			event.getDelta().accept( new IResourceDeltaVisitor() {
+				public boolean visit(IResourceDelta delta) throws CoreException {
+					boolean result;
+					
+					IResource resource = delta.getResource();
+					if(resource instanceof IWorkspaceRoot) {
+						result = true;
+					} else if(resource instanceof IProject) {
+						IProject project = (IProject) resource;
+						if ( SigilCore.isSigilProject(project) ) {
+							switch (delta.getKind()) {
+							case IResourceDelta.CHANGED: 
+								if ( (delta.getFlags() & UPDATE_MASK) == 0 ) {
+									break;
+								}
+								// else 
+								// fall through on purpose
+							case IResourceDelta.ADDED: // fall through on purpose
+							case IResourceDelta.REMOVED: // fall through on purpose
+								notifyChange();
+								break;
+							}
+							result = true;
+						} else {
+							result = false;
+						}
+					} else if(resource.getName().equals(SigilCore.SIGIL_PROJECT_FILE)) {
+						switch(delta.getKind()) {
+						case IResourceDelta.CHANGED:
+						case IResourceDelta.ADDED:
+						case IResourceDelta.REMOVED:
+							notifyChange();
+						}
+						result = false;
+					} else {
+						result = false;
+					}
+ 					return result;
+				}
+			});
+		} catch (CoreException e) {
+			SigilCore.error( "Workspace repository update failed", e ); 
+		}
+	}
+
+}

Added: felix/trunk/sigil/org.cauldron.sigil.core/src/org/cauldron/sigil/internal/repository/eclipse/WorkspaceRepositoryProvider.java
URL: http://svn.apache.org/viewvc/felix/trunk/sigil/org.cauldron.sigil.core/src/org/cauldron/sigil/internal/repository/eclipse/WorkspaceRepositoryProvider.java?rev=793581&view=auto
==============================================================================
--- felix/trunk/sigil/org.cauldron.sigil.core/src/org/cauldron/sigil/internal/repository/eclipse/WorkspaceRepositoryProvider.java (added)
+++ felix/trunk/sigil/org.cauldron.sigil.core/src/org/cauldron/sigil/internal/repository/eclipse/WorkspaceRepositoryProvider.java Mon Jul 13 13:25:46 2009
@@ -0,0 +1,43 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.cauldron.sigil.internal.repository.eclipse;
+
+import java.util.Properties;
+
+import org.cauldron.sigil.repository.IBundleRepository;
+import org.cauldron.sigil.repository.IRepositoryProvider;
+import org.eclipse.core.resources.IResourceChangeEvent;
+import org.eclipse.core.resources.ResourcesPlugin;
+
+public class WorkspaceRepositoryProvider implements IRepositoryProvider {
+	private static WorkspaceRepository repository;
+	
+	public static WorkspaceRepository getWorkspaceRepository() {
+		return repository;	
+	}
+	
+	public IBundleRepository createRepository(String id, Properties preferences) {
+		if ( repository == null ) {
+			repository = new WorkspaceRepository(id);
+			ResourcesPlugin.getWorkspace().addResourceChangeListener(repository, IResourceChangeEvent.POST_CHANGE);
+		}
+		return repository;
+	}
+}

Added: felix/trunk/sigil/org.cauldron.sigil.core/src/org/cauldron/sigil/job/ResolveProjectsJob.java
URL: http://svn.apache.org/viewvc/felix/trunk/sigil/org.cauldron.sigil.core/src/org/cauldron/sigil/job/ResolveProjectsJob.java?rev=793581&view=auto
==============================================================================
--- felix/trunk/sigil/org.cauldron.sigil.core/src/org/cauldron/sigil/job/ResolveProjectsJob.java (added)
+++ felix/trunk/sigil/org.cauldron.sigil.core/src/org/cauldron/sigil/job/ResolveProjectsJob.java Mon Jul 13 13:25:46 2009
@@ -0,0 +1,145 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.cauldron.sigil.job;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Set;
+
+import org.cauldron.sigil.SigilCore;
+import org.cauldron.sigil.model.osgi.IPackageImport;
+import org.cauldron.sigil.model.osgi.IRequiredBundle;
+import org.cauldron.sigil.model.project.ISigilProjectModel;
+import org.cauldron.sigil.repository.IBundleResolver;
+import org.cauldron.sigil.repository.IRepositoryManager;
+import org.cauldron.sigil.repository.IResolution;
+import org.cauldron.sigil.repository.ResolutionConfig;
+import org.cauldron.sigil.repository.ResolutionException;
+import org.cauldron.sigil.repository.ResolutionMonitorAdapter;
+import org.eclipse.core.resources.IMarker;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.IWorkspace;
+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.MultiStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.core.runtime.jobs.Job;
+
+public class ResolveProjectsJob extends Job {
+	
+	private final IWorkspace workspace;
+	private final IProject project;
+	
+	public ResolveProjectsJob(IWorkspace workspace) {
+		super("Resolving Sigil projects");
+		this.workspace = workspace;
+		this.project = null;
+		setRule(ResourcesPlugin.getWorkspace().getRoot());
+	}
+	
+	public ResolveProjectsJob(IProject project) {
+		super("Resolving Sigil project");
+		this.workspace = null;
+		this.project = project;
+		setRule(project.getFile(SigilCore.SIGIL_PROJECT_FILE));
+	}
+	
+	@Override
+	protected IStatus run(IProgressMonitor monitor) {
+		MultiStatus status = new MultiStatus(SigilCore.PLUGIN_ID, 0, "Error resolving Sigil projects", null);
+		
+		Collection<ISigilProjectModel> sigilProjects = null;
+		
+		if(workspace != null) {
+			sigilProjects = SigilCore.getRoot().getProjects();
+		} else if(project != null) {
+			try {
+				ISigilProjectModel sigilProject = SigilCore.create(project);
+				sigilProjects = Collections.singleton(sigilProject);
+			} catch (CoreException e) {
+				status.add(e.getStatus());
+			}
+		}
+
+		if ( sigilProjects != null ) {
+			for (ISigilProjectModel sigilProject : sigilProjects) {
+				try {
+					// Delete existing dependency markers on project
+					sigilProject.getProject().deleteMarkers(SigilCore.MARKER_UNRESOLVED_DEPENDENCY, true, IResource.DEPTH_ONE);
+					
+					IRepositoryManager repository = SigilCore.getRepositoryManager(sigilProject);
+					ResolutionMonitorAdapter resolutionMonitor = new ResolutionMonitorAdapter(monitor);
+		
+					IBundleResolver resolver = repository.getBundleResolver();
+					ResolutionConfig config = new ResolutionConfig(ResolutionConfig.IGNORE_ERRORS);
+					
+					// Execute resolver
+					IResolution resolution = resolver.resolve(sigilProject, config, resolutionMonitor);
+					
+					// Find missing imports
+					Set<IPackageImport> imports = sigilProject.getBundle().getBundleInfo().getImports();
+					for (IPackageImport pkgImport : imports) {
+						if(resolution.getProvider(pkgImport) == null) {
+							markMissingImport(pkgImport, sigilProject.getProject());
+						}
+					}
+					
+					// Find missing required bundles
+					Set<IRequiredBundle> requiredBundles = sigilProject.getBundle().getBundleInfo().getRequiredBundles();
+					for (IRequiredBundle requiredBundle : requiredBundles) {
+						if(resolution.getProvider(requiredBundle) == null) {
+							markMissingRequiredBundle(requiredBundle, sigilProject.getProject());
+						}
+					}
+				} catch (ResolutionException e) {
+					status.add(new Status(IStatus.ERROR, SigilCore.PLUGIN_ID, 0, "Error resolving project " + sigilProject.getProject().getName(), e));
+				} catch (CoreException e) {
+					status.add(e.getStatus());
+				}
+			}
+		}
+		
+		return status;
+	}
+	
+	private static void markMissingImport(IPackageImport pkgImport, IProject project) throws CoreException {
+		IMarker marker = project.getProject().createMarker(SigilCore.MARKER_UNRESOLVED_IMPORT_PACKAGE);
+		marker.setAttribute("element", pkgImport.getPackageName());
+		marker.setAttribute("versionRange", pkgImport.getVersions().toString());
+		marker.setAttribute(IMarker.MESSAGE, "Cannot resolve imported package \"" + pkgImport.getPackageName() + "\" with version range " + pkgImport.getVersions());
+		marker.setAttribute(IMarker.SEVERITY, pkgImport.isOptional() ? IMarker.SEVERITY_WARNING : IMarker.SEVERITY_ERROR);
+		marker.setAttribute(IMarker.PRIORITY, IMarker.PRIORITY_HIGH);
+	}
+	
+	private static void markMissingRequiredBundle(IRequiredBundle req, IProject project) throws CoreException {
+		IMarker marker = project.getProject().createMarker(SigilCore.MARKER_UNRESOLVED_REQUIRE_BUNDLE);
+		marker.setAttribute("element", req.getSymbolicName());
+		marker.setAttribute("versionRange", req.getVersions().toString());
+		marker.setAttribute(IMarker.MESSAGE, "Cannot resolve required bundle \"" + req.getSymbolicName() + "\" with version range " + req.getVersions());
+		marker.setAttribute(IMarker.SEVERITY, req.isOptional() ? IMarker.SEVERITY_WARNING : IMarker.SEVERITY_ERROR);
+		marker.setAttribute(IMarker.PRIORITY, IMarker.PRIORITY_HIGH);
+	}
+	
+	
+
+}

Added: felix/trunk/sigil/org.cauldron.sigil.core/src/org/cauldron/sigil/job/ThreadProgressMonitor.java
URL: http://svn.apache.org/viewvc/felix/trunk/sigil/org.cauldron.sigil.core/src/org/cauldron/sigil/job/ThreadProgressMonitor.java?rev=793581&view=auto
==============================================================================
--- felix/trunk/sigil/org.cauldron.sigil.core/src/org/cauldron/sigil/job/ThreadProgressMonitor.java (added)
+++ felix/trunk/sigil/org.cauldron.sigil.core/src/org/cauldron/sigil/job/ThreadProgressMonitor.java Mon Jul 13 13:25:46 2009
@@ -0,0 +1,34 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.cauldron.sigil.job;
+
+import org.eclipse.core.runtime.IProgressMonitor;
+
+public class ThreadProgressMonitor {
+	private static ThreadLocal<IProgressMonitor> local = new ThreadLocal<IProgressMonitor>();
+	
+	public static void setProgressMonitor(IProgressMonitor monitor) {
+		local.set(monitor);
+	}
+	
+	public static IProgressMonitor getProgressMonitor() {
+		return local.get();
+	}
+}

Added: felix/trunk/sigil/org.cauldron.sigil.core/src/org/cauldron/sigil/model/project/ISigilModelRoot.java
URL: http://svn.apache.org/viewvc/felix/trunk/sigil/org.cauldron.sigil.core/src/org/cauldron/sigil/model/project/ISigilModelRoot.java?rev=793581&view=auto
==============================================================================
--- felix/trunk/sigil/org.cauldron.sigil.core/src/org/cauldron/sigil/model/project/ISigilModelRoot.java (added)
+++ felix/trunk/sigil/org.cauldron.sigil.core/src/org/cauldron/sigil/model/project/ISigilModelRoot.java Mon Jul 13 13:25:46 2009
@@ -0,0 +1,36 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.cauldron.sigil.model.project;
+
+import java.util.Collection;
+import java.util.List;
+
+import org.cauldron.sigil.model.IModelElement;
+import org.cauldron.sigil.model.eclipse.ISigilBundle;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+
+public interface ISigilModelRoot {
+	List<ISigilProjectModel> getProjects();
+	
+	Collection<ISigilProjectModel> resolveDependentProjects(ISigilProjectModel sigil, IProgressMonitor monitor);
+
+	Collection<ISigilBundle> resolveBundles(ISigilProjectModel sigil, IModelElement element, boolean includeOptional, IProgressMonitor monitor) throws CoreException;
+}

Added: felix/trunk/sigil/org.cauldron.sigil.core/src/org/cauldron/sigil/model/project/ISigilProjectModel.java
URL: http://svn.apache.org/viewvc/felix/trunk/sigil/org.cauldron.sigil.core/src/org/cauldron/sigil/model/project/ISigilProjectModel.java?rev=793581&view=auto
==============================================================================
--- felix/trunk/sigil/org.cauldron.sigil.core/src/org/cauldron/sigil/model/project/ISigilProjectModel.java (added)
+++ felix/trunk/sigil/org.cauldron.sigil.core/src/org/cauldron/sigil/model/project/ISigilProjectModel.java Mon Jul 13 13:25:46 2009
@@ -0,0 +1,105 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.cauldron.sigil.model.project;
+
+import java.util.Collection;
+
+import org.cauldron.bld.config.IBldProject;
+import org.cauldron.bld.core.BldCore;
+import org.cauldron.sigil.model.ICompoundModelElement;
+import org.cauldron.sigil.model.IModelElement;
+import org.cauldron.sigil.model.eclipse.ISigilBundle;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.jdt.core.IClasspathEntry;
+import org.eclipse.jdt.core.IJavaProject;
+import org.eclipse.jdt.core.IPackageFragmentRoot;
+import org.eclipse.jdt.core.JavaModelException;
+import org.osgi.framework.Version;
+import org.osgi.service.prefs.Preferences;
+
+/**
+ * Represents a sigil project. To get a reference to a ISigilProjectModel you can use the 
+ * helper method {@link BldCore#create(IProject)}.
+ * 
+ * @author dave
+ *
+ */
+public interface ISigilProjectModel extends ICompoundModelElement {
+    
+    /**
+     * @return
+     */
+    IProject getProject();
+	
+	// shortcut to getProject().getName()
+	String getName();
+	
+	Preferences getPreferences();
+    
+    /**
+	 * 
+	 * @param monitor
+	 *            The progress monitor to use for reporting progress to the
+	 *            user. It is the caller's responsibility to call done() on the
+	 *            given monitor. Accepts null, indicating that no progress
+	 *            should be reported and that the operation cannot be cancelled
+	 * @throws CoreException
+	 */
+	void save(IProgressMonitor monitor) throws CoreException;
+    
+	/**
+	 * @return
+	 */
+	Version getVersion();
+	    
+	String getSymbolicName();
+	
+	ISigilBundle getBundle();
+	
+	void setBundle(ISigilBundle bundle);
+	
+	/**
+	 * @return
+	 */
+	IJavaProject getJavaModel();
+	
+	Collection<ISigilProjectModel> findDependentProjects(IProgressMonitor monitor);
+
+	void resetClasspath(IProgressMonitor monitor) throws CoreException;
+	
+	IPath findBundleLocation() throws CoreException;
+
+	IModelElement findImport(String packageName, IProgressMonitor monitor);
+
+	boolean isInClasspath(String packageName, IProgressMonitor monitor) throws CoreException;
+
+	boolean isInClasspath(ISigilBundle bundle);
+	
+	boolean isInBundleClasspath(IPackageFragmentRoot root) throws JavaModelException;
+	
+	IPath findOutputLocation() throws CoreException;
+
+	IBldProject getBldProject() throws CoreException;
+
+	Collection<IClasspathEntry> findExternalClasspath(IProgressMonitor monitor) throws CoreException;
+}

Added: felix/trunk/sigil/org.cauldron.sigil.core/src/org/cauldron/sigil/model/repository/IRepositoryConfiguration.java
URL: http://svn.apache.org/viewvc/felix/trunk/sigil/org.cauldron.sigil.core/src/org/cauldron/sigil/model/repository/IRepositoryConfiguration.java?rev=793581&view=auto
==============================================================================
--- felix/trunk/sigil/org.cauldron.sigil.core/src/org/cauldron/sigil/model/repository/IRepositoryConfiguration.java (added)
+++ felix/trunk/sigil/org.cauldron.sigil.core/src/org/cauldron/sigil/model/repository/IRepositoryConfiguration.java Mon Jul 13 13:25:46 2009
@@ -0,0 +1,49 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.cauldron.sigil.model.repository;
+
+import java.util.List;
+import java.util.Map;
+
+import org.cauldron.sigil.internal.model.repository.RepositoryType;
+import org.eclipse.core.runtime.CoreException;
+
+public interface IRepositoryConfiguration {
+
+	List<IRepositoryModel> loadRepositories();
+	
+	IRepositoryModel findRepository(String id);
+
+	void saveRepositories(List<IRepositoryModel> repositories) throws CoreException;
+
+	List<RepositoryType> loadRepositoryTypes();
+
+	IRepositoryModel newRepositoryElement(IRepositoryType type);
+	
+	IRepositorySet getDefaultRepositorySet();
+
+	void setDefaultRepositorySet(IRepositorySet defaultSet);
+	
+	IRepositorySet getRepositorySet(String name);
+	
+	Map<String, IRepositorySet> loadRepositorySets();
+	
+	void saveRepositorySets(Map<String, IRepositorySet> sets);
+}
\ No newline at end of file

Added: felix/trunk/sigil/org.cauldron.sigil.core/src/org/cauldron/sigil/model/repository/IRepositoryModel.java
URL: http://svn.apache.org/viewvc/felix/trunk/sigil/org.cauldron.sigil.core/src/org/cauldron/sigil/model/repository/IRepositoryModel.java?rev=793581&view=auto
==============================================================================
--- felix/trunk/sigil/org.cauldron.sigil.core/src/org/cauldron/sigil/model/repository/IRepositoryModel.java (added)
+++ felix/trunk/sigil/org.cauldron.sigil.core/src/org/cauldron/sigil/model/repository/IRepositoryModel.java Mon Jul 13 13:25:46 2009
@@ -0,0 +1,35 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.cauldron.sigil.model.repository;
+
+import org.eclipse.jface.preference.PreferenceStore;
+
+public interface IRepositoryModel {
+
+	String getId();
+
+	void setName(String stringValue);
+	
+	String getName();
+
+	PreferenceStore getPreferences();
+
+	IRepositoryType getType();
+}
\ No newline at end of file

Added: felix/trunk/sigil/org.cauldron.sigil.core/src/org/cauldron/sigil/model/repository/IRepositorySet.java
URL: http://svn.apache.org/viewvc/felix/trunk/sigil/org.cauldron.sigil.core/src/org/cauldron/sigil/model/repository/IRepositorySet.java?rev=793581&view=auto
==============================================================================
--- felix/trunk/sigil/org.cauldron.sigil.core/src/org/cauldron/sigil/model/repository/IRepositorySet.java (added)
+++ felix/trunk/sigil/org.cauldron.sigil.core/src/org/cauldron/sigil/model/repository/IRepositorySet.java Mon Jul 13 13:25:46 2009
@@ -0,0 +1,27 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.cauldron.sigil.model.repository;
+
+public interface IRepositorySet {
+	void setRepository(IRepositoryModel id, int position);
+	void removeRepository(IRepositoryModel id);
+	IRepositoryModel[] getRepositories();
+	void setRepositories(IRepositoryModel[] repositories);
+}

Added: felix/trunk/sigil/org.cauldron.sigil.core/src/org/cauldron/sigil/model/repository/IRepositoryType.java
URL: http://svn.apache.org/viewvc/felix/trunk/sigil/org.cauldron.sigil.core/src/org/cauldron/sigil/model/repository/IRepositoryType.java?rev=793581&view=auto
==============================================================================
--- felix/trunk/sigil/org.cauldron.sigil.core/src/org/cauldron/sigil/model/repository/IRepositoryType.java (added)
+++ felix/trunk/sigil/org.cauldron.sigil.core/src/org/cauldron/sigil/model/repository/IRepositoryType.java Mon Jul 13 13:25:46 2009
@@ -0,0 +1,34 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.cauldron.sigil.model.repository;
+
+import org.eclipse.swt.graphics.Image;
+
+public interface IRepositoryType {
+
+	String getType();
+
+	String getId();
+
+	Image getIcon();
+
+	boolean isDynamic();
+
+}
\ No newline at end of file

Added: felix/trunk/sigil/org.cauldron.sigil.core/src/org/cauldron/sigil/model/repository/RepositorySet.java
URL: http://svn.apache.org/viewvc/felix/trunk/sigil/org.cauldron.sigil.core/src/org/cauldron/sigil/model/repository/RepositorySet.java?rev=793581&view=auto
==============================================================================
--- felix/trunk/sigil/org.cauldron.sigil.core/src/org/cauldron/sigil/model/repository/RepositorySet.java (added)
+++ felix/trunk/sigil/org.cauldron.sigil.core/src/org/cauldron/sigil/model/repository/RepositorySet.java Mon Jul 13 13:25:46 2009
@@ -0,0 +1,63 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.cauldron.sigil.model.repository;
+
+import java.util.ArrayList;
+import java.util.Collection;
+
+public class RepositorySet implements IRepositorySet {
+
+	private static final IRepositoryModel[] EMPTY = new IRepositoryModel[0];
+	
+	private IRepositoryModel[] reps;
+
+	public RepositorySet() {
+		this( EMPTY );
+	}
+	
+	public RepositorySet(Collection<IRepositoryModel> reps) {
+		this( reps.toArray( new IRepositoryModel[reps.size()] ) );
+	}
+
+	public RepositorySet(IRepositoryModel[] repositories) {
+		this.reps = repositories;
+	}
+	
+	public void setRepository(IRepositoryModel id, int position) {
+		ArrayList<IRepositoryModel> tmp = new ArrayList<IRepositoryModel>(reps.length + 1);
+		tmp.remove(id);
+		tmp.add(position, id);
+		reps = tmp.toArray( new IRepositoryModel[tmp.size()] );
+	}
+
+	public IRepositoryModel[] getRepositories() {
+		return reps;
+	}
+
+	public void removeRepository(IRepositoryModel id) {
+		ArrayList<IRepositoryModel> tmp = new ArrayList<IRepositoryModel>(reps.length + 1);
+		tmp.remove(id);
+		reps = tmp.toArray( new IRepositoryModel[tmp.size()] );
+	}
+
+	public void setRepositories(IRepositoryModel[] repositories) {
+		reps = repositories == null ? EMPTY : repositories;
+	}
+}

Added: felix/trunk/sigil/org.cauldron.sigil.core/src/org/cauldron/sigil/model/util/Grep.java
URL: http://svn.apache.org/viewvc/felix/trunk/sigil/org.cauldron.sigil.core/src/org/cauldron/sigil/model/util/Grep.java?rev=793581&view=auto
==============================================================================
--- felix/trunk/sigil/org.cauldron.sigil.core/src/org/cauldron/sigil/model/util/Grep.java (added)
+++ felix/trunk/sigil/org.cauldron.sigil.core/src/org/cauldron/sigil/model/util/Grep.java Mon Jul 13 13:25:46 2009
@@ -0,0 +1,108 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.cauldron.sigil.model.util;
+
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.nio.CharBuffer;
+import java.nio.MappedByteBuffer;
+import java.nio.channels.FileChannel;
+import java.nio.charset.Charset;
+import java.nio.charset.CharsetDecoder;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.runtime.CoreException;
+
+public class Grep {
+
+	// Pattern used to parse lines
+	private static Pattern linePattern = Pattern.compile(".*\r?\n");
+	
+	// The input pattern that we're looking for
+	private Pattern pattern;
+	
+	private CharBuffer cb;
+
+	private FileChannel fc;
+	
+	private Grep(IFile f, Pattern pattern) throws IOException, CoreException {
+		this.pattern = pattern;
+		cb = openBuffer(f);			
+	}
+	
+	private CharBuffer openBuffer(IFile f) throws IOException, CoreException {
+		Charset charset = Charset.forName(f.getCharset());
+		CharsetDecoder decoder = charset.newDecoder();
+		// Open the file and then get a channel from the stream
+		FileInputStream fis = new FileInputStream(f.getLocation().toFile());
+		fc = fis.getChannel();
+
+		// Get the file's size and then map it into memory
+		int sz = (int) fc.size();
+		MappedByteBuffer bb = fc.map(FileChannel.MapMode.READ_ONLY, 0, sz);
+
+		// Decode the file into a char buffer
+		return decoder.decode(bb);
+	}
+
+	public static String[] grep(Pattern pattern, IFile...files) throws CoreException {
+		LinkedList<String> matches = new LinkedList<String>();
+		for ( IFile f : files ) {
+			try {
+				Grep g = new Grep( f, pattern );
+				g.grep(matches);
+				g.close();
+			} catch (IOException e) {
+				// TODO Auto-generated catch block
+				e.printStackTrace();
+			}
+		}
+		return matches.toArray( new String[matches.size()]);
+	}
+
+	private void close() throws IOException {
+		fc.close();
+	}
+
+	// Use the linePattern to break the given CharBuffer into lines, applying
+	// the input pattern to each line to see if we have a match
+	//
+	private void grep(List<String> matches) {
+		Matcher lm = linePattern.matcher(cb); // Line matcher
+		Matcher pm = null; // Pattern matcher
+		int lines = 0;
+		while (lm.find()) {
+			lines++;
+			CharSequence cs = lm.group(); // The current line
+			if (pm == null)
+				pm = pattern.matcher(cs);
+			else
+				pm.reset(cs);
+			if (pm.find())
+				matches.add(pm.group());
+			if (lm.end() == cb.limit())
+				break;
+		}		
+	}
+}